summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-03 01:21:19 +0000
committeraldyh <aldyh@138bc75d-0d04-0410-961f-82ee72b054a4>2011-11-03 01:21:19 +0000
commitc2fa69a37e08822d26bd067d7c1ee4fe3215d569 (patch)
tree1e42666ac70522aa17140e74c50679e6ba9db1eb
parent2d261e9be4ab83ffbb56a619e85fa69047265817 (diff)
parent973b45a7c6656ccc06e9d59749668d292543abd9 (diff)
downloadgcc-c2fa69a37e08822d26bd067d7c1ee4fe3215d569.tar.gz
* Merge from trunk at revision 180790.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/cxx-mem-model@180811 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog42
-rw-r--r--MAINTAINERS2
-rw-r--r--Makefile.in7
-rw-r--r--Makefile.tpl7
-rwxr-xr-xconfig.sub17
-rw-r--r--config/ChangeLog4
-rw-r--r--config/mh-interix5
-rw-r--r--fixincludes/ChangeLog6
-rw-r--r--fixincludes/fixincl.x11
-rw-r--r--fixincludes/inclhack.def1
-rw-r--r--gcc/ChangeLog3700
-rw-r--r--gcc/ChangeLog.mm4
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in270
-rw-r--r--gcc/ada/ChangeLog872
-rw-r--r--gcc/ada/Makefile.rtl12
-rw-r--r--gcc/ada/a-cbprqu.adb31
-rw-r--r--gcc/ada/a-cbprqu.ads10
-rw-r--r--gcc/ada/a-cbsyqu.ads10
-rw-r--r--gcc/ada/a-ciorma.adb1
-rw-r--r--gcc/ada/a-convec.adb60
-rw-r--r--gcc/ada/a-convec.ads4
-rw-r--r--gcc/ada/a-csquin.ads16
-rw-r--r--gcc/ada/a-cuprqu.adb23
-rw-r--r--gcc/ada/a-cuprqu.ads10
-rw-r--r--gcc/ada/a-cusyqu.ads10
-rw-r--r--gcc/ada/a-ngcoar.adb590
-rw-r--r--gcc/ada/a-ngcoar.ads2
-rw-r--r--gcc/ada/a-ngrear.adb128
-rw-r--r--gcc/ada/a-tienau.adb25
-rw-r--r--gcc/ada/back_end.adb6
-rw-r--r--gcc/ada/bindgen.adb19
-rw-r--r--gcc/ada/checks.adb17
-rw-r--r--gcc/ada/checks.ads29
-rw-r--r--gcc/ada/debug.adb11
-rw-r--r--gcc/ada/exp_aggr.adb17
-rw-r--r--gcc/ada/exp_ch2.adb51
-rw-r--r--gcc/ada/exp_ch3.adb491
-rw-r--r--gcc/ada/exp_ch3.ads22
-rw-r--r--gcc/ada/exp_ch4.adb79
-rw-r--r--gcc/ada/exp_ch5.adb14
-rw-r--r--gcc/ada/exp_ch6.adb318
-rw-r--r--gcc/ada/exp_ch6.ads28
-rw-r--r--gcc/ada/exp_ch9.adb436
-rw-r--r--gcc/ada/exp_ch9.ads38
-rw-r--r--gcc/ada/exp_disp.adb4
-rw-r--r--gcc/ada/expect.c25
-rw-r--r--gcc/ada/freeze.adb11
-rw-r--r--gcc/ada/g-trasym.adb6
-rw-r--r--gcc/ada/g-trasym.ads7
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in115
-rw-r--r--gcc/ada/gcc-interface/Makefile.in63
-rw-r--r--gcc/ada/gcc-interface/ada-tree.h16
-rw-r--r--gcc/ada/gcc-interface/decl.c76
-rw-r--r--gcc/ada/gcc-interface/gigi.h9
-rw-r--r--gcc/ada/gcc-interface/lang-specs.h2
-rw-r--r--gcc/ada/gcc-interface/lang.opt47
-rw-r--r--gcc/ada/gcc-interface/misc.c24
-rw-r--r--gcc/ada/gcc-interface/trans.c348
-rw-r--r--gcc/ada/gcc-interface/utils.c109
-rw-r--r--gcc/ada/gcc-interface/utils2.c97
-rw-r--r--gcc/ada/gnat_rm.texi30
-rw-r--r--gcc/ada/gnat_ugn.texi581
-rw-r--r--gcc/ada/gnatlink.adb4
-rw-r--r--gcc/ada/impunit.adb2
-rw-r--r--gcc/ada/impunit.ads5
-rw-r--r--gcc/ada/init.c34
-rw-r--r--gcc/ada/lib-xref.adb5
-rw-r--r--gcc/ada/link.c29
-rw-r--r--gcc/ada/make.adb2
-rw-r--r--gcc/ada/mlib-prj.adb30
-rw-r--r--gcc/ada/mlib-utl.adb5
-rw-r--r--gcc/ada/opt.ads5
-rw-r--r--gcc/ada/par-ch2.adb29
-rw-r--r--gcc/ada/par-ch3.adb33
-rw-r--r--gcc/ada/par-ch6.adb10
-rw-r--r--gcc/ada/par-prag.adb342
-rw-r--r--gcc/ada/par-util.adb39
-rw-r--r--gcc/ada/par.adb5
-rw-r--r--gcc/ada/prj-conf.adb2
-rw-r--r--gcc/ada/prj-pars.adb2
-rw-r--r--gcc/ada/prj-pars.ads2
-rw-r--r--gcc/ada/prj-part.adb2
-rw-r--r--gcc/ada/prj-part.ads2
-rw-r--r--gcc/ada/prj-proc.adb21
-rw-r--r--gcc/ada/prj-proc.ads2
-rw-r--r--gcc/ada/projects.texi30
-rw-r--r--gcc/ada/rtsfind.ads2
-rw-r--r--gcc/ada/s-finmas.adb169
-rw-r--r--gcc/ada/s-finmas.ads26
-rw-r--r--gcc/ada/s-gearop.adb292
-rw-r--r--gcc/ada/s-gearop.ads54
-rw-r--r--gcc/ada/s-linux-alpha.ads2
-rw-r--r--gcc/ada/s-linux-sparc.ads2
-rw-r--r--gcc/ada/s-osinte-lynxos-3.ads34
-rwxr-xr-xgcc/ada/s-regpat.adb8
-rw-r--r--gcc/ada/s-rident.ads2
-rw-r--r--gcc/ada/s-stopoo.ads8
-rw-r--r--gcc/ada/s-stposu.adb65
-rw-r--r--gcc/ada/s-taprop-posix.adb19
-rw-r--r--gcc/ada/s-tasren.adb2
-rw-r--r--gcc/ada/sem.adb19
-rw-r--r--gcc/ada/sem_aggr.adb13
-rw-r--r--gcc/ada/sem_attr.adb25
-rw-r--r--gcc/ada/sem_attr.ads14
-rw-r--r--gcc/ada/sem_ch10.adb2
-rw-r--r--gcc/ada/sem_ch12.adb623
-rw-r--r--gcc/ada/sem_ch13.adb19
-rw-r--r--gcc/ada/sem_ch3.adb128
-rw-r--r--gcc/ada/sem_ch4.adb104
-rw-r--r--gcc/ada/sem_ch6.adb73
-rw-r--r--gcc/ada/sem_ch8.adb9
-rw-r--r--gcc/ada/sem_ch9.adb27
-rw-r--r--gcc/ada/sem_disp.adb2
-rw-r--r--gcc/ada/sem_eval.adb67
-rw-r--r--gcc/ada/sem_intr.adb6
-rw-r--r--gcc/ada/sem_prag.adb489
-rw-r--r--gcc/ada/sem_res.adb42
-rw-r--r--gcc/ada/sem_type.adb46
-rw-r--r--gcc/ada/sem_util.adb134
-rw-r--r--gcc/ada/sem_util.ads22
-rw-r--r--gcc/ada/sem_warn.adb2
-rw-r--r--gcc/ada/sigtramp-ppcvxw.c256
-rw-r--r--gcc/ada/sigtramp.h56
-rw-r--r--gcc/ada/sinfo.adb18
-rw-r--r--gcc/ada/sinfo.ads18
-rw-r--r--gcc/ada/snames.ads-tmpl8
-rw-r--r--gcc/ada/switch-c.adb13
-rw-r--r--gcc/ada/switch-m.adb18
-rw-r--r--gcc/ada/sysdep.c3
-rw-r--r--gcc/ada/tb-alvms.c25
-rw-r--r--gcc/ada/tb-alvxw.c25
-rw-r--r--gcc/ada/tb-gcc.c25
-rw-r--r--gcc/ada/tb-ivms.c25
-rw-r--r--gcc/ada/tracebak.c25
-rw-r--r--gcc/ada/types.ads35
-rw-r--r--gcc/ada/usage.adb5
-rw-r--r--gcc/ada/vms_data.ads25
-rw-r--r--gcc/ada/warnsw.adb16
-rw-r--r--gcc/ada/warnsw.ads8
-rw-r--r--gcc/builtins.c5
-rw-r--r--gcc/c-family/ChangeLog117
-rw-r--r--gcc/c-family/c-common.c26
-rw-r--r--gcc/c-family/c-common.def6
-rw-r--r--gcc/c-family/c-common.h35
-rw-r--r--gcc/c-family/c-lex.c75
-rw-r--r--gcc/c-family/c-opts.c34
-rw-r--r--gcc/c-family/c-ppoutput.c100
-rw-r--r--gcc/c-family/c.opt62
-rw-r--r--gcc/cfgexpand.c9
-rw-r--r--gcc/cfgrtl.c2
-rw-r--r--gcc/cgraph.c4
-rw-r--r--gcc/cgraphunit.c72
-rw-r--r--gcc/combine.c15
-rw-r--r--gcc/config.gcc315
-rw-r--r--gcc/config.host8
-rw-r--r--gcc/config.in13
-rw-r--r--gcc/config/alpha/t-alpha2
-rw-r--r--gcc/config/alpha/t-ieee2
-rw-r--r--gcc/config/alpha/t-vms45
-rw-r--r--gcc/config/arm/arm.c521
-rw-r--r--gcc/config/arm/arm.h28
-rw-r--r--gcc/config/arm/arm.opt10
-rw-r--r--gcc/config/arm/bpabi.h1
-rw-r--r--gcc/config/arm/crti.asm86
-rw-r--r--gcc/config/arm/crtn.asm82
-rw-r--r--gcc/config/arm/driver-arm.c149
-rw-r--r--gcc/config/arm/iterators.md12
-rw-r--r--gcc/config/arm/linux-atomic.c278
-rw-r--r--gcc/config/arm/linux-eabi.h2
-rw-r--r--gcc/config/arm/neon.md66
-rw-r--r--gcc/config/arm/predicates.md5
-rw-r--r--gcc/config/arm/sync.md424
-rw-r--r--gcc/config/arm/t-arm3
-rw-r--r--gcc/config/arm/t-arm-elf37
-rw-r--r--gcc/config/arm/t-bpabi31
-rw-r--r--gcc/config/arm/t-linux34
-rw-r--r--gcc/config/arm/t-linux-eabi14
-rw-r--r--gcc/config/arm/t-netbsd47
-rw-r--r--gcc/config/arm/t-strongarm-elf20
-rw-r--r--gcc/config/arm/t-symbian23
-rw-r--r--gcc/config/arm/t-vxworks2
-rw-r--r--gcc/config/arm/t-wince-pe6
-rw-r--r--gcc/config/arm/x-arm3
-rw-r--r--gcc/config/avr/avr-protos.h5
-rw-r--r--gcc/config/avr/avr.c1161
-rw-r--r--gcc/config/avr/avr.h10
-rw-r--r--gcc/config/avr/avr.md564
-rw-r--r--gcc/config/avr/avr.opt16
-rw-r--r--gcc/config/avr/constraints.md10
-rw-r--r--gcc/config/avr/libgcc.S1535
-rw-r--r--gcc/config/avr/predicates.md2
-rw-r--r--gcc/config/avr/t-avr59
-rw-r--r--gcc/config/bfin/t-bfin34
-rw-r--r--gcc/config/bfin/t-bfin-elf23
-rw-r--r--gcc/config/bfin/t-bfin-linux11
-rw-r--r--gcc/config/bfin/t-bfin-uclinux15
-rw-r--r--gcc/config/c6x/c6x-mult.md4
-rw-r--r--gcc/config/c6x/c6x-mult.md.in2
-rw-r--r--gcc/config/c6x/c6x.c284
-rw-r--r--gcc/config/c6x/c6x.md16
-rw-r--r--gcc/config/c6x/t-c6x-elf37
-rw-r--r--gcc/config/c6x/t-c6x-uclinux4
-rw-r--r--gcc/config/cris/cris-protos.h9
-rw-r--r--gcc/config/cris/cris.c175
-rw-r--r--gcc/config/cris/cris.h153
-rw-r--r--gcc/config/cris/cris.md4
-rw-r--r--gcc/config/cris/cris_abi_symbol.c45
-rw-r--r--gcc/config/cris/t-cris12
-rw-r--r--gcc/config/cris/t-elfmulti4
-rw-r--r--gcc/config/cris/t-linux4
-rw-r--r--gcc/config/darwin.c173
-rw-r--r--gcc/config/fr30/crtn.asm44
-rw-r--r--gcc/config/fr30/t-fr3044
-rw-r--r--gcc/config/frv/t-frv63
-rw-r--r--gcc/config/frv/t-linux11
-rw-r--r--gcc/config/gnu.h4
-rw-r--r--gcc/config/h8300/crti.asm63
-rw-r--r--gcc/config/h8300/crtn.asm53
-rw-r--r--gcc/config/h8300/fixunssfsi.c41
-rw-r--r--gcc/config/h8300/t-elf6
-rw-r--r--gcc/config/h8300/t-h830017
-rw-r--r--gcc/config/i386/cygming-crtbegin.c135
-rw-r--r--gcc/config/i386/cygming-crtend.c88
-rw-r--r--gcc/config/i386/djgpp.h4
-rw-r--r--gcc/config/i386/driver-i386.c15
-rw-r--r--gcc/config/i386/freebsd64.h1
-rw-r--r--gcc/config/i386/gthr-win32.c260
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c1975
-rw-r--r--gcc/config/i386/i386.h1
-rw-r--r--gcc/config/i386/i386.md135
-rw-r--r--gcc/config/i386/i386.opt2
-rw-r--r--gcc/config/i386/mingw32.h9
-rw-r--r--gcc/config/i386/mmx.md36
-rw-r--r--gcc/config/i386/predicates.md38
-rw-r--r--gcc/config/i386/sse.md1884
-rw-r--r--gcc/config/i386/t-crtstuff7
-rw-r--r--gcc/config/i386/t-cygming71
-rw-r--r--gcc/config/i386/t-cygwin39
-rw-r--r--gcc/config/i386/t-darwin3
-rw-r--r--gcc/config/i386/t-darwin646
-rw-r--r--gcc/config/i386/t-djgpp2
-rw-r--r--gcc/config/i386/t-dlldir6
-rw-r--r--gcc/config/i386/t-dlldir-x9
-rw-r--r--gcc/config/i386/t-gthr-win322
-rw-r--r--gcc/config/i386/t-i386elf4
-rw-r--r--gcc/config/i386/t-interix3
-rw-r--r--gcc/config/i386/t-linux5
-rw-r--r--gcc/config/i386/t-linux647
-rw-r--r--gcc/config/i386/t-mingw-w329
-rw-r--r--gcc/config/i386/t-mingw-w649
-rw-r--r--gcc/config/i386/t-mingw325
-rw-r--r--gcc/config/i386/t-nto4
-rw-r--r--gcc/config/i386/t-openbsd2
-rw-r--r--gcc/config/ia64/crti.asm53
-rw-r--r--gcc/config/ia64/crtn.asm43
-rw-r--r--gcc/config/ia64/ia64.c8
-rw-r--r--gcc/config/ia64/t-glibc1
-rw-r--r--gcc/config/ia64/t-hpux44
-rw-r--r--gcc/config/ia64/t-ia6425
-rw-r--r--gcc/config/ia64/t-vms47
-rw-r--r--gcc/config/ia64/vms_symvec_libgcc_s.opt89
-rw-r--r--gcc/config/iq2000/t-iq200038
-rw-r--r--gcc/config/m32c/m32c-lib2-trapv.c43
-rw-r--r--gcc/config/m32c/m32c.c2
-rw-r--r--gcc/config/m32c/t-m32c14
-rw-r--r--gcc/config/m32r/initfini.c168
-rw-r--r--gcc/config/m32r/t-linux25
-rw-r--r--gcc/config/m32r/t-m32r39
-rw-r--r--gcc/config/m68k/fpgnulib.c595
-rw-r--r--gcc/config/m68k/m68k.c3
-rw-r--r--gcc/config/m68k/t-crtstuff10
-rw-r--r--gcc/config/m68k/t-floatlib31
-rw-r--r--gcc/config/m68k/t-linux8
-rw-r--r--gcc/config/m68k/t-m68kelf4
-rw-r--r--gcc/config/m68k/t-mlibs3
-rw-r--r--gcc/config/m68k/t-uclinux5
-rw-r--r--gcc/config/mcore/crti.asm62
-rw-r--r--gcc/config/mcore/crtn.asm44
-rw-r--r--gcc/config/mcore/t-mcore27
-rw-r--r--gcc/config/mep/t-mep24
-rw-r--r--gcc/config/microblaze/t-microblaze12
-rw-r--r--gcc/config/mips/t-elf22
-rw-r--r--gcc/config/mips/t-isa326422
-rw-r--r--gcc/config/mips/t-libgcc-mips1642
-rw-r--r--gcc/config/mips/t-linux642
-rw-r--r--gcc/config/mips/t-mips2
-rw-r--r--gcc/config/mips/t-r390013
-rw-r--r--gcc/config/mips/t-sde20
-rw-r--r--gcc/config/mips/t-sr71k26
-rw-r--r--gcc/config/mips/t-st4
-rw-r--r--gcc/config/mips/t-vr26
-rw-r--r--gcc/config/mmix/crti.asm116
-rw-r--r--gcc/config/mmix/t-mmix13
-rw-r--r--gcc/config/mn10300/t-mn103003
-rw-r--r--gcc/config/moxie/crti.asm40
-rw-r--r--gcc/config/moxie/crtn.asm34
-rw-r--r--gcc/config/openbsd.h4
-rw-r--r--gcc/config/pa/constraints.md6
-rw-r--r--gcc/config/pa/elf.h2
-rw-r--r--gcc/config/pa/pa-linux.h2
-rw-r--r--gcc/config/pa/pa-protos.h122
-rw-r--r--gcc/config/pa/pa.c311
-rw-r--r--gcc/config/pa/pa.h28
-rw-r--r--gcc/config/pa/pa.md344
-rw-r--r--gcc/config/pa/pa64-hpux.h2
-rw-r--r--gcc/config/pa/pa64-linux.h2
-rw-r--r--gcc/config/pa/predicates.md14
-rw-r--r--gcc/config/pa/som.h2
-rw-r--r--gcc/config/pa/t-dce-thr3
-rw-r--r--gcc/config/pa/t-hpux-shlib46
-rw-r--r--gcc/config/pa/t-linux37
-rw-r--r--gcc/config/pa/t-linux6432
-rw-r--r--gcc/config/pa/t-pa-hpux7
-rw-r--r--gcc/config/pa/t-pa-hpux102
-rw-r--r--gcc/config/pa/t-pa-hpux1131
-rw-r--r--gcc/config/pa/t-pa6467
-rw-r--r--gcc/config/pdp11/t-pdp115
-rw-r--r--gcc/config/picochip/libgccExtras/clzsi2.asm189
-rw-r--r--gcc/config/picochip/libgccExtras/fake_libgcc.asm6
-rw-r--r--gcc/config/picochip/t-picochip39
-rw-r--r--gcc/config/rs6000/476.h32
-rw-r--r--gcc/config/rs6000/476.opt24
-rw-r--r--gcc/config/rs6000/altivec.md143
-rw-r--r--gcc/config/rs6000/darwin.h25
-rw-r--r--gcc/config/rs6000/power7.md51
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c656
-rw-r--r--gcc/config/rs6000/rs6000.h29
-rw-r--r--gcc/config/rs6000/rs6000.md106
-rw-r--r--gcc/config/rs6000/t-aix4332
-rw-r--r--gcc/config/rs6000/t-aix5231
-rw-r--r--gcc/config/rs6000/t-darwin39
-rw-r--r--gcc/config/rs6000/t-darwin649
-rw-r--r--gcc/config/rs6000/t-fprules5
-rw-r--r--gcc/config/rs6000/t-linux642
-rw-r--r--gcc/config/rs6000/t-lynx17
-rw-r--r--gcc/config/rs6000/t-netbsd56
-rw-r--r--gcc/config/rs6000/t-ppccomm51
-rw-r--r--gcc/config/rs6000/t-spe3
-rw-r--r--gcc/config/rs6000/t-vxworks11
-rw-r--r--gcc/config/rs6000/vsx.md45
-rw-r--r--gcc/config/rx/rx.c2
-rw-r--r--gcc/config/rx/t-rx5
-rw-r--r--gcc/config/score/crti.asm131
-rw-r--r--gcc/config/score/crtn.asm50
-rw-r--r--gcc/config/score/t-score-elf26
-rw-r--r--gcc/config/sh/crt1.asm1369
-rw-r--r--gcc/config/sh/crti.asm125
-rw-r--r--gcc/config/sh/crtn.asm77
-rw-r--r--gcc/config/sh/sh.c16
-rw-r--r--gcc/config/sh/sh.h5
-rw-r--r--gcc/config/sh/sh.md161
-rw-r--r--gcc/config/sh/t-elf10
-rw-r--r--gcc/config/sh/t-linux6
-rw-r--r--gcc/config/sh/t-linux641
-rw-r--r--gcc/config/sh/t-netbsd24
-rw-r--r--gcc/config/sh/t-sh58
-rw-r--r--gcc/config/sh/t-sh649
-rw-r--r--gcc/config/sh/t-superh33
-rw-r--r--gcc/config/sh/t-vxworks3
-rw-r--r--gcc/config/sparc/lb1spl.asm246
-rw-r--r--gcc/config/sparc/linux.h2
-rw-r--r--gcc/config/sparc/linux64.h11
-rw-r--r--gcc/config/sparc/little-endian.opt27
-rw-r--r--gcc/config/sparc/netbsd-elf.h1
-rw-r--r--gcc/config/sparc/openbsd64.h1
-rw-r--r--gcc/config/sparc/predicates.md8
-rw-r--r--gcc/config/sparc/sol2.h2
-rw-r--r--gcc/config/sparc/sp64-elf.h8
-rw-r--r--gcc/config/sparc/sparc-modes.def4
-rw-r--r--gcc/config/sparc/sparc-protos.h7
-rw-r--r--gcc/config/sparc/sparc.c1063
-rw-r--r--gcc/config/sparc/sparc.h158
-rw-r--r--gcc/config/sparc/sparc.md1745
-rw-r--r--gcc/config/sparc/sparc.opt14
-rw-r--r--gcc/config/sparc/t-elf6
-rw-r--r--gcc/config/sparc/t-leon6
-rw-r--r--gcc/config/sparc/t-leon33
-rw-r--r--gcc/config/sparc/t-linux5
-rw-r--r--gcc/config/sparc/t-linux649
-rw-r--r--gcc/config/sparc/t-netbsd645
-rw-r--r--gcc/config/spu/divmodti4.c188
-rw-r--r--gcc/config/spu/spu-elf.h5
-rw-r--r--gcc/config/spu/spu.c152
-rw-r--r--gcc/config/spu/spu.md451
-rw-r--r--gcc/config/spu/t-spu-elf69
-rw-r--r--gcc/config/stormy16/stormy16-lib2-ashlsi3.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-ashrsi3.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-clzhi2.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-cmpsi2.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-ctzhi2.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-divsi3.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-ffshi2.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-lshrsi3.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-modsi3.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-parityhi2.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-popcounthi2.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-ucmpsi2.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-udivmodsi4.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-udivsi3.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2-umodsi3.c2
-rw-r--r--gcc/config/stormy16/stormy16-lib2.c357
-rw-r--r--gcc/config/stormy16/t-stormy1639
-rw-r--r--gcc/config/t-darwin6
-rw-r--r--gcc/config/t-freebsd5
-rw-r--r--gcc/config/t-freebsd-thread2
-rw-r--r--gcc/config/t-gnu2
-rw-r--r--gcc/config/t-libc-ok1
-rw-r--r--gcc/config/t-libgcc-pic2
-rw-r--r--gcc/config/t-libunwind6
-rw-r--r--gcc/config/t-linux27
-rw-r--r--gcc/config/t-lynx11
-rw-r--r--gcc/config/t-netbsd2
-rw-r--r--gcc/config/t-openbsd-thread3
-rw-r--r--gcc/config/t-rtems5
-rw-r--r--gcc/config/t-slibgcc2
-rw-r--r--gcc/config/t-slibgcc-dummy3
-rw-r--r--gcc/config/t-slibgcc-elf-ver56
-rw-r--r--gcc/config/t-slibgcc-libgcc32
-rw-r--r--gcc/config/t-sol23
-rw-r--r--gcc/config/t-svr48
-rw-r--r--gcc/config/t-vxworks30
-rw-r--r--gcc/config/v850/t-v85062
-rw-r--r--gcc/config/vax/t-linux2
-rw-r--r--gcc/config/vms/t-vms13
-rw-r--r--gcc/config/vms/xm-vms.h3
-rw-r--r--gcc/config/xtensa/t-elf6
-rw-r--r--gcc/config/xtensa/t-linux3
-rw-r--r--gcc/config/xtensa/t-xtensa21
-rwxr-xr-xgcc/configure216
-rw-r--r--gcc/configure.ac86
-rw-r--r--gcc/cp/ChangeLog388
-rw-r--r--gcc/cp/Make-lang.in2
-rw-r--r--gcc/cp/NEWS4
-rw-r--r--gcc/cp/call.c16
-rw-r--r--gcc/cp/class.c88
-rw-r--r--gcc/cp/cp-objcp-common.c2
-rw-r--r--gcc/cp/cp-tree.def4
-rw-r--r--gcc/cp/cp-tree.h63
-rw-r--r--gcc/cp/cvt.c5
-rw-r--r--gcc/cp/cxx-pretty-print.c19
-rw-r--r--gcc/cp/cxx-pretty-print.h2
-rw-r--r--gcc/cp/decl.c112
-rw-r--r--gcc/cp/decl2.c74
-rw-r--r--gcc/cp/error.c40
-rw-r--r--gcc/cp/init.c41
-rw-r--r--gcc/cp/mangle.c32
-rw-r--r--gcc/cp/method.c68
-rw-r--r--gcc/cp/name-lookup.c2
-rw-r--r--gcc/cp/parser.c790
-rw-r--r--gcc/cp/parser.h4
-rw-r--r--gcc/cp/pt.c45
-rw-r--r--gcc/cp/search.c86
-rw-r--r--gcc/cp/semantics.c225
-rw-r--r--gcc/cp/tree.c25
-rw-r--r--gcc/cp/typeck.c234
-rw-r--r--gcc/cp/typeck2.c19
-rw-r--r--gcc/cppdefault.c23
-rw-r--r--gcc/crtstuff.c650
-rw-r--r--gcc/cselib.c7
-rw-r--r--gcc/diagnostic.c24
-rw-r--r--gcc/diagnostic.h2
-rw-r--r--gcc/doc/cppopts.texi31
-rw-r--r--gcc/doc/extend.texi50
-rw-r--r--gcc/doc/fragments.texi9
-rw-r--r--gcc/doc/install.texi16
-rw-r--r--gcc/doc/invoke.texi243
-rw-r--r--gcc/doc/md.texi17
-rw-r--r--gcc/doc/tm.texi38
-rw-r--r--gcc/doc/tm.texi.in38
-rw-r--r--gcc/dwarf2out.c42
-rw-r--r--gcc/emit-rtl.c21
-rw-r--r--gcc/expr.c80
-rw-r--r--gcc/fold-const.c127
-rw-r--r--gcc/fortran/ChangeLog204
-rw-r--r--gcc/fortran/Make-lang.in2
-rw-r--r--gcc/fortran/array.c3
-rw-r--r--gcc/fortran/check.c106
-rw-r--r--gcc/fortran/cpp.c22
-rw-r--r--gcc/fortran/decl.c24
-rw-r--r--gcc/fortran/expr.c2
-rw-r--r--gcc/fortran/frontend-passes.c17
-rw-r--r--gcc/fortran/gfortran.h4
-rw-r--r--gcc/fortran/gfortran.texi45
-rw-r--r--gcc/fortran/intrinsic.c8
-rw-r--r--gcc/fortran/intrinsic.texi49
-rw-r--r--gcc/fortran/invoke.texi5
-rw-r--r--gcc/fortran/io.c30
-rw-r--r--gcc/fortran/lang.opt4
-rw-r--r--gcc/fortran/libgfortran.h2
-rw-r--r--gcc/fortran/options.c6
-rw-r--r--gcc/fortran/primary.c39
-rw-r--r--gcc/fortran/resolve.c131
-rw-r--r--gcc/fortran/simplify.c91
-rw-r--r--gcc/fortran/symbol.c5
-rw-r--r--gcc/fortran/trans-array.c50
-rw-r--r--gcc/fortran/trans-array.h2
-rw-r--r--gcc/fortran/trans-expr.c10
-rw-r--r--gcc/fortran/trans-intrinsic.c19
-rw-r--r--gcc/fortran/trans-types.c2
-rw-r--r--gcc/fortran/trans.c9
-rw-r--r--gcc/function.c65
-rw-r--r--gcc/gcc-ar.c96
-rw-r--r--gcc/gcc.c2
-rw-r--r--gcc/gengtype.c5
-rw-r--r--gcc/genopinit.c5
-rw-r--r--gcc/ggc-none.c9
-rw-r--r--gcc/ggc-page.c188
-rw-r--r--gcc/ggc-zone.c27
-rw-r--r--gcc/ggc.h2
-rw-r--r--gcc/gimple-fold.c229
-rw-r--r--gcc/gimple-pretty-print.c4
-rw-r--r--gcc/gimple.c21
-rw-r--r--gcc/gimple.h1
-rw-r--r--gcc/gimplify.c17
-rw-r--r--gcc/go/ChangeLog4
-rw-r--r--gcc/go/Make-lang.in2
-rw-r--r--gcc/go/gofrontend/expressions.cc273
-rw-r--r--gcc/go/gofrontend/expressions.h33
-rw-r--r--gcc/go/gofrontend/gogo.cc11
-rw-r--r--gcc/go/gofrontend/parse.cc17
-rw-r--r--gcc/go/gofrontend/runtime.def3
-rw-r--r--gcc/go/gofrontend/statements.cc58
-rw-r--r--gcc/go/gofrontend/types.cc20
-rw-r--r--gcc/go/gofrontend/types.h4
-rw-r--r--gcc/godump.c155
-rw-r--r--gcc/gthr-aix.h35
-rw-r--r--gcc/gthr-lynx.h61
-rw-r--r--gcc/gthr-posix.c264
-rw-r--r--gcc/gthr-vxworks.h169
-rw-r--r--gcc/gthr.h168
-rw-r--r--gcc/haifa-sched.c479
-rw-r--r--gcc/ifcvt.c58
-rw-r--r--gcc/input.c124
-rw-r--r--gcc/input.h20
-rw-r--r--gcc/ipa-inline.c34
-rw-r--r--gcc/ipa-prop.c252
-rw-r--r--gcc/ipa-split.c24
-rw-r--r--gcc/java/ChangeLog9
-rw-r--r--gcc/java/Make-lang.in2
-rw-r--r--gcc/java/jcf-parse.c2
-rw-r--r--gcc/jump.c3
-rw-r--r--gcc/libgcc2.c2252
-rw-r--r--gcc/lists.c31
-rw-r--r--gcc/lto-cgraph.c11
-rw-r--r--gcc/lto-streamer-in.c98
-rw-r--r--gcc/lto-streamer-out.c88
-rw-r--r--gcc/lto-wrapper.c221
-rw-r--r--gcc/lto/ChangeLog14
-rw-r--r--gcc/lto/lto.c121
-rw-r--r--gcc/mkconfig.sh8
-rw-r--r--gcc/modulo-sched.c22
-rw-r--r--gcc/objc/ChangeLog66
-rw-r--r--gcc/objc/Make-lang.in10
-rw-r--r--gcc/objc/config-lang.in2
-rw-r--r--gcc/objc/objc-act.c512
-rw-r--r--gcc/objc/objc-act.h6
-rw-r--r--gcc/objc/objc-map.c161
-rw-r--r--gcc/objc/objc-map.h309
-rw-r--r--gcc/objc/objc-next-runtime-abi-02.c1
-rw-r--r--gcc/objcp/ChangeLog7
-rw-r--r--gcc/objcp/Make-lang.in10
-rw-r--r--gcc/objcp/config-lang.in2
-rw-r--r--gcc/optabs.c484
-rw-r--r--gcc/optabs.h34
-rw-r--r--gcc/params.def7
-rw-r--r--gcc/plugin.c4
-rw-r--r--gcc/po/ChangeLog23
-rw-r--r--gcc/po/EXCLUDES16
-rw-r--r--gcc/po/ja.po718
-rw-r--r--gcc/profile.c41
-rw-r--r--gcc/reg-notes.def1
-rw-r--r--gcc/regcprop.c20
-rw-r--r--gcc/regrename.c294
-rw-r--r--gcc/regrename.h101
-rw-r--r--gcc/reload.c115
-rw-r--r--gcc/reload1.c4
-rw-r--r--gcc/reorg.c19
-rw-r--r--gcc/rtl.h42
-rw-r--r--gcc/rtlanal.c52
-rw-r--r--gcc/sched-deps.c294
-rw-r--r--gcc/sched-ebb.c31
-rw-r--r--gcc/sched-int.h41
-rw-r--r--gcc/sched-rgn.c21
-rw-r--r--gcc/sel-sched-ir.c5
-rw-r--r--gcc/sel-sched.c20
-rw-r--r--gcc/simplify-rtx.c16
-rw-r--r--gcc/streamer-hooks.h10
-rw-r--r--gcc/system.h3
-rw-r--r--gcc/target.def15
-rw-r--r--gcc/testsuite/ChangeLog1062
-rw-r--r--gcc/testsuite/c-c++-common/dfp/pr33466.c12
-rw-r--r--gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C161
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-98.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype34.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted20.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted21.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/defaulted32.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit-copy.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit12.C54
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit4.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit5.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/implicit8.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist59.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-neg.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/not_special.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/override2.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr50901.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv1n.C34
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv2n.C110
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv3n.C202
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv4n.C230
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv5n.C170
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv6n.C74
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/rv7n.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-addr.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C38
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-args.C38
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-concat.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-cpp98-neg.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C34
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-friend.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-general.C52
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-inline.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C43
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C42
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C49
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-template.C51
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/udlit_system_header6
-rw-r--r--gcc/testsuite/g++.dg/eh/partial1.C37
-rw-r--r--gcc/testsuite/g++.dg/ext/bases.C35
-rw-r--r--gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/is_base_of_incomplete.C9
-rw-r--r--gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-4.C37
-rw-r--r--gcc/testsuite/g++.dg/inherit/error5.C14
-rw-r--r--gcc/testsuite/g++.dg/init/aggr7.C13
-rw-r--r--gcc/testsuite/g++.dg/init/ref20.C8
-rw-r--r--gcc/testsuite/g++.dg/init/value9.C32
-rw-r--r--gcc/testsuite/g++.dg/init/vbase1.C39
-rw-r--r--gcc/testsuite/g++.dg/lookup/using23.C13
-rw-r--r--gcc/testsuite/g++.dg/overload/operator4.C14
-rw-r--r--gcc/testsuite/g++.dg/overload/operator5.C16
-rw-r--r--gcc/testsuite/g++.dg/parse/error20.C2
-rw-r--r--gcc/testsuite/g++.dg/parse/error41.C11
-rw-r--r--gcc/testsuite/g++.dg/parse/error42.C4
-rw-r--r--gcc/testsuite/g++.dg/parse/error43.C5
-rw-r--r--gcc/testsuite/g++.dg/parse/error44.C11
-rw-r--r--gcc/testsuite/g++.dg/pr50672.C101
-rw-r--r--gcc/testsuite/g++.dg/pr50763-3.C57
-rw-r--r--gcc/testsuite/g++.dg/template/crash108.C5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr34850.C1
-rw-r--r--gcc/testsuite/g++.dg/torture/pr49720.C8
-rw-r--r--gcc/testsuite/g++.dg/torture/pr50189.C121
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr45605.C6
-rw-r--r--gcc/testsuite/g++.dg/vect/pr50698.cc27
-rw-r--r--gcc/testsuite/g++.dg/vect/slp-pr50819.cc53
-rw-r--r--gcc/testsuite/g++.dg/vect/vect.exp11
-rw-r--r--gcc/testsuite/g++.dg/warn/Wcast-qual2.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/Wconversion4.C17
-rw-r--r--gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-1.C100
-rw-r--r--gcc/testsuite/g++.dg/warn/format6.C7
-rw-r--r--gcc/testsuite/g++.dg/warn/format7.C10
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/sync-1.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/sync-2.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/sync-3.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/vshuf-v16hi.c5
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/DFcmp.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/HIcmp.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/HIset.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/SFset.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/SIcmp.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/SIset.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/UHIcmp.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/unsorted/USIcmp.c2
-rw-r--r--gcc/testsuite/gcc.dg/builtins-67.c4
-rw-r--r--gcc/testsuite/gcc.dg/constructor-1.c37
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c21
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c14
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c14
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c32
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c34
-rw-r--r--gcc/testsuite/gcc.dg/di-longlong64-sync-1.c164
-rw-r--r--gcc/testsuite/gcc.dg/di-sync-multithread.c205
-rw-r--r--gcc/testsuite/gcc.dg/format/ms_c90-printf-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/format/ms_c90-scanf-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/graphite/run-id-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-sra-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-sra-6.c1
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipcp-4.c68
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr46940_0.c8
-rw-r--r--gcc/testsuite/gcc.dg/memcpy-4.c11
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/920507-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/noncompile/invalid_asm.c1
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugindir1.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugindir2.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugindir3.c2
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugindir4.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr49994-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr50205.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr50340.c46
-rw-r--r--gcc/testsuite/gcc.dg/pr50717-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/pr50763-2.c46
-rw-r--r--gcc/testsuite/gcc.dg/pr50763.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr50908-2.c80
-rw-r--r--gcc/testsuite/gcc.dg/pr50908-3.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr50908.c175
-rw-r--r--gcc/testsuite/gcc.dg/scal-to-vec2.c1
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-22.c41
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-4.c12
-rw-r--r--gcc/testsuite/gcc.dg/tls/thr-cse-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr36400.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50723.c26
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50729.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50767.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50768.c17
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50838.c27
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50890.c17
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr50902.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/restrict-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-16.inc135
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-2.inc19
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-32.inc135
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-4.inc135
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-8.inc135
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-main.inc55
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v16hi.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v16qi.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v2df.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v2di.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v2sf.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v2si.c17
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v32qi.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4df.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4di.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4hi.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4sf.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v4si.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v8hi.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v8qi.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v8sf.c21
-rw-r--r--gcc/testsuite/gcc.dg/torture/vshuf-v8si.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-29.c59
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-scevccp-outer-6-global.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c17
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr50727.c21
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-multitypes-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vec-scal-opt.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-114.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-120.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-21.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bool-1.c15
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cond-10.c165
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cond-9.c200
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c107
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c58
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c58
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c65
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect.exp7
-rw-r--r--gcc/testsuite/gcc.dg/vector-compare-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/vla-23.c17
-rw-r--r--gcc/testsuite/gcc.dg/vshift-1.c132
-rw-r--r--gcc/testsuite/gcc.dg/vshift-2.c7
-rw-r--r--gcc/testsuite/gcc.dg/vshift-3.c136
-rw-r--r--gcc/testsuite/gcc.dg/vshift-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/vshift-5.c81
-rw-r--r--gcc/testsuite/gcc.target/arm/di-longlong64-sync-withhelpers.c14
-rw-r--r--gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c17
-rw-r--r--gcc/testsuite/gcc.target/arm/pr42575.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-1.c19
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-2.c21
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-3.c21
-rw-r--r--gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c18
-rw-r--r--gcc/testsuite/gcc.target/arm/wmul-12.c4
-rw-r--r--gcc/testsuite/gcc.target/arm/wmul-8.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-cvt-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-cvt-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-mul-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vphminposuw-2.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/avx-vphminposuw-3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-check.h3
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-cvt-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-cvt-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherd-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherps-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherps-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherq-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherq-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherd-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherps-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherps-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherq-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherq-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-mul-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpaddb-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpaddd-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpaddq-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpaddw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpand-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpmulld-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpmullw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpop-check.h53
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsrad-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsraw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsrld-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsrlw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsubb-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsubd-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsubq-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vpsubw-3.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/avx2-vshift-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/bmi2-check.h3
-rw-r--r--gcc/testsuite/gcc.target/i386/branch-cost1.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/branch-cost2.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/branch-cost3.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/branch-cost4.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/fma-check.h2
-rw-r--r--gcc/testsuite/gcc.target/i386/fma4-check.h2
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_3.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_4.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_5.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_double_6.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_3.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_4.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_5.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_float_6.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_3.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_4.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_5.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_double_6.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_3.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_4.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_5.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/fma_run_float_6.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/funcspec-1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/funcspec-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_1.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_2.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_4.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_5.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_double_6.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_1.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_2.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_4.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_5.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_float_6.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pad-4.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr37843-4.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr40906-1.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr40906-2.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr46226.c1
-rw-r--r--gcc/testsuite/gcc.target/i386/pr50712.c33
-rw-r--r--gcc/testsuite/gcc.target/i386/pr50766.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr50788.c10
-rw-r--r--gcc/testsuite/gcc.target/i386/sse-5.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-cvt-1.c111
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-cvt-2.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/sse2-mul-1.c209
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-mul-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-2.c78
-rw-r--r--gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-3.c6
-rw-r--r--gcc/testsuite/gcc.target/i386/vectorize4-avx.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vperm-v2df.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vperm-v2di.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vperm-v4sf-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vperm-v4sf-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vperm-v4si-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/vperm-v4si-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/warn-vect-op-1.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/warn-vect-op-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/warn-vect-op-3.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-check.h2
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-mul-1.c13
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-vshift-1.c140
-rw-r--r--gcc/testsuite/gcc.target/i386/xop-vshift-2.c8
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-pow.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-2.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-3.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-4.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/recip-5.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/warn-1.c1
-rw-r--r--gcc/testsuite/gcc.target/powerpc/warn-2.c1
-rw-r--r--gcc/testsuite/gcc.target/sparc/20111102-1.c17
-rw-r--r--gcc/testsuite/gcc.target/sparc/cmask.c4
-rw-r--r--gcc/testsuite/gcc.target/sparc/fand.c11
-rw-r--r--gcc/testsuite/gcc.target/sparc/fandnot.c20
-rw-r--r--gcc/testsuite/gcc.target/sparc/fhalve.c4
-rw-r--r--gcc/testsuite/gcc.target/sparc/fmaf-1.c51
-rw-r--r--gcc/testsuite/gcc.target/sparc/fnegop.c4
-rw-r--r--gcc/testsuite/gcc.target/sparc/fnot.c11
-rw-r--r--gcc/testsuite/gcc.target/sparc/for.c11
-rw-r--r--gcc/testsuite/gcc.target/sparc/fornot.c21
-rw-r--r--gcc/testsuite/gcc.target/sparc/fpadds.c4
-rw-r--r--gcc/testsuite/gcc.target/sparc/fshift.c4
-rw-r--r--gcc/testsuite/gcc.target/sparc/fucmp.c4
-rw-r--r--gcc/testsuite/gcc.target/sparc/fxnor.c20
-rw-r--r--gcc/testsuite/gcc.target/sparc/fxor.c11
-rw-r--r--gcc/testsuite/gcc.target/sparc/lzd.c4
-rw-r--r--gcc/testsuite/gcc.target/sparc/setcc-1.c39
-rw-r--r--gcc/testsuite/gcc.target/sparc/setcc-2.c39
-rw-r--r--gcc/testsuite/gcc.target/sparc/setcc-3.c24
-rw-r--r--gcc/testsuite/gcc.target/sparc/vis3misc.c4
-rw-r--r--gcc/testsuite/gcc.target/sparc/vis3move-1.c29
-rw-r--r--gcc/testsuite/gcc.target/sparc/vis3move-2.c29
-rw-r--r--gcc/testsuite/gcc.target/sparc/vis3move-3.c41
-rw-r--r--gcc/testsuite/gcc.target/sparc/xmul.c4
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_usage_22.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_usage_23.f908
-rw-r--r--gcc/testsuite/gfortran.dg/bind_c_usage_24.f902
-rw-r--r--gcc/testsuite/gfortran.dg/c_kind_tests_3.f0311
-rw-r--r--gcc/testsuite/gfortran.dg/coarray/subobject_1.f9043
-rw-r--r--gcc/testsuite/gfortran.dg/coarray_subobject_1.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/dshift_3.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/elemental_args_check_4.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/format_string.f31
-rw-r--r--gcc/testsuite/gfortran.dg/inquire_5.f905
-rw-r--r--gcc/testsuite/gfortran.dg/ishft_3.f9043
-rw-r--r--gcc/testsuite/gfortran.dg/iso_c_binding_class.f0315
-rw-r--r--gcc/testsuite/gfortran.dg/kind_tests_4.f908
-rw-r--r--gcc/testsuite/gfortran.dg/nearest_5.f9010
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_check_11.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_check_12.f9022
-rw-r--r--gcc/testsuite/gfortran.dg/pointer_intent_5.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/pr50875.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/rank_3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/rank_4.f902
-rw-r--r--gcc/testsuite/gfortran.dg/sizeof_proc.f9028
-rw-r--r--gcc/testsuite/gfortran.dg/substring_integer_index.f908
-rw-r--r--gcc/testsuite/gfortran.fortran-torture/compile/logical-2.f9010
-rw-r--r--gcc/testsuite/gnat.dg/source_ref1.adb6
-rw-r--r--gcc/testsuite/gnat.dg/source_ref2.adb7
-rw-r--r--gcc/testsuite/gnat.dg/specs/atomic1.ads16
-rw-r--r--gcc/testsuite/gnat.dg/specs/debug1.ads2
-rw-r--r--gcc/testsuite/gnat.dg/specs/discr1.ads10
-rw-r--r--gcc/testsuite/gnat.dg/specs/discr1_pkg.ads14
-rw-r--r--gcc/testsuite/gnat.dg/specs/unchecked_union.ads20
-rw-r--r--gcc/testsuite/gnat.dg/specs/unchecked_union1.ads20
-rw-r--r--gcc/testsuite/gnat.dg/specs/unchecked_union2.ads30
-rw-r--r--gcc/testsuite/gnat.dg/vect1.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect1.ads42
-rw-r--r--gcc/testsuite/gnat.dg/vect1_pkg.ads6
-rw-r--r--gcc/testsuite/gnat.dg/vect2.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect2.ads42
-rw-r--r--gcc/testsuite/gnat.dg/vect2_pkg.ads6
-rw-r--r--gcc/testsuite/gnat.dg/vect3.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect3.ads43
-rw-r--r--gcc/testsuite/gnat.dg/vect3_pkg.ads10
-rw-r--r--gcc/testsuite/gnat.dg/vect4.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect4.ads42
-rw-r--r--gcc/testsuite/gnat.dg/vect4_pkg.ads6
-rw-r--r--gcc/testsuite/gnat.dg/vect5.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect5.ads42
-rw-r--r--gcc/testsuite/gnat.dg/vect5_pkg.ads6
-rw-r--r--gcc/testsuite/gnat.dg/vect6.adb93
-rw-r--r--gcc/testsuite/gnat.dg/vect6.ads43
-rw-r--r--gcc/testsuite/gnat.dg/vect6_pkg.ads10
-rw-r--r--gcc/testsuite/go.test/test/chan/sieve2.go38
-rw-r--r--gcc/testsuite/go.test/test/interface/fake.go40
-rw-r--r--gcc/testsuite/go.test/test/vectors.go64
-rw-r--r--gcc/testsuite/lib/c-torture.exp17
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp28
-rw-r--r--gcc/testsuite/lib/lto.exp29
-rw-r--r--gcc/testsuite/lib/prune.exp1
-rw-r--r--gcc/testsuite/lib/target-supports.exp119
-rw-r--r--gcc/testsuite/obj-c++.dg/warn6.mm7
-rw-r--r--gcc/testsuite/obj-c++.dg/warn7.mm10
-rw-r--r--gcc/toplev.c11
-rw-r--r--gcc/tree-cfg.c46
-rw-r--r--gcc/tree-data-ref.c45
-rw-r--r--gcc/tree-diagnostic.c182
-rw-r--r--gcc/tree-diagnostic.h3
-rw-r--r--gcc/tree-eh.c93
-rw-r--r--gcc/tree-flow.h1
-rw-r--r--gcc/tree-inline.c3
-rw-r--r--gcc/tree-pretty-print.c23
-rw-r--r--gcc/tree-ssa-alias.c53
-rw-r--r--gcc/tree-ssa-alias.h6
-rw-r--r--gcc/tree-ssa-dce.c37
-rw-r--r--gcc/tree-ssa-dom.c18
-rw-r--r--gcc/tree-ssa-forwprop.c3
-rw-r--r--gcc/tree-ssa-loop-im.c8
-rw-r--r--gcc/tree-ssa-math-opts.c10
-rw-r--r--gcc/tree-ssa-pre.c3
-rw-r--r--gcc/tree-ssa-sink.c117
-rw-r--r--gcc/tree-ssa-strlen.c66
-rw-r--r--gcc/tree-ssa-structalias.c99
-rw-r--r--gcc/tree-ssa-tail-merge.c251
-rw-r--r--gcc/tree-ssa.c2
-rw-r--r--gcc/tree-streamer-in.c5
-rw-r--r--gcc/tree-streamer-out.c5
-rw-r--r--gcc/tree-vect-data-refs.c151
-rw-r--r--gcc/tree-vect-generic.c99
-rw-r--r--gcc/tree-vect-loop.c9
-rw-r--r--gcc/tree-vect-patterns.c872
-rw-r--r--gcc/tree-vect-slp.c335
-rw-r--r--gcc/tree-vect-stmts.c347
-rw-r--r--gcc/tree-vectorizer.h4
-rw-r--r--gcc/tree-vrp.c36
-rw-r--r--gcc/tree.c1
-rw-r--r--gcc/tree.def31
-rw-r--r--gcc/tree.h18
-rw-r--r--gcc/var-tracking.c2172
-rw-r--r--gcc/varasm.c2
-rw-r--r--gcc/varpool.c6
-rw-r--r--gnattools/ChangeLog10
-rw-r--r--gnattools/Makefile.in34
-rw-r--r--include/ChangeLog8
-rw-r--r--include/ansidecl.h6
-rw-r--r--include/obstack.h6
-rw-r--r--libada/ChangeLog11
-rw-r--r--libada/Makefile.in12
-rwxr-xr-xlibada/configure7
-rw-r--r--libada/configure.ac6
-rw-r--r--libcpp/ChangeLog299
-rw-r--r--libcpp/directives.c20
-rw-r--r--libcpp/expr.c189
-rw-r--r--libcpp/files.c5
-rw-r--r--libcpp/include/cpplib.h56
-rw-r--r--libcpp/include/line-map.h617
-rw-r--r--libcpp/init.c47
-rw-r--r--libcpp/internal.h143
-rw-r--r--libcpp/lex.c62
-rw-r--r--libcpp/line-map.c1097
-rw-r--r--libcpp/macro.c1381
-rw-r--r--libcpp/traditional.c2
-rw-r--r--libgcc/ChangeLog892
-rw-r--r--libgcc/Makefile.in206
-rw-r--r--libgcc/config.host562
-rw-r--r--libgcc/config/alpha/gthr-posix.c266
-rw-r--r--libgcc/config/alpha/libgcc-alpha-ldbl.ver (renamed from gcc/config/alpha/libgcc-alpha-ldbl.ver)0
-rw-r--r--libgcc/config/alpha/linux-unwind.h2
-rw-r--r--libgcc/config/alpha/qrnnd.S (renamed from gcc/config/alpha/qrnnd.asm)0
-rw-r--r--libgcc/config/alpha/t-alpha2
-rw-r--r--libgcc/config/alpha/t-linux (renamed from gcc/config/alpha/t-linux)0
-rw-r--r--libgcc/config/alpha/t-osf-pthread2
-rw-r--r--libgcc/config/alpha/t-slibgcc-osf2
-rw-r--r--libgcc/config/alpha/t-vms9
-rw-r--r--libgcc/config/alpha/vms-dwarf2.S (renamed from gcc/config/alpha/vms-dwarf2.asm)0
-rw-r--r--libgcc/config/alpha/vms-dwarf2eh.S (renamed from gcc/config/alpha/vms-dwarf2eh.asm)0
-rw-r--r--libgcc/config/alpha/vms-gcc_shell_handler.c (renamed from gcc/config/alpha/vms-gcc_shell_handler.c)0
-rw-r--r--libgcc/config/arm/bpabi-v6m.S (renamed from gcc/config/arm/bpabi-v6m.S)0
-rw-r--r--libgcc/config/arm/bpabi.S (renamed from gcc/config/arm/bpabi.S)0
-rw-r--r--libgcc/config/arm/bpabi.c (renamed from gcc/config/arm/bpabi.c)0
-rw-r--r--libgcc/config/arm/crti.S86
-rw-r--r--libgcc/config/arm/crtn.S83
-rw-r--r--libgcc/config/arm/fp16.c (renamed from gcc/config/arm/fp16.c)0
-rw-r--r--libgcc/config/arm/ieee754-df.S (renamed from gcc/config/arm/ieee754-df.S)0
-rw-r--r--libgcc/config/arm/ieee754-sf.S (renamed from gcc/config/arm/ieee754-sf.S)0
-rw-r--r--libgcc/config/arm/lib1funcs.S (renamed from gcc/config/arm/lib1funcs.asm)0
-rw-r--r--libgcc/config/arm/libgcc-bpabi.ver (renamed from gcc/config/arm/libgcc-bpabi.ver)0
-rw-r--r--libgcc/config/arm/libunwind.S2
-rw-r--r--libgcc/config/arm/linux-atomic-64bit.c166
-rw-r--r--libgcc/config/arm/linux-atomic.c279
-rw-r--r--libgcc/config/arm/t-arm3
-rw-r--r--libgcc/config/arm/t-bpabi12
-rw-r--r--libgcc/config/arm/t-elf18
-rw-r--r--libgcc/config/arm/t-linux7
-rw-r--r--libgcc/config/arm/t-linux-eabi5
-rw-r--r--libgcc/config/arm/t-netbsd7
-rw-r--r--libgcc/config/arm/t-strongarm-elf6
-rw-r--r--libgcc/config/arm/t-symbian17
-rw-r--r--libgcc/config/arm/t-vxworks1
-rw-r--r--libgcc/config/arm/t-wince-pe1
-rw-r--r--libgcc/config/arm/unaligned-funcs.c (renamed from gcc/config/arm/unaligned-funcs.c)0
-rw-r--r--libgcc/config/avr/lib1funcs.S1533
-rw-r--r--libgcc/config/avr/t-avr56
-rw-r--r--libgcc/config/bfin/crti.S (renamed from gcc/config/bfin/crti.s)0
-rw-r--r--libgcc/config/bfin/crtlibid.S (renamed from gcc/config/bfin/crtlibid.s)0
-rw-r--r--libgcc/config/bfin/crtn.S (renamed from gcc/config/bfin/crtn.s)0
-rw-r--r--libgcc/config/bfin/lib1funcs.S (renamed from gcc/config/bfin/lib1funcs.asm)0
-rw-r--r--libgcc/config/bfin/libgcc-glibc.ver (renamed from gcc/config/bfin/libgcc-bfin.ver)0
-rw-r--r--libgcc/config/bfin/t-bfin3
-rw-r--r--libgcc/config/bfin/t-crtlibid3
-rw-r--r--libgcc/config/bfin/t-crtstuff1
-rw-r--r--libgcc/config/bfin/t-elf1
-rw-r--r--libgcc/config/bfin/t-linux1
-rw-r--r--libgcc/config/c6x/crti.S (renamed from gcc/config/c6x/crti.s)0
-rw-r--r--libgcc/config/c6x/crtn.S (renamed from gcc/config/c6x/crtn.s)0
-rw-r--r--libgcc/config/c6x/eqd.c (renamed from gcc/config/c6x/eqd.c)0
-rw-r--r--libgcc/config/c6x/eqf.c (renamed from gcc/config/c6x/eqf.c)0
-rw-r--r--libgcc/config/c6x/ged.c (renamed from gcc/config/c6x/ged.c)0
-rw-r--r--libgcc/config/c6x/gef.c (renamed from gcc/config/c6x/gef.c)0
-rw-r--r--libgcc/config/c6x/gtd.c (renamed from gcc/config/c6x/gtd.c)0
-rw-r--r--libgcc/config/c6x/gtf.c (renamed from gcc/config/c6x/gtf.c)0
-rw-r--r--libgcc/config/c6x/led.c (renamed from gcc/config/c6x/led.c)0
-rw-r--r--libgcc/config/c6x/lef.c (renamed from gcc/config/c6x/lef.c)0
-rw-r--r--libgcc/config/c6x/lib1funcs.S (renamed from gcc/config/c6x/lib1funcs.asm)0
-rw-r--r--libgcc/config/c6x/libgcc-eabi.ver (renamed from gcc/config/c6x/libgcc-c6xeabi.ver)0
-rw-r--r--libgcc/config/c6x/ltd.c (renamed from gcc/config/c6x/ltd.c)0
-rw-r--r--libgcc/config/c6x/ltf.c (renamed from gcc/config/c6x/ltf.c)0
-rw-r--r--libgcc/config/c6x/pr-support.c37
-rw-r--r--libgcc/config/c6x/t-elf36
-rw-r--r--libgcc/config/c6x/t-uclinux3
-rw-r--r--libgcc/config/cris/arit.c (renamed from gcc/config/cris/arit.c)0
-rw-r--r--libgcc/config/cris/libgcc-glibc.ver (renamed from gcc/config/cris/libgcc.ver)0
-rw-r--r--libgcc/config/cris/mulsi3.S (renamed from gcc/config/cris/mulsi3.asm)0
-rw-r--r--libgcc/config/cris/t-cris10
-rw-r--r--libgcc/config/cris/t-elfmulti3
-rw-r--r--libgcc/config/cris/t-linux2
-rw-r--r--libgcc/config/darwin-64.c (renamed from gcc/config/darwin-64.c)0
-rw-r--r--libgcc/config/darwin-crt3.c6
-rw-r--r--libgcc/config/fr30/crti.S (renamed from gcc/config/fr30/crti.asm)0
-rw-r--r--libgcc/config/fr30/crtn.S44
-rw-r--r--libgcc/config/fr30/lib1funcs.S (renamed from gcc/config/fr30/lib1funcs.asm)0
-rw-r--r--libgcc/config/fr30/t-fr302
-rw-r--r--libgcc/config/frv/cmovd.c (renamed from gcc/config/frv/cmovd.c)0
-rw-r--r--libgcc/config/frv/cmovh.c (renamed from gcc/config/frv/cmovh.c)0
-rw-r--r--libgcc/config/frv/cmovw.c (renamed from gcc/config/frv/cmovw.c)0
-rw-r--r--libgcc/config/frv/frvbegin.c (renamed from gcc/config/frv/frvbegin.c)0
-rw-r--r--libgcc/config/frv/frvend.c (renamed from gcc/config/frv/frvend.c)0
-rw-r--r--libgcc/config/frv/lib1funcs.S (renamed from gcc/config/frv/lib1funcs.asm)0
-rw-r--r--libgcc/config/frv/libgcc-glibc.ver (renamed from gcc/config/frv/libgcc-frv.ver)0
-rw-r--r--libgcc/config/frv/modi.c (renamed from gcc/config/frv/modi.c)0
-rw-r--r--libgcc/config/frv/t-frv22
-rw-r--r--libgcc/config/frv/t-linux3
-rw-r--r--libgcc/config/frv/uitod.c (renamed from gcc/config/frv/uitod.c)0
-rw-r--r--libgcc/config/frv/uitof.c (renamed from gcc/config/frv/uitof.c)0
-rw-r--r--libgcc/config/frv/ulltod.c (renamed from gcc/config/frv/ulltod.c)0
-rw-r--r--libgcc/config/frv/ulltof.c (renamed from gcc/config/frv/ulltof.c)0
-rw-r--r--libgcc/config/frv/umodi.c (renamed from gcc/config/frv/umodi.c)0
-rw-r--r--libgcc/config/gthr-lynx.h61
-rw-r--r--libgcc/config/gthr-posix.h (renamed from gcc/gthr-posix.h)0
-rw-r--r--libgcc/config/gthr-rtems.h (renamed from gcc/gthr-rtems.h)0
-rw-r--r--libgcc/config/gthr-vxworks.h170
-rw-r--r--libgcc/config/h8300/clzhi2.c (renamed from gcc/config/h8300/clzhi2.c)0
-rw-r--r--libgcc/config/h8300/crti.S63
-rw-r--r--libgcc/config/h8300/crtn.S53
-rw-r--r--libgcc/config/h8300/ctzhi2.c (renamed from gcc/config/h8300/ctzhi2.c)0
-rw-r--r--libgcc/config/h8300/fixunssfsi.c41
-rw-r--r--libgcc/config/h8300/lib1funcs.S (renamed from gcc/config/h8300/lib1funcs.asm)0
-rw-r--r--libgcc/config/h8300/parityhi2.c (renamed from gcc/config/h8300/parityhi2.c)0
-rw-r--r--libgcc/config/h8300/popcounthi2.c (renamed from gcc/config/h8300/popcounthi2.c)0
-rw-r--r--libgcc/config/h8300/t-h830013
-rw-r--r--libgcc/config/i386/cygming-crtbegin.c136
-rw-r--r--libgcc/config/i386/cygming-crtend.c89
-rw-r--r--libgcc/config/i386/cygwin.S (renamed from gcc/config/i386/cygwin.asm)0
-rw-r--r--libgcc/config/i386/gthr-win32.c261
-rw-r--r--libgcc/config/i386/gthr-win32.h (renamed from gcc/gthr-win32.h)0
-rw-r--r--libgcc/config/i386/libgcc-darwin.10.4.ver (renamed from gcc/config/i386/darwin-libgcc.10.4.ver)0
-rw-r--r--libgcc/config/i386/libgcc-darwin.10.5.ver (renamed from gcc/config/i386/darwin-libgcc.10.5.ver)0
-rw-r--r--libgcc/config/i386/libgcc-glibc.ver (renamed from gcc/config/i386/libgcc-glibc.ver)0
-rw-r--r--libgcc/config/i386/morestack.S88
-rw-r--r--libgcc/config/i386/t-chkstk2
-rw-r--r--libgcc/config/i386/t-cygming15
-rw-r--r--libgcc/config/i386/t-cygwin19
-rw-r--r--libgcc/config/i386/t-darwin4
-rw-r--r--libgcc/config/i386/t-darwin643
-rw-r--r--libgcc/config/i386/t-dlldir2
-rw-r--r--libgcc/config/i386/t-dlldir-x3
-rw-r--r--libgcc/config/i386/t-dw2-eh (renamed from gcc/config/i386/t-dw2-eh)0
-rw-r--r--libgcc/config/i386/t-gthr-win322
-rw-r--r--libgcc/config/i386/t-interix3
-rw-r--r--libgcc/config/i386/t-linux4
-rw-r--r--libgcc/config/i386/t-mingw-pthread (renamed from gcc/config/i386/t-mingw-pthread)0
-rw-r--r--libgcc/config/i386/t-mingw322
-rw-r--r--libgcc/config/i386/t-nto3
-rw-r--r--libgcc/config/i386/t-sjlj-eh (renamed from gcc/config/i386/t-sjlj-eh)0
-rw-r--r--libgcc/config/i386/t-slibgcc-cygming58
-rw-r--r--libgcc/config/i386/t-sol22
-rw-r--r--libgcc/config/ia64/__divxf3.S11
-rw-r--r--libgcc/config/ia64/__divxf3.asm11
-rw-r--r--libgcc/config/ia64/_fixtfdi.S11
-rw-r--r--libgcc/config/ia64/_fixtfdi.asm11
-rw-r--r--libgcc/config/ia64/_fixunstfdi.S11
-rw-r--r--libgcc/config/ia64/_fixunstfdi.asm11
-rw-r--r--libgcc/config/ia64/_floatditf.S11
-rw-r--r--libgcc/config/ia64/_floatditf.asm11
-rw-r--r--libgcc/config/ia64/crtbegin.S (renamed from gcc/config/ia64/crtbegin.asm)0
-rw-r--r--libgcc/config/ia64/crtend.S (renamed from gcc/config/ia64/crtend.asm)0
-rw-r--r--libgcc/config/ia64/crti.S53
-rw-r--r--libgcc/config/ia64/crtn.S43
-rw-r--r--libgcc/config/ia64/fde-vms.c1
-rw-r--r--libgcc/config/ia64/lib1funcs.S (renamed from gcc/config/ia64/lib1funcs.asm)0
-rw-r--r--libgcc/config/ia64/libgcc-glibc.ver (renamed from gcc/config/ia64/libgcc-glibc.ver)0
-rw-r--r--libgcc/config/ia64/libgcc-ia64.ver (renamed from gcc/config/ia64/libgcc-ia64.ver)0
-rw-r--r--libgcc/config/ia64/quadlib.c (renamed from gcc/config/ia64/quadlib.c)0
-rw-r--r--libgcc/config/ia64/t-glibc3
-rw-r--r--libgcc/config/ia64/t-hpux8
-rw-r--r--libgcc/config/ia64/t-ia6442
-rw-r--r--libgcc/config/ia64/t-linux5
-rw-r--r--libgcc/config/ia64/t-linux-libunwind (renamed from libgcc/config/ia64/t-glibc-libunwind)0
-rw-r--r--libgcc/config/ia64/t-slibgcc-hpux6
-rw-r--r--libgcc/config/ia64/t-softfp-compat2
-rw-r--r--libgcc/config/ia64/t-vms6
-rw-r--r--libgcc/config/ia64/unwind-ia64.c1
-rw-r--r--libgcc/config/ia64/vms-crtinit.S (renamed from gcc/config/ia64/vms-crtinit.asm)0
-rw-r--r--libgcc/config/iq2000/lib2funcs.c (renamed from gcc/config/iq2000/lib2extra-funcs.c)0
-rw-r--r--libgcc/config/iq2000/t-iq20005
-rw-r--r--libgcc/config/libbid/bid_gcc_intrinsics.h3
-rw-r--r--libgcc/config/libgcc-glibc.ver (renamed from gcc/config/libgcc-glibc.ver)0
-rw-r--r--libgcc/config/libgcc-libsystem.ver (renamed from gcc/libgcc-libsystem.ver)0
-rw-r--r--libgcc/config/lm32/t-elf10
-rw-r--r--libgcc/config/lm32/t-uclinux4
-rw-r--r--libgcc/config/m32c/lib1funcs.S (renamed from gcc/config/m32c/m32c-lib1.S)0
-rw-r--r--libgcc/config/m32c/lib2funcs.c (renamed from gcc/config/m32c/m32c-lib2.c)0
-rw-r--r--libgcc/config/m32c/t-m32c13
-rw-r--r--libgcc/config/m32c/trapv.c43
-rw-r--r--libgcc/config/m32r/initfini.c168
-rw-r--r--libgcc/config/m32r/libgcc-glibc.ver (renamed from gcc/config/m32r/libgcc-glibc.ver)0
-rw-r--r--libgcc/config/m32r/t-linux5
-rw-r--r--libgcc/config/m32r/t-m32r23
-rw-r--r--libgcc/config/m68k/crti.S (renamed from gcc/config/m68k/crti.s)0
-rw-r--r--libgcc/config/m68k/crtn.S (renamed from gcc/config/m68k/crtn.s)0
-rw-r--r--libgcc/config/m68k/fpgnulib.c595
-rw-r--r--libgcc/config/m68k/lb1sf68.S (renamed from gcc/config/m68k/lb1sf68.asm)0
-rw-r--r--libgcc/config/m68k/t-floatlib11
-rw-r--r--libgcc/config/m68k/t-slibgcc-elf-ver (renamed from gcc/config/m68k/t-slibgcc-elf-ver)0
-rw-r--r--libgcc/config/mcore/crti.S63
-rw-r--r--libgcc/config/mcore/crtn.S45
-rw-r--r--libgcc/config/mcore/lib1funcs.S (renamed from gcc/config/mcore/lib1.asm)0
-rw-r--r--libgcc/config/mcore/t-mcore5
-rw-r--r--libgcc/config/mep/lib1funcs.S (renamed from gcc/config/mep/mep-lib1.asm)0
-rw-r--r--libgcc/config/mep/lib2funcs.c (renamed from gcc/config/mep/mep-lib2.c)0
-rw-r--r--libgcc/config/mep/t-mep16
-rw-r--r--libgcc/config/mep/tramp.c (renamed from gcc/config/mep/mep-tramp.c)0
-rw-r--r--libgcc/config/microblaze/crti.S (renamed from gcc/config/microblaze/crti.s)0
-rw-r--r--libgcc/config/microblaze/crtn.S (renamed from gcc/config/microblaze/crtn.s)0
-rw-r--r--libgcc/config/microblaze/divsi3.S96
-rw-r--r--libgcc/config/microblaze/divsi3.asm96
-rw-r--r--libgcc/config/microblaze/moddi3.S115
-rw-r--r--libgcc/config/microblaze/moddi3.asm115
-rw-r--r--libgcc/config/microblaze/modsi3.S93
-rw-r--r--libgcc/config/microblaze/modsi3.asm93
-rw-r--r--libgcc/config/microblaze/muldi3_hard.S144
-rw-r--r--libgcc/config/microblaze/muldi3_hard.asm144
-rw-r--r--libgcc/config/microblaze/mulsi3.S69
-rw-r--r--libgcc/config/microblaze/mulsi3.asm69
-rw-r--r--libgcc/config/microblaze/stack_overflow_exit.S61
-rw-r--r--libgcc/config/microblaze/stack_overflow_exit.asm61
-rw-r--r--libgcc/config/microblaze/t-microblaze18
-rw-r--r--libgcc/config/microblaze/udivsi3.S103
-rw-r--r--libgcc/config/microblaze/udivsi3.asm103
-rw-r--r--libgcc/config/microblaze/umodsi3.S106
-rw-r--r--libgcc/config/microblaze/umodsi3.asm106
-rw-r--r--libgcc/config/mips/crti.S (renamed from gcc/config/mips/crti.asm)0
-rw-r--r--libgcc/config/mips/crtn.S (renamed from gcc/config/mips/crtn.asm)0
-rw-r--r--libgcc/config/mips/gthr-mipssde.h (renamed from gcc/gthr-mipssde.h)0
-rw-r--r--libgcc/config/mips/libgcc-mips16.ver (renamed from gcc/config/mips/libgcc-mips16.ver)0
-rw-r--r--libgcc/config/mips/mips16.S (renamed from gcc/config/mips/mips16.S)0
-rw-r--r--libgcc/config/mips/t-crtstuff2
-rw-r--r--libgcc/config/mips/t-elf3
-rw-r--r--libgcc/config/mips/t-mips2
-rw-r--r--libgcc/config/mips/t-mips1643
-rw-r--r--libgcc/config/mips/t-slibgcc-irix2
-rw-r--r--libgcc/config/mips/t-vr2
-rw-r--r--libgcc/config/mips/vr4120-div.S (renamed from gcc/config/mips/vr4120-div.S)0
-rw-r--r--libgcc/config/mmix/crti.S116
-rw-r--r--libgcc/config/mmix/crtn.S (renamed from gcc/config/mmix/crtn.asm)0
-rw-r--r--libgcc/config/mmix/t-mmix24
-rw-r--r--libgcc/config/moxie/crti.S40
-rw-r--r--libgcc/config/moxie/crti.asm40
-rw-r--r--libgcc/config/moxie/crtn.S34
-rw-r--r--libgcc/config/moxie/crtn.asm34
-rw-r--r--libgcc/config/moxie/t-moxie9
-rw-r--r--libgcc/config/pa/fptr.c (renamed from gcc/config/pa/fptr.c)0
-rw-r--r--libgcc/config/pa/gthr-dce.h (renamed from gcc/gthr-dce.h)0
-rw-r--r--libgcc/config/pa/lib2funcs.S (renamed from gcc/config/pa/lib2funcs.asm)0
-rw-r--r--libgcc/config/pa/linux-atomic.c (renamed from gcc/config/pa/linux-atomic.c)0
-rw-r--r--libgcc/config/pa/milli64.S (renamed from gcc/config/pa/milli64.S)0
-rw-r--r--libgcc/config/pa/quadlib.c (renamed from gcc/config/pa/quadlib.c)0
-rw-r--r--libgcc/config/pa/stublib.c (renamed from gcc/config/pa/stublib.c)0
-rw-r--r--libgcc/config/pa/t-hpux3
-rw-r--r--libgcc/config/pa/t-hpux101
-rw-r--r--libgcc/config/pa/t-linux10
-rw-r--r--libgcc/config/pa/t-linux648
-rw-r--r--libgcc/config/pa/t-pa643
-rw-r--r--libgcc/config/pa/t-slibgcc-dwarf-ver (renamed from gcc/config/pa/t-slibgcc-dwarf-ver)0
-rw-r--r--libgcc/config/pa/t-slibgcc-hpux25
-rw-r--r--libgcc/config/pa/t-slibgcc-sjlj-ver (renamed from gcc/config/pa/t-slibgcc-sjlj-ver)0
-rw-r--r--libgcc/config/pa/t-stublib21
-rw-r--r--libgcc/config/pa/t-stublib6413
-rw-r--r--libgcc/config/pdp11/t-pdp118
-rw-r--r--libgcc/config/picochip/adddi3.S (renamed from gcc/config/picochip/libgccExtras/adddi3.asm)0
-rw-r--r--libgcc/config/picochip/ashlsi3.S (renamed from gcc/config/picochip/libgccExtras/ashlsi3.asm)0
-rw-r--r--libgcc/config/picochip/ashlsi3.c (renamed from gcc/config/picochip/libgccExtras/ashlsi3.c)0
-rw-r--r--libgcc/config/picochip/ashrsi3.S (renamed from gcc/config/picochip/libgccExtras/ashrsi3.asm)0
-rw-r--r--libgcc/config/picochip/ashrsi3.c (renamed from gcc/config/picochip/libgccExtras/ashrsi3.c)0
-rw-r--r--libgcc/config/picochip/clzsi2.S189
-rw-r--r--libgcc/config/picochip/cmpsi2.S (renamed from gcc/config/picochip/libgccExtras/cmpsi2.asm)0
-rw-r--r--libgcc/config/picochip/divmod15.S (renamed from gcc/config/picochip/libgccExtras/divmod15.asm)0
-rw-r--r--libgcc/config/picochip/divmodhi4.S (renamed from gcc/config/picochip/libgccExtras/divmodhi4.asm)0
-rw-r--r--libgcc/config/picochip/divmodsi4.S (renamed from gcc/config/picochip/libgccExtras/divmodsi4.asm)0
-rw-r--r--libgcc/config/picochip/lib1funcs.S4
-rw-r--r--libgcc/config/picochip/longjmp.S (renamed from gcc/config/picochip/libgccExtras/longjmp.asm)0
-rw-r--r--libgcc/config/picochip/lshrsi3.S (renamed from gcc/config/picochip/libgccExtras/lshrsi3.asm)0
-rw-r--r--libgcc/config/picochip/lshrsi3.c (renamed from gcc/config/picochip/libgccExtras/lshrsi3.c)0
-rw-r--r--libgcc/config/picochip/parityhi2.S (renamed from gcc/config/picochip/libgccExtras/parityhi2.asm)0
-rw-r--r--libgcc/config/picochip/popcounthi2.S (renamed from gcc/config/picochip/libgccExtras/popcounthi2.asm)0
-rw-r--r--libgcc/config/picochip/setjmp.S (renamed from gcc/config/picochip/libgccExtras/setjmp.asm)0
-rw-r--r--libgcc/config/picochip/subdi3.S (renamed from gcc/config/picochip/libgccExtras/subdi3.asm)0
-rw-r--r--libgcc/config/picochip/t-picochip37
-rw-r--r--libgcc/config/picochip/ucmpsi2.S (renamed from gcc/config/picochip/libgccExtras/ucmpsi2.asm)0
-rw-r--r--libgcc/config/picochip/udivmodhi4.S (renamed from gcc/config/picochip/libgccExtras/udivmodhi4.asm)0
-rw-r--r--libgcc/config/picochip/udivmodsi4.S (renamed from gcc/config/picochip/libgccExtras/udivmodsi4.asm)0
-rw-r--r--libgcc/config/rs6000/crtresfpr.S (renamed from gcc/config/rs6000/crtresfpr.asm)0
-rw-r--r--libgcc/config/rs6000/crtresgpr.S (renamed from gcc/config/rs6000/crtresgpr.asm)0
-rw-r--r--libgcc/config/rs6000/crtresxfpr.S (renamed from gcc/config/rs6000/crtresxfpr.asm)0
-rw-r--r--libgcc/config/rs6000/crtresxgpr.S (renamed from gcc/config/rs6000/crtresxgpr.asm)0
-rw-r--r--libgcc/config/rs6000/crtsavfpr.S (renamed from gcc/config/rs6000/crtsavfpr.asm)0
-rw-r--r--libgcc/config/rs6000/crtsavgpr.S (renamed from gcc/config/rs6000/crtsavgpr.asm)0
-rw-r--r--libgcc/config/rs6000/darwin-asm.h (renamed from gcc/config/rs6000/darwin-asm.h)0
-rw-r--r--libgcc/config/rs6000/darwin-fallback.c3
-rw-r--r--libgcc/config/rs6000/darwin-fpsave.S (renamed from gcc/config/rs6000/darwin-fpsave.asm)0
-rw-r--r--libgcc/config/rs6000/darwin-gpsave.S118
-rw-r--r--libgcc/config/rs6000/darwin-tramp.S (renamed from gcc/config/rs6000/darwin-tramp.asm)0
-rw-r--r--libgcc/config/rs6000/darwin-vecsave.S (renamed from gcc/config/rs6000/darwin-vecsave.asm)0
-rw-r--r--libgcc/config/rs6000/darwin-world.S (renamed from gcc/config/rs6000/darwin-world.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtres32gpr.S (renamed from gcc/config/rs6000/e500crtres32gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtres64gpr.S (renamed from gcc/config/rs6000/e500crtres64gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtres64gprctr.S (renamed from gcc/config/rs6000/e500crtres64gprctr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtrest32gpr.S (renamed from gcc/config/rs6000/e500crtrest32gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtrest64gpr.S (renamed from gcc/config/rs6000/e500crtrest64gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtresx32gpr.S (renamed from gcc/config/rs6000/e500crtresx32gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtresx64gpr.S (renamed from gcc/config/rs6000/e500crtresx64gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtsav32gpr.S (renamed from gcc/config/rs6000/e500crtsav32gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtsav64gpr.S (renamed from gcc/config/rs6000/e500crtsav64gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtsav64gprctr.S (renamed from gcc/config/rs6000/e500crtsav64gprctr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtsavg32gpr.S (renamed from gcc/config/rs6000/e500crtsavg32gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtsavg64gpr.S (renamed from gcc/config/rs6000/e500crtsavg64gpr.asm)0
-rw-r--r--libgcc/config/rs6000/e500crtsavg64gprctr.S (renamed from gcc/config/rs6000/e500crtsavg64gprctr.asm)0
-rw-r--r--libgcc/config/rs6000/eabi-ci.S (renamed from gcc/config/rs6000/eabi-ci.asm)0
-rw-r--r--libgcc/config/rs6000/eabi-cn.S (renamed from gcc/config/rs6000/eabi-cn.asm)0
-rw-r--r--libgcc/config/rs6000/eabi.S (renamed from gcc/config/rs6000/eabi.asm)0
-rw-r--r--libgcc/config/rs6000/gthr-aix.h35
-rw-r--r--libgcc/config/rs6000/libgcc-darwin.10.4.ver (renamed from gcc/config/rs6000/darwin-libgcc.10.4.ver)0
-rw-r--r--libgcc/config/rs6000/libgcc-darwin.10.5.ver (renamed from gcc/config/rs6000/darwin-libgcc.10.5.ver)0
-rw-r--r--libgcc/config/rs6000/libgcc-glibc.ver (renamed from libgcc/config/rs6000/libgcc-ppc-glibc.ver)0
-rw-r--r--libgcc/config/rs6000/libgcc-ibm-ldouble.ver (renamed from libgcc/config/rs6000/libgcc-ppc64.ver)0
-rw-r--r--libgcc/config/rs6000/sol-ci.S (renamed from gcc/config/rs6000/sol-ci.asm)0
-rw-r--r--libgcc/config/rs6000/sol-cn.S (renamed from gcc/config/rs6000/sol-cn.asm)0
-rw-r--r--libgcc/config/rs6000/t-crtstuff3
-rw-r--r--libgcc/config/rs6000/t-darwin19
-rw-r--r--libgcc/config/rs6000/t-darwin646
-rw-r--r--libgcc/config/rs6000/t-freebsd2
-rw-r--r--libgcc/config/rs6000/t-ibm-ldouble2
-rw-r--r--libgcc/config/rs6000/t-ldbl1283
-rw-r--r--libgcc/config/rs6000/t-linux3
-rw-r--r--libgcc/config/rs6000/t-linux642
-rw-r--r--libgcc/config/rs6000/t-lynx1
-rw-r--r--libgcc/config/rs6000/t-netbsd9
-rw-r--r--libgcc/config/rs6000/t-ppccomm124
-rw-r--r--libgcc/config/rs6000/t-slibgcc-aix44
-rw-r--r--libgcc/config/rs6000/tramp.S (renamed from gcc/config/rs6000/tramp.asm)0
-rw-r--r--libgcc/config/s390/gthr-tpf.h (renamed from gcc/gthr-tpf.h)0
-rw-r--r--libgcc/config/s390/t-tpf2
-rw-r--r--libgcc/config/score/crti.S131
-rw-r--r--libgcc/config/score/crtn.S50
-rw-r--r--libgcc/config/sh/crt1.S1369
-rw-r--r--libgcc/config/sh/crti.S125
-rw-r--r--libgcc/config/sh/crtn.S77
-rw-r--r--libgcc/config/sh/lib1funcs-4-300.S (renamed from gcc/config/sh/lib1funcs-4-300.asm)0
-rw-r--r--libgcc/config/sh/lib1funcs-Os-4-200.S (renamed from gcc/config/sh/lib1funcs-Os-4-200.asm)0
-rw-r--r--libgcc/config/sh/lib1funcs.S (renamed from gcc/config/sh/lib1funcs.asm)0
-rw-r--r--libgcc/config/sh/lib1funcs.h (renamed from gcc/config/sh/lib1funcs.h)0
-rw-r--r--libgcc/config/sh/libgcc-excl.ver (renamed from gcc/config/sh/libgcc-excl.ver)0
-rw-r--r--libgcc/config/sh/libgcc-glibc.ver (renamed from gcc/config/sh/libgcc-glibc.ver)0
-rw-r--r--libgcc/config/sh/linux-atomic.S (renamed from gcc/config/sh/linux-atomic.asm)0
-rw-r--r--libgcc/config/sh/t-linux37
-rw-r--r--libgcc/config/sh/t-netbsd5
-rw-r--r--libgcc/config/sh/t-sh63
-rw-r--r--libgcc/config/sh/t-sh646
-rw-r--r--libgcc/config/sh/t-superh11
-rw-r--r--libgcc/config/sparc/lb1spc.S (renamed from gcc/config/sparc/lb1spc.asm)0
-rw-r--r--libgcc/config/sparc/libgcc-glibc.ver (renamed from gcc/config/sparc/libgcc-sparc-glibc.ver)0
-rw-r--r--libgcc/config/sparc/t-linux4
-rw-r--r--libgcc/config/sparc/t-linux642
-rw-r--r--libgcc/config/sparc/t-softmul2
-rw-r--r--libgcc/config/sparc/t-sol22
-rw-r--r--libgcc/config/spu/cache.S (renamed from gcc/config/spu/cache.S)0
-rw-r--r--libgcc/config/spu/cachemgr.c (renamed from gcc/config/spu/cachemgr.c)0
-rw-r--r--libgcc/config/spu/divmodti4.c188
-rw-r--r--libgcc/config/spu/divv2df3.c (renamed from gcc/config/spu/divv2df3.c)0
-rw-r--r--libgcc/config/spu/float_disf.c (renamed from gcc/config/spu/float_disf.c)0
-rw-r--r--libgcc/config/spu/float_unsdidf.c (renamed from gcc/config/spu/float_unsdidf.c)0
-rw-r--r--libgcc/config/spu/float_unsdisf.c (renamed from gcc/config/spu/float_unsdisf.c)0
-rw-r--r--libgcc/config/spu/float_unssidf.c (renamed from gcc/config/spu/float_unssidf.c)0
-rw-r--r--libgcc/config/spu/mfc_multi_tag_release.c (renamed from gcc/config/spu/mfc_multi_tag_release.c)0
-rw-r--r--libgcc/config/spu/mfc_multi_tag_reserve.c (renamed from gcc/config/spu/mfc_multi_tag_reserve.c)0
-rw-r--r--libgcc/config/spu/mfc_tag_release.c (renamed from gcc/config/spu/mfc_tag_release.c)0
-rw-r--r--libgcc/config/spu/mfc_tag_reserve.c (renamed from gcc/config/spu/mfc_tag_reserve.c)0
-rw-r--r--libgcc/config/spu/mfc_tag_table.c (renamed from gcc/config/spu/mfc_tag_table.c)0
-rw-r--r--libgcc/config/spu/multi3.c (renamed from gcc/config/spu/multi3.c)0
-rw-r--r--libgcc/config/spu/t-elf56
-rw-r--r--libgcc/config/stormy16/ashlsi3.c2
-rw-r--r--libgcc/config/stormy16/ashrsi3.c2
-rw-r--r--libgcc/config/stormy16/clzhi2.c2
-rw-r--r--libgcc/config/stormy16/cmpsi2.c2
-rw-r--r--libgcc/config/stormy16/ctzhi2.c2
-rw-r--r--libgcc/config/stormy16/divsi3.c2
-rw-r--r--libgcc/config/stormy16/ffshi2.c2
-rw-r--r--libgcc/config/stormy16/lib2funcs.c358
-rw-r--r--libgcc/config/stormy16/lshrsi3.c2
-rw-r--r--libgcc/config/stormy16/modsi3.c2
-rw-r--r--libgcc/config/stormy16/parityhi2.c2
-rw-r--r--libgcc/config/stormy16/popcounthi2.c2
-rw-r--r--libgcc/config/stormy16/t-stormy1639
-rw-r--r--libgcc/config/stormy16/ucmpsi2.c2
-rw-r--r--libgcc/config/stormy16/udivmodsi4.c2
-rw-r--r--libgcc/config/stormy16/udivsi3.c2
-rw-r--r--libgcc/config/stormy16/umodsi3.c2
-rw-r--r--libgcc/config/t-crtin4
-rw-r--r--libgcc/config/t-crtstuff-pic2
-rw-r--r--libgcc/config/t-darwin6
-rw-r--r--libgcc/config/t-freebsd-thread2
-rw-r--r--libgcc/config/t-libgcc-pic2
-rw-r--r--libgcc/config/t-libunwind9
-rw-r--r--libgcc/config/t-linux3
-rw-r--r--libgcc/config/t-openbsd-thread3
-rw-r--r--libgcc/config/t-slibgcc5
-rw-r--r--libgcc/config/t-slibgcc-darwin5
-rw-r--r--libgcc/config/t-slibgcc-elf-ver2
-rw-r--r--libgcc/config/t-slibgcc-gld-nover3
-rw-r--r--libgcc/config/t-slibgcc-hpux7
-rw-r--r--libgcc/config/t-slibgcc-libgcc32
-rw-r--r--libgcc/config/t-slibgcc-nolc-override (renamed from gcc/config/t-slibgcc-nolc-override)0
-rw-r--r--libgcc/config/t-slibgcc-vms28
-rw-r--r--libgcc/config/t-sol28
-rw-r--r--libgcc/config/t-vxworks18
-rw-r--r--libgcc/config/v850/lib1funcs.S (renamed from gcc/config/v850/lib1funcs.asm)0
-rw-r--r--libgcc/config/v850/t-v85060
-rw-r--r--libgcc/config/vax/lib1funcs.S (renamed from gcc/config/vax/lib1funcs.asm)0
-rw-r--r--libgcc/config/vax/t-linux2
-rw-r--r--libgcc/config/vms/t-vms6
-rw-r--r--libgcc/config/vms/vms-ucrt0.c (renamed from gcc/config/vms/vms-ucrt0.c)0
-rw-r--r--libgcc/config/vxlib-tls.c (renamed from gcc/config/vxlib-tls.c)0
-rw-r--r--libgcc/config/vxlib.c (renamed from gcc/config/vxlib.c)0
-rw-r--r--libgcc/config/xtensa/crti.S (renamed from gcc/config/xtensa/crti.asm)0
-rw-r--r--libgcc/config/xtensa/crtn.S (renamed from gcc/config/xtensa/crtn.asm)0
-rw-r--r--libgcc/config/xtensa/ieee754-df.S (renamed from gcc/config/xtensa/ieee754-df.S)0
-rw-r--r--libgcc/config/xtensa/ieee754-sf.S (renamed from gcc/config/xtensa/ieee754-sf.S)0
-rw-r--r--libgcc/config/xtensa/lib1funcs.S (renamed from gcc/config/xtensa/lib1funcs.asm)0
-rw-r--r--libgcc/config/xtensa/lib2funcs.S (renamed from gcc/config/xtensa/lib2funcs.S)0
-rw-r--r--libgcc/config/xtensa/libgcc-glibc.ver (renamed from gcc/config/xtensa/libgcc-xtensa.ver)0
-rw-r--r--libgcc/config/xtensa/t-elf5
-rw-r--r--libgcc/config/xtensa/t-linux1
-rw-r--r--libgcc/config/xtensa/t-xtensa14
-rw-r--r--libgcc/config/xtensa/unwind-dw2-xtensa.c1
-rw-r--r--libgcc/configure333
-rw-r--r--libgcc/configure.ac83
-rw-r--r--libgcc/crtstuff.c651
-rw-r--r--libgcc/dfp-bit.h3
-rw-r--r--libgcc/divmod.c (renamed from gcc/config/divmod.c)0
-rw-r--r--libgcc/emutls.c3
-rw-r--r--libgcc/fixed-bit.c3
-rw-r--r--libgcc/floatunsidf.c (renamed from gcc/config/floatunsidf.c)0
-rw-r--r--libgcc/floatunsisf.c (renamed from gcc/config/floatunsisf.c)0
-rw-r--r--libgcc/floatunsitf.c (renamed from gcc/config/floatunsitf.c)0
-rw-r--r--libgcc/floatunsixf.c (renamed from gcc/config/floatunsixf.c)0
-rw-r--r--libgcc/fp-bit.c1
-rw-r--r--libgcc/gbl-ctors.h (renamed from gcc/gbl-ctors.h)0
-rw-r--r--libgcc/generic-morestack-thread.c1
-rw-r--r--libgcc/generic-morestack.c1
-rw-r--r--libgcc/gthr-single.h (renamed from gcc/gthr-single.h)0
-rw-r--r--libgcc/gthr.h148
-rw-r--r--libgcc/libgcc2.c2253
-rw-r--r--libgcc/libgcc2.h (renamed from gcc/libgcc2.h)0
-rw-r--r--libgcc/libgcov.c3
-rw-r--r--libgcc/longlong.h (renamed from gcc/longlong.h)0
-rw-r--r--libgcc/memcmp.c (renamed from gcc/config/memcmp.c)0
-rw-r--r--libgcc/memcpy.c (renamed from gcc/config/memcpy.c)0
-rw-r--r--libgcc/memmove.c (renamed from gcc/config/memmove.c)0
-rw-r--r--libgcc/memset.c (renamed from gcc/config/memset.c)0
-rwxr-xr-xlibgcc/mkheader.sh41
-rw-r--r--libgcc/mkmap-flat.awk (renamed from gcc/mkmap-flat.awk)0
-rw-r--r--libgcc/mkmap-symver.awk (renamed from gcc/mkmap-symver.awk)0
-rw-r--r--libgcc/siditi-object.mk8
-rw-r--r--libgcc/udivmod.c (renamed from gcc/config/udivmod.c)0
-rw-r--r--libgcc/udivmodsi4.c (renamed from gcc/config/udivmodsi4.c)0
-rw-r--r--libgcc/unwind-arm-common.inc2
-rw-r--r--libgcc/unwind-dw2-fde-dip.c3
-rw-r--r--libgcc/unwind-dw2-fde.c3
-rw-r--r--libgcc/unwind-dw2.c1
-rw-r--r--libgcc/unwind-sjlj.c3
-rw-r--r--libgfortran/ChangeLog67
-rw-r--r--libgfortran/Makefile.am4
-rw-r--r--libgfortran/Makefile.in4
-rw-r--r--libgfortran/acinclude.m411
-rw-r--r--libgfortran/config.h.in3
-rwxr-xr-xlibgfortran/configure19
-rw-r--r--libgfortran/configure.ac3
-rw-r--r--libgfortran/io/file_pos.c15
-rw-r--r--libgfortran/io/inquire.c48
-rw-r--r--libgfortran/io/intrinsics.c2
-rw-r--r--libgfortran/io/io.h10
-rw-r--r--libgfortran/io/open.c2
-rw-r--r--libgfortran/io/transfer.c30
-rw-r--r--libgfortran/io/unit.c58
-rw-r--r--libgfortran/io/unix.c117
-rw-r--r--libgfortran/io/unix.h16
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/Makefile.am732
-rw-r--r--libgo/Makefile.in840
-rwxr-xr-xlibgo/configure288
-rw-r--r--libgo/configure.ac47
-rw-r--r--libgo/go/archive/tar/common.go51
-rw-r--r--libgo/go/archive/tar/reader.go2
-rw-r--r--libgo/go/archive/tar/testdata/writer.tarbin3072 -> 3584 bytes
-rw-r--r--libgo/go/archive/tar/writer.go2
-rw-r--r--libgo/go/archive/tar/writer_test.go19
-rw-r--r--libgo/go/archive/zip/reader.go2
-rw-r--r--libgo/go/archive/zip/reader_test.go18
-rw-r--r--libgo/go/archive/zip/struct.go19
-rw-r--r--libgo/go/archive/zip/writer.go4
-rw-r--r--libgo/go/archive/zip/writer_test.go58
-rw-r--r--libgo/go/asn1/asn1.go2
-rw-r--r--libgo/go/asn1/asn1_test.go16
-rw-r--r--libgo/go/asn1/marshal.go12
-rw-r--r--libgo/go/big/int.go8
-rw-r--r--libgo/go/big/int_test.go3
-rw-r--r--libgo/go/big/nat.go2
-rw-r--r--libgo/go/big/rat.go8
-rw-r--r--libgo/go/big/rat_test.go40
-rw-r--r--libgo/go/bufio/bufio.go24
-rw-r--r--libgo/go/bufio/bufio_test.go70
-rw-r--r--libgo/go/bytes/buffer.go9
-rw-r--r--libgo/go/bytes/bytes.go74
-rw-r--r--libgo/go/bytes/bytes_test.go36
-rw-r--r--libgo/go/cmath/asin.go4
-rw-r--r--libgo/go/cmath/sin.go2
-rw-r--r--libgo/go/cmath/sqrt.go6
-rw-r--r--libgo/go/cmath/tan.go10
-rw-r--r--libgo/go/container/heap/heap_test.go32
-rw-r--r--libgo/go/container/vector/defs.go43
-rw-r--r--libgo/go/container/vector/intvector.go188
-rw-r--r--libgo/go/container/vector/intvector_test.go331
-rw-r--r--libgo/go/container/vector/nogen_test.go67
-rw-r--r--libgo/go/container/vector/numbers_test.go123
-rw-r--r--libgo/go/container/vector/stringvector.go188
-rw-r--r--libgo/go/container/vector/stringvector_test.go331
-rw-r--r--libgo/go/container/vector/vector.go188
-rw-r--r--libgo/go/container/vector/vector_test.go331
-rw-r--r--libgo/go/crypto/bcrypt/base64.go38
-rw-r--r--libgo/go/crypto/bcrypt/bcrypt.go282
-rw-r--r--libgo/go/crypto/bcrypt/bcrypt_test.go195
-rw-r--r--libgo/go/crypto/blowfish/block.go105
-rw-r--r--libgo/go/crypto/blowfish/blowfish_test.go18
-rw-r--r--libgo/go/crypto/blowfish/cipher.go26
-rw-r--r--libgo/go/crypto/elliptic/elliptic_test.go2
-rw-r--r--libgo/go/crypto/ocsp/ocsp_test.go2
-rw-r--r--libgo/go/crypto/openpgp/s2k/s2k.go4
-rw-r--r--libgo/go/crypto/rand/rand_unix.go2
-rw-r--r--libgo/go/crypto/tls/cipher_suites.go105
-rw-r--r--libgo/go/crypto/tls/common.go110
-rw-r--r--libgo/go/crypto/tls/conn.go86
-rw-r--r--libgo/go/crypto/tls/conn_test.go54
-rw-r--r--libgo/go/crypto/tls/handshake_client.go18
-rw-r--r--libgo/go/crypto/tls/handshake_client_test.go1
-rw-r--r--libgo/go/crypto/tls/handshake_messages.go6
-rw-r--r--libgo/go/crypto/tls/handshake_messages_test.go13
-rw-r--r--libgo/go/crypto/tls/handshake_server.go22
-rw-r--r--libgo/go/crypto/tls/handshake_server_test.go369
-rw-r--r--libgo/go/crypto/tls/key_agreement.go16
-rw-r--r--libgo/go/crypto/tls/prf.go107
-rw-r--r--libgo/go/crypto/tls/prf_test.go21
-rw-r--r--libgo/go/crypto/tls/root_darwin.go95
-rw-r--r--libgo/go/crypto/tls/root_stub.go8
-rw-r--r--libgo/go/crypto/tls/root_test.go36
-rw-r--r--libgo/go/crypto/tls/root_unix.go29
-rw-r--r--libgo/go/crypto/tls/root_windows.go54
-rw-r--r--libgo/go/crypto/x509/cert_pool.go10
-rw-r--r--libgo/go/crypto/x509/pkcs1.go122
-rw-r--r--libgo/go/crypto/x509/pkix/pkix.go3
-rw-r--r--libgo/go/crypto/x509/verify_test.go15
-rw-r--r--libgo/go/crypto/x509/x509.go171
-rw-r--r--libgo/go/crypto/x509/x509_test.go35
-rw-r--r--libgo/go/csv/reader.go4
-rw-r--r--libgo/go/csv/reader_test.go24
-rw-r--r--libgo/go/debug/dwarf/type.go2
-rw-r--r--libgo/go/ebnf/ebnf.go245
-rw-r--r--libgo/go/ebnf/ebnf_test.go87
-rw-r--r--libgo/go/ebnf/parser.go197
-rw-r--r--libgo/go/encoding/binary/binary.go6
-rw-r--r--libgo/go/encoding/binary/varint.go149
-rw-r--r--libgo/go/encoding/binary/varint_test.go182
-rw-r--r--libgo/go/exec/exec.go6
-rw-r--r--libgo/go/exec/exec_test.go43
-rw-r--r--libgo/go/exec/lp_unix.go2
-rw-r--r--libgo/go/exp/datafmt/datafmt.go710
-rw-r--r--libgo/go/exp/datafmt/datafmt_test.go330
-rw-r--r--libgo/go/exp/datafmt/parser.go368
-rw-r--r--libgo/go/exp/ebnf/ebnf.go269
-rw-r--r--libgo/go/exp/ebnf/ebnf_test.go71
-rw-r--r--libgo/go/exp/ebnf/parser.go191
-rw-r--r--libgo/go/exp/ebnflint/doc.go22
-rw-r--r--libgo/go/exp/ebnflint/ebnflint.go109
-rw-r--r--libgo/go/exp/gotype/doc.go61
-rw-r--r--libgo/go/exp/gotype/gotype.go192
-rw-r--r--libgo/go/exp/gotype/gotype_test.go49
-rw-r--r--libgo/go/exp/gotype/testdata/test1.go23
-rw-r--r--libgo/go/exp/gui/x11/auth.go12
-rw-r--r--libgo/go/exp/gui/x11/conn.go27
-rw-r--r--libgo/go/exp/norm/composition.go115
-rw-r--r--libgo/go/exp/norm/composition_test.go39
-rw-r--r--libgo/go/exp/norm/forminfo.go71
-rw-r--r--libgo/go/exp/norm/input.go107
-rw-r--r--libgo/go/exp/norm/maketables.go6
-rw-r--r--libgo/go/exp/norm/maketesttables.go1
-rw-r--r--libgo/go/exp/norm/normalize.go421
-rw-r--r--libgo/go/exp/norm/normalize_test.go644
-rw-r--r--libgo/go/exp/norm/normregtest.go295
-rw-r--r--libgo/go/exp/norm/readwriter.go129
-rw-r--r--libgo/go/exp/norm/readwriter_test.go69
-rw-r--r--libgo/go/exp/norm/tables.go6081
-rw-r--r--libgo/go/exp/norm/trie.go103
-rw-r--r--libgo/go/exp/norm/trie_test.go45
-rw-r--r--libgo/go/exp/norm/triedata_test.go76
-rw-r--r--libgo/go/exp/norm/triegen.go159
-rw-r--r--libgo/go/exp/regexp/all_test.go429
-rw-r--r--libgo/go/exp/regexp/exec.go295
-rw-r--r--libgo/go/exp/regexp/find_test.go472
-rw-r--r--libgo/go/exp/regexp/regexp.go795
-rw-r--r--libgo/go/exp/regexp/syntax/compile.go269
-rw-r--r--libgo/go/exp/regexp/syntax/parse.go1797
-rw-r--r--libgo/go/exp/regexp/syntax/parse_test.go350
-rw-r--r--libgo/go/exp/regexp/syntax/prog.go237
-rw-r--r--libgo/go/exp/regexp/syntax/prog_test.go91
-rw-r--r--libgo/go/exp/regexp/syntax/regexp.go284
-rw-r--r--libgo/go/exp/regexp/syntax/simplify_test.go151
-rw-r--r--libgo/go/exp/spdy/read.go313
-rw-r--r--libgo/go/exp/spdy/spdy_test.go (renamed from libgo/go/http/spdy/spdy_test.go)0
-rw-r--r--libgo/go/exp/spdy/types.go (renamed from libgo/go/http/spdy/types.go)0
-rw-r--r--libgo/go/exp/spdy/write.go (renamed from libgo/go/http/spdy/write.go)0
-rw-r--r--libgo/go/exp/sql/convert.go106
-rw-r--r--libgo/go/exp/sql/convert_test.go108
-rw-r--r--libgo/go/exp/sql/driver/driver.go169
-rw-r--r--libgo/go/exp/sql/driver/types.go161
-rw-r--r--libgo/go/exp/sql/fakedb_test.go497
-rw-r--r--libgo/go/exp/sql/sql.go578
-rw-r--r--libgo/go/exp/sql/sql_test.go145
-rw-r--r--libgo/go/exp/ssh/channel.go317
-rw-r--r--libgo/go/exp/ssh/common.go129
-rw-r--r--libgo/go/exp/ssh/doc.go79
-rw-r--r--libgo/go/exp/ssh/messages.go636
-rw-r--r--libgo/go/exp/ssh/messages_test.go125
-rw-r--r--libgo/go/exp/ssh/server.go645
-rw-r--r--libgo/go/exp/ssh/server_shell.go400
-rw-r--r--libgo/go/exp/ssh/server_shell_test.go134
-rw-r--r--libgo/go/exp/ssh/transport.go369
-rw-r--r--libgo/go/exp/ssh/transport_test.go37
-rw-r--r--libgo/go/exp/template/html/attr.go175
-rw-r--r--libgo/go/exp/template/html/clone.go90
-rw-r--r--libgo/go/exp/template/html/clone_test.go90
-rw-r--r--libgo/go/exp/template/html/content.go94
-rw-r--r--libgo/go/exp/template/html/content_test.go222
-rw-r--r--libgo/go/exp/template/html/context.go285
-rw-r--r--libgo/go/exp/template/html/css.go268
-rw-r--r--libgo/go/exp/template/html/css_test.go281
-rw-r--r--libgo/go/exp/template/html/doc.go190
-rw-r--r--libgo/go/exp/template/html/error.go213
-rw-r--r--libgo/go/exp/template/html/escape.go782
-rw-r--r--libgo/go/exp/template/html/escape_test.go1634
-rw-r--r--libgo/go/exp/template/html/html.go257
-rw-r--r--libgo/go/exp/template/html/html_test.go94
-rw-r--r--libgo/go/exp/template/html/js.go346
-rw-r--r--libgo/go/exp/template/html/js_test.go401
-rw-r--r--libgo/go/exp/template/html/transition.go553
-rw-r--r--libgo/go/exp/template/html/url.go105
-rw-r--r--libgo/go/exp/template/html/url_test.go112
-rw-r--r--libgo/go/exp/terminal/shell.go359
-rw-r--r--libgo/go/exp/terminal/shell_test.go110
-rw-r--r--libgo/go/exp/terminal/terminal.go102
-rw-r--r--libgo/go/exp/types/check.go (renamed from libgo/go/go/types/check.go)0
-rw-r--r--libgo/go/exp/types/check_test.go215
-rw-r--r--libgo/go/exp/types/const.go (renamed from libgo/go/go/types/const.go)0
-rw-r--r--libgo/go/exp/types/exportdata.go (renamed from libgo/go/go/types/exportdata.go)0
-rw-r--r--libgo/go/exp/types/gcimporter.go823
-rw-r--r--libgo/go/exp/types/gcimporter_test.go (renamed from libgo/go/go/types/gcimporter_test.go)0
-rw-r--r--libgo/go/exp/types/testdata/exports.go (renamed from libgo/go/go/types/testdata/exports.go)0
-rw-r--r--libgo/go/exp/types/types.go (renamed from libgo/go/go/types/types.go)0
-rw-r--r--libgo/go/exp/types/universe.go109
-rw-r--r--libgo/go/exp/winfsnotify/winfsnotify.go569
-rw-r--r--libgo/go/exp/winfsnotify/winfsnotify_test.go124
-rw-r--r--libgo/go/exp/wingui/gui.go11
-rw-r--r--libgo/go/exp/wingui/winapi.go45
-rw-r--r--libgo/go/exp/wingui/zwinapi.go38
-rw-r--r--libgo/go/flag/flag.go41
-rw-r--r--libgo/go/flag/flag_test.go9
-rw-r--r--libgo/go/fmt/doc.go2
-rw-r--r--libgo/go/fmt/fmt_test.go46
-rw-r--r--libgo/go/fmt/print.go213
-rw-r--r--libgo/go/go/ast/filter.go297
-rw-r--r--libgo/go/go/ast/print_test.go8
-rw-r--r--libgo/go/go/build/build_test.go69
-rw-r--r--libgo/go/go/build/dir.go531
-rw-r--r--libgo/go/go/build/pkgtest/pkgtest.go6
-rw-r--r--libgo/go/go/build/pkgtest/sqrt_386_test.go1
-rw-r--r--libgo/go/go/build/pkgtest/sqrt_amd64_test.go1
-rw-r--r--libgo/go/go/build/pkgtest/sqrt_arm_test.go1
-rw-r--r--libgo/go/go/build/pkgtest/sqrt_test.go5
-rw-r--r--libgo/go/go/build/pkgtest/xsqrt_test.go5
-rw-r--r--libgo/go/go/build/syslist_test.go4
-rw-r--r--libgo/go/go/doc/example.go56
-rw-r--r--libgo/go/go/parser/parser.go88
-rw-r--r--libgo/go/go/parser/parser_test.go8
-rw-r--r--libgo/go/go/printer/nodes.go16
-rw-r--r--libgo/go/go/printer/printer.go81
-rw-r--r--libgo/go/go/printer/printer_test.go14
-rw-r--r--libgo/go/go/printer/testdata/declarations.golden111
-rw-r--r--libgo/go/go/printer/testdata/declarations.input76
-rw-r--r--libgo/go/go/scanner/scanner.go11
-rw-r--r--libgo/go/go/scanner/scanner_test.go29
-rw-r--r--libgo/go/go/token/position.go26
-rw-r--r--libgo/go/go/token/serialize.go71
-rw-r--r--libgo/go/go/token/serialize_test.go105
-rw-r--r--libgo/go/go/typechecker/scope.go69
-rw-r--r--libgo/go/go/typechecker/testdata/test0.src94
-rw-r--r--libgo/go/go/typechecker/testdata/test1.src13
-rw-r--r--libgo/go/go/typechecker/testdata/test3.src41
-rw-r--r--libgo/go/go/typechecker/testdata/test4.src11
-rw-r--r--libgo/go/go/typechecker/type.go118
-rw-r--r--libgo/go/go/typechecker/typechecker.go468
-rw-r--r--libgo/go/go/typechecker/typechecker_test.go163
-rw-r--r--libgo/go/go/typechecker/universe.go36
-rw-r--r--libgo/go/go/types/check_test.go215
-rw-r--r--libgo/go/go/types/gcimporter.go799
-rw-r--r--libgo/go/go/types/testdata/test0.src154
-rw-r--r--libgo/go/go/types/universe.go108
-rw-r--r--libgo/go/gob/codec_test.go2
-rw-r--r--libgo/go/gob/decode.go80
-rw-r--r--libgo/go/gob/decoder.go14
-rw-r--r--libgo/go/gob/doc.go5
-rw-r--r--libgo/go/gob/encode.go14
-rw-r--r--libgo/go/gob/encoder.go36
-rw-r--r--libgo/go/gob/encoder_test.go87
-rw-r--r--libgo/go/gob/gobencdec_test.go39
-rw-r--r--libgo/go/gob/type.go2
-rw-r--r--libgo/go/html/escape.go24
-rw-r--r--libgo/go/html/parse.go94
-rw-r--r--libgo/go/html/parse_test.go33
-rw-r--r--libgo/go/html/render.go169
-rw-r--r--libgo/go/html/render_test.go111
-rw-r--r--libgo/go/html/token.go707
-rw-r--r--libgo/go/html/token_test.go285
-rw-r--r--libgo/go/http/cgi/child.go12
-rw-r--r--libgo/go/http/cgi/child_test.go6
-rw-r--r--libgo/go/http/cgi/host.go43
-rw-r--r--libgo/go/http/cgi/host_test.go29
-rw-r--r--libgo/go/http/chunked.go2
-rw-r--r--libgo/go/http/client.go27
-rw-r--r--libgo/go/http/client_test.go8
-rw-r--r--libgo/go/http/cookie.go13
-rw-r--r--libgo/go/http/cookie_test.go2
-rw-r--r--libgo/go/http/dump.go2
-rw-r--r--libgo/go/http/fcgi/child.go2
-rw-r--r--libgo/go/http/fcgi/fcgi_test.go6
-rw-r--r--libgo/go/http/filetransport.go124
-rw-r--r--libgo/go/http/filetransport_test.go63
-rw-r--r--libgo/go/http/fs.go2
-rw-r--r--libgo/go/http/header.go5
-rw-r--r--libgo/go/http/httptest/server.go82
-rw-r--r--libgo/go/http/persist.go4
-rw-r--r--libgo/go/http/readrequest_test.go3
-rw-r--r--libgo/go/http/request.go176
-rw-r--r--libgo/go/http/request_test.go51
-rw-r--r--libgo/go/http/requestwrite_test.go234
-rw-r--r--libgo/go/http/response.go22
-rw-r--r--libgo/go/http/response_test.go50
-rw-r--r--libgo/go/http/serve_test.go263
-rw-r--r--libgo/go/http/server.go222
-rw-r--r--libgo/go/http/spdy/read.go313
-rw-r--r--libgo/go/http/transfer.go71
-rw-r--r--libgo/go/http/transport.go127
-rw-r--r--libgo/go/http/transport_test.go66
-rw-r--r--libgo/go/http/transport_windows.go21
-rw-r--r--libgo/go/image/bmp/reader.go13
-rw-r--r--libgo/go/image/color.go251
-rw-r--r--libgo/go/image/color/color.go293
-rw-r--r--libgo/go/image/decode_test.go3
-rw-r--r--libgo/go/image/draw/bench_test.go67
-rw-r--r--libgo/go/image/draw/clip_test.go6
-rw-r--r--libgo/go/image/draw/draw.go31
-rw-r--r--libgo/go/image/draw/draw_test.go123
-rw-r--r--libgo/go/image/gif/reader.go18
-rw-r--r--libgo/go/image/image.go234
-rw-r--r--libgo/go/image/image_test.go45
-rw-r--r--libgo/go/image/jpeg/reader.go5
-rw-r--r--libgo/go/image/jpeg/writer_test.go5
-rw-r--r--libgo/go/image/names.go48
-rw-r--r--libgo/go/image/png/reader.go347
-rw-r--r--libgo/go/image/png/reader_test.go68
-rw-r--r--libgo/go/image/png/testdata/invalid-crc32.pngbin0 -> 1289 bytes
-rw-r--r--libgo/go/image/png/testdata/invalid-noend.pngbin0 -> 1277 bytes
-rw-r--r--libgo/go/image/png/testdata/invalid-trunc.pngbin0 -> 1288 bytes
-rw-r--r--libgo/go/image/png/testdata/invalid-zlib.pngbin0 -> 1289 bytes
-rw-r--r--libgo/go/image/png/writer.go47
-rw-r--r--libgo/go/image/png/writer_test.go24
-rw-r--r--libgo/go/image/tiff/compress.go60
-rw-r--r--libgo/go/image/tiff/reader.go82
-rw-r--r--libgo/go/image/tiff/reader_test.go94
-rw-r--r--libgo/go/image/tiff/testdata/bw-deflate.tiffbin0 -> 594 bytes
-rw-r--r--libgo/go/image/tiff/testdata/bw-packbits.tiffbin0 -> 890 bytes
-rw-r--r--libgo/go/image/tiff/testdata/bw-uncompressed.tiffbin0 -> 1396 bytes
-rw-r--r--libgo/go/image/tiff/testdata/video-001-uncompressed.tiffbin0 -> 46674 bytes
-rw-r--r--libgo/go/image/ycbcr/ycbcr.go9
-rw-r--r--libgo/go/index/suffixarray/qsufsort.go6
-rw-r--r--libgo/go/index/suffixarray/suffixarray.go131
-rw-r--r--libgo/go/index/suffixarray/suffixarray_test.go76
-rw-r--r--libgo/go/io/io.go30
-rw-r--r--libgo/go/io/io_test.go67
-rw-r--r--libgo/go/io/ioutil/ioutil.go4
-rw-r--r--libgo/go/json/decode.go71
-rw-r--r--libgo/go/json/decode_test.go6
-rw-r--r--libgo/go/json/encode.go25
-rw-r--r--libgo/go/json/encode_test.go2
-rw-r--r--libgo/go/json/indent.go1
-rw-r--r--libgo/go/json/scanner_test.go35
-rw-r--r--libgo/go/json/stream_test.go25
-rw-r--r--libgo/go/mail/message_test.go1
-rw-r--r--libgo/go/math/abs.go21
-rw-r--r--libgo/go/math/abs_decl.go7
-rw-r--r--libgo/go/math/all_test.go112
-rw-r--r--libgo/go/math/bits.go2
-rw-r--r--libgo/go/math/dim.go29
-rw-r--r--libgo/go/math/dim_decl.go9
-rw-r--r--libgo/go/math/fabs.go21
-rw-r--r--libgo/go/math/fdim.go29
-rw-r--r--libgo/go/math/fmod.go47
-rw-r--r--libgo/go/math/gamma.go4
-rw-r--r--libgo/go/math/jn.go2
-rw-r--r--libgo/go/math/lgamma.go4
-rw-r--r--libgo/go/math/mod.go47
-rw-r--r--libgo/go/math/mod_decl.go7
-rw-r--r--libgo/go/math/pow.go2
-rw-r--r--libgo/go/math/pow10.go6
-rw-r--r--libgo/go/math/remainder.go4
-rw-r--r--libgo/go/mime/grammar.go9
-rw-r--r--libgo/go/mime/mediatype.go77
-rw-r--r--libgo/go/mime/mediatype_test.go19
-rw-r--r--libgo/go/mime/mime_test.go27
-rw-r--r--libgo/go/mime/multipart/formdata.go4
-rw-r--r--libgo/go/mime/multipart/multipart.go7
-rw-r--r--libgo/go/mime/multipart/writer.go6
-rw-r--r--libgo/go/mime/type.go35
-rw-r--r--libgo/go/mime/type_test.go35
-rw-r--r--libgo/go/net/cgo_bsd.go2
-rw-r--r--libgo/go/net/cgo_stub.go2
-rw-r--r--libgo/go/net/cgo_unix.go17
-rw-r--r--libgo/go/net/dial.go4
-rw-r--r--libgo/go/net/dnsclient_unix.go16
-rw-r--r--libgo/go/net/dnsconfig.go2
-rw-r--r--libgo/go/net/fd.go25
-rw-r--r--libgo/go/net/fd_linux.go2
-rw-r--r--libgo/go/net/fd_select.go18
-rw-r--r--libgo/go/net/fd_windows.go71
-rw-r--r--libgo/go/net/file.go8
-rw-r--r--libgo/go/net/file_test.go11
-rw-r--r--libgo/go/net/interface.go57
-rw-r--r--libgo/go/net/interface_bsd.go3
-rw-r--r--libgo/go/net/interface_linux.go33
-rw-r--r--libgo/go/net/interface_stub.go2
-rw-r--r--libgo/go/net/interface_test.go46
-rw-r--r--libgo/go/net/ip.go252
-rw-r--r--libgo/go/net/ip_test.go240
-rw-r--r--libgo/go/net/iprawsock_posix.go49
-rw-r--r--libgo/go/net/ipsock_posix.go2
-rw-r--r--libgo/go/net/lookup_plan9.go24
-rw-r--r--libgo/go/net/lookup_test.go27
-rw-r--r--libgo/go/net/lookup_unix.go84
-rw-r--r--libgo/go/net/lookup_windows.go38
-rw-r--r--libgo/go/net/multicast_test.go116
-rw-r--r--libgo/go/net/net_test.go50
-rw-r--r--libgo/go/net/newpollserver.go2
-rw-r--r--libgo/go/net/parse.go43
-rw-r--r--libgo/go/net/port.go2
-rw-r--r--libgo/go/net/sendfile_stub.go2
-rw-r--r--libgo/go/net/sendfile_windows.go2
-rw-r--r--libgo/go/net/server_test.go4
-rw-r--r--libgo/go/net/sock.go3
-rw-r--r--libgo/go/net/sock_bsd.go2
-rw-r--r--libgo/go/net/tcpsock_posix.go27
-rw-r--r--libgo/go/net/textproto/header.go2
-rw-r--r--libgo/go/net/textproto/pipeline.go2
-rw-r--r--libgo/go/net/textproto/reader.go33
-rw-r--r--libgo/go/net/textproto/reader_test.go53
-rw-r--r--libgo/go/net/udpsock_plan9.go11
-rw-r--r--libgo/go/net/udpsock_posix.go100
-rw-r--r--libgo/go/net/unixsock_posix.go2
-rw-r--r--libgo/go/netchan/export.go400
-rw-r--r--libgo/go/netchan/import.go287
-rw-r--r--libgo/go/old/netchan/common.go (renamed from libgo/go/netchan/common.go)0
-rw-r--r--libgo/go/old/netchan/export.go400
-rw-r--r--libgo/go/old/netchan/import.go287
-rw-r--r--libgo/go/old/netchan/netchan_test.go (renamed from libgo/go/netchan/netchan_test.go)0
-rw-r--r--libgo/go/old/regexp/all_test.go426
-rw-r--r--libgo/go/old/regexp/find_test.go472
-rw-r--r--libgo/go/old/regexp/regexp.go1488
-rw-r--r--libgo/go/old/template/template_test.go7
-rw-r--r--libgo/go/os/dir_plan9.go2
-rw-r--r--libgo/go/os/dir_unix.go2
-rw-r--r--libgo/go/os/env.go4
-rw-r--r--libgo/go/os/env_unix.go2
-rw-r--r--libgo/go/os/error_plan9.go1
-rw-r--r--libgo/go/os/error_posix.go2
-rw-r--r--libgo/go/os/exec_posix.go2
-rw-r--r--libgo/go/os/exec_unix.go5
-rw-r--r--libgo/go/os/file_posix.go37
-rw-r--r--libgo/go/os/file_unix.go35
-rw-r--r--libgo/go/os/inotify/inotify_linux.go2
-rw-r--r--libgo/go/os/os_test.go6
-rw-r--r--libgo/go/os/path.go2
-rw-r--r--libgo/go/os/path_unix.go2
-rw-r--r--libgo/go/os/str.go2
-rw-r--r--libgo/go/os/sys_bsd.go2
-rw-r--r--libgo/go/os/user/lookup_stubs.go2
-rw-r--r--libgo/go/os/user/lookup_unix.go19
-rw-r--r--libgo/go/path/filepath/match.go2
-rw-r--r--libgo/go/path/filepath/match_test.go10
-rw-r--r--libgo/go/path/filepath/path.go154
-rw-r--r--libgo/go/path/filepath/path_test.go264
-rw-r--r--libgo/go/path/filepath/path_unix.go2
-rw-r--r--libgo/go/path/filepath/path_windows.go35
-rw-r--r--libgo/go/rand/rand_test.go4
-rw-r--r--libgo/go/reflect/all_test.go165
-rw-r--r--libgo/go/reflect/deepequal.go2
-rw-r--r--libgo/go/reflect/type.go8
-rw-r--r--libgo/go/reflect/value.go118
-rw-r--r--libgo/go/regexp/all_test.go7
-rw-r--r--libgo/go/regexp/exec.go305
-rw-r--r--libgo/go/regexp/exec_test.go734
-rw-r--r--libgo/go/regexp/find_test.go32
-rw-r--r--libgo/go/regexp/regexp.go1011
-rw-r--r--libgo/go/regexp/syntax/compile.go288
-rw-r--r--libgo/go/regexp/syntax/parse.go1861
-rw-r--r--libgo/go/regexp/syntax/parse_test.go552
-rw-r--r--libgo/go/regexp/syntax/perl_groups.go (renamed from libgo/go/exp/regexp/syntax/perl_groups.go)0
-rw-r--r--libgo/go/regexp/syntax/prog.go306
-rw-r--r--libgo/go/regexp/syntax/prog_test.go102
-rw-r--r--libgo/go/regexp/syntax/regexp.go305
-rw-r--r--libgo/go/regexp/syntax/simplify.go (renamed from libgo/go/exp/regexp/syntax/simplify.go)0
-rw-r--r--libgo/go/regexp/syntax/simplify_test.go152
-rw-r--r--libgo/go/regexp/testdata/README23
-rw-r--r--libgo/go/regexp/testdata/basic.dat221
-rw-r--r--libgo/go/regexp/testdata/nullsubexpr.dat79
-rw-r--r--libgo/go/regexp/testdata/re2-search.txt3667
-rw-r--r--libgo/go/regexp/testdata/repetition.dat163
-rw-r--r--libgo/go/regexp/testdata/testregex.c2286
-rw-r--r--libgo/go/rpc/client.go25
-rw-r--r--libgo/go/rpc/jsonrpc/client.go2
-rw-r--r--libgo/go/rpc/jsonrpc/server.go2
-rw-r--r--libgo/go/rpc/server.go2
-rw-r--r--libgo/go/rpc/server_test.go117
-rw-r--r--libgo/go/runtime/chan_test.go51
-rw-r--r--libgo/go/runtime/extern.go7
-rw-r--r--libgo/go/runtime/gc_test.go24
-rw-r--r--libgo/go/runtime/mfinal_test.go64
-rw-r--r--libgo/go/runtime/pprof/pprof_test.go3
-rw-r--r--libgo/go/scanner/scanner.go18
-rw-r--r--libgo/go/scanner/scanner_test.go15
-rw-r--r--libgo/go/sort/example_test.go17
-rw-r--r--libgo/go/sort/export_test.go9
-rw-r--r--libgo/go/sort/sort.go61
-rw-r--r--libgo/go/sort/sort_test.go68
-rw-r--r--libgo/go/strconv/atof.go58
-rw-r--r--libgo/go/strconv/atof_test.go1
-rw-r--r--libgo/go/strconv/decimal.go11
-rw-r--r--libgo/go/strconv/decimal_test.go8
-rw-r--r--libgo/go/strconv/ftoa.go9
-rw-r--r--libgo/go/strconv/quote.go16
-rw-r--r--libgo/go/strconv/quote_test.go16
-rw-r--r--libgo/go/strings/export_test.go9
-rw-r--r--libgo/go/strings/replace.go315
-rw-r--r--libgo/go/strings/replace_test.go174
-rw-r--r--libgo/go/strings/strings.go55
-rw-r--r--libgo/go/strings/strings_test.go107
-rw-r--r--libgo/go/sync/atomic/atomic.c143
-rw-r--r--libgo/go/sync/atomic/atomic_test.go621
-rw-r--r--libgo/go/sync/atomic/doc.go39
-rw-r--r--libgo/go/syscall/bpf_bsd.go169
-rw-r--r--libgo/go/syscall/errno.c25
-rw-r--r--libgo/go/syscall/errstr.go27
-rw-r--r--libgo/go/syscall/errstr_linux.go23
-rw-r--r--libgo/go/syscall/errstr_nor.go33
-rw-r--r--libgo/go/syscall/exec_stubs.go23
-rw-r--r--libgo/go/syscall/exec_unix.go449
-rw-r--r--libgo/go/syscall/exec_windows.go327
-rw-r--r--libgo/go/syscall/libcall_irix.go8
-rw-r--r--libgo/go/syscall/libcall_linux.go333
-rw-r--r--libgo/go/syscall/libcall_posix.go385
-rw-r--r--libgo/go/syscall/libcall_posix_largefile.go37
-rw-r--r--libgo/go/syscall/libcall_posix_regfile.go38
-rw-r--r--libgo/go/syscall/libcall_solaris_386.go12
-rw-r--r--libgo/go/syscall/libcall_solaris_amd64.go10
-rw-r--r--libgo/go/syscall/libcall_solaris_sparc.go8
-rw-r--r--libgo/go/syscall/libcall_solaris_sparc64.go10
-rw-r--r--libgo/go/syscall/libcall_support.go12
-rw-r--r--libgo/go/syscall/libcall_uname.go8
-rw-r--r--libgo/go/syscall/libcall_wait4.go21
-rw-r--r--libgo/go/syscall/libcall_waitpid.go21
-rw-r--r--libgo/go/syscall/lsf_linux.go78
-rw-r--r--libgo/go/syscall/mksyscall.awk263
-rw-r--r--libgo/go/syscall/netlink_linux.go229
-rw-r--r--libgo/go/syscall/route_bsd.go197
-rw-r--r--libgo/go/syscall/route_darwin.go77
-rw-r--r--libgo/go/syscall/route_freebsd.go77
-rw-r--r--libgo/go/syscall/route_openbsd.go35
-rw-r--r--libgo/go/syscall/sleep_rtems.go13
-rw-r--r--libgo/go/syscall/sleep_select.go13
-rw-r--r--libgo/go/syscall/sockcmsg_linux.go38
-rw-r--r--libgo/go/syscall/sockcmsg_unix.go115
-rw-r--r--libgo/go/syscall/socket.go419
-rw-r--r--libgo/go/syscall/socket_bsd.go (renamed from libgo/syscalls/socket_bsd.go)0
-rw-r--r--libgo/go/syscall/socket_irix.go129
-rw-r--r--libgo/go/syscall/socket_linux.go174
-rw-r--r--libgo/go/syscall/socket_solaris.go80
-rw-r--r--libgo/go/syscall/str.go20
-rw-r--r--libgo/go/syscall/syscall.go35
-rw-r--r--libgo/go/syscall/syscall_linux_386.go (renamed from libgo/syscalls/syscall_linux_386.go)0
-rw-r--r--libgo/go/syscall/syscall_linux_alpha.go (renamed from libgo/syscalls/syscall_linux_alpha.go)0
-rw-r--r--libgo/go/syscall/syscall_linux_amd64.go (renamed from libgo/syscalls/syscall_linux_amd64.go)0
-rw-r--r--libgo/go/syscall/syscall_stubs.go27
-rw-r--r--libgo/go/syscall/syscall_unix.go159
-rw-r--r--libgo/go/syscall/wait.c107
-rw-r--r--libgo/go/template/exec.go2
-rw-r--r--libgo/go/template/exec_test.go67
-rw-r--r--libgo/go/template/helper.go6
-rw-r--r--libgo/go/template/parse.go16
-rw-r--r--libgo/go/template/parse/lex.go52
-rw-r--r--libgo/go/template/parse/lex_test.go40
-rw-r--r--libgo/go/template/parse/node.go74
-rw-r--r--libgo/go/template/parse/parse.go7
-rw-r--r--libgo/go/template/parse/parse_test.go2
-rw-r--r--libgo/go/template/parse/set.go4
-rw-r--r--libgo/go/template/set.go14
-rw-r--r--libgo/go/testing/example.go84
-rw-r--r--libgo/go/testing/testing.go120
-rw-r--r--libgo/go/time/format.go32
-rw-r--r--libgo/go/time/internal_test.go12
-rw-r--r--libgo/go/time/sleep_test.go3
-rw-r--r--libgo/go/time/sys_plan9.go5
-rw-r--r--libgo/go/time/sys_posix.go18
-rw-r--r--libgo/go/time/sys_unix.go25
-rw-r--r--libgo/go/time/sys_windows.go22
-rw-r--r--libgo/go/time/time.go23
-rw-r--r--libgo/go/time/time_test.go59
-rw-r--r--libgo/go/time/zoneinfo_plan9.go16
-rw-r--r--libgo/go/time/zoneinfo_posix.go2
-rw-r--r--libgo/go/time/zoneinfo_unix.go7
-rw-r--r--libgo/go/time/zoneinfo_windows.go65
-rw-r--r--libgo/go/try/try.go174
-rw-r--r--libgo/go/try/try_test.go60
-rw-r--r--libgo/go/unicode/script_test.go6
-rw-r--r--libgo/go/url/url.go32
-rw-r--r--libgo/go/url/url_test.go62
-rw-r--r--libgo/go/utf8/utf8.go37
-rw-r--r--libgo/go/utf8/utf8_test.go29
-rw-r--r--libgo/go/websocket/client.go309
-rw-r--r--libgo/go/websocket/hixie.go696
-rw-r--r--libgo/go/websocket/hixie_test.go201
-rw-r--r--libgo/go/websocket/hybi.go550
-rw-r--r--libgo/go/websocket/hybi_test.go584
-rw-r--r--libgo/go/websocket/server.go210
-rw-r--r--libgo/go/websocket/websocket.go455
-rw-r--r--libgo/go/websocket/websocket_test.go196
-rw-r--r--libgo/go/xml/marshal.go93
-rw-r--r--libgo/go/xml/marshal_test.go123
-rw-r--r--libgo/go/xml/read.go5
-rw-r--r--libgo/go/xml/read_test.go22
-rw-r--r--libgo/go/xml/xml.go6
-rwxr-xr-xlibgo/merge.sh4
-rwxr-xr-xlibgo/mksysinfo.sh84
-rw-r--r--libgo/runtime/arch.h8
-rw-r--r--libgo/runtime/cpuprof.c1
-rw-r--r--libgo/runtime/go-append.c1
-rw-r--r--libgo/runtime/go-byte-array-to-string.c1
-rw-r--r--libgo/runtime/go-close.c3
-rw-r--r--libgo/runtime/go-go.c3
-rw-r--r--libgo/runtime/go-int-array-to-string.c1
-rw-r--r--libgo/runtime/go-int-to-string.c1
-rw-r--r--libgo/runtime/go-main.c1
-rw-r--r--libgo/runtime/go-make-slice.c1
-rw-r--r--libgo/runtime/go-map-delete.c2
-rw-r--r--libgo/runtime/go-new.c1
-rw-r--r--libgo/runtime/go-note.c2
-rw-r--r--libgo/runtime/go-panic.c1
-rw-r--r--libgo/runtime/go-semacquire.c6
-rw-r--r--libgo/runtime/go-string-to-byte-array.c1
-rw-r--r--libgo/runtime/go-string-to-int-array.c1
-rw-r--r--libgo/runtime/go-strplus.c1
-rw-r--r--libgo/runtime/go-strslice.c1
-rw-r--r--libgo/runtime/goc2c.c28
-rw-r--r--libgo/runtime/malloc.goc57
-rw-r--r--libgo/runtime/malloc.h40
-rw-r--r--libgo/runtime/map.goc6
-rw-r--r--libgo/runtime/mcache.c1
-rw-r--r--libgo/runtime/mcentral.c1
-rw-r--r--libgo/runtime/mem.c8
-rw-r--r--libgo/runtime/mem_posix_memalign.c1
-rw-r--r--libgo/runtime/mfinal.c226
-rw-r--r--libgo/runtime/mfixalloc.c1
-rw-r--r--libgo/runtime/mgc0.c634
-rw-r--r--libgo/runtime/mheap.c3
-rw-r--r--libgo/runtime/mprof.goc1
-rw-r--r--libgo/runtime/msize.c1
-rw-r--r--libgo/runtime/proc.c19
-rw-r--r--libgo/runtime/runtime.h9
-rw-r--r--libgo/runtime/sigqueue.goc1
-rw-r--r--libgo/runtime/thread.c13
-rw-r--r--libgo/runtime/yield.c54
-rw-r--r--libgo/syscalls/errno.c25
-rw-r--r--libgo/syscalls/errstr.go24
-rw-r--r--libgo/syscalls/errstr_decl.go9
-rw-r--r--libgo/syscalls/errstr_decl_linux.go9
-rw-r--r--libgo/syscalls/errstr_decl_rtems.go10
-rw-r--r--libgo/syscalls/errstr_nor.go32
-rw-r--r--libgo/syscalls/errstr_rtems.go26
-rw-r--r--libgo/syscalls/exec.go346
-rw-r--r--libgo/syscalls/exec_helpers.go154
-rw-r--r--libgo/syscalls/exec_stubs.go25
-rw-r--r--libgo/syscalls/netlink_linux.go227
-rw-r--r--libgo/syscalls/sleep_rtems.go19
-rw-r--r--libgo/syscalls/sleep_select.go13
-rw-r--r--libgo/syscalls/socket.go392
-rw-r--r--libgo/syscalls/socket_epoll.go50
-rw-r--r--libgo/syscalls/socket_irix.go129
-rw-r--r--libgo/syscalls/socket_linux.go165
-rw-r--r--libgo/syscalls/socket_solaris.go80
-rw-r--r--libgo/syscalls/stringbyte.go37
-rw-r--r--libgo/syscalls/syscall.go111
-rw-r--r--libgo/syscalls/syscall_irix.go17
-rw-r--r--libgo/syscalls/syscall_linux.go206
-rw-r--r--libgo/syscalls/syscall_rtems.go7
-rw-r--r--libgo/syscalls/syscall_solaris.go7
-rw-r--r--libgo/syscalls/syscall_solaris_386.go20
-rw-r--r--libgo/syscalls/syscall_solaris_amd64.go21
-rw-r--r--libgo/syscalls/syscall_solaris_sparc.go17
-rw-r--r--libgo/syscalls/syscall_solaris_sparc64.go21
-rw-r--r--libgo/syscalls/syscall_stubs.go33
-rw-r--r--libgo/syscalls/syscall_uname.go7
-rw-r--r--libgo/syscalls/syscall_unix.go67
-rw-r--r--libgo/syscalls/sysfile_largefile.go14
-rw-r--r--libgo/syscalls/sysfile_posix.go429
-rw-r--r--libgo/syscalls/sysfile_regfile.go14
-rw-r--r--libgo/syscalls/sysfile_stat_largefile.go12
-rw-r--r--libgo/syscalls/sysfile_stat_regfile.go12
-rw-r--r--libgo/syscalls/wait4.go22
-rw-r--r--libgo/syscalls/waitpid.go22
-rw-r--r--libgo/testsuite/Makefile.in7
-rwxr-xr-xlibgo/testsuite/gotest18
-rw-r--r--libiberty/ChangeLog17
-rw-r--r--libiberty/setproctitle.c4
-rw-r--r--libiberty/simple-object-mach-o.c515
-rw-r--r--libjava/ChangeLog13
-rw-r--r--libjava/exception.cc22
-rw-r--r--libjava/include/dwarf2-signal.h15
-rw-r--r--libobjc/ChangeLog14
-rw-r--r--libobjc/Makefile.in1
-rw-r--r--libobjc/config.h.in3
-rwxr-xr-xlibobjc/configure14
-rw-r--r--libobjc/configure.ac9
-rw-r--r--libobjc/exception.c27
-rw-r--r--libquadmath/ChangeLog4
-rw-r--r--libquadmath/printf/gmp-impl.h4
-rw-r--r--libstdc++-v3/ChangeLog345
-rw-r--r--libstdc++-v3/Makefile.in2
-rw-r--r--libstdc++-v3/acinclude.m475
-rw-r--r--libstdc++-v3/config.h.in7
-rw-r--r--libstdc++-v3/config/abi/pre/gnu.ver3
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/ctype_base.h64
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc243
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/ctype_inline.h75
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/error_constants.h142
-rw-r--r--libstdc++-v3/config/os/mingw32-w64/os_defines.h68
-rwxr-xr-xlibstdc++-v3/configure88
-rw-r--r--libstdc++-v3/configure.host12
-rw-r--r--libstdc++-v3/doc/Makefile.in2
-rw-r--r--libstdc++-v3/doc/doxygen/user.cfg.in4
-rw-r--r--libstdc++-v3/doc/xml/faq.xml4
-rw-r--r--libstdc++-v3/doc/xml/manual/prerequisites.xml26
-rw-r--r--libstdc++-v3/doc/xml/manual/using.xml106
-rw-r--r--libstdc++-v3/include/Makefile.am154
-rw-r--r--libstdc++-v3/include/Makefile.in156
-rw-r--r--libstdc++-v3/include/bits/algorithmfwd.h2
-rw-r--r--libstdc++-v3/include/bits/basic_string.h12
-rw-r--r--libstdc++-v3/include/bits/basic_string.tcc8
-rw-r--r--libstdc++-v3/include/bits/c++0x_warning.h6
-rw-r--r--libstdc++-v3/include/bits/c++config7
-rw-r--r--libstdc++-v3/include/bits/codecvt.h4
-rw-r--r--libstdc++-v3/include/bits/forward_list.h2
-rw-r--r--libstdc++-v3/include/bits/random.h11
-rw-r--r--libstdc++-v3/include/bits/random.tcc8
-rw-r--r--libstdc++-v3/include/bits/shared_ptr.h2
-rw-r--r--libstdc++-v3/include/bits/stl_bvector.h2
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h2
-rw-r--r--libstdc++-v3/include/bits/stl_list.h2
-rw-r--r--libstdc++-v3/include/bits/stl_map.h2
-rw-r--r--libstdc++-v3/include/bits/stl_multimap.h2
-rw-r--r--libstdc++-v3/include/bits/stl_multiset.h2
-rw-r--r--libstdc++-v3/include/bits/stl_set.h2
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h2
-rw-r--r--libstdc++-v3/include/ext/vstring.h3
-rw-r--r--libstdc++-v3/include/std/complex9
-rw-r--r--libstdc++-v3/include/std/condition_variable49
-rw-r--r--libstdc++-v3/include/std/future53
-rw-r--r--libstdc++-v3/include/std/mutex203
-rw-r--r--libstdc++-v3/include/std/valarray2
-rw-r--r--libstdc++-v3/include/tr1/complex9
-rw-r--r--libstdc++-v3/include/tr2/bool_set320
-rw-r--r--libstdc++-v3/include/tr2/bool_set.tcc277
-rw-r--r--libstdc++-v3/include/tr2/dynamic_bitset1472
-rw-r--r--libstdc++-v3/include/tr2/ratio59
-rw-r--r--libstdc++-v3/include/tr2/type_traits102
-rw-r--r--libstdc++-v3/libsupc++/Makefile.in2
-rw-r--r--libstdc++-v3/libsupc++/del_op.cc5
-rw-r--r--libstdc++-v3/libsupc++/del_opnt.cc5
-rw-r--r--libstdc++-v3/libsupc++/del_opv.cc5
-rw-r--r--libstdc++-v3/libsupc++/del_opvnt.cc5
-rw-r--r--libstdc++-v3/libsupc++/initializer_list5
-rw-r--r--libstdc++-v3/libsupc++/new36
-rw-r--r--libstdc++-v3/libsupc++/new_op.cc2
-rw-r--r--libstdc++-v3/libsupc++/new_opnt.cc2
-rw-r--r--libstdc++-v3/libsupc++/new_opv.cc5
-rw-r--r--libstdc++-v3/libsupc++/new_opvnt.cc6
-rw-r--r--libstdc++-v3/po/Makefile.in2
-rw-r--r--libstdc++-v3/python/Makefile.in2
-rwxr-xr-xlibstdc++-v3/scripts/create_testsuite_files2
-rw-r--r--libstdc++-v3/scripts/run_doxygen4
-rw-r--r--libstdc++-v3/src/Makefile.in2
-rw-r--r--libstdc++-v3/src/condition_variable.cc22
-rw-r--r--libstdc++-v3/testsuite/18_support/50594.cc72
-rw-r--r--libstdc++-v3/testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/18_support/headers/cstdint/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/19_diagnostics/headers/system_error/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc16
-rw-r--r--libstdc++-v3/testsuite/22_locale/codecvt_byname/50714.cc95
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/insert_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/headers/array/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/headers/tuple/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/headers/unordered_map/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/headers/unordered_set/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/operations/count.cc106
-rw-r--r--libstdc++-v3/testsuite/23_containers/multimap/operations/count.cc106
-rw-r--r--libstdc++-v3/testsuite/23_containers/multiset/operations/count.cc104
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/operations/count.cc104
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/operations/count.cc108
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multimap/operations/count.cc108
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_multiset/operations/count.cc106
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/operations/count.cc106
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/26_numerics/complex/50880.cc53
-rw-r--r--libstdc++-v3/testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/26_numerics/headers/cfenv/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/26_numerics/headers/random/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/operators/serialize.cc16
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/operators/serialize.cc16
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/operators/serialize.cc30
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/operators/serialize.cc16
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/operators/serialize.cc16
-rw-r--r--libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/operators/serialize.cc16
-rw-r--r--libstdc++-v3/testsuite/27_io/headers/cinttypes/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/28_regex/headers/regex/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/29_atomics/headers/atomic/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/30_threads/async/49668.cc1
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc80
-rw-r--r--libstdc++-v3/testsuite/30_threads/condition_variable_any/requirements/typedefs.cc30
-rw-r--r--libstdc++-v3/testsuite/30_threads/headers/condition_variable/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/30_threads/headers/future/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/30_threads/headers/mutex/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/30_threads/headers/thread/std_c++0x_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc1
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc56
-rw-r--r--libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc2.cc40
-rw-r--r--libstdc++-v3/testsuite/30_threads/promise/cons/alloc2.cc42
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/requirements/typedefs.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/cons/assign_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/cons/copy_neg.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/standard_layout.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/typedefs.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc4
-rw-r--r--libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc4
-rw-r--r--libstdc++-v3/testsuite/Makefile.in2
-rw-r--r--libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/lib/dg-options.exp9
-rw-r--r--libstdc++-v3/testsuite/lib/libstdc++.exp60
-rw-r--r--libstdc++-v3/testsuite/libstdc++-dg/conformance.exp1
-rw-r--r--libstdc++-v3/testsuite/performance/23_containers/insert_erase/41975.cc72
-rw-r--r--libstdc++-v3/testsuite/tr1/8_c_compatibility/complex/50880.cc51
-rw-r--r--libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc32
-rw-r--r--libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc31
-rw-r--r--libstdc++-v3/testsuite/tr2/bases/value.cc97
-rw-r--r--libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc32
-rw-r--r--libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc31
-rw-r--r--libstdc++-v3/testsuite/tr2/direct_bases/value.cc91
-rw-r--r--libstdc++-v3/testsuite/tr2/headers/all.cc24
-rw-r--r--libstdc++-v3/testsuite/tr2/headers/using_namespace_std_tr2.cc26
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_allocator.h8
-rw-r--r--libstdc++-v3/testsuite/util/testsuite_rvalref.h3
2432 files changed, 120800 insertions, 54800 deletions
diff --git a/ChangeLog b/ChangeLog
index 69c10e7f241..49ba74f4f0d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makefile.tpl (EXTRA_GCC_FLAGS): Remove LIBGCC2_CFLAGS,
+ LIBGCC2_DEBUG_CFLAGS, LIBGCC2_INCLUDES.
+ * Makefile.in: Regenerate.
+
+2011-11-01 DJ Delorie <dj@redhat.com>
+
+ * config.sub: Update to version 2011-10-29 (added rl78)
+
+2011-10-27 Nick Clifton <nickc@redhat.com>
+
+ * config.sub: Import these changes from the config project:
+
+ 2011-10-08 Joern Rennecke <joern.rennecke@embecosm.com>
+ Ben Elliston <bje@gnu.org>
+
+ * config.sub (epiphany): New.
+
+ 2011-09-09 Linas Vepstas <linasvepstas@gmail.com>
+ Ben Elliston <bje@gnu.org>
+
+ * config.sub (hexagon, hexagon-*): New.
+
+ 2011-08-23 Roland McGrath <mcgrathr@google.com>
+
+ * config.sub: Rename 32eb to be32, 32el to le32, 64el to le64, and
+ 64eb to be64.
+
+ 2011-08-16 Roland McGrath <mcgrathr@google.com>
+
+ * config.sub (32eb, 32el, 64eb, 64el): New (pseudo-)CPUs.
+ (nacl): Grok as alias for 32el-unknown-nacl.
+
+2011-10-25 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ * MAINTAINERS (Write After Approval): Add myself.
+
+2011-10-24 Teresa Johnson <tejohnson@google.com>
+
+ * MAINTAINERS (Write After Approval): Add myself.
+
2011-09-21 Jakub Jelinek <jakub@redhat.com>
* MAINTAINERS (sparc port): Remove myself.
diff --git a/MAINTAINERS b/MAINTAINERS
index 9eae7f94e25..c78388267dd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -392,6 +392,7 @@ Fariborz Jahanian fjahanian@apple.com
Martin Jambor mjambor@suse.cz
Andrew Jenner andrew@codesourcery.com
Janis Johnson janisjo@codesourcery.com
+Teresa Johnson tejohnson@google.com
Kean Johnston jkj@sco.com
Phillip Jordan phillip.m.jordan@gmail.com
Tim Josling tej@melbpc.org.au
@@ -521,6 +522,7 @@ Canqun Yang canqun@nudt.edu.cn
Jeffrey Yasskin jyasskin@google.com
Joey Ye joey.ye@arm.com
David Yuste david.yuste@gmail.com
+Kirill Yukhin kirill.yukhin@gmail.com
Kenneth Zadeck zadeck@naturalbridge.com
Yufeng Zhang yufeng.zhang@arm.com
Shujing Zhao pearly.zhao@oracle.com
diff --git a/Makefile.in b/Makefile.in
index d1206bda659..821499d7608 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -3,7 +3,7 @@
#
# Makefile for directory with subdirs to build.
# Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-# 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+# 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
# Free Software Foundation
#
# This file is free software; you can redistribute it and/or modify
@@ -871,10 +871,7 @@ TARGET_FLAGS_TO_PASS = $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS)
EXTRA_GCC_FLAGS = \
"GCC_FOR_TARGET=$(GCC_FOR_TARGET)" \
"`echo 'STMP_FIXPROTO=$(STMP_FIXPROTO)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
- "`echo 'LIMITS_H_TEST=$(LIMITS_H_TEST)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
- "`echo 'LIBGCC2_CFLAGS=$(LIBGCC2_CFLAGS)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
- "`echo 'LIBGCC2_DEBUG_CFLAGS=$(LIBGCC2_DEBUG_CFLAGS)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
- "`echo 'LIBGCC2_INCLUDES=$(LIBGCC2_INCLUDES)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`"
+ "`echo 'LIMITS_H_TEST=$(LIMITS_H_TEST)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`"
GCC_FLAGS_TO_PASS = $(BASE_FLAGS_TO_PASS) $(EXTRA_HOST_FLAGS) $(EXTRA_GCC_FLAGS)
diff --git a/Makefile.tpl b/Makefile.tpl
index 4dd23915bed..2944d60d642 100644
--- a/Makefile.tpl
+++ b/Makefile.tpl
@@ -6,7 +6,7 @@ in
#
# Makefile for directory with subdirs to build.
# Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-# 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+# 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
# Free Software Foundation
#
# This file is free software; you can redistribute it and/or modify
@@ -668,10 +668,7 @@ TARGET_FLAGS_TO_PASS = $(BASE_FLAGS_TO_PASS) $(EXTRA_TARGET_FLAGS)
EXTRA_GCC_FLAGS = \
"GCC_FOR_TARGET=$(GCC_FOR_TARGET)" \
"`echo 'STMP_FIXPROTO=$(STMP_FIXPROTO)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
- "`echo 'LIMITS_H_TEST=$(LIMITS_H_TEST)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
- "`echo 'LIBGCC2_CFLAGS=$(LIBGCC2_CFLAGS)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
- "`echo 'LIBGCC2_DEBUG_CFLAGS=$(LIBGCC2_DEBUG_CFLAGS)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`" \
- "`echo 'LIBGCC2_INCLUDES=$(LIBGCC2_INCLUDES)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`"
+ "`echo 'LIMITS_H_TEST=$(LIMITS_H_TEST)' | sed -e s'/[^=][^=]*=$$/XFOO=/'`"
GCC_FLAGS_TO_PASS = $(BASE_FLAGS_TO_PASS) $(EXTRA_HOST_FLAGS) $(EXTRA_GCC_FLAGS)
diff --git a/config.sub b/config.sub
index f9fcdc8796e..78176a44029 100755
--- a/config.sub
+++ b/config.sub
@@ -4,7 +4,7 @@
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011 Free Software Foundation, Inc.
-timestamp='2011-06-03'
+timestamp='2011-10-29'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -251,13 +251,17 @@ case $basic_machine in
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+ | be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
+ | epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
+ | le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore | mep | metag \
@@ -291,7 +295,7 @@ case $basic_machine in
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
- | rx \
+ | rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
@@ -357,6 +361,7 @@ case $basic_machine in
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
+ | be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
@@ -365,8 +370,10 @@ case $basic_machine in
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
+ | le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
@@ -400,7 +407,7 @@ case $basic_machine in
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
- | romp-* | rs6000-* | rx-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
@@ -813,6 +820,10 @@ case $basic_machine in
basic_machine=i370-ibm
os=-mvs
;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
diff --git a/config/ChangeLog b/config/ChangeLog
index 047cdf5f007..7737f99b2bd 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * mh-interix (LIBGCC2_DEBUG_CFLAGS): Remove.
+
2011-08-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* picflag.m4: New file.
diff --git a/config/mh-interix b/config/mh-interix
index 67dff5c4432..3be195b51ec 100644
--- a/config/mh-interix
+++ b/config/mh-interix
@@ -1,7 +1,2 @@
# The shell may not be in /bin.
SHELL = sh
-
-# We also need to override LIBGCC2_DEBUG_CFLAGS so libgcc2 will be
-# built without debugging information
-
-LIBGCC2_DEBUG_CFLAGS=
diff --git a/fixincludes/ChangeLog b/fixincludes/ChangeLog
index cb67edccde9..a73eaacea2f 100644
--- a/fixincludes/ChangeLog
+++ b/fixincludes/ChangeLog
@@ -1,3 +1,9 @@
+2011-10-25 Mike Stump <mikestump@comcast.net>
+
+ PR target/48851
+ * inclhack.def (void_null): New bypass.
+ * fixincl.x: Regenerate.
+
2011-09-26 Tristan Gingold <gingold@adacore.com>
* inclhack.def (ms_define_can_use_extern_prefix):
diff --git a/fixincludes/fixincl.x b/fixincludes/fixincl.x
index cc25834c399..0f5e5fcae8e 100644
--- a/fixincludes/fixincl.x
+++ b/fixincludes/fixincl.x
@@ -2,11 +2,11 @@
*
* DO NOT EDIT THIS FILE (fixincl.x)
*
- * It has been AutoGen-ed September 22, 2011 at 04:28:52 PM by AutoGen 5.11.1
+ * It has been AutoGen-ed Sunday October 23, 2011 at 12:18:29 PM EST
* From the definitions inclhack.def
* and the template file fixincl
*/
-/* DO NOT SVN-MERGE THIS FILE, EITHER Thu Sep 22 16:28:52 CEST 2011
+/* DO NOT SVN-MERGE THIS FILE, EITHER Sun Oct 23 12:18:29 EST 2011
*
* You must regenerate it. Use the ./genfixes script.
*
@@ -8587,10 +8587,13 @@ tSCC zVoid_NullSelect0[] =
*/
tSCC zVoid_NullBypass0[] =
"__cplusplus";
+tSCC zVoid_NullBypass1[] =
+ "__null";
-#define VOID_NULL_TEST_CT 2
+#define VOID_NULL_TEST_CT 3
static tTestDesc aVoid_NullTests[] = {
{ TT_NEGREP, zVoid_NullBypass0, (regex_t*)NULL },
+ { TT_NEGREP, zVoid_NullBypass1, (regex_t*)NULL },
{ TT_EGREP, zVoid_NullSelect0, (regex_t*)NULL }, };
/*
@@ -8953,7 +8956,7 @@ static const char* apzX11_SprintfPatch[] = {
*
* List of all fixes
*/
-#define REGEX_COUNT 261
+#define REGEX_COUNT 262
#define MACH_LIST_SIZE_LIMIT 181
#define FIX_COUNT 220
diff --git a/fixincludes/inclhack.def b/fixincludes/inclhack.def
index afaabc0422d..7445d99f00b 100644
--- a/fixincludes/inclhack.def
+++ b/fixincludes/inclhack.def
@@ -4585,6 +4585,7 @@ fix = {
files = sys/types.h;
/* avoid changing C++ friendly NULL */
bypass = __cplusplus;
+ bypass = __null;
select = "^#[ \t]*define[ \t]+NULL[ \t]+\\(\\(void[ \t]*\\*\\)0\\)";
c_fix = format;
c_fix_arg = "#define NULL 0";
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6bc0bd6809b..a3c6d539d6f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,3661 @@
+2011-11-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/50945
+ * config/sparc/sparc.md (movsf_insn): Reindent constraints.
+ (movdf_insn_sp32): Likewise. Remove redundant G constraint.
+ (movdf_insn_sp64): Likewise.
+ (DFmode splitter): Do not test TARGET_FPU.
+ (movtf_insn_sp32): Reindent constraints.
+ (movtf_insn_sp32_no_fpu): Likewise.
+ (movtf_insn_sp64): Likewise.
+ (movtf_insn_sp64_hq): Likewise.
+ (movtf_insn_sp64_no_fpu): Likewise.
+
+2011-11-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50956
+ * builtins.c (fold_builtin_memchr): Fix cast.
+
+2011-11-02 Teresa Johnson <tejohnson@google.com>
+
+ * config/i386/predicates.md (promotable_binary_operator): Add minus
+ to the list of promotable operators.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gthr-single.h, gthr.h: Move to ../libgcc.
+ * gthr-aix.h: Move to ../libgcc/config/rs6000.
+ * gthr-dce.h: Move to ../libgcc/config/pa.
+ * gthr-lynx.h: Move to ../libgcc/config.
+ * gthr-mipssde.h: Move to ../libgcc/config/mips.
+ * gthr-posix.h: Move to ../libgcc/config.
+ * gthr-rtems.h: Likewise.
+ * gthr-tpf.h: Move to ../libgcc/config/s390.
+ * gthr-vxworks.h: Move to ../libgcc/config.
+ * gthr-win32.h: Move to ../libgcc/config/i386.
+ * configure.ac (gthread_flags): Remove
+ (gthr-default.h): Don't create.
+ (thread_file): Don't substitute.
+ * configure: Regenerate.
+ * Makefile.in (GCC_THREAD_FILE): Remove.
+ (GTHREAD_FLAGS): Remove.
+ (libgcc.mvars): Remove GTHREAD_FLAGS.
+ * config/t-vxworks (EXTRA_HEADERS): Remove.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+ Paolo Bonzini <bonzini@gnu.org>
+
+ * configure.ac (libgcc_tm_file_list, libgcc_tm_include_list):
+ Remove.
+ * configure: Regenerate.
+ * Makefile.in (libgcc_tm_file_list, libgcc_tm_include_list): Remove.
+ (TM_H): Remove libgcc_tm.h, $(libgcc_tm_file_list).
+ (libgcc_tm.h, cs-libgcc_tm.h): Remove.
+ (clean): Remove libgcc_tm.h
+ * mkconfig.sh: Don't include libgcc_tm.h in tm.h.
+ * config.gcc (libgcc_tm_file): Remove.
+ (arm*-*-linux*): Remove libgcc_tm_file for arm*-*-linux-*eabi.
+ (arm*-*-uclinux*): Remove libgcc_tm_file for arm*-*-uclinux*eabi.
+ (arm*-*-eabi*, arm*-*-symbianelf*): Remove libgcc_tm_file.
+ (avr-*-rtems*): Likewise.
+ (avr-*-*): Likewise.
+ (frv-*-elf): Likewise.
+ (frv-*-*linux*): Likewise.
+ (h8300-*-rtems*): Likewise.
+ (h8300-*-elf*): Likewise.
+ (i[34567]86-*-darwin*): Likewise.
+ (x86_64-*-darwin*): Likewise.
+ (rx-*-elf*): Likewise.
+ (tic6x-*-elf): Likewise.
+ (tic6x-*-uclinux): Likewise.
+ (i[34567]86-*-linux*, x86_64-*-linux*): Likewise.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makefile.in (LIBGCC2_DEBUG_CFLAGS LIBGCC2_CFLAGS)
+ (LIBGCC2_INCLUDES, TARGET_LIBGCC2_CFLAGS, LIB2FUNCS_EXTRA)
+ (LIB2FUNCS_STATIC_EXTRA, LIB2FUNCS_EXCLUDE, T, T_TARGET)
+ (INCLUDES_FOR_TARGET): Remove.
+ (LIBGCC2_CFLAGS): Don't export.
+ (LIB2FUNCS_ST, LIB2_DIVMOD_FUNCS, LIB2ADD, LIB2ADD_ST, srcdirify):
+ Remove.
+ (libgcc-support): Remove $(LIB2ADD), $(LIB2ADD_ST) dependencies.
+ (libgcc.mvars): Likewise.
+ Don't emit LIB2FUNCS_ST, LIB2FUNCS_EXCLUDE, LIB2ADD, LIB2ADD_ST,
+ LIB2_SIDITI_CONV_FUNCS, LIB2_DIVMOD_FUNCS, LIBGCC2_CFLAGS,
+ TARGET_LIBGCC2_CFLAGS.
+ Emit GTHREAD_FLAGS.
+ * libgcc2.c, libgcc2.h, gbl-ctors.h, longlong.h: Move to ../libgcc.
+ * config/darwin-64.c: Move to ../libgcc/config.
+ * config/divmod.c, config/floatunsidf.c, config/floatunsisf.c,
+ config/floatunsitf.c, config/floatunsixf.c, config/udivmod.c,
+ config/udivmodsi4.c: Move to ../libgcc/config.
+ * config/gthr-posix.c: Move to ../libgcc/config/alpha.
+ * config/memcmp.c, config/memcpy.c, config/memmove.c,
+ config/memset.c: Move to ../libgcc/config.
+ * config/t-darwin (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/t-freebsd: Remove.
+ * config/t-freebsd-thread: Move to ../libgcc/config.
+ * config/t-libgcc-pic: Move to ../libgcc/config.
+ * config/t-libunwind (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/t-linux: Remove.
+ * config/t-lynx (TARGET_LIBGCC2_CFLAGS, LIBGCC, INSTALL_LIBGCC):
+ Remove
+ * config/t-openbsd-thread: Move to ../libgcc/config.
+ * config/t-rtems (LIBGCC2_INCLUDES): Remove.
+ * config/t-sol2 (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/t-svr4: Remove.
+ * config/t-vxworks (LIBGCC, INSTALL_LIBGCC, TARGET_LIBGCC2_CFLAGS)
+ (LIBGCC2_DEBUG_CFLAGS, LIB2FUNCS_EXTRA, LIBGCC2_INCLUDES): Remove.
+ * config/vxlib.c, config/vxlib-tls.c: Move to ../libgcc/config.
+ * config/alpha/qrnnd.asm: Move to ../libgcc/config/alpha/qrnnd.S.
+ * config/alpha/t-alpha, config/alpha/t-ieee: Remove.
+ * config/alpha/t-vms (LIB2FUNCS_EXTRA, LIBGCC, INSTALL_LIBGCC):
+ Remove.
+ * config/alpha/vms-gcc_shell_handler.c: Move to ../libgcc/config/alpha.
+ * config/arm/bpabi.c, config/arm/unaligned-funcs.c,
+ config/arm/fp16.c, config/arm/linux-atomic.c,
+ config/arm/linux-atomic-64bit.c: Move to ../libgcc/config/arm.
+ * config/arm/t-arm-elf (LIBGCC, INSTALL_LIBGCC)
+ (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/arm/t-bpabi, config/arm/t-linux: Remove.
+ * config/arm/t-linux-eabi (TARGET_LIBGCC2_CFLAGS)
+ (LIB2FUNCS_STATIC_EXTRA): Remove.
+ * config/arm/t-netbsd: Remove.
+ * config/arm/t-strongarm-elf (LIBGCC, INSTALL_LIBGCC)
+ (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/arm/t-symbian (LIB2FUNCS_STATIC_EXTRA): Remove.
+ * config/arm/t-wince-pe (LIBGCC, INSTALL_LIBGCC)
+ (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/avr/t-avr (LIB2FUNCS_EXCLUDE, TARGET_LIBGCC2_CFLAGS)
+ (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/bfin/t-bfin-elf (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/bfin/t-bfin-linux: Likewise.
+ * config/bfin/t-bfin-uclinux: Likewise.
+ * config/c6x/eqd.c, config/c6x/eqf.c, config/c6x/ged.c,
+ config/c6x/gef.c, config/c6x/gtd.c, config/c6x/gtf.c,
+ config/c6x/led.c, config/c6x/lef.c, config/c6x/ltd.c,
+ config/c6x/ltf.c: Move to ../libgcc/config/c6x.
+ * config/c6x/t-c6x-elf (LIB2FUNCS_EXCLUDE, LIB2FUNCS_EXTRA):
+ Remove.
+ * config/c6x/t-c6x-uclinux (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/cris/arit.c: Move to ../libgcc/config/cris.
+ * config/cris/cris_abi_symbol.c: Remove.
+ * config/cris/cris.h: Remove obsolete comment.
+ * config/cris/mulsi3.asm: Move to ../libgcc/config/cris/mulsi3.S.
+ * config/cris/t-cris (LIB2FUNCS_EXTRA, CRIS_LIB1CSRC)
+ ($(LIB2FUNCS_EXTRA)): Remove.
+ * config/cris/t-elfmulti (LIB2FUNCS_STATIC_EXTRA, INSTALL_LIBGCC)
+ (LIBGCC): Remove.
+ * config/cris/t-linux (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/fr30/t-fr30: Remove.
+ * config/frv/cmovd.c, config/frv/cmovh.c, config/frv/cmovw.c,
+ config/frv/modi.c, config/frv/uitod.c, config/frv/uitof.c,
+ config/frv/ulltod.c, config/frv/ulltof.c, config/frv/umodi.c: Move
+ to ../libgcc/config/frv.
+ * config/frv/t-frv (LIB2FUNCS_EXTRA, TARGET_LIBGCC2_CFLAGS)
+ (cmovh.c, cmovw.c, cmovd.c, modi.c, umodi.c, uitof.c, uitod.c)
+ (ulltof.c, LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/frv/t-linux (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/h8300/clzhi2.c, config/h8300/ctzhi2.c,
+ config/h8300/fixunssfsi.c, config/h8300/parityhi2.c,
+ config/h8300/popcounthi2.c: Move to ../libgcc/config/h8300.
+ * config/h8300/t-h8300 (LIB2FUNCS_EXTRA, TARGET_LIBGCC2_CFLAGS)
+ (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/i386/gthr-win32.c: Move to ../libgcc/config/i386.
+ * config/i386/t-cygming (LIBGCC2_INCLUDES): Remove.
+ * config/i386/t-cygwin: Remove.
+ * config/i386/t-darwin (LIB2_SIDITI_CONV_FUNCS, LIB2FUNCS_EXTRA)
+ (LIB2FUNCS_EXCLUDE): Remove.
+ * config/i386/t-darwin64 (LIB2_SIDITI_CONV_FUNCS, LIB2FUNCS_EXTRA)
+ (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/i386/t-gthr-win32: Move to ../libgcc/config/i386.
+ * config/i386/t-linux64 (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/i386/t-mingw-w32: Likewise.
+ * config/i386/t-mingw-w64: Likewise.
+ * config/i386/t-openbsd: Likewise.
+ * config/i386/t-nto: Remove.
+ * config/ia64/quadlib.c: Move to ../libgcc/config/ia64.
+ * config/ia64/t-hpux (LIBGCC, INSTALL_LIBGCC, LIB2FUNCS_EXTRA)
+ (quadlib.c): Remove.
+ * config/ia64/t-ia64: Remove comment.
+ * config/iq2000/lib2extra-funcs.c: Move to
+ ../libgcc/config/iq2000/lib2funcs.c.
+ * config/iq2000/t-iq2000: Remove.
+ * config/m32c/m32c-lib2.c: Move to ../libgcc/config/m32c/lib2funcs.c.
+ * config/m32c/m32c-lib2-trapv.c: Move to ../libgcc/config/m32c/trapv.c.
+ * config/m32r/t-linux (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/m32c/t-m32c (LIB2FUNCS_EXTRA): Remove.
+ * config/m32r/t-m32r (TARGET_LIBGCC2_CFLAGS, LIBGCC)
+ (INSTALL_LIBGCC): Remove.
+ * config/m68k/fpgnulib.c: Move to ../libgcc/config/m68k.
+ * config/m68k/t-floatlib: Remove.
+ * config/m68k/t-mlibs (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/mcore/t-mcore (TARGET_LIBGCC2_CFLAGS): Remove.
+ Fix typo.
+ (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/mep/mep-lib2.c: Move to ../libgcc/config/mep/lib2funcs.c.
+ * config/mep/mep-tramp.c: Move to ../libgcc/config/mep/tramp.c.
+ * config/mep/t-mep (LIB2FUNCS_EXTRA): Remove.
+ * config/mips/t-elf (TARGET_LIBGCC2_CFLAGS, LIBGCC)
+ (INSTALL_LIBGCC): Remove.
+ * config/mips/t-isa3264: Likewise.
+ * config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS): Remove.
+ * config/mips/t-r3900 (TARGET_LIBGCC2_CFLAGS, LIBGCC)
+ (INSTALL_LIBGCC): Remove.
+ * config/mips/t-sde (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/mips/t-sr71k (TARGET_LIBGCC2_CFLAGS, LIBGCC)
+ (INSTALL_LIBGCC): Remove.
+ * config/mips/t-vr (TARGET_LIBGCC2_CFLAGS)
+ (LIB2FUNCS_STATIC_EXTRA): Remove.
+ * config/mips/vr4120-div.S: Move to ../libgcc/config/mips.
+ * config/mmix/t-mmix (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/mn10300/t-mn10300 (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/pa/fptr.c, config/pa/linux-atomic.c: Move to
+ ../libgcc/config/pa.
+ * config/pa/lib2funcs.asm: Move to ../libgcc/config/pa/lib2funcs.S.
+ * config/pa/quadlib.c: Move to ../libgcc/config/pa.
+ * config/pa/t-dce-thr (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/pa/t-linux, config/pa/t-linux64: Remove.
+ * config/pa/t-pa-hpux, config/pa/t-pa-hpux10,
+ config/pa/t-pa-hpux11, config/pa/t-pa64: Remove.
+ * config/pdp11/t-pdp11 (TARGET_LIBGCC2_CFLAGS, LIB2FUNCS_EXTRA):
+ Remove.
+ * config/picochip/libgccExtras: Move to ../libgcc/config/picochip.
+ * config/picochip/t-picochip (LIB2FUNCS_EXTRA, RANLIB_FOR_TARGET)
+ (TARGET_LIBGCC2_CFLAGS, LIBGCC2_DEBUG_CFLAGS): Remove.
+ * config/rs6000/crtresfpr.asm: Move to
+ ../libgcc/config/rs6000/crtresfpr.S.
+ * config/rs6000/crtresgpr.asm: Move to
+ ../libgcc/config/rs6000/crtresgpr.S.
+ * config/rs6000/crtresxfpr.asm: Move to
+ ../libgcc/config/rs6000/crtresxfpr.S.
+ * config/rs6000/crtresxgpr.asm: Move to
+ ../libgcc/config/rs6000/crtresxgpr.S.
+ * config/rs6000/crtsavfpr.asm: Move to
+ ../libgcc/config/rs6000/crtsavfpr.S.
+ * config/rs6000/crtsavgpr.asm: Move to
+ ../libgcc/config/rs6000/crtsavgpr.S.
+ * config/rs6000/darwin-asm.h: Move to ../libgcc/config/rs6000.
+ * config/rs6000/darwin-fpsave.asm: Move to
+ ../libgcc/config/rs6000/darwin-fpsave.S.
+ * config/rs6000/darwin-gpsave.asm: Move to
+ ../libgcc/config/rs6000/darwin-gpsave.S.
+ * config/rs6000/darwin-tramp.asm: Move to
+ ../libgcc/config/rs6000/darwin-tramp.S.
+ * config/rs6000/darwin-vecsave.asm: Move to
+ ../libgcc/config/rs6000/darwin-vecsave.S.
+ * config/rs6000/darwin-world.asm: Move to
+ ../libgcc/config/rs6000/darwin-world.S.
+ * config/rs6000/e500crtres32gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtres32gpr.S.
+ * config/rs6000/e500crtres64gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtres64gpr.S.
+ * config/rs6000/e500crtres64gprctr.asm: Move to
+ ../libgcc/config/rs6000/e500crtres64gprctr.S.
+ * config/rs6000/e500crtrest32gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtrest32gpr.S.
+ * config/rs6000/e500crtrest64gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtrest64gpr.S.
+ * config/rs6000/e500crtresx32gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtresx32gpr.S.
+ * config/rs6000/e500crtresx64gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtresx64gpr.S.
+ * config/rs6000/e500crtsav32gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtsav32gpr.S.
+ * config/rs6000/e500crtsav64gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtsav64gpr.S.
+ * config/rs6000/e500crtsav64gprctr.asm: Move to
+ ../libgcc/config/rs6000/e500crtsav64gprctr.S.
+ * config/rs6000/e500crtsavg32gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtsavg32gpr.S.
+ * config/rs6000/e500crtsavg64gpr.asm: Move to
+ ../libgcc/config/rs6000/e500crtsavg64gpr.S.
+ * config/rs6000/e500crtsavg64gprctr.asm: Move to
+ ../libgcc/config/rs6000/e500crtsavg64gprctr.S.
+ * config/rs6000/eabi.asm: Move to ../libgcc/config/rs6000/eabi.S.
+ * config/rs6000/t-aix43 (LIBGCC, INSTALL_LIBGCC, LIB2FUNCS_EXTRA)
+ (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/rs6000/t-aix52: Likewise.
+ * config/rs6000/t-darwin: Remove.
+ * config/rs6000/t-darwin64 (LIB2_SIDITI_CONV_FUNCS)
+ (LIB2FUNCS_EXTRA): Remove.
+ * config/rs6000/t-fprules (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/rs6000/t-linux64 (TARGET_LIBGCC2_CFLAGS): Remove.
+ * config/rs6000/t-lynx (LIB2FUNCS_EXTRA, tramp.S, LIBGCC)
+ (INSTALL_LIBGCC): Remove.
+ * config/rs6000/t-netbsd (LIB2FUNCS_EXTRA)
+ (LIB2FUNCS_STATIC_EXTRA, tramp.S, crtsavfpr.S, crtresfpr.S)
+ (crtsavgpr.S, crtresgpr.S, crtresxfpr.S, crtresxgpr.S, LIBGCC)
+ (INSTALL_LIBGCC, $(T)crtsavfpr$(objext), $(T)crtresfpr$(objext))
+ (($(T)crtsavgpr$(objext), $(T)crtresgpr$(objext),
+ $(T)crtresxfpr$(objext), $(T)crtresxgpr$(objext)): Remove.
+ * config/rs6000/t-ppccomm (LIB2FUNCS_EXTRA)
+ (LIB2FUNCS_STATIC_EXTRA, eabi.S, tramp.S): Remove.
+ * config/rs6000/t-spe (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/rs6000/t-vxworks: Remove comment.
+ * config/rs6000/tramp.asm: Move to ../libgcc/config/rs6000/tramp.S.
+ * config/rx/t-rx (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/sh/linux-atomic.asm: Move to
+ ../libgcc/config/sh/linux-atomic.S.
+ * config/sh/t-linux (LIB2FUNCS_EXTRA): Remove.
+ * config/sh/t-netbsd: Remove.
+ * config/sh/t-sh (TARGET_LIBGCC2_CFLAGS, LIBGCC, INSTALL_LIBGCC):
+ Remove.
+ * config/sparc/t-elf (LIBGCC, INSTALL_LIBGCC): Remove.
+ * config/sparc/t-leon: Likewise.
+ * config/sparc/t-leon3: Likewise.
+ * config/sparc/t-linux64: Likewise.
+ * config/sparc/t-netbsd64: Fix typo.
+ Remove comment.
+ * config/spu/divmodti4.c, config/spu/divv2df3.c,
+ config/spu/float_disf.c, config/spu/float_unsdidf.c,
+ config/spu/float_unsdisf.c, config/spu/float_unssidf.c,
+ config/spu/mfc_multi_tag_release.c,
+ config/spu/mfc_multi_tag_reserve.c, config/spu/mfc_tag_release.c,
+ config/spu/mfc_tag_reserve.c, config/spu/mfc_tag_table.c,
+ config/spu/multi3.c: Move to ../libgcc/config/spu.
+ * config/spu/t-spu-elf (TARGET_LIBGCC2_CFLAGS, LIB2FUNCS_EXCLUDE)
+ (LIB2FUNCS_STATIC_EXTRA, LIB2_SIDITI_CONV_FUNCS, LIBGCC)
+ (INSTALL_LIBGCC): Remove.
+ * config/stormy16/stormy16-lib2.c: Move to
+ ../libgcc/config/stormy16/lib2.c.
+ * config/stormy16/stormy16-lib2-ashlsi3.c: Move to
+ ../libgcc/config/stormy16/ashlsi3.c.
+ * config/stormy16/stormy16-lib2-ashrsi3.c: Move to
+ ../libgcc/config/stormy16/ashrsi3.c.
+ * config/stormy16/stormy16-lib2-clzhi2.c: Move to
+ ../libgcc/config/stormy16/clzhi2.c.
+ * config/stormy16/stormy16-lib2-cmpsi2.c: Move to
+ ../libgcc/config/stormy16/cmpsi2.c.
+ * config/stormy16/stormy16-lib2-ctzhi2.c: Move to
+ ../libgcc/config/stormy16/ctzhi2.c.
+ * config/stormy16/stormy16-lib2-divsi3.c: Move to
+ ../libgcc/config/stormy16/divsi3.c.
+ * config/stormy16/stormy16-lib2-ffshi2.c: Move to
+ ../libgcc/config/stormy16/ffshi2.c.
+ * config/stormy16/stormy16-lib2-lshrsi3.c: Move to
+ ../libgcc/config/stormy16/lshrsi3.c.
+ * config/stormy16/stormy16-lib2-modsi3.c: Move to
+ ../libgcc/config/stormy16/modsi3.c.
+ * config/stormy16/stormy16-lib2-parityhi2.c: Move to
+ ../libgcc/config/stormy16/parityhi2.c.
+ * config/stormy16/stormy16-lib2-popcounthi2.c: Move to
+ ../libgcc/config/stormy16/popcounthi2.c.
+ * config/stormy16/stormy16-lib2-ucmpsi2.c: Move to
+ ../libgcc/config/stormy16/ucmpsi2.c.
+ * config/stormy16/stormy16-lib2-udivmodsi4.c: Move to
+ ../libgcc/config/stormy16/udivmodsi4.c.
+ * config/stormy16/stormy16-lib2-udivsi3.c: Move to
+ ../libgcc/config/stormy16/udivsi3.c.
+ * config/stormy16/stormy16-lib2-umodsi3.c: Move to
+ ../libgcc/config/stormy16/umodsi3.c.
+ * config/stormy16/t-stormy16: Move to ../libgcc/config/t-stormy16.
+ * config/v850/t-v850 (INSTALL_LIBGCC): Remove.
+ * config/xtensa/lib2funcs.S: Move to ../libgcc/config/xtensa.
+ * config/xtensa/t-elf: Remove.
+ * config/xtensa/t-xtensa (LIB2FUNCS_EXTRA): Remove.
+ * config.gcc (*-*-freebsd*): Remove t-freebsd, t-freebsd-thread
+ from tmake_file.
+ (*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu,
+ *-*-gnu*, *-*-kopensolaris*-gnu): Remove t-linux from tmake_file.
+ (*-*-netbsd*): Remove t-libgcc-pic from tmake_file.
+ (*-*-openbsd*): Likewise.
+ Remove t-openbsd-thread for posix threads.
+ (alpha*-*-linux*): Remove alpha/t-alpha, alpha/t-ieee
+ from tmake_file.
+ (alpha*-*-freebsd*): Likewise.
+ (alpha*-*-netbsd*): Likewise.
+ (alpha*-*-openbsd*): Likewise.
+ (alpha64-dec-*vms*): Likewise.
+ (alpha*-dec-*vms*): Likewise.
+ (arm*-*-netbsdelf*): Remove arm/t-netbsd from tmake_file.
+ (arm*-*-linux*): Remove t-linux from tmake_file.
+ Remove arm/t-bpabi from tmake_file for arm*-*-linux-*eabi.
+ (arm*-*-uclinux*): Remove arm/t-bpabi from tmake_file for
+ arm*-*-uclinux*eabi.
+ (arm*-*-eabi*, arm*-*-symbianelf* ): Remove arm/t-bpabi from
+ tmake_file for arm*-*-eabi*.
+ (fr30-*-elf): Remove tmake_file.
+ (hppa*64*-*-linux*): Remove tmake_file.
+ (hppa*-*-linux*): Likewise.
+ (hppa[12]*-*-hpux10*): Remove pa/t-pa-hpux10, pa/t-pa-hpux from
+ tmake_file.
+ (hppa*64*-*-hpux11*): Remove pa/t-pa64, pa/t-pa-hpux from tmake_file.
+ (hppa[12]*-*-hpux11*): Remove pa/t-pa-hpux11, pa/t-pa-hpux from
+ tmake_file.
+ (i[34567]86-*-elf*): Remove tmake_file.
+ (x86_64-*-elf*): Likewise.
+ (i[34567]86-*-nto-qnx*): Likewise.
+ (i[34567]86-*-cygwin*): Remove i386/t-cygwin from tmake_file.
+ (i[34567]86-*-mingw*, x86_64-*-mingw*): Remove i386/t-gthr-win32
+ from tmake_file if using win32 threads.
+ (iq2000*-*-elf*): Remove tmake-file.
+ (microblaze*-linux*): Likewise.
+ (sh-*-elf*, sh[12346l]*-*-elf*, sh-*-linux*)
+ (sh[2346lbe]*-*-linux*, sh-*-netbsdelf*, shl*-*-netbsdelf*)
+ (sh5-*-netbsd*, sh5l*-*-netbsd*, sh64-*-netbsd*)
+ (sh64l*-*-netbsd*): Remove sh/t-netbsd from tmake_file for
+ sh5*-*-netbsd*, sh64*-netbsd*, *-*-netbsd.
+ (xtensa*-*-elf*): Remove tmake_file.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makefile.in (LIB1ASMSRC): Don't export.
+ (libgcc.mvars): Don't emit LIB1ASMFUNCS, LIB1ASMSRC.
+ * config/arm/arm.c: Update lib1funcs.asm filename.
+ * config/arm/linux-eabi.h: Likewise.
+ * config/arm/bpabi-v6m.S, config/arm/bpabi.S,
+ config/arm/ieee754-df.S, config/arm/ieee754-sf.S: Move to
+ ../libgcc/config/arm.
+ * config/arm/lib1funcs.asm: Move to ../libgcc/config/arm/lib1funcs.S.
+ * config/arm/t-arm (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/arm/t-arm-elf (LIB1ASMFUNCS): Remove.
+ * config/arm/t-bpabi: Likewise.
+ * config/arm/t-linux (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/arm/t-linux-eabi (LIB1ASMFUNCS): Remove.
+ * config/arm/t-strongarm-elf: Likewise.
+ * config/arm/t-symbian: Likewise.
+ * config/arm/t-vxworks: Likewise.
+ * config/arm/t-wince-pe: Likewise.
+ * config/avr/libgcc.S: Move to ../libgcc/config/avr.
+ * config/avr/t-avr (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/bfin/lib1funcs.asm: Move to
+ ../libgcc/config/bfin/lib1funcs.S.
+ * config/bfin/t-bfin: Remove.
+ * config/bfin/t-bfin-elf (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/bfin/t-bfin-linux: Likewise.
+ * config/bfin/t-bfin-uclinux: Likewise.
+ * config/c6x/lib1funcs.asm: Move to
+ ../libgcc/config/c6x/lib1funcs.S.
+ * config/c6x/t-c6x-elf (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/fr30/lib1funcs.asm: Move to
+ ../libgcc/config/fr30/lib1funcs.S.
+ * config/fr30/t-fr30 (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/frv/lib1funcs.asm: Move to
+ ../libgcc/config/frv/lib1funcs.S.
+ * config/frv/t-frv (CROSS_LIBGCC1, LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/h8300/fixunssfsi.c: Update lib1funcs.asm filename.
+ * config/h8300/lib1funcs.asm: Move to
+ ../libgcc/config/h8300/lib1funcs.S.
+ * config/h8300/t-h8300 (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/i386/cygwin.asm: Move to ../libgcc/config/i386/cygwin.S.
+ * config/i386/t-cygming (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/i386/t-interix: Likewise.
+ * config/ia64/lib1funcs.asm: Move to
+ ../libgcc/config/ia64/lib1funcs.S.
+ * config/ia64/t-hpux (LIB1ASMFUNCS, LIBGCC1_TEST): Remove.
+ * config/ia64/t-ia64 (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/iq2000/t-iq2000 (LIBGCC1, CROSS_LIBGCC1): Remove.
+ * config/m32c/m32c.c: Update m32c-lib1.S filename.
+ * config/m32c/m32c-lib1.S: Move to ../libgcc/config/m32c/lib1funcs.S.
+ * config/m32c/t-m32c (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/m32r/t-linux (CROSS_LIBGCC1, LIBGCC1, LIBGCC1_TEST): Remove.
+ * config/m68k/lb1sf68.asm: Move to ../libgcc/config/m68k/lb1sf68.S.
+ * config/m68k/t-floatlib (LIB1ASMSRC, LIB1ASMFUNCS): New file.
+ * config/mcore/lib1.asm: Move to ../libgcc/config/mcore/lib1funcs.S.
+ * config/mcore/t-mcore (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/mep/mep-lib1.asm: Move to ../libgcc/config/mep/lib1funcs.S.
+ * config/mep/t-mep (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/mips/mips16.S: Move to ../libgcc/config/mips.
+ * config/mips/t-libgcc-mips16: Remove.
+ * config/mips/t-sr71k (LIBGCC1, CROSS_LIBGCC1): Remove.
+ * config/pa/milli64.S: Move to ../libgcc/config/pa.
+ * config/pa/t-linux (LIB1ASMFUNCS, LIB1ASMSRC): Remove.
+ * config/pa/t-linux64: Likewise.
+ * config/picochip/libgccExtras/fake_libgcc.asm: Move to
+ ../libgcc/config/picochip/lib1funcs.S.
+ * config/picochip/t-picochip (LIB1ASMFUNCS, LIB1ASMSRC): Remove.
+ * config/sh/lib1funcs.asm: Move to ../libgcc/config/sh/lib1funcs.S.
+ * config/sh/lib1funcs.h: Move to ../libgcc/config/sh.
+ * config/sh/sh.h: Update lib1funcs.asm filename.
+ * config/sh/t-linux (LIB1ASMFUNCS_CACHE): Remove.
+ * config/sh/t-netbsd: Likewise.
+ * config/sh/t-sh (LIB1ASMSRC, LIB1ASMFUNCS, LIB1ASMFUNCS_CACHE):
+ Remove.
+ * config/sh/t-sh64 (LIB1ASMFUNCS): Remove.
+ * config/sparc/lb1spc.asm: Move to ../libgcc/config/sparc/lb1spc.S.
+ * config/sparc/lb1spl.asm: Remove.
+ * config/sparc/t-elf (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config/sparc/t-leon: Likewise.
+ * config/spu/t-spu-elf (LIBGCC1, CROSS_LIBGCC1): Remove.
+ * config/v850/lib1funcs.asm: Move to ../libgcc/config/v850/lib1funcs.S.
+ * config/v850/t-v850 (LIB1ASMSRC, LIB1ASMFUNCS): Remove
+ * config/vax/lib1funcs.asm: Move to ../libgcc/config/vax/lib1funcs.S.
+ * config/vax/t-linux: Remove.
+ * config/xtensa/ieee754-df.S, config/xtensa/ieee754-sf.S: Move to
+ ../libgcc/config/xtensa.
+ * config/xtensa/lib1funcs.asm: Move to
+ ../libgcc/config/xtensa/lib1funcs.S.
+ * config/xtensa/t-xtensa (LIB1ASMSRC, LIB1ASMFUNCS): Remove.
+ * config.gcc (bfin*-rtems*): Remove bfin/t-bfin from tmake_file.
+ (bfin*-*): Likewise.
+ (mips64*-*-linux*, mipsisa64*-*-linux*): Remove
+ mips/t-libgcc-mips16 from tmake_file.
+ (mips*-*-linux*): Likewise.
+ (mips*-sde-elf*): Likewise.
+ (mipsisa32-*-elf*, mipsisa32el-*-elf*, mipsisa32r2-*-elf*)
+ (mipsisa32r2el-*-elf*, mipsisa64-*-elf*, mipsisa64el-*-elf*)
+ (mipsisa64r2-*-elf*, mipsisa64r2el-*-elf*): Likewise.
+ (mipsisa64sb1-*-elf*, mipsisa64sb1el-*-elf*): Likewise.
+ (mips-*-elf*, mipsel-*-elf*): Likewise.
+ (mips64-*-elf*, mips64el-*-elf*): Likewise.
+ (mips64orion-*-elf*, mips64orionel-*-elf*): Likewise.
+ (mips*-*-rtems*): Likewise.
+ (mipstx39-*-elf*, mipstx39el-*-elf*): Likewise.
+ (vax-*-linux*): Remove vax/t-linux from tmake_file.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * config.gcc (extra_parts): Remove.
+ (*-*-freebsd*): Remove extra_parts.
+ (*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu,
+ *-*-gnu*, *-*-kopensolaris*-gnu): Likewise.
+ (*-*-netbsd*): Remove t-libc-ok, t-netbsd from tmake_file.
+ Remove extra_parts for *-*-netbsd*1.[7-9]*, *-*-netbsd[2-9]*,
+ *-*-netbsdelf[2-9]*.
+ (*-*-openbsd*): Remove t-libc-ok from tmake_file.
+ (alpha*-*-linux*): Remove extra_parts.
+ (alpha*-*-freebsd*): Likewise.
+ (bfin*-linux-uclibc*): Likewise.
+ (fr30-*-elf): Likewise.
+ (moxie-*-elf): Likewise.
+ (moxie-*-uclinux*): Likewise.
+ (h8300-*-rtems*): Remove h8300/t-elf from tmake_file.
+ (h8300-*-elf*): Likewise.
+ (hppa*64*-*-hpux11*): Remove extra_parts.
+ (i[34567]86-*-elf*): Remove i386/t-i386elf, i386/t-crtstuff from
+ tmake_file.
+ (x86_64-*-elf*): Likewise.
+ (i[34567]86-*-freebsd*): Remove tmake_file.
+ (x86_64-*-freebsd*): Likewise.
+ (x86_64-*-netbsd*): Likewise.
+ (i[34567]86-*-openbsd2.*, i[34567]86-*openbsd3.[0123]): Remove
+ t-libc-ok from tmake_file.
+ (i[34567]86-*-linux*, i[34567]86-*-kfreebsd*-gnu,
+ i[34567]86-*-knetbsd*-gnu, i[34567]86-*-gnu*,
+ i[34567]86-*-kopensolaris*-gnu): Remove i386/t-crtstuff from tmake_file.
+ Remove extra_parts.
+ (x86_64-*-linux*, x86_64-*-kfreebsd*-gnu, x86_64-*-knetbsd*-gnu):
+ Remove i386/t-crtstuff from tmake_file.
+ (i[34567]86-*-lynxos*): Likewise.
+ Remove extra_parts.
+ (ia64*-*-elf*): Remove extra_parts.
+ (ia64*-*-freebsd*): Likewise.
+ (ia64*-*-linux*): Likewise.
+ (ia64-hp-*vms*): Remove ia64/t-vms from tmake_file.
+ (m32r-*-elf*): Remove extra_parts.
+ (m32rle-*-elf*): Likewise.
+ (m32r-*-rtems*): Likewise.
+ (m68k-*-elf*, fido-*-elf*): Likewise.
+ (m68k*-*-openbsd*): Remove t-libc-ok from tmake_file.
+ (m68k-*-rtems*): Remove extra_parts.
+ (mep-*-*): Likewise.
+ (microblaze*-linux*): Likewise.
+ (mips64*-*-linux*, mipsisa64*-*-linux*): Likewise.
+ (mips*-*-linux*): Likewise.
+ (powerpc-*-lynxos*): Likewise.
+ (s390x-ibm-tpf*): Likewise.
+ (score-*-elf): Likewise.
+ Remove tmake_file.
+ (sh-*-elf*, sh[12346l]*-*-elf*, sh-*-linux*, sh[2346lbe]*-*-linux*,
+ sh-*-netbsdelf*, shl*-*-netbsdelf*, sh5-*-netbsd*, sh5l*-*-netbsd*,
+ sh64-*-netbsd*, sh64l*-*-netbsd*): Remove sh/t-elf from tmake_file.
+ Remove sh/t-superh from tmake_file for sh*-superh-elf.
+ Remove sh/t-linux64 from tmake_file for sh64*-*-linux*.
+ (sh-*-rtems*): Remove sh/t-elf from tmake_file.
+ (sh-wrs-vxworks): Likewise.
+ (sparc-*-linux*): Remove extra_parts.
+ (sparc64-*-linux*): Likewise.
+ (sparc64-*-freebsd*, ultrasparc-*-freebsd*): Likewise.
+ (xstormy16-*-elf): Likewise.
+ (xtensa*-*-linux*): Remove xtensa/t-linux from tmake_file.
+ (am33_2.0-*-linux*): Remove extra_parts.
+ * configure.ac (extra_parts): Don't substitute.
+ * configure: Regenerate.
+ * crtstuff.c: Move to ../libgcc.
+ * Makefile.in (CRTSTUFF_CFLAGS): Remove.
+ (EXTRA_PARTS): Remove.
+ (CRTSTUFF_T_CFLAGS): Remove.
+ (MOSTLYCLEANFILES): Remove $(EXTRA_PARTS).
+ (GCC_EXTRA_PARTS): Remove.
+ (libgcc.mvars): Remove GCC_EXTRA_PARTS, CRTSTUFF_CFLAGS,
+ CRTSTUFF_T_CFLAGS, CRTSTUFF_T_CFLAGS_S.
+ Emit GCC_CFLAGS, INHIBIT_LIBC_CFLAGS.
+ ($(T)crtbegin.o, $(T)crtend.o, $(T)crtbeginS.o, $(T)crtendS.o)
+ ($(T)crtbeginT.o): Remove.
+ * config/alpha/t-vms (EXTRA_PARTS): Remove.
+ ($(T)vms-dwarf2.o, $(T)vms-dwarf2eh.o): Remove.
+ * config/alpha/vms-dwarf2.asm: Move to
+ ../libgcc/config/alpha/vms-dwarf2.S.
+ * config/alpha/vms-dwarf2eh.asm: Move to
+ ../libgcc/config/alpha/vms-dwarf2eh.S.
+ * config/arm/crti.asm: Move to ../libgcc/config/arm/crti.S.
+ * config/arm/crtn.asm: Move to ../libgcc/config/arm/crtn.S.
+ * config/arm/t-arm-elf (EXTRA_MULTILIB_PARTS): Remove.
+ ($(T)crti.o, $(T)crtn.o): Remove.
+ * config/arm/t-linux: Remove comment.
+ * config/arm/t-linux-eabi (EXTRA_MULTILIB_PARTS): Remove.
+ * config/arm/t-strongarm-elf (EXTRA_MULTILIB_PARTS): Remove.
+ ($(T)crti.o, $(T)crtn.o): Remove.
+ * config/arm/t-symbian (EXTRA_MULTILIB_PARTS): Remove.
+ * config/bfin/crti.s: Move to ../libgcc/config/bfin/crti.S.
+ * config/bfin/crtn.s: Move to ../libgcc/config/bfin/crtn.S.
+ * config/bfin/crtlibid.s: Move to ../libgcc/config/bfin/crtlibid.S.
+ * config/bfin/t-bfin (EXTRA_PARTS): Remove.
+ ($(T)crti.o, $(T)crtn.o): Remove.
+ * config/bfin/t-bfin-elf (CRTSTUFF_T_CFLAGS): Remove.
+ ($(T)crti.o, $(T)crtn.o, $(T)crtlibid.o): Remove
+ (EXTRA_MULTILIB_PARTS): Remove.
+ * config/bfin/t-bfin-linux (CRTSTUFF_T_CFLAGS,
+ EXTRA_MULTILIB_PARTS): Remove.
+ * config/bfin/t-bfin-uclinux (CRTSTUFF_T_CFLAGS): Remove.
+ ($(T)crtlibid.o): Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ * config/c6x/crti.s: Move to ../libgcc/config/c6x/crti.S.
+ * config/c6x/crtn.s: Move to ../libgcc/config/c6x/crtn.S.
+ * config/c6x/t-c6x-elf ($(T)crti.o, $(T)crtn.o): Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ (CRTSTUFF_T_CFLAGS, CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/c6x/t-c6x-uclinux (CRTSTUFF_T_CFLAGS,
+ CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/cris/t-elfmulti (CRTSTUFF_T_CFLAGS): Remove.
+ * config/cris/t-linux (CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/fr30/crti.asm: Move to ../libgcc/config/fr30/crti.S.
+ * config/fr30/crtn.asm: Move to ../libgcc/config/fr30/crtn.S.
+ * config/fr30/t-fr30 ($(T)crti.o, $(T)crtn.o): Remove.
+ * config/frv/frvbegin.c, config/frv/frvend.c: Move to
+ ../libgcc/config/frv.
+ * config/frv/t-frv (EXTRA_MULTILIB_PARTS): Remove.
+ (FRVSTUFF_CFLAGS, $(T)frvbegin$(objext), $(T)frvend$(objext)): Remove.
+ * config/frv/t-linux (EXTRA_MULTILIB_PARTS): Remove.
+ (CRTSTUFF_T_CFLAGS): Remove.
+ * config/h8300/crti.asm: Move to ../libgcc/config/h8300/crti.S.
+ * config/h8300/crtn.asm: Move to ../libgcc/config/h8300/crtn.S.
+ * config/h8300/t-elf: Remove.
+ * config/i386/cygming-crtbegin.c, config/i386/cygming-crtend.c:
+ Move to ../libgcc/config/i386.
+ * config/i386/t-crtstuff: Remove.
+ * config/i386/t-i386elf: Remove.
+ * config/i386/t-linux64 (EXTRA_MULTILIB_PARTS): Remove.
+ * config/i386/t-nto (CRTSTUFF_T_CFLAGS, EXTRA_PARTS): Remove.
+ * config/ia64/crtbegin.asm: Move to
+ ../libgcc/config/ia64/crtbegin.S.
+ * config/ia64/crtend.asm: Move to
+ ../libgcc/config/ia64/crtend.S.
+ * config/ia64/crti.asm: Move to ../libgcc/config/ia64/crti.S.
+ * config/ia64/crtn.asm: Move to ../libgcc/config/ia64/crtn.S.
+ * config/ia64/t-vms: Remove.
+ * config/ia64/vms-crtinit.asm: Move to
+ ../libgcc/config/ia64/vms-crtinit.S.
+ * config/m32c/t-m32c (EXTRA_MULTILIB_PARTS): Remove.
+ * config/m32r/initfini.c: Move to ../libgcc/config/m32r.
+ * config/m32r/t-linux (CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/m32r/t-m32r (CRTSTUFF_T_CFLAGS): Remove.
+ ($(T)crtinit.o, $(T)crtfini.o): Remove.
+ (m32rx, m32r2): Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ * config/m68k/crti.s: Move to ../libgcc/config/m68k/crti.S.
+ * config/m68k/crtn.s: Move to ../libgcc/config/m68k/crtn.S.
+ * config/m68k/t-crtstuff: Remove.
+ * config/m68k/t-linux (EXTRA_MULTILIB_PARTS): Remove.
+ * config/m68k/t-m68kelf: Remove.
+ * config/m68k/t-uclinux (EXTRA_MULTILIB_PARTS): Remove.
+ * config/mcore/crti.asm: Move to ../libgcc/config/mcore/crti.S.
+ * config/mcore/crtn.asm: Move to ../libgcc/config/mcore/crtn.S.
+ * config/mcore/t-mcore ($(T)crti.o, $(T)crtn.o): Remove.
+ (EXTRA_PARTS, EXTRA_MULTILIB_PARTS): Remove.
+ * config/mep/t-mep (CRTSTUFF_CFLAGS): Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ * config/microblaze/crti.s: Move to ../libgcc/config/microblaze/crti.S.
+ * config/microblaze/crtn.s: Move to ../libgcc/config/microblaze/crtn.S.
+ * config/microblaze/t-microblaze (EXTRA_MULTILIB_PARTS,
+ EXTRA_PARTS): Remove.
+ ($(T)crti$(objext), $(T)crtn$(objext)): Remove.
+ * config/mips/crti.asm: Move to ../libgcc/config/mips/crti.S.
+ * config/mips/crtn.asm: Move to ../libgcc/config/mips/crtn.S.
+ * config/mips/t-elf (CRTSTUFF_T_CFLAGS): Remove.
+ ($(T)crti.o, $(T)crtn.o): Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ * config/mips/t-isa3264: Likewise.
+ * config/mips/t-linux64 (EXTRA_MULTILIB_PARTS): Remove.
+ * config/mips/t-r3900 (EXTRA_MULTILIB_PARTS): Remove.
+ (CRTSTUFF_T_CFLAGS): Remove.
+ * config/mips/t-sde (CRTSTUFF_T_CFLAGS): Remove.
+ ($(T)crti.o, $(T)crtn.o): Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ * config/mips/t-sr71k (EXTRA_MULTILIB_PARTS, CRTSTUFF_T_CFLAGS):
+ Remove.
+ ($(T)crti.o, $(T)crtn.o): Remove.
+ * config/mips/t-st (EXTRA_MULTILIB_PARTS): Remove.
+ * config/mips/t-vr (CRTSTUFF_T_CFLAGS): Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ ($(T)crti.o, $(T)crtn.o): Remove.
+ * config/mmix/crti.asm: Move to ../libgcc/config/crti.S.
+ * config/mmix/crtn.asm: Move to ../libgcc/config/crtn.S.
+ * config/mmix/t-mmix (CRTSTUFF_T_CFLAGS): Remove.
+ * config/moxie/crti.asm, config/moxie/crtn.asm: Remove.
+ * config/pa/stublib.c: Move to libgcc/config/pa.
+ * config/pa/t-linux (CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/pa/t-linux64 (CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/pa/t-pa-hpux11 (LIBGCCSTUB_OBJS, stublib.c): Remove.
+ (pthread_default_stacksize_np-stub.o, pthread_mutex_lock-stub.o)
+ (pthread_mutex_unlock-stub.o, pthread_once-stub.o)
+ ($(T)libgcc_stub.a): Remove.
+ * config/pa/t-pa64 (LIBGCCSTUB_OBJS, stublib.c): Remove.
+ (rfi-stub.o, dfi-stub.o, cxaf-stub.o, jvrc-stub.o)
+ (pthread_default_stacksize_np-stub.o, pthread_mutex_lock-stub.o)
+ (pthread_mutex_unlock-stub.o, pthread_once-stub.o)
+ ($(T)libgcc_stub.a): Remove.
+ * config/rs6000/eabi-cn.asm: Move to
+ ../../../libgcc/config/rs6000/eabi-cn.S.
+ * config/rs6000/eabi-ci.asm: Move to
+ ../../../libgcc/config/rs6000/eabi-ci.S.
+ * config/rs6000/sol-ci.asm: Move to
+ ../../../libgcc/config/rs6000/sol-ci.S.
+ * config/rs6000/sol-cn.asm: Move to
+ ../../../libgcc/config/rs6000/sol-cn.S.
+ * config/rs6000/t-lynx (EXTRA_MULTILIB_PARTS): Remove.
+ (CRTSTUFF_T_CFLAGS, CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/rs6000/t-netbsd (CRTSTUFF_T_CFLAGS, CRTSTUFF_T_CFLAGS_S):
+ Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ * config/rs6000/t-ppccomm (EXTRA_MULTILIB_PARTS): Remove.
+ (ecrti.S, ecrtn.S, ncrti.S, ncrtn.S): Remove.
+ ($(T)ecrti$(objext), $(T)ecrtn$(objext), $(T)ncrti$(objext),
+ $(T)ncrtn$(objext)): Remove.
+ (CRTSTUFF_T_CFLAGS, CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/rs6000/t-vxworks (EXTRA_MULTILIB_PARTS): Remove.
+ * config/rx/t-rx (EXTRA_MULTILIB_PARTS): Remove.
+ * config/score/crti.asm: Move to ../libgcc/config/score/crti.S.
+ * config/score/crtn.asm: Move to ../libgcc/config/score/crtn.S.
+ * config/score/t-score-elf: Remove.
+ * config/sh/crt1.asm: Move to ../libgcc/config/sh/crt1.S.
+ * config/sh/crti.asm: Move to ../libgcc/config/sh/crti.S.
+ * config/sh/crtn.asm: Move to ../libgcc/config/sh/crtn.S.
+ * config/sh/lib1funcs-4-300.asm: Move to
+ ../../../libgcc/config/sh/lib1funcs-4-300.S.
+ * config/sh/lib1funcs-Os-4-200.asm: Move to
+ ../libgcc/config/sh/lib1funcs-Os-4-200.S.
+ * config/sh/t-elf: Remove.
+ * config/sh/t-linux (EXTRA_MULTILIB_PARTS): Remove.
+ * config/sh/t-linux64: Remove.
+ * config/sh/t-netbsd (EXTRA_MULTILIB_PARTS): Remove.
+ * config/sh/t-sh ($(T)crt1.o, $(T)crti.o, $(T)crtn.o): Remove.
+ (IC_EXTRA_PARTS, OPT_EXTRA_PARTS, EXTRA_MULTILIB_PARTS): Remove.
+ ($(T)ic_invalidate_array_4-100.o)
+ ($(T)libic_invalidate_array_4-100.a)
+ ($(T)ic_invalidate_array_4-200.o)
+ ($(T)libic_invalidate_array_4-200.a, $(T)ic_invalidate_array_4a.o)
+ ($(T)libic_invalidate_array_4a.a, $(T)sdivsi3_i4i-Os-4-200.o)
+ ($(T)udivsi3_i4i-Os-4-200.o, $(T)unwind-dw2-Os-4-200.o)
+ ($(T)libgcc-Os-4-200.a, $(T)div_table-4-300.o)
+ ($(T)libgcc-4-300.a): Remove.
+ * config/sh/t-superh: Remove.
+ * config/sh/t-vxworks (EXTRA_MULTILIB_PARTS): Remove.
+ * config/sparc/t-linux64 (CRTSTUFF_T_CFLAGS): Remove.
+ * config/spu/cache.S: Move to ../libgcc/config/spu.
+ * config/spu/cachemgr.c: Move to ../libgcc/config/spu.
+ * config/spu/t-spu-elf (CRTSTUFF_T_CFLAGS): Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ ($(T)cachemgr.o, $(T)cachemgr_nonatomic.o, $(T)libgcc_%.a): Remove.
+ ($(T)cache8k.o, $(T)cache16k.o, $(T)cache32k.o, $(T)cache32k.o)
+ ($(T)cache64k.o, $(T)cache128k.o): Remove.
+ * config/t-freebsd (CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/t-libc-ok: Remove.
+ * config/t-linux (CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/t-lynx (CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/t-netbsd: Remove.
+ * config/t-svr4 (CRTSTUFF_T_CFLAGS_S): Remove.
+ * config/t-vxworks (EXTRA_MULTILIB_PARTS): Remove.
+ * config/vms/t-vms (VMS_EXTRA_PARTS): Remove.
+ ($(T)vcrt0.o, $(T)pcrt0.o): Remove.
+ * config/vms/vms-ucrt0.c: Move to ../libgcc/config/vms.
+ * config/xtensa/crti.asm: Move to ../libgcc/config/xtensa/crti.S.
+ * config/xtensa/crtn.asm: Move to ../libgcc/config/xtensa/crtn.S.
+ * config/xtensa/t-elf (CRTSTUFF_T_CFLAGS, CRTSTUFF_T_CFLAGS_S):
+ Remove.
+ (EXTRA_MULTILIB_PARTS): Remove.
+ * config/xtensa/t-linux: Remove.
+ * config/xtensa/t-xtensa ($(T)crti.o, $(T)crtn.o): Remove.
+
+2011-11-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (bdesc_args) [IX86_BUILTIN_CVTTPD2DQ256]: Use
+ CODE_FOR_fix_truncv4dfv4si2, not CODE_FOR_fix_truncv4sfv4si2.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR translation/45116
+ * Makefile.in (slibdir): Remove, don't export.
+ (SHLIB_NM_FLAGS): Remove.
+ (libgcc.mvars): Don't emit SHLIB_LINK, SHLIB_INSTALL,
+ SHLIB_DLLDIR, SHLIB_EXT, SHLIB_MKMAP, SHLIB_MKMAP_OPTS,
+ SHLIB_MAPFILES, SHLIB_NM_FLAGS.
+ (DRIVER_DEFINES): Test SHLIB instead of SHLIB_LINK.
+ (gcc.o): Pass SHLIB instead of SHLIB_LINK.
+ (gccspec.o): Likewise.
+ (installdirs): Don't create $(DESTDIR)$(slibdir).
+ * configure.ac (slibdir): Remove.
+ * configure: Regenerate.
+ * libgcc-libsystem.ver: Move to ../libgcc/config.
+ * mkmap-flat.awk, mkmap-symver.awk: Move to ../libgcc.
+ * config/libgcc-glibc.ver: Move to ../libgcc/config.
+ * config/t-libunwind (SHLIB_LC): Remove.
+ * config/t-linux (SHLIB_MAPFILES): Remove.
+ * config/t-slibgcc-dummy: Rename to config/t-slibgcc.
+ * config/t-slibgcc-elf-ver: Remove.
+ * config/t-slibgcc-libgcc, config/t-slibgcc-nolc-override: Move to
+ ../libgcc/config.
+ * config/alpha/libgcc-alpha-ldbl.ver, config/alpha/t-linux: Move
+ to ../libgcc/config/alpha.
+ * config/alpha/t-vms (shlib_version, SHLIB_EXT, SHLIB_OBJS,
+ SHLIB_NAME, SHLIB_MULTILIB, SHLIB_INSTALL, SHLIB_SYMVEC,
+ SHLIB_SYMVECX2, SHLIB_LINK): Remove.
+ * config/arm/libgcc-bpabi.ver: Move to ../libgcc/config/arm.
+ * config/arm/t-bpabi (SHLIB_MAPFILES): Remove.
+ * config/arm/t-netbsd (SHLIB_EXT, SHLIB_NAME, SHLIB_SONAME,
+ SHLIB_OBJS, SHLIB_LINK, SHLIB_INSTALL): Remove.
+ * config/arm/t-symbian (SHLIB_LC): Remove.
+ * config/bfin/libgcc-bfin.ver: Move to
+ ../libgcc/config/bfin/libgcc-glibc.ver.
+ * config/bfin/t-bfin-linux (SHLIB_MAPFILES): Remove.
+ * config/c6x/libgcc-c6xeabi.ver: Move to
+ ../libgcc/config/c6x/libgcc-eabi.ver.
+ * config/c6x/t-c6x-elf (SHLIB_MAPFILES): Remove.
+ * config/cris/libgcc.ver: Move to
+ ../libgcc/config/cris/libgcc-glibc.ver.
+ * config/cris/t-linux (SHLIB_MAPFILES): Remove.
+ * config/frv/libgcc-frv.ver: Move to ../libgcc/config/frv.
+ * config/frv/t-linux (SHLIB_MAPFILES): Remove.
+ * config/i386/darwin-libgcc.10.4.ver: Move to
+ ../libgcc/config/i386/libgcc-darwin.10.4.ver.
+ * config/i386/darwin-libgcc.10.5.ver: Move to
+ ../libgcc/config/i386/libgcc-darwin.10.5.ver.
+ * config/i386/libgcc-glibc.ver: Move to ../libgcc/config/i386.
+ * config/i386/t-cygming (SHLIB_EXT, SHLIB_IMPLIB, SHLIB_SOVERSION,
+ SHLIB_SONAME, SHLIB_MAP, SHLIB_OBJS, SHLIB_DIR, SHLIB_SLIBDIR_QUAL)
+ SHLIB_PTHREAD_CFLAG, SHLIB_PTHREAD_LDFLAG, SHLIB_LINK,
+ SHLIB_INSTALL, SHLIB_MKMAP, SHLIB_MKMAP_OPTS, SHLIB_MAPFILES): Remove.
+ * config/i386/t-cygwin (SHLIB_LC, SHLIB_EH_EXTENSION,
+ SHLIB_IMPLIB, SHLIB_SONAME, SHLIB_MKMAP_OPTS): Remove.
+ * config/i386/t-dlldir, config/i386/t-dlldir-x: Move to
+ ../libgcc/config/i386.
+ * config/i386/t-dw2-eh, config/i386/t-sjlj-eh: Move to
+ ../libgcc/config/i386.
+ * config/i386/t-linux: Move to ../libgcc/config/i386.
+ * config/i386/t-mingw-pthread: Move to ../libgcc/config/i386.
+ * config/i386/t-mingw-w32 (SHLIB_LC): Remove.
+ * config/i386/t-mingw-w64: Likewise.
+ * config/i386/t-mingw32: Remove.
+ * config/ia64/libgcc-glibc.ver, config/ia64/libgcc-ia64.ver: Move
+ to ../libgcc/config/ia64.
+ * config/ia64/t-glibc: Remove.
+ * config/ia64/t-hpux (SHLIB_EXT, SHLIB_LINK, SHLIB_INSTALL): Remove.
+ * config/ia64/t-ia64 (SHLIB_MAPFILES): Remove.
+ * config/ia64/t-vms (shlib_version, SHLIB_EXT, SHLIB_OBJS,
+ SHLIB_NAME, SHLIB_MULTILIB, SHLIB_INSTALL, SHLIB_LINK): Remove.
+ * config/ia64/vms_symvec_libgcc_s.opt: Remove.
+ * config/m32r/libgcc-glibc.ver: Move to ../libgcc/config/m32r.
+ * config/m32r/t-linux (SHLIB_MAPFILES): Remove.
+ * config/m68k/t-slibgcc-elf-ver: Move to ../libgcc/config/m68k.
+ * config/mips/t-libgcc-mips16 (SHLIB_MAPFILES): Remove.
+ * config/pa/t-hpux-shlib: Move to ../libgcc/config/pa/t-slibgcc-hpux.
+ * config/pa/t-slibgcc-dwarf-ver, config/pa/t-slibgcc-sjsj-ver:
+ Move to ../libgcc/config/pa.
+ * config/rs6000/darwin-libgcc.10.4.ver: Move to
+ ../libgcc/config/rs6000/libgcc-darwin.10.4.ver.
+ * config/rs6000/darwin-libgcc.10.5.ver: Move to
+ ../libgcc/config/rs6000/libgcc-darwin.10.5.ver.
+ * config/rs6000/t-aix43 (SHLIB_EXT, SHLIB_LINK, SHLIB_INSTALL,
+ SHLIB_LIBS, SHLIB_MKMAP, SHLIB_NM_FLAGS, AR_FLAGS_FOR_TARGET): Remove.
+ * config/rs6000/t-aix52: Likewise.
+ * config/sh/libgcc-excl.ver, config/sh/libgcc-glibc.ver: Move to
+ ../libgcc/config/sh.
+ * config/sparc/libgcc-sparc-glibc.ver: Move to
+ ../libgcc/config/sparc/libgcc-glibc.ver.
+ * config/sparc/t-linux: Move to ../libgcc/config/sparc.
+ * config/xtensa/t-linux (SHLIB_MAPFILES): Remove.
+ * config/xtensa/libgcc-xtensa.ver: Move to
+ ../libgcc/config/xtensa/libgcc-glibc.ver.
+ * config.gcc (*-*-freebsd*): Replace t-slibgcc-elf-ver with
+ t-slibgcc in tmake_file.
+ Remove t-slibgcc-nolc-override for *-*-freebsd[34],
+ *-*-freebsd[34].* with pthreads.
+ (*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu,
+ *-*-knetbsd*-gnu, *-*-gnu*, *-*-kopensolaris*-gnu): Replace
+ t-slibgcc-elf-ver with t-slibgcc in tmake_file.
+ (*-*-netbsd*): Likewise.
+ (*-*-solaris2*): Replace t-slibgcc-dummy with t-slibgcc in tmake_file.
+ (*-*-*vms*): Add t-slibgcc to tmake_file.
+ (alpha*-*-linux*): Remove alpha/t-linux from tmake_file.
+ (alpha*-dec-osf5.1*): Replace t-slibgcc-dummy with t-slibgcc in
+ tmake_file.
+ (arm*-*-linux*): Remove t-slibgcc-libgcc from tmake_file for
+ arm*-*-linux-*eabi.
+ (bfin*-linux-uclibc*): Replace t-slibgcc-dummy with t-slibgcc in
+ tmake_file.
+ (crisv32-*-linux*, cris-*-linux*): Likewise.
+ (hppa*-*-linux*): Remove t-slibgcc-libgcc, pa/t-slibgcc-sjlj-ver,
+ pa/t-slibgcc-dwarf-ver from tmake_file.
+ (hppa[12]*-*-hpux10*): Replace pa/t-hpux-shlib with t-slibgcc in
+ tmake_file.
+ Remove pa/t-slibgcc-sjlj-ver, pa/t-slibgcc-dwarf-ver from tmake_file.
+ (hppa*64*-*-hpux11*): Likewise.
+ (hppa[12]*-*-hpux11*): Likewise.
+ (i[34567]86-*-darwin*): Replace t-slibgcc-dummy in t-slibgcc in
+ tmake_file.
+ (x86_64-*-darwin*): Likewise.
+ (i[34567]86-*-cygwin*): Remove tmake_eh_file, tmake_dlldir_file.
+ Add t-slibgcc to tmake_file.
+ (i[34567]86-*-mingw*, x86_64-*-mingw*): Likewise.
+ Remove i386/t-mingw32 from tmake_file unless x86_64-w64-*,
+ i[34567]86-w64-*.
+ Remove i386/t-mingw-pthread from tmake_file.
+ (ia64*-*-linux*): Remove ia64/t-glibc from tmake_file.
+ (ia64*-*-hpux*): Add t-slibgcc to tmake_file.
+ (ia64-hp-*vms*): Likewise.
+ (m32r-*-linux*): Replace t-slibgcc-elf-ver with t-slibgcc in
+ tmake_file.
+ (m32rle-*-linux*): Likewise.
+ (m68k-*-linux*): Remove m68k/t-slibgcc-elf-ver from tmake_file.
+ (microblaze*-linux*): Remove t-slibgcc-elf-ver,
+ t-slibgcc-nolc-override from tmake_file.
+ (mips-sgi-irix6.5*): Replace t-slibgcc-dummy with t-slibgcc in
+ tmake_file.
+ (powerpc-*-darwin*): Likewise.
+ (powerpc64-*-darwin*): Likewise.
+ (powerpc-*-freebsd*): Remove t-slibgcc-libgcc from tmake_file.
+ (powerpc-*-linux*, powerpc64-*-linux*): Likewise.
+ (rs6000-ibm-aix4.[3456789]*, powerpc-ibm-aix4.[3456789]*): Add
+ t-slibgcc to tmake_file.
+ (rs6000-ibm-aix5.1.*, powerpc-ibm-aix5.1.*): Likewise.
+ (rs6000-ibm-aix5.2.*, powerpc-ibm-aix5.2.*): Likewise.
+ (rs6000-ibm-aix5.3.*, powerpc-ibm-aix5.3.*): Likewise.
+ (rs6000-ibm-aix[6789].*, powerpc-ibm-aix[6789].*): Likewise.
+ (sparc-*-linux*): Remove sparc/t-linux from tmake_file.
+ (sparc64-*-linux*): Likewise.
+ (tic6x-*-uclinux): Replace t-slibgcc-elf-ver with t-slibgcc in
+ tmake_file.
+ (i[34567]86-*-linux*, x86_64-*-linux*, i[34567]86-*-kfreebsd*-gnu,
+ x86_64-*-kfreebsd*-gnu, i[34567]86-*-gnu*): Remove i386/t-linux
+ from tmake_file.
+
+2011-11-02 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50902
+ * tree-vect-stmts.c (vectorizable_load): Properly convert
+ an invariant initializer element.
+
+2010-11-02 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50890
+ * gimple.h (gimple_fold_call): Remove.
+ * gimple-fold.c (fold_stmt_1): Move all call related code to ...
+ (gimple_fold_call): ... here. Make static. Update the
+ cannot-inline flag on direct calls.
+ * ipa-inline.c (early_inliner): Copy the cannot-inline flag
+ from the statements to the edges.
+
+2011-11-01 Ian Lance Taylor <iant@google.com>
+
+ * godump.c (struct macro_hash_value): Define.
+ (macro_hash_hashval): New static function.
+ (macro_hash_eq, macro_hash_del): New static functions.
+ (go_define): Use macro_hash_value to store values in macro_hash.
+ Replace an old value on a redefinition. Don't print anything to
+ go_dump_file.
+ (go_undef): Delete the entry from the hash table.
+ (go_output_typedef): For an enum, use macro_hash_value, and don't
+ print anything to go_dump_file.
+ (go_print_macro): New static function.
+ (go_finish): Traverse macro_hash with go_print_macro.
+ (dump_go_spec_init): Update macro_hash creation for macro_hash_value.
+
+2011-11-02 Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/rs6000.c (rs6000_code_end): Declare ATTRIBUTE_UNUSED.
+
+2011-11-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/44277
+ * doc/invoke.texi: Document -Wzero-as-null-pointer-constant.
+
+2011-11-01 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/arm/bpabi.h (BE8_LINK_SPEC): Recognize generic-armv7 tuning.
+
+2011-11-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (splitters for int-float conversion): Use
+ SUBREG_REG on SUBREGs in splitter constraints.
+
+2011-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386-protos.h (ix86_expand_adjust_ufix_to_sfix_si): New
+ prototype.
+ * config/i386/i386.c (ix86_expand_adjust_ufix_to_sfix_si): New
+ function.
+ * config/i386/sse.md (fixuns_trunc<mode><sseintvecmodelower>2): Use it.
+ (ssepackfltmode): New mode attr.
+ (vec_pack_ufix_trunc_<mode>): New expander.
+
+2011-11-01 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/50940
+ * config/i386/i386.md (floatsi<mode>2_vector_sse_with_temp splitter):
+ Compare <ssevecmode>mode with V4SFmode, not V4SImode.
+
+2011-11-01 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config.gcc (powerpc*-*-linux*): Add powerpc*-*-linux*ppc476* variant.
+ * config/rs6000/476.h: New file.
+ * config/rs6000/476.opt: Likewise.
+ * config/rs6000/rs6000.h (TARGET_LINK_STACK): New define.
+ (SET_TARGET_LINK_STACK): Likewise.
+ (TARGET_ASM_CODE_END): Define.
+ * config/rs6000/rs6000.c (rs6000_option_override_internal): Enable
+ TARGET_LINK_STACK for -mtune=476 and -mtune=476fp.
+ (rs6000_legitimize_tls_address): Emit the link stack preserving GOT
+ code if TARGET_LINK_STACK.
+ (rs6000_emit_load_toc_table): Likewise.
+ (output_function_profiler): Likewise
+ (macho_branch_islands): Likewise
+ (machopic_output_stub): Likewise
+ (get_ppc476_thunk_name): New function.
+ (rs6000_code_end): Likewise.
+ * config/rs6000/rs6000.md (load_toc_v4_PIC_1, load_toc_v4_PIC_1b):
+ Convert to a define_expand.
+ (load_toc_v4_PIC_1_normal): New define_insn.
+ (load_toc_v4_PIC_1_476): Likewise.
+ (load_toc_v4_PIC_1b_normal): Likewise.
+ (load_toc_v4_PIC_1b_476): Likewise.
+
+2011-11-01 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50910
+ * config/avr/avr.opt (-mbranch-cost=): New option.
+ * config/avr/avr.h (BRANCH_COST): Define to avr_branch_cost.
+ * config/avr/avr.c (avr_rtx_costs_1): Adjust [U]DIV/[U]MOD costs.
+ * config/avr/avr.md (*addqi3.lt0, *addhi3.lt0, *addsi3.lt0): New insns.
+ (*addhi3_zero_extend1): Remove % in constraint of operand 1.
+ (*addhi3.sign_extend1, *subhi3.sign_extend2): New insns.
+
+2011-11-01 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50908
+ * tree-ssa-tail-merge.c (update_vuses): Now that edges are removed
+ before update_vuses, test for 1 predecessor rather than two.
+ (delete_block_update_dominator_info): New function, part of it factored
+ out of ...
+ (replace_block_by): Use delete_block_update_dominator_info. Call
+ update_vuses after deleting bb1 and updating dominator info, instead of
+ before.
+
+2011-11-01 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.c (vector_init_faligndata): New function.
+ (sparc_expand_vector_init): Use it for V4HImode on VIS1.
+
+ * config/sparc/sparc.c (sparc_expand_vcond): New function.
+ * config/sparc/sparc-protos.h (sparc_expand_vcond): Declare it.
+ * config/sparc/sparc.md (vcond<mode><mode>): New VIS3 expander.
+ (vconduv8qiv8qi): Likewise.
+
+2011-11-01 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/50869
+ * cselib.c (cfa_base_preserved_regno): Initialize.
+ (cselib_expand_value_rtx_1): Don't expand it.
+ * var-tracking.c (vt_expand_var_loc_chain): Initialize depth.
+ Check it's only zero if result is NULL.
+
+2011-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (fixuns_trunc<mode><sseintvecmodelower>2): New
+ expander.
+
+ * config/i386/sse.md (sseintvecmode): Remove duplicate modes.
+ (sseintvecmodelower): New mode iterator.
+ (floatv8siv8sf2, floatunsv4siv4sf2): Macroize into...
+ (float<sseintvecmodelower><mode>2): ... this using VF1 iterator.
+ (floatunsv4siv4sf2): Macroize into...
+ (floatuns<sseintvecmodelower><mode>2): ... this using VF1 iterator.
+
+2011-10-31 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (cmask patterns): Allow zero operand.
+
+ * dwarf2out.c (cached_next_real_insn): New.
+ (dwarf2out_end_epilogue): Set it to NULL_RTX.
+ (dwarf2out_var_location): Remove cached_next_real_insn local static.
+
+2011-10-31 Richard Henderson <rth@redhat.com>
+
+ * config/i386/sse.md (floatv8siv8sf2): Rename from avx_cvtdq2ps256.
+ (floatv4siv4sf2): Rename from sse2_cvtdq2ps.
+ (floatunsv4siv4sf2): Rename from sse2_cvtudq2ps.
+ (fix_truncv8sfv8si2): Rename from avx_cvttps2dq256.
+ (fix_truncv4sfv4si2): Rename from sse2_cvttps2dq.
+ (floatv4siv4df2): Rename from avx_cvtdq2pd256.
+ (fix_truncv4dfv4si2): Rename from avx_cvttpd2dq256.
+ (vec_unpacku_float_hi_v8si): Update for insn pattern name changes.
+ * config/i386/i386.md (splitters for int-float conversion): Likewise.
+ * config/i386/i386.c (ix86_split_convert_uns_si_sse): Likewise.
+ (bdesc_args): Likewise.
+ (enum ix86_builtins) [IX86_BUILTIN_CVTUDQ2PS]: Remove.
+ (ix86_vectorize_builtin_conversion): Remove.
+ (TARGET_VECTORIZE_BUILTIN_CONVERSION): Remove.
+
+2011-10-31 Martin Jambor <mjambor@suse.cz>
+
+ * ipa-prop.c (mark_modified): Moved up in the file.
+ (is_parm_modified_before_call): Renamed to
+ is_parm_modified_before_stmt, moved up in the file.
+ (load_from_unmodified_param): New function.
+ (compute_complex_assign_jump_func): Also attempt to create pass
+ through jump functions for values loaded from (addressable)
+ parameters.
+
+2011-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vect-stmts.c (vectorizable_shift): If op1 is vect_external_def
+ in a loop and has different type from op0, cast it to op0's type
+ before the loop first. For slp give up. Don't crash if op1_vectype
+ is NULL.
+
+2011-10-31 Paul Brook <paul@codesourcery.com>
+
+ * cgraphunit.c: Don't mark clones as static constructors.
+
+2011-10-31 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc-ar: Do not include stdio.h.
+
+2011-10-31 Diego Novillo <dnovillo@google.com>
+
+ * tree-streamer-out.c (pack_ts_base_value_fields): Emit
+ TYPE_ADDR_SPACE.
+ * tree-streamer-in.c (unpack_ts_base_value_fields): Read
+ TYPE_ADDR_SPACE.
+
+2011-10-30 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.c (vector_init_bshuffle): New function.
+ (vector_init_fpmerge): New function.
+ (sparc_expand_vector_init): Use them to improve non-const cases.
+
+ * dwarf2out.c (dwarf2out_var_location): When processing several
+ consecutive location notes, cache the result of next_real_insn().
+
+2011-10-30 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (avx2_vec_dup<mode>): Macroize insn from
+ avx2_vec_dup{v8sf,v4sf} using VF1 mode iterator.
+ (vec_dupv4sf): Remove expander.
+ (vec_dupv4sf): Merge from *vec_dupv4sf and *vec_dupv4sf_avx.
+ (vec_dupv2df): Remove expander.
+ (vec_dupv2df): Merge from *vec_dupv2df and *vec_dupv2df_sse3.
+ (*vec_concatv2df): Merge *vec_concatv2df_sse3.
+ (*vec_dupv4si): Merge *vec_dupv4si_avx.
+ (*vec_dupv2di): Merge *vec_dupv2di_sse3.
+
+2011-10-30 Dmitry Plotnikov <dplotnikov@ispras.ru>
+
+ * tree-cfg.c (verify_gimple_assign_unary): Allow vector conversions.
+ * optabs.c (supportable_convert_operation): New function.
+ * optabs.h (supportable_convert_operation): New prototype.
+ * tree-vect-stmts.c (vectorizable_conversion): Change condition and
+ behavior for NONE modifier case.
+ * tree.h (VECTOR_INTEGER_TYPE_P): New macro.
+
+2011-10-30 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vectorizer.h (NUM_PATTERNS): Bump to 9.
+ * tree-vect-patterns.c (vect_recog_vector_vector_shift_pattern): New
+ function.
+ (vect_vect_recog_func_ptrs): Add it.
+
+2011-10-30 David S. Miller <davem@davemloft.net>
+
+ * reorg.c (label_before_next_insn): New function.
+ (relax_delay_slots): Use it instead of prev_label.
+ * rtl.h (prev_label): Delete declaration.
+ * emit-rtl.c (prev_label): Remove.
+
+2011-10-30 Revital Eres <revital.eres@linaro.org>
+
+ * modulo-sched.c (generate_prolog_epilog): Mark prolog and epilog
+ as BB_DISABLE_SCHEDULE.
+ (mark_loop_unsched): New function.
+ (sms_schedule): Call it.
+
+2011-10-29 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+
+ PR target/50617
+ * config/pa/protos.h (attr_length_save_restore_dltp): Delete.
+ (cmpib_comparison_operator): Likewise.
+ (following_cal, output_and, output_ior, output_move_double,
+ output_fp_move_double, output_block_move, output_block_clear,
+ output_cbranch, output_lbranch, output_bb, output_bvb, output_dbra,
+ output_movb, output_parallel_movb, output_parallel_addb, output_call,
+ output_indirect_call, output_millicode_call, output_mul_insn,
+ output_div_insn, output_mod_insn, singlemove_string,
+ output_arg_descriptor, output_global_address, print_operand,
+ legitimize_pic_address, hppa_encode_label, symbolic_expression_p,
+ fmpyaddoperands, fmpysuboperands, emit_bcond_fp, emit_move_sequence,
+ emit_hpdiv_const, is_function_label_plus_const, jump_in_call_delay,
+ hppa_fpstore_bypass_p, attr_length_millicode_call, attr_length_call,
+ attr_length_indirect_call, return_addr_rtx, function_arg_padding,
+ insn_refs_are_delayed, get_deferred_plabel, ldil_cint_p, zdepi_cint_p,
+ output_ascii, compute_frame_size, and_mask_p, cint_ok_for_move,
+ hppa_expand_prologue, hppa_expand_epilogue, ior_mask_p,
+ compute_zdepdi_operands, output_64bit_and, output_64bit_ior,
+ reloc_needed, magic_milli, shadd_constant_p): Consistently prefix
+ exported functions and variables with "pa_".
+ * config/pa/predicates.md: Likewise.
+ * config/pa/pa64-hpux.h: likewise.
+ * config/pa/som.h: Likewise.
+ * config/pa/elf.h: Likewise.
+ * config/pa/pa64-linux.h: Likewise.
+ * config/pa/pa.md: Likewise.
+ * config/pa/pa.c: Likewise.
+ * config/pa/pa-linux.h: Likewise.
+ * config/pa/pa.h: Likewise.
+ * config/pa/constraints.md: Likewise.
+
+2011-10-29 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (xop_sha<mode>3): Rename from xop_ashl<mode>3.
+ Update all uses.
+ (xop_shl<mode>3): Rename from xop_lshl<mode>3. Update all uses.
+ * config/i386/i386.c: Update all uses.
+
+2011-10-29 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (lshlv16qi3): Remove expander.
+ (lshrv16qi3): New expander.
+ (<shift_insn>v16qi3): Macroize expander from ashrv16qi3 and lshrv16qi3
+ using any_shiftrt code iterator. Cleanup.
+ (ashlv16qi3): Cleanup.
+ (ashrv2di3): Ditto.
+
+2011-10-29 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+
+ PR target/50691
+ * config/pa/pa.c (emit_move_sequence): Legitimize TLS symbol
+ references.
+ (pa_legitimate_constant_p): Return false for TLS_MODEL_GLOBAL_DYNAMIC
+ and TLS_MODEL_LOCAL_DYNAMIC symbol references.
+
+2011-10-29 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50887
+ * config/avr/avr.opt (-maccumulate-args): New option.
+ * config/avr/avr.h (STARTING_FRAME_OFFSET): Redefine to
+ avr_starting_frame_offset.
+ (ACCUMULATE_OUTGOING_ARGS): Define to avr_accumulate_outgoing_args.
+ * config/avr/avr.md (UNSPECV_WRITE_SP_IRQ_ON): Remove.
+ (UNSPECV_WRITE_SP_IRQ_OFF): Remove.
+ (UNSPECV_WRITE_SP): New constant.
+ (*addhi3_sp_R): Rewrite to...
+ (*addhi3_sp): ...this new insn.
+ (movhi_sp_r_irq_off, movhi_sp_r_irq_on): Combine to...
+ (movhi_sp_r): ...this new insn.
+ * config/avr/avr-protos.h (avr_accumulate_outgoing_args): New.
+ (avr_starting_frame_offset): New.
+ * config/avr/avr.c (avr_accumulate_outgoing_args): New function.
+ (avr_starting_frame_offset): New function.
+ (avr_outgoing_args_size): New static function.
+ (avr_initial_elimination_offset): Use it.
+ (avr_simple_epilogue): Use it.
+ (avr_asm_function_end_prologue): Use it.
+ (expand_epilogue): Use it.
+ (expand_prologue): Use it. Break out code to...
+ (avr_prologue_setup_frame): ...this new static function.
+ (avr_can_eliminate): Allow eliminating to frame pointer if there
+ is one.
+ (avr_frame_pointer_required_p): Use frame pointer if target has a
+ nonlocal label.
+ * config/avr/constraints.md (R): Remove.
+ (Csp): New constraint.
+ * config/avr/predicates.md (avr_sp_immediate_operand): Use it.
+
+2011-10-29 Andi Kleen <ak@linux.intel.com>
+
+ * gcc-ar.c (target_machine): Add.
+
+2011-10-29 Anatoly Sokolov <aesok@post.ru>
+
+ * config/cris/cris.c (reg_ok_for_base_p, reg_ok_for_index_p,
+ cris_constant_index_p, cris_base_p, cris_index_p,
+ cris_base_or_autoincr_p, cris_bdap_index_p, cris_biap_index_p,
+ cris_legitimate_address_p): New functions.
+ (TARGET_LEGITIMATE_ADDRESS_P): Define.
+ (cris_pic_symbol_type, cris_valid_pic_const): Change arguments type
+ from rtx to const_rtx.
+ (cris_print_operand_address, cris_address_cost,
+ cris_side_effect_mode_ok): Use
+ cris_constant_index_p, cris_base_p, cris_base_or_autoincr_p,
+ cris_biap_index_p and cris_bdap_index_p.
+ * config/cris/cris.h (CONSTANT_INDEX_P, BASE_P, BASE_OR_AUTOINCR_P,
+ BDAP_INDEX_P, BIAP_INDEX_P, GO_IF_LEGITIMATE_ADDRESS,
+ REG_OK_FOR_BASE_P, REG_OK_FOR_INDEX_P): Remove.
+ (EXTRA_CONSTRAINT_Q, EXTRA_CONSTRAINT_R, EXTRA_CONSTRAINT_T): Use
+ cris_constant_index_p, cris_base_p, cris_base_or_autoincr_p,
+ cris_biap_index_p and cris_bdap_index_p.
+ * config/cris/cris.md (moversideqi movemsideqi peephole2): Use
+ cris_base_p.
+ * config/cris/cris-protos.h (cris_constant_index_p, cris_base_p,
+ cris_base_or_autoincr_p, cris_bdap_index_p, cris_biap_index_p): New
+ prototype.
+ (cris_pic_symbol_type, cris_valid_pic_const): Update prototype.
+
+2011-10-21 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page (PAGE_ALIGN): Add.
+ (alloc_page, ggc_pch_total_size, ggc_pch_this_base, ggc_pch_read):
+ Replace ROUND_UP with PAGE_ALIGN.
+
+2011-10-20 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page (alloc_anon): Add check argument.
+ (alloc_page): Add fallback to 1 page allocation.
+ Adjust alloc_anon calls to new argument.
+
+2011-10-18 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page (release_pages): First free large continuous
+ chunks in the madvise path.
+
+2011-10-18 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page.c (alloc_pages): Always round up entry_size.
+
+2011-10-19 Andi Kleen <ak@linux.intel.com>
+
+ * Makefile.in (MOSTLYCLEANFILES): Add gcc-ar/nm/ranlib.
+ (native): Add gcc-ar, gcc-nm, gcc-ranlib.
+ (AR_LIBS, gcc-ar, gcc-ar.o, gcc-ranlib, gcc-ranlib.o,
+ gcc-nm, gcc-nm.o, gcc-ranlib.c, gcc-nm.c): Add.
+ (install): Depend on install-gcc-ar.
+ (install-gcc-ar): Add.
+ (uninstall): Uninstall gcc-ar, gcc-nm, gcc-ranlib.
+ * gcc-ar.c: Add new file.
+
+2011-10-28 Pat Haugen <pthaugen@us.ibm.com>
+
+ * config/rs6000/rs6000.md (define_attr "type"): Add vecdouble.
+ * config/rs6000/vsx.md (VStype_simple, VStype_mul): Use vecdouble
+ type for V2DF.
+ (VStype_div): Use vector types for V2DF/V4SF.
+ (VStype_sqrt): Use *sqrt types.
+ (VS_spdp_type): Change type to vecdouble.
+ (*vsx_fmav2df4, *vsx_nfmsv2df4, vsx_xvcvdpsxws, vsx_xvcvdpuxws,
+ vsx_xvcvuxdsp, vsx_xvcvsxwdp, vsx_xvcvuxwdp, vsx_xvcvspsxds,
+ vsx_xvcvspuxds): Likewise.
+ (*vsx_fms<mode>4): Set type via <VStype_mul>.
+ (*vsx_eq_<mode>_p, *vsx_gt_<mode>_p, *vsx_ge_<mode>_p): Set type via
+ <VStype_simple>.
+ * config/rs6000/power7.md (power7-vecstore): Correct VSU pipe.
+ (power7-fpcompare, power7-sdiv, power7-ddiv, power7-sqrt,
+ power7-dsqrt): Correct insn latency.
+ (power7-vecsimple): Add veccmp type and correct dispatch/VSU values.
+ (power7-veccmp): Delete.
+ (power7-vecfloat): Correct latency/dispatch/VSU values.
+ (define_bypass "power7-vecfloat"): Correct latency and types.
+ (power7-veccomplex, power7-vecperm): Correct dispatch/VSU values.
+ (power7-vecdouble, power7-vecfdiv, power7-vecdiv): New.
+
+2011-10-28 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.md (shift_insn): Rename code attribute from
+ shiftrt_insn. Also handle ashift RTX.
+ (shift): Rename code attribute from shiftrt. Also handle ashift RTX.
+ (vshift): New code attribute.
+ (<shift_insn>*): Rename from <shiftrt_insn>*. Update asm templates.
+ (any_lshift): Move and rename code iterator from ...
+ * config/i386/sse.md (lshift): ... here.
+ (lshift_insn): Remove code attribute.
+ (lshift): Remove code attribute.
+ (vlshr<mode>3): Use lshiftrt RTX.
+ (vashr<mode>3, ashrv16qi3, ashrv2di3): Use ashiftrt RTX.
+ (vashl<mode>3, ashlv16qi3): Use ashift RTX.
+ (avx2_<lshift>v<mode>): Rename from avx2_<shift_insn>v<mode>. Use
+ any_lshift code iterator. Update asm template.
+ (<shift_insn><mode>3): Macroize insn from lshr<mode>3 and ashl<mode>3
+ usign any_lshift code iterator.
+ * config/i386/mmx.md (mmx_<shift_insn><mode>3): Macroize insn from
+ mmx_lshr<mode>3 and mmx_ashl<mode>3 usign any_lshift code iterator.
+ * config/i386/i386.c (bdesc_args) <__builtin_ia32_psll>: Update.
+
+2011-10-28 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49313
+ * config/avr/avr.md (parityhi2): Expand allowing pseudos.
+ (*parityhi2): New pre-reload insn-and-split to map 16-bit parity
+ to the libgcc insn.
+ (*parityqihi2): Same for 8-bit parity.
+
+2011-10-28 Julian Brown <julian@codesourcery.com>
+
+ PR rtl-optimization/47918
+ * reload1.c (set_initial_label_offsets): Use initial offsets
+ for labels on the nonlocal_goto_handler_labels chain.
+
+2011-10-28 Iain Sandoe <iains@gcc.gnu.org>
+
+ * config/rs6000/t-darwin (LIB2FUNCS_STATIC_EXTRA):
+ Move darwin-fpsave.asm from here to ... LIB2FUNCS_EXTRA.
+ (LIB2FUNCS_EXTRA): Add darwin-gpsave.asm.
+ (TARGET_LIBGCC2_CFLAGS): Ensure that fPIC and -pipe are inherited from
+ config/t-darwin.
+ * config/rs6000/darwin.h (FP_SAVE_INLINE): Adjust to enable.
+ (GP_SAVE_INLINE): Likewise.
+ (SAVE_FP_PREFIX, SAVE_FP_SUFFIX, RESTORE_FP_PREFIX,
+ RESTORE_FP_SUFFIX): Set to empty strings.
+ * config/rs6000/rs6000.c (rs6000_savres_strategy): Implement for Darwin.
+ (debug_stack_info): Print savres_strategy.
+ (rs6000_savres_routine_name): Implement for Darwin.
+ (rs6000_make_savres_rtx): Adjust used register for Darwin.
+ (rs6000_emit_prologue): Implement out-of-line saves for Darwin.
+ (rs6000_output_function_prologue): Don't emit .extern for Mach-O.
+ (rs6000_emit_epilogue): Implement out-of-line saves for Darwin.
+ * config/rs6000/darwin-gpsave.asm: New file.
+
+2011-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (VI4SD_AVX2): Removed.
+ (VI48_AVX2, VI128_128, VI48_128, VI48_256): New mode iterators.
+ (vashl<mode>3): Use VI12_128 iterator instead of VI124_128.
+ Add another expander using VI48_128 iterator for
+ TARGET_AVX2 || TARGET_XOP and another using VI48_256 iterator
+ for TARGET_AVX2.
+ (vlshr<mode>3): Likewise. Change register_operand predicate to
+ nonimmediate_operand on last operand in the VI12_128 expander.
+ (vashr<mode>3): Use VI128_128 iterator instead of VI124_128.
+ (vashrv4si3, vashrv8si3): New expanders.
+ (avx2_ashrvv8si, avx2_ashrvv4si, avx2_<lshift>vv8si,
+ avx2_<lshift>vv2di): Removed.
+ (avx2_ashrv<mode>): New insn with VI4_AVX2 iterator.
+ (avx2_<lshift>v<mode>): Macroize using VI48_AVX2
+ iterator. Simplify pattern.
+
+2010-10-28 Richard Guenther <rguenther@suse.de>
+
+ PR driver/50876
+ * lto-wrapper.c (get_options_from_collect_gcc_options):
+ Properly count arguments.
+ (run_gcc): Use an obstack to collect argv, properly separate
+ switches and their arguments.
+
+2011-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * tree-vect-stmts.c (vectorizable_shift): Give up if op1 has different
+ vector mode from vectype's mode.
+
+2011-10-28 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR rtl-optimization/49720
+ * simplify-rtx.c (simplify_relational_operation_1): Detect
+ infinite recursion condition in "(eq/ne (plus x cst1) cst2)
+ simplifies to (eq/ne x (cst2 - cst1))" case.
+
+2011-10-27 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (snedi_special): Only match when not VIS3.
+ (*snedi_zero): Likewise.
+ (*snedi_zero_trunc): Likewise.
+ (snedi_special_vis3): New expander.
+ (*snedi_zero_vis3): New insn.
+ (*snedi_zero_trunc_vis3): Likewise.
+ (*sltu_insn_vis3): Likewise.
+ (*sltu_insn_vis3_trunc): Likewise.
+ (addxc): Likewise.
+ (*addxc_trunc_sp64_vis3): Likewise.
+ * config/sparc/sparc.c (emit_scc_insn): When VIS3 use the
+ gen_snedi_special_vis3 expander, and try GTU/LTU addx based
+ sequences on DImode values.
+
+ * config/sparc/sparc.md (64-bit vector moves): Use 'e' not 'f'
+ constraint.
+
+ * regcprop.c (copyprop_hardreg_forward_1): Reject the
+ transformation when we narrow the mode on big endian.
+
+2011-10-27 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (avx_cvtpd2dq256_2, avx_cvttpd2dq256_2,
+ vec_pack_sfix_trunc_v4df, vec_pack_sfix_v4df): New expanders.
+ (*avx_cvtpd2dq256_2, *avx_cvttpd2dq256_2): New insns.
+
+ * config/i386/i386.c (ix86_print_operand): Handle 'q' and 'x'
+ overrides for -masm=intel memory.
+ * config/i386/sse.md (sse2_cvtdq2pd, sse2_cvtps2pd,
+ sse4_1_<code>v8qiv8hi2, avx2_<code>v8qiv8si2,
+ sse4_1_<code>v4hiv4si2, avx2_<code>v4hiv4di2,
+ sse4_1_<code>v2siv2di2): Use %q1 instead of %1 for -masm=intel.
+ (sse4_1_<code>v4qiv4si2, avx2_<code>v4qiv4di2,
+ sse4_1_<code>v2hiv2di2): Use %k1 instead of %1 for -masm=intel.
+ (sse4_1_<code>v2qiv2di2): Use %w1 instead of %1 for -masm=intel.
+
+2011-10-27 Martin Jambor <mjambor@suse.cz>
+
+ * ipa-prop.c (compute_pass_through_member_ptrs): Rename parm_info
+ to parm_ainfo.
+ (ipa_compute_jump_functions_for_edge): Likewise.
+ (ipa_compute_jump_functions): Likewise.
+ (ipa_analyze_indirect_call_uses): Likewise.
+ (ipa_analyze_call_uses): Likewise.
+ (ipa_analyze_params_uses): Likewise.
+ (ipa_analyze_node): Likewise.
+
+2011-10-27 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/50875
+ * config/i386/sse.md (*avx_unpcklpd256): Remove extra insn
+ constraints. Change alternative 1 to "x,m,1".
+
+2011-10-27 Jakub Jelinek <jakub@redhat.com>
+
+ * Makefile.in (build/gencheck.o): Depend on tree.def and
+ c-family/c-common.def.
+
+ * tree-ssa-strlen.c: Include expr.h.
+ (get_stridx): Don't use c_strlen, instead use string_constant
+ and compute string length from it.
+ * Makefile.in (tree-ssa-strlen.o): Depend on $(EXPR_H).
+
+2011-10-27 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/46603
+ PR bootstrap/50879
+ * reload.c (push_reload): In the out case, restore previous behavior
+ for subregs that don't have word mode.
+
+2011-10-27 Ian Lance Taylor <iant@google.com>
+
+ * cppdefault.c: Undef NATIVE_SYSTEM_HEADER_DIR if
+ CROSS_DIRECTORY_STRUCTURE is defined and TARGET_SYSTEM_ROOT is not.
+ (cpp_include_defaults): Only use NATIVE_SYSTEM_HEADER_DIR if it is
+ defined.
+
+2011-10-27 Richard Henderson <rth@redhat.com>
+
+ * optabs.c (expand_vec_perm): Use the correct mode for scaling the
+ selector. Save the qimode constant selector for later use by the
+ qimode vec_perm pattern.
+
+2011-10-27 Bernd Schmidt <bernds@codesourcery.com>
+
+ * config/c6x/c6x.c (unit_req_imbalance, res_mii): Cast the first arg
+ to unit_req_factor to the right enum type.
+ (get_unit_operand_masks, reshuffle_units, try_rename_operands,
+ hwloop_optimize): Remove unused variables.
+
+2010-10-27 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50731
+ * tree-vect-generic.c (do_binop): Handle scalar operands.
+
+2011-08-27 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/37191
+ * config/i386/sse.md (*vec_extract_v4sf_mem): Avoid combining registers
+ from different units in a single alternative.
+
+2011-10-26 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.c (emit_scc_insn): Force attempt of v9 sequences
+ if we're comparing DImode and comparison is other than EQ or NE.
+
+ * config/sparc/sparc.c (emit_scc_insn): Do not try v9 sequences until
+ LEU/LTU/GEU/GTU is attempted.
+ * config/sparc/sparc.md (*neg_snesi_sign_extend): New 64-bit insn
+ and split.
+ (*neg_seqsi_sign_extend): Likewise.
+ (*sltu_extend_sp64, *neg_sltu_extend_sp64, *sgeu_extend_sp64,
+ *neg_sgeu_extend_sp64): New insns.
+
+ * config/sparc/sparc-protos.h (sparc_expand_conditional_move): Declare.
+ * config/sparc/sparc.md (mov<I:mode>cc, mov<F:mode>cc): Call it.
+ (*mov<I:mode>_cc_v9): Normalize to expect operand 0 always in operand 4.
+ (*mov<I:mode>_cc_reg_sp64): Likewise.
+ (*movsf_cc_v9): Likewise.
+ (*movsf_cc_reg_sp64): Likewise.
+ (*movdf_cc_v9): Likewise.
+ (*movdf_cc_reg_sp64): Likewise.
+ (*movtf_cc_hq_v9): Likewise.
+ (*movtf_cc_reg_hq_sp64): Likewise.
+ (*movtf_cc_v9): Likewise.
+ (*movtf_cc_reg_sp64): Likewise.
+ * config/sparc/sparc.c (sparc_expand_conditional_move): New function.
+ (sparc_print_operand): Delete 'c' and 'd' handling, no longer used.
+
+2011-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * reload.c (reload_inner_reg_of_subreg): Change type of return value
+ and type of OUTPUT parameter to bool and adjust. Document MODE and
+ OUTPUT parameters. Use HARD_REGISTER_P. Reorder final condition
+ and improve associated comment.
+ (push_reload): Clarify and update comments about reloading of subregs.
+ Adjust calls to reload_inner_reg_of_subreg. Compute the class upfront
+ for the reloading of subregs in the out case as well.
+
+2011-10-26 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/50826
+ * var-tracking.c (rtx_debug_expr_p): New.
+ (use_type): Don't use debug exprs to track non-VTA variables.
+
+2011-10-26 Jeff Law <law@redhat.com>
+
+ * doc/invoke.texi (sink-frequency-threshold): Document.
+ * tree-ssa-sink.c: Include params.h.
+ (select_best_block): New function.
+ (statement_sink_location): Use it.
+ * params.def (SINK_FREQUENCY_THRESHOLD): New PARAM.
+
+2011-10-26 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/48108
+ * config/darwin.c (top level): Amend comments concerning LTO output.
+ (lto_section_num): New variable. (darwin_lto_section_e): New GTY.
+ (LTO_SECTS_SECTION, LTO_INDEX_SECTION): New.
+ (LTO_NAMES_SECTION): Rename.
+ (darwin_asm_named_section): Record LTO section counts and switches
+ in a vec of darwin_lto_section_e.
+ (darwin_file_start): Remove unused code.
+ (darwin_file_end): Put an LTO section termination label. Handle
+ output of the wrapped LTO sections, index and names table.
+
+2011-10-26 Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/rs6000.c (rs6000_make_savres_rtx): Delete unneeded
+ declaration.
+ (rs6000_emit_stack_reset): Only return insn emitted when it adjusts sp.
+ (rs6000_make_savres_rtx): Rename to rs6000_emit_savres_rtx. Use
+ simple_return in pattern, emit instruction, and set jump_label.
+ (rs6000_emit_prologue): Update for rs6000_emit_savres_rtx. Use
+ simple_return rather than return.
+ (emit_cfa_restores): New function.
+ (rs6000_emit_epilogue): Emit cfa_restores when flag_shrink_wrap.
+ Add missing cfa_restores for SAVE_WORLD. Add missing LR cfa_restore
+ when using out-of-line gpr restore. Add missing LR and FP regs
+ cfa_restores for out-of-line fpr restore. Consolidate code setting
+ up cfa_restores. Formatting. Use LR_REGNO define.
+ (rs6000_output_mi_thunk): Use simple_return rather than return.
+ * config/rs6000/rs6000.md (sibcall*, sibcall_value*): Likewise.
+ (return_internal*): Likewise.
+ (any_return, return_pred, return_str): New iterators.
+ (return, conditional return insns): Provide both return and
+ simple_return variants.
+ * config/rs6000/rs6000.h (EARLY_R12, LATE_R12): Define.
+ (REG_ALLOC_ORDER): Move r12 before call-saved regs when FIXED_R13.
+ Move r11 and r0 later to suit shrink-wrapping.
+
+2011-10-26 Richard Guenther <rguenther@suse.de>
+
+ * lto-wrapper.c (run_gcc): Properly init/free obstack.
+
+2011-10-26 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.md (UNSPEC_VSIBADDR): New.
+ * config/i386/predicates.md (vsib_address_operand,
+ vsib_mem_operator): New predicates.
+ * config/i386/i386.c (ix86_print_operand_address): Handle
+ UNSPEC_VSIBADDR addresses.
+ * config/i386/sse.md (avx2_gathersi<mode>, avx2_gatherdi<mode>,
+ avx2_gatherdi<mode>256): Adjust expanders to use MEM with
+ UNSPEC_VSIBADDR address.
+ (*avx2_gathersi<mode>, *avx2_gatherdi<mode>, *avx2_gatherdi<mode>256):
+ Adjust insns to use MEM with UNSPEC_VSIBADDR address.
+
+2011-10-26 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50763
+ * tree-ssa-tail-merge.c (replace_block_by): Update vops if phi_vuse1 or
+ phi_vuse2 is NULL_TREE only if bb1 dominates or is dominated by bb2.
+
+2011-10-26 Richard Guenther <rguenther@suse.de>
+
+ PR lto/41844
+ * Makefile.in (lto-wrapper): Depend on and link against opts-common.o.
+ (lto-wrapper.o): Depend on $(OPTS_H) and $(OPTIONS_H).
+ * lto-wrapper.c (get_options_from_collect_gcc_options): New function.
+ (run_gcc): Use it. Filter out language specific options.
+
+2011-10-26 Andreas Tobler <andreast@fgznet.ch>
+
+ * config/i386/freebsd64.h (LINK_SPEC): Emit the same warning as the
+ 32-bit target does.
+
+2011-10-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR driver/46617
+ * gcc.c (main): Fix fatal_error string for translation.
+
+2011-10-25 Ian Lance Taylor <iant@google.com>
+
+ * tree-eh.c (do_return_redirection): Remove return_value_p
+ parameter. Change all callers.
+ (lower_try_finally_nofallthru): Remove local return_val.
+ (lower_try_finally_onedest): Likewise.
+ (lower_try_finally_copy): Likewise.
+ (lower_try_finally_switch): Likewise.
+
+2011-10-25 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/mmx.md (*mmx_maskmovq): Replace :SI with :P and
+ remove "&& !TARGET_64BIT"
+ (*mmx_maskmovq_rex): Removed.
+
+2011-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/46603
+ * reload.c (push_reload): In the out case, reload the subreg as well
+ as the reg if it has word mode.
+
+2011-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * dwarf2out.c (add_gnat_descriptive_type_attribute): Temporarily
+ suppress debug info for the parent type.
+
+2011-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/ia64/ia64.c (ia64_profile_hook): Fix thinko.
+
+2011-10-25 Richard Henderson <rth@redhat.com>
+
+ * config/i386/sse.md (VEC_EXTRACT_EVENODD_MODE): Remove.
+ (vec_extract_even<mode>, vec_extract_odd<mode>): Remove.
+
+ * config/rs6000/altivec.md (vec_extract_evenv8hi,
+ vec_extract_evenv16qi, vec_extract_oddv4si,
+ vec_extract_oddv4sf): Remove.
+
+ * config/spu/spu.md (vec_extract_evenv4si, vec_extract_evenv4sf,
+ vec_extract_evenv8hi, vec_extract_evenv16qi, vec_extract_oddv4si,
+ vec_extract_oddv4sf, vec_extract_oddv8hi, vec_extract_oddv16qi,
+ vec_interleave_highv4sf, vec_interleave_lowv4sf,
+ vec_interleave_highv4si, vec_interleave_lowv4si,
+ vec_interleave_highv8hi, vec_interleave_lowv8hi,
+ vec_interleave_highv16qi, vec_interleave_lowv16qi): Remove.
+
+ * expr.c (expand_expr_real_2) [VEC_EXTRACT_EVEN_EXPR]: Use binop.
+ [VEC_EXTRACT_ODD_EXPR, VEC_INTERLEAVE_HIGH_EXPR]: Likewise.
+ [VEC_INTERLEAVE_LOW_EXPR]: Likewise.
+ * optabs.c (expand_binop): Implement vec_interleave_high_optab,
+ vec_interleave_low_optab, vec_extract_even_optab,
+ vec_extract_odd_optab with expand_vec_perm.
+ (can_vec_perm_for_code_p): New.
+ * optabs.h: Update.
+ * tree-vect-data-refs.c (vect_strided_store_supported): Allow for
+ fallback via can_vec_perm_for_code_p.
+ (vect_strided_load_supported): Likewise.
+ * tree-vect-generic.c (expand_vector_operations_1): Never lower
+ VEC_INTERLEAVE_HIGH_EXPR, VEC_INTERLEAVE_LOW_EXPR,
+ VEC_EXTRACT_EVEN_EXPR, VEC_EXTRACT_ODD_EXPR.
+
+ * target.def (vec_perm_const_ok): Change parameters to mode and
+ array of indicies.
+ * doc/tm.texi: Rebuild.
+ * config/i386/i386.c (ix86_vectorize_vec_perm_const_ok): Change
+ parameters to mode and array of indicies.
+ * expr.c (expand_expr_real_2) [VEC_PERM_EXPR]: Expand operands here.
+ * optabs.c (can_vec_perm_p): Rename from can_vec_perm_expr_p.
+ Change parameters to mode and array of indicies.
+ (expand_vec_perm_1): Rename from expand_vec_perm_expr_1.
+ (expand_vec_perm): Rename from expand_vec_perm_expr. Change
+ parameters to mode and rtx inputs. Try lowering to QImode
+ vec_perm_const before trying fully variable permutation.
+ * optabs.h: Update decls.
+ * tree-vect-generic.c (lower_vec_perm): Extract array of indices from
+ VECTOR_CST to pass to can_vec_perm_p.
+ * tree-vect-slp.c (vect_get_mask_element): Change mask parameter type
+ from int pointer to unsigned char pointer.
+ (vect_transform_slp_perm_load): Update for change to can_vec_perm_p.
+ * tree-vect-stmts.c (perm_mask_for_reverse): Likewise.
+
+ * tree.def (VEC_EXTRACT_EVEN_EXPR): Fix typo in text name.
+ (VEC_EXTRACT_ODD_EXPR, VEC_INTERLEAVE_HIGH_EXPR,
+ VEC_INTERLEAVE_LOW_EXPR): Likewise.
+
+2011-10-25 Mike Stump <mikestump@comcast.net>
+
+ * reload.c (regno_clobbered_p): Fix typo.
+
+2011-10-25 Dodji Seketeli <dodji@redhat.com>
+
+ * input.c (expand_location): Rewrite using linemap_resolve_location
+ and linemap_expand_location. Add a comment.
+
+2011-10-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50596
+ * tree-vect-stmts.c (vect_mark_relevant): Only use
+ FOR_EACH_IMM_USE_FAST if lhs is SSA_NAME.
+ (vectorizable_store): If is_pattern_stmt_p look through
+ VIEW_CONVERT_EXPR on lhs.
+ * tree-vect-patterns.c (check_bool_pattern, adjust_bool_pattern):
+ Use unsigned type instead of signed.
+ (vect_recog_bool_pattern): Optimize also stores into bool memory in
+ addition to casts from bool to integral types.
+ (vect_mark_pattern_stmts): If pattern_stmt already has vinfo
+ created, don't create it again.
+
+2011-10-25 Kai Tietz <ktietz@redhat.com>
+
+ * config/i386/i386.c (ix86_frame_pointer_required): Require
+ frame-pointer, if setjmp is used for 32-bit ms-abi.
+
+2011-10-24 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * builtins.c (set_builtin_user_assembler_name): Remove extra
+ newline added in October 11th, 2011 change.
+
+2011-10-24 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/little-endian.opt: Delete.
+ * config.gcc: Remove references to config/sparc/little-endian.opt
+ * doc/invoke.texi: Remove documentation of -mlittl-endian on sparc.
+ * config/sparc/linux64.h: Delete references to -mlittle-endian.
+ * config/sparc/netbsd-elf.h: Likewise.
+ * config/sparc/openbsd64.h: Likewise.
+ * config/sparc/sparc.h: Likewise.
+ * config/sparc/sp64-elf.h: Likewise and delete overrides for
+ BYTES_BIG_ENDIAN and WORDS_BIG_ENDIAN.
+ * config/sparc/sparc.c (dump_target_flag_bits): Remove reference
+ to MASK_LITTLE_ENDIAN.
+ * config/sparc/sparc.opt (Mask(LITTLE_ENDIAN)): Delete.
+
+ * config/sparc/sparc.md: Only use F, G, and C constraints in FP insns.
+ Only use D, Y, and Z constraints in vector insns.
+
+ * config/sparc/sparc.md (cpu_feature, enabled): New attributes.
+ (*movsi_insn_novis3, *movsi_insn_vis3): Consolidate into one pattern
+ called *movsi_insn.
+ (*movdi_insn_sp32_v9_novis3, *movdi_insn_sp32_v9_vis3): Consolidate
+ into *movdi_insn_sp32.
+ (*movdi_insn_sp64_novis3, *movdi_insn_sp64_vis3): Consolidate into
+ one pattern called *movdi_insn_sp64.
+ (*movsf_insn_novis3, *movsf_insn_vis3, *movsf_insn_no_fpu):
+ Consolidate into one pattern called *movsf_insn.
+ (*movdf_insn_sp32_no_fpu, *movdf_insn_sp32_v9_novis3,
+ *movdf_insn_sp32_v9_vis3, *movdf_insn_sp32_v9_no_fpu): Consolidate
+ into *movdf_insn_sp32.
+ (*movdf_insn_sp64_novis3, *movdf_insn_sp64_vis3,
+ *movdf_insn_sp64_no_fpu): Consolidate into one pattern called
+ *movdf_insn_sp64.
+ (*zero_extendsidi2_insn_sp64_novis3,
+ *zero_extendsidi2_insn_sp64_vis3): Consolidate into one pattern
+ called *zero_extendsidi2_insn_sp64.
+ (*sign_extendsidi2_insn_novis3, *sign_extendsidi2_insn_vis3):
+ Consolidate into one pattern named *sign_extendsidi2_insn.
+ (*mov<VM32:mode>_insn_novis3, *mov<VM32:mode>_insn_vis3):
+ Consolidate into one pattern named *mov<VM32:mode>_insn.
+ (*mov<VM64:mode>_insn_sp64_novis3,
+ *mov<VM64:mode>_insn_sp64_novis3): Consolidate into one pattern
+ named *mov<VM64:mode>_insn_sp64.
+ (*mov<VM64:mode>_insn_sp32_novis3,
+ *mov<VM64:mode>_insn_sp32_vis3): Consolidate into one pattern
+ named *mov<VM64:mode>_insn_sp32.
+
+2011-10-24 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * tree-ssa-strlen.c (get_string_length): Change assertion to STPCPY.
+ (zero_length_string): Change assertion to accept strinfo without
+ length but with stmt instead.
+ Set the endptr pointer also if starting a new chain.
+ (adjust_related_strinfos): Ignore strinfos marked for delayed
+ length computation.
+ (handle_builtin_strcpy): Mark earlier strinfo elements also for
+ delayed length computation.
+
+2011-10-24 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50820
+ Port from 4.6 branch r180379
+ * doc/invoke.texi (AVR Options): New subsubsection to explain EIND
+ handling and indirect jump/calls on devices > 128k.
+
+2011-10-24 Anatoly Sokolov <aesok@post.ru>
+ Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/49824
+ * doc/extend.texi (Declaring Attributes of Functions):
+ Document OS_main and OS_task attributes.
+ (Specifying Attributes of Variables): Move up
+ subsection "AVR Variable Attributes" as of alphabetical order.
+
+2011-10-24 Richard Guenther <rguenther@suse.de>
+
+ * tree-vect-stmts.c (vect_get_vec_def_for_operand): Convert constants
+ to vector element type.
+ (vectorizable_assignment): Bail out for non-mode-precision operations.
+ (vectorizable_shift): Likewise.
+ (vectorizable_operation): Likewise.
+ (vectorizable_type_demotion): Likewise.
+ (vectorizable_type_promotion): Likewise.
+ (vectorizable_store): Handle non-mode-precision stores.
+ (vectorizable_load): Handle non-mode-precision loads.
+ (get_vectype_for_scalar_type_and_size): Return a vector type
+ for non-mode-precision integers.
+ * tree-vect-loop.c (vectorizable_reduction): Bail out for
+ non-mode-precision reductions.
+
+2011-10-24 Julian Brown <julian@codesourcery.com>
+
+ * config/m68k/m68k.c (notice_update_cc): Tighten condition for
+ setting CC_REVERSED for FP comparisons.
+
+2011-10-24 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50838
+ * tree-data-ref.c (dr_analyze_indices): Properly canonicalize
+ a MEM_REF base if we change it.
+
+2011-10-24 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR bootstrap/50836
+ * rtlanal.c: Swap includes of "hard-reg-set.h" and "rtl.h".
+
+ PR rtl-optimization/50833
+ * function.c (thread_prologue_and_epilogue_insns): Expect the
+ return insn optimization only if optimize.
+
+2011-10-24 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.c: Break long lines.
+ Define target hooks on the fly if applicable.
+ (TARGET_ASM_FUNCTION_RODATA_SECTION): Remove first definition
+ overridden later.
+ (targetm): Move definition to end of file.
+ (avr_can_eliminate): Make static on the fly.
+ (avr_frame_pointer_required_p): Ditto.
+ (avr_hard_regno_scratch_ok): Ditto.
+ (avr_builtin_setjmp_frame_value): Make static on the fly.
+ Indent according to coding rules.
+ (avr_case_values_threshold): Ditto.
+ (avr_attribute_table): Move down.
+
+2011-10-24 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50730
+ * tree-vect-data-refs.c (vect_analyze_data_refs): Stop basic block
+ analysis if encountered unsupported data-ref.
+
+2011-10-23 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.c (sparc_option_override): Remove -mv8plus
+ cpu adjustment.
+ * config/sparc/linux64.h (CC1_SPEC): When defaulting to 64-bit,
+ append -mcpu=v9 when -mv8plus is given.
+
+ * config/sparc/sparc.h (SECONDARY_MEMORY_NEEDED): We can move
+ between float and non-float regs when VIS3.
+ * config/sparc/sparc.c (eligible_for_restore_insn): We can't
+ use a restore when the source is a float register.
+ (sparc_split_regreg_legitimate): When VIS3 allow moves between
+ float and integer regs.
+ (sparc_register_move_cost): Adjust to account for VIS3 moves.
+ (sparc_preferred_reload_class): On 32-bit with VIS3 when moving an
+ integer reg to a class containing EXTRA_FP_REGS, constrain to FP_REGS.
+ (sparc_secondary_reload): On 32-bit with VIS3 when moving between
+ float and integer regs we sometimes need a FP_REGS class
+ intermediate move to satisfy the reload. When this happens
+ specify an extra cost of 2.
+ (*movsi_insn): Rename to have "_novis3" suffix and add !VIS3 guard.
+ (*movdi_insn_sp32_v9): Likewise.
+ (*movdi_insn_sp64): Likewise.
+ (*movsf_insn): Likewise.
+ (*movdf_insn_sp32_v9): Likewise.
+ (*movdf_insn_sp64): Likewise.
+ (*zero_extendsidi2_insn_sp64): Likewise.
+ (*sign_extendsidi2_insn): Likewise.
+ (*movsi_insn_vis3): New insn.
+ (*movdi_insn_sp32_v9_vis3): New insn.
+ (*movdi_insn_sp64_vis3): New insn.
+ (*movsf_insn_vis3): New insn.
+ (*movdf_insn_sp32_v9_vis3): New insn.
+ (*movdf_insn_sp64_vis3): New insn.
+ (*zero_extendsidi2_insn_sp64_vis3): New insn.
+ (*sign_extendsidi2_insn_vis3): New insn.
+ (TFmode reg/reg split): Make sure both REG operands are float.
+ (*mov<VM32:mode>_insn): Add "_novis3" suffix and !VIS3 guard. Remove
+ easy constant to integer reg alternatives.
+ (*mov<VM64:mode>_insn_sp64): Likewise.
+ (*mov<VM64:mode>_insn_sp32_novis3): Likewise.
+ (*mov<VM32:mode>_insn_vis3): New insn.
+ (*mov<VM64:mode>_insn_sp64_vis3): New insn.
+ (*mov<VM64:mode>_insn_sp32_vis3): New insn.
+ (VM64 reg<-->reg split): New splitter for 32-bit.
+
+ * config/sparc/sparc.c (sparc_split_regreg_legitimate): New function.
+ * config/sparc/sparc-protos.h (sparc_split_regreg_legitimate):
+ Declare it.
+ * config/sparc/sparc.md (DImode reg/reg split): Use it.
+ (DFmode reg/reg split): Likewise.
+
+ * config/sparc/sparc.md (*movdi_insn_sp32_v9): Add alternatives for
+ generating fzero and fone instructions.
+ (DImode const_int --> reg splitter): Only trigger for integer regs.
+
+ * config/sparc/predicates.md (input_operand): Disallow vector
+ constants other than 0 and -1.
+ * config/sparc/sparc.c (sparc_preferred_reload_class): Return
+ NO_REGS for vector constants other than 0 and -1.
+
+ * config/sparc/sparc.h (SPARC_FIRST_INT_REG, SPARC_LAST_INT_REG,
+ SPARC_INT_REG_P): Define.
+ (HARD_REGNO_NREGS): Use SPARC_INT_REG_P.
+ (REGNO_OK_FOR_INDEX_P): Likewise.
+ * config/sparc/sparc.c (gen_df_reg): Likewise.
+ (eligible_for_return_delay): Likewise.
+ (eligible_for_sibcall_delay): Likewise.
+ (sparc_legitimate_address_p): Likewise.
+ (emit_save_or_restore_regs): Likewise.
+ (registers_ok_for_ldd_peep): Likewise.
+ * config/spac/sparc.md (DI mode splitters): Likewise.
+ (SF mode const splitters): Likewise.
+ (DF mode splitters): Likewise.
+ (32-bit DI mode logical op splitters): Likewise.
+
+2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50841
+ Revert:
+ 2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50810
+ * doc/invoke.texi ([-Wnarrowing], [-Wc++0x-compat]): Update.
+
+2011-10-23 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (avx2_lshl<mode>3): Remove insn pattern.
+ (VI248_256): Remove mode iterator.
+ * config/i386/i386.c (ix86_expand_vec_perm): Use gen_ashlv4di3
+ instead of gen_avx2_lshlv4di3.
+ (bdesc_args): Use CODE_FOR_ashl{v16hi,v8si,v4di}3 instead of
+ CODE_FOR_avx2_lshl{v16hi,v8si,v4di}3.
+
+2011-10-23 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/sse.md (sseintprefix): Rename from gthrfirstp.
+ (<avx_avx2>_maskload<ssemodesuffix><avxsizesuffix>): Delete expander.
+ (<avx_avx2>_maskload<ssemodesuffix><avxsizesuffix>) Merge insn
+ pattern from *avx2_maskload<ssemodesuffix><avxsizesuffix> and
+ *avx_maskload<ssemodesuffix><avxsizesuffix> using V48_AVX mode
+ iterator. Use sseintprefix mode attribute.
+ (<avx_avx2>_maskstore<ssemodesuffix><avxsizesuffix>): Delete expander.
+ (<avx_avx2>_maskstore<ssemodesuffix><avxsizesuffix>) Merge insn
+ pattern from *avx2_maskstore<ssemodesuffix><avxsizesuffix> and
+ *avx_maskstore<ssemodesuffix><avxsizesuffix> using V48_AVX mode
+ iterator. Use sseintprefix mode attribute.
+ (*avx2_gathersi<mode>) Use sseintprefix and ssemodesuffix mode
+ attributes.
+ (*avx2_gatherdi<mode>): Ditto.
+ (*avx2_gatherdi<mode>256): Ditto.
+ (VI48_AVX2): Remove mode iterator.
+ (gthrlastfp): Remove mode attribute.
+
+2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50810
+ * doc/invoke.texi ([-Wnarrowing], [-Wc++0x-compat]): Update.
+
+2011-10-23 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50763
+ * tree-ssa-tail-merge.c (same_succ_flush_bb): New function, factored
+ out of ...
+ (same_succ_flush_bbs): Use same_succ_flush_bb.
+ (purge_bbs): Remove argument. Remove calls to same_succ_flush_bbs,
+ release_last_vdef and delete_basic_block.
+ (unlink_virtual_phi): New function.
+ (update_vuses): Add and use vuse1_phi_args argument. Set var to
+ SSA_NAME_VAR of vuse1 or vuse2, and use var. Handle case that
+ def_stmt2 is NULL. Use phi result as phi arg in case vuse1 or vuse2
+ is NULL_TREE. Replace uses of vuse1 if vuse2 is NULL_TREE. Fix code
+ to limit replacement of uses. Propagate phi argument for phis with a
+ single argument.
+ (replace_block_by): Update vops if phi_vuse1 or phi_vuse2 is NULL_TREE.
+ Set vuse1_phi_args if vuse1 is a phi defined in bb1. Add
+ vuse1_phi_args as argument to call to update_vuses. Call
+ release_last_vdef, same_succ_flush_bb, delete_basic_block. Update
+ CDI_DOMINATORS info.
+ (tail_merge_optimize): Remove argument in call to purge_bbs. Remove
+ call to free_dominance_info. Only call calculate_dominance_info once.
+
+2011-10-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fold-const.c (invert_tree_comparison): Always invert EQ_EXPR/NE_EXPR.
+
+ PR tree-optimization/44683
+ * tree-ssa-dom.c (record_edge_info): Record simple equivalences only if
+ we can be sure that there are no signed zeros involved.
+
+2011-10-23 Jan Hubicka <jh@suse.cz>
+
+ * ipa-inline.c (estimate_badness): Scale up and handle overflows.
+
+2011-10-23 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/50788
+ * config/i386/sse.md (<avx_avx2>_maskload<ssemodesuffix><avxsizesuffix>):
+ Remove (match_dup 0).
+ (*avx2_maskload<ssemodesuffix><avxsizesuffix>): New insn pattern.
+ (*avx_maskload<ssemodesuffix><avxsizesuffix>): Ditto.
+ (*avx2_maskstore<ssemodesuffix><avxsizesuffix>): Ditto.
+ (*avx_maskstore<ssemodesuffix><avxsizesuffix>): Ditto.
+ (*avx2_maskmov<ssemodesuffix><avxsizesuffix>): Remove insn pattern.
+ (*avx_maskmov<ssemodesuffix><avxsizesuffix>): Ditto.
+
+2011-10-23 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50819
+ * tree-vectorizer.h (vect_analyze_data_ref_dependences): Remove
+ the last argument.
+ * tree-vect-loop.c (vect_analyze_loop_2): Update call to
+ vect_analyze_data_ref_dependences.
+ * tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Remove
+ the last argument. Check load-after-store dependence for unknown
+ dependencies in basic blocks.
+ (vect_analyze_data_ref_dependences): Update call to
+ vect_analyze_data_ref_dependences.
+ * tree-vect-patterns.c (vect_recog_widen_shift_pattern): Fix typo.
+ * tree-vect-slp.c (vect_bb_vectorizable_with_dependencies): Remove.
+ (vect_slp_analyze_bb_1): Update call to
+ vect_analyze_data_ref_dependences. Don't call
+ vect_bb_vectorizable_with_dependencies.
+
+2011-10-22 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.h (SECONDARY_INPUT_RELOAD_CLASS,
+ SECONDARY_OUTPUT_RELOAD_CLASS): Delete.
+ * config/sparc/sparc.c (TARGET_SECONDARY_RELOAD): Redefine.
+ (sparc_secondary_reload): New function.
+
+ * config/sparc/sparc.h (sparc_costs): Remove extern decl.
+ (struct processor_costs): Move from here..
+ * config/sparc/sparc.c (struct processor_costs): To here.
+ (sparc_costs): Mark static.
+
+ * config/sparc/sparc.c (short_branch, reg_unused_after): Delete.
+ * config/sparc/sparc-protos.h (short_branch, reg_unused_after):
+ Get rid of declarations.
+
+2011-10-21 Paul Brook <paul@codesourcery.com>
+
+ * config/c6x/c6x.c (c6x_asm_emit_except_personality,
+ c6x_asm_init_sections): New functions.
+ (TARGET_ASM_EMIT_EXCEPT_PERSONALITY, TARGET_ASM_INIT_SECTIONS): Define.
+
+2011-10-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/50813
+ * config/i386/i386.c (expand_vec_perm_even_odd_1): Handle
+ V4DImode and V8SImode for !TARGET_AVX2.
+
+2011-10-21 Bernd Schmidt <bernds@codesourcery.com>
+
+ PR bootstrap/50825
+ * sched-deps.c (add_dependence): If not doing predication, promote
+ REG_DEP_CONTROL to REG_DEP_ANTI.
+
+2011-10-21 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.h (LEGITIMIZE_RELOAD_ADDRESS): Pass address of X
+ instead of X to avr_legitimize_reload_address.
+ * config/avr/avr-protos.h (avr_legitimize_reload_address): Change
+ first argument's type from rtx to rtx*.
+ * config/avr/avr.c (avr_legitimize_reload_address): Ditto.
+ Pass PX to push_reload instead of &X. Change log messages for
+ better distinction.
+
+2011-10-21 Roland Stigge <stigge@antcom.de>
+
+ PR translation/47064
+ * params.def: Fix typo "compilatoin" -> "compilation".
+
+2011-10-21 H.J. Lu <hongjiu.lu@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+
+ PR target/50740
+ * config/i386/driver-i386.c (host_detect_local_cpu): Do cpuid 7 only
+ if max_level allows that.
+
+2011-10-21 Bernd Schmidt <bernds@codesourcery.com>
+
+ * reg-notes.def (DEP_CONTROL): New.
+ * sched-ebb.c (add_deps_for_risky_insns): Add a REG_DEP_CONTROL when
+ not doing speculation.
+ * rtlanal.c (record_hard_reg_sets, find_all_hard_reg_sets,
+ record_hard_reg_uses_1, record_hard_reg_uses): New functions.
+ * function.c (record_hard_reg_sets, record_hard_reg_uses,
+ record_hard_reg_uses_1): Remove; move to rtlanal.c.
+ * lists.c (copy_INSN_LIST, concat_INSN_LIST): New functions.
+ * haifa-sched.c: Swap includes of "rtl.h" and "hard-reg-set.h".
+ (MUST_RECOMPUTE_SPEC_P): New macro.
+ (real_insn_for_shadow): New function.
+ (cond_clobbered_p, recompute_todo_spec, check_clobbered_conditions,
+ toggle_cancelled_flags): New static functions.
+ (schedule_insn): Relax an assert to only check for empty hard back
+ dependencies. Skip cancelled dependencies. Call
+ check_clobbered_conditions.
+ (copy_insn_list): Remove function, renamed moved to lists.c.
+ (save_backtrack_point): Use new spelling copy_INSN_LIST.
+ (unschedule_insns_until): Ensure TODO_SPEC is reset properly.
+ (restore_last_backtrack_point): Likewise. Call toggle_cancelled_flags.
+ (estimate_insn_tick): Ignore cancelled dependencies.
+ (haifa_speculate_insn): Move declaration.
+ (try_ready): Move code into recompute_todo_spec and call it. Tweak
+ some asserts. Ensure predicated patterns are restored if necessary.
+ Dump DEP_CONTROL flag.
+ (haifa_change_pattern): Merge with sched_change_pattern.
+ (sched_change_pattern): Remove function.
+ * sched-deps.c (NON_FLUSH_JUMP_KIND, NON_FLUSH_JUMP): Remove. All
+ uses changed to simply not test NON_FLUSH_JUMP_P.
+ (ds_to_dk, dk_to_ds, dump_dep, ds_to_dt, dump_ds, check_dep): Handle
+ REG_DEP_CONTROL.
+ (dep_spec_p): If DO_PREDICATION, REG_DEP_CONTROL is speculative.
+ (reg_pending_control_uses, control_dependency_cache): New static
+ variables.
+ (sched_get_reverse_condition_uncached): New function.
+ (sd_find_dep_between): Remove pointless assert. Look in
+ control_dependency_cache.
+ (ask_dependency_caches, set_dependency_caches, sd_delete_dep,
+ extend_dependency_caches, sched_deps_finish): Handle REG_DEP_CONTROL
+ and control_dependency_cache.
+ (sd_unresolve_dep): Use dep_spec_p.
+ (add_dependence): Now a wrapper around add_dependence_1, handling
+ REG_DEP_CONTROL specially.
+ (flush_pending_lists): Clear pending_jump_insns.
+ (sched_analyze_1): Handle pending_jump_insns like a memory flush.
+ (sched_analyze_2): Unconditionally add to pending memory flushes,
+ keep previous behaviour but apply it to pending_jump_insns instead.
+ (sched_analyze_insn): Defer adding jump reg dependencies using
+ reg_pending_control_uses; add them to the control_uses list. Handle
+ pending_jump_insns and control_uses when adding dependence lists.
+ (deps_analyze_insn): Update INSN_COND_DEPS.
+ (deps_analyze_insn): Add jumps to pending_jump_insns rather than
+ last_pending_memory_flush.
+ (init_deps): Initialize pending_jump_insns.
+ (free_deps): Free control_uses.
+ (remove_from_deps): Remove from pending_jump_insns.
+ (init_deps_global): Allocate reg_pending_control_uses).
+ (finish_deps_global): Free it.
+ (add_dependence_1): Renamed from add_dependence. Handle
+ REG_DEP_CONTROL.
+ * rtl.h (record_hard_reg_uses, find_all_hard_reg_sets): Declare.
+ (copy_INSN_LIST, concat_INSN_LIST): Declare.
+ * sched-int.h (struct deps_reg): Add control_uses.
+ (struct deps_desc): Add pending_jump_insns.
+ (struct _haifa_deps_insn_data): Add cond_deps.
+ (struct _haifa_insn_data): Add must_recompute_spec and predicated_pat.
+ (INSN_COND_DEPS, PREDICATED_PAT): New macros.
+ (BITS_PER_DEP_WEAK): Adjust for two extra bits in the word.
+ (DEP_CONTROL): New macro.
+ (DEP_TYPES): Include it.
+ (HARD_DEP): Adjust definition.
+ (DEP_CANCELLED): New macro.
+ (enum SCHED_FLAGS): Add DO_PREDICATION.
+ (sched_get_reverse_condition_uncached, real_insn_for_shadow): Declare.
+ * sched-rgn.c (concat_INSN_LIST): Remove function.
+ (deps_join): Handle pending_jump_insns.
+ (free_pending_lists): Likewise.
+ * config/c6x/c6x.c (c6x_set_sched_flags): Set DO_PREDICATION for final
+ schedule.
+
+2011-10-21 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50820
+ * config/avr/libgcc.S (__EIND__): New define to 0x3C.
+ (__tablejump__): Consistently use EIND for indirect jump/call.
+ (__tablejump_elpm__): Ditto.
+
+2011-10-21 Bernd Schmidt <bernds@codesourcery.com>
+
+ * config/c6x/c6x.md (attr "op_pattern"): New.
+ (load_sdata_pic, mov<mode>_insn for QIHIM and SISFVM): Set it.
+ * config/c6x/c6x-mult.md.in (mulhi3_VARIANT_, mulhisi3_insn_VARIANT_):
+ Likewise.
+ * config/c6x/c6x-mult.md: Regenerate.
+ * config/c6x/c6x.c: Include "regrename.h".
+ (unit_req_table): New typedef.
+ (unit_reqs): Use it for the declaration.
+ (unit_req_factor, get_unit_reqs, merge_unit_reqs, unit_req_imbalance,
+ get_unit_operand_masks, try_rename_operands, reshuffle_units): New
+ static functions.
+ (count_unit_reqs): New arg reqs. All callers changed. Use
+ get_unit_reqs, and don't merge here.
+ (res_mii): New arg reqs. All callers changed. Rewrite to use a loop
+ using unit_req_factor.
+ (hwloop_optimize): Call reshuffle_units. Call merge_unit_reqs after
+ count_unit_reqs.
+ (c6x_reorg): Add reg notes problem, and call df_analyze.
+ * Makefile.in ($(out_object_file)): Depend on regrename.h.
+
+2011-10-21 Kai Tietz <ktietz@redhat.com>
+
+ * fold-const.c (simple_operand_p_2): Handle integral
+ casts from boolean-operands.
+
+2011-10-21 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.c (dump_cgraph_node): Dump alias flag.
+ * cgraphunit.c (handle_alias_pairs): Handle weakrefs with
+ no destination.
+ (get_alias_symbol): New function.
+ (output_weakrefs): Output also weakrefs with no destinatoin.
+ (lto_output_node): Output weakref alias flag when at function boundary.
+
+2011-10-21 Andrew Stubbs <ams@codesourcery.com>
+
+ PR target/50809
+ * config/arm/driver-arm.c (vendors): Make static.
+
+2011-10-21 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_emit_swdivsf): Force b into register.
+ (ix86_emit_swsqrtsf): Force a into register.
+
+2011-10-20 Mike Stump <mikestump@comcast.net>
+
+ * regcprop.c (copyprop_hardreg_forward_1): Update recog_data
+ after validate_change wipes it out.
+
+2011-10-20 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/spu/spu.md ("vec_permv16qi"): Reduce selector modulo 32
+ before using the shufb instruction.
+
+2011-10-20 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ PR target/50766
+ * config/i386/i386.md (bmi_bextr_<mode>): Update register/
+ memory operand order.
+ (bmi2_bzhi_<mode>3): Ditto.
+ (bmi2_pdep_<mode>3): Ditto.
+ (bmi2_pext_<mode>3): Ditto.
+
+2011-10-20 Richard Henderson <rth@redhat.com>
+
+ * target.def (vec_perm_const_ok): Rename from builtin_vec_perm_ok.
+ * optabs.c (can_vec_perm_expr_p): Update to match.
+ (expand_vec_perm_expr): Likewise.
+ * config/i386/i386.c (TARGET_VECTORIZE_VEC_PERM_CONST_OK): Rename
+ from TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK.
+ * doc/tm.texi.in: Likewise.
+
+2011-10-20 Sergey Ostanevich <sergos.gnu@gmail.com>
+
+ PR target/50572
+ * config/i386/i386.c (processor_target_table): Change Atom
+ align_loops_max_skip to 15.
+
+2011-10-20 Richard Henderson <rth@redhat.com>
+
+ * target.def (builtin_vec_perm): Remove.
+ * doc/tm.texi.in (TARGET_VECTORIZE_BUILTIN_VEC_PERM): Remove.
+
+ * config/i386/i386.c (ix86_expand_vec_perm_builtin): Remove.
+ (IX86_BUILTIN_VEC_PERM_*): Remove.
+ (bdesc_args): Remove vec_perm builtins
+ (ix86_expand_builtin): Likewise.
+ (ix86_expand_vec_perm_const_1): Rename from
+ ix86_expand_vec_perm_builtin_1.
+ (extract_vec_perm_cst): Merge into...
+ (ix86_vectorize_vec_perm_const_ok): ... here. Rename from
+ ix86_vectorize_builtin_vec_perm_ok.
+ (TARGET_VECTORIZE_BUILTIN_VEC_PERM): Remove.
+
+ * config/rs6000/rs6000.c (rs6000_builtin_vec_perm): Remove.
+ (TARGET_VECTORIZE_BUILTIN_VEC_PERM): Remove.
+
+ * config/spu/spu.c (spu_builtin_vec_perm): Remove.
+ (TARGET_VECTORIZE_BUILTIN_VEC_PERM): Remove.
+
+2011-10-20 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/47989
+ * config/i386/i386.h (RECIP_MASK_DEFAULT): New define.
+ * config/i386/i386.op (recip_mask): Initialize with RECIP_MASK_DEFAULT.
+ * doc/invoke.texi (ix86 Options, -mrecip): Document that GCC
+ implements vectorized single float division and vectorized sqrtf(x)
+ with reciprocal sequence with additional Newton-Raphson step with
+ -ffast-math.
+
+2011-10-20 Dodji Seketeli <dodji@redhat.com>
+
+ * ggc-zone.c (ggc_internal_alloc_zone_stat): Rename
+ ggc_alloced_size_order_for_request into ggc_round_alloc_size like
+ it was done in ggc-page.c.
+
+ PR other/50659
+ * doc/cppopts.texi: Use @smallexample/@end smallexample in
+ documentation for -fdebug-cpp instead of @quotation/@end quotation
+ that is not supported by contrib/texi2pod.pl.
+
+2011-10-19 Jan Hubicka <jh@suse.cz>
+
+ * ipa-inline.c (inline_small_functions): Always update all calles after
+ inlining.
+
+2011-10-19 Jan Hubicka <jh@suse.cz>
+
+ PR bootstrap/50709
+ * ipa-inline.c (inline_small_functions): Fix checking code to not make
+ effect on fibheap stability.
+
+2011-10-20 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * config/m68k/t-linux (M68K_MLIB_CPU): Add ColdFire CPUs.
+
+2011-10-20 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
+
+ PR target/50106
+ * config/arm/arm.c (thumb_unexpanded_epilogue): Handle return
+ reg size from 1-3.
+
+2011-10-20 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-loop-im.c (stmt_cost): Add WIDEN_*, FMA_EXPR
+ and rotates to the set of expensive operations.
+
+2011-10-19 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.c (sparc_expand_move): Use can_create_pseudo_p.
+ (sparc_emit_set_const32): Likewise.
+ (sparc_emit_set_const64_longway): Likewise.
+ (sparc_emit_set_const64): Likewise.
+ (sparc_legitimize_pic_address): Likewise.
+ (memory_ok_for_ldd): Likewise.
+
+2011-10-20 Dehao Chen <dehao@google.com>
+
+ * profile.c (compute_branch_probabilities): Compute and dump the
+ overlap between the static estimation and the instrumentation profile.
+ (OVERLAP_BASE): New macro.
+ (compute_frequency_overlap): New function
+
+2011-10-19 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (expand_vec_perm_vpshufb2_vpermq_even_odd): Use
+ d->op1 instead of d->op0 for the second vpshufb.
+ (expand_vec_perm_even_odd_1): For V8SImode fix vpshufd immediates.
+ (ix86_expand_vec_perm_const): If mask indicates two operands are
+ needed, but both are the same and expanding them as d.op0 == d.op1
+ failed, retry with d.op0 != d.op1.
+ (ix86_expand_vec_perm_builtin): Likewise. Handle sorry printing
+ also for d.nelt == 32.
+
+ PR middle-end/50754
+ * cfgexpand.c (expand_debug_expr): Handle WIDEN_LSHIFT_EXPR, ignore
+ VEC_PERM_EXPR.
+
+2011-10-19 Bernd Schmidt <bernds@codesourcery.com>
+
+ * regrename.h: New file.
+ * regrename.c: Include it. Also include "emit-rtl.h".
+ (struct du_head, struct du_chain, du_head_p DEF_VEC and
+ DEF_VEC_ALLOC_P): Move to regrename.h.
+ (do_replace): Remove declaration.
+ (insn_rr): New variable.
+ (cur_operand): New static variable.
+ (regrename_chain_from_id): Renamed from chain_from_id and no longer
+ static. All callers changed.
+ (record_operand_use): New static function.
+ (scan_rtx_reg): Use it.
+ (find_best_rename_reg): New function, broken out of rename_chains.
+ (rename_chains): Use it. Don't update chain regno and nregs here, ...
+ (regrename_do_replace): ... do it here instead. Renamed from
+ do_replace, and no longer static. All callers changed.
+ (regrename_analyze): No longer static. New arg bb_mask.
+ All callers changed. If bb_mask is nonzero, use it to limit the
+ number of basic blocks we analyze. If we failed to analyze a block,
+ clear insn operand data.
+ (record_out_operands): New arg insn_info. Update cur_operand if it is
+ nonnull.
+ (build_def_use): If insn_rr is nonnull, pass an insn_info to
+ record_out_operands, and update cur_operand here as well.
+ (regrename_init, regrename_finish): New functions.
+ (regrename_optimize): Use them.
+ * Makefile.in (regrename.o): Adjust dependencies.
+
+2011-10-19 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50769
+ * tree-ssa-tail-merge.c (replace_block_by): Calculate phi_vuse2
+ unconditionally. Handle case that phi_vuse2 is not an SSA_NAME. Add
+ dummy argument .MEM to phi when increasing number of arguments of phi by
+ redirecting edges to the block with phi.
+
+2011-10-19 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR bootstrap/50777
+ * configure.ac: Save and restore CXXFLAGS around
+ gcc_AC_CHECK_DECLS uses.
+ Check for madvise() declaration with g++ if --enable-build-with-cxx.
+ * configure: Regenerate.
+ * config.in: Regenerate.
+ * ggc-page.c (USING_MADVISE): Also check HAVE_DECL_MADVISE.
+
+2011-10-19 Alexandre Oliva <aoliva@redhat.com>
+
+ PR debug/49310
+ * var-tracking.c (loc_exp_dep, onepart_aux): New structs.
+ (variable_part): Replace offset with union.
+ (enum onepart_enum, onepart_enum_t): New.
+ (variable_def): Drop cur_loc_changed, add onepart.
+ (value_chain_def, const_value_chain): Remove.
+ (VAR_PART_OFFSET, VAR_LOC_1PAUX): New macros, with checking.
+ (VAR_LOC_DEP_LST, VAR_LOC_DEP_LSTP): New macros.
+ (VAR_LOC_FROM, VAR_LOC_DEPTH, VAR_LOC_DEP_VEC): Likewise.
+ (value_chain_pool, value_chains): Remove.
+ (dropped_values): New.
+ (struct parm_reg): Only if HAVE_window_save.
+ (vt_stack_adjustments): Don't record register arguments.
+ (dv_as_rtx): New.
+ (dv_onepart_p): Return a onepart_enum_t.
+ (onepart_pool): New.
+ (dv_pool): Remove.
+ (dv_from_rtx): New.
+ (variable_htab_free): Release onepart aux data. Reset flags.
+ (value_chain_htab_hash, value_chain_htab_eq): Remove.
+ (unshare_variable): Use onepart field. Propagate onepart aux
+ data or offset. Drop cur_loc_changed.
+ (val_store): Cope with NULL insn. Rephrase dump output. Check
+ for unsuitable locs. Add FIXME on using cselib locs.
+ (val_reset): Remove FIXME of unfounded concerns.
+ (val_resolve): Check for unsuitable locs. Add FIXME on using
+ cselib locs.
+ (variable_union): Use onepart field, adjust access to offset.
+ (NO_LOC_P): New.
+ (VALUE_CHANGED, DECL_CHANGED): Update doc.
+ (set_dv_changed): Clear NO_LOC_P when changed.
+ (find_loc_in_1pdv): Use onepart field.
+ (intersect_loc_chains): Likewise.
+ (unsuitable_loc): New.
+ (loc_cmp): Keep ENTRY_VALUEs at the end of the loc list.
+ (add_value_chain, add_value_chains): Remove.
+ (add_cselib_value_chains, remove_value_chain): Likewise.
+ (remove_value_chains, remove_cselib_value_chains): Likewise.
+ (canonicalize_loc_order_check): Use onepart. Drop cur_loc_changed.
+ (canonicalize_values_star, canonicalize_vars_star): Use onepart.
+ (variable_merge_over_cur): Likewise. Adjust access to offset.
+ Drop cur_loc_changed.
+ (variable_merge_over_src): Use onepart field.
+ (remove_duplicate_values): Likewise.
+ (variable_post_merge_new_vals): Likewise.
+ (find_mem_expr_in_1pdv): Likewise.
+ (dataflow_set_preserve_mem_locs): Likewise. Drop cur_loc_changed
+ and value chains.
+ (dataflow_set_remove_mem_locs): Likewise. Use VAR_LOC_FROM.
+ (variable_different_p): Use onepart field. Move onepart test out
+ of the loop.
+ (argument_reg_set): Drop.
+ (add_uses, add_stores): Preserve but do not record in dynamic
+ tables equivalences for ENTRY_VALUEs and CFA_based addresses.
+ Avoid unsuitable address expressions.
+ (EXPR_DEPTH): Unlimit.
+ (EXPR_USE_DEPTH): Repurpose PARAM_MAX_VARTRACK_EXPR_DEPTH.
+ (prepare_call_arguments): Use DECL_RTL_IF_SET.
+ (dump_var): Adjust access to offset.
+ (variable_from_dropped, recover_dropped_1paux): New.
+ (variable_was_changed): Drop cur_loc_changed. Use onepart.
+ Preserve onepart aux in empty_var. Recover empty_var and onepart
+ aux from dropped_values.
+ (find_variable_location_part): Special-case onepart. Adjust
+ access to offset.
+ (set_slot_part): Use onepart. Drop cur_loc_changed. Adjust
+ access to offset. Initialize onepaux. Drop value chains.
+ (delete_slot_part): Drop value chains. Use VAR_LOC_FROM.
+ (VEC (variable, heap), VEC (rtx, stack)): Define.
+ (expand_loc_callback_data): Drop dummy, cur_loc_changed,
+ ignore_cur_loc. Add expanding, pending, depth.
+ (loc_exp_dep_alloc, loc_exp_dep_clear): New.
+ (loc_exp_dep_insert, loc_exp_dep_set): New.
+ (notify_dependents_of_resolved_value): New.
+ (update_depth, vt_expand_var_loc_chain): New.
+ (vt_expand_loc_callback): Revamped.
+ (resolve_expansions_pending_recursion): New.
+ (INIT_ELCD, FINI_ELCD): New.
+ (vt_expand_loc): Use the new macros above. Drop ignore_cur_loc
+ parameter, adjust all callers.
+ (vt_expand_loc_dummy): Drop.
+ (vt_expand_1pvar): New.
+ (emit_note_insn_var_location): Operate on non-debug decls only.
+ Revamp multi-part cur_loc recomputation and one-part expansion.
+ Drop cur_loc_changed. Adjust access to offset.
+ (VEC (variable, heap)): Drop.
+ (changed_variables_stack, changed_values_stack): Drop.
+ (check_changed_vars_0, check_changed_vars_1): Remove.
+ (check_changed_vars_2, check_changed_vars_3): Remove.
+ (values_to_stack, remove_value_from_changed_variables): New.
+ (notify_dependents_of_changed_value, process_changed_values): New.
+ (emit_notes_for_changes): Revamp onepart updates.
+ (emit_notes_for_differences_1): Use onepart. Drop cur_loc_changed
+ and value chains. Propagate onepaux. Recover empty_var and onepaux
+ from dropped_values.
+ (emit_notes_for_differences_2): Drop value chains.
+ (emit_notes_in_bb): Adjust.
+ (vt_emit_notes): Drop value chains, changed_variables_stack.
+ Initialize and release dropped_values.
+ (create_entry_value): Revamp.
+ (vt_add_function_parameter): Use new interface.
+ (note_register_arguments): Remove.
+ (vt_initialize): Drop value chains and register arguments.
+ (vt_finalize): Drop value chains. Release windowed_parm_regs only
+ if HAVE_window_save.
+ * rtl.h: Document various pass-local uses of RTL flags.
+ * tree.h (DECL_RTL_KNOWN_SET): New.
+ * doc/invoke.texi (param max-vartrack-expr-depth): Update
+ description and default.
+
+2011-10-19 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50447
+ * config/avr/avr.md (cc): New alternative out_plus_noclobber.
+ (adjust_len): Ditto.
+ (addhi3): Don't pipe through short; use gen_int_mode instead.
+ Prior to reload, expand to gen_addhi3_clobber.
+ (*addhi3): Use avr_out_plus_noclobber if applicable, use
+ out_plus_noclobber in cc and adjust_len attribute.
+ (addhi3_clobber): 2 new RTL peepholes.
+ (addhi3_clobber): New insn.
+ * config/avr/avr-protos.h: (avr_out_plus_noclobber): New prototype.
+ * config/avr/avr.c (avr_out_plus_noclobber): New function.
+ (notice_update_cc): Handle CC_OUT_PLUS_NOCLOBBER.
+ (avr_out_plus_1): Tweak if only MSB is +/-1 and other bytes are 0.
+ Set cc0 to set_zn for adiw on 16-bit values.
+ (adjust_insn_length): Handle ADJUST_LEN_OUT_PLUS_NOCLOBBER.
+ (expand_epilogue): No need to add 0 to frame_pointer_rtx.
+
+2011-10-19 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50780
+ * tree-ssa-forwprop.c (forward_propagate_into_cond): Verify
+ the condition is properly gimple before using it.
+ * tree-eh (stmt_could_throw_1_p): Properly extract the
+ operation type from comparisons.
+
+2011-10-19 Roland Stigge <stigge@antcom.de>
+
+ PR translation/48638
+ * plugin.c (add_new_plugin): Fix typo in fatal_error message.
+
+2011-10-19 Roland Stigge <stigge@antcom.de>
+
+ PR translation/49517
+ * config/rx/rx.c (rx_print_operand): Fix typo in warning message.
+
+2011-10-19 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50768
+ * gimple-fold.c (gimplify_and_update_call_from_tree): Rewrite.
+
+2011-10-19 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/50340
+ * sel-sched-ir.c (update_target_availability): LHS register
+ availability is not known if the unavailable LHS of the other
+ expression is a different register.
+
+2011-10-19 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ PR target/50310
+ * config/spu/spu.c (spu_emit_vector_compare): Support unordered
+ floating-point comparisons.
+
+2011-10-19 Jan Hubicka <jh@suse.cz>
+
+ * cgraphunit.c (handle_alias_pairs): Also handle wekref with
+ destination declared.
+ (output_weakrefs): New function.
+ * varpool.c (varpool_create_variable_alias): Handle external aliases.
+
+2011-10-19 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (loc_descriptor): For SUBREG pass SUBREG_REG's mode as
+ second argument instead of mode.
+
+2011-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (ix86_expand_vec_perm): In merge_two use
+ mode SUBREG of operands[0] as target.
+ (valid_perm_using_mode_p): Don't ignore higher bits of d->perm.
+ (expand_vec_pshufb): For V8SImode vmode emit avx2_permvarv8si.
+ (expand_vec_perm_1): Handle identity and some broadcast
+ permutations.
+ (expand_vec_perm_interleave2): Handle also 32-byte modes, using
+ vperm2[fi]128 or vpunpck[lh]* followed by single insn permutation.
+ For d->testing_p return true earlier to avoid creating more GC
+ garbage.
+ (expand_vec_perm_vpermq_perm_1): New function.
+ (expand_vec_perm_vpshufb2_vpermq): For d->testing_p return true
+ earlier to avoid creating more GC garbage. Fix handling of
+ V16HImode. Avoid some SUBREGs in SET_DEST.
+ (expand_vec_perm_broadcast_1): Return false for 32-byte integer
+ vector modes.
+ (expand_vec_perm_vpshufb4_vpermq2): New function.
+ (ix86_expand_vec_perm_builtin_1): Call expand_vec_perm_vpermq_perm_1
+ and expand_vec_perm_vpshufb4_vpermq2.
+
+2011-10-18 Andrew Stubbs <ams@codesourcery.com>
+
+ * config/arm/driver-arm.c (host_detect_local_cpu): Close the file
+ before exiting.
+
+2011-10-18 Andrew Stubbs <ams@codesourcery.com>
+
+ PR tree-optimization/50717
+ * tree-ssa-math-opts.c (is_widening_mult_p): Remove the 'type'
+ parameter. Calculate 'type' from stmt.
+ (convert_mult_to_widen): Update call the is_widening_mult_p.
+ (convert_plusminus_to_widen): Likewise.
+
+2011-10-18 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * config/spu/spu.c (struct machine_function): New data structure.
+ (spu_init_machine_status): New function.
+ (spu_option_override): Install it.
+ (get_pic_reg): Set and use cfun->machine->pic_reg.
+ (spu_split_immediate): Do not set crtl->uses_pic_offset_table.
+ (need_to_save_reg): Use cfun->machine->pic_reg instead of
+ checking crtl->uses_pic_offset_table.
+ (spu_expand_prologue): Likewise.
+
+2011-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50735
+ * function.c (gimplify_parameters): Use create_tmp_var instead of
+ create_tmp_reg. If parm is not TREE_ADDRESSABLE and type is complex
+ or vector type, set DECL_GIMPLE_REG_P.
+
+2011-10-18 Andrew Stubbs <ams@codesourcery.com>
+
+ * config.host (arm*-*-linux*): Add driver-arm.o and x-arm.
+ * config/arm/arm.opt: Add 'native' processor_type and
+ arm_arch enum values.
+ * config/arm/arm.h (host_detect_local_cpu): New prototype.
+ (EXTRA_SPEC_FUNCTIONS): New define.
+ (MCPU_MTUNE_NATIVE_SPECS): New define.
+ (DRIVER_SELF_SPECS): New define.
+ * config/arm/driver-arm.c: New file.
+ * config/arm/x-arm: New file.
+ * doc/invoke.texi (ARM Options): Document -mcpu=native,
+ -mtune=native and -march=native.
+
+2011-10-18 Alexander Monakov <amonakov@ispras.ru>
+
+ PR rtl-optimization/50205
+ * sel-sched.c (count_occurrences_1): Simplify on the assumption that
+ p->x is a register. Forbid substitution when the same register is
+ found in a different mode.
+ (count_occurrences_equiv): Assert that 'what' is a register.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50767
+ * tree-ssa-pre.c (create_expression_by_pieces): Update the
+ folded statement.
+
+2011-10-18 Julian Brown <julian@codesourcery.com>
+
+ * config/arm/arm.c (arm_block_move_unaligned_straight)
+ (arm_adjust_block_mem, arm_block_move_unaligned_loop)
+ (arm_movmemqi_unaligned): New.
+ (arm_gen_movmemqi): Support unaligned block copies.
+
+2011-10-18 Ira Rosen <ira.rosen@linaro.org>
+
+ * doc/md.texi (vec_widen_ushiftl_hi, vec_widen_ushiftl_lo,
+ vec_widen_sshiftl_hi, vec_widen_sshiftl_lo): Document.
+ * tree-pretty-print.c (dump_generic_node): Handle WIDEN_LSHIFT_EXPR,
+ VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
+ (op_code_prio): Likewise.
+ (op_symbol_code): Handle WIDEN_LSHIFT_EXPR.
+ * optabs.c (optab_for_tree_code): Handle
+ VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
+ (init-optabs): Initialize optab codes for vec_widen_u/sshiftl_hi/lo.
+ * optabs.h (enum optab_index): Add OTI_vec_widen_u/sshiftl_hi/lo.
+ * genopinit.c (optabs): Initialize the new optabs.
+ * expr.c (expand_expr_real_2): Handle
+ VEC_WIDEN_LSHIFT_HI_EXPR and VEC_WIDEN_LSHIFT_LO_EXPR.
+ * gimple-pretty-print.c (dump_binary_rhs): Likewise.
+ * tree-vectorizer.h (NUM_PATTERNS): Increase to 8.
+ * tree.def (WIDEN_LSHIFT_EXPR, VEC_WIDEN_LSHIFT_HI_EXPR,
+ VEC_WIDEN_LSHIFT_LO_EXPR): New.
+ * cfgexpand.c (expand_debug_expr): Handle new tree codes.
+ * tree-vect-patterns.c (vect_vect_recog_func_ptrs): Add
+ vect_recog_widen_shift_pattern.
+ (vect_handle_widen_mult_by_const): Rename...
+ (vect_handle_widen_op_by_const): ...to this. Handle shifts.
+ Add a new argument, update documentation.
+ (vect_recog_widen_mult_pattern): Assume that only second
+ operand can be constant. Update call to
+ vect_handle_widen_op_by_const.
+ (vect_recog_over_widening_pattern): Fix typo.
+ (vect_recog_widen_shift_pattern): New.
+ * tree-vect-stmts.c (vectorizable_type_promotion): Handle
+ widening shifts.
+ (supportable_widening_operation): Likewise.
+ * tree-inline.c (estimate_operator_cost): Handle new tree codes.
+ * tree-vect-generic.c (expand_vector_operations_1): Likewise.
+ * tree-cfg.c (verify_gimple_assign_binary): Likewise.
+ * config/arm/neon.md (neon_vec_<US>shiftl_<mode>): New.
+ (vec_widen_<US>shiftl_lo_<mode>, neon_vec_<US>shiftl_hi_<mode>,
+ vec_widen_<US>shiftl_hi_<mode>, neon_vec_<US>shift_left_<mode>):
+ Likewise.
+ * config/arm/predicates.md (const_neon_scalar_shift_amount_operand):
+ New.
+ * config/arm/iterators.md (V_innermode): New.
+ * tree-vect-slp.c (vect_build_slp_tree): Require same shift operand
+ for widening shift.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-alias.h (struct pt_solution): Remove
+ vars_contains_restrict member.
+ (pt_solutions_same_restrict_base): Remove.
+ (pt_solution_set): Adjust.
+ * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Remove
+ vars_contains_restrict handling.
+ (dump_points_to_solution): Likewise.
+ (ptr_derefs_may_alias_p): Do not call pt_solutions_same_restrict_base.
+ * tree-ssa-structalias.c (struct variable_info): Remove is_restrict_var
+ field.
+ (new_var_info): Do not initialize it.
+ (ipa_escaped_pt): Adjust.
+ (make_constraint_from_restrict): Make the tag global.
+ (make_constraint_from_global_restrict): New function.
+ (make_constraint_from_heapvar): Remove.
+ (create_variable_info_for): Do not make restrict vars point
+ to NONLOCAL.
+ (intra_create_variable_infos): Likewise.
+ (find_what_var_points_to): Remove vars_contains_restrict handling.
+ (pt_solution_set): Adjust.
+ (pt_solution_ior_into): Likewise.
+ (pt_solutions_same_restrict_base): Remove.
+ (compute_points_to_sets): Do not test is_restrict_var.
+ * cfgexpand.c (update_alias_info_with_stack_vars): Adjust.
+ * gimple-pretty-print.c (pp_points_to_solution): Likewise.
+
+2011-10-18 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50672
+ * tree-ssa-dce.c (mark_virtual_operand_for_renaming): New function,
+ factored out of ...
+ (mark_virtual_phi_result_for_renaming): Use
+ mark_virtual_operand_for_renaming.
+ * tree-flow.h (mark_virtual_operand_for_renaming): Declare.
+ * tree-ssa-tail-merge.c (release_last_vdef): New function.
+ (purge_bbs): Add update_vops parameter. Call release_last_vdef for each
+ deleted basic block.
+ (tail_merge_optimize): Add argument to call to purge_bbs.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50716
+ * expr.c (get_object_or_type_alignment): New function.
+ (expand_assignment): Use it.
+ (expand_expr_real_1): Likewise.
+
+2011-10-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR bootstrap/50760
+ * input.c (dump_line_table_statistics): Use long, not size_t.
+
+2011-10-17 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sparc.md (in_call_delay): Fix formatting issues.
+
+2011-10-17 Simon Baldwin <simonb@google.com>
+ Ian Lance Taylor <iant@google.com>
+
+ * configure.ac: Add --with-native-system-header-dir. Set and
+ substitute NATIVE_SYSTEM_HEADER_DIR. Use native_system_header
+ when setting target_header_dir.
+ * config.gcc: Always set native_system_header_dir.
+ (*-*-gnu*): Set native_system_header_dir. Don't use t-gnu.
+ (i[34567]86-pc-msdosdjgpp*): Set native_system_header_dir. Don't
+ use i386/t-djgpp.
+ (i[34567]86-*-mingw* | x86_64-*-mingw*): Set
+ native_system_header_dir.
+ (spu-*-elf*): Set native_system_header_dir.
+ * Makefile.in (NATIVE_SYSTEM_HEADER_DIR): Set to
+ @NATIVE_SYSTEM_HEADER_DIR@.
+ (PREPROCESSOR_DEFINES): Define NATIVE_SYSTEM_HEADER_DIR.
+ * cppdefault.c (STANDARD_INCLUDE_DIR): Don't define.
+ (NATIVE_SYSTEM_HEADER_COMPONENT): Rename from
+ STANDARD_INCLUDE_COMPONENT.
+ (cpp_include_defaults): Don't use SYSTEM_INCLUDE_DIR. Rename
+ STANDARD_INCLUDE_DIR to NATIVE_SYSTEM_HEADER_DIR.
+ * system.h: Poison SYSTEM_INCLUDE_DIR, STANDARD_INCLUDE_DIR, and
+ STANDARD_INCLUDE_COMPONENT.
+ * config/i386/t-mingw32 (NATIVE_SYSTEM_HEADER_DIR): Remove.
+ * config/i386/t-mingw-w32: Likewise.
+ * config/i386/t-mingw-w64: Likewise.
+ * config/spu/t-spu-elf: Likewise.
+ * config/i386/t-djgpp: Remove.
+ * config/t-gnu: Remove.
+ * config/i386/mingw32.h (STANDARD_INCLUDE_DIR): Don't define.
+ (NATIVE_SYSTEM_HEADER_COMPONENT): Rename from
+ STANDARD_INCLUDE_COMPONENT.
+ * config/i386/djgpp.h (STANDARD_INCLUDE_DIR): Don't define.
+ * config/spu/spu-elf.h: Likewise.
+ * config/vms/xm-vms.h: Likewise.
+ * config/gnu.h: Likewise.
+ * config/openbsd.h (INCLUDE_DEFAULTS): Change STANDARD_INCLUDE_DIR
+ and STANDARD_INCLUDE_COMPONENT to NATIVE_SYSTEM_HEADER_DIR and
+ NATIVE_SYSTME_HEADER_COMPONENT.
+ * doc/install.texi (Configuration): Document
+ --with-native-system-header-dir. Mention it in the documentation
+ for --with-sysroot and --with-build-sysroot.
+ * doc/tm.texi.in (Driver): Don't document SYSTEM_INCLUDE_DIR or
+ STANDARD_INCLUDE_DIR. Rename STANDARD_INCLUDE_COMPONENT to
+ NATIVE_SYSTEM_HEADER_COMPONENT. Rename uses of
+ STANDARD_INCLUDE_DIR to NATIVE_SYSTEM_HEADER_DIR.
+ * doc/fragments.texi (Target Fragment): Don't document
+ NATIVE_SYSTEM_HEADER_DIR.
+ * configure, doc/tm.texi: Rebuild.
+
+2011-10-17 Richard Henderson <rth@redhat.com>
+
+ * config/sparc/sparc.md: Use register_or_zero_operand where rJ
+ is the constraint.
+
+ * config/sparc/sparc.md (vec_perm_constv8qi, vec_perm<mode>): New
+ patterns.
+ * config/sparc/sparc.c (sparc_expand_vec_perm_bmask): New function.
+ * config/sparc/sparc-protos.h (sparc_expand_vec_perm_bmask): Declare.
+
+2011-10-17 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc-modes.def: Add single entry vector modes for
+ DImode and SImode.
+ * config/sparc/sparc.md (V32, V32I, V64, V64I, V64N8): Delete
+ mode iterators.
+ (mov<V32:mode>): Revert back to plain SFmode pattern.
+ (*movsf_insn): Likewise.
+ (mov<V64:mode>): Revert back to plain DFmode pattern.
+ (*movdf_insn_sp32): Likewise.
+ (*movdf_insn_sp32_v9): Likewise.
+ (*movdf_insn_sp64): Likewise.
+ (V64 mode splitters) Likewise.
+ (addsi3): Remove VIS alternatives.
+ (subsi3): Likewise.
+ (and<V64I:mode>3): Revert to DImode only pattern.
+ (and<V64I:mode>3_sp32): Likewise.
+ (*and<V64I:mode>3_sp64): Likewise.
+ (and<V32I:mode>3): Likewise.
+ (*and_not_<V64I:mode>_sp32): Likewise.
+ (*and_not_<V64I:mode>_sp64): Likewise.
+ (*and_not_<V32I:mode>): Likewise.
+ (ior<V64I:mode>3): Likewise.
+ (*ior<V64I:mode>3_sp32): Likewise.
+ (*ior<V64I:mode>3_sp64): Likewise.
+ (ior<V32I:mode>3): Likewise.
+ (*or_not_<V64I:mode>_sp32): Likewise.
+ (*or_not_<V64I:mode>_sp64): Likewise.
+ (*or_not_<V32I:mode>): Likewise.
+ (xor<V64I:mode>3): Likewise.
+ (*xor<V64I:mode>3_sp32): Likewise.
+ (*xor<V64I:mode>3_sp64): Likewise.
+ (xor<V32I:mode>3): Likewise.
+ (V64I mode splitters): Likewise.
+ (*xor_not_<V64I:mode>_sp32): Likewise.
+ (*xor_not_<V64I:mode>_sp64): Likewise.
+ (*xor_not_<V32I:mode>): Likewise.
+ (one_cmpl<V64I:mode>2): Likewise.
+ (*one_cmpl<V64I:mode>2_sp32): Likewise.
+ (*one_cmpl<V64I:mode>2_sp64): Likewise.
+ (one_cmpl<V32I:mode>2): Likewise.
+ (VM32, VM64, VMALL): New mode iterators.
+ (vbits, vconstr, vfptype): New mode attributes.
+ (mov<VMALL:mode>): New expander.
+ (*mov<VM32:mode>_insn): New insn.
+ (*mov<VM64:mode>_insn_sp64): New insn.
+ (*mov<VM64:mode>_insn_sp32): New insn, and associated splitter
+ specifically for the register to memory case.
+ (vec_init<mode>): New expander.
+ (VADDSUB): New mode iterator.
+ (<plusminus_insn>v2si3, <plusminus_insn>v2hi3): Remove and replace
+ with...
+ (<plusminus_insn><mode>3): New consolidated pattern.
+ (VL): New mode iterator for logical operations.
+ (vlsuf): New more attribute.
+ (vlop): New code iterator.
+ (vlinsn, vlninsn): New code attributes.
+ (<code><mode>3): New insn to non-negated vector logical ops.
+ (*not_<code><mode>3): Likewise for negated variants.
+ (*nand<mode>_vis): New insn.
+ (vlnotop): New code iterator.
+ (*<code>_not1<mode>_vis, *<code>_not2<mode>_vis): New insns.
+ (one_cmpl<mode>2): New insn.
+ (faligndata<V64I:mode>_vis): Rewrite to use VM64 iterator.
+ (bshuffle<VM64:mode>_vis): Likewise.
+ (v<vis3_shift_patname><mode>3): Use GCM mode iterator.
+ (fp<plusminus_insn>64_vis): Use V1DI mode.
+ (VASS mode iterator): Use V1SI not SI mode.
+ * config/sparc/sparc.c (sparc_vis_init_builtins): Account for
+ single-entry vector mode changes.
+ (sparc_expand_builtin): Likewise.
+ (sparc_expand_vector_init): New function.
+ * config/sparc/sparc-protos.h (sparc_expand_vector_init): Declare.
+
+2011-10-17 Kai Tietz <ktietz@redhat.com>
+
+ * fold-const.c (simple_operand_p_2): New function.
+ (fold_truthop): Rename to
+ (fold_truth_andor_1): function name.
+ Additionally remove branching creation for logical and/or.
+ (fold_truth_andor): Handle branching creation for logical and/or here.
+
+2011-10-17 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page.c (USING_MADVISE): Adjust ifdef to check for USING_MMAP.
+
+2011-10-17 Georg-Johann Lay <avr@gjlay.de>
+
+ * config/avr/avr.h (ASSEMBLER_DIALECT): Remove.
+ * config/avr/avr.md (mcu_have_movw, mcu_mega): Remove attributes.
+ (adjust_len): Add alternative "call".
+ (isa, enabled): New insn attributes.
+ (length): Use match_test with AVR_HAVE_JMP_CALL instead of
+ mcu_mega attribute.
+ (*sbrx_branch<mode>): Ditto.
+ (*sbrx_and_branch<mode>): Ditto.
+ (*sbix_branch): Ditto.
+ (*sbix_branch_bit7): Ditto.
+ (*sbix_branch_tmp): Ditto.
+ (*sbix_branch_tmp_bit7): Ditto.
+ (jump): Ditto.
+ (negsi2): Use attribute "isa" instead of assembler dialect.
+ (extendhisi2): Ditto.
+ (call_insn, call_value_insn): Set adjust_len attribute.
+ (indirect_jump): Indent to coding rules.
+ (call_prologue_saves): Use isa attribute instead of mcu_mega.
+ (epilogue_restores): Ditto. Fix setting of SP as described in the
+ RTX pattern.
+ (*indirect_jump): Fusion of *jcindirect_jump, *njcindirect_jump
+ and *indirect_jump_avr6.
+ (*tablejump): Fusion of *tablejump_rjmp and *tablejump_lib.
+ (*jcindirect_jump, *njcindirect_jump, *indirect_jump_avr6): Remove.
+ (*tablejump_rjmp, *tablejump_lib): Remove.
+ * config/avr/avr.c (adjust_insn_length): Handle ADJUST_LEN_CALL.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50757
+ * doc/invoke.texi ([Wnonnull]): Update.
+
+2011-10-17 Richard Henderson <rth@redhat.com>
+
+ PR 50746
+ * optabs.c (expand_vec_perm_expr): Fix indexing error.
+
+2011-10-17 Sergio Durigan Junior <sergiodj@redhat.com>
+
+ * configure.ac: Display `yes' if the SystemTap header has been found.
+ * configure: Regenerate.
+
+2011-10-08 Andi Kleen <ak@linux.intel.com>
+
+ PR other/50636
+ * config.in, configure: Regenerate.
+ * configure.ac (madvise): Add to AC_CHECK_FUNCS.
+ * ggc-page.c (USING_MADVISE): Add.
+ (page_entry): Add discarded field.
+ (alloc_page): Check for discarded pages.
+ (release_pages): Add USING_MADVISE branch.
+
+2011-10-17 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50729
+ * tree-vrp.c (extract_range_from_unary_expr_1): Remove redundant test.
+ (simplify_conversion_using_ranges): Properly test the
+ intermediate result.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * ggc.h (ggc_round_alloc_size): Declare new public entry point.
+ * ggc-none.c (ggc_round_alloc_size): New public stub function.
+ * ggc-page.c (ggc_alloced_size_order_for_request): New static
+ function. Factorized from ggc_internal_alloc_stat.
+ (ggc_round_alloc_size): New public function. Uses
+ ggc_alloced_size_order_for_request.
+ (ggc_internal_alloc_stat): Use ggc_alloced_size_order_for_request.
+ * ggc-zone.c (ggc_round_alloc_size): New public function extracted
+ from ggc_internal_alloc_zone_stat.
+ (ggc_internal_alloc_zone_stat): Use ggc_round_alloc_size.
+ * toplev.c (general_init): Initialize
+ line_table->alloced_size_for_request.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * input.c (ONE_K, ONE_M, SCALE, STAT_LABEL, FORMAT_AMOUNT): New macros.
+ (num_expanded_macros_counter, num_macro_tokens_counter): Declare
+ new counters.
+ (dump_line_table_statistics): Define new function.
+ * input.h (dump_line_table_statistics): Declare new function.
+ * toplev.c (dump_memory_report): Call dump_line_table_statistics.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * doc/cppopts.texi: Document -fdebug-cpp.
+ * doc/invoke.texi: Add -fdebug-cpp to the list of preprocessor options.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * gcc/diagnostic.h (diagnostic_report_current_module): Add a
+ location parameter.
+ * diagnostic.c (diagnostic_report_current_module): Add a location
+ parameter to the function definition. Use it instead of
+ input_location. Resolve the virtual location rather than just
+ looking up its map and risking to touch a resulting macro map.
+ (default_diagnostic_starter): Pass the relevant diagnostic
+ location to diagnostic_report_current_module.
+ * tree-diagnostic.c (maybe_unwind_expanded_macro_loc): New.
+ (virt_loc_aware_diagnostic_finalizer): Likewise.
+ (diagnostic_report_current_function): Pass the
+ relevant location to diagnostic_report_current_module.
+ * tree-diagnostic.h (virt_loc_aware_diagnostic_finalizer): Declare
+ new function.
+ * toplev.c (general_init): By default, use the new
+ virt_loc_aware_diagnostic_finalizer as diagnostic finalizer.
+ * Makefile.in: Add vec.h dependency to tree-diagnostic.c.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * doc/cppopts.texi (-ftrack-macro-expansion): Document new option.
+ * doc/invoke.texi (-ftrack-macro-expansion): Add this to the list of
+ preprocessor related options.
+
+2011-10-15 Tom Tromey <tromey@redhat>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * input.h (struct expanded_location): Move to libcpp/line-map.h.
+ (LOCATION_COLUMN): New accessor
+ (in_system_header_at): Use linemap_location_in_system_header_p.
+ * diagnostic.c (diagnostic_report_current_module): Adjust to avoid
+ touching the internals of struct line_map. Use the public API instead.
+ (diagnostic_report_diagnostic): Don't use relational operator '<'
+ on virtual locations. Use linemap_location_before_p instead.
+ * input.c (expand_location): Adjust to expand to the tokens'
+ spelling location when macro location tracking is on.
+
+
+2011-10-08 Andi Kleen <ak@linux.intel.com>
+
+ * ggc-page.c (GGC_QUIRE_SIZE): Increase to 512
+
+2011-10-13 Andi Kleen <ak@linux.intel.com>
+
+ * toplev.c (compile_file): Rename __gnu_slim_lto to __gnu_lto_slim.
+
+2011-10-16 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50727
+ * tree-vect-patterns.c (vect_operation_fits_smaller_type): Add
+ DEF_STMT to the list of statements to be replaced by the
+ pattern statements.
+
+2011-10-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR rtl-optimization/50615
+ * combine.c (distribute_notes) <REG_ARGS_SIZE>: Skip if I3 is a no-op.
+
+2011-10-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50596
+ * tree-vectorizer.h (NUM_PATTERNS): Increase to 7.
+ * tree-vect-patterns.c (vect_vect_recog_func_ptrs): Add
+ vect_recog_bool_pattern.
+ (check_bool_pattern, adjust_bool_pattern_cast,
+ adjust_bool_pattern, vect_recog_bool_pattern): New functions.
+
+2011-10-16 Ira Rosen <ira.rosen@linaro.org>
+
+ * tree-vect-stmts.c (vectorizable_load): For SLP without permutation
+ treat the first load of the node as the first element in its
+ interleaving chain.
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): Swap the operands if
+ necessary and possible.
+ (vect_build_slp_tree): Add new argument. Allow load groups of any size
+ in basic blocks. Keep all the loads for further permutation check.
+ Use the new argument to determine if there is a permutation. Update
+ the recursive calls.
+ (vect_supported_load_permutation_p): Allow subchains of interleaving
+ chains in basic block vectorization.
+ (vect_analyze_slp_instance): Update the call to vect_build_slp_tree.
+ Check load permutation based on the new parameter.
+ (vect_schedule_slp_instance): Don't start from the first element in
+ interleaving chain unless the loads are permuted.
+
+2011-10-15 Jan Hubicka <jh@suse.cz>
+
+ PR target/48668
+ PR target/50689
+ * cgraphunit.c (cgraph_expand_function): Expand thunks and alises
+ after function body.
+
+2011-10-15 Richard Henderson <rth@redhat.com>
+
+ * tree-vect-slp.c: Include langhooks.h.
+ (vect_create_mask_and_perm): Emit VEC_PERM_EXPR, not a builtin.
+ (vect_transform_slp_perm_load): Use can_vec_perm_expr_p. Simplify
+ mask creation for VEC_PERM_EXPR.
+ * tree-vect-stmts.c (perm_mask_for_reverse): Return the mask,
+ not the builtin.
+ (reverse_vec_elements): Emit VEC_PERM_EXPR not a builtin.
+ * Makefile.in (tree-vect-slp.o): Update dependency.
+ * optabs.c (can_vec_perm_expr_p): Allow NULL as unknown constant.
+
+2011-10-15 Alan Modra <amodra@gmail.com>
+
+ PR bootstrap/50738
+ * ifcvt.c (dead_or_predicable): Revert accidental commit with
+ HAVE_simple_return test.
+
+2011-10-15 Alan Modra <amodra@gmail.com>
+
+ * ifcvt.c (dead_or_predicable): Disable if-conversion when
+ doing so is likely to kill a shrink-wrapping opportunity.
+
+ PR rtl-optimization/49941
+ * jump.c (mark_jump_label_1): Set JUMP_LABEL for simple_return jumps.
+
+ * rtl.h (set_return_jump_label): Declare.
+ * function.c (set_return_jump_label): New function, extracted..
+ (thread_prologue_and_epilogue_insns): ..from here. Use it in
+ another instance to set return jump_label.
+ * cfgrtl.c (force_nonfallthru_and_redirect): Use set_return_jump_label.
+ * reorg.c (find_end_label): Likewise.
+
+2011-10-14 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sol2.h: Protect -m{cpu,tune}=native handling
+ with a more complete cpp test.
+ * config/sparc/linux64.h: Likewise.
+ * config/sparc/linux.h: Likewise.
+ * config/sparc/sparc.opt (sparc_debug): New target variable.
+ (mdebug): New target option.
+ * config/sparc/sparc.h (MASK_DEBUG_OPTIONS, MASK_DEBUG_ALL,
+ TARGET_DEBUG_OPTIONS): New defines.
+ * config/sparc/sparc.c (debug_target_flag_bits,
+ debug_target_flags): New functions.
+ (sparc_option_override): Add name strings back to cpu_table[].
+ Parse -mdebug string. When TARGET_DEBUG_OPTIONS is true, print
+ out the target flags before and after override processing as well
+ as the selected cpu. If MASK_V8PLUS, make sure that the selected
+ cpu is at least v9.
+
+2011-10-15 Oleg Endo <oleg.endo@t-online.de>
+
+ PR target/49263
+ * config/sh/sh.h (ZERO_EXTRACT_ANDMASK): New macro.
+ * config/sh/sh.c (sh_rtx_costs): Add test instruction case.
+ * config/sh/sh.md (tstsi_t): Name existing insn. Make inner
+ and instruction commutative.
+ (tsthi_t, tstqi_t, tstqi_t_zero, tstsi_t_and_not,
+ tstsi_t_zero_extract_eq, tstsi_t_zero_extract_xor,
+ tstsi_t_zero_extract_subreg_xor_little,
+ tstsi_t_zero_extract_subreg_xor_big): New insns.
+ (*movsicc_t_false, *movsicc_t_true): Replace space with tab in
+ asm output.
+ (*andsi_compact): Reorder alternatives so that K08 is considered first.
+
+2011-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/50354
+ * config/sparc/linux64.h (TARGET_DEFAULT): Only override if the default
+ processor is at least V9 and TARGET_64BIT_DEFAULT is defined.
+
+2011-10-14 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * invoke.texi (AVR Options): Avoid \leq{}.
+
+2011-10-14 Kai Tietz <ktietz@redhat.com>
+
+ * gimplify.c (gimplify_expr): Take care that for bitwise-binary
+ transformation the operands have compatible types.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (vec_widen_smult_hi_v8hi,
+ vec_widen_smult_lo_v8hi, vec_widen_umult_hi_v8hi,
+ vec_widen_umult_lo_v8hi): Macroize using VI2_AVX2
+ mode iterator and any_extend code iterator.
+ (vec_widen_<s>mult_hi_v8si, vec_widen_<s>mult_lo_v8si): New expanders.
+ (vec_widen_smult_hi_v4si, vec_widen_smult_lo_v4si): Enable
+ also for TARGET_SSE4_1 using pmuldq insn.
+ (sdot_prodv8hi): Macroize using VI2_AVX2 iterator.
+ (sse2_sse4_1): New code attr.
+ (udot_prodv4si): Macroize using any_extend code iterator.
+ (<s>dot_prodv8si): New expander.
+
+2011-10-14 Yakovlev Vladimir <vladimir.b.yakovlev@intel.com>
+
+ * config/i386/i386.c (atom_cost): Changed cost for loading
+ QImode using movzbl.
+
+2011-10-14 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_init_builtins): Fix typo in my
+ change on October 11th, 2011.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (vec_interleave_high<mode>,
+ vec_interleave_low<mode>): Add AVX2 expanders for VI_256 modes.
+ * config/i386/i386.c (expand_vec_perm_interleave3): New function.
+ (ix86_expand_vec_perm_builtin_1): Call it.
+
+2011-10-14 Georg-Johann Lay <avr@gjlay.de>
+
+ Fix thinko from r179765
+ * config/avr/avr.c (avr_option_override): Don't override
+ flag_omit_frame_pointer if not actually needed.
+
+2011-10-14 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/46278
+ * doc/invoke.texi (AVR Options): Document -mstrict-X.
+
+ * config/avr/avr.opt (-mstrict-X): New option.
+ (avr_strict_X): New variable reflecting -mstrict-X.
+ * config/avr/avr.c (avr_reg_ok_for_addr_p): Add parameter
+ outer_code and pass it down to avr_regno_mode_code_ok_for_base_p.
+ (avr_legitimate_address_p): Pass outer_code to
+ avr_reg_ok_for_addr_p and use that function in case PLUS.
+ (avr_mode_code_base_reg_class): Depend on avr_strict_X.
+ (avr_regno_mode_code_ok_for_base_p): Ditto, and depend on outer_code.
+ (avr_option_override): Disable -fcaller-saves if -mstrict-X is on.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (neg<mode>2): Use VI_AVX2 iterator instead
+ of VI_128.
+
+ * config/i386/sse.md (mulv2di3): Macroize using VI8_AVX2 iterator.
+ (ashl<mode>3): Use VI248_AVX2 iterator instead of VI248_128.
+ Use <sseinsnmode> instead of TI in mode attr.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ * config/arm/linux-atomic-64bit.c: New (based on linux-atomic.c).
+ * config/arm/linux-atomic.c: Change comment to point to 64bit version.
+ (SYNC_LOCK_RELEASE): Instantiate 64bit version.
+ * config/arm/t-linux-eabi: Pull in linux-atomic-64bit.c.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ * config/arm/arm.c (arm_output_ldrex): Support ldrexd.
+ (arm_output_strex): Support strexd.
+ (arm_output_it): New helper to output it in Thumb2 mode only.
+ (arm_output_sync_loop): Support DI mode. Change comment to
+ not support const_int.
+ (arm_expand_sync): Support DI mode.
+ * config/arm/arm.h (TARGET_HAVE_LDREXBHD): Split into LDREXBH
+ and LDREXD.
+ * config/arm/iterators.md (NARROW): move from sync.md.
+ (QHSD): New iterator for all current ARM integer modes.
+ (SIDI): New iterator for SI and DI modes only.
+ * config/arm/sync.md (sync_predtab): New mode_attr.
+ (sync_compare_and_swapsi): Fold into sync_compare_and_swap<mode>.
+ (sync_lock_test_and_setsi): Fold into sync_lock_test_and_setsi<mode>.
+ (sync_<sync_optab>si): Fold into sync_<sync_optab><mode>.
+ (sync_nandsi): Fold into sync_nand<mode>.
+ (sync_new_<sync_optab>si): Fold into sync_new_<sync_optab><mode>.
+ (sync_new_nandsi): Fold into sync_new_nand<mode>.
+ (sync_old_<sync_optab>si): Fold into sync_old_<sync_optab><mode>.
+ (sync_old_nandsi): Fold into sync_old_nand<mode>.
+ (sync_compare_and_swap<mode>): Support SI & DI.
+ (sync_lock_test_and_set<mode>): Likewise.
+ (sync_<sync_optab><mode>): Likewise.
+ (sync_nand<mode>): Likewise.
+ (sync_new_<sync_optab><mode>): Likewise.
+ (sync_new_nand<mode>): Likewise.
+ (sync_old_<sync_optab><mode>): Likewise.
+ (sync_old_nand<mode>): Likewise.
+ (arm_sync_compare_and_swapsi): Turn into iterator on SI & DI.
+ (arm_sync_lock_test_and_setsi): Likewise.
+ (arm_sync_new_<sync_optab>si): Likewise.
+ (arm_sync_new_nandsi): Likewise.
+ (arm_sync_old_<sync_optab>si): Likewise.
+ (arm_sync_old_nandsi): Likewise.
+ (arm_sync_compare_and_swap<mode> NARROW): use sync_predtab, fix indent.
+ (arm_sync_lock_test_and_setsi<mode> NARROW): Likewise.
+ (arm_sync_new_<sync_optab><mode> NARROW): Likewise.
+ (arm_sync_new_nand<mode> NARROW): Likewise.
+ (arm_sync_old_<sync_optab><mode> NARROW): Likewise.
+ (arm_sync_old_nand<mode> NARROW): Likewise.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ PR target/48126
+ * config/arm/arm.c (arm_output_sync_loop): Move label before barrier.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ * config/arm/arm.h (TARGET_HAVE_DMB_MCR): MCR Not available in Thumb1.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * doc/invoke.texi ([Wformat-zero-length]): Tidy.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * gimple.c (walk_stmt_load_store_addr_ops): Call visit_addr also
+ on COND_EXPR/VEC_COND_EXPR comparison operands if they are ADDR_EXPRs.
+
+2011-10-14 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50723
+ * ipa-split.c (split_function): Use GSI_CONTINUE_LINKING.
+
+2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * gengtype.c (files_rules): Added rules for objc/objc-map.h and
+ objc/objc-map.c.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/17212
+ * doc/invoke.texi ([Wformat-zero-length]): Update.
+
+2011-10-14 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR bootstrap/50699
+ * config/darwin.c (darwin_patch_builtin): Adjust argument type. Only
+ build for powerpc targets. (darwin_patch_builtins): Only build for
+ powerpc targets.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (*avx_cvtdq2pd256_2): Rename to...
+ (avx_cvtdq2pd256_2): ... this.
+ (sseunpackfltmode): New mode attr.
+ (vec_unpacks_float_hi_v8hi, vec_unpacks_float_lo_v8hi,
+ vec_unpacku_float_hi_v8hi, vec_unpacku_float_lo_v8hi): Macroize
+ using VI2_AVX2 iterator.
+ (vec_unpacku_float_hi_v8si, vec_unpacku_float_lo_v8si): New expanders.
+
+2011-10-13 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (plusminus): New code iterator.
+ (plusminus_insn): New code attr.
+ (addv2si3, subv2si3, addv4hi3, subv4hi3, addv2hi3, subv2hi3): Merge
+ using plusminus and plusminus_insn.
+ (fpadd64_vis, fpsub64_vis): Likewise.
+
+2011-10-13 Richard Henderson <rth@redhat.com>
+
+ * doc/md.texi (vec_perm): Document fallback to byte permutation.
+ * genopinit.c (optabs): Add vec_perm_const.
+ * optabs.c (can_vec_perm_expr_p): Rename from expand_vec_perm_expr_p.
+ Reject non-vector modes. Allow fallback to byte permutation.
+ (expand_vec_perm_expr_1): Split out from ...
+ (expand_vec_perm_expr): ... here. Allow fallback to byte permutation.
+ * optabs.h (DOI_vec_perm_const, vec_perm_const_optab): New.
+ * tree-vect-generic.c (lower_vec_perm): Update for name change.
+
+2011-10-13 Richard Henderson <rth@redhat.com>
+
+ * config/rs6000/altivec.md (vec_permv16qi): New pattern.
+
+ * config/rs6000/spu.md (vec_permv16qi): New pattern.
+
+ * config/i386/i386.c (ix86_expand_vec_perm_const): New.
+ * config/i386/i386-protos.h: Update.
+ * config/i386/sse.md (VEC_PERM_CONST): New mode iterator.
+ (vec_perm_const<VEC_PERM_CONST>): New expander.
+
+ * optabs.c (expand_vector_broadcast): New.
+ (expand_binop): Expand scalar shifts of vectors to vector shifts
+ of vectors, if the former isn't supported.
+ * tree-vect-generic.c (expand_vector_operations_1): Don't do that
+ here; always simplify to scalar shift of vector if possible.
+
+ * config/rs6000/rs6000.c (rs6000_expand_vector_init): Fix mode
+ test for vector splat.
+
+2011-10-13 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (vec_set<mode>): Change V_128 iterator mode to V.
+
+2011-10-13 Jakub Jelinek <jakub@redhat.com>
+ Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa.c (maybe_optimize_var): Drop TREE_ADDRESSABLE from vector
+ or complex vars even if their DECL_UID is in not_reg_needs bitmap.
+
+2011-10-13 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (reduc_umin_v8hi): New pattern.
+ * config/i386/i386.c (ix86_build_const_vector): Handle
+ also V32QI, V16QI, V16HI and V8HI modes.
+ (emit_reduc_half): New function.
+ (ix86_expand_reduc): Use phminposuw insn for V8HImode UMIN.
+ Use emit_reduc_half helper function.
+
+2011-10-13 Lawrence Crowl <crowl@google.com>
+ Diego Novillo <dnovillo@google.com>
+
+ * lto-streamer-in.c (input_struct_function_base): Factor out of ...
+ (input_function): ... here.
+ * lto-streamer-out.c (output_struct_function_base): Factor out of ...
+ (output_function): ... here.
+
+2011-10-13 Gabriel Charette <gchare@google.com>
+ Diego Novillo <dnovillo@google.com>
+
+ * streamer-hooks.h (struct streamer_hooks): Add hooks
+ input_location and output_location.
+ * lto-streamer-in.c (lto_input_location): Use
+ streamer_hooks.input_location, if set.
+ * lto-streamer-out.c (lto_output_location): Use
+ streamer_hooks.output_location, if set.
+
+2011-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/invoke.texi (SPARC options): Document -mfix-at697f.
+ * config/sparc/sparc.opt (mfix-at697f): New option.
+ * config/sparc/sparc.c (TARGET_MACHINE_DEPENDENT_REORG): Define.
+ (sparc_reorg): New function.
+
+2011-10-13 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50712
+ * ipa-split.c (split_function): Always re-gimplify parameters
+ when they are not gimple vals before passing them. Properly
+ check for type compatibility.
+
+2011-10-13 Tom de Vries <tom@codesourcery.com>
+
+ * function.c (gimplify_parameters): Set number of arguments of call to
+ BUILT_IN_ALLOCA_WITH_ALIGN to 2.
+
+2011-10-13 Tom de Vries <tom@codesourcery.com>
+
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Set MEM_READONLY_P
+ for static const strings.
+ * varasm.c (build_constant_desc): Generate the memory location of the
+ constant using gen_const_mem.
+
+2011-10-13 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50698
+ * tree-data-ref.c (split_constant_offset_1): Also process
+ offsets of &MEM.
+
+2011-10-12 David S. Miller <davem@davemloft.net>
+
+ * config/sparc/sparc.md (UNSPEC_FPMERGE): Delete.
+ (UNSPEC_MUL16AU, UNSPEC_MUL8, UNSPEC_MUL8SU, UNSPEC_MULDSU): New
+ unspecs.
+ (fpmerge_vis): Remove inaccurate comment, represent using vec_select
+ of a vec_concat.
+ (vec_interleave_lowv8qi, vec_interleave_highv8qi): New insns.
+ (fmul8x16_vis, fmul8x16au_vis, fmul8sux16_vis, fmuld8sux16_vis):
+ Reimplement as unspecs and remove inaccurate comments.
+ (vis3_shift_patname): New code attr.
+ (<vis3_shift_insn><vbits>_vis): Rename to
+ "v<vis3_shift_patname><mode>3".
+ (vis3_addsub_ss_patname): New code attr.
+ (<vis3_addsub_ss_insn><vbits>_vis): Rename to
+ "<vis3_addsub_ss_patname><mode>3".
+ * config/sparc/sparc.c (sparc_vis_init_builtins): Update to
+ accommodate pattern name changes.
+
+ * config/sparc/sparc.h: Do not force TARGET_VIS3 and TARGET_FMAF
+ to zero when assembler lacks support for such instructions.
+ * config/sparc/sparc.c (sparc_option_override): Clear MASK_VIS3
+ and MASK_FMAF in defaults when assembler lacks necessary support.
+
+2011-10-12 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/sse.md (vec_unpacks_lo_<mode>,
+ vec_unpacks_hi_<mode>, vec_unpacku_lo_<mode>,
+ vec_unpacku_hi_<mode>): Change VI124_128 mode to VI124_AVX2.
+ * config/i386/i386.c (ix86_expand_sse_unpack): Handle
+ V32QImode, V16HImode and V8SImode for TARGET_AVX2.
+
+ * config/i386/sse.md (vec_avx2): New mode_attr.
+ (mulv16qi3): Macroize to cover also mulv32qi3 for TARGET_AVX2 into ...
+ (mul<mode>3): ... this.
+
+ * config/i386/i386.md (UNSPEC_VPERMDI): Remove.
+ * config/i386/i386.c (ix86_expand_vec_perm): Handle
+ V16QImode and V32QImode for TARGET_AVX2.
+ (MAX_VECT_LEN): Increase to 32.
+ (expand_vec_perm_blend): Add support for 32-byte integer
+ vectors with TARGET_AVX2.
+ (valid_perm_using_mode_p): New function.
+ (expand_vec_perm_pshufb): Add support for 32-byte integer
+ vectors with TARGET_AVX2.
+ (expand_vec_perm_vpshufb2_vpermq): New function.
+ (expand_vec_perm_vpshufb2_vpermq_even_odd): New function.
+ (expand_vec_perm_even_odd_1): Handle 32-byte integer vectors
+ with TARGET_AVX2.
+ (ix86_expand_vec_perm_builtin_1): Try expand_vec_perm_vpshufb2_vpermq
+ and expand_vec_perm_vpshufb2_vpermq_even_odd.
+ * config/i386/sse.md (VEC_EXTRACT_EVENODD_MODE): Add for TARGET_AVX2
+ 32-byte integer vector modes.
+ (vec_pack_trunc_<mode>): Use VI248_AVX2 instead of VI248_128.
+ (avx2_interleave_highv32qi, avx2_interleave_lowv32qi): Remove pasto.
+ (avx2_pshufdv3, avx2_pshuflwv3, avx2_pshufhwv3): Generate
+ 4 new operands.
+ (avx2_pshufd_1, avx2_pshuflw_1, avx2_pshufhw_1): Don't use
+ match_dup, instead add 4 new operands and require they have
+ right cross-lane values.
+ (avx2_permv4di): Change into define_expand.
+ (avx2_permv4di_1): New instruction.
+ (avx2_permv2ti): Use nonimmediate_operand instead of register_operand
+ for "xm" constrained operand.
+ (VEC_PERM_AVX2): Add V32QI and V16QI for TARGET_AVX2.
+
+ * config/i386/sse.md (avx2_gathersi<mode>,
+ avx2_gatherdi<mode>, avx2_gatherdi<mode>256): Add clobber of
+ match_scratch, change memory_operand to register_operand,
+ add (mem:BLK (scratch)) use.
+ (*avx2_gathersi<mode>, *avx2_gatherdi<mode>,
+ *avx2_gatherdi<mode>256): Add clobber of match_scratch,
+ add earlyclobber to the output operand and match_scratch,
+ add (mem:BLK (scratch)) use, change the other mem to match_operand.
+ Use %p6 instead of %c6 in the pattern.
+ * config/i386/i386.c (ix86_expand_builtin): Adjust for
+ operand 2 being a Pmode register_operand instead of memory_operand.
+
+2011-10-12 Kai Tietz <ktietz@redhat.com>
+
+ * config/i386/i386.md (simple_return): Disable if TARGET_SEH is active.
+
+2011-10-12 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/ia64.c (ia64_init_builtins): Fix unbalanced parentheses.
+
+2011-10-12 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-alias.c (maybe_skip_until): Cache also at the point
+ of the first store we visit in a basic-block.
+ (get_continuation_for_phi): Search for a candidate VUSE that
+ might dominates all others. Do pairwise disambiguation against
+ that candidate.
+
+2011-10-12 Paul Koning <pkoning@gcc.gnu.org>
+
+ PR tree-optimization/50189
+ * tree-vrp.c (extract_range_from_assert): Use the type of
+ the variable, not the limit.
+
2011-10-12 Richard Guenther <rguenther@suse.de>
PR tree-optimization/50700
@@ -7,9 +3665,8 @@
2011-10-12 Bernd Schmidt <bernds@codesourcery.com>
* function.c (prepare_shrink_wrap, bb_active_p): New function.
- (thread_prologue_and_epilogue_insns): Use bb_active_p.
- Call prepare_shrink_wrap, then recompute bb_active_p for the
- last block.
+ (thread_prologue_and_epilogue_insns): Use bb_active_p. Call
+ prepare_shrink_wrap, then recompute bb_active_p for the last block.
2011-10-12 Joseph Myers <joseph@codesourcery.com>
@@ -189,7 +3846,8 @@
2011-10-11 Georg-Johann Lay <avr@gjlay.de>
- * config/avr/avr-protos.h (avr_mode_code_base_reg_class): New prototype.
+ * config/avr/avr-protos.h (avr_mode_code_base_reg_class): New
+ prototype.
(avr_regno_mode_code_ok_for_base_p): New prototype.
* config/avr/avr.h (BASE_REG_CLASS): Remove.
(REGNO_OK_FOR_BASE_P): Remove.
@@ -239,12 +3897,6 @@
(get_continuation_for_phi): ... here. Handle arbitrary number
of PHI args.
-2011-10-11 Paolo Carlini <paolo.carlini@oracle.com>
-
- PR c++/33067
- * c-family/c-pretty-print.c (pp_c_floating_constant): Output
- max_digits10 (in the ISO C++ WG N1822 sense) decimal digits.
-
2011-10-11 Richard Sandiford <richard.sandiford@linaro.org>
* modulo-sched.c: Fix comment typo. Mention the possibility
@@ -258,9 +3910,8 @@
2011-10-10 Georg-Johann Lay <avr@gjlay.de>
- * config/avr/avr.c (avr_option_override): Set
- flag_omit_frame_pointer to 0 if frame pointer is needed for
- unwinding.
+ * config/avr/avr.c (avr_option_override): Set flag_omit_frame_pointer
+ to 0 if frame pointer is needed for unwinding.
2011-10-10 Uros Bizjak <ubizjak@gmail.com>
@@ -405,8 +4056,7 @@
(get_sched_window): Adjust for above field and SCHED_* macro changes.
Use NODE_ASAP instead of SCHED_ASAP.
(try_scheduling_node_in_cycle): Remove node parameter. Update
- call to ps_add_node_check_conflicts. Pass ids to the SCHED_*
- macros.
+ call to ps_add_node_check_conflicts. Pass ids to the SCHED_* macros.
(sms_schedule_by_order): Update call to try_scheduling_node_in_cycle.
(ps_insert_empty_row): Adjust for above field changes.
(compute_split_row): Use ids rather than nodes.
@@ -541,16 +4191,33 @@
PR middle-end/50527
* tree.c (build_common_builtin_nodes): Add local_define_builtin for
+ BUILT_IN_ALLOCA_WITH_ALIGN. Mark that BUILT_IN_ALLOCA_WITH_ALIGN can
+ throw.
* builtins.c (expand_builtin_alloca): Handle BUILT_IN_ALLOCA_WITH_ALIGN
+ arglist. Set align for BUILT_IN_ALLOCA_WITH_ALIGN.
+ (expand_builtin): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
+ (is_inexpensive_builtin): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
* tree-ssa-ccp.c (evaluate_stmt): Set align for
+ BUILT_IN_ALLOCA_WITH_ALIGN.
+ (fold_builtin_alloca_for_var): Rename to ...
+ (fold_builtin_alloca_with_align): Set DECL_ALIGN from 2nd
+ BUILT_IN_ALLOCA_WITH_ALIGN argument.
+ (ccp_fold_stmt): Try folding BUILT_IN_ALLOCA_WITH_ALIGN using
+ fold_builtin_alloca_with_align.
+ (optimize_stack_restore): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
* builtins.def (BUILT_IN_ALLOCA_WITH_ALIGN): Declare using
+ DEF_BUILTIN_STUB.
* ipa-pure-const.c (special_builtin_state): Handle
+ BUILT_IN_ALLOCA_WITH_ALIGN.
* tree-ssa-alias.c (ref_maybe_used_by_call_p_1)
+ (call_may_clobber_ref_p_1): Same.
* function.c (gimplify_parameters): Lower vla to
+ BUILT_IN_ALLOCA_WITH_ALIGN.
* gimplify.c (gimplify_vla_decl): Same.
* cfgexpand.c (expand_call_stmt): Handle BUILT_IN_ALLOCA_WITH_ALIGN.
* tree-mudflap.c (mf_xform_statements): Same.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary)
+ (mark_all_reaching_defs_necessary_1, propagate_necessity): Same.
* varasm.c (incorporeal_function_p): Same.
* tree-object-size.c (alloc_object_size): Same.
* gimple.c (gimple_build_call_from_tree): Same.
@@ -18721,8 +22388,6 @@
2011-04-29 Jan Hubicka <jh@suse.cz>
- * gcc.dg/tree-ssa/inline-10.c: New testcase.
- * gcc.dg/tree-ssa/inline-9.c: Disable partial inlining.
* ipa-inline.h (clause_t): Turn into unsigned int.
* ipa-inline-analysis.c (add_clause): Do more simplification.
(and_predicates): Shortcut more cases.
@@ -24547,7 +28212,6 @@
* dwarf2asm.c (dw2_asm_output_encoded_addr_rtx): Add missing
va_end.
* c-family/c-common.c (def_fn_type): Likewise.
- * ada/gcc-interface/utils.c (def_fn_type): Likewise.
* emit-rtl.c (gen_rtvec): Likewise.
* lto/lto-lang.c (def_fn_type): Likewise.
diff --git a/gcc/ChangeLog.mm b/gcc/ChangeLog.mm
index 7b2a4da969d..a22c40bfc27 100644
--- a/gcc/ChangeLog.mm
+++ b/gcc/ChangeLog.mm
@@ -1,3 +1,7 @@
+2011-11-02 Aldy Hernandez <aldyh@redhat.com>
+
+ * Merge from trunk at revision 180790.
+
2011-11-02 Andrew MacLeod <amacleod@redhat.com>
* builtins.c (fold_builtin_atomic_always_lock_free): Add object param
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 1733141c50f..45f404307d2 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20111012
+20111102
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 9870f753f6d..22dae503b02 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -455,7 +455,7 @@ LINKER_PLUGIN_API_H = $(srcdir)/../include/plugin-api.h
LTO_SYMTAB_H = $(srcdir)/../include/lto-symtab.h
# Default native SYSTEM_HEADER_DIR, to be overridden by targets.
-NATIVE_SYSTEM_HEADER_DIR = /usr/include
+NATIVE_SYSTEM_HEADER_DIR = @NATIVE_SYSTEM_HEADER_DIR@
# Default cross SYSTEM_HEADER_DIR, to be overridden by targets.
CROSS_SYSTEM_HEADER_DIR = @CROSS_SYSTEM_HEADER_DIR@
@@ -490,8 +490,6 @@ md_file=$(srcdir)/config/@md_file@
tm_file_list=@tm_file_list@
tm_include_list=@tm_include_list@
tm_defines=@tm_defines@
-libgcc_tm_file_list=@libgcc_tm_file_list@
-libgcc_tm_include_list=@libgcc_tm_include_list@
tm_p_file_list=@tm_p_file_list@
tm_p_include_list=@tm_p_include_list@
build_xm_file_list=@build_xm_file_list@
@@ -534,9 +532,7 @@ lang_opt_files=@lang_opt_files@ $(srcdir)/c-family/c.opt $(srcdir)/common.opt
lang_specs_files=@lang_specs_files@
lang_tree_files=@lang_tree_files@
target_cpu_default=@target_cpu_default@
-GCC_THREAD_FILE=@thread_file@
OBJC_BOEHM_GC=@objc_boehm_gc@
-GTHREAD_FLAGS=@gthread_flags@
extra_modes_file=@extra_modes_file@
extra_opt_files=@extra_opt_files@
host_hook_obj=@out_host_hook_obj@
@@ -612,8 +608,6 @@ prefix_to_exec_prefix := \
dollar = @dollar@
# Used in install-cross.
gcc_tooldir = @gcc_tooldir@
-# Used to install the shared libgcc.
-slibdir = @slibdir@
# Since gcc_tooldir does not exist at build-time, use -B$(build_tooldir)/bin/
build_tooldir = $(exec_prefix)/$(target_noncanonical)
# Directory in which the compiler finds target-independent g++ includes.
@@ -673,32 +667,6 @@ ifeq ($(inhibit_libc),true)
INHIBIT_LIBC_CFLAGS = -Dinhibit_libc
endif
-# Options to use when compiling libgcc2.a.
-#
-LIBGCC2_DEBUG_CFLAGS = -g
-LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(INCLUDES_FOR_TARGET) $(GCC_CFLAGS) \
- $(TARGET_LIBGCC2_CFLAGS) $(LIBGCC2_DEBUG_CFLAGS) \
- $(GTHREAD_FLAGS) -DIN_LIBGCC2 \
- -fbuilding-libgcc -fno-stack-protector \
- $(INHIBIT_LIBC_CFLAGS)
-
-# Additional options to use when compiling libgcc2.a.
-# Some targets override this to -isystem include
-LIBGCC2_INCLUDES =
-
-# Additional target-dependent options for compiling libgcc2.a.
-TARGET_LIBGCC2_CFLAGS =
-
-# Options to use when compiling crtbegin/end.
-CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES_FOR_TARGET) $(MULTILIB_CFLAGS) \
- -g0 -finhibit-size-directive -fno-inline -fno-exceptions \
- -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
- -fno-stack-protector \
- $(INHIBIT_LIBC_CFLAGS)
-
-# nm flags to list global symbols in libgcc object files.
-SHLIB_NM_FLAGS = -pg
-
# List of extra executables that should be compiled for this target machine
# that are used for compiling from source code to object code.
# The rules for compiling them should be in the t-* file for the machine.
@@ -707,10 +675,6 @@ EXTRA_PASSES =@extra_passes@
# Like EXTRA_PASSES, but these are used when linking.
EXTRA_PROGRAMS = @extra_programs@
-# List of extra object files that should be compiled for this target machine.
-# The rules for compiling them should be in the t-* file for the machine.
-EXTRA_PARTS = @extra_parts@
-
# List of extra object files that should be compiled and linked with
# compiler proper (cc1, cc1obj, cc1plus).
EXTRA_OBJS = @extra_objs@
@@ -733,17 +697,6 @@ USE_GCC_STDINT = @use_gcc_stdint@
# set to empty.
COLLECT2 = @collect2@
-# List of extra C and assembler files to add to static and shared libgcc2.
-# Assembler files should have names ending in `.asm'.
-LIB2FUNCS_EXTRA =
-
-# List of extra C and assembler files to add to static libgcc2.
-# Assembler files should have names ending in `.asm'.
-LIB2FUNCS_STATIC_EXTRA =
-
-# List of functions not to build from libgcc2.c.
-LIB2FUNCS_EXCLUDE =
-
# Program to convert libraries.
LIBCONVERT =
@@ -806,17 +759,6 @@ RUNTEST = `if [ -f $${srcdir}/../dejagnu/runtest ] ; then \
else echo runtest; fi`
RUNTESTFLAGS =
-# Extra flags to use when compiling crt{begin,end}.o.
-CRTSTUFF_T_CFLAGS =
-
-# "t" or nothing, for building multilibbed versions of, say, crtbegin.o.
-T =
-
-# Should T contain a `=', libgcc/Makefile will make T_TARGET, setting
-# $(T_TARGET) to the name of the actual target filename.
-T_TARGET =
-T_TARGET : $(T_TARGET)
-
# This should name the specs file that we're going to install. Target
# Makefiles may override it and name another file to be generated from
# the built-in specs and installed as the default spec, as long as
@@ -844,8 +786,7 @@ CONFIG_H = config.h $(host_xm_file_list)
TCONFIG_H = tconfig.h $(xm_file_list)
TM_P_H = tm_p.h $(tm_p_file_list)
GTM_H = tm.h $(tm_file_list) insn-constants.h
-TM_H = $(GTM_H) libgcc_tm.h $(libgcc_tm_file_list) insn-flags.h \
- $(OPTIONS_H)
+TM_H = $(GTM_H) insn-flags.h $(OPTIONS_H)
# Variables for version information.
BASEVER := $(srcdir)/BASE-VER # 4.x.y
@@ -1104,9 +1045,6 @@ INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
$(CPPINC) $(GMPINC) $(DECNUMINC) \
$(PPLINC) $(CLOOGINC)
-INCLUDES_FOR_TARGET = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
- -I$(srcdir)/../include $(DECNUMINC) -I$(srcdir)/../libgcc
-
.c.o:
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
@@ -1129,15 +1067,12 @@ export DESTDIR
export GCC_FOR_TARGET
export INCLUDES
export INSTALL_DATA
-export LIB1ASMSRC
-export LIBGCC2_CFLAGS
export LIPO_FOR_TARGET
export MACHMODE_H
export NM_FOR_TARGET
export STRIP_FOR_TARGET
export RANLIB_FOR_TARGET
export libsubdir
-export slibdir
FLAGS_TO_PASS = \
"ADA_CFLAGS=$(ADA_CFLAGS)" \
@@ -1544,19 +1479,13 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
tree-check.h min-insn-modes.c insn-modes.c insn-modes.h \
genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \
- $(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
- $(SPECS) collect2$(exeext) lto-wrapper$(exeext) \
+ $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
+ $(SPECS) collect2$(exeext) gcc-ar$(exeext) gcc-nm$(exeext) \
+ gcc-ranlib$(exeext) \
gcov-iov$(build_exeext) gcov$(exeext) gcov-dump$(exeext) \
gengtype$(exeext) *.[0-9][0-9].* *.[si] *-checksum.c libbackend.a \
libcommon-target.a libcommon.a libgcc.mk
-# Defined in libgcc2.c, included only in the static library.
-LIB2FUNCS_ST = _eprintf __gcc_bcmp
-
-# 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
-
#
# Language makefile fragments.
@@ -1665,7 +1594,6 @@ config.h: cs-config.h ; @true
bconfig.h: cs-bconfig.h ; @true
tconfig.h: cs-tconfig.h ; @true
tm.h: cs-tm.h ; @true
-libgcc_tm.h: cs-libgcc_tm.h ; @true
tm_p.h: cs-tm_p.h ; @true
cs-config.h: Makefile
@@ -1688,11 +1616,6 @@ cs-tm.h: Makefile
HEADERS="$(tm_include_list)" DEFINES="$(tm_defines)" \
$(SHELL) $(srcdir)/mkconfig.sh tm.h
-cs-libgcc_tm.h: Makefile
- TARGET_CPU_DEFAULT="" \
- HEADERS="$(libgcc_tm_include_list)" DEFINES="" \
- $(SHELL) $(srcdir)/mkconfig.sh libgcc_tm.h
-
cs-tm_p.h: Makefile
TARGET_CPU_DEFAULT="" \
HEADERS="$(tm_p_include_list)" DEFINES="" \
@@ -1791,7 +1714,8 @@ rest.encap: lang.rest.encap
# This is what is made with the host's compiler
# whether making a cross compiler or not.
native: config.status auto-host.h build-@POSUB@ $(LANGUAGES) \
- $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext)
+ $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext) \
+ gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
ifeq ($(enable_plugin),yes)
native: gengtype$(exeext)
@@ -1876,52 +1800,13 @@ cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
#
# Build libgcc.a.
-LIB2ADD = $(LIB2FUNCS_EXTRA)
-LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
-
-# All source files for libgcc are either generated in the libgcc build
-# directory which will be substituted for $$(libgcc_objdir), in the
-# source directory (in which case they will start with $(srcdir)), or
-# generated into the build directory (in which case they will be
-# relative paths).
-srcdirify = $(patsubst $$(libgcc_objdir)/%,%, \
- $(filter $$(libgcc_objdir)%,$(1))) \
- $(patsubst $(srcdir)%,$$(gcc_srcdir)%,$(filter $(srcdir)%,$(1))) \
- $(patsubst %,$$(gcc_objdir)/%, \
- $(filter-out $(srcdir)% $$(libgcc_objdir)%,$(1)))
-
-# The distinction between these two variables is no longer relevant,
-# so we combine them. Sort removes duplicates.
-GCC_EXTRA_PARTS := $(sort $(EXTRA_MULTILIB_PARTS) $(EXTRA_PARTS))
-
libgcc-support: libgcc.mvars stmp-int-hdrs $(TCONFIG_H) \
- $(MACHMODE_H) $(LIB2ADD) $(LIB2ADD_ST) gcov-iov.h
+ $(MACHMODE_H) gcov-iov.h
-libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs \
- xgcc$(exeext)
+libgcc.mvars: config.status Makefile specs xgcc$(exeext)
: > tmp-libgcc.mvars
- echo LIB1ASMFUNCS = '$(LIB1ASMFUNCS)' >> tmp-libgcc.mvars
- echo LIB1ASMSRC = '$(LIB1ASMSRC)' >> tmp-libgcc.mvars
- echo LIB2FUNCS_ST = '$(LIB2FUNCS_ST)' >> tmp-libgcc.mvars
- echo LIB2FUNCS_EXCLUDE = '$(LIB2FUNCS_EXCLUDE)' >> tmp-libgcc.mvars
- echo LIB2ADD = '$(call srcdirify,$(LIB2ADD))' >> tmp-libgcc.mvars
- echo LIB2ADD_ST = '$(call srcdirify,$(LIB2ADD_ST))' >> tmp-libgcc.mvars
- echo LIB2_SIDITI_CONV_FUNCS = '$(LIB2_SIDITI_CONV_FUNCS)' >> tmp-libgcc.mvars
- echo LIB2_DIVMOD_FUNCS = '$(LIB2_DIVMOD_FUNCS)' >> tmp-libgcc.mvars
- echo GCC_EXTRA_PARTS = '$(GCC_EXTRA_PARTS)' >> tmp-libgcc.mvars
- echo SHLIB_LINK = '$(subst $(GCC_FOR_TARGET),$$(GCC_FOR_TARGET),$(SHLIB_LINK))' >> tmp-libgcc.mvars
- echo SHLIB_INSTALL = '$(SHLIB_INSTALL)' >> tmp-libgcc.mvars
- echo SHLIB_DLLDIR = '$(SHLIB_DLLDIR)' >> tmp-libgcc.mvars
- echo SHLIB_EXT = '$(SHLIB_EXT)' >> tmp-libgcc.mvars
- echo SHLIB_MKMAP = '$(call srcdirify,$(SHLIB_MKMAP))' >> tmp-libgcc.mvars
- echo SHLIB_MKMAP_OPTS = '$(SHLIB_MKMAP_OPTS)' >> tmp-libgcc.mvars
- echo SHLIB_MAPFILES = '$(call srcdirify,$(SHLIB_MAPFILES))' >> tmp-libgcc.mvars
- echo SHLIB_NM_FLAGS = '$(SHLIB_NM_FLAGS)' >> tmp-libgcc.mvars
- echo LIBGCC2_CFLAGS = '$(LIBGCC2_CFLAGS)' >> tmp-libgcc.mvars
- echo TARGET_LIBGCC2_CFLAGS = '$(TARGET_LIBGCC2_CFLAGS)' >> tmp-libgcc.mvars
- echo CRTSTUFF_CFLAGS = '$(CRTSTUFF_CFLAGS)' >> tmp-libgcc.mvars
- echo CRTSTUFF_T_CFLAGS = '$(CRTSTUFF_T_CFLAGS)' >> tmp-libgcc.mvars
- echo CRTSTUFF_T_CFLAGS_S = '$(CRTSTUFF_T_CFLAGS_S)' >> tmp-libgcc.mvars
+ echo GCC_CFLAGS = '$(GCC_CFLAGS)' >> tmp-libgcc.mvars
+ echo INHIBIT_LIBC_CFLAGS = '$(INHIBIT_LIBC_CFLAGS)' >> tmp-libgcc.mvars
echo TARGET_SYSTEM_ROOT = '$(TARGET_SYSTEM_ROOT)' >> tmp-libgcc.mvars
mv tmp-libgcc.mvars libgcc.mvars
@@ -1949,41 +1834,6 @@ s-mlib: $(srcdir)/genmultilib Makefile
fi
$(SHELL) $(srcdir)/../move-if-change tmp-mlib.h multilib.h
$(STAMP) s-mlib
-
-# 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.
-$(T)crtbegin.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
- gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
- $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
- -c $(srcdir)/crtstuff.c -DCRT_BEGIN \
- -o $(T)crtbegin$(objext)
-
-$(T)crtend.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
- gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
- $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
- -c $(srcdir)/crtstuff.c -DCRT_END \
- -o $(T)crtend$(objext)
-
-# These are versions of crtbegin and crtend for shared libraries.
-$(T)crtbeginS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
- gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
- $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS_S) \
- -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFS_O \
- -o $(T)crtbeginS$(objext)
-
-$(T)crtendS.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
- gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
- $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS_S) \
- -c $(srcdir)/crtstuff.c -DCRT_END -DCRTSTUFFS_O \
- -o $(T)crtendS$(objext)
-
-# This is a version of crtbegin for -static links.
-$(T)crtbeginT.o: crtstuff.c $(GCC_PASSES) $(TCONFIG_H) auto-host.h \
- gbl-ctors.h stmp-int-hdrs tsystem.h coretypes.h $(TM_H)
- $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) \
- -c $(srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O \
- -o $(T)crtbeginT$(objext)
#
# Compiling object files from source files.
@@ -2049,6 +1899,46 @@ sbitmap.o: sbitmap.c sbitmap.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(BASIC_BLOCK
ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_H)
sparseset.o: sparseset.c $(SYSTEM_H) sparseset.h $(CONFIG_H)
+AR_LIBS = @COLLECT2_LIBS@
+
+gcc-ar$(exeext): gcc-ar.o $(LIBDEPS)
+ +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ar.o -o $@ \
+ $(LIBS) $(AR_LIBS)
+
+gcc-nm$(exeext): gcc-nm.o $(LIBDEPS)
+ +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-nm.o -o $@ \
+ $(LIBS) $(AR_LIBS)
+
+gcc-ranlib$(exeext): gcc-ranlib.o $(LIBDEPS)
+ +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ranlib.o -o $@ \
+ $(LIBS) $(AR_LIBS)
+
+CFLAGS-gcc-ar.o += $(DRIVER_DEFINES) \
+ -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ar\"
+
+gcc-ar.o: gcc-ar.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+CFLAGS-gcc-ranlib.o += $(DRIVER_DEFINES) \
+ -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ranlib\"
+
+gcc-ranlib.o: gcc-ranlib.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+CFLAGS-gcc-nm.o += $(DRIVER_DEFINES) \
+ -DTARGET_MACHINE=\"$(target_noncanonical)\" \
+ @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"nm\"
+
+gcc-nm.o: gcc-nm.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+# ??? the implicit rules dont trigger if the source file has a different name
+# so copy instead
+gcc-ranlib.c: gcc-ar.c
+ cp $^ $@
+
+gcc-nm.c: gcc-ar.c
+ cp $^ $@
+
COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o
COLLECT2_LIBS = @COLLECT2_LIBS@
collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
@@ -2069,12 +1959,13 @@ collect2-aix.o : collect2-aix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(OBSTACK_H) collect2.h intl.h $(DIAGNOSTIC_CORE_H)
-lto-wrapper$(exeext): lto-wrapper.o $(LIBDEPS)
- +$(LINKER) $(ALL_COMPILERFLAGS) $(LDFLAGS) -o T$@ lto-wrapper.o $(LIBS)
+lto-wrapper$(exeext): lto-wrapper.o ggc-none.o libcommon-target.a $(LIBDEPS)
+ +$(LINKER) $(ALL_COMPILERFLAGS) $(LDFLAGS) -o T$@ \
+ lto-wrapper.o ggc-none.o libcommon-target.a $(LIBS)
mv -f T$@ $@
lto-wrapper.o: lto-wrapper.c $(CONFIG_H) $(SYSTEM_H) coretypes.h intl.h \
- $(OBSTACK_H) $(DIAGNOSTIC_H)
+ $(OBSTACK_H) $(DIAGNOSTIC_H) $(OPTS_H) $(OPTIONS_H)
# Files used by all variants of C.
c-family/c-common.o : c-family/c-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
@@ -2185,20 +2076,20 @@ DRIVER_DEFINES = \
-DTOOLDIR_BASE_PREFIX=\"$(libsubdir_to_prefix)$(prefix_to_exec_prefix)\" \
@TARGET_SYSTEM_ROOT_DEFINE@ \
$(VALGRIND_DRIVER_DEFINES) \
- `test "X$${SHLIB_LINK}" = "X" || test "@enable_shared@" != "yes" || echo "-DENABLE_SHARED_LIBGCC"` \
+ `test "X$${SHLIB}" = "X" || test "@enable_shared@" != "yes" || echo "-DENABLE_SHARED_LIBGCC"` \
-DCONFIGURE_SPECS="\"@CONFIGURE_SPECS@\""
gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h multilib.h \
Makefile $(lang_specs_files) specs.h prefix.h $(GCC_H) $(FLAGS_H) \
configargs.h $(OBSTACK_H) $(OPTS_H) $(DIAGNOSTIC_H) $(VEC_H) $(PARAMS_H)
- (SHLIB_LINK='$(SHLIB_LINK)'; \
+ (SHLIB='$(SHLIB)'; \
$(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
-c $(srcdir)/gcc.c $(OUTPUT_OPTION))
gccspec.o: gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
$(OPTS_H)
- (SHLIB_LINK='$(SHLIB_LINK)'; \
+ (SHLIB='$(SHLIB)'; \
$(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
-c $(srcdir)/gccspec.c $(OUTPUT_OPTION))
@@ -2753,7 +2644,7 @@ tree-vect-slp.o: tree-vect-slp.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \
$(EXPR_H) $(RECOG_H) $(OPTABS_H) $(TREE_VECTORIZER_H) tree-pretty-print.h \
- gimple-pretty-print.h $(TREE_DATA_REF_H)
+ gimple-pretty-print.h $(TREE_DATA_REF_H) langhooks.h
tree-vect-stmts.o: tree-vect-stmts.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
$(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) \
@@ -2805,7 +2696,8 @@ tree-pretty-print.o : tree-pretty-print.c $(CONFIG_H) $(SYSTEM_H) \
$(TM_H) coretypes.h tree-iterator.h $(SCEV_H) langhooks.h \
$(TREE_PASS_H) value-prof.h output.h tree-pretty-print.h
tree-diagnostic.o : tree-diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS_DEF_H)
+ $(TREE_H) $(DIAGNOSTIC_H) tree-diagnostic.h langhooks.h $(LANGHOOKS_DEF_H) \
+ $(VEC_H)
fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(FLAGS_H) $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) $(EXPR_H) $(RTL_H) \
$(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h $(TARGET_H) \
@@ -3171,7 +3063,7 @@ tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_FLOW_H) $(CONFIG_H) \
$(DBGCNT_H) tree-pretty-print.h gimple-pretty-print.h gimple-fold.h
tree-ssa-strlen.o : tree-ssa-strlen.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_FLOW_H) $(TREE_PASS_H) domwalk.h alloc-pool.h tree-ssa-propagate.h \
- gimple-pretty-print.h $(PARAMS_H)
+ gimple-pretty-print.h $(PARAMS_H) $(EXPR_H)
tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h alloc-pool.h \
$(TM_H) $(TREE_H) $(GIMPLE_H) $(CGRAPH_H) $(TREE_FLOW_H) \
$(IPA_PROP_H) $(DIAGNOSTIC_H) statistics.h $(TREE_DUMP_H) $(TIMEVAR_H) \
@@ -3505,7 +3397,8 @@ regcprop.o : regcprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_ERROR_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
output.h $(RECOG_H) $(FUNCTION_H) $(OBSTACK_H) $(FLAGS_H) $(TM_P_H) \
- addresses.h reload.h $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(TARGET_H)
+ addresses.h reload.h $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(TARGET_H) \
+ regrename.h $(EMIT_RTL_H)
ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(REGS_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) insn-config.h $(FUNCTION_H) $(RECOG_H) \
$(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h $(EXCEPT_H) $(TM_P_H) \
@@ -3535,7 +3428,8 @@ $(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) \
output.h $(INSN_ATTR_H) $(SYSTEM_H) toplev.h $(DIAGNOSTIC_CORE_H) \
$(TARGET_H) $(LIBFUNCS_H) $(TARGET_DEF_H) $(FUNCTION_H) $(SCHED_INT_H) \
$(TM_P_H) $(EXPR_H) langhooks.h $(GGC_H) $(OPTABS_H) $(REAL_H) \
- tm-constrs.h $(GIMPLE_H) $(DF_H) cselib.h $(COMMON_TARGET_H) hw-doloop.h
+ tm-constrs.h $(GIMPLE_H) $(DF_H) cselib.h $(COMMON_TARGET_H) hw-doloop.h \
+ regrename.h
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(out_file) $(OUTPUT_OPTION)
@@ -3954,7 +3848,8 @@ build/genautomata.o : genautomata.c $(RTL_BASE_H) $(OBSTACK_H) \
$(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(VEC_H) \
$(HASHTAB_H) gensupport.h $(FNMATCH_H)
build/gencheck.o : gencheck.c all-tree.def $(BCONFIG_H) $(GTM_H) \
- $(SYSTEM_H) coretypes.h $(lang_tree_files) gimple.def
+ $(SYSTEM_H) coretypes.h tree.def c-family/c-common.def \
+ $(lang_tree_files) gimple.def
build/genchecksum.o : genchecksum.c $(BCONFIG_H) $(SYSTEM_H) $(MD5_H)
build/gencodes.o : gencodes.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
coretypes.h $(GTM_H) errors.h gensupport.h
@@ -4074,6 +3969,7 @@ PREPROCESSOR_DEFINES = \
-DLOCAL_INCLUDE_DIR=\"$(local_includedir)\" \
-DCROSS_INCLUDE_DIR=\"$(CROSS_SYSTEM_HEADER_DIR)\" \
-DTOOL_INCLUDE_DIR=\"$(gcc_tooldir)/include\" \
+ -DNATIVE_SYSTEM_HEADER_DIR=\"$(NATIVE_SYSTEM_HEADER_DIR)\" \
-DPREFIX=\"$(prefix)/\" \
-DSTANDARD_EXEC_PREFIX=\"$(libdir)/gcc/\" \
@TARGET_SYSTEM_ROOT_DEFINE@
@@ -4517,7 +4413,7 @@ clean: mostlyclean lang.clean
-rm -f libgcc.a libgcc_eh.a libgcov.a
-rm -f libgcc_s*
-rm -f libunwind*
- -rm -f config.h tconfig.h bconfig.h tm_p.h tm.h libgcc_tm.h
+ -rm -f config.h tconfig.h bconfig.h tm_p.h tm.h
-rm -f options.c options.h optionlist
-rm -f cs-*
-rm -f doc/*.dvi
@@ -4573,7 +4469,7 @@ maintainer-clean:
# broken is small.
install: install-common $(INSTALL_HEADERS) \
install-cpp install-man install-info install-@POSUB@ \
- install-driver install-lto-wrapper
+ install-driver install-lto-wrapper install-gcc-ar
ifeq ($(enable_plugin),yes)
install: install-plugin
@@ -4603,7 +4499,6 @@ installdirs:
$(mkinstalldirs) $(DESTDIR)$(bindir)
$(mkinstalldirs) $(DESTDIR)$(includedir)
$(mkinstalldirs) $(DESTDIR)$(infodir)
- $(mkinstalldirs) $(DESTDIR)$(slibdir)
$(mkinstalldirs) $(DESTDIR)$(man1dir)
$(mkinstalldirs) $(DESTDIR)$(man7dir)
@@ -4898,6 +4793,23 @@ install-collect2: collect2 installdirs
install-lto-wrapper: lto-wrapper$(exeext)
$(INSTALL_PROGRAM) lto-wrapper$(exeext) $(DESTDIR)$(libexecsubdir)/lto-wrapper$(exeext)
+install-gcc-ar:
+ set -e ; \
+ for i in ar nm ranlib ; do \
+ install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ;\
+ target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ; \
+ binname=gcc-$$i$(exeext) ; \
+ rm -f $(DESTDIR)$(bindir)/$$install_name ; \
+ rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
+ $(INSTALL_PROGRAM) $$binname $(DESTDIR)$(bindir)/$$install_name ;\
+ if test -f $(DESTDIR)$(bindir)$$target_install_name ; then \
+ :; \
+ else \
+ ( cd $(DESTDIR)$(bindir) && \
+ $(LN) $$install_name $$target_install_name ) ; \
+ fi ; \
+ done
+
# Cancel installation by deleting the installed files.
uninstall: lang.uninstall
-rm -rf $(DESTDIR)$(libsubdir)
@@ -4912,6 +4824,12 @@ uninstall: lang.uninstall
-rm -rf $(DESTDIR)$(man1dir)/cpp$(man1ext)
-rm -f $(DESTDIR)$(infodir)/cpp.info* $(DESTDIR)$(infodir)/gcc.info*
-rm -f $(DESTDIR)$(infodir)/cppinternals.info* $(DESTDIR)$(infodir)/gccint.info*
+ for i in ar nm ranlib ; do \
+ install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ;\
+ target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ; \
+ rm -f $(DESTDIR)$(bindir)/$$install_name ; \
+ rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
+ done
#
# These targets are for the dejagnu testsuites. The file site.exp
# contains global variables that all the testsuites will use.
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index bbcb20bafcc..350f8e9c47f 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,11 +1,877 @@
+2011-10-28 Iain Sandoe <iains@gcc.gnu.org>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/50678
+ * init.c (__gnat_error_handler) [Darwin]: Apply a work-around to the
+ bug filed as radar #10302855 (inconsistent unwind data for sigtramp).
+
+2011-10-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/50842
+ * gcc-interface/Makefile.in (SYMDEPS): Delete.
+ (LIBICONV): New variable.
+ (LIBICONV_DEP): Likewise.
+ (LIBS): Add $(LIBICONV).
+ (LIBDEPS): Add $(LIBICONV_DEP).
+ (EXTRA_GNATTOOLS_OBJS): Merge into...
+ (TOOLS_LIBS): ...this. Add $(LIBICONV).
+
+2011-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (elaborate_expression_1): Add EXPR_PUBLIC_P local
+ variable. Always create the elaboration variable, if any, as constant.
+
+2011-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Subtype>: Try to
+ make a packable type for fields of union types as well.
+ <is_type>: Use RECORD_OR_UNION_TYPE_P predicate.
+ (gnat_to_gnu_component_type): Try to make a packable type for fields
+ of union types as well.
+ (make_packable_type): Use RECORD_OR_UNION_TYPE_P predicate.
+ (maybe_pad_type): Try to make a packable type for fields of union types
+ as well.
+ (gnat_to_gnu_field): Likewise.
+ (is_variable_size): Use RECORD_OR_UNION_TYPE_P predicate.
+ (set_rm_size): Likewise.
+ (rm_size): Likewise.
+ * gcc-interface/misc.c (gnat_type_max_size): Likewise.
+ * gcc-interface/trans.c (add_decl_expr): Likewise.
+ * gcc-interface/utils.c (finish_record_type): Likewise.
+ * gcc-interface/utils2.c (build_simple_component_ref): Likewise.
+
+2011-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_field): Always check components
+ declared as atomic. Move around conditionally executed code.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * sem.adb (Initialize): Fix bug that blew up if called a second time.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * tb-alvxw.c, tracebak.c, expect.c, initflt.c, tb-alvms.c,
+ tb-ivms.c, tb-gcc.c: Update headers to GPL 3.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma, case Debug): Give proper pragma
+ name in error msg.
+
+2011-10-24 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * gnat_rm.texi: Add an entry for restriction No_Finalization.
+
+2011-10-24 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Insert_Freeze_Node_For_Instance): If the
+ current instance is within the one that contains the generic,
+ the freeze node for the current one must appear in the current
+ declarative part. Ditto if the current instance is within another
+ package instance. In both of these cases the freeze node of the
+ previous instance is not relevant.
+
+2011-10-24 Gary Dismukes <dismukes@adacore.com>
+
+ * switch-m.adb (Normalize_Compiler_Switches): Add recognition
+ of AAMP-specific switches -univ and -aamp_target.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * a-tienau.adb (Put): Deal properly with limited line length.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * sem_warn.adb, sem_ch12.adb: Minor reformatting.
+
+2011-10-24 Tristan Gingold <gingold@adacore.com>
+
+ * gcc-interface/Makefile.in: Use GNU ld switches to generate map files
+ on AIX.
+
+2011-10-24 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Earlier): make available globally. If both
+ nodes have the same sloc, the freeze node that does not come
+ from source is the later one.
+ (True_Parent): Make available globally.
+ (Previous_Instance): Subsidiary of
+ Insert_Freeze_Node_For_Instance, to check whether the generic
+ parent of the current instance is declared within a previous
+ instance in the same unit or declarative part, in which case the
+ freeze nodes of both instances must appear in order to prevent
+ elaboration problems in gigi.
+ * sem_ch12.adb (Insert_Freeze_Node_For_Instance): A stub is a
+ freeze point, and the freeze node of a preceding instantiation
+ must be inserted before it.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * checks.ads, checks.adb: Add handling of Synchronization_Check
+ * debug.adb: Add doc for -gnatd.d and -gnatd.e (disable/enable
+ atomic sync).
+ * exp_ch2.adb (Expand_Entity_Reference): Set Atomic_Sync_Required
+ flag Minor code reorganization.
+ * opt.ads (Warn_On_Atomic_Synchronization): New switch.
+ * par-prag.adb: Add dummy entries for pragma
+ Disable/Enable_Atomic_Synchronization.
+ * sem_prag.adb (Process_Suppress_Unsuppress): Handle
+ case of Atomic_Synchronization specially (not suppressed
+ by All_Checks, cannot be set from Source).
+ (Pragma Disable/Enable_Atomic_Synchronization): Add processing.
+ * sinfo.ads, sinfo.adb: Add Atomic_Sync_Required flag
+ * snames.ads-tmpl: Add entry for Atomic_Synchronization Add
+ entry for pragma Disable/Enable_Atomic_Synchronization
+ * switch-c.adb: The -gnatp switch does not disable
+ Atomic_Synchronization Add -gnatep switch to disable
+ Atomic_Synchronization.
+ * types.ads: Add entry for Synchronization_Check
+ * usage.adb: Add line for -gnated switch
+ * warnsw.adb: Settings for Warn_On_Atomic_Synchronization
+
+2011-10-24 Geert Bosch <bosch@adacore.com>
+
+ * s-gearop.adb (Back_Substitute): Avoid overflow if matrix bounds start
+ at Integer'First.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch12.adb, s-gearop.adb: Minor reformatting.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * warnsw.adb: Add some missing warnings to Set_GNAT_Mode_Warnings.
+ * warnsw.ads: Add comments to Set_GNAT_Mode_Warnings.
+
+2011-10-24 Emmanuel Briot <briot@adacore.com>
+
+ * prj-proc.adb (Process_Expression_Variable_Decl): No special
+ handling for Project_Path unless it is an attribute.
+
+2011-10-24 Javier Miranda <miranda@adacore.com>
+
+ * sem_ch12.adb (Check_Hidden_Primitives): New subprogram.
+ (Install_Hidden_Primitives): New subprogram.
+ (Restore_Hidden_Primitives): New subprogram.
+ (Analyze_Formal_Package_Declaration,
+ Analyze_Package_Instantiation, Analyze_Subprogram_Instantiation):
+ Invoke Check_Hidden_Primitives after every call to
+ Analyze_Associations, and invoke Restore_Hidden_Primitives to
+ restore their visibility after processing the instantiation.
+ (Instantiate_Package_Body): Install visible primitives before
+ analyzing the instantiation and uninstall them to restore their
+ visibility when the instantiation has been analyzed.
+ * sem_util.ads, sem_util.adb (Add_Suffix): New subprogram
+ (Remove_Suffix): New subprogram
+ * sem_ch3.adb (Derive_Subprogram): When handling
+ a derived subprogram for the instantiation of a formal derived
+ tagged type, inherit the dispatching attributes from the actual
+ subprogram (not from the parent type).
+
+2011-10-24 Vasiliy Fofanov <fofanov@adacore.com>
+
+ * gnat_ugn.texi: Document explicit use of XDECGNAT library.
+
+2011-10-24 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch3.adb (Build_Assignment): Add local constant N_Loc and
+ update its uses.
+ (Build_Discriminant_Assignments): Add local variable D_Loc and update
+ its uses.
+ (Build_Init_Statements): Add local variables Comp_Loc, Decl_Loc and
+ Var_Loc and update their uses.
+ (Build_Record_Init_Proc): Code reformatting.
+ (Increment_Counter): Add formal parameter Loc.
+ (Make_Counter): Add formal parameter Loc.
+
+2011-10-24 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_disp.adb (Covers_Some_Interface): Fix typo.
+
+2011-10-24 Matthew Heaney <heaney@adacore.com>
+
+ * a-cuprqu.adb, a-cbprqu.adb (Dequeue_Only_High_Priority): Fix sense
+ of predicate.
+
+2011-10-24 Yannick Moy <moy@adacore.com>
+
+ * sem_ch13.adb (Analyze_Aspect_Specifications/Aspect_Test_Case):
+ Translate arguments in positional notation into pragma argument
+ association arguments for the generated pragma.
+
+2011-10-24 Arnaud Charlet <charlet@adacore.com>
+
+ * exp_ch5.adb: Fix minor typo.
+
+2011-10-24 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Is_Visible_Component): Refine predicate for
+ the case of a component reference in an instance body, when the
+ enclosing type is private.
+
+2011-10-24 Sergey Rybin <rybin@adacore.com frybin>
+
+ * gnat_ugn.texi: For gnatelim, move the note about using the GNAT
+ driver for getting the project support into gnatelim section.
+
+2011-10-24 Robert Dewar <dewar@adacore.com>
+
+ * gnat_rm.texi: Minor correction to documentation on address clause.
+
+2011-10-24 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * s-finmas.adb (Attach): Synchronize and call the unprotected version.
+ (Attach_Unprotected): New routine.
+ (Delete_Finalize_Address): Removed.
+ (Delete_Finalize_Address_Unprotected): New routine.
+ (Detach): Synchronize and call the unprotected version.
+ (Detach_Unprotected): Remove locking.
+ (Finalize): Add various comment on synchronization. Lock the critical
+ region and call the unprotected versions of routines.
+ (Finalize_Address): Removed.
+ (Finalize_Address_Unprotected): New routine.
+ (Set_Finalize_Address): Synchronize and call
+ the unprotected version.
+ (Set_Finalize_Address_Unprotected): New routine.
+ (Set_Heterogeneous_Finalize_Address): Removed.
+ (Set_Heterogeneous_Finalize_Address_Unprotected): New routine.
+ (Set_Is_Heterogeneous): Add comment on synchronization and
+ locking.
+ * s-finmas.ads: Flag Finalization_Started is no longer atomic
+ because synchronization uses task locking / unlocking.
+ (Attach): Add comment on usage.
+ (Attach_Unprotected): New routine.
+ (Delete_Finalize_Address): Renamed to
+ Delete_Finalize_Address_Unprotected.
+ (Detach): Add comment on usage.
+ (Detach_Unprotected): New routine.
+ (Finalize_Address): Renamed to Finalize_Address_Unprotected.
+ (Set_Finalize_Address): Add comment on usage.
+ (Set_Finalize_Address_Unprotected): New routine.
+ (Set_Heterogeneous_Finalize_Address): Renamed to
+ Set_Heterogeneous_Finalize_Address_Unprotected.
+ * s-stposu.adb (Allocate_Any_Controlled): Add local variable
+ Allocation_Locked. Add various comments on synchronization. Lock
+ the critical region and call the unprotected version of
+ routines.
+ (Deallocate_Any_Controlled): Add various comments on
+ synchronization. Lock the critical region and call the unprotected
+ version of routines.
+
+2011-10-24 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (Set_Fixed_Range): The bounds of a fixed point type
+ are universal and must carry the corresponding type.
+ * sem_eval.adb (Check_Non_Static_Context): If the type of the
+ expression is universal real, as may be the case for a fixed point
+ expression with constant operands in the context of a conversion,
+ there is nothing to check.
+ * s-finmas.adb: Minor reformatting
+
+2011-10-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (create_concat_name): Add explicit cast.
+
+2011-10-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Make-lang.in (GNATLIBFLAGS, GNATLIBCFLAGS, THREAD_KIND,
+ TRACE): Reintroduce.
+ (ada/tracebak.o, ada/targext.o, ada/cio.o, ada/init.o,
+ ada/initialize.o, ada/raise.o): Reintroduce explicit compilation rules.
+
+2011-10-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (lhs_or_actual_p): New predicate.
+ (unchecked_conversion_nop): Use it.
+ (gnat_to_gnu): Likewise.
+
+2011-10-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * back_end.adb (Call_Back_End): Pass the maximum logical line number
+ instead of the maximum physical line number to gigi.
+ * gcc-interface/trans.c (Sloc_to_locus): Cope with line zero.
+
+2011-10-16 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * gcc-interface/trans.c (gigi, Sloc_to_locus): Adjust to use the new
+ public ordinary map interface.
+
+2011-10-16 Tristan Gingold <gingold@adacore.com>
+
+ * link.c (_AIX): Add support for GNU ld.
+
+2011-10-16 Fedor Rybin <frybin@adacore.com>
+
+ * gnat_ugn.texi: Fixing gnattest example names in the doc.
+ Adding explanation to additional tests usage.
+
+2011-10-16 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch6.adb, sem_ch6.adb: Minor reformatting.
+
+2011-10-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * a-convec.adb: Fix minor inconsistencies.
+
+2011-10-16 Matthew Heaney <heaney@adacore.com>
+
+ * a-cusyqu.ads, a-cbsyqu.ads, a-cuprqu.ads, a-cbprqu.ads (package
+ Implementation): Specify pragma Implementation_Defined.
+
+2011-10-15 Nicolas Roche <roche@adacore.com>
+
+ * gcc-interface/lang-specs.h: Ensure -mrtp switch is passed when using
+ either rtp-smp or ravenscar-cert-rtp runtimes.
+
+2011-10-15 Bob Duff <duff@adacore.com>
+
+ * exp_ch6.adb (Add_Unconstrained_Actuals_To_Build_In_Place_Call):
+ Do not create a pool formal on unless RE_Root_Storage_Pool_Ptr
+ is available.
+ (Expand_N_Extended_Return_Statement): Do not create a renaming of the
+ build-in-place pool parameter unless RE_Root_Storage_Pool_Ptr is
+ available.
+ (Make_Build_In_Place_Call_In_Allocator): Add the user-defined
+ pool only if RE_Root_Storage_Pool_Ptr is available.
+ (Make_Build_In_Place_Call_In_Object_Declaration): Do not add a
+ pool actual unless RE_Root_Storage_Pool_Ptr is available.
+ * sem_ch6.adb (Create_Extra_Formals): Add build-in-place pool
+ formal only if RE_Root_Storage_Pool_Ptr is available.
+
+2011-10-15 Matthew Heaney <heaney@adacore.com>
+
+ * a-cusyqu.ads, a-cbsyqu.ads, a-cuprqu.ads, a-cbprqu.ads (Queue
+ type): Specify Priority aspect for protected type.
+
+2011-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_disp.adb (Check_Premature_Freezing): If an untagged type
+ is a generic actual, it is a subtype of a type that was frozen
+ by the instantiation, and even if not marked frozen it does not
+ affect the construction of the dispatch table.
+
+2011-10-14 Robert Dewar <dewar@adacore.com>
+
+ * make.adb, mlib-utl.adb, sem_util.adb, sem_ch4.adb: Minor code
+ reformatting.
+ * s-rident.ads: Add missing Compiler_Unit pragma.
+
+2011-10-14 Gary Dismukes <dismukes@adacore.com>
+
+ * sem_res.adb: Minor reformatting.
+
+2011-10-14 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch6.adb (Add_Task_Actuals_To_Build_In_Place_Call):
+ Code and comment reformatting. Use BIP_Task_Master
+ when creating a _master.
+ (BIP_Formal_Suffix): Code reformatting. Correct the case for
+ BIP_Task_Master.
+ (Make_Build_In_Place_Call_In_Object_Declaration): Use
+ BIP_Task_Master when creating a reference to the enclosing
+ function's _master formal.
+ (Move_Activation_Chain): Use BIP_Task_Master when creating a reference
+ to the _master.
+ * exp_ch6.ads: Change BIP_Master to BIP_Task_Master.
+ (Needs_BIP_Finalization_Master): Alphabetized.
+ * sem_ch6.adb (Create_Extra_Formals): Update the usage of
+ BIP_Task_Master.
+
+2011-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * par-ch6.adb (P_Return_Object_Declaration): In Ada 2012 mode,
+ reject an aliased keyword on the object declaration of an extended
+ return statement. In older versions of the language indicate
+ that this is illegal in the standard.
+
+2011-10-14 Pascal Obry <obry@adacore.com>
+
+ * sem_util.adb, sem_ch4.adb: Minor reformatting.
+
+2011-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch13.adb: Recognize properly procedure calls that are
+ transformed into code statements.
+
+2011-10-14 Vincent Celier <celier@adacore.com>
+
+ * projects.texi: Minor fix in project example.
+
+2011-10-14 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.adb: Return objects are aliased if their type is
+ immutably limited as per AI05-0053.
+
+2011-10-14 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Op_And): Remove Short_Circuit_And_Or
+ expansion code (moved to sem_res) (Expand_N_Op_Or): Remove
+ Short_Circuit_And_Or expansion code (moved to sem_res).
+ * sem_res.adb (Resolve_Logical_Op): Add code to rewrite Boolean
+ "and" and "or" operators as short-circuit "and then" and "or
+ else", when pragma Short_Circuit_And_Or is active.
+
+2011-10-13 Robert Dewar <dewar@adacore.com>
+
+ * sem_ch9.adb, sem_util.adb, sem_util.ads, exp_ch6.adb, sem_ch4.adb,
+ sem_ch6.adb, exp_ch3.adb: Minor reformatting.
+
+2011-10-13 Arnaud Charlet <charlet@adacore.com>
+
+ * Makefile.rtl (GNATRTL_NONTASKING_OBJS): Add a-ngcoar.o.
+
+2011-10-13 Jerome Guitton <guitton@adacore.com>
+
+ * sysdep.c (__gnat_get_task_options): Re-enable VX_SPE_TASK on vThreads
+
+2011-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * a-convec.ads (Cursor): Minor reformatting.
+ * a-convec.adb (Next): Fix minor inconsistencies.
+ (Previous): Likewise.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_util.ads, sem_util.adb (Available_Full_View_Of_Component):
+ New predicate to determine whether some operations on an array
+ type are available when the full view of its component may differ
+ from the view of the point of the array declaration.
+ * sem_ch4.adb (Find_Equality_Types): Use
+ Available_Full_View_Of_Component.
+ * sem_type.adb (Valid_Boolean_Arg, Valid_Comparison_Arg): Ditto
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch9.adb: Analyze aspects while discriminants of protected
+ type are visible.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * Makefile.rtl (GNATRTL_TASKING_OBJECTS): Add
+ a-nlcoar.o, a-nllcar.o, a-nucoar.o and s-gearop.o, as these no
+ longer depend on an external library.
+ * gcc-interface/Makefile.in (GNATRTL_LINEARALGEBRA_OBJS): Remove
+ a-nlcoar.o, a-nllcar.o, a-nucoar.o and s-gearop.o.
+ Update dependencies.
+ * gcc-interface/Make-lang.in: Update dependencies.
+
+2011-10-13 Cyrille Comar <comar@adacore.com>
+
+ * gnat_ugn.texi: Minor editing.
+
+2011-10-13 Vincent Celier <celier@adacore.com>
+
+ * projects.texi: Add documentation on packages and attributes
+ that are inherited from a project being extended into the
+ extended project.
+
+2011-10-13 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch3.adb (Build_Master): Rewritten.
+ (Expand_N_Full_Type_Declaration): Reformat the declarative
+ region. Update the call to Build_Master_Renaming.
+ (Expand_Previous_Access_Type): Rewritten.
+ * exp_ch6.adb (Add_Task_Actuals_To_Build_In_Place_Call):
+ Add local constant Result_Subt and update related usage.
+ (Expand_N_Extended_Return_Statement): Add local constant
+ Result_Subt and update related usage.
+ * exp_ch9.adb (Build_Activation_Chain): Rewritten to use the
+ new context detection mechanism.
+ (Build_Class_Wide_Master):
+ Use Insert_Action to add the renaming into the tree.
+ (Build_Master_Entity): Rewritten to use the new context detection
+ mechanism.
+ (Build_Master_Renaming): Add formal parameter Ins_Nod
+ and related usage. Use Insert_Action to add the renaming into the
+ tree.
+ (Find_Enclosing_Context): New subsidiary routine. Rather
+ than relying on enclosing scopes, this routine looks at the
+ tree structure to figure out the proper context for a _master
+ or a _chain. This approach eliminates the issues with transient
+ scopes which have not been converted into blocks.
+ * exp_ch9.ads (Build_Master_Entity): Change parameter profile
+ to better reflect the new usage. Update the related comment.
+ (Build_Master_Renaming): Add formal parameter Ins_Nod. Update
+ the comment on usage.
+ * sem_ch3.adb (Access_Definition): Update the calls to
+ Build_Master_Entity and Build_Master_Renaming.
+ * sem_ch6.adb (Create_Extra_Formals): Add local variable
+ Full_Subt. Code reformatting.
+ * sem_util.adb (Is_Iterator): Alphabetized.
+ (Is_LHS): Alphabetized.
+ (Is_Limited_Class_Wide_Type): New routine.
+ * sem_util.ads (Is_Limited_Class_Wide_Type): New routine.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * a-ngrear.adb (Solve): Make generic and move to
+ System.Generic_Array_Operations.
+ * s-gearop.ads (Matrix_Vector_Solution, Matrix_Matrix_Solution):
+ New generic solvers to compute a vector resp. matrix Y such
+ that A * Y = X, approximately.
+ * s-gearop.adb (Matrix_Vector_Solution, Matrix_Matrix_Solution):
+ Implement using Forward_Eliminate and Back_Substitute
+ * a-ngcoar.adb: Reimplement in pure Ada to remove dependencies
+ on BLAS and LAPACK.
+ * a-ngcoar.ads ("abs"): Fix return type to be real.
+
+2011-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ PR ada/50589
+ * s-linux-alpha.ads: Do not "with" Interfaces.C.
+ * s-linux-sparc.ads: Likewise.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * s-gearop.ads (Forward_Eliminate): Add "abs" formal function
+ returning a Real.
+ * s-gearop.adb (Forward_Eliminate): Remove local "abs" function
+ and use formal.
+ * a-ngrear.adb (Forward_Eliminate): Adjust instantiation for
+ new profile.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * a-ngrear.adb, s-gearop.adb, s-gearop.ads (Sqrt): Make generic and
+ move to System.Generic_Array_Operations.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * a-ngrear.adb ("abs"): Adjust for modified L2_Norm generic
+ * s-gearop.ads (L2_Norm): Change profile to be suitable for
+ Complex_Vector
+ * s-gearop.adb (L2_Norm): Reimplement using direct definition,
+ not inner product
+
+2011-10-13 Robert Dewar <dewar@adacore.com>
+
+ * exp_ch5.adb, sem_ch3.adb, impunit.adb, impunit.ads, sem_type.adb,
+ prj-proc.adb, exp_ch9.adb, s-regpat.adb, sem_ch10.adb, sem_prag.adb,
+ sem_ch12.adb, freeze.adb, sem_attr.adb, sem_attr.ads, gnatlink.adb,
+ par-ch6.adb, exp_ch6.adb, sem_ch4.adb, sem_ch6.adb, sem_ch8.adb,
+ par-util.adb, sem_ch13.adb, lib-xref.adb, g-trasym.adb, g-trasym.ads,
+ exp_aggr.adb, s-taprop-posix.adb: Minor reformatting.
+
+2011-10-13 Geert Bosch <bosch@adacore.com>
+
+ * s-gearop.adb: Minor comment additions.
+
+2011-10-13 Fedor Rybin <frybin@adacore.com>
+
+ * gnat_ugn.texi: Add gnattest section.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * freeze.adb: Do not create body of renaming if declaration has
+ errors.
+
+2011-10-13 Olivier Hainque <hainque@adacore.com>
+
+ * init.c (__gnat_error_handler - vxworks case): Restrict sigtramp calls
+ further, to the ppc+kernel case only.
+
+2011-10-13 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch4.adb (Expand_N_Allocator): Comment reformatting.
+ * exp_ch6.adb (Add_Unconstrained_Actuals_To_Build_In_Place_Call):
+ Do not create a pool formal on .NET/JVM.
+ (Expand_N_Extended_Return_Statement): Alphabetize local
+ variables. Do not create a renaming of the build-in-place pool
+ parameter on .NET/JVM. (Make_Build_In_Place_Call_In_Allocator):
+ Add the user-defined pool only on non-VM targets.
+ (Make_Build_In_Place_Call_In_Object_Declaration): Alphabetize
+ local variables. Do not add a pool actual on .NET/JVM.
+ * sem_ch6.adb: Add with and use clause for Targparm.
+ (Create_Extra_Formals): Add build-in-place pool formal only on
+ non-VM targets.
+ * rtsfind.ads: Alphabetize entries.
+
+2011-10-13 Sergey Rybin <rybin@adacore.com>
+
+ * gnat_ugn.texi: Minor correction.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch8.adb: Minor error message improvement.
+
+2011-10-13 Robert Dewar <dewar@adacore.com>
+
+ * a-cbprqu.adb, a-ciorma.adb, exp_ch3.adb: Minor reformatting.
+
+2011-10-13 Gary Dismukes <dismukes@adacore.com>
+
+ * exp_ch5.adb (Expand_N_Loop_Statement): For the transformation
+ of a for loop for an enumeration type with an enumeration rep
+ clause, which involves moving the original loop parameter into
+ a nested block, the loop parameter's entity must be removed from
+ the entity list of the loop scope.
+
+2011-10-13 Bob Duff <duff@adacore.com>
+
+ * exp_ch6.ads (BIP_Storage_Pool): New "extra implicit parameter"
+ that gets passed in the same cases where BIP_Alloc_Form is passed
+ (caller-unknown-size results). BIP_Storage_Pool is used when
+ BIP_Alloc_Form = User_Storage_Pool. In that case, a pointer
+ to the user-defined storage pool is passed at the call site,
+ and this pool is used in callee to allocate the result.
+ * exp_ch6.adb (Add_Unconstrained_Actuals_To_Build_In_Place_Call): New
+ version of Add_Alloc_Form_Actual_To_Build_In_Place_Call. Passes
+ the additional BIP_Storage_Pool actual.
+ (Expand_N_Extended_Return_Statement): Allocate the function
+ result using the user-defined storage pool, if BIP_Alloc_Form =
+ User_Storage_Pool.
+ * sem_ch6.adb: Add the "extra formal" for BIP_Storage_Pool.
+ * exp_ch4.adb: Don't overwrite storage pool set by
+ Expand_N_Extended_Return_Statement.
+ * s-stopoo.ads, rtsfind.ads (Root_Storage_Pool_Ptr): New type,
+ for use in build-in-place function calls within allocators
+ where the access type has a user-defined storage pool.
+
+2011-10-13 Sergey Rybin <rybin@adacore.com>
+
+ * gnat_ugn.texi, vms_data.ads: Add an option to control enumeration
+ literal casing.
+
+2011-10-13 Nicolas Roche <roche@adacore.com>
+
+ * gnatlink.adb: Ensure that -mrtp is passed when runtime name ends
+ with 'rtp'.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_prag.adb (Analyze_Pragma, case Unchecked_Union): Take into
+ account that an unchecked union type can be limited.
+
+2011-10-13 Olivier Hainque <hainque@adacore.com>
+
+ * init.c (__gnat_error_handler) <VxWorks version>: Add comments on
+ the use of the signal trampoline for PPC in the sjlj case as well.
+ Add legitimate casts, preventing compile time warnings on the
+ (sighandler *) profile.
+
+2011-10-13 Yannick Moy <moy@adacore.com>
+
+ * sem_aggr.adb (Resolve_Aggr_Expr): Always perform semantic analysis
+ in Alfa mode.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch3.adb (OK_For_Limited_Init_In_05): Conditional and case
+ expressions are legal limited return values if each one of their
+ dependent expressions are legal.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch6.adb (Analyze_Procedure_Call_Statement): In Ada 2012 mode,
+ if the prefix of the call is a qualified expression, rewrite as
+ a code statement.
+ * sem_ch13.adb (Analyze_Code_Statement): In Ada 2012 mode, the
+ code statement is legal if it is a rewriting of a procedure call.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * exp_aggr.adb (Flatten): If a component association has a box,
+ assume that aggregate is not static.
+ (Safe_Aggregate): If a component association in a non-limited
+ aggregate has a box, assume that it cannot be expanded in place.
+
+2011-10-13 Vincent Celier <celier@adacore.com>
+
+ * prj-conf.adb (Get_Or_Create_Configuration_File): Call
+ Process_Project_Tree_Phase_1 with Packages_To_Check.
+ (Process_Project_And_Apply_Config): Ditto
+ * prj-part.ads, prj-part.adb, prj-pars.ads, prj-pars.adb (Parse):
+ Remove default for argument Packages_To_Check.
+ * prj-proc.adb (Recursive_Process): New argument
+ Packages_To_Check.
+ (Process): Ditto.
+ (Process_Project_Tree_Phase_1): Ditto.
+ (Recursive_Project.Process_Aggregated_Projects): Call
+ Prj.Part.Parse and Process_Project_Tree_Phase_1 with
+ Packages_To_Check.
+ * prj-proc.ads (Process): New argument Packages_To_Check
+ (Process_Project_Tree_Phase_1): Ditto
+
+2011-10-13 Arnaud Charlet <charlet@adacore.com>
+
+ * gcc-interface/Makefile.in: Fix typo.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_ch12.adb (Analyze_Formal_{Floating_Type,
+ Signed_Integer_Type, Decimal_Fixed_Point_Type, Discrete_Type}):
+ Use sloc of defining identifier of farmal type declaration,
+ as sloc of generated internal entity, to prevent misplaced
+ references in ali.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_intr.adb (Check_Intrinsic_Operator): Check that type
+ is fully defined before checking that it is a numeric type.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_aggr.adb (Resolve_Record_Aggregate): If a component
+ association for component X has a box, then X is covered in the
+ aggregate even if there is not default value for X in the type
+ declaration, and X has to be default-initialized.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * sem_attr.adb (Check_Enum_Image, Analyze_Attribute case 'Value): Mark
+ literals as referenced only if reference is in current source unit.
+
+2011-10-13 Matthew Heaney <heaney@adacore.com>
+
+ * a-csquin.ads (Enque, Dequeue): Mark interface operations as entries.
+
+2011-10-13 Olivier Hainque <hainque@adacore.com>
+
+ * sigtramp.h: New file. Prototype and spec of the signal
+ trampoline to be called by an established handler to provide
+ dwarf call frame info before the real signal processing code.
+ * sigtramp-ppcvxw.c: New file. Implementation of the signal
+ trampoline for ppc-vxworks.
+ * init.c (vxworks section): Use it for ppc.
+
+2011-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * par-ch2.adb, par.adb, par-util.adb, par-ch3.adb
+ (Check_Future_Identifier): New subprogram,
+ factors duplicated code from Par.Ch2.P_Identifier and
+ Par.Ch3.P_Defining_Identifier.
+
+2011-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * s-taprop-posix.adb (Initialize): Always raise Storage_Error
+ if we fail to initialize CV attributes or CV.
+
+2011-10-13 Thomas Quinot <quinot@adacore.com>
+
+ * s-tasren.adb (Timed_Selective_Wait, case
+ Accept_Alternative_Selected): Use Defer_Abort_Nestable, since
+ we know abortion is already deferred.
+
+2011-10-13 Hristian Kirtchev <kirtchev@adacore.com>
+
+ * exp_ch3.adb (Build_Class_Wide_Master): Moved to exp_ch9.
+ (Build_Master_Renaming (function)): Removed.
+ (Build_Master_Renaming (procedure)): Moved to exp_ch9.
+ (Expand_Full_Type_Declaration): Alphabetize
+ variables. Reformatting of code and comments. Rewrite the
+ section on processing of anonymous access-to-task types in
+ record components.
+ * exp_ch3.ads (Build_Class_Wide_Master): Moved to exp_ch9.
+ (Build_Master_Renaming): Moved to exp_ch9.
+ * exp_ch9.adb (Build_Class_Wide_Master): Moved from exp_ch3.
+ (Build_Master_Entity): Add formal parameter
+ Use_Current. Reformatting of code and comments.
+ (Build_Master_Renaming): Moved from exp_ch3.
+ * exp_ch9.ads (Build_Class_Wide_Master): Moved from
+ exp_ch3. Update comment on usage.
+ (Build_Master_Entity):
+ Add formal parameter Use_Current. Update comment on usage.
+ (Build_Master_Renaming): Moved from exp_ch3.
+ * sem_ch3.adb (Access_Definition): Remove redundant code to
+ create a _master and a renaming.
+
+2011-10-13 Ed Schonberg <schonberg@adacore.com>
+
+ * lib-xref.adb: Do no emit reference to overridden operation,
+ if it is internally generated.
+
+2011-10-13 Vincent Celier <celier@adacore.com>
+
+ * bindgen.adb: Remove any processing related to g-trasym
+ * Makefile.rtl: Add g-trasym.o to GNATRTL_NONTASKING_OBJS
+ * mlib-prj.adb: Remove any processing related to g-trasym.
+
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * sem_util.adb (Denotes_Same_Prefix): Fix fatal warning.
+ * gcc-interface/Make-lang.in (WARN_ADAFLAGS): New.
+ (ALL_ADAFLAGS): Include WARN_ADAFLAGS.
+ (ADA_FLAGS_TO_PASS): Likewise.
+ (COMMON_FLAGS_TO_PASS): New.
+ (ADA_TOOLS_FLAGS_TO_PASS): Use COMMON_FLAGS_TO_PASS. In the regular
+ native case, also use FLAGS_TO_PASS and ADA_FLAGS_TO_PASS.
+ (gnatlib): Use COMMON_FLAGS_TO_PASS.
+ (ada.install-common): Likewise.
+ (install-gnatlib): Likewise.
+ (install-gnatlib-obj): Likewise.
+ (gnattools): Use ADA_TOOLS_FLAGS_TO_PASS for gnattools1 as well.
+ (gnat-cross): Delete.
+ (gnatboot): Likewise.
+ (gnatboot2): Likewise.
+ (gnatboot3): Likewise.
+ (gnatstage1): Likewise.
+ (gnatstage2): Likewise.
+ * gcc-interface/Makefile.in (SOME_ADAFLAGS): Likewise.
+ (MOST_ADAFLAGS): Likewise.
+ (LOOSE_CFLAGS): Likewise.
+ (gnat-cross): Likewise.
+ (GNATLIBFLAGS): Add -W -Wall.
+ (GNATLIBCFLAGS_FOR_C): Likewise.
+ * gcc-interface/lang.opt: Remove C-specific warnings. Add doc lines.
+ * gcc-interface/misc.c (gnat_handle_option): Remove obsolete cases.
+
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/trans.c (Attribute_to_gnu): Use remove_conversions.
+ (push_range_check_info): Likewise.
+ (gnat_to_gnu) <N_Code_Statement>: Likewise.
+ * gcc-interface/utils2.c (build_unary_op) <INDIRECT_REF>: Likewise.
+ (gnat_invariant_expr): Likewise.
+ * gcc-interface/utils.c (compute_related_constant): Likewise.
+ (max_size): Fix handling of SAVE_EXPR.
+ (remove_conversions): Fix formatting.
+
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/ada-tree.h (DECL_LOOP_PARM_P): New flag.
+ (DECL_INDUCTION_VAR): New macro.
+ (SET_DECL_INDUCTION_VAR): Likewise.
+ * gcc-interface/gigi.h (convert_to_index_type): Declare.
+ (gnat_invariant_expr): Likewise.
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <object>: If this is a loop
+ parameter, set DECL_LOOP_PARM_P on it.
+ * gcc-interface/misc.c (gnat_print_decl) <VAR_DECL>: If DECL_LOOP_PARM_P
+ is set, print DECL_INDUCTION_VAR instead of DECL_RENAMED_OBJECT.
+ * gcc-interface/trans.c (gnu_loop_label_stack): Delete.
+ (struct range_check_info_d): New type.
+ (struct loop_info_d): Likewise.
+ (gnu_loop_stack): New stack.
+ (Identifier_to_gnu): Set TREE_READONLY flag on the first dereference
+ built for a by-double-ref read-only parameter. If DECL_LOOP_PARM_P
+ is set, do not test DECL_RENAMED_OBJECT.
+ (push_range_check_info): New function.
+ (Loop_Statement_to_gnu): Push a new struct loop_info_d instead of just
+ the label. Reference the label and the iteration variable from it.
+ Build the special induction variable in the unsigned version of the
+ size type, if it is larger than the base type. And attach it to the
+ iteration variable if the latter isn't by-ref. In the iteration scheme
+ case, initialize the invariant conditions in front of the loop if
+ deemed profitable. Use gnu_loop_stack.
+ (gnat_to_gnu) <N_Exit_Statement>: Use gnu_loop_stack.
+ <N_Raise_Constraint_Error>: Always process the reason. In the range
+ check and related cases, and if loop unswitching is enabled, compute
+ invariant conditions and push this information onto the stack.
+ Do not translate again the condition if it has been already translated.
+ * gcc-interface/utils.c (record_global_renaming_pointer): Assert that
+ DECL_LOOP_PARM_P isn't set.
+ (convert_to_index_type): New function.
+ * gcc-interface/utils2.c (build_binary_op) <ARRAY_REF>: Use it in order
+ to convert the index from the base index type to sizetype.
+ (gnat_invariant_expr): New function.
+
2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
* gcc-interface/utils.c (def_builtin_1): Delete old interface with
two parallel arrays to hold standard builtin declarations, and
replace it with a function based interface that can support
- creating builtins on the fly in the future. Change all uses, and
- poison the old names. Make sure 0 is not a legitimate builtin
- index.
+ creating builtins on the fly in the future.
* gcc-interface/trans.c (Exception_Handler_to_gnu_zcx): Ditto.
(gnat_to_gnu): Ditto.
diff --git a/gcc/ada/Makefile.rtl b/gcc/ada/Makefile.rtl
index 30a95065153..4e03c9e178e 100644
--- a/gcc/ada/Makefile.rtl
+++ b/gcc/ada/Makefile.rtl
@@ -186,27 +186,31 @@ GNATRTL_NONTASKING_OBJS= \
a-locale$(objext) \
a-ncelfu$(objext) \
a-ngcefu$(objext) \
+ a-ngcoar$(objext) \
a-ngcoty$(objext) \
a-ngelfu$(objext) \
a-ngrear$(objext) \
- a-nllrar$(objext) \
- a-nlrear$(objext) \
- a-nurear$(objext) \
a-nlcefu$(objext) \
+ a-nlcoar$(objext) \
a-nlcoty$(objext) \
a-nlelfu$(objext) \
+ a-nlrear$(objext) \
+ a-nllcar$(objext) \
a-nllcef$(objext) \
a-nllcty$(objext) \
a-nllefu$(objext) \
+ a-nllrar$(objext) \
a-nscefu$(objext) \
a-nscoty$(objext) \
a-nselfu$(objext) \
+ a-nucoar$(objext) \
a-nucoty$(objext) \
a-nudira$(objext) \
a-nuelfu$(objext) \
a-nuflra$(objext) \
a-numaux$(objext) \
a-numeri$(objext) \
+ a-nurear$(objext) \
a-rbtgbo$(objext) \
a-rbtgbk$(objext) \
a-rbtgso$(objext) \
@@ -435,6 +439,7 @@ GNATRTL_NONTASKING_OBJS= \
g-tasloc$(objext) \
g-timsta$(objext) \
g-traceb$(objext) \
+ g-trasym$(objext) \
g-u3spch$(objext) \
g-utf_32$(objext) \
g-wispch$(objext) \
@@ -514,6 +519,7 @@ GNATRTL_NONTASKING_OBJS= \
s-fvadfl$(objext) \
s-fvaffl$(objext) \
s-fvagfl$(objext) \
+ s-gearop$(objext) \
s-geveop$(objext) \
s-gloloc$(objext) \
s-htable$(objext) \
diff --git a/gcc/ada/a-cbprqu.adb b/gcc/ada/a-cbprqu.adb
index e5aff11b36e..ce2fd69fae7 100644
--- a/gcc/ada/a-cbprqu.adb
+++ b/gcc/ada/a-cbprqu.adb
@@ -51,8 +51,31 @@ package body Ada.Containers.Bounded_Priority_Queues is
Success : out Boolean)
is
begin
+ -- This operation dequeues a high priority item if it exists in the
+ -- queue. By "high priority" we mean an item whose priority is equal
+ -- or greater than the value At_Least. The generic formal operation
+ -- Before has the meaning "has higher priority than". To dequeue an
+ -- item (meaning that we return True as our Success value), we need
+ -- as our predicate the equivalent of "has equal or higher priority
+ -- than", but we cannot say that directly, so we require some logical
+ -- gymnastics to make it so.
+
+ -- If E is the element at the head of the queue, and symbol ">"
+ -- refers to the "is higher priority than" function Before, then we
+ -- derive our predicate as follows:
+
+ -- original: P(E) >= At_Least
+ -- same as: not (P(E) < At_Least)
+ -- same as: not (At_Least > P(E))
+ -- same as: not Before (At_Least, P(E))
+
+ -- But that predicate needs to be true in order to successfully
+ -- dequeue an item. If it's false, it means no item is dequeued, and
+ -- we return False as the Success value.
+
if List.Length = 0
- or else not Before (At_Least, Get_Priority (List.First_Element))
+ or else Before (At_Least,
+ Get_Priority (List.Container.First_Element))
then
Success := False;
return;
@@ -80,8 +103,10 @@ package body Ada.Containers.Bounded_Priority_Queues is
begin
C := List.Container.First;
while Has_Element (C) loop
- -- ???
+
+ -- ??? why is following commented out ???
-- if Before (P, Get_Priority (List.Constant_Reference (C))) then
+
if Before (P, Get_Priority (Element (C))) then
List.Container.Insert (C, New_Item);
exit;
@@ -109,7 +134,9 @@ package body Ada.Containers.Bounded_Priority_Queues is
(List : List_Type) return Queue_Interfaces.Element_Type
is
begin
+
-- Use Constant_Reference for this. ???
+
return List.Container.First_Element;
end First_Element;
diff --git a/gcc/ada/a-cbprqu.ads b/gcc/ada/a-cbprqu.ads
index 0d0f1689191..aa184a1cc5a 100644
--- a/gcc/ada/a-cbprqu.ads
+++ b/gcc/ada/a-cbprqu.ads
@@ -54,11 +54,11 @@ generic
package Ada.Containers.Bounded_Priority_Queues is
pragma Preelaborate;
- -- All identifiers in this unit are implementation defined
+ package Implementation is
- pragma Implementation_Defined;
+ -- All identifiers in this unit are implementation defined
- package Implementation is
+ pragma Implementation_Defined;
type List_Type (Capacity : Count_Type) is tagged limited private;
@@ -101,9 +101,7 @@ package Ada.Containers.Bounded_Priority_Queues is
protected type Queue
(Capacity : Count_Type := Default_Capacity;
Ceiling : System.Any_Priority := Default_Ceiling)
- -- ???
- -- with Priority => Ceiling is new Queue_Interfaces.Queue with
- is new Queue_Interfaces.Queue with
+ with Priority => Ceiling is new Queue_Interfaces.Queue with
overriding
entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
diff --git a/gcc/ada/a-cbsyqu.ads b/gcc/ada/a-cbsyqu.ads
index 8d25359469d..0d6e3c39958 100644
--- a/gcc/ada/a-cbsyqu.ads
+++ b/gcc/ada/a-cbsyqu.ads
@@ -44,11 +44,11 @@ generic
package Ada.Containers.Bounded_Synchronized_Queues is
pragma Preelaborate;
- -- All identifiers in this unit are implementation defined
+ package Implementation is
- pragma Implementation_Defined;
+ -- All identifiers in this unit are implementation defined
- package Implementation is
+ pragma Implementation_Defined;
type List_Type (Capacity : Count_Type) is tagged limited private;
@@ -83,9 +83,7 @@ package Ada.Containers.Bounded_Synchronized_Queues is
protected type Queue
(Capacity : Count_Type := Default_Capacity;
Ceiling : System.Any_Priority := Default_Ceiling)
- -- ???
- -- with Priority => Ceiling is new Queue_Interfaces.Queue with
- is new Queue_Interfaces.Queue with
+ with Priority => Ceiling is new Queue_Interfaces.Queue with
overriding
entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
diff --git a/gcc/ada/a-ciorma.adb b/gcc/ada/a-ciorma.adb
index 0947654a64c..3de57c76aa4 100644
--- a/gcc/ada/a-ciorma.adb
+++ b/gcc/ada/a-ciorma.adb
@@ -1152,7 +1152,6 @@ package body Ada.Containers.Indefinite_Ordered_Maps is
return Reference_Type
is
Node : aliased Element_Type := Element (Container, Key);
-
begin
return (Element => Node'Access);
end Reference;
diff --git a/gcc/ada/a-convec.adb b/gcc/ada/a-convec.adb
index a357cec8e89..a57f7fbd9a8 100644
--- a/gcc/ada/a-convec.adb
+++ b/gcc/ada/a-convec.adb
@@ -802,7 +802,7 @@ package body Ada.Containers.Vectors is
if Is_Empty (Object.Container.all) then
return No_Element;
else
- return Cursor'(Object.Container, Index_Type'First);
+ return (Object.Container, Index_Type'First);
end if;
end First;
@@ -1517,7 +1517,7 @@ package body Ada.Containers.Vectors is
Insert (Container, Index, New_Item);
- Position := Cursor'(Container'Unchecked_Access, Index);
+ Position := (Container'Unchecked_Access, Index);
end Insert;
procedure Insert
@@ -1600,7 +1600,7 @@ package body Ada.Containers.Vectors is
Insert (Container, Index, New_Item, Count);
- Position := Cursor'(Container'Unchecked_Access, Index);
+ Position := (Container'Unchecked_Access, Index);
end Insert;
procedure Insert
@@ -2017,7 +2017,7 @@ package body Ada.Containers.Vectors is
Insert_Space (Container, Index, Count => Count);
- Position := Cursor'(Container'Unchecked_Access, Index);
+ Position := (Container'Unchecked_Access, Index);
end Insert_Space;
--------------
@@ -2093,7 +2093,7 @@ package body Ada.Containers.Vectors is
if Is_Empty (Object.Container.all) then
return No_Element;
else
- return Cursor'(Object.Container, Object.Container.Last);
+ return (Object.Container, Object.Container.Last);
end if;
end Last;
@@ -2204,24 +2204,18 @@ package body Ada.Containers.Vectors is
function Next (Object : Iterator; Position : Cursor) return Cursor is
begin
- if Position.Index = Object.Container.Last then
- return No_Element;
- else
+ if Position.Index < Object.Container.Last then
return (Object.Container, Position.Index + 1);
+ else
+ return No_Element;
end if;
end Next;
- ----------
- -- Next --
- ----------
-
procedure Next (Position : in out Cursor) is
begin
if Position.Container = null then
return;
- end if;
-
- if Position.Index < Position.Container.Last then
+ elsif Position.Index < Position.Container.Last then
Position.Index := Position.Index + 1;
else
Position := No_Element;
@@ -2253,30 +2247,15 @@ package body Ada.Containers.Vectors is
-- Previous --
--------------
- procedure Previous (Position : in out Cursor) is
- begin
- if Position.Container = null then
- return;
- end if;
-
- if Position.Index > Index_Type'First then
- Position.Index := Position.Index - 1;
- else
- Position := No_Element;
- end if;
- end Previous;
-
function Previous (Position : Cursor) return Cursor is
begin
if Position.Container = null then
return No_Element;
- end if;
-
- if Position.Index > Index_Type'First then
+ elsif Position.Index > Index_Type'First then
return (Position.Container, Position.Index - 1);
+ else
+ return No_Element;
end if;
-
- return No_Element;
end Previous;
function Previous (Object : Iterator; Position : Cursor) return Cursor is
@@ -2288,6 +2267,17 @@ package body Ada.Containers.Vectors is
end if;
end Previous;
+ procedure Previous (Position : in out Cursor) is
+ begin
+ if Position.Container = null then
+ return;
+ elsif Position.Index > Index_Type'First then
+ Position.Index := Position.Index - 1;
+ else
+ Position := No_Element;
+ end if;
+ end Previous;
+
-------------------
-- Query_Element --
-------------------
@@ -2416,7 +2406,7 @@ package body Ada.Containers.Vectors is
return Constant_Reference_Type
is
begin
- if (Position) > Container.Last then
+ if Position > Container.Last then
raise Constraint_Error with "Index is out of range";
else
return (Element => Container.Elements.EA (Position)'Access);
@@ -3019,7 +3009,7 @@ package body Ada.Containers.Vectors is
if Index not in Index_Type'First .. Container.Last then
return No_Element;
else
- return Cursor'(Container'Unchecked_Access, Index);
+ return (Container'Unchecked_Access, Index);
end if;
end To_Cursor;
diff --git a/gcc/ada/a-convec.ads b/gcc/ada/a-convec.ads
index c6815d31ebb..c90cf01bde9 100644
--- a/gcc/ada/a-convec.ads
+++ b/gcc/ada/a-convec.ads
@@ -409,8 +409,8 @@ private
for Vector_Access'Storage_Size use 0;
type Cursor is record
- Container : Vector_Access;
- Index : Index_Type := Index_Type'First;
+ Container : Vector_Access;
+ Index : Index_Type := Index_Type'First;
end record;
procedure Write
diff --git a/gcc/ada/a-csquin.ads b/gcc/ada/a-csquin.ads
index 2a4d0b36eec..7567444177e 100644
--- a/gcc/ada/a-csquin.ads
+++ b/gcc/ada/a-csquin.ads
@@ -42,12 +42,24 @@ package Ada.Containers.Synchronized_Queue_Interfaces is
procedure Enqueue
(Container : in out Queue;
New_Item : Element_Type) is abstract;
- -- with Is_Synchronized => By_Entry; ???
+
+ -- ???
+ -- This is the official Ada 2012 syntax:
+ -- with Synchronization => By_Entry;
+
+ -- This is the temporary work-around:
+ pragma Implemented (Enqueue, By_Entry);
procedure Dequeue
(Container : in out Queue;
Element : out Element_Type) is abstract;
- -- with Is_Synchronized => By_Entry; ???
+
+ -- ???
+ -- This is the official Ada 2012 syntax:
+ -- with Synchronization => By_Entry;
+
+ -- This is the temporary work-around:
+ pragma Implemented (Dequeue, By_Entry);
function Current_Use (Container : Queue) return Count_Type is abstract;
diff --git a/gcc/ada/a-cuprqu.adb b/gcc/ada/a-cuprqu.adb
index 385aa5ce7d2..4f6966dc136 100644
--- a/gcc/ada/a-cuprqu.adb
+++ b/gcc/ada/a-cuprqu.adb
@@ -72,8 +72,29 @@ package body Ada.Containers.Unbounded_Priority_Queues is
Success : out Boolean)
is
begin
+ -- This operation dequeues a high priority item if it exists in the
+ -- queue. By "high priority" we mean an item whose priority is equal
+ -- or greater than the value At_Least. The generic formal operation
+ -- Before has the meaning "has higher priority than". To dequeue an
+ -- item (meaning that we return True as our Success value), we need
+ -- as our predicate the equivalent of "has equal or higher priority
+ -- than", but we cannot say that directly, so we require some logical
+ -- gymnastics to make it so.
+
+ -- If E is the element at the head of the queue, and symbol ">"
+ -- refers to the "is higher priority than" function Before, then we
+ -- derive our predicate as follows:
+ -- original: P(E) >= At_Least
+ -- same as: not (P(E) < At_Least)
+ -- same as: not (At_Least > P(E))
+ -- same as: not Before (At_Least, P(E))
+
+ -- But that predicate needs to be true in order to successfully
+ -- dequeue an item. If it's false, it means no item is dequeued, and
+ -- we return False as the Success value.
+
if List.Length = 0
- or else not Before (At_Least, Get_Priority (List.First.Element))
+ or else Before (At_Least, Get_Priority (List.First.Element))
then
Success := False;
return;
diff --git a/gcc/ada/a-cuprqu.ads b/gcc/ada/a-cuprqu.ads
index 33db4a281f3..3709f42aa29 100644
--- a/gcc/ada/a-cuprqu.ads
+++ b/gcc/ada/a-cuprqu.ads
@@ -52,11 +52,11 @@ generic
package Ada.Containers.Unbounded_Priority_Queues is
pragma Preelaborate;
- -- All identifiers in this unit are implementation defined
+ package Implementation is
- pragma Implementation_Defined;
+ -- All identifiers in this unit are implementation defined
- package Implementation is
+ pragma Implementation_Defined;
type List_Type is tagged limited private;
@@ -100,9 +100,7 @@ package Ada.Containers.Unbounded_Priority_Queues is
end Implementation;
protected type Queue (Ceiling : System.Any_Priority := Default_Ceiling)
- -- ???
- -- with Priority => Ceiling is new Queue_Interfaces.Queue with
- is new Queue_Interfaces.Queue with
+ with Priority => Ceiling is new Queue_Interfaces.Queue with
overriding
entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
diff --git a/gcc/ada/a-cusyqu.ads b/gcc/ada/a-cusyqu.ads
index 98337a03587..c4f9d7f7d59 100644
--- a/gcc/ada/a-cusyqu.ads
+++ b/gcc/ada/a-cusyqu.ads
@@ -44,11 +44,11 @@ generic
package Ada.Containers.Unbounded_Synchronized_Queues is
pragma Preelaborate;
- -- All identifiers in this unit are implementation defined
+ package Implementation is
- pragma Implementation_Defined;
+ -- All identifiers in this unit are implementation defined
- package Implementation is
+ pragma Implementation_Defined;
type List_Type is tagged limited private;
@@ -86,9 +86,7 @@ package Ada.Containers.Unbounded_Synchronized_Queues is
end Implementation;
protected type Queue (Ceiling : System.Any_Priority := Default_Ceiling)
- -- ???
- -- with Priority => Ceiling is new Queue_Interfaces.Queue with
- is new Queue_Interfaces.Queue with
+ with Priority => Ceiling is new Queue_Interfaces.Queue with
overriding
entry Enqueue (New_Item : Queue_Interfaces.Element_Type);
diff --git a/gcc/ada/a-ngcoar.adb b/gcc/ada/a-ngcoar.adb
index 9979d6baec6..3be88491d7f 100644
--- a/gcc/ada/a-ngcoar.adb
+++ b/gcc/ada/a-ngcoar.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2006-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 2006-2011, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -30,66 +30,35 @@
------------------------------------------------------------------------------
with System.Generic_Array_Operations; use System.Generic_Array_Operations;
-with System.Generic_Complex_BLAS;
-with System.Generic_Complex_LAPACK;
+with Ada.Numerics; use Ada.Numerics;
package body Ada.Numerics.Generic_Complex_Arrays is
- -- Operations involving inner products use BLAS library implementations.
- -- This allows larger matrices and vectors to be computed efficiently,
- -- taking into account memory hierarchy issues and vector instructions
- -- that vary widely between machines.
-
-- Operations that are defined in terms of operations on the type Real,
-- such as addition, subtraction and scaling, are computed in the canonical
-- way looping over all elements.
- -- Operations for solving linear systems and computing determinant,
- -- eigenvalues, eigensystem and inverse, are implemented using the
- -- LAPACK library.
-
- type BLAS_Real_Vector is array (Integer range <>) of Real;
-
- package BLAS is new System.Generic_Complex_BLAS
- (Real => Real,
- Complex_Types => Complex_Types,
- Complex_Vector => Complex_Vector,
- Complex_Matrix => Complex_Matrix);
-
- package LAPACK is new System.Generic_Complex_LAPACK
- (Real => Real,
- Real_Vector => BLAS_Real_Vector,
- Complex_Types => Complex_Types,
- Complex_Vector => Complex_Vector,
- Complex_Matrix => Complex_Matrix);
+ package Ops renames System.Generic_Array_Operations;
subtype Real is Real_Arrays.Real;
-- Work around visibility bug ???
- use BLAS, LAPACK;
-
- -- Procedure versions of functions returning unconstrained values.
- -- This allows for inlining the function wrapper.
+ function Is_Non_Zero (X : Complex) return Boolean is (X /= (0.0, 0.0));
+ -- Needed by Back_Substitute
- procedure Eigenvalues
- (A : Complex_Matrix;
- Values : out Real_Vector);
+ procedure Back_Substitute is new Ops.Back_Substitute
+ (Scalar => Complex,
+ Matrix => Complex_Matrix,
+ Is_Non_Zero => Is_Non_Zero);
- procedure Inverse
- (A : Complex_Matrix;
- R : out Complex_Matrix);
+ procedure Forward_Eliminate is new Ops.Forward_Eliminate
+ (Scalar => Complex,
+ Real => Real'Base,
+ Matrix => Complex_Matrix,
+ Zero => (0.0, 0.0),
+ One => (1.0, 0.0));
- procedure Solve
- (A : Complex_Matrix;
- X : Complex_Vector;
- B : out Complex_Vector);
-
- procedure Solve
- (A : Complex_Matrix;
- X : Complex_Matrix;
- B : out Complex_Matrix);
-
- procedure Transpose is new System.Generic_Array_Operations.Transpose
+ procedure Transpose is new Ops.Transpose
(Scalar => Complex,
Matrix => Complex_Matrix);
@@ -98,6 +67,12 @@ package body Ada.Numerics.Generic_Complex_Arrays is
function Length is new Square_Matrix_Length (Complex, Complex_Matrix);
+ -- Instant a generic square root implementation here, in order to avoid
+ -- instantiating a complete copy of Generic_Elementary_Functions.
+ -- Speed of the square root is not a big concern here.
+
+ function Sqrt is new Ops.Sqrt (Real'Base);
+
-- Instantiating the following subprograms directly would lead to
-- name clashes, so use a local package.
@@ -155,6 +130,14 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Right_Vector => Complex_Vector,
Zero => (0.0, 0.0));
+ function "*" is new Inner_Product
+ (Left_Scalar => Complex,
+ Right_Scalar => Complex,
+ Result_Scalar => Complex,
+ Left_Vector => Complex_Vector,
+ Right_Vector => Complex_Vector,
+ Zero => (0.0, 0.0));
+
function "*" is new Outer_Product
(Left_Scalar => Complex,
Right_Scalar => Complex,
@@ -229,6 +212,15 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Result_Vector => Complex_Vector,
Zero => (0.0, 0.0));
+ function "*" is new Matrix_Vector_Product
+ (Left_Scalar => Complex,
+ Right_Scalar => Complex,
+ Result_Scalar => Complex,
+ Matrix => Complex_Matrix,
+ Right_Vector => Complex_Vector,
+ Result_Vector => Complex_Vector,
+ Zero => (0.0, 0.0));
+
function "*" is new Vector_Matrix_Product
(Left_Scalar => Real'Base,
Right_Scalar => Complex,
@@ -247,6 +239,24 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Result_Vector => Complex_Vector,
Zero => (0.0, 0.0));
+ function "*" is new Vector_Matrix_Product
+ (Left_Scalar => Complex,
+ Right_Scalar => Complex,
+ Result_Scalar => Complex,
+ Left_Vector => Complex_Vector,
+ Matrix => Complex_Matrix,
+ Result_Vector => Complex_Vector,
+ Zero => (0.0, 0.0));
+
+ function "*" is new Matrix_Matrix_Product
+ (Left_Scalar => Complex,
+ Right_Scalar => Complex,
+ Result_Scalar => Complex,
+ Left_Matrix => Complex_Matrix,
+ Right_Matrix => Complex_Matrix,
+ Result_Matrix => Complex_Matrix,
+ Zero => (0.0, 0.0));
+
function "*" is new Matrix_Matrix_Product
(Left_Scalar => Real'Base,
Right_Scalar => Complex,
@@ -445,6 +455,15 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Result_Matrix => Complex_Matrix,
Operation => "/");
+ -----------
+ -- "abs" --
+ -----------
+
+ function "abs" is new L2_Norm
+ (X_Scalar => Complex,
+ Result_Real => Real'Base,
+ X_Vector => Complex_Vector);
+
--------------
-- Argument --
--------------
@@ -671,6 +690,16 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Y_Matrix => Real_Matrix,
Update => Set_Re);
+ -----------
+ -- Solve --
+ -----------
+
+ function Solve is
+ new Matrix_Vector_Solution (Complex, Complex_Vector, Complex_Matrix);
+
+ function Solve is
+ new Matrix_Matrix_Solution (Complex, Complex_Matrix);
+
-----------------
-- Unit_Matrix --
-----------------
@@ -686,7 +715,6 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Vector => Complex_Vector,
Zero => (0.0, 0.0),
One => (1.0, 0.0));
-
end Instantiations;
---------
@@ -696,15 +724,7 @@ package body Ada.Numerics.Generic_Complex_Arrays is
function "*"
(Left : Complex_Vector;
Right : Complex_Vector) return Complex
- is
- begin
- if Left'Length /= Right'Length then
- raise Constraint_Error with
- "vectors are of different length in inner product";
- end if;
-
- return dot (Left'Length, X => Left, Y => Right);
- end "*";
+ renames Instantiations."*";
function "*"
(Left : Real_Vector;
@@ -738,31 +758,8 @@ package body Ada.Numerics.Generic_Complex_Arrays is
function "*"
(Left : Complex_Matrix;
- Right : Complex_Matrix)
- return Complex_Matrix
- is
- R : Complex_Matrix (Left'Range (1), Right'Range (2));
-
- begin
- if Left'Length (2) /= Right'Length (1) then
- raise Constraint_Error with
- "incompatible dimensions in matrix-matrix multiplication";
- end if;
-
- gemm (Trans_A => No_Trans'Access,
- Trans_B => No_Trans'Access,
- M => Right'Length (2),
- N => Left'Length (1),
- K => Right'Length (1),
- A => Right,
- Ld_A => Right'Length (2),
- B => Left,
- Ld_B => Left'Length (2),
- C => R,
- Ld_C => R'Length (2));
-
- return R;
- end "*";
+ Right : Complex_Matrix) return Complex_Matrix
+ renames Instantiations."*";
function "*"
(Left : Complex_Vector;
@@ -772,48 +769,12 @@ package body Ada.Numerics.Generic_Complex_Arrays is
function "*"
(Left : Complex_Vector;
Right : Complex_Matrix) return Complex_Vector
- is
- R : Complex_Vector (Right'Range (2));
-
- begin
- if Left'Length /= Right'Length (1) then
- raise Constraint_Error with
- "incompatible dimensions in vector-matrix multiplication";
- end if;
-
- gemv (Trans => No_Trans'Access,
- M => Right'Length (2),
- N => Right'Length (1),
- A => Right,
- Ld_A => Right'Length (2),
- X => Left,
- Y => R);
-
- return R;
- end "*";
+ renames Instantiations."*";
function "*"
(Left : Complex_Matrix;
Right : Complex_Vector) return Complex_Vector
- is
- R : Complex_Vector (Left'Range (1));
-
- begin
- if Left'Length (2) /= Right'Length then
- raise Constraint_Error with
- "incompatible dimensions in matrix-vector multiplication";
- end if;
-
- gemv (Trans => Trans'Access,
- M => Left'Length (2),
- N => Left'Length (1),
- A => Left,
- Ld_A => Left'Length (2),
- X => Right,
- Y => R);
-
- return R;
- end "*";
+ renames Instantiations."*";
function "*"
(Left : Real_Matrix;
@@ -984,10 +945,8 @@ package body Ada.Numerics.Generic_Complex_Arrays is
-- "abs" --
-----------
- function "abs" (Right : Complex_Vector) return Complex is
- begin
- return (nrm2 (Right'Length, Right), 0.0);
- end "abs";
+ function "abs" (Right : Complex_Vector) return Real'Base
+ renames Instantiations."abs";
--------------
-- Argument --
@@ -1070,38 +1029,12 @@ package body Ada.Numerics.Generic_Complex_Arrays is
-----------------
function Determinant (A : Complex_Matrix) return Complex is
- N : constant Integer := Length (A);
- LU : Complex_Matrix (1 .. N, 1 .. N) := A;
- Piv : Integer_Vector (1 .. N);
- Info : aliased Integer := -1;
- Neg : Boolean;
- Det : Complex;
-
+ M : Complex_Matrix := A;
+ B : Complex_Matrix (A'Range (1), 1 .. 0);
+ R : Complex;
begin
- if N = 0 then
- return (0.0, 0.0);
- end if;
-
- getrf (N, N, LU, N, Piv, Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "ill-conditioned matrix";
- end if;
-
- Det := LU (1, 1);
- Neg := Piv (1) /= 1;
-
- for J in 2 .. N loop
- Det := Det * LU (J, J);
- Neg := Neg xor (Piv (J) /= J);
- end loop;
-
- if Neg then
- return -Det;
-
- else
- return Det;
- end if;
+ Forward_Eliminate (M, B, R);
+ return R;
end Determinant;
-----------------
@@ -1113,174 +1046,96 @@ package body Ada.Numerics.Generic_Complex_Arrays is
Values : out Real_Vector;
Vectors : out Complex_Matrix)
is
- Job_Z : aliased Character := 'V';
- Rng : aliased Character := 'A';
- Uplo : aliased Character := 'U';
-
- N : constant Natural := Length (A);
- W : BLAS_Real_Vector (Values'Range);
- M : Integer;
- B : Complex_Matrix (1 .. N, 1 .. N);
- L_Work : Complex_Vector (1 .. 1);
- LR_Work : BLAS_Real_Vector (1 .. 1);
- LI_Work : Integer_Vector (1 .. 1);
- I_Supp_Z : Integer_Vector (1 .. 2 * N);
- Info : aliased Integer;
+ N : constant Natural := Length (A);
+
+ -- For a Hermitian matrix C, we convert the eigenvalue problem to a
+ -- real symmetric one: if C = A + i * B, then the (N, N) complex
+ -- eigenvalue problem:
+ -- (A + i * B) * (u + i * v) = Lambda * (u + i * v)
+ --
+ -- is equivalent to the (2 * N, 2 * N) real eigenvalue problem:
+ -- [ A, B ] [ u ] = Lambda * [ u ]
+ -- [ -B, A ] [ v ] [ v ]
+ --
+ -- Note that the (2 * N, 2 * N) matrix above is symmetric, as
+ -- Transpose (A) = A and Transpose (B) = -B if C is Hermitian.
+
+ -- We solve this eigensystem using the real-valued algorithms. The final
+ -- result will have every eigenvalue twice, so in the sorted output we
+ -- just pick every second value, with associated eigenvector u + i * v.
+
+ M : Real_Matrix (1 .. 2 * N, 1 .. 2 * N);
+ Vals : Real_Vector (1 .. 2 * N);
+ Vecs : Real_Matrix (1 .. 2 * N, 1 .. 2 * N);
begin
- if Values'Length /= N then
- raise Constraint_Error with "wrong length for output vector";
- end if;
-
- if Vectors'First (1) /= A'First (1)
- or else Vectors'Last (1) /= A'Last (1)
- or else Vectors'First (2) /= A'First (2)
- or else Vectors'Last (2) /= A'Last (2)
- then
- raise Constraint_Error with "wrong dimensions for output matrix";
- end if;
-
- if N = 0 then
- return;
- end if;
-
- -- Check for hermitian matrix ???
- -- Copy only required triangle ???
-
- B := A;
-
- -- Find size of work area
-
- heevr
- (Job_Z'Access, Rng'Access, Uplo'Access, N, B, N,
- M => M,
- W => W,
- Z => Vectors,
- Ld_Z => N,
- I_Supp_Z => I_Supp_Z,
- Work => L_Work,
- L_Work => -1,
- R_Work => LR_Work,
- LR_Work => -1,
- I_Work => LI_Work,
- LI_Work => -1,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error;
- end if;
-
- declare
- Work : Complex_Vector (1 .. Integer (L_Work (1).Re));
- R_Work : BLAS_Real_Vector (1 .. Integer (LR_Work (1)));
- I_Work : Integer_Vector (1 .. LI_Work (1));
-
- begin
- heevr
- (Job_Z'Access, Rng'Access, Uplo'Access, N, B, N,
- M => M,
- W => W,
- Z => Vectors,
- Ld_Z => N,
- I_Supp_Z => I_Supp_Z,
- Work => Work,
- L_Work => Work'Length,
- R_Work => R_Work,
- LR_Work => LR_Work'Length,
- I_Work => I_Work,
- LI_Work => LI_Work'Length,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "inverting non-Hermitian matrix";
- end if;
-
- for J in Values'Range loop
- Values (J) := W (J);
+ for J in 1 .. N loop
+ for K in 1 .. N loop
+ declare
+ C : constant Complex :=
+ (A (A'First (1) + (J - 1), A'First (2) + (K - 1)));
+ begin
+ M (J, K) := Re (C);
+ M (J + N, K + N) := Re (C);
+ M (J + N, K) := Im (C);
+ M (J, K + N) := -Im (C);
+ end;
end loop;
- end;
+ end loop;
+
+ Eigensystem (M, Vals, Vecs);
+
+ for J in 1 .. N loop
+ declare
+ Col : constant Integer := Values'First + (J - 1);
+ begin
+ Values (Col) := Vals (2 * J);
+
+ for K in 1 .. N loop
+ declare
+ Row : constant Integer := Vectors'First (2) + (K - 1);
+ begin
+ Vectors (Row, Col)
+ := (Vecs (J * 2, Col), Vecs (J * 2, Col + N));
+ end;
+ end loop;
+ end;
+ end loop;
end Eigensystem;
-----------------
-- Eigenvalues --
-----------------
- procedure Eigenvalues
- (A : Complex_Matrix;
- Values : out Real_Vector)
- is
- Job_Z : aliased Character := 'N';
- Rng : aliased Character := 'A';
- Uplo : aliased Character := 'U';
- N : constant Natural := Length (A);
- B : Complex_Matrix (1 .. N, 1 .. N) := A;
- Z : Complex_Matrix (1 .. 1, 1 .. 1);
- W : BLAS_Real_Vector (Values'Range);
- L_Work : Complex_Vector (1 .. 1);
- LR_Work : BLAS_Real_Vector (1 .. 1);
- LI_Work : Integer_Vector (1 .. 1);
- I_Supp_Z : Integer_Vector (1 .. 2 * N);
- M : Integer;
- Info : aliased Integer;
+ function Eigenvalues (A : Complex_Matrix) return Real_Vector is
+ -- See Eigensystem for a description of the algorithm
+ N : constant Natural := Length (A);
+ R : Real_Vector (A'Range (1));
+
+ M : Real_Matrix (1 .. 2 * N, 1 .. 2 * N);
+ Vals : Real_Vector (1 .. 2 * N);
begin
- if Values'Length /= N then
- raise Constraint_Error with "wrong length for output vector";
- end if;
-
- if N = 0 then
- return;
- end if;
-
- -- Check for hermitian matrix ???
-
- -- Find size of work area
-
- heevr (Job_Z'Access, Rng'Access, Uplo'Access, N, B, N,
- M => M,
- W => W,
- Z => Z,
- Ld_Z => 1,
- I_Supp_Z => I_Supp_Z,
- Work => L_Work, L_Work => -1,
- R_Work => LR_Work, LR_Work => -1,
- I_Work => LI_Work, LI_Work => -1,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error;
- end if;
-
- declare
- Work : Complex_Vector (1 .. Integer (L_Work (1).Re));
- R_Work : BLAS_Real_Vector (1 .. Integer (LR_Work (1)));
- I_Work : Integer_Vector (1 .. LI_Work (1));
- begin
- heevr (Job_Z'Access, Rng'Access, Uplo'Access, N, B, N,
- M => M,
- W => W,
- Z => Z,
- Ld_Z => 1,
- I_Supp_Z => I_Supp_Z,
- Work => Work, L_Work => Work'Length,
- R_Work => R_Work, LR_Work => R_Work'Length,
- I_Work => I_Work, LI_Work => I_Work'Length,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "inverting singular matrix";
- end if;
-
- for J in Values'Range loop
- Values (J) := W (J);
+ for J in 1 .. N loop
+ for K in 1 .. N loop
+ declare
+ C : constant Complex :=
+ (A (A'First (1) + (J - 1), A'First (2) + (K - 1)));
+ begin
+ M (J, K) := Re (C);
+ M (J + N, K + N) := Re (C);
+ M (J + N, K) := Im (C);
+ M (J, K + N) := -Im (C);
+ end;
end loop;
- end;
- end Eigenvalues;
+ end loop;
+
+ Vals := Eigenvalues (M);
+
+ for J in 1 .. N loop
+ R (A'First (1) + (J - 1)) := Vals (2 * J);
+ end loop;
- function Eigenvalues (A : Complex_Matrix) return Real_Vector is
- R : Real_Vector (A'Range (1));
- begin
- Eigenvalues (A, R);
return R;
end Eigenvalues;
@@ -1298,73 +1153,8 @@ package body Ada.Numerics.Generic_Complex_Arrays is
-- Inverse --
-------------
- procedure Inverse (A : Complex_Matrix; R : out Complex_Matrix) is
- N : constant Integer := Length (A);
- Piv : Integer_Vector (1 .. N);
- L_Work : Complex_Vector (1 .. 1);
- Info : aliased Integer := -1;
-
- begin
- -- All computations are done using column-major order, but this works
- -- out fine, because Transpose (Inverse (Transpose (A))) = Inverse (A).
-
- R := A;
-
- -- Compute LU decomposition
-
- getrf (M => N,
- N => N,
- A => R,
- Ld_A => N,
- I_Piv => Piv,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "inverting singular matrix";
- end if;
-
- -- Determine size of work area
-
- getri (N => N,
- A => R,
- Ld_A => N,
- I_Piv => Piv,
- Work => L_Work,
- L_Work => -1,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error;
- end if;
-
- declare
- Work : Complex_Vector (1 .. Integer (L_Work (1).Re));
-
- begin
- -- Compute inverse from LU decomposition
-
- getri (N => N,
- A => R,
- Ld_A => N,
- I_Piv => Piv,
- Work => Work,
- L_Work => Work'Length,
- Info => Info'Access);
-
- if Info /= 0 then
- raise Constraint_Error with "inverting singular matrix";
- end if;
-
- -- ??? Should iterate with gerfs, based on implementation advice
- end;
- end Inverse;
-
function Inverse (A : Complex_Matrix) return Complex_Matrix is
- R : Complex_Matrix (A'Range (2), A'Range (1));
- begin
- Inverse (A, R);
- return R;
- end Inverse;
+ (Solve (A, Unit_Matrix (Length (A))));
-------------
-- Modulus --
@@ -1418,53 +1208,15 @@ package body Ada.Numerics.Generic_Complex_Arrays is
-- Solve --
-----------
- procedure Solve
- (A : Complex_Matrix;
- X : Complex_Vector;
- B : out Complex_Vector)
- is
- begin
- if Length (A) /= X'Length then
- raise Constraint_Error with
- "incompatible matrix and vector dimensions";
- end if;
-
- -- ??? Should solve directly, is faster and more accurate
-
- B := Inverse (A) * X;
- end Solve;
-
- procedure Solve
- (A : Complex_Matrix;
- X : Complex_Matrix;
- B : out Complex_Matrix)
- is
- begin
- if Length (A) /= X'Length (1) then
- raise Constraint_Error with "incompatible matrix dimensions";
- end if;
-
- -- ??? Should solve directly, is faster and more accurate
-
- B := Inverse (A) * X;
- end Solve;
-
function Solve
(A : Complex_Matrix;
X : Complex_Vector) return Complex_Vector
- is
- B : Complex_Vector (A'Range (2));
- begin
- Solve (A, X, B);
- return B;
- end Solve;
+ renames Instantiations.Solve;
- function Solve (A, X : Complex_Matrix) return Complex_Matrix is
- B : Complex_Matrix (A'Range (2), X'Range (2));
- begin
- Solve (A, X, B);
- return B;
- end Solve;
+ function Solve
+ (A : Complex_Matrix;
+ X : Complex_Matrix) return Complex_Matrix
+ renames Instantiations.Solve;
---------------
-- Transpose --
diff --git a/gcc/ada/a-ngcoar.ads b/gcc/ada/a-ngcoar.ads
index abffbd1b636..8f8f37a7906 100644
--- a/gcc/ada/a-ngcoar.ads
+++ b/gcc/ada/a-ngcoar.ads
@@ -66,7 +66,7 @@ package Ada.Numerics.Generic_Complex_Arrays is
function "+" (Left, Right : Complex_Vector) return Complex_Vector;
function "-" (Left, Right : Complex_Vector) return Complex_Vector;
function "*" (Left, Right : Complex_Vector) return Complex;
- function "abs" (Right : Complex_Vector) return Complex;
+ function "abs" (Right : Complex_Vector) return Real'Base;
-- Mixed Real_Vector and Complex_Vector arithmetic operations
diff --git a/gcc/ada/a-ngrear.adb b/gcc/ada/a-ngrear.adb
index 8ce8d9a98b0..2a740b5c6b4 100644
--- a/gcc/ada/a-ngrear.adb
+++ b/gcc/ada/a-ngrear.adb
@@ -33,7 +33,7 @@
-- reason for this is new Ada 2012 requirements that prohibit algorithms such
-- as Strassen's algorithm, which may be used by some BLAS implementations. In
-- addition, some platforms lacked suitable compilers to compile the reference
--- BLAS/LAPACK implementation. Finally, on many platforms there may be more
+-- BLAS/LAPACK implementation. Finally, on some platforms there are more
-- floating point types than supported by BLAS/LAPACK.
with Ada.Containers.Generic_Anonymous_Array_Sort; use Ada.Containers;
@@ -59,6 +59,7 @@ package body Ada.Numerics.Generic_Real_Arrays is
procedure Forward_Eliminate is new Ops.Forward_Eliminate
(Scalar => Real'Base,
+ Real => Real'Base,
Matrix => Real_Matrix,
Zero => 0.0,
One => 1.0);
@@ -102,10 +103,10 @@ package body Ada.Numerics.Generic_Real_Arrays is
procedure Swap (Left, Right : in out Real);
-- Exchange Left and Right
- function Sqrt (X : Real) return Real;
- -- Sqrt is implemented locally here, in order to avoid dragging in all of
- -- the elementary functions. Speed of the square root is not a big concern
- -- here. This also avoids depending on a specific floating point type.
+ function Sqrt is new Ops.Sqrt (Real);
+ -- Instant a generic square root implementation here, in order to avoid
+ -- instantiating a complete copy of Generic_Elementary_Functions.
+ -- Speed of the square root is not a big concern here.
------------
-- Rotate --
@@ -120,51 +121,6 @@ package body Ada.Numerics.Generic_Real_Arrays is
end Rotate;
----------
- -- Sqrt --
- ----------
-
- function Sqrt (X : Real) return Real is
- Root, Next : Real;
-
- begin
- -- Be defensive: any comparisons with NaN values will yield False.
-
- if not (X > 0.0) then
- if X = 0.0 then
- return X;
- else
- raise Argument_Error;
- end if;
- end if;
-
- -- Compute an initial estimate based on:
-
- -- X = M * R**E and Sqrt (X) = Sqrt (M) * R**(E / 2.0),
-
- -- where M is the mantissa, R is the radix and E the exponent.
-
- -- By ignoring the mantissa and ignoring the case of an odd
- -- exponent, we get a final error that is at most R. In other words,
- -- the result has about a single bit precision.
-
- Root := Real (Real'Machine_Radix) ** (Real'Exponent (X) / 2);
-
- -- Because of the poor initial estimate, use the Babylonian method of
- -- computing the square root, as it is stable for all inputs. Every step
- -- will roughly double the precision of the result. Just a few steps
- -- suffice in most cases. Eight iterations should give about 2**8 bits
- -- of precision.
-
- for J in 1 .. 8 loop
- Next := (Root + X / Root) / 2.0;
- exit when Root = Next;
- Root := Next;
- end loop;
-
- return Root;
- end Sqrt;
-
- ----------
-- Swap --
----------
@@ -356,10 +312,14 @@ package body Ada.Numerics.Generic_Real_Arrays is
function "abs" is new
L2_Norm
- (Scalar => Real'Base,
- Vector => Real_Vector,
- Inner_Product => "*",
- Sqrt => Sqrt);
+ (X_Scalar => Real'Base,
+ Result_Real => Real'Base,
+ X_Vector => Real_Vector,
+ "abs" => "+");
+ -- While the L2_Norm by definition uses the absolute values of the
+ -- elements of X_Vector, for real values the subsequent squaring
+ -- makes this unnecessary, so we substitute the "+" identity function
+ -- instead.
function "abs" is new
Vector_Elementwise_Operation
@@ -377,6 +337,11 @@ package body Ada.Numerics.Generic_Real_Arrays is
Result_Matrix => Real_Matrix,
Operation => "abs");
+ function Solve is
+ new Matrix_Vector_Solution (Real'Base, Real_Vector, Real_Matrix);
+
+ function Solve is new Matrix_Matrix_Solution (Real'Base, Real_Matrix);
+
function Unit_Matrix is new
Generic_Array_Operations.Unit_Matrix
(Scalar => Real'Base,
@@ -736,58 +701,11 @@ package body Ada.Numerics.Generic_Real_Arrays is
-- Solve --
-----------
- function Solve (A : Real_Matrix; X : Real_Vector) return Real_Vector is
- N : constant Natural := Length (A);
- MA : Real_Matrix := A;
- MX : Real_Matrix (A'Range (1), 1 .. 1);
- R : Real_Vector (A'Range (2));
- Det : Real'Base;
-
- begin
- if X'Length /= N then
- raise Constraint_Error with "incompatible vector length";
- end if;
-
- for J in 0 .. MX'Length (1) - 1 loop
- MX (MX'First (1) + J, 1) := X (X'First + J);
- end loop;
-
- Forward_Eliminate (MA, MX, Det);
- Back_Substitute (MA, MX);
-
- for J in 0 .. R'Length - 1 loop
- R (R'First + J) := MX (MX'First (1) + J, 1);
- end loop;
-
- return R;
- end Solve;
-
- function Solve (A, X : Real_Matrix) return Real_Matrix is
- N : constant Natural := Length (A);
- MA : Real_Matrix (A'Range (2), A'Range (2));
- MB : Real_Matrix (A'Range (2), X'Range (2));
- Det : Real'Base;
-
- begin
- if X'Length (1) /= N then
- raise Constraint_Error with "matrices have unequal number of rows";
- end if;
-
- for J in 0 .. A'Length (1) - 1 loop
- for K in MA'Range (2) loop
- MA (MA'First (1) + J, K) := A (A'First (1) + J, K);
- end loop;
-
- for K in MB'Range (2) loop
- MB (MB'First (1) + J, K) := X (X'First (1) + J, K);
- end loop;
- end loop;
-
- Forward_Eliminate (MA, MB, Det);
- Back_Substitute (MA, MB);
+ function Solve (A : Real_Matrix; X : Real_Vector) return Real_Vector
+ renames Instantiations.Solve;
- return MB;
- end Solve;
+ function Solve (A, X : Real_Matrix) return Real_Matrix
+ renames Instantiations.Solve;
----------------------
-- Sort_Eigensystem --
diff --git a/gcc/ada/a-tienau.adb b/gcc/ada/a-tienau.adb
index f0c1800f9e7..5498ca4f55d 100644
--- a/gcc/ada/a-tienau.adb
+++ b/gcc/ada/a-tienau.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -126,6 +126,25 @@ package body Ada.Text_IO.Enumeration_Aux is
Actual_Width : constant Count := Count'Max (Count (Width), Item'Length);
begin
+ -- Deal with limited line length
+
+ if Line_Length /= 0 then
+
+ -- If actual width exceeds line length, raise Layout_Error
+
+ if Actual_Width > Line_Length then
+ raise Layout_Error;
+ end if;
+
+ -- If full width cannot fit on current line move to new line
+
+ if Actual_Width + (Col - 1) > Line_Length then
+ New_Line (File);
+ end if;
+ end if;
+
+ -- Output in lower case if necessary
+
if Set = Lower_Case and then Item (Item'First) /= ''' then
declare
Iteml : String (Item'First .. Item'Last);
@@ -138,10 +157,14 @@ package body Ada.Text_IO.Enumeration_Aux is
Put_Item (File, Iteml);
end;
+ -- Otherwise output in upper case
+
else
Put_Item (File, Item);
end if;
+ -- Fill out item with spaces to width
+
for J in 1 .. Actual_Width - Item'Length loop
Put (File, ' ');
end loop;
diff --git a/gcc/ada/back_end.adb b/gcc/ada/back_end.adb
index a089f3862c4..b6ad263c232 100644
--- a/gcc/ada/back_end.adb
+++ b/gcc/ada/back_end.adb
@@ -114,9 +114,13 @@ package body Back_End is
return;
end if;
+ -- The back end needs to know the maximum line number that can appear
+ -- in a Sloc, in other words the maximum logical line number.
+
for J in 1 .. Last_Source_File loop
File_Info_Array (J).File_Name := Full_Debug_Name (J);
- File_Info_Array (J).Num_Source_Lines := Num_Source_Lines (J);
+ File_Info_Array (J).Num_Source_Lines :=
+ Nat (Physical_To_Logical (Last_Source_Line (J), J));
end loop;
if Generate_SCIL then
diff --git a/gcc/ada/bindgen.adb b/gcc/ada/bindgen.adb
index f5a2bdcecad..d75fe06c51b 100644
--- a/gcc/ada/bindgen.adb
+++ b/gcc/ada/bindgen.adb
@@ -1893,25 +1893,6 @@ package body Bindgen is
Write_Str (Name_Buffer (1 .. Name_Len));
Write_Eol;
end if;
-
- -- Don't link with the shared library on VMS if an internal
- -- filename object is seen. Multiply defined symbols will
- -- result.
-
- if OpenVMS_On_Target
- and then Is_Internal_File_Name
- (ALIs.Table
- (Units.Table (Elab_Order.Table (E)).My_ALI).Sfile)
- then
- -- Special case for g-trasym.obj (not included in libgnat)
-
- Get_Name_String (ALIs.Table
- (Units.Table (Elab_Order.Table (E)).My_ALI).Sfile);
-
- if Name_Buffer (1 .. 8) /= "g-trasym" then
- Opt.Shared_Libgnat := False;
- end if;
- end if;
end if;
end if;
end loop;
diff --git a/gcc/ada/checks.adb b/gcc/ada/checks.adb
index e07d70e47be..f3234865dbd 100644
--- a/gcc/ada/checks.adb
+++ b/gcc/ada/checks.adb
@@ -2555,6 +2555,23 @@ package body Checks is
end if;
end Apply_Universal_Integer_Attribute_Checks;
+ -------------------------------------
+ -- Atomic_Synchronization_Disabled --
+ -------------------------------------
+
+ -- Note: internally Disable/Enable_Atomic_Synchronization is implemented
+ -- using a bogus check called Atomic_Synchronization. This is to make it
+ -- more convenient to get exactly the same semantics as [Un]Suppress.
+
+ function Atomic_Synchronization_Disabled (E : Entity_Id) return Boolean is
+ begin
+ if Present (E) and then Checks_May_Be_Suppressed (E) then
+ return Is_Check_Suppressed (E, Atomic_Synchronization);
+ else
+ return Scope_Suppress (Atomic_Synchronization);
+ end if;
+ end Atomic_Synchronization_Disabled;
+
-------------------------------
-- Build_Discriminant_Checks --
-------------------------------
diff --git a/gcc/ada/checks.ads b/gcc/ada/checks.ads
index 509a55c2533..83a67dcb814 100644
--- a/gcc/ada/checks.ads
+++ b/gcc/ada/checks.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -46,19 +46,20 @@ package Checks is
-- Called for each new main source program, to initialize internal
-- variables used in the package body of the Checks unit.
- function Access_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Accessibility_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Alignment_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Discriminant_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Division_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Elaboration_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Index_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Length_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Overflow_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Range_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Storage_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Tag_Checks_Suppressed (E : Entity_Id) return Boolean;
- function Validity_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Access_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Accessibility_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Alignment_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Atomic_Synchronization_Disabled (E : Entity_Id) return Boolean;
+ function Discriminant_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Division_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Elaboration_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Index_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Length_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Overflow_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Range_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Storage_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Tag_Checks_Suppressed (E : Entity_Id) return Boolean;
+ function Validity_Checks_Suppressed (E : Entity_Id) return Boolean;
-- These functions check to see if the named check is suppressed, either
-- by an active scope suppress setting, or because the check has been
-- specifically suppressed for the given entity. If no entity is relevant
diff --git a/gcc/ada/debug.adb b/gcc/ada/debug.adb
index b3eb5cfd8e8..99ba3d5585d 100644
--- a/gcc/ada/debug.adb
+++ b/gcc/ada/debug.adb
@@ -94,8 +94,8 @@ package body Debug is
-- d.a Force Target_Strict_Alignment mode to True
-- d.b Dump backend types
-- d.c Generate inline concatenation, do not call procedure
- -- d.d
- -- d.e
+ -- d.d Disable atomic synchronization
+ -- d.e Enable atomic synchronization
-- d.f Inhibit folding of static expressions
-- d.g Enable conversion of raise into goto
-- d.h
@@ -513,6 +513,13 @@ package body Debug is
-- System.Concat_n.Str_Concat_n routines in cases where the latter
-- routines would normally be called.
+ -- d.d Disable atomic synchronization for all atomic variable references.
+ -- Pragma Enable_Atomic_Synchronization is ignored.
+
+ -- d.e Enable atomic synchronization for all atomic variable references.
+ -- Pragma Disable_Atomic_Synchronization is ignored, and also the
+ -- compiler switch -gnated is ignored.
+
-- d.f Suppress folding of static expressions. This of course results
-- in seriously non-conforming behavior, but is useful sometimes
-- when tracking down handling of complex expressions.
diff --git a/gcc/ada/exp_aggr.adb b/gcc/ada/exp_aggr.adb
index d06d8b9fb54..783772f0188 100644
--- a/gcc/ada/exp_aggr.adb
+++ b/gcc/ada/exp_aggr.adb
@@ -3398,6 +3398,15 @@ package body Exp_Aggr is
begin
Assoc := First (Component_Associations (N));
while Present (Assoc) loop
+
+ -- If this is a box association, flattening is in general
+ -- not possible because at this point we cannot tell if the
+ -- default is static or even exists.
+
+ if Box_Present (Assoc) then
+ return False;
+ end if;
+
Choice := First (Choices (Assoc));
while Present (Choice) loop
@@ -3506,7 +3515,7 @@ package body Exp_Aggr is
-- active, if this is a preelaborable unit or a
-- predefined unit. This ensures that predefined
-- units get the same level of constant folding in
- -- Ada 95 and Ada 05, where their categorization
+ -- Ada 95 and Ada 2005, where their categorization
-- has changed.
declare
@@ -4148,6 +4157,12 @@ package body Exp_Aggr is
return False;
end if;
+ -- If association has a box, no way to determine yet
+ -- whether default can be assigned in place.
+
+ elsif Box_Present (Expr) then
+ return False;
+
elsif not Safe_Component (Expression (Expr)) then
return False;
end if;
diff --git a/gcc/ada/exp_ch2.adb b/gcc/ada/exp_ch2.adb
index 68483ffb393..a71ce69602e 100644
--- a/gcc/ada/exp_ch2.adb
+++ b/gcc/ada/exp_ch2.adb
@@ -24,6 +24,7 @@
------------------------------------------------------------------------------
with Atree; use Atree;
+with Checks; use Checks;
with Debug; use Debug;
with Einfo; use Einfo;
with Elists; use Elists;
@@ -354,10 +355,10 @@ package body Exp_Ch2 is
elsif Is_Protected_Component (E) then
if No_Run_Time_Mode then
return;
+ else
+ Expand_Protected_Component (N);
end if;
- Expand_Protected_Component (N);
-
elsif Ekind (E) = E_Entry_Index_Parameter then
Expand_Entry_Index_Parameter (N);
@@ -398,6 +399,52 @@ package body Exp_Ch2 is
Write_Eol;
end if;
+ -- Set Atomic_Sync_Required if necessary for atomic variable
+
+ if Is_Atomic (E) then
+ declare
+ Set : Boolean;
+ MLoc : Node_Id;
+
+ begin
+ -- Always set if debug flag d.e is set
+
+ if Debug_Flag_Dot_E then
+ Set := True;
+
+ -- Never set if debug flag d.d is set
+
+ elsif Debug_Flag_Dot_D then
+ Set := False;
+
+ -- Otherwise setting comes from Atomic_Synchronization state
+
+ else
+ Set := not Atomic_Synchronization_Disabled (E);
+ end if;
+
+ -- Set flag if required
+
+ if Set then
+
+ -- Generate info message if requested
+
+ if Warn_On_Atomic_Synchronization then
+ if Nkind (N) = N_Identifier then
+ MLoc := N;
+ else
+ MLoc := Selector_Name (N);
+ end if;
+
+ Error_Msg_N
+ ("?info: atomic synchronization set for &", MLoc);
+ end if;
+
+ Set_Atomic_Sync_Required (N);
+ end if;
+ end;
+ end if;
+
-- Interpret possible Current_Value for variable case
if Is_Assignable (E)
diff --git a/gcc/ada/exp_ch3.adb b/gcc/ada/exp_ch3.adb
index ef769758e57..15547232491 100644
--- a/gcc/ada/exp_ch3.adb
+++ b/gcc/ada/exp_ch3.adb
@@ -114,20 +114,6 @@ package body Exp_Ch3 is
-- removing the implicit call that would otherwise constitute elaboration
-- code.
- function Build_Master_Renaming
- (N : Node_Id;
- T : Entity_Id) return Entity_Id;
- -- If the designated type of an access type is a task type or contains
- -- tasks, we make sure that a _Master variable is declared in the current
- -- scope, and then declare a renaming for it:
- --
- -- atypeM : Master_Id renames _Master;
- --
- -- where atyp is the name of the access type. This declaration is used when
- -- an allocator for the access type is expanded. The node is the full
- -- declaration of the designated type that contains tasks. The renaming
- -- declaration is inserted before N, and after the Master declaration.
-
procedure Build_Record_Init_Proc (N : Node_Id; Rec_Ent : Entity_Id);
-- Build record initialization procedure. N is the type declaration
-- node, and Rec_Ent is the corresponding entity for the record type.
@@ -777,132 +763,6 @@ package body Exp_Ch3 is
end if;
end Build_Array_Init_Proc;
- -----------------------------
- -- Build_Class_Wide_Master --
- -----------------------------
-
- procedure Build_Class_Wide_Master (T : Entity_Id) is
- Loc : constant Source_Ptr := Sloc (T);
- Master_Id : Entity_Id;
- Master_Scope : Entity_Id;
- Name_Id : Node_Id;
- Related_Node : Node_Id;
- Ren_Decl : Node_Id;
-
- begin
- -- Nothing to do if there is no task hierarchy
-
- if Restriction_Active (No_Task_Hierarchy) then
- return;
- end if;
-
- -- Find the declaration that created the access type. It is either a
- -- type declaration, or an object declaration with an access definition,
- -- in which case the type is anonymous.
-
- if Is_Itype (T) then
- Related_Node := Associated_Node_For_Itype (T);
- else
- Related_Node := Parent (T);
- end if;
-
- Master_Scope := Find_Master_Scope (T);
-
- -- Nothing to do if the master scope already contains a _master entity.
- -- The only exception to this is the following scenario:
-
- -- Source_Scope
- -- Transient_Scope_1
- -- _master
-
- -- Transient_Scope_2
- -- use of master
-
- -- In this case the source scope is marked as having the master entity
- -- even though the actual declaration appears inside an inner scope. If
- -- the second transient scope requires a _master, it cannot use the one
- -- already declared because the entity is not visible.
-
- Name_Id := Make_Identifier (Loc, Name_uMaster);
-
- if not Has_Master_Entity (Master_Scope)
- or else No (Current_Entity_In_Scope (Name_Id))
- then
- declare
- Master_Decl : Node_Id;
-
- begin
- Set_Has_Master_Entity (Master_Scope);
-
- -- Generate:
- -- _master : constant Integer := Current_Master.all;
-
- Master_Decl :=
- Make_Object_Declaration (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Name_uMaster),
- Constant_Present => True,
- Object_Definition =>
- New_Reference_To (Standard_Integer, Loc),
- Expression =>
- Make_Explicit_Dereference (Loc,
- New_Reference_To (RTE (RE_Current_Master), Loc)));
-
- Insert_Action (Related_Node, Master_Decl);
- Analyze (Master_Decl);
-
- -- Mark the containing scope as a task master. Masters associated
- -- with return statements are already marked at this stage (see
- -- Analyze_Subprogram_Body).
-
- if Ekind (Current_Scope) /= E_Return_Statement then
- declare
- Par : Node_Id := Related_Node;
-
- begin
- while Nkind (Par) /= N_Compilation_Unit loop
- Par := Parent (Par);
-
- -- If we fall off the top, we are at the outer level, and
- -- the environment task is our effective master, so
- -- nothing to mark.
-
- if Nkind_In (Par, N_Block_Statement,
- N_Subprogram_Body,
- N_Task_Body)
- then
- Set_Is_Task_Master (Par);
- exit;
- end if;
- end loop;
- end;
- end if;
- end;
- end if;
-
- Master_Id :=
- Make_Defining_Identifier (Loc,
- New_External_Name (Chars (T), 'M'));
-
- -- Generate:
- -- Mnn renames _master;
-
- Ren_Decl :=
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier => Master_Id,
- Subtype_Mark => New_Reference_To (Standard_Integer, Loc),
- Name => Name_Id);
-
- Insert_Before (Related_Node, Ren_Decl);
- Analyze (Ren_Decl);
-
- Set_Master_Id (T, Master_Id);
-
- exception
- when RE_Not_Available =>
- return;
- end Build_Class_Wide_Master;
-
--------------------------------
-- Build_Discr_Checking_Funcs --
--------------------------------
@@ -1673,77 +1533,18 @@ package body Exp_Ch3 is
return Empty_List;
end Build_Initialization_Call;
- ---------------------------
- -- Build_Master_Renaming --
- ---------------------------
-
- function Build_Master_Renaming
- (N : Node_Id;
- T : Entity_Id) return Entity_Id
- is
- Loc : constant Source_Ptr := Sloc (N);
- M_Id : Entity_Id;
- Decl : Node_Id;
-
- begin
- -- Nothing to do if there is no task hierarchy
-
- if Restriction_Active (No_Task_Hierarchy) then
- return Empty;
- end if;
-
- M_Id :=
- Make_Defining_Identifier (Loc,
- New_External_Name (Chars (T), 'M'));
-
- Decl :=
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier => M_Id,
- Subtype_Mark => New_Reference_To (RTE (RE_Master_Id), Loc),
- Name => Make_Identifier (Loc, Name_uMaster));
- Insert_Before (N, Decl);
- Analyze (Decl);
- return M_Id;
-
- exception
- when RE_Not_Available =>
- return Empty;
- end Build_Master_Renaming;
-
- ---------------------------
- -- Build_Master_Renaming --
- ---------------------------
-
- procedure Build_Master_Renaming (N : Node_Id; T : Entity_Id) is
- M_Id : Entity_Id;
-
- begin
- -- Nothing to do if there is no task hierarchy
-
- if Restriction_Active (No_Task_Hierarchy) then
- return;
- end if;
-
- M_Id := Build_Master_Renaming (N, T);
- Set_Master_Id (T, M_Id);
-
- exception
- when RE_Not_Available =>
- return;
- end Build_Master_Renaming;
-
----------------------------
-- Build_Record_Init_Proc --
----------------------------
procedure Build_Record_Init_Proc (N : Node_Id; Rec_Ent : Entity_Id) is
- Decls : constant List_Id := New_List;
- Discr_Map : constant Elist_Id := New_Elmt_List;
- Counter : Int := 0;
- Loc : Source_Ptr := Sloc (N);
- Proc_Id : Entity_Id;
- Rec_Type : Entity_Id;
- Set_Tag : Entity_Id := Empty;
+ Decls : constant List_Id := New_List;
+ Discr_Map : constant Elist_Id := New_Elmt_List;
+ Loc : constant Source_Ptr := Sloc (Rec_Ent);
+ Counter : Int := 0;
+ Proc_Id : Entity_Id;
+ Rec_Type : Entity_Id;
+ Set_Tag : Entity_Id := Empty;
function Build_Assignment (Id : Entity_Id; N : Node_Id) return List_Id;
-- Build an assignment statement which assigns the default expression
@@ -1820,18 +1621,18 @@ package body Exp_Ch3 is
----------------------
function Build_Assignment (Id : Entity_Id; N : Node_Id) return List_Id is
- Typ : constant Entity_Id := Underlying_Type (Etype (Id));
- Exp : Node_Id := N;
- Kind : Node_Kind := Nkind (N);
- Lhs : Node_Id;
- Res : List_Id;
+ N_Loc : constant Source_Ptr := Sloc (N);
+ Typ : constant Entity_Id := Underlying_Type (Etype (Id));
+ Exp : Node_Id := N;
+ Kind : Node_Kind := Nkind (N);
+ Lhs : Node_Id;
+ Res : List_Id;
begin
- Loc := Sloc (N);
Lhs :=
- Make_Selected_Component (Loc,
+ Make_Selected_Component (N_Loc,
Prefix => Make_Identifier (Loc, Name_uInit),
- Selector_Name => New_Occurrence_Of (Id, Loc));
+ Selector_Name => New_Occurrence_Of (Id, N_Loc));
Set_Assignment_OK (Lhs);
-- Case of an access attribute applied to the current instance.
@@ -1852,9 +1653,9 @@ package body Exp_Ch3 is
and then Entity (Prefix (N)) = Rec_Type
then
Exp :=
- Make_Attribute_Reference (Loc,
+ Make_Attribute_Reference (N_Loc,
Prefix =>
- Make_Identifier (Loc, Name_uInit),
+ Make_Identifier (N_Loc, Name_uInit),
Attribute_Name => Name_Unrestricted_Access);
end if;
@@ -1880,13 +1681,13 @@ package body Exp_Ch3 is
and then Tagged_Type_Expansion
then
Append_To (Res,
- Make_Assignment_Statement (Loc,
+ Make_Assignment_Statement (N_Loc,
Name =>
- Make_Selected_Component (Loc,
+ Make_Selected_Component (N_Loc,
Prefix =>
New_Copy_Tree (Lhs, New_Scope => Proc_Id),
Selector_Name =>
- New_Reference_To (First_Tag_Component (Typ), Loc)),
+ New_Reference_To (First_Tag_Component (Typ), N_Loc)),
Expression =>
Unchecked_Convert_To (RTE (RE_Tag),
@@ -1894,7 +1695,7 @@ package body Exp_Ch3 is
(Node
(First_Elmt
(Access_Disp_Table (Underlying_Type (Typ)))),
- Loc))));
+ N_Loc))));
end if;
-- Adjust the component if controlled except if it is an aggregate
@@ -1928,6 +1729,7 @@ package body Exp_Ch3 is
procedure Build_Discriminant_Assignments (Statement_List : List_Id) is
Is_Tagged : constant Boolean := Is_Tagged_Type (Rec_Type);
D : Entity_Id;
+ D_Loc : Source_Ptr;
begin
if Has_Discriminants (Rec_Type)
@@ -1947,10 +1749,10 @@ package body Exp_Ch3 is
null;
else
- Loc := Sloc (D);
+ D_Loc := Sloc (D);
Append_List_To (Statement_List,
Build_Assignment (D,
- New_Reference_To (Discriminal (D), Loc)));
+ New_Reference_To (Discriminal (D), D_Loc)));
end if;
Next_Discriminant (D);
@@ -2657,6 +2459,7 @@ package body Exp_Ch3 is
function Build_Init_Statements (Comp_List : Node_Id) return List_Id is
Checks : constant List_Id := New_List;
Actions : List_Id := No_List;
+ Comp_Loc : Source_Ptr;
Counter_Id : Entity_Id := Empty;
Decl : Node_Id;
Has_POC : Boolean;
@@ -2665,11 +2468,11 @@ package body Exp_Ch3 is
Stmts : List_Id;
Typ : Entity_Id;
- procedure Increment_Counter;
+ procedure Increment_Counter (Loc : Source_Ptr);
-- Generate an "increment by one" statement for the current counter
-- and append it to the list Stmts.
- procedure Make_Counter;
+ procedure Make_Counter (Loc : Source_Ptr);
-- Create a new counter for the current component list. The routine
-- creates a new defining Id, adds an object declaration and sets
-- the Id generator for the next variant.
@@ -2678,7 +2481,7 @@ package body Exp_Ch3 is
-- Increment_Counter --
-----------------------
- procedure Increment_Counter is
+ procedure Increment_Counter (Loc : Source_Ptr) is
begin
-- Generate:
-- Counter := Counter + 1;
@@ -2696,7 +2499,7 @@ package body Exp_Ch3 is
-- Make_Counter --
------------------
- procedure Make_Counter is
+ procedure Make_Counter (Loc : Source_Ptr) is
begin
-- Increment the Id generator
@@ -2781,11 +2584,11 @@ package body Exp_Ch3 is
Decl := First_Non_Pragma (Component_Items (Comp_List));
while Present (Decl) loop
- Loc := Sloc (Decl);
+ Comp_Loc := Sloc (Decl);
Build_Record_Checks
(Subtype_Indication (Component_Definition (Decl)), Checks);
- Id := Defining_Identifier (Decl);
+ Id := Defining_Identifier (Decl);
Typ := Etype (Id);
-- Leave any processing of per-object constrained component for
@@ -2805,12 +2608,13 @@ package body Exp_Ch3 is
if Is_CPP_Constructor_Call (Expression (Decl)) then
Actions :=
Build_Initialization_Call
- (Loc,
+ (Comp_Loc,
Id_Ref =>
- Make_Selected_Component (Loc,
+ Make_Selected_Component (Comp_Loc,
Prefix =>
- Make_Identifier (Loc, Name_uInit),
- Selector_Name => New_Occurrence_Of (Id, Loc)),
+ Make_Identifier (Comp_Loc, Name_uInit),
+ Selector_Name =>
+ New_Occurrence_Of (Id, Comp_Loc)),
Typ => Typ,
In_Init_Proc => True,
Enclos_Type => Rec_Type,
@@ -2827,10 +2631,11 @@ package body Exp_Ch3 is
then
Actions :=
Build_Initialization_Call
- (Loc,
- Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
- Selector_Name => New_Occurrence_Of (Id, Loc)),
+ (Comp_Loc,
+ Make_Selected_Component (Comp_Loc,
+ Prefix =>
+ Make_Identifier (Comp_Loc, Name_uInit),
+ Selector_Name => New_Occurrence_Of (Id, Comp_Loc)),
Typ,
In_Init_Proc => True,
Enclos_Type => Rec_Type,
@@ -2864,10 +2669,10 @@ package body Exp_Ch3 is
and then Needs_Finalization (Typ)
then
if No (Counter_Id) then
- Make_Counter;
+ Make_Counter (Comp_Loc);
end if;
- Increment_Counter;
+ Increment_Counter (Comp_Loc);
end if;
end if;
end if;
@@ -2923,6 +2728,7 @@ package body Exp_Ch3 is
Corresponding_Concurrent_Type (Rec_Type);
Task_Decl : constant Node_Id := Parent (Task_Type);
Task_Def : constant Node_Id := Task_Definition (Task_Decl);
+ Decl_Loc : Source_Ptr;
Ent : Entity_Id;
Vis_Decl : Node_Id;
@@ -2930,7 +2736,7 @@ package body Exp_Ch3 is
if Present (Task_Def) then
Vis_Decl := First (Visible_Declarations (Task_Def));
while Present (Vis_Decl) loop
- Loc := Sloc (Vis_Decl);
+ Decl_Loc := Sloc (Vis_Decl);
if Nkind (Vis_Decl) = N_Attribute_Definition_Clause then
if Get_Attribute_Id (Chars (Vis_Decl)) =
@@ -2940,18 +2746,19 @@ package body Exp_Ch3 is
if Ekind (Ent) = E_Entry then
Append_To (Stmts,
- Make_Procedure_Call_Statement (Loc,
+ Make_Procedure_Call_Statement (Decl_Loc,
Name =>
New_Reference_To (RTE (
- RE_Bind_Interrupt_To_Entry), Loc),
+ RE_Bind_Interrupt_To_Entry), Decl_Loc),
Parameter_Associations => New_List (
- Make_Selected_Component (Loc,
+ Make_Selected_Component (Decl_Loc,
Prefix =>
- Make_Identifier (Loc, Name_uInit),
+ Make_Identifier (Decl_Loc, Name_uInit),
Selector_Name =>
- Make_Identifier (Loc, Name_uTask_Id)),
+ Make_Identifier
+ (Decl_Loc, Name_uTask_Id)),
Entry_Index_Expression
- (Loc, Ent, Empty, Task_Type),
+ (Decl_Loc, Ent, Empty, Task_Type),
Expression (Vis_Decl))));
end if;
end if;
@@ -2988,7 +2795,7 @@ package body Exp_Ch3 is
if Has_POC then
Decl := First_Non_Pragma (Component_Items (Comp_List));
while Present (Decl) loop
- Loc := Sloc (Decl);
+ Comp_Loc := Sloc (Decl);
Id := Defining_Identifier (Decl);
Typ := Etype (Id);
@@ -2997,10 +2804,11 @@ package body Exp_Ch3 is
then
if Has_Non_Null_Base_Init_Proc (Typ) then
Append_List_To (Stmts,
- Build_Initialization_Call (Loc,
- Make_Selected_Component (Loc,
- Prefix => Make_Identifier (Loc, Name_uInit),
- Selector_Name => New_Occurrence_Of (Id, Loc)),
+ Build_Initialization_Call (Comp_Loc,
+ Make_Selected_Component (Comp_Loc,
+ Prefix =>
+ Make_Identifier (Comp_Loc, Name_uInit),
+ Selector_Name => New_Occurrence_Of (Id, Comp_Loc)),
Typ,
In_Init_Proc => True,
Enclos_Type => Rec_Type,
@@ -3013,10 +2821,10 @@ package body Exp_Ch3 is
if Needs_Finalization (Typ) then
if No (Counter_Id) then
- Make_Counter;
+ Make_Counter (Comp_Loc);
end if;
- Increment_Counter;
+ Increment_Counter (Comp_Loc);
end if;
elsif Component_Needs_Simple_Initialization (Typ) then
@@ -3035,15 +2843,16 @@ package body Exp_Ch3 is
if Present (Variant_Part (Comp_List)) then
declare
Variant_Alts : constant List_Id := New_List;
+ Var_Loc : Source_Ptr;
Variant : Node_Id;
begin
Variant :=
First_Non_Pragma (Variants (Variant_Part (Comp_List)));
while Present (Variant) loop
- Loc := Sloc (Variant);
+ Var_Loc := Sloc (Variant);
Append_To (Variant_Alts,
- Make_Case_Statement_Alternative (Loc,
+ Make_Case_Statement_Alternative (Var_Loc,
Discrete_Choices =>
New_Copy_List (Discrete_Choices (Variant)),
Statements =>
@@ -3056,10 +2865,10 @@ package body Exp_Ch3 is
-- formal parameter of the initialization procedure.
Append_To (Stmts,
- Make_Case_Statement (Loc,
+ Make_Case_Statement (Var_Loc,
Expression =>
New_Reference_To (Discriminal (
- Entity (Name (Variant_Part (Comp_List)))), Loc),
+ Entity (Name (Variant_Part (Comp_List)))), Var_Loc),
Alternatives => Variant_Alts));
end;
end if;
@@ -4323,29 +4132,27 @@ package body Exp_Ch3 is
------------------------------------
procedure Expand_N_Full_Type_Declaration (N : Node_Id) is
- Def_Id : constant Entity_Id := Defining_Identifier (N);
- B_Id : constant Entity_Id := Base_Type (Def_Id);
- Par_Id : Entity_Id;
- FN : Node_Id;
- procedure Build_Master (Def_Id : Entity_Id);
- -- Create the master associated with Def_Id
+ procedure Build_Master (Ptr_Typ : Entity_Id);
+ -- Create the master associated with Ptr_Typ
------------------
-- Build_Master --
------------------
- procedure Build_Master (Def_Id : Entity_Id) is
+ procedure Build_Master (Ptr_Typ : Entity_Id) is
+ Desig_Typ : constant Entity_Id := Designated_Type (Ptr_Typ);
+
begin
-- Anonymous access types are created for the components of the
-- record parameter for an entry declaration. No master is created
-- for such a type.
- if Has_Task (Designated_Type (Def_Id))
- and then Comes_From_Source (N)
+ if Comes_From_Source (N)
+ and then Has_Task (Desig_Typ)
then
- Build_Master_Entity (Def_Id);
- Build_Master_Renaming (Parent (Def_Id), Def_Id);
+ Build_Master_Entity (Ptr_Typ);
+ Build_Master_Renaming (Ptr_Typ);
-- Create a class-wide master because a Master_Id must be generated
-- for access-to-limited-class-wide types whose root may be extended
@@ -4354,32 +4161,38 @@ package body Exp_Ch3 is
-- Note: This code covers access-to-limited-interfaces because they
-- can be used to reference tasks implementing them.
- elsif Is_Class_Wide_Type (Designated_Type (Def_Id))
- and then Is_Limited_Type (Designated_Type (Def_Id))
+ elsif Is_Limited_Class_Wide_Type (Desig_Typ)
and then Tasking_Allowed
- -- Do not create a class-wide master for types whose convention is
- -- Java since these types cannot embed Ada tasks anyway. Note that
- -- the following test cannot catch the following case:
+ -- Do not create a class-wide master for types whose convention is
+ -- Java since these types cannot embed Ada tasks anyway. Note that
+ -- the following test cannot catch the following case:
- -- package java.lang.Object is
- -- type Typ is tagged limited private;
- -- type Ref is access all Typ'Class;
- -- private
- -- type Typ is tagged limited ...;
- -- pragma Convention (Typ, Java)
- -- end;
+ -- package java.lang.Object is
+ -- type Typ is tagged limited private;
+ -- type Ref is access all Typ'Class;
+ -- private
+ -- type Typ is tagged limited ...;
+ -- pragma Convention (Typ, Java)
+ -- end;
- -- Because the convention appears after we have done the
- -- processing for type Ref.
+ -- Because the convention appears after we have done the
+ -- processing for type Ref.
- and then Convention (Designated_Type (Def_Id)) /= Convention_Java
- and then Convention (Designated_Type (Def_Id)) /= Convention_CIL
+ and then Convention (Desig_Typ) /= Convention_Java
+ and then Convention (Desig_Typ) /= Convention_CIL
then
- Build_Class_Wide_Master (Def_Id);
+ Build_Class_Wide_Master (Ptr_Typ);
end if;
end Build_Master;
+ -- Local declarations
+
+ Def_Id : constant Entity_Id := Defining_Identifier (N);
+ B_Id : constant Entity_Id := Base_Type (Def_Id);
+ FN : Node_Id;
+ Par_Id : Entity_Id;
+
-- Start of processing for Expand_N_Full_Type_Declaration
begin
@@ -4390,6 +4203,8 @@ package body Exp_Ch3 is
Expand_Access_Protected_Subprogram_Type (N);
end if;
+ -- Array of anonymous access-to-task pointers
+
elsif Ada_Version >= Ada_2005
and then Is_Array_Type (Def_Id)
and then Is_Access_Type (Component_Type (Def_Id))
@@ -4400,73 +4215,57 @@ package body Exp_Ch3 is
elsif Has_Task (Def_Id) then
Expand_Previous_Access_Type (Def_Id);
+ -- Check the components of a record type or array of records for
+ -- anonymous access-to-task pointers.
+
elsif Ada_Version >= Ada_2005
- and then
- (Is_Record_Type (Def_Id)
- or else (Is_Array_Type (Def_Id)
- and then Is_Record_Type (Component_Type (Def_Id))))
+ and then (Is_Record_Type (Def_Id)
+ or else
+ (Is_Array_Type (Def_Id)
+ and then Is_Record_Type (Component_Type (Def_Id))))
then
declare
- Comp : Entity_Id;
- Typ : Entity_Id;
- M_Id : Entity_Id;
+ Comp : Entity_Id;
+ First : Boolean;
+ M_Id : Entity_Id;
+ Typ : Entity_Id;
begin
- -- Look for the first anonymous access type component
-
if Is_Array_Type (Def_Id) then
Comp := First_Entity (Component_Type (Def_Id));
else
Comp := First_Entity (Def_Id);
end if;
+ -- Examine all components looking for anonymous access-to-task
+ -- types.
+
+ First := True;
while Present (Comp) loop
Typ := Etype (Comp);
- exit when Is_Access_Type (Typ)
- and then Ekind (Typ) = E_Anonymous_Access_Type;
-
- Next_Entity (Comp);
- end loop;
-
- -- If found we add a renaming declaration of master_id and we
- -- associate it to each anonymous access type component. Do
- -- nothing if the access type already has a master. This will be
- -- the case if the array type is the packed array created for a
- -- user-defined array type T, where the master_id is created when
- -- expanding the declaration for T.
+ if Ekind (Typ) = E_Anonymous_Access_Type
+ and then Has_Task (Available_View (Designated_Type (Typ)))
+ and then No (Master_Id (Typ))
+ then
+ -- Ensure that the record or array type have a _master
- if Present (Comp)
- and then Ekind (Typ) = E_Anonymous_Access_Type
- and then not Restriction_Active (No_Task_Hierarchy)
- and then No (Master_Id (Typ))
+ if First then
+ Build_Master_Entity (Def_Id);
+ Build_Master_Renaming (Typ);
+ M_Id := Master_Id (Typ);
- -- Do not consider run-times with no tasking support
+ First := False;
- and then RTE_Available (RE_Current_Master)
- and then Has_Task (Non_Limited_Designated_Type (Typ))
- then
- Build_Master_Entity (Def_Id);
- M_Id := Build_Master_Renaming (N, Def_Id);
+ -- Reuse the same master to service any additional types
- if Is_Array_Type (Def_Id) then
- Comp := First_Entity (Component_Type (Def_Id));
- else
- Comp := First_Entity (Def_Id);
- end if;
-
- while Present (Comp) loop
- Typ := Etype (Comp);
-
- if Is_Access_Type (Typ)
- and then Ekind (Typ) = E_Anonymous_Access_Type
- then
+ else
Set_Master_Id (Typ, M_Id);
end if;
+ end if;
- Next_Entity (Comp);
- end loop;
- end if;
+ Next_Entity (Comp);
+ end loop;
end;
end if;
@@ -4482,7 +4281,7 @@ package body Exp_Ch3 is
end if;
if Nkind (Type_Definition (Original_Node (N))) =
- N_Derived_Type_Definition
+ N_Derived_Type_Definition
and then not Is_Tagged_Type (Def_Id)
and then Present (Freeze_Node (Par_Id))
and then Present (TSS_Elist (Freeze_Node (Par_Id)))
@@ -5387,23 +5186,31 @@ package body Exp_Ch3 is
---------------------------------
procedure Expand_Previous_Access_Type (Def_Id : Entity_Id) is
- T : Entity_Id := First_Entity (Current_Scope);
+ Ptr_Typ : Entity_Id;
begin
- -- Find all access types declared in the current scope, whose
- -- designated type is Def_Id. If it does not have a Master_Id,
- -- create one now.
-
- while Present (T) loop
- if Is_Access_Type (T)
- and then Designated_Type (T) = Def_Id
- and then No (Master_Id (T))
+ -- Find all access types in the current scope whose designated type is
+ -- Def_Id and build master renamings for them.
+
+ Ptr_Typ := First_Entity (Current_Scope);
+ while Present (Ptr_Typ) loop
+ if Is_Access_Type (Ptr_Typ)
+ and then Designated_Type (Ptr_Typ) = Def_Id
+ and then No (Master_Id (Ptr_Typ))
then
+ -- Ensure that the designated type has a master
+
Build_Master_Entity (Def_Id);
- Build_Master_Renaming (Parent (Def_Id), T);
+
+ -- Private and incomplete types complicate the insertion of master
+ -- renamings because the access type may precede the full view of
+ -- the designated type. For this reason, the master renamings are
+ -- inserted relative to the designated type.
+
+ Build_Master_Renaming (Ptr_Typ, Ins_Nod => Parent (Def_Id));
end if;
- Next_Entity (T);
+ Next_Entity (Ptr_Typ);
end loop;
end Expand_Previous_Access_Type;
diff --git a/gcc/ada/exp_ch3.ads b/gcc/ada/exp_ch3.ads
index 7b67e23a8cf..8cedc0b05cd 100644
--- a/gcc/ada/exp_ch3.ads
+++ b/gcc/ada/exp_ch3.ads
@@ -46,15 +46,6 @@ package Exp_Ch3 is
procedure Expand_Record_Extension (T : Entity_Id; Def : Node_Id);
-- Add a field _parent in the extension part of the record
- procedure Build_Class_Wide_Master (T : Entity_Id);
- -- For access to class-wide limited types we must build a task master
- -- because some subsequent extension may add a task component. To avoid
- -- bringing in the tasking run-time whenever an access-to-class-wide
- -- limited type is used, we use the soft-link mechanism and add a level of
- -- indirection to calls to routines that manipulate Master_Ids. This must
- -- also be used for anonymous access types whose designated type is a task
- -- or synchronized interface.
-
procedure Build_Discr_Checking_Funcs (N : Node_Id);
-- Builds function which checks whether the component name is consistent
-- with the current discriminants. N is the full type declaration node,
@@ -93,19 +84,6 @@ package Exp_Ch3 is
-- Constructor_Ref is a call to a constructor subprogram. It is currently
-- used only to support C++ constructors.
- procedure Build_Master_Renaming (N : Node_Id; T : Entity_Id);
- -- If the designated type of an access type is a task type or contains
- -- tasks, we make sure that a _Master variable is declared in the current
- -- scope, and then declare a renaming for it:
- --
- -- atypeM : Master_Id renames _Master;
- --
- -- where atyp is the name of the access type. This declaration is
- -- used when an allocator for the access type is expanded. The node N
- -- is the full declaration of the designated type that contains tasks.
- -- The renaming declaration is inserted before N, and after the Master
- -- declaration.
-
function Freeze_Type (N : Node_Id) return Boolean;
-- This function executes the freezing actions associated with the given
-- freeze type node N and returns True if the node is to be deleted. We
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 677eec74dd5..87e02d0e1ee 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -3526,23 +3526,28 @@ package body Exp_Ch4 is
end if;
-- Set the storage pool and find the appropriate version of Allocate to
- -- call.
+ -- call. Do not overwrite the storage pool if it is already set, which
+ -- can happen for build-in-place function returns (see
+ -- Exp_Ch4.Expand_N_Extended_Return_Statement).
- Pool := Associated_Storage_Pool (Root_Type (PtrT));
- Set_Storage_Pool (N, Pool);
+ if No (Storage_Pool (N)) then
+ Pool := Associated_Storage_Pool (Root_Type (PtrT));
- if Present (Pool) then
- if Is_RTE (Pool, RE_SS_Pool) then
- if VM_Target = No_VM then
- Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
- end if;
+ if Present (Pool) then
+ Set_Storage_Pool (N, Pool);
- elsif Is_Class_Wide_Type (Etype (Pool)) then
- Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
+ if Is_RTE (Pool, RE_SS_Pool) then
+ if VM_Target = No_VM then
+ Set_Procedure_To_Call (N, RTE (RE_SS_Allocate));
+ end if;
- else
- Set_Procedure_To_Call (N,
- Find_Prim_Op (Etype (Pool), Name_Allocate));
+ elsif Is_Class_Wide_Type (Etype (Pool)) then
+ Set_Procedure_To_Call (N, RTE (RE_Allocate_Any));
+
+ else
+ Set_Procedure_To_Call (N,
+ Find_Prim_Op (Etype (Pool), Name_Allocate));
+ end if;
end if;
end if;
@@ -5574,26 +5579,10 @@ package body Exp_Ch4 is
Expand_Boolean_Operator (N);
elsif Is_Boolean_Type (Etype (N)) then
-
- -- Replace AND by AND THEN if Short_Circuit_And_Or active and the
- -- type is standard Boolean (do not mess with AND that uses a non-
- -- standard Boolean type, because something strange is going on).
-
- if Short_Circuit_And_Or and then Typ = Standard_Boolean then
- Rewrite (N,
- Make_And_Then (Sloc (N),
- Left_Opnd => Relocate_Node (Left_Opnd (N)),
- Right_Opnd => Relocate_Node (Right_Opnd (N))));
- Analyze_And_Resolve (N, Typ);
-
- -- Otherwise, adjust conditions
-
- else
- Adjust_Condition (Left_Opnd (N));
- Adjust_Condition (Right_Opnd (N));
- Set_Etype (N, Standard_Boolean);
- Adjust_Result_Type (N, Typ);
- end if;
+ Adjust_Condition (Left_Opnd (N));
+ Adjust_Condition (Right_Opnd (N));
+ Set_Etype (N, Standard_Boolean);
+ Adjust_Result_Type (N, Typ);
elsif Is_Intrinsic_Subprogram (Entity (N)) then
Expand_Intrinsic_Call (N, Entity (N));
@@ -7530,26 +7519,10 @@ package body Exp_Ch4 is
Expand_Boolean_Operator (N);
elsif Is_Boolean_Type (Etype (N)) then
-
- -- Replace OR by OR ELSE if Short_Circuit_And_Or active and the type
- -- is standard Boolean (do not mess with AND that uses a non-standard
- -- Boolean type, because something strange is going on).
-
- if Short_Circuit_And_Or and then Typ = Standard_Boolean then
- Rewrite (N,
- Make_Or_Else (Sloc (N),
- Left_Opnd => Relocate_Node (Left_Opnd (N)),
- Right_Opnd => Relocate_Node (Right_Opnd (N))));
- Analyze_And_Resolve (N, Typ);
-
- -- Otherwise, adjust conditions
-
- else
- Adjust_Condition (Left_Opnd (N));
- Adjust_Condition (Right_Opnd (N));
- Set_Etype (N, Standard_Boolean);
- Adjust_Result_Type (N, Typ);
- end if;
+ Adjust_Condition (Left_Opnd (N));
+ Adjust_Condition (Right_Opnd (N));
+ Set_Etype (N, Standard_Boolean);
+ Adjust_Result_Type (N, Typ);
elsif Is_Intrinsic_Subprogram (Entity (N)) then
Expand_Intrinsic_Call (N, Entity (N));
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index 291d68e7b3e..971d0ad65d2 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -3458,6 +3458,20 @@ package body Exp_Ch5 is
Statements => Statements (N)))),
End_Label => End_Label (N)));
+
+ -- The loop parameter's entity must be removed from the loop
+ -- scope's entity list, since it will now be located in the
+ -- new block scope. Any other entities already associated with
+ -- the loop scope, such as the loop parameter's subtype, will
+ -- remain there.
+
+ pragma Assert (First_Entity (Scope (Loop_Id)) = Loop_Id);
+ Set_First_Entity (Scope (Loop_Id), Next_Entity (Loop_Id));
+
+ if Last_Entity (Scope (Loop_Id)) = Loop_Id then
+ Set_Last_Entity (Scope (Loop_Id), Empty);
+ end if;
+
Analyze (N);
-- Nothing to do with other cases of for loops
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb
index 8955e5d9174..993fa40c3fa 100644
--- a/gcc/ada/exp_ch6.adb
+++ b/gcc/ada/exp_ch6.adb
@@ -94,15 +94,18 @@ package body Exp_Ch6 is
-- along directly to the build-in-place function. Finally, if Return_Object
-- is empty, then pass a null literal as the actual.
- procedure Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ procedure Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Function_Call : Node_Id;
Function_Id : Entity_Id;
Alloc_Form : BIP_Allocation_Form := Unspecified;
- Alloc_Form_Exp : Node_Id := Empty);
- -- Ada 2005 (AI-318-02): Add an actual indicating the form of allocation,
- -- if any, to be done by a build-in-place function. If Alloc_Form_Exp is
- -- present, then use it, otherwise pass a literal corresponding to the
- -- Alloc_Form parameter (which must not be Unspecified in that case).
+ Alloc_Form_Exp : Node_Id := Empty;
+ Pool_Actual : Node_Id := Make_Null (No_Location));
+ -- Ada 2005 (AI-318-02): Add the actuals needed for a build-in-place
+ -- function call that returns a caller-unknown-size result (BIP_Alloc_Form
+ -- and BIP_Storage_Pool). If Alloc_Form_Exp is present, then use it,
+ -- otherwise pass a literal corresponding to the Alloc_Form parameter
+ -- (which must not be Unspecified in that case). Pool_Actual is the
+ -- parameter to pass to BIP_Storage_Pool.
procedure Add_Finalization_Master_Actual_To_Build_In_Place_Call
(Func_Call : Node_Id;
@@ -251,19 +254,21 @@ package body Exp_Ch6 is
Add_Extra_Actual_To_Call (Function_Call, Obj_Acc_Formal, Obj_Address);
end Add_Access_Actual_To_Build_In_Place_Call;
- --------------------------------------------------
- -- Add_Alloc_Form_Actual_To_Build_In_Place_Call --
- --------------------------------------------------
+ ------------------------------------------------------
+ -- Add_Unconstrained_Actuals_To_Build_In_Place_Call --
+ ------------------------------------------------------
- procedure Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ procedure Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Function_Call : Node_Id;
Function_Id : Entity_Id;
Alloc_Form : BIP_Allocation_Form := Unspecified;
- Alloc_Form_Exp : Node_Id := Empty)
+ Alloc_Form_Exp : Node_Id := Empty;
+ Pool_Actual : Node_Id := Make_Null (No_Location))
is
Loc : constant Source_Ptr := Sloc (Function_Call);
Alloc_Form_Actual : Node_Id;
Alloc_Form_Formal : Node_Id;
+ Pool_Formal : Node_Id;
begin
-- The allocation form generally doesn't need to be passed in the case
@@ -305,7 +310,19 @@ package body Exp_Ch6 is
Add_Extra_Actual_To_Call
(Function_Call, Alloc_Form_Formal, Alloc_Form_Actual);
- end Add_Alloc_Form_Actual_To_Build_In_Place_Call;
+
+ -- Pass the Storage_Pool parameter. This parameter is omitted on
+ -- .NET/JVM/ZFP as those targets do not support pools.
+
+ if VM_Target = No_VM
+ and then RTE_Available (RE_Root_Storage_Pool_Ptr)
+ then
+ Pool_Formal := Build_In_Place_Formal (Function_Id, BIP_Storage_Pool);
+ Analyze_And_Resolve (Pool_Actual, Etype (Pool_Formal));
+ Add_Extra_Actual_To_Call
+ (Function_Call, Pool_Formal, Pool_Actual);
+ end if;
+ end Add_Unconstrained_Actuals_To_Build_In_Place_Call;
-----------------------------------------------------------
-- Add_Finalization_Master_Actual_To_Build_In_Place_Call --
@@ -462,16 +479,23 @@ package body Exp_Ch6 is
Function_Id : Entity_Id;
Master_Actual : Node_Id)
is
- Loc : constant Source_Ptr := Sloc (Function_Call);
- Actual : Node_Id := Master_Actual;
+ Loc : constant Source_Ptr := Sloc (Function_Call);
+ Result_Subt : constant Entity_Id :=
+ Available_View (Etype (Function_Id));
+ Actual : Node_Id;
+ Chain_Actual : Node_Id;
+ Chain_Formal : Node_Id;
+ Master_Formal : Node_Id;
begin
-- No such extra parameters are needed if there are no tasks
- if not Has_Task (Available_View (Etype (Function_Id))) then
+ if not Has_Task (Result_Subt) then
return;
end if;
+ Actual := Master_Actual;
+
-- Use a dummy _master actual in case of No_Task_Hierarchy
if Restriction_Active (No_Task_Hierarchy) then
@@ -484,52 +508,34 @@ package body Exp_Ch6 is
Actual := New_Reference_To (Actual, Loc);
end if;
- -- The master
-
- declare
- Master_Formal : Node_Id;
- begin
- -- Locate implicit master parameter in the called function
-
- Master_Formal := Build_In_Place_Formal (Function_Id, BIP_Master);
+ -- Locate the implicit master parameter in the called function
- Analyze_And_Resolve (Actual, Etype (Master_Formal));
+ Master_Formal := Build_In_Place_Formal (Function_Id, BIP_Task_Master);
+ Analyze_And_Resolve (Actual, Etype (Master_Formal));
- -- Build the parameter association for the new actual and add it to
- -- the end of the function's actuals.
+ -- Build the parameter association for the new actual and add it to the
+ -- end of the function's actuals.
- Add_Extra_Actual_To_Call (Function_Call, Master_Formal, Actual);
- end;
+ Add_Extra_Actual_To_Call (Function_Call, Master_Formal, Actual);
- -- The activation chain
+ -- Locate the implicit activation chain parameter in the called function
- declare
- Activation_Chain_Actual : Node_Id;
- Activation_Chain_Formal : Node_Id;
+ Chain_Formal :=
+ Build_In_Place_Formal (Function_Id, BIP_Activation_Chain);
- begin
- -- Locate implicit activation chain parameter in the called function
+ -- Create the actual which is a pointer to the current activation chain
- Activation_Chain_Formal :=
- Build_In_Place_Formal (Function_Id, BIP_Activation_Chain);
+ Chain_Actual :=
+ Make_Attribute_Reference (Loc,
+ Prefix => Make_Identifier (Loc, Name_uChain),
+ Attribute_Name => Name_Unrestricted_Access);
- -- Create the actual which is a pointer to the current activation
- -- chain
+ Analyze_And_Resolve (Chain_Actual, Etype (Chain_Formal));
- Activation_Chain_Actual :=
- Make_Attribute_Reference (Loc,
- Prefix => Make_Identifier (Loc, Name_uChain),
- Attribute_Name => Name_Unrestricted_Access);
-
- Analyze_And_Resolve
- (Activation_Chain_Actual, Etype (Activation_Chain_Formal));
-
- -- Build the parameter association for the new actual and add it to
- -- the end of the function's actuals.
+ -- Build the parameter association for the new actual and add it to the
+ -- end of the function's actuals.
- Add_Extra_Actual_To_Call
- (Function_Call, Activation_Chain_Formal, Activation_Chain_Actual);
- end;
+ Add_Extra_Actual_To_Call (Function_Call, Chain_Formal, Chain_Actual);
end Add_Task_Actuals_To_Build_In_Place_Call;
-----------------------
@@ -541,10 +547,12 @@ package body Exp_Ch6 is
case Kind is
when BIP_Alloc_Form =>
return "BIPalloc";
+ when BIP_Storage_Pool =>
+ return "BIPstoragepool";
when BIP_Finalization_Master =>
return "BIPfinalizationmaster";
- when BIP_Master =>
- return "BIPmaster";
+ when BIP_Task_Master =>
+ return "BIPtaskmaster";
when BIP_Activation_Chain =>
return "BIPactivationchain";
when BIP_Object_Access =>
@@ -560,6 +568,9 @@ package body Exp_Ch6 is
(Func : Entity_Id;
Kind : BIP_Formal_Kind) return Entity_Id
is
+ Formal_Name : constant Name_Id :=
+ New_External_Name
+ (Chars (Func), BIP_Formal_Suffix (Kind));
Extra_Formal : Entity_Id := Extra_Formals (Func);
begin
@@ -578,9 +589,8 @@ package body Exp_Ch6 is
loop
pragma Assert (Present (Extra_Formal));
- exit when
- Chars (Extra_Formal) =
- New_External_Name (Chars (Func), BIP_Formal_Suffix (Kind));
+ exit when Chars (Extra_Formal) = Formal_Name;
+
Next_Formal_With_Extras (Extra_Formal);
end loop;
@@ -4573,6 +4583,7 @@ package body Exp_Ch6 is
Par_Func : constant Entity_Id :=
Return_Applies_To (Return_Statement_Entity (N));
+ Result_Subt : constant Entity_Id := Etype (Par_Func);
Ret_Obj_Id : constant Entity_Id :=
First_Entity (Return_Statement_Entity (N));
Ret_Obj_Decl : constant Node_Id := Parent (Ret_Obj_Id);
@@ -4638,11 +4649,12 @@ package body Exp_Ch6 is
Alloc_Expr : Node_Id) return Node_Id
is
begin
+ pragma Assert (Is_Build_In_Place_Function (Func_Id));
+
-- Processing for build-in-place object allocation. This is disabled
-- on .NET/JVM because the targets do not support pools.
if VM_Target = No_VM
- and then Is_Build_In_Place_Function (Func_Id)
and then Needs_Finalization (Ret_Typ)
then
declare
@@ -4811,7 +4823,7 @@ package body Exp_Ch6 is
-- New master
New_Reference_To
- (Build_In_Place_Formal (Par_Func, BIP_Master), Loc)));
+ (Build_In_Place_Formal (Par_Func, BIP_Task_Master), Loc)));
end Move_Activation_Chain;
-- Start of processing for Expand_N_Extended_Return_Statement
@@ -4876,7 +4888,7 @@ package body Exp_Ch6 is
-- built in place (though we plan to do so eventually).
if Present (HSS)
- or else Is_Composite_Type (Etype (Par_Func))
+ or else Is_Composite_Type (Result_Subt)
or else No (Exp)
then
if No (HSS) then
@@ -4903,7 +4915,7 @@ package body Exp_Ch6 is
-- the case of result types with task parts.
if Is_Build_In_Place
- and then Has_Task (Etype (Par_Func))
+ and then Has_Task (Result_Subt)
then
-- The return expression is an aggregate for a complex type which
-- contains tasks. This particular case is left unexpanded since
@@ -4914,7 +4926,12 @@ package body Exp_Ch6 is
Expand_N_Aggregate (Exp);
end if;
- Append_To (Stmts, Move_Activation_Chain);
+ -- Do not move the activation chain if the return object does not
+ -- contain tasks.
+
+ if Has_Task (Etype (Ret_Obj_Id)) then
+ Append_To (Stmts, Move_Activation_Chain);
+ end if;
end if;
-- Update the state of the function right before the object is
@@ -5013,7 +5030,6 @@ package body Exp_Ch6 is
Return_Obj_Typ : constant Entity_Id := Etype (Return_Obj_Id);
Return_Obj_Expr : constant Node_Id :=
Expression (Ret_Obj_Decl);
- Result_Subt : constant Entity_Id := Etype (Par_Func);
Constr_Result : constant Boolean :=
Is_Constrained (Result_Subt);
Obj_Alloc_Formal : Entity_Id;
@@ -5116,12 +5132,16 @@ package body Exp_Ch6 is
Build_In_Place_Formal (Par_Func, BIP_Alloc_Form);
declare
- Ref_Type : Entity_Id;
- Ptr_Type_Decl : Node_Id;
+ Pool_Id : constant Entity_Id :=
+ Make_Temporary (Loc, 'P');
Alloc_Obj_Id : Entity_Id;
Alloc_Obj_Decl : Node_Id;
Alloc_If_Stmt : Node_Id;
Heap_Allocator : Node_Id;
+ Pool_Decl : Node_Id;
+ Pool_Allocator : Node_Id;
+ Ptr_Type_Decl : Node_Id;
+ Ref_Type : Entity_Id;
SS_Allocator : Node_Id;
begin
@@ -5216,6 +5236,37 @@ package body Exp_Ch6 is
Set_No_Initialization (Heap_Allocator);
end if;
+ -- The Pool_Allocator is just like the Heap_Allocator,
+ -- except we set Storage_Pool and Procedure_To_Call so
+ -- it will use the user-defined storage pool.
+
+ Pool_Allocator := New_Copy_Tree (Heap_Allocator);
+
+ -- Do not generate the renaming of the build-in-place
+ -- pool parameter on .NET/JVM/ZFP because the parameter
+ -- is not created in the first place.
+
+ if VM_Target = No_VM
+ and then RTE_Available (RE_Root_Storage_Pool_Ptr)
+ then
+ Pool_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Pool_Id,
+ Subtype_Mark =>
+ New_Reference_To
+ (RTE (RE_Root_Storage_Pool), Loc),
+ Name =>
+ Make_Explicit_Dereference (Loc,
+ New_Reference_To
+ (Build_In_Place_Formal
+ (Par_Func, BIP_Storage_Pool), Loc)));
+ Set_Storage_Pool (Pool_Allocator, Pool_Id);
+ Set_Procedure_To_Call
+ (Pool_Allocator, RTE (RE_Allocate_Any));
+ else
+ Pool_Decl := Make_Null_Statement (Loc);
+ end if;
+
-- If the No_Allocators restriction is active, then only
-- an allocator for secondary stack allocation is needed.
-- It's OK for such allocators to have Comes_From_Source
@@ -5225,22 +5276,25 @@ package body Exp_Ch6 is
if Restriction_Active (No_Allocators) then
SS_Allocator := Heap_Allocator;
Heap_Allocator := Make_Null (Loc);
+ Pool_Allocator := Make_Null (Loc);
- -- Otherwise the heap allocator may be needed, so we make
- -- another allocator for secondary stack allocation.
+ -- Otherwise the heap and pool allocators may be needed,
+ -- so we make another allocator for secondary stack
+ -- allocation.
else
SS_Allocator := New_Copy_Tree (Heap_Allocator);
- -- The heap allocator is marked Comes_From_Source
- -- since it corresponds to an explicit user-written
- -- allocator (that is, it will only be executed on
- -- behalf of callers that call the function as
- -- initialization for such an allocator). This
- -- prevents errors when No_Implicit_Heap_Allocations
+ -- The heap and pool allocators are marked as
+ -- Comes_From_Source since they correspond to an
+ -- explicit user-written allocator (that is, it will
+ -- only be executed on behalf of callers that call the
+ -- function as initialization for such an allocator).
+ -- Prevents errors when No_Implicit_Heap_Allocations
-- is in force.
Set_Comes_From_Source (Heap_Allocator, True);
+ Set_Comes_From_Source (Pool_Allocator, True);
end if;
-- The allocator is returned on the secondary stack. We
@@ -5269,10 +5323,12 @@ package body Exp_Ch6 is
-- Create an if statement to test the BIP_Alloc_Form
-- formal and initialize the access object to either the
- -- BIP_Object_Access formal (BIP_Alloc_Form = 0), the
- -- result of allocating the object in the secondary stack
- -- (BIP_Alloc_Form = 1), or else an allocator to create
- -- the return object in the heap (BIP_Alloc_Form = 2).
+ -- BIP_Object_Access formal (BIP_Alloc_Form =
+ -- Caller_Allocation), the result of allocating the
+ -- object in the secondary stack (BIP_Alloc_Form =
+ -- Secondary_Stack), or else an allocator to create the
+ -- return object in the heap or user-defined pool
+ -- (BIP_Alloc_Form = Global_Heap or User_Storage_Pool).
-- ??? An unchecked type conversion must be made in the
-- case of assigning the access object formal to the
@@ -5320,15 +5376,34 @@ package body Exp_Ch6 is
Make_Assignment_Statement (Loc,
Name =>
New_Reference_To (Alloc_Obj_Id, Loc),
- Expression => SS_Allocator)))),
+ Expression => SS_Allocator))),
+
+ Make_Elsif_Part (Loc,
+ Condition =>
+ Make_Op_Eq (Loc,
+ Left_Opnd =>
+ New_Reference_To (Obj_Alloc_Formal, Loc),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc,
+ UI_From_Int (BIP_Allocation_Form'Pos
+ (Global_Heap)))),
+
+ Then_Statements => New_List (
+ Build_Heap_Allocator
+ (Temp_Id => Alloc_Obj_Id,
+ Temp_Typ => Ref_Type,
+ Func_Id => Par_Func,
+ Ret_Typ => Return_Obj_Typ,
+ Alloc_Expr => Heap_Allocator)))),
Else_Statements => New_List (
+ Pool_Decl,
Build_Heap_Allocator
(Temp_Id => Alloc_Obj_Id,
Temp_Typ => Ref_Type,
Func_Id => Par_Func,
Ret_Typ => Return_Obj_Typ,
- Alloc_Expr => Heap_Allocator)));
+ Alloc_Expr => Pool_Allocator)));
-- If a separate initialization assignment was created
-- earlier, append that following the assignment of the
@@ -7592,7 +7667,7 @@ package body Exp_Ch6 is
-- called as a dispatching operation and must be treated similarly
-- to functions with unconstrained result subtypes.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
Add_Finalization_Master_Actual_To_Build_In_Place_Call
@@ -7623,11 +7698,30 @@ package body Exp_Ch6 is
-- operations. ???
else
- -- Pass an allocation parameter indicating that the function should
- -- allocate its result on the heap.
+ -- Case of a user-defined storage pool. Pass an allocation parameter
+ -- indicating that the function should allocate its result in the
+ -- pool, and pass the pool. Use 'Unrestricted_Access because the
+ -- pool may not be aliased.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
- (Func_Call, Function_Id, Alloc_Form => Global_Heap);
+ if VM_Target = No_VM
+ and then Present (Associated_Storage_Pool (Acc_Type))
+ then
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
+ (Func_Call, Function_Id, Alloc_Form => User_Storage_Pool,
+ Pool_Actual =>
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Reference_To
+ (Associated_Storage_Pool (Acc_Type), Loc),
+ Attribute_Name => Name_Unrestricted_Access));
+
+ -- No user-defined pool; pass an allocation parameter indicating that
+ -- the function should allocate its result on the heap.
+
+ else
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
+ (Func_Call, Function_Id, Alloc_Form => Global_Heap);
+ end if;
Add_Finalization_Master_Actual_To_Build_In_Place_Call
(Func_Call, Function_Id, Acc_Type);
@@ -7796,7 +7890,7 @@ package body Exp_Ch6 is
-- called as a dispatching operation and must be treated similarly
-- to functions with unconstrained result subtypes.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
Add_Finalization_Master_Actual_To_Build_In_Place_Call
@@ -7820,7 +7914,7 @@ package body Exp_Ch6 is
-- Pass an allocation parameter indicating that the function should
-- allocate its result on the secondary stack.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Secondary_Stack);
Add_Finalization_Master_Actual_To_Build_In_Place_Call
@@ -7898,7 +7992,7 @@ package body Exp_Ch6 is
-- controlling result, because dispatching calls to the function needs
-- to be treated effectively the same as calls to class-wide functions.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Func_Id, Alloc_Form => Caller_Allocation);
Add_Finalization_Master_Actual_To_Build_In_Place_Call
@@ -7978,20 +8072,20 @@ package body Exp_Ch6 is
Loc : Source_Ptr;
Obj_Def_Id : constant Entity_Id :=
Defining_Identifier (Object_Decl);
-
- Func_Call : Node_Id := Function_Call;
- Function_Id : Entity_Id;
- Result_Subt : Entity_Id;
- Caller_Object : Node_Id;
- Call_Deref : Node_Id;
- Ref_Type : Entity_Id;
- Ptr_Typ_Decl : Node_Id;
- Def_Id : Entity_Id;
- New_Expr : Node_Id;
Enclosing_Func : constant Entity_Id :=
Enclosing_Subprogram (Obj_Def_Id);
+ Call_Deref : Node_Id;
+ Caller_Object : Node_Id;
+ Def_Id : Entity_Id;
Fmaster_Actual : Node_Id := Empty;
+ Func_Call : Node_Id := Function_Call;
+ Function_Id : Entity_Id;
+ Pool_Actual : Node_Id;
+ Ptr_Typ_Decl : Node_Id;
Pass_Caller_Acc : Boolean := False;
+ New_Expr : Node_Id;
+ Ref_Type : Entity_Id;
+ Result_Subt : Entity_Id;
begin
-- Step past qualification or unchecked conversion (the latter can occur
@@ -8047,19 +8141,33 @@ package body Exp_Ch6 is
-- has an unconstrained or tagged result type).
if Needs_BIP_Alloc_Form (Enclosing_Func) then
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ if VM_Target = No_VM and then
+ RTE_Available (RE_Root_Storage_Pool_Ptr)
+ then
+ Pool_Actual :=
+ New_Reference_To (Build_In_Place_Formal
+ (Enclosing_Func, BIP_Storage_Pool), Loc);
+
+ -- The build-in-place pool formal is not built on .NET/JVM
+
+ else
+ Pool_Actual := Empty;
+ end if;
+
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call,
Function_Id,
Alloc_Form_Exp =>
New_Reference_To
(Build_In_Place_Formal (Enclosing_Func, BIP_Alloc_Form),
- Loc));
+ Loc),
+ Pool_Actual => Pool_Actual);
-- Otherwise, if enclosing function has a constrained result subtype,
-- then caller allocation will be used.
else
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
end if;
@@ -8102,7 +8210,7 @@ package body Exp_Ch6 is
-- called as a dispatching operation and must be treated similarly
-- to functions with unconstrained result subtypes.
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id, Alloc_Form => Caller_Allocation);
-- In other unconstrained cases, pass an indication to do the allocation
@@ -8111,10 +8219,8 @@ package body Exp_Ch6 is
-- scope is established to ensure eventual cleanup of the result.
else
- Add_Alloc_Form_Actual_To_Build_In_Place_Call
- (Func_Call,
- Function_Id,
- Alloc_Form => Secondary_Stack);
+ Add_Unconstrained_Actuals_To_Build_In_Place_Call
+ (Func_Call, Function_Id, Alloc_Form => Secondary_Stack);
Caller_Object := Empty;
Establish_Transient_Scope (Object_Decl, Sec_Stack => True);
@@ -8138,8 +8244,8 @@ package body Exp_Ch6 is
Add_Task_Actuals_To_Build_In_Place_Call
(Func_Call, Function_Id,
Master_Actual =>
- New_Reference_To
- (Build_In_Place_Formal (Enclosing_Func, BIP_Master), Loc));
+ New_Reference_To (Build_In_Place_Formal
+ (Enclosing_Func, BIP_Task_Master), Loc));
else
Add_Task_Actuals_To_Build_In_Place_Call
diff --git a/gcc/ada/exp_ch6.ads b/gcc/ada/exp_ch6.ads
index 06145f525e0..77df2b7da42 100644
--- a/gcc/ada/exp_ch6.ads
+++ b/gcc/ada/exp_ch6.ads
@@ -88,21 +88,26 @@ package Exp_Ch6 is
type BIP_Formal_Kind is
-- Ada 2005 (AI-318-02): This type defines the kinds of implicit extra
- -- formals created for build-in-place functions. The order of the above
+ -- formals created for build-in-place functions. The order of these
-- enumeration literals matches the order in which the formals are
-- declared. See Sem_Ch6.Create_Extra_Formals.
(BIP_Alloc_Form,
- -- Present if result subtype is unconstrained, or if the result type
- -- is tagged. Indicates whether the return object is allocated by the
- -- caller or callee, and if the callee, whether to use the secondary
- -- stack or the heap. See Create_Extra_Formals.
+ -- Present if result subtype is unconstrained or tagged. Indicates
+ -- whether the return object is allocated by the caller or callee, and
+ -- if the callee, whether to use the secondary stack or the heap. See
+ -- Create_Extra_Formals.
+
+ BIP_Storage_Pool,
+ -- Present if result subtype is unconstrained or tagged. If
+ -- BIP_Alloc_Form = User_Storage_Pool, this is a pointer to the pool
+ -- (of type access to Root_Storage_Pool'Class). Otherwise null.
BIP_Finalization_Master,
-- Present if result type needs finalization. Pointer to caller's
-- finalization master.
- BIP_Master,
+ BIP_Task_Master,
-- Present if result type contains tasks. Master associated with
-- calling context.
@@ -114,8 +119,7 @@ package Exp_Ch6 is
-- the return object, or null if BIP_Alloc_Form indicates allocated by
-- callee.
--
- -- ??? We also need to be able to pass in some way to access a user-
- -- defined storage pool at some point. And perhaps a constrained flag.
+ -- ??? We might also need to be able to pass in a constrained flag.
function BIP_Formal_Suffix (Kind : BIP_Formal_Kind) return String;
-- Ada 2005 (AI-318-02): Returns a string to be used as the suffix of names
@@ -197,14 +201,14 @@ package Exp_Ch6 is
-- for which Is_Build_In_Place_Call is True, or an N_Qualified_Expression
-- node applied to such a function call.
- function Needs_BIP_Finalization_Master (Func_Id : Entity_Id) return Boolean;
- -- Ada 2005 (AI-318-02): Return True if the function needs an implicit
- -- finalization master implicit parameter.
-
function Needs_BIP_Alloc_Form (Func_Id : Entity_Id) return Boolean;
-- Ada 2005 (AI-318-02): Return True if the function needs an implicit
-- BIP_Alloc_Form parameter (see type BIP_Formal_Kind).
+ function Needs_BIP_Finalization_Master (Func_Id : Entity_Id) return Boolean;
+ -- Ada 2005 (AI-318-02): Return True if the result subtype of function
+ -- Func_Id needs finalization actions.
+
function Needs_Result_Accessibility_Level
(Func_Id : Entity_Id) return Boolean;
-- Ada 2012 (AI05-0234): Return True if the function needs an implicit
diff --git a/gcc/ada/exp_ch9.adb b/gcc/ada/exp_ch9.adb
index 433ee6b3a74..8305278e8d8 100644
--- a/gcc/ada/exp_ch9.adb
+++ b/gcc/ada/exp_ch9.adb
@@ -346,6 +346,18 @@ package body Exp_Ch9 is
-- to handle properly the case of bounds that depend on discriminants.
-- If Cap is true, the result is capped according to Entry_Family_Bound.
+ procedure Find_Enclosing_Context
+ (N : Node_Id;
+ Context : out Node_Id;
+ Context_Id : out Entity_Id;
+ Context_Decls : out List_Id);
+ -- Subsidiary routine to procedures Build_Activation_Chain_Entity and
+ -- Build_Master_Entity. Given an arbitrary node in the tree, find the
+ -- nearest enclosing body, block, package or return statement and return
+ -- its constituents. Context is the enclosing construct, Context_Id is
+ -- the scope of Context_Id and Context_Decls is the declarative list of
+ -- Context.
+
procedure Extract_Dispatching_Call
(N : Node_Id;
Call_Ent : out Entity_Id;
@@ -870,64 +882,33 @@ package body Exp_Ch9 is
-- Local variables
- Decls : List_Id;
- Par : Node_Id;
+ Context : Node_Id;
+ Context_Id : Entity_Id;
+ Decls : List_Id;
-- Start of processing for Build_Activation_Chain_Entity
begin
- -- Traverse the parent chain looking for an enclosing construct which
- -- contains an activation chain variable. The construct is either a
- -- body, a block, or an extended return.
-
- Par := Parent (N);
-
- while not Nkind_In (Par, N_Block_Statement,
- N_Entry_Body,
- N_Extended_Return_Statement,
- N_Package_Body,
- N_Package_Declaration,
- N_Subprogram_Body,
- N_Task_Body)
- loop
- Par := Parent (Par);
- end loop;
-
- -- When the enclosing construct is a package body, the activation chain
- -- variable is declared in the body, but the Activation_Chain_Entity is
- -- attached to the spec.
-
- if Nkind (Par) = N_Package_Body then
- Decls := Declarations (Par);
- Par := Unit_Declaration_Node (Corresponding_Spec (Par));
-
- elsif Nkind (Par) = N_Package_Declaration then
- Decls := Visible_Declarations (Specification (Par));
-
- elsif Nkind (Par) = N_Extended_Return_Statement then
- Decls := Return_Object_Declarations (Par);
-
- else
- Decls := Declarations (Par);
- end if;
+ Find_Enclosing_Context (N, Context, Context_Id, Decls);
-- If an activation chain entity has not been declared already, create
-- one.
- if Nkind (Par) = N_Extended_Return_Statement
- or else No (Activation_Chain_Entity (Par))
+ if Nkind (Context) = N_Extended_Return_Statement
+ or else No (Activation_Chain_Entity (Context))
then
-- Since extended return statements do not store the entity of the
-- chain, examine the return object declarations to avoid creating
-- a duplicate.
- if Nkind (Par) = N_Extended_Return_Statement
- and then Has_Activation_Chain (Par)
+ if Nkind (Context) = N_Extended_Return_Statement
+ and then Has_Activation_Chain (Context)
then
return;
end if;
declare
+ Loc : constant Source_Ptr := Sloc (Context);
Chain : Entity_Id;
Decl : Node_Id;
@@ -943,19 +924,29 @@ package body Exp_Ch9 is
-- Activate_Tasks. Task activation is the responsibility of the
-- caller.
- if Nkind (Par) /= N_Extended_Return_Statement then
- Set_Activation_Chain_Entity (Par, Chain);
+ if Nkind (Context) /= N_Extended_Return_Statement then
+ Set_Activation_Chain_Entity (Context, Chain);
end if;
Decl :=
- Make_Object_Declaration (Sloc (Par),
+ Make_Object_Declaration (Loc,
Defining_Identifier => Chain,
Aliased_Present => True,
Object_Definition =>
- New_Reference_To (RTE (RE_Activation_Chain), Sloc (Par)));
+ New_Reference_To (RTE (RE_Activation_Chain), Loc));
Prepend_To (Decls, Decl);
- Analyze (Decl);
+
+ -- Ensure that the _chain appears in the proper scope of the
+ -- context.
+
+ if Context_Id /= Current_Scope then
+ Push_Scope (Context_Id);
+ Analyze (Decl);
+ Pop_Scope;
+ else
+ Analyze (Decl);
+ end if;
end;
end if;
end Build_Activation_Chain_Entity;
@@ -1073,6 +1064,127 @@ package body Exp_Ch9 is
Parameter_Associations => New_List (Concurrent_Ref (N)));
end Build_Call_With_Task;
+ -----------------------------
+ -- Build_Class_Wide_Master --
+ -----------------------------
+
+ procedure Build_Class_Wide_Master (Typ : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (Typ);
+ Master_Id : Entity_Id;
+ Master_Scope : Entity_Id;
+ Name_Id : Node_Id;
+ Related_Node : Node_Id;
+ Ren_Decl : Node_Id;
+
+ begin
+ -- Nothing to do if there is no task hierarchy
+
+ if Restriction_Active (No_Task_Hierarchy) then
+ return;
+ end if;
+
+ -- Find the declaration that created the access type. It is either a
+ -- type declaration, or an object declaration with an access definition,
+ -- in which case the type is anonymous.
+
+ if Is_Itype (Typ) then
+ Related_Node := Associated_Node_For_Itype (Typ);
+ else
+ Related_Node := Parent (Typ);
+ end if;
+
+ Master_Scope := Find_Master_Scope (Typ);
+
+ -- Nothing to do if the master scope already contains a _master entity.
+ -- The only exception to this is the following scenario:
+
+ -- Source_Scope
+ -- Transient_Scope_1
+ -- _master
+
+ -- Transient_Scope_2
+ -- use of master
+
+ -- In this case the source scope is marked as having the master entity
+ -- even though the actual declaration appears inside an inner scope. If
+ -- the second transient scope requires a _master, it cannot use the one
+ -- already declared because the entity is not visible.
+
+ Name_Id := Make_Identifier (Loc, Name_uMaster);
+
+ if not Has_Master_Entity (Master_Scope)
+ or else No (Current_Entity_In_Scope (Name_Id))
+ then
+ declare
+ Master_Decl : Node_Id;
+
+ begin
+ Set_Has_Master_Entity (Master_Scope);
+
+ -- Generate:
+ -- _master : constant Integer := Current_Master.all;
+
+ Master_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier =>
+ Make_Defining_Identifier (Loc, Name_uMaster),
+ Constant_Present => True,
+ Object_Definition =>
+ New_Reference_To (Standard_Integer, Loc),
+ Expression =>
+ Make_Explicit_Dereference (Loc,
+ New_Reference_To (RTE (RE_Current_Master), Loc)));
+
+ Insert_Action (Related_Node, Master_Decl);
+ Analyze (Master_Decl);
+
+ -- Mark the containing scope as a task master. Masters associated
+ -- with return statements are already marked at this stage (see
+ -- Analyze_Subprogram_Body).
+
+ if Ekind (Current_Scope) /= E_Return_Statement then
+ declare
+ Par : Node_Id := Related_Node;
+
+ begin
+ while Nkind (Par) /= N_Compilation_Unit loop
+ Par := Parent (Par);
+
+ -- If we fall off the top, we are at the outer level, and
+ -- the environment task is our effective master, so
+ -- nothing to mark.
+
+ if Nkind_In (Par, N_Block_Statement,
+ N_Subprogram_Body,
+ N_Task_Body)
+ then
+ Set_Is_Task_Master (Par);
+ exit;
+ end if;
+ end loop;
+ end;
+ end if;
+ end;
+ end if;
+
+ Master_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Typ), 'M'));
+
+ -- Generate:
+ -- Mnn renames _master;
+
+ Ren_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Master_Id,
+ Subtype_Mark => New_Reference_To (Standard_Integer, Loc),
+ Name => Name_Id);
+
+ Insert_Action (Related_Node, Ren_Decl);
+
+ Set_Master_Id (Typ, Master_Id);
+ end Build_Class_Wide_Master;
+
--------------------------------
-- Build_Corresponding_Record --
--------------------------------
@@ -2763,64 +2875,150 @@ package body Exp_Ch9 is
-- Build_Master_Entity --
-------------------------
- procedure Build_Master_Entity (E : Entity_Id) is
- Loc : constant Source_Ptr := Sloc (E);
- P : Node_Id;
- Decl : Node_Id;
- S : Entity_Id;
+ procedure Build_Master_Entity (Obj_Or_Typ : Entity_Id) is
+ Loc : constant Source_Ptr := Sloc (Obj_Or_Typ);
+ Context : Node_Id;
+ Context_Id : Entity_Id;
+ Decl : Node_Id;
+ Decls : List_Id;
+ Par : Node_Id;
begin
- S := Find_Master_Scope (E);
+ if Is_Itype (Obj_Or_Typ) then
+ Par := Associated_Node_For_Itype (Obj_Or_Typ);
+ else
+ Par := Parent (Obj_Or_Typ);
+ end if;
+
+ -- When creating a master for a record component which is either a task
+ -- or access-to-task, the enclosing record is the master scope and the
+ -- proper insertion point is the component list.
+
+ if Is_Record_Type (Current_Scope) then
+ Context := Par;
+ Context_Id := Current_Scope;
+ Decls := List_Containing (Context);
+
+ -- Default case for object declarations and access types. Note that the
+ -- context is updated to the nearest enclosing body, block, package or
+ -- return statement.
- -- Nothing to do if we already built a master entity for this scope
- -- or if there is no task hierarchy.
+ else
+ Find_Enclosing_Context (Par, Context, Context_Id, Decls);
+ end if;
+
+ -- Do not create a master if one already exists or there is no task
+ -- hierarchy.
- if Has_Master_Entity (S)
+ if Has_Master_Entity (Context_Id)
or else Restriction_Active (No_Task_Hierarchy)
then
return;
end if;
- -- Otherwise first build the master entity
+ -- Create a master, generate:
-- _Master : constant Master_Id := Current_Master.all;
- -- and insert it just before the current declaration
Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier =>
Make_Defining_Identifier (Loc, Name_uMaster),
- Constant_Present => True,
- Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
- Expression =>
+ Constant_Present => True,
+ Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
+ Expression =>
Make_Explicit_Dereference (Loc,
New_Reference_To (RTE (RE_Current_Master), Loc)));
- P := Parent (E);
- Insert_Before (P, Decl);
- Analyze (Decl);
+ -- The master is inserted at the start of the declarative list of the
+ -- context.
- Set_Has_Master_Entity (S);
+ Prepend_To (Decls, Decl);
- -- Now mark the containing scope as a task master
+ -- In certain cases where transient scopes are involved, the immediate
+ -- scope is not always the proper master scope. Ensure that the master
+ -- declaration and entity appear in the same context.
- while Nkind (P) /= N_Compilation_Unit loop
- P := Parent (P);
+ if Context_Id /= Current_Scope then
+ Push_Scope (Context_Id);
+ Analyze (Decl);
+ Pop_Scope;
+ else
+ Analyze (Decl);
+ end if;
- -- If we fall off the top, we are at the outer level, and the
- -- environment task is our effective master, so nothing to mark.
+ -- Mark the enclosing scope and its associated construct as being task
+ -- masters.
- if Nkind_In
- (P, N_Task_Body, N_Block_Statement, N_Subprogram_Body)
+ Set_Has_Master_Entity (Context_Id);
+
+ while Present (Context)
+ and then Nkind (Context) /= N_Compilation_Unit
+ loop
+ if Nkind_In (Context, N_Block_Statement,
+ N_Subprogram_Body,
+ N_Task_Body)
then
- Set_Is_Task_Master (P, True);
- return;
+ Set_Is_Task_Master (Context);
+ exit;
- elsif Nkind (Parent (P)) = N_Subunit then
- P := Corresponding_Stub (Parent (P));
+ elsif Nkind (Parent (Context)) = N_Subunit then
+ Context := Corresponding_Stub (Parent (Context));
end if;
+
+ Context := Parent (Context);
end loop;
end Build_Master_Entity;
+ ---------------------------
+ -- Build_Master_Renaming --
+ ---------------------------
+
+ procedure Build_Master_Renaming
+ (Ptr_Typ : Entity_Id;
+ Ins_Nod : Node_Id := Empty)
+ is
+ Loc : constant Source_Ptr := Sloc (Ptr_Typ);
+ Context : Node_Id;
+ Master_Decl : Node_Id;
+ Master_Id : Entity_Id;
+
+ begin
+ -- Nothing to do if there is no task hierarchy
+
+ if Restriction_Active (No_Task_Hierarchy) then
+ return;
+ end if;
+
+ -- Determine the proper context to insert the master renaming
+
+ if Present (Ins_Nod) then
+ Context := Ins_Nod;
+ elsif Is_Itype (Ptr_Typ) then
+ Context := Associated_Node_For_Itype (Ptr_Typ);
+ else
+ Context := Parent (Ptr_Typ);
+ end if;
+
+ -- Generate:
+ -- <Ptr_Typ>M : Master_Id renames _Master;
+
+ Master_Id :=
+ Make_Defining_Identifier (Loc,
+ New_External_Name (Chars (Ptr_Typ), 'M'));
+
+ Master_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Master_Id,
+ Subtype_Mark => New_Reference_To (RTE (RE_Master_Id), Loc),
+ Name => Make_Identifier (Loc, Name_uMaster));
+
+ Insert_Action (Context, Master_Decl);
+
+ -- The renamed master now services the access type
+
+ Set_Master_Id (Ptr_Typ, Master_Id);
+ end Build_Master_Renaming;
+
-----------------------------------------
-- Build_Private_Protected_Declaration --
-----------------------------------------
@@ -4236,7 +4434,7 @@ package body Exp_Ch9 is
Make_Object_Declaration (Loc,
Defining_Identifier => Chain,
- Aliased_Present => True,
+ Aliased_Present => True,
Object_Definition =>
New_Reference_To (RTE (RE_Activation_Chain), Loc))),
@@ -11849,6 +12047,94 @@ package body Exp_Ch9 is
Make_Integer_Literal (Loc, 0)));
end Family_Size;
+ ----------------------------
+ -- Find_Enclosing_Context --
+ ----------------------------
+
+ procedure Find_Enclosing_Context
+ (N : Node_Id;
+ Context : out Node_Id;
+ Context_Id : out Entity_Id;
+ Context_Decls : out List_Id)
+ is
+ begin
+ -- Traverse the parent chain looking for an enclosing body, block,
+ -- package or return statement.
+
+ Context := Parent (N);
+ while not Nkind_In (Context, N_Block_Statement,
+ N_Entry_Body,
+ N_Extended_Return_Statement,
+ N_Package_Body,
+ N_Package_Declaration,
+ N_Subprogram_Body,
+ N_Task_Body)
+ loop
+ Context := Parent (Context);
+ end loop;
+
+ -- Extract the constituents of the context
+
+ if Nkind (Context) = N_Extended_Return_Statement then
+ Context_Decls := Return_Object_Declarations (Context);
+ Context_Id := Return_Statement_Entity (Context);
+
+ -- Package declarations and bodies use a common library-level activation
+ -- chain or task master, therefore return the package declaration as the
+ -- proper carrier for the appropriate flag.
+
+ elsif Nkind (Context) = N_Package_Body then
+ Context_Decls := Declarations (Context);
+ Context_Id := Corresponding_Spec (Context);
+ Context := Parent (Context_Id);
+
+ if Nkind (Context) = N_Defining_Program_Unit_Name then
+ Context := Parent (Parent (Context));
+ else
+ Context := Parent (Context);
+ end if;
+
+ elsif Nkind (Context) = N_Package_Declaration then
+ Context_Decls := Visible_Declarations (Specification (Context));
+ Context_Id := Defining_Unit_Name (Specification (Context));
+
+ if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
+ Context_Id := Defining_Identifier (Context_Id);
+ end if;
+
+ else
+ Context_Decls := Declarations (Context);
+
+ if Nkind (Context) = N_Block_Statement then
+ Context_Id := Entity (Identifier (Context));
+
+ elsif Nkind (Context) = N_Entry_Body then
+ Context_Id := Defining_Identifier (Context);
+
+ elsif Nkind (Context) = N_Subprogram_Body then
+ if Present (Corresponding_Spec (Context)) then
+ Context_Id := Corresponding_Spec (Context);
+ else
+ Context_Id := Defining_Unit_Name (Specification (Context));
+
+ if Nkind (Context_Id) = N_Defining_Program_Unit_Name then
+ Context_Id := Defining_Identifier (Context_Id);
+ end if;
+ end if;
+
+ elsif Nkind (Context) = N_Task_Body then
+ Context_Id := Corresponding_Spec (Context);
+
+ else
+ raise Program_Error;
+ end if;
+ end if;
+
+ pragma Assert (Present (Context));
+ pragma Assert (Present (Context_Id));
+ pragma Assert (Present (Context_Decls));
+ end Find_Enclosing_Context;
+
-----------------------
-- Find_Master_Scope --
-----------------------
diff --git a/gcc/ada/exp_ch9.ads b/gcc/ada/exp_ch9.ads
index ea2fb8e7916..3bbbf0dc719 100644
--- a/gcc/ada/exp_ch9.ads
+++ b/gcc/ada/exp_ch9.ads
@@ -50,28 +50,32 @@ package Exp_Ch9 is
-- Task_Id of the associated task as the parameter. The caller is
-- responsible for analyzing and resolving the resulting tree.
+ procedure Build_Class_Wide_Master (Typ : Entity_Id);
+ -- Given an access-to-limited class-wide type or an access-to-limited
+ -- interface, ensure that the designated type has a _master and generate
+ -- a renaming of the said master to service the access type.
+
function Build_Entry_Names (Conc_Typ : Entity_Id) return Node_Id;
-- Create the statements which populate the entry names array of a task or
-- protected type. The statements are wrapped inside a block due to a local
-- declaration.
- procedure Build_Master_Entity (E : Entity_Id);
- -- Given an entity E for the declaration of an object containing tasks
- -- or of a type declaration for an allocator whose designated type is a
- -- task or contains tasks, this routine marks the appropriate enclosing
- -- context as a master, and also declares a variable called _Master in
- -- the current declarative part which captures the value of Current_Master
- -- (if not already built by a prior call). We build this object (instead
- -- of just calling Current_Master) for two reasons. First it is clearly
- -- more efficient to call Current_Master only once for a bunch of tasks
- -- in the same declarative part, and second it makes things easier in
- -- generating the initialization routines, since they can just reference
- -- the object _Master by name, and they will get the proper Current_Master
- -- value at the outer level, and copy in the parameter value for the outer
- -- initialization call if the call is for a nested component). Note that
- -- in the case of nested packages, we only really need to make one such
- -- object at the outer level, but it is much easier to generate one per
- -- declarative part.
+ procedure Build_Master_Entity (Obj_Or_Typ : Entity_Id);
+ -- Given the name of an object or a type which is either a task, contains
+ -- tasks or designates tasks, create a _master in the appropriate scope
+ -- which captures the value of Current_Master. Mark the nearest enclosing
+ -- body or block as being a task master.
+
+ procedure Build_Master_Renaming
+ (Ptr_Typ : Entity_Id;
+ Ins_Nod : Node_Id := Empty);
+ -- Given an access type Ptr_Typ whose designated type is either a task or
+ -- contains tasks, create a renaming of the form:
+ --
+ -- <Ptr_Typ>M : Master_Id renames _Master;
+ --
+ -- where _master denotes the task master of the enclosing context. Ins_Nod
+ -- is used to provide a specific insertion node for the renaming.
function Build_Private_Protected_Declaration (N : Node_Id) return Entity_Id;
-- A subprogram body without a previous spec that appears in a protected
diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb
index 5f9cd8326f1..21745288abf 100644
--- a/gcc/ada/exp_disp.adb
+++ b/gcc/ada/exp_disp.adb
@@ -3771,12 +3771,16 @@ package body Exp_Disp is
-- Start of processing for Check_Premature_Freezing
begin
+ -- Note that if the type is a (subtype of) a generic actual, the
+ -- actual will have been frozen by the instantiation.
+
if Present (N)
and then Is_Private_Type (Typ)
and then No (Full_View (Typ))
and then not Is_Generic_Type (Typ)
and then not Is_Tagged_Type (Typ)
and then not Is_Frozen (Typ)
+ and then not Is_Generic_Actual_Type (Typ)
then
Error_Msg_Sloc := Sloc (Subp);
Error_Msg_NE
diff --git a/gcc/ada/expect.c b/gcc/ada/expect.c
index 4f0f73fd15b..a40ffa3d29d 100644
--- a/gcc/ada/expect.c
+++ b/gcc/ada/expect.c
@@ -1,29 +1,28 @@
/****************************************************************************
* *
- * GNAT COMPILER COMPONENTS *
+ * GNAT RUN-TIME COMPONENTS *
* *
* E X P E C T *
* *
* C Implementation File *
* *
- * Copyright (C) 2001-2009, AdaCore *
+ * Copyright (C) 2001-2011, AdaCore *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
- * ware Foundation; either version 2, or (at your option) any later ver- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
* sion. GNAT is distributed in the hope that it will be useful, but WITH- *
* OUT 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 distributed with GNAT; see file COPYING. If not, write *
- * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
- * Boston, MA 02110-1301, USA. *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
* *
- * As a special exception, if you link this file with other files to *
- * produce an executable, this file does not by itself cause the resulting *
- * executable to be covered by the GNU General Public License. This except- *
- * ion does not however invalidate any other reasons why the executable *
- * file might be covered by the GNU Public License. *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
* *
* GNAT was originally developed by the GNAT team at New York University. *
* Extensive contributions were provided by Ada Core Technologies Inc. *
diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb
index 7d1dc1fc212..8c42fed255b 100644
--- a/gcc/ada/freeze.adb
+++ b/gcc/ada/freeze.adb
@@ -1407,7 +1407,11 @@ package body Freeze is
Decl := Unit_Declaration_Node (E);
if Nkind (Decl) = N_Subprogram_Renaming_Declaration then
- Build_And_Analyze_Renamed_Body (Decl, E, After);
+ if Error_Posted (Decl) then
+ Set_Has_Completion (E);
+ else
+ Build_And_Analyze_Renamed_Body (Decl, E, After);
+ end if;
elsif Nkind (Decl) = N_Subprogram_Declaration
and then Present (Corresponding_Body (Decl))
@@ -1616,8 +1620,8 @@ package body Freeze is
-- Start of processing for Check_Current_Instance
begin
- -- In Ada 95, the (imprecise) rule is that the current instance of a
- -- limited type is aliased. In Ada 2005, limitedness must be
+ -- In Ada 95, the (imprecise) rule is that the current instance
+ -- of a limited type is aliased. In Ada 2005, limitedness must be
-- explicit: either a tagged type, or a limited record.
if Is_Limited_Type (Rec_Type)
@@ -1646,6 +1650,7 @@ package body Freeze is
if Nkind (Decl) = N_Full_Type_Declaration then
declare
Tdef : constant Node_Id := Type_Definition (Decl);
+
begin
if Nkind (Tdef) = N_Modular_Type_Definition then
declare
diff --git a/gcc/ada/g-trasym.adb b/gcc/ada/g-trasym.adb
index 12793c870c4..ac2444e001e 100644
--- a/gcc/ada/g-trasym.adb
+++ b/gcc/ada/g-trasym.adb
@@ -30,8 +30,8 @@
------------------------------------------------------------------------------
-- This is the default implementation for platforms where the full capability
--- is not supported. It returns tracebacks as lists of "0x..." strings
--- corresponding to the addresses.
+-- is not supported. It returns tracebacks as lists of LF separated strings of
+-- the form "0x..." corresponding to the addresses.
with Ada.Exceptions.Traceback; use Ada.Exceptions.Traceback;
with System.Address_Image;
@@ -51,8 +51,10 @@ package body GNAT.Traceback.Symbolic is
else
declare
Img : String := System.Address_Image (Traceback (Traceback'First));
+
Result : String (1 .. (Img'Length + 3) * Traceback'Length);
Last : Natural := 0;
+
begin
for J in Traceback'Range loop
Img := System.Address_Image (Traceback (J));
diff --git a/gcc/ada/g-trasym.ads b/gcc/ada/g-trasym.ads
index 679d236e5f8..4b30600adb3 100644
--- a/gcc/ada/g-trasym.ads
+++ b/gcc/ada/g-trasym.ads
@@ -42,6 +42,10 @@
-- OpenVMS Alpha and ia64
-- Windows
+-- Note: on targets other than those listed above, a dummy implementation of
+-- the body returns a series of LF separated strings of the form "0x..."
+-- corresponding to the addresses.
+
-- The routines provided in this package assume that your application has
-- been compiled with debugging information turned on, since this information
-- is used to build a symbolic traceback.
@@ -87,8 +91,7 @@ package GNAT.Traceback.Symbolic is
pragma Elaborate_Body;
function Symbolic_Traceback (Traceback : Tracebacks_Array) return String;
- -- Build a string containing a symbolic traceback of the given call chain
- --
+ -- Build a string containing a symbolic traceback of the given call chain.
-- Note: This procedure may be installed by Set_Trace_Decorator, to get a
-- symbolic traceback on all exceptions raised (see GNAT.Exception_Traces).
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 9f25fc26d92..43d42f658b5 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -46,6 +46,7 @@ RMDIR = rm -rf
# Extra flags to pass to recursive makes.
COMMON_ADAFLAGS= -gnatpg -gnata
+WARN_ADAFLAGS= -W -Wall
BOOT_ADAFLAGS= $(COMMON_ADAFLAGS)
ifeq ($(CROSS),)
@@ -56,17 +57,23 @@ else
ADAFLAGS= $(COMMON_ADAFLAGS)
endif
-ALL_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(ADAFLAGS)
+ALL_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(ADAFLAGS) $(WARN_ADAFLAGS)
FORCE_DEBUG_ADAFLAGS = -g
ADA_CFLAGS =
ADA_INCLUDES = -nostdinc -I- -I. -Iada -I$(srcdir)/ada -I$(srcdir)/ada/gcc-interface
+GNATLIBFLAGS= -W -Wall -gnatpg -nostdinc
+GNATLIBCFLAGS= -g -O2 $(TCFLAGS)
ADA_INCLUDE_DIR = $(libsubdir)/adainclude
ADA_RTL_OBJ_DIR = $(libsubdir)/adalib
+THREAD_KIND=native
+TRACE=no
+# We do not want the WARN_CFLAGS of the compiler in Ada as it is for C/C++.
+COMMON_FLAGS_TO_PASS = $(filter-out -pedantic -W%, $(FLAGS_TO_PASS))
ADA_FLAGS_TO_PASS = \
"ADA_FOR_BUILD=$(ADA_FOR_BUILD)" \
"ADA_INCLUDE_DIR=$(ADA_INCLUDE_DIR)" \
"ADA_RTL_OBJ_DIR=$(ADA_RTL_OBJ_DIR)" \
- "ADAFLAGS=$(ADAFLAGS)" \
+ "ADAFLAGS=$(ADAFLAGS) $(WARN_ADAFLAGS)" \
"ADA_FOR_TARGET=$(ADA_FOR_TARGET)" \
"INSTALL=$(INSTALL)" \
"INSTALL_DATA=$(INSTALL_DATA)" \
@@ -99,14 +106,12 @@ ifeq ($(build), $(host))
# This is a regular native. So use the compiler from our current build
# tree.
ADA_TOOLS_FLAGS_TO_PASS=\
- "CC=../../xgcc -B../../" \
- "CFLAGS=$(CFLAGS)" \
- "exeext=$(exeext)" \
- "ADAFLAGS=$(ADAFLAGS)" \
- "ADA_INCLUDES=-I../rts" \
- "GNATMAKE=../../gnatmake" \
- "GNATLINK=../../gnatlink" \
- "GNATBIND=../../gnatbind"
+ CC="../../xgcc -B../../" \
+ $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
+ ADA_INCLUDES="-I- -I../rts" \
+ GNATMAKE="../../gnatmake" \
+ GNATLINK="../../gnatlink" \
+ GNATBIND="../../gnatbind"
else
# This is a regular cross compiler. Use the native compiler to compile
# the tools.
@@ -117,7 +122,7 @@ ifeq ($(build), $(host))
ADA_TOOLS_FLAGS_TO_PASS=\
CC="$(CC)" \
- $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
+ $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
ADA_INCLUDES="-I$(RTS_DIR)../adainclude -I$(RTS_DIR)" \
GNATMAKE="gnatmake" \
GNATBIND="gnatbind" \
@@ -139,7 +144,7 @@ else
# built runtime.
ADA_TOOLS_FLAGS_TO_PASS=\
CC="$(CC)" \
- $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
+ $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
ADA_INCLUDES="-I../rts" \
GNATMAKE="$(GNATMAKE_FOR_HOST)" \
GNATBIND="$(GNATBIND_FOR_HOST)" \
@@ -151,7 +156,7 @@ else
RTS_DIR:=$(strip $(subst \,/,$(shell $(GNATLS_FOR_HOST) -v | grep adalib )))
ADA_TOOLS_FLAGS_TO_PASS=\
CC="$(CC)" \
- $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
+ $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
ADA_INCLUDES="-I$(RTS_DIR)../adainclude -I$(RTS_DIR)" \
GNATMAKE="$(GNATMAKE_FOR_HOST)" \
GNATBIND="$(GNATBIND_FOR_HOST)" \
@@ -547,9 +552,7 @@ gnatbind$(exeext): ada/b_gnatb.o $(CONFIG_H) $(GNATBIND_OBJS) ggc-none.o libcomm
# use target-gcc target-gnatmake target-gnatbind target-gnatlink
gnattools: $(GCC_PARTS) $(CONFIG_H) prefix.o force
- $(MAKE) -C ada $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) \
- ADA_INCLUDES="-I- -I../rts"\
- CC="../../xgcc -B../../" GNATBIND="../../gnatbind" gnattools1
+ $(MAKE) -C ada $(ADA_TOOLS_FLAGS_TO_PASS) gnattools1
$(MAKE) -C ada $(ADA_TOOLS_FLAGS_TO_PASS) gnattools2
regnattools:
@@ -566,7 +569,7 @@ canadian-gnattools: force
$(MAKE) -C ada $(ADA_TOOLS_FLAGS_TO_PASS) gnattools2
gnatlib gnatlib-sjlj gnatlib-zcx gnatlib-shared: ada/s-oscons.ads force
- $(MAKE) -C ada $(FLAGS_TO_PASS) \
+ $(MAKE) -C ada $(COMMON_FLAGS_TO_PASS) \
GNATLIBFLAGS="$(GNATLIBFLAGS)" \
GNATLIBCFLAGS="$(GNATLIBCFLAGS)" \
TARGET_LIBGCC2_CFLAGS="$(TARGET_LIBGCC2_CFLAGS)" \
@@ -578,11 +581,6 @@ gnatlib gnatlib-sjlj gnatlib-zcx gnatlib-shared: ada/s-oscons.ads force
# use only for native compiler
gnatlib_and_tools: gnatlib gnattools
-# use cross-gcc
-gnat-cross: force
- make $(GNAT1_ADA_OBJS) CC="gcc -B../stage1/" CFLAGS="-S -gnatp" \
- $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) HOST_CFLAGS= HOST_CC=cc
-
# Build hooks:
ada.all.cross:
@@ -966,14 +964,14 @@ ada.install-common:
#
-if [ -f gnat1$(exeext) ] ; \
then \
- $(MAKE) $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib; \
+ $(MAKE) $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib; \
fi
install-gnatlib:
- $(MAKE) -C ada $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib$(LIBGNAT_TARGET)
+ $(MAKE) -C ada $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib$(LIBGNAT_TARGET)
install-gnatlib-obj:
- $(MAKE) -C ada $(FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib-obj
+ $(MAKE) -C ada $(COMMON_FLAGS_TO_PASS) $(ADA_FLAGS_TO_PASS) install-gnatlib-obj
ada.install-man:
ada.install-plugin:
@@ -1129,50 +1127,7 @@ $(check_acats_targets): check-acats%:
export testdir; cd $(ACATSDIR)$* && $(SHELL) $${testdir}/run_acats $$chapters
.PHONY: check-acats $(check_acats_targets)
-
-# Bootstrapping targets for just GNAT - use the same stage directories
-gnatboot: force
- -$(RM) gnatboot3
- $(MAKE) gnat1$(exeext) gnatbind$(exeext) CC="$(CC)" \
- CFLAGS="$(CFLAGS)"
- $(MAKE) gnatboot2 BOOT_CFLAGS="$(BOOT_CFLAGS)" \
- BOOT_ADAFLAGS="$(BOOT_ADAFLAGS)" \
- LDFLAGS="$(BOOT_LDFLAGS)"
-
-gnatboot2: force
- $(MAKE) gnatstage1
- $(MAKE) gnat1$(exeext) gnatbind$(exeext) CC="gcc -B../stage1/"\
- CFLAGS="$(BOOT_CFLAGS)" \
- ADAFLAGS="$(BOOT_ADAFLAGS)"\
- LDFLAGS="$(BOOT_LDFLAGS)" \
- GNATBIND="../stage1/gnatbind"
- $(MAKE) gnatboot3 BOOT_CFLAGS="$(BOOT_CFLAGS)" \
- BOOT_ADAFLAGS="$(BOOT_ADAFLAGS)" \
- LDFLAGS="$(BOOT_LDFLAGS)"
-
-gnatboot3:
- $(MAKE) gnatstage2
- $(MAKE) gnat1$(exeext) gnatbind$(exeext) CC="gcc -B../stage2/"\
- CFLAGS="$(BOOT_CFLAGS)" \
- ADAFLAGS="$(BOOT_ADAFLAGS)"\
- LDFLAGS="$(BOOT_LDFLAGS)" \
- GNATBIND="../stage2/gnatbind"
-
-gnatstage1: force
- -$(MKDIR) stage1
- -$(MKDIR) stage1/ada
- -$(MV) gnat1$(exeext) gnatbind$(exeext) stage1
- -$(MV) ada/*$(objext) ada/*.ali stage1/ada
- -$(MV) ada/stamp-* stage1/ada
-
-gnatstage2: force
- -$(MKDIR) stage2
- -$(MKDIR) stage2/ada
- -$(MV) gnat1$(exeext) gnatbind$(exeext) stage2
- -$(MV) ada/*$(objext) ada/*.ali stage2/ada
- -$(MV) ada/stamp-* stage2/ada
-
# Compiling object files from source files.
# Note that dependencies on obstack.h are not written
@@ -1248,8 +1203,9 @@ ada/a-tags.o : ada/a-tags.adb ada/a-tags.ads
$(CC) -c $(ALL_ADAFLAGS) $(FORCE_DEBUG_ADAFLAGS) $(ADA_INCLUDES) \
$< $(OUTPUT_OPTION)
-CFLAGS-ada/tracebak.o += $(ADA_CFLAGS) -fno-omit-frame-pointer
ada/tracebak.o : ada/tracebak.c $(CONFIG_H) $(SYSTEM_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) \
+ $(INCLUDES) -fno-omit-frame-pointer $< $(OUTPUT_OPTION)
# dependencies for windows specific tool (mdll)
@@ -1270,20 +1226,25 @@ ada/exit.o : ada/exit.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
ada/final.o : ada/final.c $(CONFIG_H) $(SYSTEM_H) ada/raise.h
ada/link.o : ada/link.c
-CFLAGS-ada/targext.o += $(ADA_CFLAGS)
ada/targext.o : ada/targext.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-CFLAGS-ada/cio.o += $(ADA_CFLAGS)
ada/cio.o : ada/cio.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-CFLAGS-ada/init.o += $(ADA_CFLAGS)
ada/init.o : ada/init.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-CFLAGS-ada/initialize.o += $(ADA_CFLAGS)
ada/initialize.o : ada/initialize.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-CFLAGS-ada/raise.o += $(ADA_CFLAGS)
ada/raise.o : ada/raise.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
ada/cuintp.o : ada/gcc-interface/cuintp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) ada/gcc-interface/ada.h ada/types.h ada/uintp.h \
@@ -3759,9 +3720,9 @@ ada/sem_aggr.o : ada/ada.ads ada/a-except.ads ada/a-unccon.ads \
ada/lib-list.adb ada/lib-load.ads ada/lib-sort.adb ada/lib-util.ads \
ada/lib-xref.ads ada/namet.ads ada/namet.adb ada/namet-sp.ads \
ada/nlists.ads ada/nlists.adb ada/nmake.ads ada/nmake.adb ada/opt.ads \
- ada/output.ads ada/par_sco.ads ada/put_alfa.ads ada/restrict.ads \
- ada/restrict.adb ada/rident.ads ada/rtsfind.ads ada/scans.ads \
- ada/sem.ads ada/sem.adb ada/sem_aggr.ads ada/sem_aggr.adb \
+ ada/opt.adb ada/output.ads ada/par_sco.ads ada/put_alfa.ads \
+ ada/restrict.ads ada/restrict.adb ada/rident.ads ada/rtsfind.ads \
+ ada/scans.ads ada/sem.ads ada/sem.adb ada/sem_aggr.ads ada/sem_aggr.adb \
ada/sem_attr.ads ada/sem_aux.ads ada/sem_aux.adb ada/sem_cat.ads \
ada/sem_ch10.ads ada/sem_ch11.ads ada/sem_ch12.ads ada/sem_ch13.ads \
ada/sem_ch13.adb ada/sem_ch2.ads ada/sem_ch3.ads ada/sem_ch4.ads \
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 71bd5ea7993..990a6987736 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -105,25 +105,22 @@ TEXI2PDF = texi2pdf
GNATBIND_FLAGS = -static -x
ADA_CFLAGS =
ADAFLAGS = -W -Wall -gnatpg -gnata
-SOME_ADAFLAGS =-gnata
FORCE_DEBUG_ADAFLAGS = -g
-NO_SIBLING_ADAFLAGS=-fno-optimize-sibling-calls
-NO_REORDER_ADAFLAGS=-fno-toplevel-reorder
-GNATLIBFLAGS = -gnatpg -nostdinc
+NO_SIBLING_ADAFLAGS = -fno-optimize-sibling-calls
+NO_REORDER_ADAFLAGS = -fno-toplevel-reorder
+GNATLIBFLAGS = -W -Wall -gnatpg -nostdinc
GNATLIBCFLAGS = -g -O2
PICFLAG_FOR_TARGET = @PICFLAG_FOR_TARGET@
# Pretend that _Unwind_GetIPInfo is available for the target by default. This
# should be autodetected during the configuration of libada and passed down to
# here, but we need something for --disable-libada and hope for the best.
-GNATLIBCFLAGS_FOR_C = $(GNATLIBCFLAGS) $(PICFLAG_FOR_TARGET) -fexceptions \
- -DIN_RTS -DHAVE_GETIPINFO
+GNATLIBCFLAGS_FOR_C = -W -Wall $(GNATLIBCFLAGS) $(PICFLAG_FOR_TARGET) \
+ -fexceptions -DIN_RTS -DHAVE_GETIPINFO
ALL_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(ADAFLAGS)
-MOST_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(SOME_ADAFLAGS)
THREAD_KIND = native
THREADSLIB =
GMEM_LIB =
MISCLIB =
-SYMDEPS = $(LIBINTL_DEP)
OUTPUT_OPTION = @OUTPUT_OPTION@
objext = .o
@@ -177,13 +174,13 @@ top_builddir = ../..
LIBINTL = @LIBINTL@
LIBINTL_DEP = @LIBINTL_DEP@
+# Character encoding conversion library.
+LIBICONV = @LIBICONV@
+LIBICONV_DEP = @LIBICONV_DEP@
+
# Any system libraries needed just for GNAT.
SYSLIBS = @GNAT_LIBEXC@
-# List of extra object files linked in with various programs.
-EXTRA_GNATTOOLS_OBJS = ../../libcommon-target.a ../../libcommon.a \
- ../../../libcpp/libcpp.a
-
# List extra gnattools
EXTRA_GNATTOOLS =
@@ -231,8 +228,7 @@ all.indirect: Makefile ../gnat1$(exeext)
INTERNAL_CFLAGS = @CROSS@ -DIN_GCC
# This is the variable actually used when we compile.
-LOOSE_CFLAGS = `echo $(CFLAGS) $(WARN2_CFLAGS)|sed -e 's/-pedantic//g' -e 's/-Wtraditional//g'`
-ALL_CFLAGS = $(INTERNAL_CFLAGS) $(T_CFLAGS) $(LOOSE_CFLAGS)
+ALL_CFLAGS = $(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS)
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS)
@@ -245,11 +241,13 @@ LIBIBERTY = ../../libiberty/libiberty.a
# How to link with both our special library facilities
# and the system's installed libraries.
-LIBS = $(LIBINTL) $(LIBIBERTY) $(SYSLIBS)
-LIBDEPS = $(LIBINTL_DEP) $(LIBIBERTY)
+LIBS = $(LIBINTL) $(LIBICONV) $(LIBIBERTY) $(SYSLIBS)
+LIBDEPS = $(LIBINTL_DEP) $(LIBICONV_DEP) $(LIBIBERTY)
# Default is no TGT_LIB; one might be passed down or something
TGT_LIB =
-TOOLS_LIBS = $(EXTRA_GNATTOOLS_OBJS) targext.o link.o $(LIBGNAT) $(LIBINTL) ../../../libiberty/libiberty.a $(SYSLIBS) $(TGT_LIB)
+TOOLS_LIBS = targext.o link.o ../../libcommon-target.a ../../libcommon.a \
+ ../../../libcpp/libcpp.a $(LIBGNAT) $(LIBINTL) $(LIBICONV) \
+ ../../../libiberty/libiberty.a $(SYSLIBS) $(TGT_LIB)
# Convert the target variable into a space separated list of architecture,
# manufacturer, and operating system and assign each of those to its own
@@ -576,6 +574,8 @@ ifeq ($(strip $(filter-out e500% powerpc% wrs vxworks,$(targ))),)
endif
endif
EXTRA_GNATRTL_NONTASKING_OBJS=i-vxwork.o i-vxwoio.o s-vxwexc.o
+ EXTRA_LIBGNAT_OBJS+=sigtramp-ppcvxw.o
+ EXTRA_LIBGNAT_SRCS+=sigtramp-ppcvxw.c
endif
endif
@@ -620,6 +620,9 @@ ifeq ($(strip $(filter-out powerpc% e500v2 wrs vxworksae,$(targ))),)
EXTRA_GNATRTL_NONTASKING_OBJS=i-vxwork.o i-vxwoio.o s-vxwexc.o
EXTRA_GNATRTL_TASKING_OBJS=s-vxwork.o s-vxwext.o
+ EXTRA_LIBGNAT_SRCS+=sigtramp-ppcvxw.c
+ EXTRA_LIBGNAT_OBJS+=sigtramp-ppcvxw.o
+
# Extra pairs for the vthreads runtime
ifeq ($(strip $(filter-out vthreads,$(THREAD_KIND))),)
LIBGNAT_TARGET_PAIRS += \
@@ -682,8 +685,8 @@ ifeq ($(strip $(filter-out e500% powerpc% wrs vxworksmils,$(targ))),)
EXTRA_GNATRTL_NONTASKING_OBJS=i-vxwork.o i-vxwoio.o s-thread.o s-vxwexc.o
EXTRA_GNATRTL_TASKING_OBJS=s-vxwork.o s-vxwext.o
- EXTRA_LIBGNAT_SRCS+=vx_stack_info.c
- EXTRA_LIBGNAT_OBJS+=vx_stack_info.o
+ EXTRA_LIBGNAT_SRCS+=vx_stack_info.c sigtramp-ppcvxw.c
+ EXTRA_LIBGNAT_OBJS+=vx_stack_info.o sigtramp-ppcvxw.o
GNATRTL_SOCKETS_OBJS =
ifeq ($(strip $(filter-out yes,$(TRACE))),)
@@ -847,7 +850,7 @@ ifeq ($(strip $(filter-out %86 wrs vxworks,$(targ))),)
system.ads<system-vxworks-x86-rtp.ads
EXTRA_GNATRTL_NONTASKING_OBJS=s-vxwexc.o
- EXTRA_LIBGNAT_SRCS+=affinity.o
+ EXTRA_LIBGNAT_OBJS+=affinity.o
EXTRA_LIBGNAT_SRCS+=affinity.c
else
ifeq ($(strip $(filter-out kernel-smp, $(THREAD_KIND))),)
@@ -1399,16 +1402,19 @@ ifeq ($(strip $(filter-out ibm aix%,$(manu) $(osys))),)
ppc64)
LIBGNAT_TARGET_PAIRS = \
$(LIBGNAT_TARGET_PAIRS_COMMON) $(LIBGNAT_TARGET_PAIRS_64)
+ TOOLS_TARGET_PAIRS = \
+ indepsw.adb<indepsw-aix.adb
else
LIBGNAT_TARGET_PAIRS = \
$(LIBGNAT_TARGET_PAIRS_COMMON) $(LIBGNAT_TARGET_PAIRS_32)
+ TOOLS_TARGET_PAIRS = \
+ indepsw.adb<indepsw-gnu.adb
endif
THREADSLIB = -lpthreads
EH_MECHANISM=-gcc
- TOOLS_TARGET_PAIRS = \
- mlib-tgt-specific.adb<mlib-tgt-specific-aix.adb \
- indepsw.adb<indepsw-aix.adb
+ TOOLS_TARGET_PAIRS += \
+ mlib-tgt-specific.adb<mlib-tgt-specific-aix.adb
GMEM_LIB = gmemlib
endif
@@ -2232,11 +2238,10 @@ LIBGNAT_OBJS = adadecode.o adaint.o argv.o cio.o cstreams.o ctrl_c.o \
include $(fsrcdir)/ada/Makefile.rtl
-GNATRTL_LINEARALGEBRA_OBJS = a-nlcoar.o a-nllcar.o \
- a-nucoar.o i-forbla.o i-forlap.o s-gearop.o
+GNATRTL_LINEARALGEBRA_OBJS = i-forbla.o i-forlap.o
GNATRTL_OBJS = $(GNATRTL_NONTASKING_OBJS) $(GNATRTL_TASKING_OBJS) \
- $(GNATRTL_LINEARALGEBRA_OBJS) g-trasym.o memtrack.o
+ $(GNATRTL_LINEARALGEBRA_OBJS) memtrack.o
# Default run time files
@@ -2416,7 +2421,6 @@ install-gnatlib: ../stamp-gnatlib-$(RTSDIR)
for file in $(RTSDIR)/*.ali; do \
$(INSTALL_DATA_DATE) $$file $(DESTDIR)$(ADA_RTL_OBJ_DIR); \
done
- -$(INSTALL_DATA) $(RTSDIR)/g-trasym$(objext) $(DESTDIR)$(ADA_RTL_OBJ_DIR)
-cd $(RTSDIR); for file in *$(arext);do \
$(INSTALL_DATA) $$file $(DESTDIR)$(ADA_RTL_OBJ_DIR); \
$(RANLIB_FOR_TARGET) $(DESTDIR)$(ADA_RTL_OBJ_DIR)/$$file; \
@@ -2736,10 +2740,6 @@ gnatlib-zcx:
THREAD_KIND="$(THREAD_KIND)" \
PICFLAG_FOR_TARGET="$(PICFLAG_FOR_TARGET)" gnatlib
-# .s files for cross-building
-gnat-cross: force
- make $(GNAT1_ADA_OBJS) CC="gcc -B../stage1/" CFLAGS="-S -gnatp"
-
# Compiling object files from source files.
# Note that dependencies on obstack.h are not written
@@ -2842,6 +2842,7 @@ mkdir.o : mkdir.c
socket.o : socket.c gsocket.h
sysdep.o : sysdep.c
raise.o : raise.c raise.h
+sigtramp-ppcvxw.o : sigtramp-ppcvxw.c sigtramp.h
vx_stack_info.o : vx_stack_info.c
raise-gcc.o : raise-gcc.c raise.h
diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index d10fcf0ad92..c408de30296 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -355,6 +355,9 @@ do { \
/* Nonzero in a DECL if it is made for a pointer that can never be null. */
#define DECL_CAN_NEVER_BE_NULL_P(NODE) DECL_LANG_FLAG_2 (NODE)
+/* Nonzero in a VAR_DECL if it is made for a loop parameter. */
+#define DECL_LOOP_PARM_P(NODE) DECL_LANG_FLAG_3 (VAR_DECL_CHECK (NODE))
+
/* Nonzero in a FIELD_DECL that is a dummy built for some internal reason. */
#define DECL_INTERNAL_P(NODE) DECL_LANG_FLAG_3 (FIELD_DECL_CHECK (NODE))
@@ -409,9 +412,16 @@ do { \
|| (DECL_ORIGINAL_FIELD (FIELD1) \
&& (DECL_ORIGINAL_FIELD (FIELD1) == DECL_ORIGINAL_FIELD (FIELD2))))
-/* In a VAR_DECL, points to the object being renamed if the VAR_DECL is a
- renaming pointer, otherwise 0. Note that this object is guaranteed to
- be protected against multiple evaluations. */
+/* In a VAR_DECL with the DECL_LOOP_PARM_P flag set, points to the special
+ induction variable that is built under certain circumstances, if any. */
+#define DECL_INDUCTION_VAR(NODE) \
+ GET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))
+#define SET_DECL_INDUCTION_VAR(NODE, X) \
+ SET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE), X)
+
+/* In a VAR_DECL without the DECL_LOOP_PARM_P flag set and that is a renaming
+ pointer, points to the object being renamed, if any. Note that this object
+ is guaranteed to be protected against multiple evaluations. */
#define DECL_RENAMED_OBJECT(NODE) \
GET_DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))
#define SET_DECL_RENAMED_OBJECT(NODE, X) \
diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index feb353ba783..49434430ecd 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -1431,10 +1431,14 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TREE_ADDRESSABLE (gnu_decl) = 1;
}
+ /* If this is a loop parameter, set the corresponding flag. */
+ else if (kind == E_Loop_Parameter)
+ DECL_LOOP_PARM_P (gnu_decl) = 1;
+
/* If this is a renaming pointer, attach the renamed object to it and
register it if we are at the global level. Note that an external
constant is at the global level. */
- if (TREE_CODE (gnu_decl) == VAR_DECL && renamed_obj)
+ else if (TREE_CODE (gnu_decl) == VAR_DECL && renamed_obj)
{
SET_DECL_RENAMED_OBJECT (gnu_decl, renamed_obj);
if ((!definition && kind == E_Constant) || global_bindings_p ())
@@ -3298,7 +3302,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
== INTEGER_CST)
{
gnu_size = DECL_SIZE (gnu_old_field);
- if (TREE_CODE (gnu_field_type) == RECORD_TYPE
+ if (RECORD_OR_UNION_TYPE_P (gnu_field_type)
&& !TYPE_FAT_POINTER_P (gnu_field_type)
&& host_integerp (TYPE_SIZE (gnu_field_type), 1))
gnu_field_type
@@ -4641,13 +4645,11 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
tree size;
/* If a size was specified, take it into account. Otherwise
- use the RM size for records as the type size has already
- been adjusted to the alignment. */
+ use the RM size for records or unions as the type size has
+ already been adjusted to the alignment. */
if (gnu_size)
size = gnu_size;
- else if ((TREE_CODE (gnu_type) == RECORD_TYPE
- || TREE_CODE (gnu_type) == UNION_TYPE
- || TREE_CODE (gnu_type) == QUAL_UNION_TYPE)
+ else if (RECORD_OR_UNION_TYPE_P (gnu_type)
&& !TYPE_FAT_POINTER_P (gnu_type))
size = rm_size (gnu_type);
else
@@ -5296,7 +5298,7 @@ gnat_to_gnu_component_type (Entity_Id gnat_array, bool definition,
&& !Is_Bit_Packed_Array (gnat_array)
&& !Has_Aliased_Components (gnat_array)
&& !Strict_Alignment (gnat_type)
- && TREE_CODE (gnu_type) == RECORD_TYPE
+ && RECORD_OR_UNION_TYPE_P (gnu_type)
&& !TYPE_FAT_POINTER_P (gnu_type)
&& host_integerp (TYPE_SIZE (gnu_type), 1))
gnu_type = make_packable_type (gnu_type, false);
@@ -6083,7 +6085,8 @@ static tree
elaborate_expression_1 (tree gnu_expr, Entity_Id gnat_entity, tree gnu_name,
bool definition, bool need_debug)
{
- const bool expr_global_p = Is_Public (gnat_entity) || global_bindings_p ();
+ const bool expr_public_p = Is_Public (gnat_entity);
+ const bool expr_global_p = expr_public_p || global_bindings_p ();
bool expr_variable_p, use_variable;
/* In most cases, we won't see a naked FIELD_DECL because a discriminant
@@ -6151,11 +6154,10 @@ elaborate_expression_1 (tree gnu_expr, Entity_Id gnat_entity, tree gnu_name,
if (use_variable || need_debug)
{
tree gnu_decl
- = create_var_decl (create_concat_name (gnat_entity,
- IDENTIFIER_POINTER (gnu_name)),
- NULL_TREE, TREE_TYPE (gnu_expr), gnu_expr,
- !need_debug, Is_Public (gnat_entity),
- !definition, expr_global_p, NULL, gnat_entity);
+ = create_var_decl_1
+ (create_concat_name (gnat_entity, IDENTIFIER_POINTER (gnu_name)),
+ NULL_TREE, TREE_TYPE (gnu_expr), gnu_expr, true, expr_public_p,
+ !definition, expr_global_p, !need_debug, NULL, gnat_entity);
if (use_variable)
return gnu_decl;
@@ -6353,9 +6355,7 @@ make_packable_type (tree type, bool in_record)
tree new_field_type = TREE_TYPE (old_field);
tree new_field, new_size;
- if ((TREE_CODE (new_field_type) == RECORD_TYPE
- || TREE_CODE (new_field_type) == UNION_TYPE
- || TREE_CODE (new_field_type) == QUAL_UNION_TYPE)
+ if (RECORD_OR_UNION_TYPE_P (new_field_type)
&& !TYPE_FAT_POINTER_P (new_field_type)
&& host_integerp (TYPE_SIZE (new_field_type), 1))
new_field_type = make_packable_type (new_field_type, true);
@@ -6365,9 +6365,7 @@ make_packable_type (tree type, bool in_record)
packable version of the record type, see finish_record_type. */
if (!DECL_CHAIN (old_field)
&& !TYPE_PACKED (type)
- && (TREE_CODE (new_field_type) == RECORD_TYPE
- || TREE_CODE (new_field_type) == UNION_TYPE
- || TREE_CODE (new_field_type) == QUAL_UNION_TYPE)
+ && RECORD_OR_UNION_TYPE_P (new_field_type)
&& !TYPE_FAT_POINTER_P (new_field_type)
&& !TYPE_CONTAINS_TEMPLATE_P (new_field_type)
&& TYPE_ADA_SIZE (new_field_type))
@@ -6529,7 +6527,7 @@ maybe_pad_type (tree type, tree size, unsigned int align,
between them and it might be hard to overcome afterwards, including
at the RTL level when the stand-alone object is accessed as a whole. */
if (align != 0
- && TREE_CODE (type) == RECORD_TYPE
+ && RECORD_OR_UNION_TYPE_P (type)
&& TYPE_MODE (type) == BLKmode
&& !TREE_ADDRESSABLE (type)
&& TREE_CODE (orig_size) == INTEGER_CST
@@ -6829,7 +6827,7 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
effects on the outer record type. A typical case is a field known to be
byte-aligned and not to share a byte with another field. */
if (!needs_strict_alignment
- && TREE_CODE (gnu_field_type) == RECORD_TYPE
+ && RECORD_OR_UNION_TYPE_P (gnu_field_type)
&& !TYPE_FAT_POINTER_P (gnu_field_type)
&& host_integerp (TYPE_SIZE (gnu_field_type), 1)
&& (packed == 1
@@ -6849,10 +6847,8 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
}
}
- /* If we are packing the record and the field is BLKmode, round the
- size up to a byte boundary. */
- if (packed && TYPE_MODE (gnu_field_type) == BLKmode && gnu_size)
- gnu_size = round_up (gnu_size, BITS_PER_UNIT);
+ if (Is_Atomic (gnat_field))
+ check_ok_for_atomic (gnu_field_type, gnat_field, false);
if (Present (Component_Clause (gnat_field)))
{
@@ -6942,9 +6938,6 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
gnu_pos = NULL_TREE;
}
}
-
- if (Is_Atomic (gnat_field))
- check_ok_for_atomic (gnu_field_type, gnat_field, false);
}
/* If the record has rep clauses and this is the tag field, make a rep
@@ -6957,7 +6950,14 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
}
else
- gnu_pos = NULL_TREE;
+ {
+ gnu_pos = NULL_TREE;
+
+ /* If we are packing the record and the field is BLKmode, round the
+ size up to a byte boundary. */
+ if (packed && TYPE_MODE (gnu_field_type) == BLKmode && gnu_size)
+ gnu_size = round_up (gnu_size, BITS_PER_UNIT);
+ }
/* We need to make the size the maximum for the type if it is
self-referential and an unconstrained type. In that case, we can't
@@ -7041,9 +7041,7 @@ is_variable_size (tree type)
&& !TREE_CONSTANT (DECL_SIZE (TYPE_FIELDS (type))))
return true;
- if (TREE_CODE (type) != RECORD_TYPE
- && TREE_CODE (type) != UNION_TYPE
- && TREE_CODE (type) != QUAL_UNION_TYPE)
+ if (!RECORD_OR_UNION_TYPE_P (type))
return false;
for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
@@ -8084,9 +8082,7 @@ set_rm_size (Uint uint_size, tree gnu_type, Entity_Id gnat_entity)
SET_TYPE_RM_SIZE (gnu_type, size);
/* ...or the Ada size for record and union types. */
- else if ((TREE_CODE (gnu_type) == RECORD_TYPE
- || TREE_CODE (gnu_type) == UNION_TYPE
- || TREE_CODE (gnu_type) == QUAL_UNION_TYPE)
+ else if (RECORD_OR_UNION_TYPE_P (gnu_type)
&& !TYPE_FAT_POINTER_P (gnu_type))
SET_TYPE_ADA_SIZE (gnu_type, size);
}
@@ -8938,10 +8934,8 @@ rm_size (tree gnu_type)
rm_size (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (gnu_type)))),
DECL_SIZE (TYPE_FIELDS (gnu_type)));
- /* For record types, we store the size explicitly. */
- if ((TREE_CODE (gnu_type) == RECORD_TYPE
- || TREE_CODE (gnu_type) == UNION_TYPE
- || TREE_CODE (gnu_type) == QUAL_UNION_TYPE)
+ /* For record or union types, we store the size explicitly. */
+ if (RECORD_OR_UNION_TYPE_P (gnu_type)
&& !TYPE_FAT_POINTER_P (gnu_type)
&& TYPE_ADA_SIZE (gnu_type))
return TYPE_ADA_SIZE (gnu_type);
@@ -8972,7 +8966,7 @@ create_concat_name (Entity_Id gnat_entity, const char *suffix)
if (suffix)
{
- String_Template temp = {1, strlen (suffix)};
+ String_Template temp = {1, (int) strlen (suffix)};
Fat_Pointer fp = {suffix, &temp};
Get_External_Name_With_Suffix (gnat_entity, fp);
}
diff --git a/gcc/ada/gcc-interface/gigi.h b/gcc/ada/gcc-interface/gigi.h
index f7f9b09272e..143926160ac 100644
--- a/gcc/ada/gcc-interface/gigi.h
+++ b/gcc/ada/gcc-interface/gigi.h
@@ -492,6 +492,10 @@ extern bool fntype_same_flags_p (const_tree, tree, bool, bool, bool);
not permitted by the language being compiled. */
extern tree convert (tree type, tree expr);
+/* Create an expression whose value is that of EXPR converted to the common
+ index type, which is sizetype. */
+extern tree convert_to_index_type (tree expr);
+
/* Routines created solely for the tree translator's sake. Their prototypes
can be changed as desired. */
@@ -916,6 +920,11 @@ extern tree gnat_protect_expr (tree exp);
through something we don't know how to stabilize. */
extern tree gnat_stabilize_reference (tree ref, bool force, bool *success);
+/* If EXPR is an expression that is invariant in the current function, in the
+ sense that it can be evaluated anywhere in the function and any number of
+ times, return EXPR or an equivalent expression. Otherwise return NULL. */
+extern tree gnat_invariant_expr (tree expr);
+
/* Implementation of the builtin_function langhook. */
extern tree gnat_builtin_function (tree decl);
diff --git a/gcc/ada/gcc-interface/lang-specs.h b/gcc/ada/gcc-interface/lang-specs.h
index ff3de85b986..9657a6e5767 100644
--- a/gcc/ada/gcc-interface/lang-specs.h
+++ b/gcc/ada/gcc-interface/lang-specs.h
@@ -40,7 +40,7 @@
%{coverage:-fprofile-arcs -ftest-coverage} "
"%{gnatea:-gnatez} %{g*&m*} "
#if defined(TARGET_VXWORKS_RTP)
- "%{fRTS=rtp:-mrtp} "
+ "%{fRTS=rtp:-mrtp} %{fRTS=rtp-smp:-mrtp} %{fRTS=ravenscar-cert-rtp:-mrtp}"
#endif
"%1 %{!S:%{o*:%w%*-gnatO}} \
%i %{S:%W{o*}%{!o*:-o %b.s}} \
diff --git a/gcc/ada/gcc-interface/lang.opt b/gcc/ada/gcc-interface/lang.opt
index fd79c300112..48392352ebd 100644
--- a/gcc/ada/gcc-interface/lang.opt
+++ b/gcc/ada/gcc-interface/lang.opt
@@ -48,66 +48,35 @@ Ada AdaWhy Alias(nostdlib)
I
Ada AdaWhy Joined Separate
-; Documented for C
+-I <dir>. Add <dir> to the end of the main source path
Wall
Ada AdaWhy
-; Documented for C
-
-Wmissing-prototypes
-Ada AdaWhy
-; Documented for C
-
-Wstrict-prototypes
-Ada AdaWhy
-; Documented for C
-
-Wwrite-strings
-Ada AdaWhy
-; Documented for C
-
-Wlong-long
-Ada AdaWhy
-; Documented for C
-
-Wvariadic-macros
-Ada AdaWhy
-; Documented for C
-
-Wold-style-definition
-Ada AdaWhy
-; Documented for C
-
-Wmissing-format-attribute
-Ada AdaWhy
-; Documented for C
-
-Woverlength-strings
-Ada AdaWhy
-; Documented for C
+Enable most warning messages
k8
Driver
+Synonym of -gnatk8
nostdinc
Ada AdaWhy RejectNegative
-; Don't look for source files
+Do not look for source files in standard path
nostdlib
Ada AdaWhy
-; Don't look for object files
+Do not look for object files in standard path
fRTS=
Ada AdaWhy Joined RejectNegative
-; Selects the runtime
+Select the runtime
gant
Ada AdaWhy Joined Undocumented
-; Catches typos
+Catch typos
gnatO
Ada AdaWhy Separate
-; Sets name of output ALI file (internal switch)
+Set name of output ALI file (internal switch)
gnat
Ada AdaWhy Joined
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index f651af5afe3..4b2fba0c191 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -124,17 +124,6 @@ gnat_handle_option (size_t scode, const char *arg ATTRIBUTE_UNUSED, int value,
warn_maybe_uninitialized = value;
break;
- case OPT_Wmissing_prototypes:
- case OPT_Wstrict_prototypes:
- case OPT_Wwrite_strings:
- case OPT_Wlong_long:
- case OPT_Wvariadic_macros:
- case OPT_Wold_style_definition:
- case OPT_Wmissing_format_attribute:
- case OPT_Woverlength_strings:
- /* These are used in the GCC Makefile. */
- break;
-
case OPT_gant:
warning (0, "%<-gnat%> misspelled as %<-gant%>");
@@ -394,8 +383,12 @@ gnat_print_decl (FILE *file, tree node, int indent)
break;
case VAR_DECL:
- print_node (file, "renamed object", DECL_RENAMED_OBJECT (node),
- indent + 4);
+ if (DECL_LOOP_PARM_P (node))
+ print_node (file, "induction var", DECL_INDUCTION_VAR (node),
+ indent + 4);
+ else
+ print_node (file, "renamed object", DECL_RENAMED_OBJECT (node),
+ indent + 4);
break;
default:
@@ -563,9 +556,8 @@ gnat_type_max_size (const_tree gnu_type)
/* If we don't have a constant, see what we can get from TYPE_ADA_SIZE,
which should stay untouched. */
if (!host_integerp (max_unitsize, 1)
- && (TREE_CODE (gnu_type) == RECORD_TYPE
- || TREE_CODE (gnu_type) == UNION_TYPE
- || TREE_CODE (gnu_type) == QUAL_UNION_TYPE)
+ && RECORD_OR_UNION_TYPE_P (gnu_type)
+ && !TYPE_FAT_POINTER_P (gnu_type)
&& TYPE_ADA_SIZE (gnu_type))
{
tree max_adasize = max_size (TYPE_ADA_SIZE (gnu_type), true);
diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c
index 858810ae4e8..1f43f4dcc94 100644
--- a/gcc/ada/gcc-interface/trans.c
+++ b/gcc/ada/gcc-interface/trans.c
@@ -189,8 +189,33 @@ static GTY(()) VEC(tree,gc) *gnu_return_label_stack;
parameters. See processing for N_Subprogram_Body. */
static GTY(()) VEC(tree,gc) *gnu_return_var_stack;
-/* Stack of LOOP_STMT nodes. */
-static GTY(()) VEC(tree,gc) *gnu_loop_label_stack;
+/* Structure used to record information for a range check. */
+struct GTY(()) range_check_info_d {
+ tree low_bound;
+ tree high_bound;
+ tree type;
+ tree invariant_cond;
+};
+
+typedef struct range_check_info_d *range_check_info;
+
+DEF_VEC_P(range_check_info);
+DEF_VEC_ALLOC_P(range_check_info,gc);
+
+/* Structure used to record information for a loop. */
+struct GTY(()) loop_info_d {
+ tree label;
+ tree loop_var;
+ VEC(range_check_info,gc) *checks;
+};
+
+typedef struct loop_info_d *loop_info;
+
+DEF_VEC_P(loop_info);
+DEF_VEC_ALLOC_P(loop_info,gc);
+
+/* Stack of loop_info structures associated with LOOP_STMT nodes. */
+static GTY(()) VEC(loop_info,gc) *gnu_loop_stack;
/* The stacks for N_{Push,Pop}_*_Label. */
static GTY(()) VEC(tree,gc) *gnu_constraint_error_label_stack;
@@ -289,7 +314,7 @@ gigi (Node_Id gnat_root, int max_gnat_node, int number_name ATTRIBUTE_UNUSED,
(Get_Name_String (file_info_ptr[i].File_Name))));
/* We rely on the order isomorphism between files and line maps. */
- gcc_assert ((int) line_table->used == i);
+ gcc_assert ((int) LINEMAPS_ORDINARY_USED (line_table) == i);
/* We create the line map for a source file at once, with a fixed number
of columns chosen to avoid jumping over the next power of 2. */
@@ -1008,6 +1033,9 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
gnu_result = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_result);
if (TREE_CODE (gnu_result) == INDIRECT_REF)
TREE_THIS_NOTRAP (gnu_result) = 1;
+
+ if (read_only)
+ TREE_READONLY (gnu_result) = 1;
}
/* If it's a PARM_DECL to foreign convention subprogram, convert it. */
@@ -1024,6 +1052,7 @@ Identifier_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p)
we can reference the renamed object directly, since the renamed
expression has been protected against multiple evaluations. */
if (TREE_CODE (gnu_result) == VAR_DECL
+ && !DECL_LOOP_PARM_P (gnu_result)
&& DECL_RENAMED_OBJECT (gnu_result)
&& (!DECL_RENAMING_GLOBAL_P (gnu_result) || global_bindings_p ()))
gnu_result = DECL_RENAMED_OBJECT (gnu_result);
@@ -1335,10 +1364,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
don't try to build a trampoline. */
if (attribute == Attr_Code_Address)
{
- for (gnu_expr = gnu_result;
- CONVERT_EXPR_P (gnu_expr);
- gnu_expr = TREE_OPERAND (gnu_expr, 0))
- TREE_CONSTANT (gnu_expr) = 1;
+ gnu_expr = remove_conversions (gnu_result, false);
if (TREE_CODE (gnu_expr) == ADDR_EXPR)
TREE_NO_TRAMPOLINE (gnu_expr) = TREE_CONSTANT (gnu_expr) = 1;
@@ -1349,10 +1375,7 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute)
a useful warning with -Wtrampolines. */
else if (TREE_CODE (TREE_TYPE (gnu_prefix)) == FUNCTION_TYPE)
{
- for (gnu_expr = gnu_result;
- CONVERT_EXPR_P (gnu_expr);
- gnu_expr = TREE_OPERAND (gnu_expr, 0))
- ;
+ gnu_expr = remove_conversions (gnu_result, false);
if (TREE_CODE (gnu_expr) == ADDR_EXPR
&& decl_function_context (TREE_OPERAND (gnu_expr, 0)))
@@ -2114,6 +2137,43 @@ Case_Statement_to_gnu (Node_Id gnat_node)
return gnu_result;
}
+/* Find out whether VAR is an iteration variable of an enclosing loop in the
+ current function. If so, push a range_check_info structure onto the stack
+ of this enclosing loop and return it. Otherwise, return NULL. */
+
+static struct range_check_info_d *
+push_range_check_info (tree var)
+{
+ struct loop_info_d *iter = NULL;
+ unsigned int i;
+
+ if (VEC_empty (loop_info, gnu_loop_stack))
+ return NULL;
+
+ var = remove_conversions (var, false);
+
+ if (TREE_CODE (var) != VAR_DECL)
+ return NULL;
+
+ if (decl_function_context (var) != current_function_decl)
+ return NULL;
+
+ for (i = VEC_length (loop_info, gnu_loop_stack) - 1;
+ VEC_iterate (loop_info, gnu_loop_stack, i, iter);
+ i--)
+ if (var == iter->loop_var)
+ break;
+
+ if (iter)
+ {
+ struct range_check_info_d *rci = ggc_alloc_range_check_info_d ();
+ VEC_safe_push (range_check_info, gc, iter->checks, rci);
+ return rci;
+ }
+
+ return NULL;
+}
+
/* Return true if VAL (of type TYPE) can equal the minimum value if MAX is
false, or the maximum value if MAX is true, of TYPE. */
@@ -2181,10 +2241,15 @@ static tree
Loop_Statement_to_gnu (Node_Id gnat_node)
{
const Node_Id gnat_iter_scheme = Iteration_Scheme (gnat_node);
+ struct loop_info_d *gnu_loop_info = ggc_alloc_cleared_loop_info_d ();
tree gnu_loop_stmt = build4 (LOOP_STMT, void_type_node, NULL_TREE,
NULL_TREE, NULL_TREE, NULL_TREE);
tree gnu_loop_label = create_artificial_label (input_location);
- tree gnu_cond_expr = NULL_TREE, gnu_result;
+ tree gnu_cond_expr = NULL_TREE, gnu_low = NULL_TREE, gnu_high = NULL_TREE;
+ tree gnu_result;
+
+ /* Push the loop_info structure associated with the LOOP_STMT. */
+ VEC_safe_push (loop_info, gc, gnu_loop_stack, gnu_loop_info);
/* Set location information for statement and end label. */
set_expr_location_from_node (gnu_loop_stmt, gnat_node);
@@ -2192,9 +2257,8 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
&DECL_SOURCE_LOCATION (gnu_loop_label));
LOOP_STMT_LABEL (gnu_loop_stmt) = gnu_loop_label;
- /* Save the end label of this LOOP_STMT in a stack so that a corresponding
- N_Exit_Statement can find it. */
- VEC_safe_push (tree, gc, gnu_loop_label_stack, gnu_loop_label);
+ /* Save the label so that a corresponding N_Exit_Statement can find it. */
+ gnu_loop_info->label = gnu_loop_label;
/* Set the condition under which the loop must keep going.
For the case "LOOP .... END LOOP;" the condition is always true. */
@@ -2214,14 +2278,15 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
Entity_Id gnat_loop_var = Defining_Entity (gnat_loop_spec);
Entity_Id gnat_type = Etype (gnat_loop_var);
tree gnu_type = get_unpadded_type (gnat_type);
- tree gnu_low = TYPE_MIN_VALUE (gnu_type);
- tree gnu_high = TYPE_MAX_VALUE (gnu_type);
tree gnu_base_type = get_base_type (gnu_type);
tree gnu_one_node = convert (gnu_base_type, integer_one_node);
tree gnu_loop_var, gnu_loop_iv, gnu_first, gnu_last, gnu_stmt;
enum tree_code update_code, test_code, shift_code;
bool reverse = Reverse_Present (gnat_loop_spec), use_iv = false;
+ gnu_low = TYPE_MIN_VALUE (gnu_type);
+ gnu_high = TYPE_MAX_VALUE (gnu_type);
+
/* We must disable modulo reduction for the iteration variable, if any,
in order for the loop comparison to be effective. */
if (reverse)
@@ -2296,17 +2361,20 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
;
/* Otherwise, use the do-while form with the help of a special
- induction variable in the (unsigned version of) the base
- type, in order to have wrap-around arithmetics for it. */
+ induction variable in the unsigned version of the base type
+ or the unsigned version of the size type, whichever is the
+ largest, in order to have wrap-around arithmetics for it. */
else
{
- if (!TYPE_UNSIGNED (gnu_base_type))
- {
- gnu_base_type = gnat_unsigned_type (gnu_base_type);
- gnu_first = convert (gnu_base_type, gnu_first);
- gnu_last = convert (gnu_base_type, gnu_last);
- gnu_one_node = convert (gnu_base_type, integer_one_node);
- }
+ if (TYPE_PRECISION (gnu_base_type)
+ > TYPE_PRECISION (size_type_node))
+ gnu_base_type = gnat_unsigned_type (gnu_base_type);
+ else
+ gnu_base_type = size_type_node;
+
+ gnu_first = convert (gnu_base_type, gnu_first);
+ gnu_last = convert (gnu_base_type, gnu_last);
+ gnu_one_node = convert (gnu_base_type, integer_one_node);
use_iv = true;
}
@@ -2379,6 +2447,12 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
gnu_loop_var = gnat_to_gnu_entity (gnat_loop_var, gnu_first, 1);
if (DECL_BY_REF_P (gnu_loop_var))
gnu_loop_var = build_unary_op (INDIRECT_REF, NULL_TREE, gnu_loop_var);
+ else if (use_iv)
+ {
+ gcc_assert (DECL_LOOP_PARM_P (gnu_loop_var));
+ SET_DECL_INDUCTION_VAR (gnu_loop_var, gnu_loop_iv);
+ }
+ gnu_loop_info->loop_var = gnu_loop_var;
/* Do all the arithmetics in the base type. */
gnu_loop_var = convert (gnu_base_type, gnu_loop_var);
@@ -2437,6 +2511,45 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
the LOOP_STMT to it, finish it and make it the "loop". */
if (Present (gnat_iter_scheme) && No (Condition (gnat_iter_scheme)))
{
+ struct range_check_info_d *rci;
+ unsigned n_checks = VEC_length (range_check_info, gnu_loop_info->checks);
+ unsigned int i;
+
+ /* First, if we have computed a small number of invariant conditions for
+ range checks applied to the iteration variable, then initialize these
+ conditions in front of the loop. Otherwise, leave them set to True.
+
+ ??? The heuristics need to be improved, by taking into account the
+ following datapoints:
+ - loop unswitching is disabled for big loops. The cap is the
+ parameter PARAM_MAX_UNSWITCH_INSNS (50).
+ - loop unswitching can only be applied a small number of times
+ to a given loop. The cap is PARAM_MAX_UNSWITCH_LEVEL (3).
+ - the front-end quickly generates useless or redundant checks
+ that can be entirely optimized away in the end. */
+ if (1 <= n_checks && n_checks <= 4)
+ for (i = 0;
+ VEC_iterate (range_check_info, gnu_loop_info->checks, i, rci);
+ i++)
+ {
+ tree low_ok
+ = build_binary_op (GE_EXPR, boolean_type_node,
+ convert (rci->type, gnu_low),
+ rci->low_bound);
+ tree high_ok
+ = build_binary_op (LE_EXPR, boolean_type_node,
+ convert (rci->type, gnu_high),
+ rci->high_bound);
+ tree range_ok
+ = build_binary_op (TRUTH_ANDIF_EXPR, boolean_type_node,
+ low_ok, high_ok);
+
+ TREE_OPERAND (rci->invariant_cond, 0)
+ = build_unary_op (TRUTH_NOT_EXPR, boolean_type_node, range_ok);
+
+ add_stmt_with_node_force (rci->invariant_cond, gnat_node);
+ }
+
add_stmt (gnu_loop_stmt);
gnat_poplevel ();
gnu_loop_stmt = end_stmt_group ();
@@ -2453,7 +2566,7 @@ Loop_Statement_to_gnu (Node_Id gnat_node)
else
gnu_result = gnu_loop_stmt;
- VEC_pop (tree, gnu_loop_label_stack);
+ VEC_pop (loop_info, gnu_loop_stack);
return gnu_result;
}
@@ -4359,6 +4472,28 @@ Compilation_Unit_to_gnu (Node_Id gnat_node)
invalidate_global_renaming_pointers ();
}
+/* Return true if GNAT_NODE is on the LHS of an assignment or an actual
+ parameter of a call. */
+
+static bool
+lhs_or_actual_p (Node_Id gnat_node)
+{
+ Node_Id gnat_parent = Parent (gnat_node);
+ Node_Kind kind = Nkind (gnat_parent);
+
+ if (kind == N_Assignment_Statement && Name (gnat_parent) == gnat_node)
+ return true;
+
+ if ((kind == N_Procedure_Call_Statement || kind == N_Function_Call)
+ && Name (gnat_parent) != gnat_node)
+ return true;
+
+ if (kind == N_Parameter_Association)
+ return true;
+
+ return false;
+}
+
/* Return true if GNAT_NODE, an unchecked type conversion, is a no-op as far
as gigi is concerned. This is used to avoid conversions on the LHS. */
@@ -4370,11 +4505,7 @@ unchecked_conversion_nop (Node_Id gnat_node)
/* The conversion must be on the LHS of an assignment or an actual parameter
of a call. Otherwise, even if the conversion was essentially a no-op, it
could de facto ensure type consistency and this should be preserved. */
- if (!(Nkind (Parent (gnat_node)) == N_Assignment_Statement
- && Name (Parent (gnat_node)) == gnat_node)
- && !((Nkind (Parent (gnat_node)) == N_Procedure_Call_Statement
- || Nkind (Parent (gnat_node)) == N_Function_Call)
- && Name (Parent (gnat_node)) != gnat_node))
+ if (!lhs_or_actual_p (gnat_node))
return false;
from_type = Etype (Expression (gnat_node));
@@ -5588,7 +5719,7 @@ gnat_to_gnu (Node_Id gnat_node)
? gnat_to_gnu (Condition (gnat_node)) : NULL_TREE),
(Present (Name (gnat_node))
? get_gnu_tree (Entity (Name (gnat_node)))
- : VEC_last (tree, gnu_loop_label_stack)));
+ : VEC_last (loop_info, gnu_loop_stack)->label));
break;
case N_Return_Statement:
@@ -6019,7 +6150,7 @@ gnat_to_gnu (Node_Id gnat_node)
is modelled on the C front-end. */
if (!allows_reg)
{
- STRIP_NOPS (output);
+ output = remove_conversions (output, false);
if (TREE_CODE (output) == CONST_DECL
&& DECL_CONST_CORRESPONDING_VAR (output))
output = DECL_CONST_CORRESPONDING_VAR (output);
@@ -6047,7 +6178,7 @@ gnat_to_gnu (Node_Id gnat_node)
mark it addressable. */
if (!allows_reg && allows_mem)
{
- STRIP_NOPS (input);
+ input = remove_conversions (input, false);
if (TREE_CODE (input) == CONST_DECL
&& DECL_CONST_CORRESPONDING_VAR (input))
input = DECL_CONST_CORRESPONDING_VAR (input);
@@ -6174,7 +6305,11 @@ gnat_to_gnu (Node_Id gnat_node)
case N_Raise_Storage_Error:
{
const int reason = UI_To_Int (Reason (gnat_node));
- const Node_Id cond = Condition (gnat_node);
+ const Node_Id gnat_cond = Condition (gnat_node);
+ const bool with_extra_info = Exception_Extra_Info
+ && !No_Exception_Handlers_Set ()
+ && !get_exception_label (kind);
+ tree gnu_cond = NULL_TREE;
if (type_annotate_only)
{
@@ -6184,43 +6319,66 @@ gnat_to_gnu (Node_Id gnat_node)
gnu_result_type = get_unpadded_type (Etype (gnat_node));
- if (Exception_Extra_Info
- && !No_Exception_Handlers_Set ()
- && !get_exception_label (kind)
- && VOID_TYPE_P (gnu_result_type)
- && Present (cond))
- switch (reason)
- {
- case CE_Access_Check_Failed:
+ switch (reason)
+ {
+ case CE_Access_Check_Failed:
+ if (with_extra_info)
gnu_result = build_call_raise_column (reason, gnat_node);
- break;
+ break;
- case CE_Index_Check_Failed:
- case CE_Range_Check_Failed:
- case CE_Invalid_Data:
- if (Nkind (cond) == N_Op_Not
- && Nkind (Right_Opnd (cond)) == N_In
- && Nkind (Right_Opnd (Right_Opnd (cond))) == N_Range)
- {
- Node_Id op = Right_Opnd (cond); /* N_In node */
- Node_Id index = Left_Opnd (op);
- Node_Id range = Right_Opnd (op);
- Node_Id type = Etype (index);
- if (Is_Type (type)
- && Known_Esize (type)
- && UI_To_Int (Esize (type)) <= 32)
- gnu_result
- = build_call_raise_range (reason, gnat_node,
- gnat_to_gnu (index),
- gnat_to_gnu
- (Low_Bound (range)),
- gnat_to_gnu
- (High_Bound (range)));
- }
- break;
+ case CE_Index_Check_Failed:
+ case CE_Range_Check_Failed:
+ case CE_Invalid_Data:
+ if (Present (gnat_cond)
+ && Nkind (gnat_cond) == N_Op_Not
+ && Nkind (Right_Opnd (gnat_cond)) == N_In
+ && Nkind (Right_Opnd (Right_Opnd (gnat_cond))) == N_Range)
+ {
+ Node_Id gnat_index = Left_Opnd (Right_Opnd (gnat_cond));
+ Node_Id gnat_type = Etype (gnat_index);
+ Node_Id gnat_range = Right_Opnd (Right_Opnd (gnat_cond));
+ tree gnu_index = gnat_to_gnu (gnat_index);
+ tree gnu_low_bound = gnat_to_gnu (Low_Bound (gnat_range));
+ tree gnu_high_bound = gnat_to_gnu (High_Bound (gnat_range));
+ struct range_check_info_d *rci;
+
+ if (with_extra_info
+ && Known_Esize (gnat_type)
+ && UI_To_Int (Esize (gnat_type)) <= 32)
+ gnu_result
+ = build_call_raise_range (reason, gnat_node, gnu_index,
+ gnu_low_bound, gnu_high_bound);
+
+ /* If loop unswitching is enabled, we try to compute invariant
+ conditions for checks applied to iteration variables, i.e.
+ conditions that are both independent of the variable and
+ necessary in order for the check to fail in the course of
+ some iteration, and prepend them to the original condition
+ of the checks. This will make it possible later for the
+ loop unswitching pass to replace the loop with two loops,
+ one of which has the checks eliminated and the other has
+ the original checks reinstated, and a run time selection.
+ The former loop will be suitable for vectorization. */
+ if (flag_unswitch_loops
+ && (gnu_low_bound = gnat_invariant_expr (gnu_low_bound))
+ && (gnu_high_bound = gnat_invariant_expr (gnu_high_bound))
+ && (rci = push_range_check_info (gnu_index)))
+ {
+ rci->low_bound = gnu_low_bound;
+ rci->high_bound = gnu_high_bound;
+ rci->type = gnat_to_gnu_type (gnat_type);
+ rci->invariant_cond = build1 (SAVE_EXPR, boolean_type_node,
+ boolean_true_node);
+ gnu_cond = build_binary_op (TRUTH_ANDIF_EXPR,
+ boolean_type_node,
+ rci->invariant_cond,
+ gnat_to_gnu (gnat_cond));
+ }
+ }
+ break;
- default:
- break;
+ default:
+ break;
}
if (gnu_result == error_mark_node)
@@ -6232,10 +6390,14 @@ gnat_to_gnu (Node_Id gnat_node)
the code for the call. Handle a condition, if there is one. */
if (VOID_TYPE_P (gnu_result_type))
{
- if (Present (cond))
- gnu_result
- = build3 (COND_EXPR, void_type_node, gnat_to_gnu (cond),
- gnu_result, alloc_stmt_list ());
+ if (Present (gnat_cond))
+ {
+ if (!gnu_cond)
+ gnu_cond = gnat_to_gnu (gnat_cond);
+ gnu_result
+ = build3 (COND_EXPR, void_type_node, gnu_cond, gnu_result,
+ alloc_stmt_list ());
+ }
}
else
gnu_result = build1 (NULL_EXPR, gnu_result_type, gnu_result);
@@ -6384,13 +6546,13 @@ gnat_to_gnu (Node_Id gnat_node)
/* Now convert the result to the result type, unless we are in one of the
following cases:
- 1. If this is the Name of an assignment statement or a parameter of
- a procedure call, return the result almost unmodified since the
- RHS will have to be converted to our type in that case, unless
- the result type has a simpler size. Likewise if there is just
- a no-op unchecked conversion in-between. Similarly, don't convert
- integral types that are the operands of an unchecked conversion
- since we need to ignore those conversions (for 'Valid).
+ 1. If this is the LHS of an assignment or an actual parameter of a
+ call, return the result almost unmodified since the RHS will have
+ to be converted to our type in that case, unless the result type
+ has a simpler size. Likewise if there is just a no-op unchecked
+ conversion in-between. Similarly, don't convert integral types
+ that are the operands of an unchecked conversion since we need
+ to ignore those conversions (for 'Valid).
2. If we have a label (which doesn't have any well-defined type), a
field or an error, return the result almost unmodified. Similarly,
@@ -6405,13 +6567,9 @@ gnat_to_gnu (Node_Id gnat_node)
4. Finally, if the type of the result is already correct. */
if (Present (Parent (gnat_node))
- && ((Nkind (Parent (gnat_node)) == N_Assignment_Statement
- && Name (Parent (gnat_node)) == gnat_node)
+ && (lhs_or_actual_p (gnat_node)
|| (Nkind (Parent (gnat_node)) == N_Unchecked_Type_Conversion
&& unchecked_conversion_nop (Parent (gnat_node)))
- || (Nkind (Parent (gnat_node)) == N_Procedure_Call_Statement
- && Name (Parent (gnat_node)) != gnat_node)
- || Nkind (Parent (gnat_node)) == N_Parameter_Association
|| (Nkind (Parent (gnat_node)) == N_Unchecked_Type_Conversion
&& !AGGREGATE_TYPE_P (gnu_result_type)
&& !AGGREGATE_TYPE_P (TREE_TYPE (gnu_result))))
@@ -6596,10 +6754,8 @@ add_decl_expr (tree gnu_decl, Entity_Id gnat_entity)
}
/* In any case, we have to deal with our own TYPE_ADA_SIZE field. */
else if (TREE_CODE (gnu_decl) == TYPE_DECL
- && ((TREE_CODE (type) == RECORD_TYPE
- && !TYPE_FAT_POINTER_P (type))
- || TREE_CODE (type) == UNION_TYPE
- || TREE_CODE (type) == QUAL_UNION_TYPE))
+ && RECORD_OR_UNION_TYPE_P (type)
+ && !TYPE_FAT_POINTER_P (type))
MARK_VISITED (TYPE_ADA_SIZE (type));
}
else if (!DECL_EXTERNAL (gnu_decl))
@@ -8247,12 +8403,14 @@ Sloc_to_locus (Source_Ptr Sloc, location_t *locus)
Source_File_Index file = Get_Source_File_Index (Sloc);
Logical_Line_Number line = Get_Logical_Line_Number (Sloc);
Column_Number column = Get_Column_Number (Sloc);
- struct line_map *map = &line_table->maps[file - 1];
+ struct line_map *map = LINEMAPS_ORDINARY_MAP_AT (line_table, file - 1);
+
+ /* We can have zero if pragma Source_Reference is in effect. */
+ if (line < 1)
+ line = 1;
- /* Translate the location according to the line-map.h formula. */
- *locus = map->start_location
- + ((line - map->to_line) << map->column_bits)
- + (column & ((1 << map->column_bits) - 1));
+ /* Translate the location. */
+ *locus = linemap_position_for_line_and_column (map, line, column);
}
ref_filename
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 7c7e7c6c499..73657528a8a 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -726,9 +726,7 @@ finish_record_type (tree record_type, tree field_list, int rep_level,
tree this_size = DECL_SIZE (field);
tree this_ada_size;
- if ((TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE
- || TREE_CODE (type) == QUAL_UNION_TYPE)
+ if (RECORD_OR_UNION_TYPE_P (type)
&& !TYPE_FAT_POINTER_P (type)
&& !TYPE_CONTAINS_TEMPLATE_P (type)
&& TYPE_ADA_SIZE (type))
@@ -1147,11 +1145,11 @@ compute_related_constant (tree op0, tree op1)
static tree
split_plus (tree in, tree *pvar)
{
- /* Strip NOPS in order to ease the tree traversal and maximize the
- potential for constant or plus/minus discovery. We need to be careful
+ /* Strip conversions in order to ease the tree traversal and maximize the
+ potential for constant or plus/minus discovery. We need to be careful
to always return and set *pvar to bitsizetype trees, but it's worth
the effort. */
- STRIP_NOPS (in);
+ in = remove_conversions (in, false);
*pvar = convert (bitsizetype, in);
@@ -1771,7 +1769,7 @@ process_attributes (tree decl, struct attrib *attr_list)
void
record_global_renaming_pointer (tree decl)
{
- gcc_assert (DECL_RENAMED_OBJECT (decl));
+ gcc_assert (!DECL_LOOP_PARM_P (decl) && DECL_RENAMED_OBJECT (decl));
VEC_safe_push (tree, gc, global_renaming_pointers, decl);
}
@@ -2288,7 +2286,9 @@ max_size (tree exp, bool max_p)
switch (TREE_CODE_LENGTH (code))
{
case 1:
- if (code == NON_LVALUE_EXPR)
+ if (code == SAVE_EXPR)
+ return exp;
+ else if (code == NON_LVALUE_EXPR)
return max_size (TREE_OPERAND (exp, 0), max_p);
else
return
@@ -2330,9 +2330,7 @@ max_size (tree exp, bool max_p)
}
case 3:
- if (code == SAVE_EXPR)
- return exp;
- else if (code == COND_EXPR)
+ if (code == COND_EXPR)
return fold_build2 (max_p ? MAX_EXPR : MIN_EXPR, type,
max_size (TREE_OPERAND (exp, 1), max_p),
max_size (TREE_OPERAND (exp, 2), max_p));
@@ -4247,6 +4245,92 @@ convert (tree type, tree expr)
gcc_unreachable ();
}
}
+
+/* Create an expression whose value is that of EXPR converted to the common
+ index type, which is sizetype. EXPR is supposed to be in the base type
+ of the GNAT index type. Calling it is equivalent to doing
+
+ convert (sizetype, expr)
+
+ but we try to distribute the type conversion with the knowledge that EXPR
+ cannot overflow in its type. This is a best-effort approach and we fall
+ back to the above expression as soon as difficulties are encountered.
+
+ This is necessary to overcome issues that arise when the GNAT base index
+ type and the GCC common index type (sizetype) don't have the same size,
+ which is quite frequent on 64-bit architectures. In this case, and if
+ the GNAT base index type is signed but the iteration type of the loop has
+ been forced to unsigned, the loop scalar evolution engine cannot compute
+ a simple evolution for the general induction variables associated with the
+ array indices, because it will preserve the wrap-around semantics in the
+ unsigned type of their "inner" part. As a result, many loop optimizations
+ are blocked.
+
+ The solution is to use a special (basic) induction variable that is at
+ least as large as sizetype, and to express the aforementioned general
+ induction variables in terms of this induction variable, eliminating
+ the problematic intermediate truncation to the GNAT base index type.
+ This is possible as long as the original expression doesn't overflow
+ and if the middle-end hasn't introduced artificial overflows in the
+ course of the various simplification it can make to the expression. */
+
+tree
+convert_to_index_type (tree expr)
+{
+ enum tree_code code = TREE_CODE (expr);
+ tree type = TREE_TYPE (expr);
+
+ /* If the type is unsigned, overflow is allowed so we cannot be sure that
+ EXPR doesn't overflow. Keep it simple if optimization is disabled. */
+ if (TYPE_UNSIGNED (type) || !optimize)
+ return convert (sizetype, expr);
+
+ switch (code)
+ {
+ case VAR_DECL:
+ /* The main effect of the function: replace a loop parameter with its
+ associated special induction variable. */
+ if (DECL_LOOP_PARM_P (expr) && DECL_INDUCTION_VAR (expr))
+ expr = DECL_INDUCTION_VAR (expr);
+ break;
+
+ CASE_CONVERT:
+ {
+ tree otype = TREE_TYPE (TREE_OPERAND (expr, 0));
+ /* Bail out as soon as we suspect some sort of type frobbing. */
+ if (TYPE_PRECISION (type) != TYPE_PRECISION (otype)
+ || TYPE_UNSIGNED (type) != TYPE_UNSIGNED (otype))
+ break;
+ }
+
+ /* ... fall through ... */
+
+ case NON_LVALUE_EXPR:
+ return fold_build1 (code, sizetype,
+ convert_to_index_type (TREE_OPERAND (expr, 0)));
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ return fold_build2 (code, sizetype,
+ convert_to_index_type (TREE_OPERAND (expr, 0)),
+ convert_to_index_type (TREE_OPERAND (expr, 1)));
+
+ case COMPOUND_EXPR:
+ return fold_build2 (code, sizetype, TREE_OPERAND (expr, 0),
+ convert_to_index_type (TREE_OPERAND (expr, 1)));
+
+ case COND_EXPR:
+ return fold_build3 (code, sizetype, TREE_OPERAND (expr, 0),
+ convert_to_index_type (TREE_OPERAND (expr, 1)),
+ convert_to_index_type (TREE_OPERAND (expr, 2)));
+
+ default:
+ break;
+ }
+
+ return convert (sizetype, expr);
+}
/* Remove all conversions that are done in EXP. This includes converting
from a padded type or to a justified modular type. If TRUE_ADDRESS
@@ -4273,8 +4357,9 @@ remove_conversions (tree exp, bool true_address)
return remove_conversions (TREE_OPERAND (exp, 0), true_address);
break;
- case VIEW_CONVERT_EXPR: case NON_LVALUE_EXPR:
CASE_CONVERT:
+ case VIEW_CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
return remove_conversions (TREE_OPERAND (exp, 0), true_address);
default:
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index cf290a397b1..4075a27014c 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -798,7 +798,7 @@ build_binary_op (enum tree_code op_code, tree result_type,
/* Then convert the right operand to its base type. This will prevent
unneeded sign conversions when sizetype is wider than integer. */
right_operand = convert (right_base_type, right_operand);
- right_operand = convert (sizetype, right_operand);
+ right_operand = convert_to_index_type (right_operand);
modulus = NULL_TREE;
break;
@@ -1277,13 +1277,8 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
case INDIRECT_REF:
{
- bool can_never_be_null;
- tree t = operand;
-
- while (CONVERT_EXPR_P (t) || TREE_CODE (t) == VIEW_CONVERT_EXPR)
- t = TREE_OPERAND (t, 0);
-
- can_never_be_null = DECL_P (t) && DECL_CAN_NEVER_BE_NULL_P (t);
+ tree t = remove_conversions (operand, false);
+ bool can_never_be_null = DECL_P (t) && DECL_CAN_NEVER_BE_NULL_P (t);
/* If TYPE is a thin pointer, first convert to the fat pointer. */
if (TYPE_IS_THIN_POINTER_P (type)
@@ -1753,9 +1748,7 @@ build_simple_component_ref (tree record_variable, tree component,
tree record_type = TYPE_MAIN_VARIANT (TREE_TYPE (record_variable));
tree ref, inner_variable;
- gcc_assert ((TREE_CODE (record_type) == RECORD_TYPE
- || TREE_CODE (record_type) == UNION_TYPE
- || TREE_CODE (record_type) == QUAL_UNION_TYPE)
+ gcc_assert (RECORD_OR_UNION_TYPE_P (record_type)
&& COMPLETE_TYPE_P (record_type)
&& (component == NULL_TREE) != (field == NULL_TREE));
@@ -2598,3 +2591,85 @@ gnat_stabilize_reference (tree ref, bool force, bool *success)
return result;
}
+
+/* If EXPR is an expression that is invariant in the current function, in the
+ sense that it can be evaluated anywhere in the function and any number of
+ times, return EXPR or an equivalent expression. Otherwise return NULL. */
+
+tree
+gnat_invariant_expr (tree expr)
+{
+ tree type = TREE_TYPE (expr), t;
+
+ expr = remove_conversions (expr, false);
+
+ while ((TREE_CODE (expr) == CONST_DECL
+ || (TREE_CODE (expr) == VAR_DECL && TREE_READONLY (expr)))
+ && decl_function_context (expr) == current_function_decl
+ && DECL_INITIAL (expr))
+ expr = remove_conversions (DECL_INITIAL (expr), false);
+
+ if (TREE_CONSTANT (expr))
+ return fold_convert (type, expr);
+
+ t = expr;
+
+ while (true)
+ {
+ switch (TREE_CODE (t))
+ {
+ case COMPONENT_REF:
+ if (TREE_OPERAND (t, 2) != NULL_TREE)
+ return NULL_TREE;
+ break;
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ if (!TREE_CONSTANT (TREE_OPERAND (t, 1))
+ || TREE_OPERAND (t, 2) != NULL_TREE
+ || TREE_OPERAND (t, 3) != NULL_TREE)
+ return NULL_TREE;
+ break;
+
+ case BIT_FIELD_REF:
+ case VIEW_CONVERT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ break;
+
+ case INDIRECT_REF:
+ if (!TREE_READONLY (t)
+ || TREE_SIDE_EFFECTS (t)
+ || !TREE_THIS_NOTRAP (t))
+ return NULL_TREE;
+ break;
+
+ default:
+ goto object;
+ }
+
+ t = TREE_OPERAND (t, 0);
+ }
+
+object:
+ if (TREE_SIDE_EFFECTS (t))
+ return NULL_TREE;
+
+ if (TREE_CODE (t) == CONST_DECL
+ && (DECL_EXTERNAL (t)
+ || decl_function_context (t) != current_function_decl))
+ return fold_convert (type, expr);
+
+ if (!TREE_READONLY (t))
+ return NULL_TREE;
+
+ if (TREE_CODE (t) == PARM_DECL)
+ return fold_convert (type, expr);
+
+ if (TREE_CODE (t) == VAR_DECL
+ && (DECL_EXTERNAL (t)
+ || decl_function_context (t) != current_function_decl))
+ return fold_convert (type, expr);
+
+ return NULL_TREE;
+}
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 50cafb536c6..513bca20642 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -9016,6 +9016,32 @@ in a distributed environment. If this exception is active, then the generated
code is simplified by omitting the otherwise-required global registration
of exceptions when they are declared.
+@item No_Finalization
+@findex No_Finalization
+This restriction disables the language features described in chapter 7.6 of the
+Ada 2005 RM as well as all form of code generation performed by the compiler to
+support these features. The following types are no longer considered controlled
+when this restriction is in effect:
+@itemize @bullet
+@item
+@code{Ada.Finalization.Controlled}
+@item
+@code{Ada.Finalization.Limited_Controlled}
+@item
+Derivations from @code{Controlled} or @code{Limited_Controlled}
+@item
+Class-wide types
+@item
+Protected types
+@item
+Task types
+@item
+Array and record types with controlled components
+@end itemize
+The compiler no longer generates code to initialize, finalize or adjust an
+object or a nested component, either declared on the stack or on the heap. The
+deallocation of a controlled object no longer finalizes its contents.
+
@item No_Implicit_Aliasing
@findex No_Implicit_Aliasing
@@ -11925,9 +11951,7 @@ The type of the item is non-elementary (e.g.@: a record or array).
@item
There is explicit or implicit initialization required for the object.
-Note that access values are always implicitly initialized, and also
-in GNAT, certain bit-packed arrays (those having a dynamic length or
-a length greater than 64) will also be implicitly initialized to zero.
+Note that access values are always implicitly initialized.
@item
The address value is non-static. Here GNAT is more permissive than the
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 6d9138c7505..abf8093a8ed 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -192,6 +192,7 @@ AdaCore@*
* Stack Related Facilities::
* Verifying Properties Using gnatcheck::
* Creating Sample Bodies Using gnatstub::
+* Creating Unit Tests Using gnattest::
* Generating Ada Bindings for C and C++ headers::
* Other Utility Programs::
* Running and Debugging Ada Programs::
@@ -468,6 +469,22 @@ Sample Bodies Using gnatstub
* Running gnatstub::
* Switches for gnatstub::
+Creating Unit Tests Using gnattest
+
+* Running gnattest::
+* Switches for gnattest::
+* Project Attributes for gnattest::
+* Simple Example::
+* Setting Up and Tearing Down Testing Environment::
+* Regenerating Tests::
+* Default Test Behavior::
+* Testing Primitive Operations of Tagged Types::
+* Test Inheritance::
+* Tagged Types Substitutability Testing::
+* Testing with Contracts::
+* Additional Tests::
+* Current Limitations::
+
Other Utility Programs
* Using Other Utility Programs with GNAT::
@@ -814,6 +831,10 @@ a utility that checks Ada code against a set of rules.
a utility that generates empty but compilable bodies for library units.
@item
+@ref{Creating Unit Tests Using gnattest}, discusses @code{gnattest},
+a utility that generates unit testing templates for library units.
+
+@item
@ref{Generating Ada Bindings for C and C++ headers}, describes how to
generate automatically Ada bindings from C and C++ headers.
@@ -10071,9 +10092,6 @@ and some of the techniques for making your program run faster.
It then documents the @command{gnatelim} tool and unused subprogram/data
elimination feature, which can reduce the size of program executables.
-Note: to invoke @command{gnatelim} with a project file, use the @code{gnat}
-driver (see @ref{The GNAT Driver and Project Files}).
-
@ifnottex
@menu
* Performance Considerations::
@@ -10997,6 +11015,10 @@ indicate that the analysed set of sources is incomplete to make up a
partition and that some subprogram bodies are missing are not generated.
@end table
+@noindent
+Note: to invoke @command{gnatelim} with a project file, use the @code{gnat}
+driver (see @ref{The GNAT Driver and Project Files}).
+
@node Processing Precompiled Libraries
@subsection Processing Precompiled Libraries
@@ -12811,6 +12833,7 @@ the configuration file describing the corresponding naming scheme;
see the description of the @command{gnatpp}
switches below. Another possibility is to use a project file and to
call @command{gnatpp} through the @command{gnat} driver
+(see @ref{The GNAT Driver and Project Files}).
The @command{gnatpp} command has the form
@@ -13002,6 +13025,23 @@ Names are in lower case
@item ^-nM^/NAME_CASING=MIXED_CASE^
Names are in mixed case
+@cindex @option{^-ne@var{x}^/ENUM_CASING^} (@command{gnatpp})
+@item ^-neD^/ENUM_CASING=AS_DECLARED^
+Enumeration literal casing for defining occurrences are as they appear in the
+source file. Overrides ^-n^/NAME_CASING^ casing setting.
+
+@item ^-neU^/ENUM_CASING=UPPER_CASE^
+Enumeration literals are in upper case. Overrides ^-n^/NAME_CASING^ casing
+setting.
+
+@item ^-neL^/ENUM_CASING=LOWER_CASE^
+Enumeration literals are in lower case. Overrides ^-n^/NAME_CASING^ casing
+setting.
+
+@item ^-neM^/ENUM_CASING=MIXED_CASE^
+Enumeration literals are in mixed case. Overrides ^-n^/NAME_CASING^ casing
+setting.
+
@cindex @option{^-p@var{x}^/PRAGMA_CASING^} (@command{gnatpp})
@item ^-pL^/PRAGMA_CASING=LOWER_CASE^
Pragma names are lower case
@@ -13921,7 +13961,7 @@ in files with names that do not follow the GNAT file naming rules, you have to
provide the configuration file describing the corresponding naming scheme (see
the description of the @command{gnatmetric} switches below.)
Alternatively, you may use a project file and invoke @command{gnatmetric}
-through the @command{gnat} driver.
+through the @command{gnat} driver (see @ref{The GNAT Driver and Project Files}).
The @command{gnatmetric} command has the form
@@ -17486,7 +17526,7 @@ current directory)
@item @samp{@var{gcc_switches}} is a list of switches for
@command{gcc}. They will be passed on to all compiler invocations made by
-@command{gnatelim} to generate the ASIS trees. Here you can provide
+@command{gnatstub} to generate the ASIS trees. Here you can provide
@option{^-I^/INCLUDE_DIRS=^} switches to form the source search path,
use the @option{-gnatec} switch to set the configuration file,
use the @option{-gnat05} switch if sources should be compiled in
@@ -17628,6 +17668,530 @@ Verbose mode: generate version information.
@end table
@c *********************************
+@node Creating Unit Tests Using gnattest
+@chapter Creating Unit Tests Using @command{gnattest}
+@findex gnattest
+
+@noindent
+@command{gnattest} is an ASIS-based utility that creates unit tests stubs
+as well as a test driver infrastructure (harness). @command{gnattest} creates
+a stub for each visible subprogram in the packages under consideration when
+they do not exist already.
+
+In order to process source files from the project, @command{gnattest} has to
+semantically analyze these Ada sources. Therefore, test stubs can only be
+generated for legal Ada units. If a unit is dependent on some other units,
+those units should be among source files of the project or of other projects
+imported by this one.
+
+Generated stubs and harness are based on the AUnit testing framework. AUnit is
+an Ada adaptation of the xxxUnit testing frameworks similar to JUnit for Java or
+CppUnit for C++. While it is advised that gnattest users read AUnit manual, deep
+knowledge of AUnit is not necessary for using gnattest. For correct operation of
+@command{gnattest} AUnit should be installed and aunit.gpr must be on the
+project path. This happens automatically when Aunit is installed at its default
+location.
+@menu
+* Running gnattest::
+* Switches for gnattest::
+* Project Attributes for gnattest::
+* Simple Example::
+* Setting Up and Tearing Down Testing Environment::
+* Regenerating Tests::
+* Default Test Behavior::
+* Testing Primitive Operations of Tagged Types::
+* Test Inheritance::
+* Tagged Types Substitutability Testing::
+* Testing with Contracts::
+* Additional Tests::
+* Current Limitations::
+@end menu
+
+@node Running gnattest
+@section Running @command{gnattest}
+
+@noindent
+@command{gnattest} has the command-line interface of the form
+
+@smallexample
+@c $ gnattest @var{-Pprojname} @ovar{switches} @ovar{filename} @ovar{directory}
+@c Expanding @ovar macro inline (explanation in macro def comments)
+$ gnattest @var{-Pprojname} @r{[}@var{--harness-dir=dirname}@r{]} @r{[}@var{switches}@r{]} @r{[}@var{filename}@r{]} @r{[}-cargs @var{gcc_switches}@r{]}
+@end smallexample
+
+@noindent
+where
+@table @var
+
+@item -Pprojname
+specifies the project that allow locating the source files. When no [filenames]
+are provided on the command line, all project sources are used as input. This
+switch is mandatory.
+
+@item --harness-dir=dirname
+specifies directory to put harness packages and project file for the test
+driver. The harness dir should be either specified by that switch or by
+corresponding attribute in the argument project file.
+
+@item filename
+is the name of the source file that contains a library unit package declaration
+for which a test package must be created. The file name may contain the path
+information.
+
+@item @samp{@var{gcc_switches}} is a list of switches for
+@command{gcc}. They will be passed on to all compiler invocations made by
+@command{gnatstub} to generate the ASIS trees. Here you can provide
+@option{^-I^/INCLUDE_DIRS=^} switches to form the source search path,
+use the @option{-gnatec} switch to set the configuration file,
+use the @option{-gnat05} switch if sources should be compiled in
+Ada 2005 mode etc.
+
+@item switches
+is an optional sequence of switches as described in the next section
+
+@end table
+
+@command{gnattest} results can be found in two different places.
+
+@itemize @bullet
+@item automatic harness
+the harnessing code which is located in the harness-dir as specified on the
+comand line or in the project file. All this code is generated completely
+automatically and can be destroyed and regenerated at will. It is not
+recommended to modify manually this code since it might be overridden
+easily. The entry point in this harnessing code is the project file called
+@command{test_driver.gpr}. Tests can be compiled and run using a command
+such as:
+
+@smallexample
+gnatmake -P<harness-dir>/test_driver
+test_runner
+@end smallexample
+
+@item actual unit test stubs
+a test stub for each visible subprogram is created in a separate file, if it
+doesn't exist already. By default, those separate test files are located in a
+"tests" directory that is created in the directory containing the source file
+itself. if it is not appropriate to create the tests in subdirs of the source,
+option @option{--separate-root} can be used. So let say for instance that
+a source file my_unit.ads in directory src contains a visible subprogram Proc.
+Then, the corresponding unit test will be found in file
+src/tests/my_unit-tests-proc_<code>.adb. <code> is an signature encoding used to
+differentiate test names in case of overloading.
+@end itemize
+
+@node Switches for gnattest
+@section Switches for @command{gnattest}
+
+@table @option
+@c !sort!
+
+@item --harness-only
+@cindex @option{--harness-only} (@command{gnattest})
+When this option is given, @command{gnattest} creates a harness for all
+sources treating them as test packages.
+
+@item --additional-tests=@var{projname}
+@cindex @option{--additional-tests} (@command{gnattest})
+Sources described in @var{projname} are considered potential additional
+manual tests to be added to the test suite.
+
+@item -r
+@cindex @option{-r} (@command{gnattest})
+Consider recursively all sources from all projects.
+
+@item -q
+@cindex @option{-q} (@command{gnattest})
+Supresses non-critical output messages.
+
+@item -v
+@cindex @option{-v} (@command{gnattest})
+Verbose mode: generate version information.
+
+@item --liskov
+@cindex @option{--liskov} (@command{gnattest})
+Enables Liskov verification: run all tests from all parents in order
+to check substitutability.
+
+@item --stub-default=@var{val}
+@cindex @option{--stub-default} (@command{gnattest})
+Specifies the default behavior of generated stubs. @var{val} can be either
+"fail" or "pass", "fail" being the default.
+
+@item --separate-root=@var{dirname}
+@cindex @option{--separate-root} (@command{gnattest})
+Directory hierarchy of tested sources is recreated in the @var{dirname} directory,
+test packages are placed in corresponding dirs.
+
+@item --subdir=@var{dirname}
+@cindex @option{--subdir} (@command{gnattest})
+Test packages are placed in subdirectories. That's the default output mode since
+it does not require any additional input from the user. Subdirs called "tests"
+will be created by default.
+
+@end table
+
+@option{--separate_root} and @option{--subdir} switches are mutually exclusive.
+
+@node Project Attributes for gnattest
+@section Project Attributes for @command{gnattest}
+
+@noindent
+
+Most of the command line options can be also given to the tool by adding
+special attributes to the project file. Those attributes should be put in
+package gnattest. Here is the list of the attributes.
+
+@itemize @bullet
+
+@item Separate_Stub_Root
+is used to select the same output mode as with the --separate-root option.
+This attribute cannot be used togather with Stub_Subdir.
+
+@item Stub_Subdir
+is used to select the same output mode as with the --sudbir option.
+This attribute cannot be used togather with Separate_Stub_Root.
+
+@item Harness_Dir
+is used to specify the directory to place harness packages and project
+file for the test driver, otherwise specified by --harness-dir.
+
+@item Additional_Tests
+is used to specify the project file otherwise given by
+--additional-tests switch.
+
+@item Stubs_Default
+is used to specify the default behaviour of test stubs, otherwise
+specified by --stub-default option. The value for this attribute
+shoul be either "pass" or "fail"
+
+@end itemize
+
+All those attributes can be overridden from command line if needed.
+Other @command{gnattest} switches can also be passed via the project
+file as an attribute list called GNATtest_Switches.
+
+@node Simple Example
+@section Simple Example
+
+@noindent
+
+Let's take a very simple example using the first @command{gnattest} example
+located at
+
+@smallexample
+<install_prefix>/share/examples/gnattest/simple
+@end smallexample
+
+This project contains a simple package containing one subprogram. By running gnattest
+
+@smallexample
+$ gnattest --harness-dir=driver -Psimple.gpr
+@end smallexample
+
+a test driver is created in dir "driver". It can be compiled and run:
+
+@smallexample
+$ cd driver
+$ gprbuild -Ptest_driver
+$ test_runner
+@end smallexample
+
+One failed test with diagnosis "test not implemented" is reported.
+Since no special output option was specified the test package Simple.Tests
+is located in
+
+@smallexample
+<install_prefix>/share/examples/gnattest/simple/src/tests
+@end smallexample
+
+For each package containing visible subprograms, a child test package is
+generated. It contains one test routine per tested subprogram. Each
+declaration of test subprogram has a comment specifying to which tested
+subprogram it corresponds. All the test routines have separated bodies.
+The test routine locates at simple-tests-test_inc_5eaee3.adb has a single
+statement - procedure Assert. It has two arguments: the boolean expression
+which we want to check and the diagnosis message to display if the condition
+is false.
+
+That is where actual testing code should be written after a proper setup.
+An actual check can be performed by replacing the assert statement with
+
+@smallexample @c ada
+Assert (Inc (1) = 2, "wrong incrementation");
+@end smallexample
+
+After recompiling and running the test driver one successfully passed test
+is reported.
+
+@node Setting Up and Tearing Down Testing Environment
+@section Setting Up and Tearing Down Testing Environment
+
+@noindent
+
+Besides test routines themselves, each test package has an inner package
+Env_Mgmt that has two procedures: User_Set_Up and User_Tear_Down.
+User_Set_Up is called before each test routine of the package and
+User_Tear_Down is called after each test routine. Those two procedures can
+be used to perform necessary initialization and finalization,
+memory allocation etc.
+
+@node Regenerating Tests
+@section Regenerating Tests
+
+@noindent
+
+Bodies of test routines and env_mgmt packages are never overridden after they
+have been created once. As long as the name of the subprogram, full expanded Ada
+names and order of its parameters are the same, the old test routine will
+fit in it's place and no test stub will be generated for this subprogram.
+
+This can be demonstrated with the previous example. By uncommenting declaration
+and body of function Dec in simple.ads and simple.adb, running
+@command{gnattest} on the project and then running the test driver:
+
+@smallexample
+gnattest --harness-dir=driver -Psimple.gpr
+cd driver
+gprbuild -Ptest_driver
+test_runner
+@end smallexample
+
+the old test is not replaced with a stub neither lost but a new test stub is
+created for function Dec.
+
+The only way for regenerating tests stubs is t oremove the previously created
+tests.
+
+@node Default Test Behavior
+@section Default Test Behavior
+
+@noindent
+
+Generated test driver can treat all unimplemented tests in two ways:
+either count them all as failed (this is usefull to see which tests are still
+left to implement) or as passed (to sort out unimplemented ones from those
+actually failing for a reason).
+
+Test driver accepts a switch to specify this behavior: --stub-default=val,
+where val is either "pass" or "fail" (exactly as for @command{gnattest}).
+
+The default behavior of the test driver is set with the same switch
+passed to gnattest when generating the test driver.
+
+Passing it to the driver generated on the first example
+
+@smallexample
+test_runner --stub-default=pass
+@end smallexample
+
+makes both tests pass, even the unimplemented one.
+
+@node Testing Primitive Operations of Tagged Types
+@section Testing Primitive Operations of Tagged Types
+
+@noindent
+
+Creating test stubs for primitive operations of tagged types have a number
+of features. Test routines for all primitives of a given tagged type are
+placed in a separate child package named after the tagged type (so if you
+have tagged type T in package P all tests for primitives of T will be in
+P.T_Tests).
+
+By running gnattest on the second example (actual tests for this example
+are already written so no need to worry if the tool reports that 0 new stubs
+were generated).
+
+@smallexample
+cd <install_prefix>/share/examples/gnattest/tagged_rec
+gnattest --harness-dir=driver -Ptagged_rec.gpr
+@end smallexample
+
+Taking a closer look at the test type declared in the test package
+Speed1.Controller_Tests is necessary. It is declared in
+
+@smallexample
+<install_prefix>/share/examples/gnattest/tagged_rec/src/tests
+@end smallexample
+
+Test types are direct or indirect descendants of
+AUnit.Test_Fixtures.Test_Fixture type. For non-primitive tested subprograms
+there is no need for the user to care about them. However when generating
+test packages for primitive operations, there are some things the user
+should know.
+
+Type Test_Controller has component that allows to assign it all kinds of
+derivations of type Controller. And if you look at the specification of
+package Speed2.Auto_Controller, you can see, that Test_Auto_Controller
+actually derives from Test_Controller rather that AUnit type Test_Fixture.
+Thus test types repeat the hierarchy of tested types.
+
+The User_Set_Up procedure of Env_Mgmt package corresponding to a test package
+of primitive operations of type T assigns Fixture with a reference to an
+object of that exact type T. Notice however, that if the tagged type has
+discriminants, the User_Set_Up only has a commented template of setting
+up the fixture since filling the discriminant with actual value is up
+to the user.
+
+The knowledge of the structure if test types allows to have additional testing
+without additional effort. Those possibilities are described below.
+
+@node Test Inheritance
+@section Test Inheritance
+
+@noindent
+
+Since test type hierarchy mimics the hierarchy of tested types, the
+inheritance of tests take place. An example of such inheritance can be
+shown by running the test driver generated for second example. As previously
+mentioned, actual tests are already written for this example.
+
+@smallexample
+cd driver
+gprbuild -Ptest_driver
+test_runner
+@end smallexample
+
+There are 6 passed tests while there are only 5 testable subprograms. Test
+routine for function Speed has been inherited and ran against objects of the
+derived type.
+
+@node Tagged Types Substitutability Testing
+@section Tagged Types Substitutability Testing
+
+@noindent
+
+Tagged Types Substitutability Testing is a way of verifying by testing
+the Liskov substitution principle (LSP). LSP is a principle stating that if
+S is a subtype of T (in Ada, S is a derived type of tagged type T),
+then objects of type T may be replaced with objects of type S (i.e., objects
+of type S may be substituted for objects of type T), without altering any of
+the desirable properties of the program. When the properties of the program are
+expressed in the form of subprogram pre & postconditions, LSP is formulated
+as relations between the pre & post of primitive operations and the pre & post
+of theirs derived operations. The pre of a derived operation should not be
+stronger that the original pre, and the post of the derived operation should not
+be weaker than the original post. Those relations insure that verifying if a
+dyspatching call is safe can be done just with the pre & post of the root
+operation.
+
+Verifying LSP by testing consists in running all the unit tests associated with
+the primitives of a given tagged type with objects of its derived types.
+
+In the example used by the previous section there clearly have a violation of LSP.
+The overriding primitive Adjust_Speed in package Speed2 removes the
+functionality of the overridden primitive and thus doesn't respect LSP.
+Gnattest has a special option to run
+overridden parent tests against objects of the type which have overriding
+primitives.
+
+@smallexample
+gnattest --harness-dir=driver --liskov -Ptagged_rec.gpr
+cd driver
+gprbuild -Ptest_driver
+test_runner
+@end smallexample
+
+While all the tests pass by themselves, the parent test for Adjust_Speed fails
+against object of derived type.
+
+@node Testing with Contracts
+@section Testing with Contracts
+
+@noindent
+
+@command{gnattest} supports pragmas Precondition, Postcondition and Test_Case.
+Test routines are generated one per each Test_Case associated with a tested
+subprogram. Those test routines have special wrappers for tested functions
+that have composition of pre- and postcondition of the subprogram an
+"requires" and "ensures" of the Test_Case (depending on the mode pre- and post
+either count for Nominal mode or do not for Robustness mode).
+
+The third example demonstrates how it works:
+
+@smallexample
+cd <install_prefix>/share/examples/gnattest/contracts
+gnattest --harness-dir=driver -Pcontracts.gpr
+@end smallexample
+
+Putting actual checks within the range of the contract does not cause any
+error reports. For example, for the test routine which corresponds to
+test case 1
+
+@smallexample @c ada
+Assert (Sqrt (9.0) = 3.0, "wrong sqrt");
+@end smallexample
+
+and for the test routine corresponding to test case 2
+
+@smallexample @c ada
+Assert (Sqrt (-5.0) = -1.0, "wrong error indication");
+@end smallexample
+
+are acceptable:
+
+@smallexample
+cd driver
+gprbuild -Ptest_driver
+test_runner
+@end smallexample
+
+However, by by changing 9.0 to 25.0 and 3.0 to 5.0 for example you can get
+a precondition violation for test case one. Also by putting any otherwise
+correct but positive pair of numbers to the second test routine you can also
+get a precondition violation. Postconditions are checked and reported
+the same way.
+
+@node Additional Tests
+@section Additional Tests
+
+@noindent
+@command{gnattest} can add user written tests to the main suite of the test
+driver. @command{gnattest} traverses given packages and searches for test
+routines. All procedures with a single in out parameter of a type which is
+a derivation of AUnit.Test_Fixtures.Test_Fixture declared in package
+specifications are added to the suites and then are executed by test driver.
+(Set_Up and Tear_Down are filtered out).
+
+An example illustrates two ways of crating test harness for user written tests.
+Directory additional contains a AUnit based test driver written by hand.
+
+@smallexample
+<install_prefix>/share/examples/gnattest/additional_tests/
+@end smallexample
+
+To create a test driver for already written tests use --harness-only option:
+
+@smallexample
+gnattest -Padditional/harness/harness.gpr --harness-dir=harness_only \
+ --harness-only
+gnatmake -Pharness_only/test_driver.gpr
+harness_only/test_runner
+@end smallexample
+
+Additional tests can also be executed together withgenerated tests:
+
+@smallexample
+gnattest -Psimple.gpr --additional-tests=additional/harness/harness.gpr \
+ --harness-dir=mixing
+gnatmake -Pmixing/test_driver.gpr
+mixing/test_runner
+@end smallexample
+
+@node Current Limitations
+@section Current Limitations
+
+@noindent
+
+The tool currently does not support following features:
+
+@itemize @bullet
+@item generic tests for generic packages and package instantiations
+@item tests for protected operations and entries
+@item acpects Pre-, Postcondition and Test_Case
+@end itemize
+
+@c *********************************
@node Generating Ada Bindings for C and C++ headers
@chapter Generating Ada Bindings for C and C++ headers
@findex binding
@@ -20579,6 +21143,13 @@ On OpenVMS Alpha, HP Ada provides the following strongly-typed bindings:
GNAT provides implementations of these HP bindings in the @code{DECLIB}
directory, on both the Alpha and I64 OpenVMS platforms.
+The X components of DECLIB compatibility package are located in a separate
+library, called XDECGNAT, which is not linked with by default; this library
+must be explicitly linked with any application that makes use of any X facilities,
+with a command similar to
+
+@code{GNAT MAKE USE_X /LINK /LIBRARY=XDECGNAT}
+
The X/Motif bindings used to build @code{DECLIB} are whatever versions are
in the
HP Ada @file{ADA$PREDEFINED} directory with extension @file{.ADC}.
diff --git a/gcc/ada/gnatlink.adb b/gcc/ada/gnatlink.adb
index 61d3db3861f..9a1aab4c071 100644
--- a/gcc/ada/gnatlink.adb
+++ b/gcc/ada/gnatlink.adb
@@ -1614,7 +1614,9 @@ begin
-- Pass -mrtp to the linker if --RTS=rtp was passed
if Arg'Length > 8
- and then Arg (Arg'First + 6 .. Arg'First + 8) = "rtp"
+ and then
+ (Arg (Arg'First + 6 .. Arg'First + 8) = "rtp"
+ or else Arg (Arg'Last - 2 .. Arg'Last) = "rtp")
then
Linker_Options.Increment_Last;
Linker_Options.Table (Linker_Options.Last) :=
diff --git a/gcc/ada/impunit.adb b/gcc/ada/impunit.adb
index be1d05744f9..dfe176bf38d 100644
--- a/gcc/ada/impunit.adb
+++ b/gcc/ada/impunit.adb
@@ -61,7 +61,7 @@ package body Impunit is
-- The following is a giant string list containing the names of all non-
-- implementation internal files, i.e. the complete list of files for
-- internal units which a program may legitimately WITH when operating in
- -- either Ada 95 or Ada 05 mode.
+ -- either Ada 95 or Ada 2005 mode.
-- Note that this list should match the list of units documented in the
-- "GNAT Library" section of the GNAT Reference Manual. A unit listed here
diff --git a/gcc/ada/impunit.ads b/gcc/ada/impunit.ads
index e5244938ef9..be3e8d3c06a 100644
--- a/gcc/ada/impunit.ads
+++ b/gcc/ada/impunit.ads
@@ -25,8 +25,9 @@
-- This package contains data and functions used to determine if a given unit
-- is an internal unit intended only for use by the implementation and which
--- should not be directly WITH'ed by user code. It also checks for Ada 05
--- units that should only be WITH'ed in Ada 05 mode.
+-- should not be directly WITH'ed by user code. It also checks for Ada 2005
+-- units that should only be WITH'ed in Ada 2005 mode, and Ada 2012 units
+-- that should only be WITH'ed in Ada 2012 mode.
with Types; use Types;
diff --git a/gcc/ada/init.c b/gcc/ada/init.c
index 0cf32e8166f..8d2f4e1f235 100644
--- a/gcc/ada/init.c
+++ b/gcc/ada/init.c
@@ -1906,7 +1906,8 @@ __gnat_clear_exception_count (void)
/* Handle different SIGnal to exception mappings in different VxWorks
versions. */
static void
-__gnat_map_signal (int sig)
+__gnat_map_signal (int sig, void *si ATTRIBUTE_UNUSED,
+ struct sigcontext *sc ATTRIBUTE_UNUSED)
{
struct Exception_Data *exception;
const char *msg;
@@ -2001,9 +2002,7 @@ __gnat_map_signal (int sig)
propagation after the required low level adjustments. */
void
-__gnat_error_handler (int sig,
- void *si ATTRIBUTE_UNUSED,
- struct sigcontext *sc ATTRIBUTE_UNUSED)
+__gnat_error_handler (int sig, void *si, struct sigcontext *sc)
{
sigset_t mask;
@@ -2015,7 +2014,22 @@ __gnat_error_handler (int sig,
sigdelset (&mask, sig);
sigprocmask (SIG_SETMASK, &mask, NULL);
- __gnat_map_signal (sig);
+#if defined (__PPC__) && defined(_WRS_KERNEL)
+ /* On PowerPC, kernel mode, we process signals through a Call Frame Info
+ trampoline, voiding the need for myriads of fallback_frame_state
+ variants in the ZCX runtime. We have no simple way to distinguish ZCX
+ from SJLJ here, so we do this for SJLJ as well even though this is not
+ necessary. This only incurs a few extra instructions and a tiny
+ amount of extra stack usage. */
+
+ #include "sigtramp.h"
+
+ __gnat_sigtramp (sig, (void *)si, (void *)sc,
+ (sighandler_t *)&__gnat_map_signal);
+
+#else
+ __gnat_map_signal (sig, si, sc);
+#endif
}
void
@@ -2273,6 +2287,16 @@ __gnat_error_handler (int sig, siginfo_t *si, void *ucontext ATTRIBUTE_UNUSED)
{
struct Exception_Data *exception;
const char *msg;
+#if defined (__x86_64__)
+ /* Work around radar #10302855/pr50678, where the unwinders (libunwind or
+ libgcc_s depending on the system revision) and the DWARF unwind data for
+ the sigtramp have different ideas about register numbering (causing rbx
+ and rdx to be transposed).. */
+ ucontext_t *uc = (ucontext_t *)ucontext ;
+ unsigned long t = uc->uc_mcontext->__ss.__rbx;
+ uc->uc_mcontext->__ss.__rbx = uc->uc_mcontext->__ss.__rdx;
+ uc->uc_mcontext->__ss.__rdx = t;
+#endif
switch (sig)
{
diff --git a/gcc/ada/lib-xref.adb b/gcc/ada/lib-xref.adb
index 35cfdfca8a1..83a06e452f3 100644
--- a/gcc/ada/lib-xref.adb
+++ b/gcc/ada/lib-xref.adb
@@ -1910,7 +1910,9 @@ package body Lib.Xref is
Op := Ultimate_Alias (Old_E);
- -- Normal case of no alias present
+ -- Normal case of no alias present. We omit generated
+ -- primitives like tagged equality, that have no source
+ -- representation.
else
Op := Old_E;
@@ -1918,6 +1920,7 @@ package body Lib.Xref is
if Present (Op)
and then Sloc (Op) /= Standard_Location
+ and then Comes_From_Source (Op)
then
declare
Loc : constant Source_Ptr := Sloc (Op);
diff --git a/gcc/ada/link.c b/gcc/ada/link.c
index bf5d584b02b..8bcad27d86b 100644
--- a/gcc/ada/link.c
+++ b/gcc/ada/link.c
@@ -152,18 +152,6 @@ const char *__gnat_object_library_extension = ".a";
unsigned char __gnat_separate_run_path_options = 0;
const char *__gnat_default_libgcc_subdir = "lib";
-#elif defined (_AIX)
-const char *__gnat_object_file_option = "-Wl,-f,";
-const char *__gnat_run_path_option = "";
-int __gnat_link_max = 15000;
-const unsigned char __gnat_objlist_file_supported = 1;
-char __gnat_shared_libgnat_default = STATIC;
-char __gnat_shared_libgcc_default = STATIC;
-unsigned char __gnat_using_gnu_linker = 0;
-const char *__gnat_object_library_extension = ".a";
-unsigned char __gnat_separate_run_path_options = 0;
-const char *__gnat_default_libgcc_subdir = "lib";
-
#elif defined (__FreeBSD__)
const char *__gnat_object_file_option = "";
const char *__gnat_run_path_option = "-Wl,-rpath,";
@@ -204,12 +192,27 @@ const char *__gnat_default_libgcc_subdir = "lib64";
const char *__gnat_default_libgcc_subdir = "lib";
#endif
+#elif defined (_AIX)
+/* On AIX, even when with GNU ld we use native linker switches. This is
+ particularly important for '-f' as it should be interpreted by collect2. */
+
+const char *__gnat_object_file_option = "-Wl,-f,";
+const char *__gnat_run_path_option = "";
+char __gnat_shared_libgnat_default = STATIC;
+char __gnat_shared_libgcc_default = STATIC;
+int __gnat_link_max = 15000;
+const unsigned char __gnat_objlist_file_supported = 1;
+unsigned char __gnat_using_gnu_linker = 0;
+const char *__gnat_object_library_extension = ".a";
+unsigned char __gnat_separate_run_path_options = 0;
+const char *__gnat_default_libgcc_subdir = "lib";
+
#elif (HAVE_GNU_LD)
/* These are the settings for all systems that use gnu ld. GNU style response
file is supported, the shared library default is STATIC. */
-const char *__gnat_run_path_option = "";
const char *__gnat_object_file_option = "";
+const char *__gnat_run_path_option = "";
char __gnat_shared_libgnat_default = STATIC;
char __gnat_shared_libgcc_default = STATIC;
int __gnat_link_max = 8192;
diff --git a/gcc/ada/make.adb b/gcc/ada/make.adb
index bf6a21a0dad..92043487bfa 100644
--- a/gcc/ada/make.adb
+++ b/gcc/ada/make.adb
@@ -4603,7 +4603,7 @@ package body Make is
procedure Library_Phase
(Stand_Alone_Libraries : in out Boolean;
- Library_Rebuilt : in out Boolean)
+ Library_Rebuilt : in out Boolean)
is
Depth : Natural;
Current : Natural;
diff --git a/gcc/ada/mlib-prj.adb b/gcc/ada/mlib-prj.adb
index 9020705d49b..83c74b94842 100644
--- a/gcc/ada/mlib-prj.adb
+++ b/gcc/ada/mlib-prj.adb
@@ -70,9 +70,6 @@ package body MLib.Prj is
S_Dec_Ads : File_Name_Type := No_File;
-- Name_Id for "dec.ads"
- G_Trasym_Ads : File_Name_Type := No_File;
- -- Name_Id for "g-trasym.ads"
-
Arguments : String_List_Access := No_Argument;
-- Used to accumulate arguments for the invocation of gnatbind and of the
-- compiler. Also used to collect the interface ALI when copying the ALI
@@ -316,9 +313,6 @@ package body MLib.Prj is
Libdecgnat_Needed : Boolean := False;
-- On OpenVMS, set True if library needs to be linked with libdecgnat
- Gtrasymobj_Needed : Boolean := False;
- -- On OpenVMS, set rue if library needs to be linked with g-trasym.obj
-
Object_Directory_Path : constant String :=
Get_Name_String
(For_Project.Object_Directory.Display_Name);
@@ -375,8 +369,7 @@ package body MLib.Prj is
-- to link with -lgnarl (this is the case when there is a dependency
-- on s-osinte.ads). On OpenVMS, set Libdecgnat_Needed if the ALI file
-- indicates that there is a need to link with -ldecgnat (this is the
- -- case when there is a dependency on dec.ads). Set Gtrasymobj_Needed
- -- if there is a dependency on g-trasym.ads.
+ -- case when there is a dependency on dec.ads).
procedure Process (The_ALI : File_Name_Type);
-- Check if the closure of a library unit which is or should be in the
@@ -513,8 +506,7 @@ package body MLib.Prj is
if Libgnarl_Needed /= Yes
or else
(Main_Project
- and then OpenVMS_On_Target
- and then ((not Libdecgnat_Needed) or (not Gtrasymobj_Needed)))
+ and then OpenVMS_On_Target)
then
-- Scan the ALI file
@@ -548,9 +540,6 @@ package body MLib.Prj is
elsif OpenVMS_On_Target then
if ALI.Sdep.Table (Index).Sfile = S_Dec_Ads then
Libdecgnat_Needed := True;
-
- elsif ALI.Sdep.Table (Index).Sfile = G_Trasym_Ads then
- Gtrasymobj_Needed := True;
end if;
end if;
end loop;
@@ -838,12 +827,6 @@ package body MLib.Prj is
S_Dec_Ads := Name_Find;
end if;
- if G_Trasym_Ads = No_File then
- Name_Len := 0;
- Add_Str_To_Name_Buffer ("g-trasym.ads");
- G_Trasym_Ads := Name_Find;
- end if;
-
-- We work in the object directory
Change_Dir (Object_Directory_Path);
@@ -1556,8 +1539,7 @@ package body MLib.Prj is
ALIs.Append (new String'(ALI_Path));
-- Find out if for this ALI file,
- -- libgnarl or libdecgnat or
- -- g-trasym.obj (on OpenVMS) is
+ -- libgnarl or libdecgnat is
-- necessary.
Check_Libs (ALI_Path, True);
@@ -1642,12 +1624,6 @@ package body MLib.Prj is
end if;
end if;
- if Gtrasymobj_Needed then
- Opts.Increment_Last;
- Opts.Table (Opts.Last) :=
- new String'(Lib_Directory & "/g-trasym.obj");
- end if;
-
if Libdecgnat_Needed then
Opts.Increment_Last;
diff --git a/gcc/ada/mlib-utl.adb b/gcc/ada/mlib-utl.adb
index 67e03097ed6..215fa5d6e8d 100644
--- a/gcc/ada/mlib-utl.adb
+++ b/gcc/ada/mlib-utl.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2002-2010, AdaCore --
+-- Copyright (C) 2002-2011, AdaCore --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -553,8 +553,7 @@ package body MLib.Utl is
Write_RF (Opening'Address, 1);
end if;
- Write_RF
- (Objects (J).all'Address, Objects (J).all'Length);
+ Write_RF (Objects (J).all'Address, Objects (J).all'Length);
-- Closing quote for GNU linker
diff --git a/gcc/ada/opt.ads b/gcc/ada/opt.ads
index ed940d43c19..e6a42815e82 100644
--- a/gcc/ada/opt.ads
+++ b/gcc/ada/opt.ads
@@ -1448,6 +1448,11 @@ package Opt is
-- with literals or S'Length, presumably assuming a lower bound of one. Set
-- False by -gnatwW.
+ Warn_On_Atomic_Synchronization : Boolean := False;
+ -- GNAT
+ -- Set to True to generate information messages for atomic synchronization.
+ -- Set True by use of -gnatw.n.
+
Warn_On_Bad_Fixed_Value : Boolean := False;
-- GNAT
-- Set to True to generate warnings for static fixed-point expression
diff --git a/gcc/ada/par-ch2.adb b/gcc/ada/par-ch2.adb
index 02914422c2c..2cd54b7001c 100644
--- a/gcc/ada/par-ch2.adb
+++ b/gcc/ada/par-ch2.adb
@@ -62,34 +62,7 @@ package body Ch2 is
-- Code duplication, see Par_Ch3.P_Defining_Identifier???
if Token = Tok_Identifier then
-
- -- Shouldn't the warnings below be emitted when in Ada 83 mode???
-
- -- Ada 2005 (AI-284): If compiling in Ada 95 mode, we warn that
- -- INTERFACE, OVERRIDING, and SYNCHRONIZED are new reserved words.
-
- if Ada_Version = Ada_95
- and then Warn_On_Ada_2005_Compatibility
- then
- if Token_Name = Name_Overriding
- or else Token_Name = Name_Synchronized
- or else (Token_Name = Name_Interface
- and then Prev_Token /= Tok_Pragma)
- then
- Error_Msg_N ("& is a reserved word in Ada 2005?", Token_Node);
- end if;
- end if;
-
- -- Similarly, warn about Ada 2012 reserved words
-
- if Ada_Version in Ada_95 .. Ada_2005
- and then Warn_On_Ada_2012_Compatibility
- then
- if Token_Name = Name_Some then
- Error_Msg_N ("& is a reserved word in Ada 2012?", Token_Node);
- end if;
- end if;
-
+ Check_Future_Keyword;
Ident_Node := Token_Node;
Scan; -- past Identifier
return Ident_Node;
diff --git a/gcc/ada/par-ch3.adb b/gcc/ada/par-ch3.adb
index c05a5b65b49..ef017f08960 100644
--- a/gcc/ada/par-ch3.adb
+++ b/gcc/ada/par-ch3.adb
@@ -213,38 +213,7 @@ package body Ch3 is
-- Duplication should be removed, common code should be factored???
if Token = Tok_Identifier then
-
- -- Shouldn't the warnings below be emitted when in Ada 83 mode???
-
- -- Ada 2005 (AI-284): If compiling in Ada 95 mode, we warn that
- -- INTERFACE, OVERRIDING, and SYNCHRONIZED are new reserved words.
- -- Note that in the case where these keywords are misused in Ada 95
- -- mode, this routine will generally not be called at all.
-
- -- What sort of misuse is this comment talking about??? These are
- -- perfectly legitimate defining identifiers in Ada 95???
-
- if Ada_Version = Ada_95
- and then Warn_On_Ada_2005_Compatibility
- then
- if Token_Name = Name_Overriding
- or else Token_Name = Name_Synchronized
- or else (Token_Name = Name_Interface
- and then Prev_Token /= Tok_Pragma)
- then
- Error_Msg_N ("& is a reserved word in Ada 2005?", Token_Node);
- end if;
- end if;
-
- -- Similarly, warn about Ada 2012 reserved words
-
- if Ada_Version in Ada_95 .. Ada_2005
- and then Warn_On_Ada_2012_Compatibility
- then
- if Token_Name = Name_Some then
- Error_Msg_N ("& is a reserved word in Ada 2012?", Token_Node);
- end if;
- end if;
+ Check_Future_Keyword;
-- If we have a reserved identifier, manufacture an identifier with
-- a corresponding name after posting an appropriate error message
diff --git a/gcc/ada/par-ch6.adb b/gcc/ada/par-ch6.adb
index 7a9df3ac804..7d598547911 100644
--- a/gcc/ada/par-ch6.adb
+++ b/gcc/ada/par-ch6.adb
@@ -184,7 +184,7 @@ package body Ch6 is
Scope.Table (Scope.Last).Ecol := Start_Column;
Scope.Table (Scope.Last).Lreq := False;
- -- Ada 2005: scan leading NOT OVERRIDING indicator
+ -- Ada 2005: Scan leading NOT OVERRIDING indicator
if Token = Tok_Not then
Scan; -- past NOT
@@ -1677,6 +1677,14 @@ package body Ch6 is
Scan; -- past ALIASED
Set_Aliased_Present (Decl_Node);
+ if Ada_Version < Ada_2012 then
+ Error_Msg_SC -- CODEFIX
+ ("ALIASED not allowed in extended return in Ada2012?");
+ else
+ Error_Msg_SC -- CODEFIX
+ ("ALIASED not allowed in extended return");
+ end if;
+
if Token = Tok_Constant then
Scan; -- past CONSTANT
Set_Constant_Present (Decl_Node);
diff --git a/gcc/ada/par-prag.adb b/gcc/ada/par-prag.adb
index 5ed6553546f..224b992274e 100644
--- a/gcc/ada/par-prag.adb
+++ b/gcc/ada/par-prag.adb
@@ -61,8 +61,8 @@ function Prag (Pragma_Node : Node_Id; Semi : Source_Ptr) return Node_Id is
-- that is the only case in which a non-present argument can be referenced.
procedure Check_Arg_Count (Required : Int);
- -- Check argument count for pragma = Required.
- -- If not give error and raise Error_Resync.
+ -- Check argument count for pragma = Required. If not give error and raise
+ -- Error_Resync.
procedure Check_Arg_Is_String_Literal (Arg : Node_Id);
-- Check the expression of the specified argument to make sure that it
@@ -1091,174 +1091,176 @@ begin
-- For all other pragmas, checking and processing is handled
-- entirely in Sem_Prag, and no further checking is done by Par.
- when Pragma_Abort_Defer |
- Pragma_Assertion_Policy |
- Pragma_Assume_No_Invalid_Values |
- Pragma_AST_Entry |
- Pragma_All_Calls_Remote |
- Pragma_Annotate |
- Pragma_Assert |
- Pragma_Asynchronous |
- Pragma_Atomic |
- Pragma_Atomic_Components |
- Pragma_Attach_Handler |
- Pragma_Check |
- Pragma_Check_Name |
- Pragma_Check_Policy |
- Pragma_CIL_Constructor |
- Pragma_Compile_Time_Error |
- Pragma_Compile_Time_Warning |
- Pragma_Compiler_Unit |
- Pragma_Convention_Identifier |
- Pragma_CPP_Class |
- Pragma_CPP_Constructor |
- Pragma_CPP_Virtual |
- Pragma_CPP_Vtable |
- Pragma_CPU |
- Pragma_C_Pass_By_Copy |
- Pragma_Comment |
- Pragma_Common_Object |
- Pragma_Complete_Representation |
- Pragma_Complex_Representation |
- Pragma_Component_Alignment |
- Pragma_Controlled |
- Pragma_Convention |
- Pragma_Debug_Policy |
- Pragma_Detect_Blocking |
- Pragma_Default_Storage_Pool |
- Pragma_Dimension |
- Pragma_Discard_Names |
- Pragma_Dispatching_Domain |
- Pragma_Eliminate |
- Pragma_Elaborate |
- Pragma_Elaborate_All |
- Pragma_Elaborate_Body |
- Pragma_Elaboration_Checks |
- Pragma_Export |
- Pragma_Export_Exception |
- Pragma_Export_Function |
- Pragma_Export_Object |
- Pragma_Export_Procedure |
- Pragma_Export_Value |
- Pragma_Export_Valued_Procedure |
- Pragma_Extend_System |
- Pragma_External |
- Pragma_External_Name_Casing |
- Pragma_Favor_Top_Level |
- Pragma_Fast_Math |
- Pragma_Finalize_Storage_Only |
- Pragma_Float_Representation |
- Pragma_Ident |
- Pragma_Implementation_Defined |
- Pragma_Implemented |
- Pragma_Implicit_Packing |
- Pragma_Import |
- Pragma_Import_Exception |
- Pragma_Import_Function |
- Pragma_Import_Object |
- Pragma_Import_Procedure |
- Pragma_Import_Valued_Procedure |
- Pragma_Independent |
- Pragma_Independent_Components |
- Pragma_Initialize_Scalars |
- Pragma_Inline |
- Pragma_Inline_Always |
- Pragma_Inline_Generic |
- Pragma_Inspection_Point |
- Pragma_Interface |
- Pragma_Interface_Name |
- Pragma_Interrupt_Handler |
- Pragma_Interrupt_State |
- Pragma_Interrupt_Priority |
- Pragma_Invariant |
- Pragma_Java_Constructor |
- Pragma_Java_Interface |
- Pragma_Keep_Names |
- Pragma_License |
- Pragma_Link_With |
- Pragma_Linker_Alias |
- Pragma_Linker_Constructor |
- Pragma_Linker_Destructor |
- Pragma_Linker_Options |
- Pragma_Linker_Section |
- Pragma_Locking_Policy |
- Pragma_Long_Float |
- Pragma_Machine_Attribute |
- Pragma_Main |
- Pragma_Main_Storage |
- Pragma_Memory_Size |
- Pragma_No_Body |
- Pragma_No_Return |
- Pragma_No_Run_Time |
- Pragma_No_Strict_Aliasing |
- Pragma_Normalize_Scalars |
- Pragma_Obsolescent |
- Pragma_Ordered |
- Pragma_Optimize |
- Pragma_Optimize_Alignment |
- Pragma_Pack |
- Pragma_Passive |
- Pragma_Preelaborable_Initialization |
- Pragma_Polling |
- Pragma_Persistent_BSS |
- Pragma_Postcondition |
- Pragma_Precondition |
- Pragma_Predicate |
- Pragma_Preelaborate |
- Pragma_Preelaborate_05 |
- Pragma_Priority |
- Pragma_Priority_Specific_Dispatching |
- Pragma_Profile |
- Pragma_Profile_Warnings |
- Pragma_Propagate_Exceptions |
- Pragma_Psect_Object |
- Pragma_Pure |
- Pragma_Pure_05 |
- Pragma_Pure_Function |
- Pragma_Queuing_Policy |
- Pragma_Relative_Deadline |
- Pragma_Remote_Call_Interface |
- Pragma_Remote_Types |
- Pragma_Restricted_Run_Time |
- Pragma_Ravenscar |
- Pragma_Reviewable |
- Pragma_Share_Generic |
- Pragma_Shared |
- Pragma_Shared_Passive |
- Pragma_Short_Circuit_And_Or |
- Pragma_Short_Descriptors |
- Pragma_Storage_Size |
- Pragma_Storage_Unit |
- Pragma_Static_Elaboration_Desired |
- Pragma_Stream_Convert |
- Pragma_Subtitle |
- Pragma_Suppress |
- Pragma_Suppress_Debug_Info |
- Pragma_Suppress_Exception_Locations |
- Pragma_Suppress_Initialization |
- Pragma_System_Name |
- Pragma_Task_Dispatching_Policy |
- Pragma_Task_Info |
- Pragma_Task_Name |
- Pragma_Task_Storage |
- Pragma_Test_Case |
- Pragma_Thread_Local_Storage |
- Pragma_Time_Slice |
- Pragma_Title |
- Pragma_Unchecked_Union |
- Pragma_Unimplemented_Unit |
- Pragma_Universal_Aliasing |
- Pragma_Universal_Data |
- Pragma_Unmodified |
- Pragma_Unreferenced |
- Pragma_Unreferenced_Objects |
- Pragma_Unreserve_All_Interrupts |
- Pragma_Unsuppress |
- Pragma_Use_VADS_Size |
- Pragma_Volatile |
- Pragma_Volatile_Components |
- Pragma_Weak_External |
- Pragma_Validity_Checks =>
+ when Pragma_Abort_Defer |
+ Pragma_Assertion_Policy |
+ Pragma_Assume_No_Invalid_Values |
+ Pragma_AST_Entry |
+ Pragma_All_Calls_Remote |
+ Pragma_Annotate |
+ Pragma_Assert |
+ Pragma_Asynchronous |
+ Pragma_Atomic |
+ Pragma_Atomic_Components |
+ Pragma_Attach_Handler |
+ Pragma_Check |
+ Pragma_Check_Name |
+ Pragma_Check_Policy |
+ Pragma_CIL_Constructor |
+ Pragma_Compile_Time_Error |
+ Pragma_Compile_Time_Warning |
+ Pragma_Compiler_Unit |
+ Pragma_Convention_Identifier |
+ Pragma_CPP_Class |
+ Pragma_CPP_Constructor |
+ Pragma_CPP_Virtual |
+ Pragma_CPP_Vtable |
+ Pragma_CPU |
+ Pragma_C_Pass_By_Copy |
+ Pragma_Comment |
+ Pragma_Common_Object |
+ Pragma_Complete_Representation |
+ Pragma_Complex_Representation |
+ Pragma_Component_Alignment |
+ Pragma_Controlled |
+ Pragma_Convention |
+ Pragma_Debug_Policy |
+ Pragma_Detect_Blocking |
+ Pragma_Default_Storage_Pool |
+ Pragma_Dimension |
+ Pragma_Disable_Atomic_Synchronization |
+ Pragma_Discard_Names |
+ Pragma_Dispatching_Domain |
+ Pragma_Eliminate |
+ Pragma_Elaborate |
+ Pragma_Elaborate_All |
+ Pragma_Elaborate_Body |
+ Pragma_Elaboration_Checks |
+ Pragma_Enable_Atomic_Synchronization |
+ Pragma_Export |
+ Pragma_Export_Exception |
+ Pragma_Export_Function |
+ Pragma_Export_Object |
+ Pragma_Export_Procedure |
+ Pragma_Export_Value |
+ Pragma_Export_Valued_Procedure |
+ Pragma_Extend_System |
+ Pragma_External |
+ Pragma_External_Name_Casing |
+ Pragma_Favor_Top_Level |
+ Pragma_Fast_Math |
+ Pragma_Finalize_Storage_Only |
+ Pragma_Float_Representation |
+ Pragma_Ident |
+ Pragma_Implementation_Defined |
+ Pragma_Implemented |
+ Pragma_Implicit_Packing |
+ Pragma_Import |
+ Pragma_Import_Exception |
+ Pragma_Import_Function |
+ Pragma_Import_Object |
+ Pragma_Import_Procedure |
+ Pragma_Import_Valued_Procedure |
+ Pragma_Independent |
+ Pragma_Independent_Components |
+ Pragma_Initialize_Scalars |
+ Pragma_Inline |
+ Pragma_Inline_Always |
+ Pragma_Inline_Generic |
+ Pragma_Inspection_Point |
+ Pragma_Interface |
+ Pragma_Interface_Name |
+ Pragma_Interrupt_Handler |
+ Pragma_Interrupt_State |
+ Pragma_Interrupt_Priority |
+ Pragma_Invariant |
+ Pragma_Java_Constructor |
+ Pragma_Java_Interface |
+ Pragma_Keep_Names |
+ Pragma_License |
+ Pragma_Link_With |
+ Pragma_Linker_Alias |
+ Pragma_Linker_Constructor |
+ Pragma_Linker_Destructor |
+ Pragma_Linker_Options |
+ Pragma_Linker_Section |
+ Pragma_Locking_Policy |
+ Pragma_Long_Float |
+ Pragma_Machine_Attribute |
+ Pragma_Main |
+ Pragma_Main_Storage |
+ Pragma_Memory_Size |
+ Pragma_No_Body |
+ Pragma_No_Return |
+ Pragma_No_Run_Time |
+ Pragma_No_Strict_Aliasing |
+ Pragma_Normalize_Scalars |
+ Pragma_Obsolescent |
+ Pragma_Ordered |
+ Pragma_Optimize |
+ Pragma_Optimize_Alignment |
+ Pragma_Pack |
+ Pragma_Passive |
+ Pragma_Preelaborable_Initialization |
+ Pragma_Polling |
+ Pragma_Persistent_BSS |
+ Pragma_Postcondition |
+ Pragma_Precondition |
+ Pragma_Predicate |
+ Pragma_Preelaborate |
+ Pragma_Preelaborate_05 |
+ Pragma_Priority |
+ Pragma_Priority_Specific_Dispatching |
+ Pragma_Profile |
+ Pragma_Profile_Warnings |
+ Pragma_Propagate_Exceptions |
+ Pragma_Psect_Object |
+ Pragma_Pure |
+ Pragma_Pure_05 |
+ Pragma_Pure_Function |
+ Pragma_Queuing_Policy |
+ Pragma_Relative_Deadline |
+ Pragma_Remote_Call_Interface |
+ Pragma_Remote_Types |
+ Pragma_Restricted_Run_Time |
+ Pragma_Ravenscar |
+ Pragma_Reviewable |
+ Pragma_Share_Generic |
+ Pragma_Shared |
+ Pragma_Shared_Passive |
+ Pragma_Short_Circuit_And_Or |
+ Pragma_Short_Descriptors |
+ Pragma_Storage_Size |
+ Pragma_Storage_Unit |
+ Pragma_Static_Elaboration_Desired |
+ Pragma_Stream_Convert |
+ Pragma_Subtitle |
+ Pragma_Suppress |
+ Pragma_Suppress_Debug_Info |
+ Pragma_Suppress_Exception_Locations |
+ Pragma_Suppress_Initialization |
+ Pragma_System_Name |
+ Pragma_Task_Dispatching_Policy |
+ Pragma_Task_Info |
+ Pragma_Task_Name |
+ Pragma_Task_Storage |
+ Pragma_Test_Case |
+ Pragma_Thread_Local_Storage |
+ Pragma_Time_Slice |
+ Pragma_Title |
+ Pragma_Unchecked_Union |
+ Pragma_Unimplemented_Unit |
+ Pragma_Universal_Aliasing |
+ Pragma_Universal_Data |
+ Pragma_Unmodified |
+ Pragma_Unreferenced |
+ Pragma_Unreferenced_Objects |
+ Pragma_Unreserve_All_Interrupts |
+ Pragma_Unsuppress |
+ Pragma_Use_VADS_Size |
+ Pragma_Volatile |
+ Pragma_Volatile_Components |
+ Pragma_Weak_External |
+ Pragma_Validity_Checks =>
null;
--------------------
diff --git a/gcc/ada/par-util.adb b/gcc/ada/par-util.adb
index 6a0e8efc6cb..259cfb8e789 100644
--- a/gcc/ada/par-util.adb
+++ b/gcc/ada/par-util.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -169,6 +169,43 @@ package body Util is
end Check_Bad_Layout;
--------------------------
+ -- Check_Future_Keyword --
+ --------------------------
+
+ procedure Check_Future_Keyword is
+ begin
+ -- Ada 2005 (AI-284): Compiling in Ada95 mode we warn that INTERFACE,
+ -- OVERRIDING, and SYNCHRONIZED are new reserved words.
+
+ if Ada_Version = Ada_95
+ and then Warn_On_Ada_2005_Compatibility
+ then
+ if Token_Name = Name_Overriding
+ or else Token_Name = Name_Synchronized
+ or else (Token_Name = Name_Interface
+ and then Prev_Token /= Tok_Pragma)
+ then
+ Error_Msg_N ("& is a reserved word in Ada 2005?", Token_Node);
+ end if;
+ end if;
+
+ -- Similarly, warn about Ada 2012 reserved words
+
+ if Ada_Version in Ada_95 .. Ada_2005
+ and then Warn_On_Ada_2012_Compatibility
+ then
+ if Token_Name = Name_Some then
+ Error_Msg_N ("& is a reserved word in Ada 2012?", Token_Node);
+ end if;
+ end if;
+
+ -- Note: we deliberately do not emit these warnings when operating in
+ -- Ada 83 mode because in that case we assume the user is building
+ -- legacy code anyway and is not interested in updating Ada versions.
+
+ end Check_Future_Keyword;
+
+ --------------------------
-- Check_Misspelling_Of --
--------------------------
diff --git a/gcc/ada/par.adb b/gcc/ada/par.adb
index e054c198143..ed2e72473e6 100644
--- a/gcc/ada/par.adb
+++ b/gcc/ada/par.adb
@@ -1156,6 +1156,11 @@ function Par (Configuration_Pragmas : Boolean) return List_Id is
-- mode. The caller has typically checked that the current token,
-- an identifier, matches one of the 95 keywords.
+ procedure Check_Future_Keyword;
+ -- Emit a warning if the current token is a valid identifier in the
+ -- language version in use, but is a reserved word in a later language
+ -- version (unless the language version in use is Ada 83).
+
procedure Check_Simple_Expression (E : Node_Id);
-- Given an expression E, that has just been scanned, so that Expr_Form
-- is still set, outputs an error if E is a non-simple expression. E is
diff --git a/gcc/ada/prj-conf.adb b/gcc/ada/prj-conf.adb
index 1514107effb..db8dba4ae88 100644
--- a/gcc/ada/prj-conf.adb
+++ b/gcc/ada/prj-conf.adb
@@ -1324,6 +1324,7 @@ package body Prj.Conf is
Prj.Proc.Process_Project_Tree_Phase_1
(In_Tree => Project_Tree,
Project => Config,
+ Packages_To_Check => Packages_To_Check,
Success => Success,
From_Project_Node => Config_Project_Node,
From_Project_Node_Tree => Project_Node_Tree,
@@ -1465,6 +1466,7 @@ package body Prj.Conf is
Process_Project_Tree_Phase_1
(In_Tree => Project_Tree,
Project => Main_Project,
+ Packages_To_Check => Packages_To_Check,
Success => Success,
From_Project_Node => User_Project_Node,
From_Project_Node_Tree => Project_Node_Tree,
diff --git a/gcc/ada/prj-pars.adb b/gcc/ada/prj-pars.adb
index f2d289f5c38..b76a77f1066 100644
--- a/gcc/ada/prj-pars.adb
+++ b/gcc/ada/prj-pars.adb
@@ -43,7 +43,7 @@ package body Prj.Pars is
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
Project_File_Name : String;
- Packages_To_Check : String_List_Access := All_Packages;
+ Packages_To_Check : String_List_Access;
Reset_Tree : Boolean := True;
In_Node_Tree : Prj.Tree.Project_Node_Tree_Ref := null;
Env : in out Prj.Tree.Environment)
diff --git a/gcc/ada/prj-pars.ads b/gcc/ada/prj-pars.ads
index fb424a90033..23f3347d700 100644
--- a/gcc/ada/prj-pars.ads
+++ b/gcc/ada/prj-pars.ads
@@ -36,7 +36,7 @@ package Prj.Pars is
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
Project_File_Name : String;
- Packages_To_Check : String_List_Access := All_Packages;
+ Packages_To_Check : String_List_Access;
Reset_Tree : Boolean := True;
In_Node_Tree : Prj.Tree.Project_Node_Tree_Ref := null;
Env : in out Prj.Tree.Environment);
diff --git a/gcc/ada/prj-part.adb b/gcc/ada/prj-part.adb
index 1c18680fbe8..022efe3c80b 100644
--- a/gcc/ada/prj-part.adb
+++ b/gcc/ada/prj-part.adb
@@ -443,7 +443,7 @@ package body Prj.Part is
Project : out Project_Node_Id;
Project_File_Name : String;
Errout_Handling : Errout_Mode := Always_Finalize;
- Packages_To_Check : String_List_Access := All_Packages;
+ Packages_To_Check : String_List_Access;
Store_Comments : Boolean := False;
Current_Directory : String := "";
Is_Config_File : Boolean;
diff --git a/gcc/ada/prj-part.ads b/gcc/ada/prj-part.ads
index 1184c77a08d..708142ddb27 100644
--- a/gcc/ada/prj-part.ads
+++ b/gcc/ada/prj-part.ads
@@ -42,7 +42,7 @@ package Prj.Part is
Project : out Project_Node_Id;
Project_File_Name : String;
Errout_Handling : Errout_Mode := Always_Finalize;
- Packages_To_Check : String_List_Access := All_Packages;
+ Packages_To_Check : String_List_Access;
Store_Comments : Boolean := False;
Current_Directory : String := "";
Is_Config_File : Boolean;
diff --git a/gcc/ada/prj-proc.adb b/gcc/ada/prj-proc.adb
index 269bc4552db..8e5060be243 100644
--- a/gcc/ada/prj-proc.adb
+++ b/gcc/ada/prj-proc.adb
@@ -145,6 +145,7 @@ package body Prj.Proc is
procedure Recursive_Process
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
Env : in out Prj.Tree.Environment;
@@ -1347,6 +1348,7 @@ package body Prj.Proc is
procedure Process
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
Success : out Boolean;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
@@ -1361,6 +1363,7 @@ package body Prj.Proc is
From_Project_Node => From_Project_Node,
From_Project_Node_Tree => From_Project_Node_Tree,
Env => Env,
+ Packages_To_Check => Packages_To_Check,
Reset_Tree => Reset_Tree);
if Project_Qualifier_Of
@@ -2050,7 +2053,7 @@ package body Prj.Proc is
Shared.Variable_Elements.Table (Var).Value := New_Value;
end if;
- if Name = Snames.Name_Project_Path then
+ if Is_Attribute and then Name = Snames.Name_Project_Path then
if In_Tree.Is_Root_Tree then
declare
Val : String_List_Id := New_Value.Values;
@@ -2325,6 +2328,7 @@ package body Prj.Proc is
procedure Process_Project_Tree_Phase_1
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
Success : out Boolean;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
@@ -2349,6 +2353,7 @@ package body Prj.Proc is
Recursive_Process
(Project => Project,
In_Tree => In_Tree,
+ Packages_To_Check => Packages_To_Check,
From_Project_Node => From_Project_Node,
From_Project_Node_Tree => From_Project_Node_Tree,
Env => Env,
@@ -2482,6 +2487,7 @@ package body Prj.Proc is
procedure Recursive_Process
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
Env : in out Prj.Tree.Environment;
@@ -2539,9 +2545,9 @@ package body Prj.Proc is
Recursive_Process
(In_Tree => In_Tree,
Project => New_Project,
+ Packages_To_Check => Packages_To_Check,
From_Project_Node =>
- Project_Node_Of
- (With_Clause, From_Project_Node_Tree),
+ Project_Node_Of (With_Clause, From_Project_Node_Tree),
From_Project_Node_Tree => From_Project_Node_Tree,
Env => Env,
Extended_By => No_Project);
@@ -2596,6 +2602,7 @@ package body Prj.Proc is
Prj.Part.Parse
(In_Tree => From_Project_Node_Tree,
Project => Loaded_Project,
+ Packages_To_Check => Packages_To_Check,
Project_File_Name => Get_Name_String (List.Path),
Errout_Handling => Prj.Part.Never_Finalize,
Current_Directory => Get_Name_String (Project.Directory.Name),
@@ -2627,6 +2634,7 @@ package body Prj.Proc is
Process_Project_Tree_Phase_1
(In_Tree => Tree,
Project => List.Project,
+ Packages_To_Check => Packages_To_Check,
Success => Success,
From_Project_Node => Loaded_Project,
From_Project_Node_Tree => From_Project_Node_Tree,
@@ -2638,6 +2646,7 @@ package body Prj.Proc is
Process_Project_Tree_Phase_1
(In_Tree => Tree,
Project => List.Project,
+ Packages_To_Check => Packages_To_Check,
Success => Success,
From_Project_Node => Loaded_Project,
From_Project_Node_Tree => From_Project_Node_Tree,
@@ -2859,8 +2868,10 @@ package body Prj.Proc is
Recursive_Process
(In_Tree => In_Tree,
Project => Project.Extends,
- From_Project_Node => Extended_Project_Of
- (Declaration_Node, From_Project_Node_Tree),
+ Packages_To_Check => Packages_To_Check,
+ From_Project_Node =>
+ Extended_Project_Of
+ (Declaration_Node, From_Project_Node_Tree),
From_Project_Node_Tree => From_Project_Node_Tree,
Env => Env,
Extended_By => Project);
diff --git a/gcc/ada/prj-proc.ads b/gcc/ada/prj-proc.ads
index f7fb7ad1411..72ab7eb919d 100644
--- a/gcc/ada/prj-proc.ads
+++ b/gcc/ada/prj-proc.ads
@@ -34,6 +34,7 @@ package Prj.Proc is
procedure Process_Project_Tree_Phase_1
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
Success : out Boolean;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
@@ -68,6 +69,7 @@ package Prj.Proc is
procedure Process
(In_Tree : Project_Tree_Ref;
Project : out Project_Id;
+ Packages_To_Check : String_List_Access;
Success : out Boolean;
From_Project_Node : Project_Node_Id;
From_Project_Node_Tree : Project_Node_Tree_Ref;
diff --git a/gcc/ada/projects.texi b/gcc/ada/projects.texi
index 87627a26f72..356104f07c0 100644
--- a/gcc/ada/projects.texi
+++ b/gcc/ada/projects.texi
@@ -580,19 +580,19 @@ packages would be involved in the build process.
@b{for} Object_Dir @b{use} "obj";
@b{for} Exec_Dir @b{use} ".";
@b{for} Main @b{use} ("proc.adb");
- @b{end} Build;
- @b{package} Builder @b{is} --<<< for gnatmake and gprbuild
- @b{end} Builder;
+ @b{package} Builder @b{is} --<<< for gnatmake and gprbuild
+ @b{end} Builder;
- @b{package} Compiler @b{is} --<<< for the compiler
- @b{end} Compiler;
+ @b{package} Compiler @b{is} --<<< for the compiler
+ @b{end} Compiler;
- @b{package} Binder @b{is} --<<< for the binder
- @b{end} Binder;
+ @b{package} Binder @b{is} --<<< for the binder
+ @b{end} Binder;
- @b{package} Linker @b{is} --<<< for the linker
- @b{end} Linker;
+ @b{package} Linker @b{is} --<<< for the linker
+ @b{end} Linker;
+ @b{end} Build;
@end smallexample
@noindent
@@ -2015,8 +2015,16 @@ end Work;
@end smallexample
@noindent
-An extending project retains all the switches specified in the
-extended project.
+All packages that are not declared in the extending project are inherited from
+the project being extended, with their attributes, with the exception of
+@code{Linker'Linker_Options} which is never inherited. In particular, an
+extending project retains all the switches specified in the project being
+extended.
+
+At the project level, if they are not declared in the extending project, some
+attributes are inherited from the project being extended. They are:
+@code{Languages}, @code{Main} (for a root non library project) and
+@code{Library_Name} (for a project extending a library project)
@menu
* Project Hierarchy Extension::
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index 07bf0121a56..b7a02066b77 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -1349,6 +1349,7 @@ package Rtsfind is
RE_Allocate_Any, -- System.Storage_Pools
RE_Deallocate_Any, -- System.Storage_Pools
RE_Root_Storage_Pool, -- System.Storage_Pools
+ RE_Root_Storage_Pool_Ptr, -- System.Storage_Pools
RE_Allocate_Any_Controlled, -- System.Storage_Pools.Subpools
RE_Deallocate_Any_Controlled, -- System.Storage_Pools.Subpools
@@ -2545,6 +2546,7 @@ package Rtsfind is
RE_Allocate_Any => System_Storage_Pools,
RE_Deallocate_Any => System_Storage_Pools,
RE_Root_Storage_Pool => System_Storage_Pools,
+ RE_Root_Storage_Pool_Ptr => System_Storage_Pools,
RE_Allocate_Any_Controlled => System_Storage_Pools_Subpools,
RE_Deallocate_Any_Controlled => System_Storage_Pools_Subpools,
diff --git a/gcc/ada/s-finmas.adb b/gcc/ada/s-finmas.adb
index c663988f43a..8474ff4a8f3 100644
--- a/gcc/ada/s-finmas.adb
+++ b/gcc/ada/s-finmas.adb
@@ -77,18 +77,28 @@ package body System.Finalization_Masters is
procedure Attach (N : not null FM_Node_Ptr; L : not null FM_Node_Ptr) is
begin
Lock_Task.all;
-
- L.Next.Prev := N;
- N.Next := L.Next;
- L.Next := N;
- N.Prev := L;
-
+ Attach_Unprotected (N, L);
Unlock_Task.all;
-- Note: No need to unlock in case of an exception because the above
-- code can never raise one.
end Attach;
+ ------------------------
+ -- Attach_Unprotected --
+ ------------------------
+
+ procedure Attach_Unprotected
+ (N : not null FM_Node_Ptr;
+ L : not null FM_Node_Ptr)
+ is
+ begin
+ L.Next.Prev := N;
+ N.Next := L.Next;
+ L.Next := N;
+ N.Prev := L;
+ end Attach_Unprotected;
+
---------------
-- Base_Pool --
---------------
@@ -100,16 +110,14 @@ package body System.Finalization_Masters is
return Master.Base_Pool;
end Base_Pool;
- -----------------------------
- -- Delete_Finalize_Address --
- -----------------------------
+ -----------------------------------------
+ -- Delete_Finalize_Address_Unprotected --
+ -----------------------------------------
- procedure Delete_Finalize_Address (Obj : System.Address) is
+ procedure Delete_Finalize_Address_Unprotected (Obj : System.Address) is
begin
- Lock_Task.all;
Finalize_Address_Table.Remove (Obj);
- Unlock_Task.all;
- end Delete_Finalize_Address;
+ end Delete_Finalize_Address_Unprotected;
------------
-- Detach --
@@ -117,20 +125,27 @@ package body System.Finalization_Masters is
procedure Detach (N : not null FM_Node_Ptr) is
begin
- if N.Prev /= null and then N.Next /= null then
- Lock_Task.all;
+ Lock_Task.all;
+ Detach_Unprotected (N);
+ Unlock_Task.all;
+
+ -- Note: No need to unlock in case of an exception because the above
+ -- code can never raise one.
+ end Detach;
+ ------------------------
+ -- Detach_Unprotected --
+ ------------------------
+
+ procedure Detach_Unprotected (N : not null FM_Node_Ptr) is
+ begin
+ if N.Prev /= null and then N.Next /= null then
N.Prev.Next := N.Next;
N.Next.Prev := N.Prev;
N.Prev := null;
N.Next := null;
-
- Unlock_Task.all;
-
- -- Note: No need to unlock in case of an exception because the above
- -- code can never raise one.
end if;
- end Detach;
+ end Detach_Unprotected;
--------------
-- Finalize --
@@ -158,10 +173,14 @@ package body System.Finalization_Masters is
-- Start of processing for Finalize
begin
- -- It is possible for multiple tasks to cause the finalization of the
- -- same master. Let only one task finalize the objects.
+ Lock_Task.all;
+
+ -- Synchronization:
+ -- Read - allocation, finalization
+ -- Write - finalization
if Master.Finalization_Started then
+ Unlock_Task.all;
return;
end if;
@@ -170,12 +189,19 @@ package body System.Finalization_Masters is
-- is explicitly deallocated or the associated access type is about to
-- go out of scope.
+ -- Synchronization:
+ -- Read - allocation, finalization
+ -- Write - finalization
+
Master.Finalization_Started := True;
while not Is_Empty_List (Master.Objects'Unchecked_Access) loop
Curr_Ptr := Master.Objects.Next;
- Detach (Curr_Ptr);
+ -- Synchronization:
+ -- Write - allocation, deallocation, finalization
+
+ Detach_Unprotected (Curr_Ptr);
-- Skip the list header in order to offer proper object layout for
-- finalization.
@@ -185,20 +211,28 @@ package body System.Finalization_Masters is
-- Retrieve TSS primitive Finalize_Address depending on the master's
-- mode of operation.
+ -- Synchronization:
+ -- Read - allocation, finalization
+ -- Write - outside
+
if Master.Is_Homogeneous then
+
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - allocation, outside
+
Cleanup := Master.Finalize_Address;
- else
- Cleanup := Finalize_Address (Obj_Addr);
- end if;
- -- If Finalize_Address is not available, then this is most likely an
- -- error in the expansion of the designated type or the allocator.
+ else
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - allocation, deallocation
- pragma Assert (Cleanup /= null);
+ Cleanup := Finalize_Address_Unprotected (Obj_Addr);
+ end if;
begin
Cleanup (Obj_Addr);
-
exception
when Fin_Occur : others =>
if not Raised then
@@ -210,11 +244,22 @@ package body System.Finalization_Masters is
-- When the master is a heterogeneous collection, destroy the object
-- - Finalize_Address pair since it is no longer needed.
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - outside
+
if not Master.Is_Homogeneous then
- Delete_Finalize_Address (Obj_Addr);
+
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - allocation, deallocation, finalization
+
+ Delete_Finalize_Address_Unprotected (Obj_Addr);
end if;
end loop;
+ Unlock_Task.all;
+
-- If the finalization of a particular object failed or Finalize_Address
-- was not set, reraise the exception now.
@@ -234,20 +279,16 @@ package body System.Finalization_Masters is
return Master.Finalize_Address;
end Finalize_Address;
- ----------------------
- -- Finalize_Address --
- ----------------------
+ ----------------------------------
+ -- Finalize_Address_Unprotected --
+ ----------------------------------
- function Finalize_Address
+ function Finalize_Address_Unprotected
(Obj : System.Address) return Finalize_Address_Ptr
is
- Result : Finalize_Address_Ptr;
begin
- Lock_Task.all;
- Result := Finalize_Address_Table.Get (Obj);
- Unlock_Task.all;
- return Result;
- end Finalize_Address;
+ return Finalize_Address_Table.Get (Obj);
+ end Finalize_Address_Unprotected;
--------------------------
-- Finalization_Started --
@@ -463,36 +504,40 @@ package body System.Finalization_Masters is
Fin_Addr_Ptr : Finalize_Address_Ptr)
is
begin
- -- TSS primitive Finalize_Address is set at the point of allocation,
- -- either through Allocate_Any_Controlled or through this routine.
- -- Since multiple tasks can allocate on the same finalization master,
- -- access to this attribute must be protected.
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - allocation, outside
Lock_Task.all;
+ Set_Finalize_Address_Unprotected (Master, Fin_Addr_Ptr);
+ Unlock_Task.all;
+ end Set_Finalize_Address;
+ --------------------------------------
+ -- Set_Finalize_Address_Unprotected --
+ --------------------------------------
+
+ procedure Set_Finalize_Address_Unprotected
+ (Master : in out Finalization_Master;
+ Fin_Addr_Ptr : Finalize_Address_Ptr)
+ is
+ begin
if Master.Finalize_Address = null then
Master.Finalize_Address := Fin_Addr_Ptr;
end if;
+ end Set_Finalize_Address_Unprotected;
- Unlock_Task.all;
- end Set_Finalize_Address;
-
- ----------------------------------------
- -- Set_Heterogeneous_Finalize_Address --
- ----------------------------------------
+ ----------------------------------------------------
+ -- Set_Heterogeneous_Finalize_Address_Unprotected --
+ ----------------------------------------------------
- procedure Set_Heterogeneous_Finalize_Address
+ procedure Set_Heterogeneous_Finalize_Address_Unprotected
(Obj : System.Address;
Fin_Addr_Ptr : Finalize_Address_Ptr)
is
begin
- -- Protected access is required in this case because
- -- Finalize_Address_Table is a global data structure.
-
- Lock_Task.all;
Finalize_Address_Table.Set (Obj, Fin_Addr_Ptr);
- Unlock_Task.all;
- end Set_Heterogeneous_Finalize_Address;
+ end Set_Heterogeneous_Finalize_Address_Unprotected;
--------------------------
-- Set_Is_Heterogeneous --
@@ -500,7 +545,13 @@ package body System.Finalization_Masters is
procedure Set_Is_Heterogeneous (Master : in out Finalization_Master) is
begin
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - outside
+
+ Lock_Task.all;
Master.Is_Homogeneous := False;
+ Unlock_Task.all;
end Set_Is_Heterogeneous;
end System.Finalization_Masters;
diff --git a/gcc/ada/s-finmas.ads b/gcc/ada/s-finmas.ads
index bb9ff5bdc3c..f0dd5b8767e 100644
--- a/gcc/ada/s-finmas.ads
+++ b/gcc/ada/s-finmas.ads
@@ -74,13 +74,23 @@ package System.Finalization_Masters is
for Finalization_Master_Ptr'Storage_Size use 0;
procedure Attach (N : not null FM_Node_Ptr; L : not null FM_Node_Ptr);
+ -- Compiler interface, do not call from withing the run-time. Prepend a
+ -- node to a specific finalization master.
+
+ procedure Attach_Unprotected
+ (N : not null FM_Node_Ptr;
+ L : not null FM_Node_Ptr);
-- Prepend a node to a specific finalization master
- procedure Delete_Finalize_Address (Obj : System.Address);
+ procedure Delete_Finalize_Address_Unprotected (Obj : System.Address);
-- Destroy the relation pair object - Finalize_Address from the internal
-- hash table.
procedure Detach (N : not null FM_Node_Ptr);
+ -- Compiler interface, do not call from within the run-time. Remove a node
+ -- from an arbitrary finalization master.
+
+ procedure Detach_Unprotected (N : not null FM_Node_Ptr);
-- Remove a node from an arbitrary finalization master
overriding procedure Finalize (Master : in out Finalization_Master);
@@ -93,7 +103,7 @@ package System.Finalization_Masters is
-- Return a reference to the TSS primitive Finalize_Address associated with
-- a master.
- function Finalize_Address
+ function Finalize_Address_Unprotected
(Obj : System.Address) return Finalize_Address_Ptr;
-- Retrieve the Finalize_Address primitive associated with a particular
-- object.
@@ -119,9 +129,15 @@ package System.Finalization_Masters is
procedure Set_Finalize_Address
(Master : in out Finalization_Master;
Fin_Addr_Ptr : Finalize_Address_Ptr);
+ -- Compiler interface, do not call from within the run-time. Set the clean
+ -- up routine of a finalization master
+
+ procedure Set_Finalize_Address_Unprotected
+ (Master : in out Finalization_Master;
+ Fin_Addr_Ptr : Finalize_Address_Ptr);
-- Set the clean up routine of a finalization master
- procedure Set_Heterogeneous_Finalize_Address
+ procedure Set_Heterogeneous_Finalize_Address_Unprotected
(Obj : System.Address;
Fin_Addr_Ptr : Finalize_Address_Ptr);
-- Add a relation pair object - Finalize_Address to the internal hash
@@ -165,11 +181,9 @@ private
-- is used only when the master is in homogeneous mode.
Finalization_Started : Boolean := False;
- pragma Atomic (Finalization_Started);
-- A flag used to detect allocations which occur during the finalization
-- of a master. The allocations must raise Program_Error. This scenario
- -- may arise in a multitask environment. The flag is atomic because it
- -- is accessed without Lock_Task / Unlock_Task.
+ -- may arise in a multitask environment.
end record;
-- Since RTSfind cannot contain names of the form RE_"+", the following
diff --git a/gcc/ada/s-gearop.adb b/gcc/ada/s-gearop.adb
index cb07f40902e..a359f14dc28 100644
--- a/gcc/ada/s-gearop.adb
+++ b/gcc/ada/s-gearop.adb
@@ -29,13 +29,15 @@
-- --
------------------------------------------------------------------------------
+with Ada.Numerics; use Ada.Numerics;
+
package body System.Generic_Array_Operations is
- -- The local function Check_Unit_Last computes the index
- -- of the last element returned by Unit_Vector or Unit_Matrix.
- -- A separate function is needed to allow raising Constraint_Error
- -- before declaring the function result variable. The result variable
- -- needs to be declared first, to allow front-end inlining.
+ -- The local function Check_Unit_Last computes the index of the last
+ -- element returned by Unit_Vector or Unit_Matrix. A separate function is
+ -- needed to allow raising Constraint_Error before declaring the function
+ -- result variable. The result variable needs to be declared first, to
+ -- allow front-end inlining.
function Check_Unit_Last
(Index : Integer;
@@ -48,7 +50,6 @@ package body System.Generic_Array_Operations is
--------------
function Diagonal (A : Matrix) return Vector is
-
N : constant Natural := Natural'Min (A'Length (1), A'Length (2));
R : Vector (A'First (1) .. A'First (1) + N - 1);
@@ -80,13 +81,14 @@ package body System.Generic_Array_Operations is
function Check_Unit_Last
(Index : Integer;
Order : Positive;
- First : Integer) return Integer is
+ First : Integer) return Integer
+ is
begin
-- Order the tests carefully to avoid overflow
if Index < First
- or else First > Integer'Last - Order + 1
- or else Index > First + (Order - 1)
+ or else First > Integer'Last - Order + 1
+ or else Index > First + (Order - 1)
then
raise Constraint_Error;
end if;
@@ -99,17 +101,17 @@ package body System.Generic_Array_Operations is
---------------------
procedure Back_Substitute (M, N : in out Matrix) is
- pragma Assert (M'First (1) = N'First (1) and then
+ pragma Assert (M'First (1) = N'First (1)
+ and then
M'Last (1) = N'Last (1));
- Max_Col : Integer := M'Last (2);
-
procedure Sub_Row
(M : in out Matrix;
Target : Integer;
Source : Integer;
Factor : Scalar);
- -- Needs comments ???
+ -- Elementary row operation that subtracts Factor * M (Source, <>) from
+ -- M (Target, <>)
procedure Sub_Row
(M : in out Matrix;
@@ -123,27 +125,47 @@ package body System.Generic_Array_Operations is
end loop;
end Sub_Row;
+ -- Local declarations
+
+ Max_Col : Integer := M'Last (2);
+
-- Start of processing for Back_Substitute
begin
- for Row in reverse M'Range (1) loop
- Find_Non_Zero : for Col in M'First (2) .. Max_Col loop
+ Do_Rows : for Row in reverse M'Range (1) loop
+ Find_Non_Zero : for Col in reverse M'First (2) .. Max_Col loop
if Is_Non_Zero (M (Row, Col)) then
- -- Found first non-zero element, so subtract a multiple
- -- of this row from all higher rows, to reduce all other
- -- elements in this column to zero.
+ -- Found first non-zero element, so subtract a multiple of this
+ -- element from all higher rows, to reduce all other elements
+ -- in this column to zero.
- for J in M'First (1) .. Row - 1 loop
- Sub_Row (N, J, Row, (M (J, Col) / M (Row, Col)));
- Sub_Row (M, J, Row, (M (J, Col) / M (Row, Col)));
- end loop;
+ declare
+ -- We can't use a for loop, as we'd need to iterate to
+ -- Row - 1, but that expression will overflow if M'First
+ -- equals Integer'First, which is true for aggregates
+ -- without explicit bounds..
+
+ J : Integer := M'First (1);
+
+ begin
+ while J < Row loop
+ Sub_Row (N, J, Row, (M (J, Col) / M (Row, Col)));
+ Sub_Row (M, J, Row, (M (J, Col) / M (Row, Col)));
+ J := J + 1;
+ end loop;
+ end;
+
+ -- Avoid potential overflow in the subtraction below
+
+ exit Do_Rows when Col = M'First (2);
Max_Col := Col - 1;
+
exit Find_Non_Zero;
end if;
end loop Find_Non_Zero;
- end loop;
+ end loop Do_Rows;
end Back_Substitute;
-----------------------
@@ -155,30 +177,35 @@ package body System.Generic_Array_Operations is
N : in out Matrix;
Det : out Scalar)
is
- pragma Assert (M'First (1) = N'First (1) and then
+ pragma Assert (M'First (1) = N'First (1)
+ and then
M'Last (1) = N'Last (1));
- function "abs" (X : Scalar) return Scalar is
- (if X < Zero then Zero - X else X);
+ -- The following are variations of the elementary matrix row operations:
+ -- row switching, row multiplication and row addition. Because in this
+ -- algorithm the addition factor is always a negated value, we chose to
+ -- use row subtraction instead. Similarly, instead of multiplying by
+ -- a reciprocal, we divide.
procedure Sub_Row
- (M : in out Matrix;
+ (M : in out Matrix;
Target : Integer;
Source : Integer;
Factor : Scalar);
- -- Needs commenting ???
+ -- Subtrace Factor * M (Source, <>) from M (Target, <>)
procedure Divide_Row
(M, N : in out Matrix;
Row : Integer;
Scale : Scalar);
- -- Needs commenting ???
+ -- Divide M (Row) and N (Row) by Scale, and update Det
procedure Switch_Row
(M, N : in out Matrix;
Row_1 : Integer;
Row_2 : Integer);
- -- Needs commenting ???
+ -- Exchange M (Row_1) and N (Row_1) with M (Row_2) and N (Row_2),
+ -- negating Det in the process.
-------------
-- Sub_Row --
@@ -189,7 +216,7 @@ package body System.Generic_Array_Operations is
Target : Integer;
Source : Integer;
Factor : Scalar)
- is
+ is
begin
for J in M'Range (2) loop
M (Target, J) := M (Target, J) - Factor * M (Source, J);
@@ -213,8 +240,8 @@ package body System.Generic_Array_Operations is
end loop;
for J in N'Range (2) loop
- N (Row - M'First (1) + N'First (1), J)
- := N (Row - M'First (1) + N'First (1), J) / Scale;
+ N (Row - M'First (1) + N'First (1), J) :=
+ N (Row - M'First (1) + N'First (1), J) / Scale;
end loop;
end Divide_Row;
@@ -254,8 +281,9 @@ package body System.Generic_Array_Operations is
end if;
end Switch_Row;
- I : Integer := M'First (1);
- -- Avoid use of I ???
+ -- Local declarations
+
+ Row : Integer := M'First (1);
-- Start of processing for Forward_Eliminate
@@ -264,38 +292,40 @@ package body System.Generic_Array_Operations is
for J in M'Range (2) loop
declare
- Max_I : Integer := I;
- Max_Abs : Scalar := Zero;
+ Max_Row : Integer := Row;
+ Max_Abs : Real'Base := 0.0;
begin
- -- Find best pivot in column J, starting in row I
+ -- Find best pivot in column J, starting in row Row
- for K in I .. M'Last (1) loop
+ for K in Row .. M'Last (1) loop
declare
- New_Abs : constant Scalar := abs M (K, J);
+ New_Abs : constant Real'Base := abs M (K, J);
begin
if Max_Abs < New_Abs then
Max_Abs := New_Abs;
- Max_I := K;
+ Max_Row := K;
end if;
end;
end loop;
- if Zero < Max_Abs then
- Switch_Row (M, N, I, Max_I);
- Divide_Row (M, N, I, M (I, J));
+ if Max_Abs > 0.0 then
+ Switch_Row (M, N, Row, Max_Row);
+ Divide_Row (M, N, Row, M (Row, J));
- for U in I + 1 .. M'Last (1) loop
- Sub_Row (N, U, I, M (U, J));
- Sub_Row (M, U, I, M (U, J));
+ for U in Row + 1 .. M'Last (1) loop
+ Sub_Row (N, U, Row, M (U, J));
+ Sub_Row (M, U, Row, M (U, J));
end loop;
- exit when I >= M'Last (1);
+ exit when Row >= M'Last (1);
- I := I + 1;
+ Row := Row + 1;
else
- Det := Zero; -- Zero, but we don't have literals
+ -- Set zero (note that we do not have literals)
+
+ Det := Zero;
end if;
end;
end loop;
@@ -307,8 +337,7 @@ package body System.Generic_Array_Operations is
function Inner_Product
(Left : Left_Vector;
- Right : Right_Vector)
- return Result_Scalar
+ Right : Right_Vector) return Result_Scalar
is
R : Result_Scalar := Zero;
@@ -329,9 +358,15 @@ package body System.Generic_Array_Operations is
-- L2_Norm --
-------------
- function L2_Norm (X : Vector) return Scalar is
+ function L2_Norm (X : X_Vector) return Result_Real'Base is
+ Sum : Result_Real'Base := 0.0;
+
begin
- return Sqrt (Inner_Product (X, X));
+ for J in X'Range loop
+ Sum := Sum + Result_Real'Base (abs X (J))**2;
+ end loop;
+
+ return Sqrt (Sum);
end L2_Norm;
----------------------------------
@@ -372,17 +407,17 @@ package body System.Generic_Array_Operations is
function Matrix_Matrix_Elementwise_Operation
(Left : Left_Matrix;
- Right : Right_Matrix)
- return Result_Matrix
+ Right : Right_Matrix) return Result_Matrix
is
R : Result_Matrix (Left'Range (1), Left'Range (2));
begin
if Left'Length (1) /= Right'Length (1)
- or else Left'Length (2) /= Right'Length (2)
+ or else
+ Left'Length (2) /= Right'Length (2)
then
raise Constraint_Error with
- "matrices are of different dimension in elementwise operation";
+ "matrices are of different dimension in elementwise operation";
end if;
for J in R'Range (1) loop
@@ -412,10 +447,11 @@ package body System.Generic_Array_Operations is
begin
if X'Length (1) /= Y'Length (1)
- or else X'Length (2) /= Y'Length (2)
+ or else
+ X'Length (2) /= Y'Length (2)
then
raise Constraint_Error with
- "matrices are of different dimension in elementwise operation";
+ "matrices are of different dimension in elementwise operation";
end if;
for J in R'Range (1) loop
@@ -445,7 +481,7 @@ package body System.Generic_Array_Operations is
begin
if Left'Length /= Right'Length then
raise Constraint_Error with
- "vectors are of different length in elementwise operation";
+ "vectors are of different length in elementwise operation";
end if;
for J in R'Range loop
@@ -469,7 +505,7 @@ package body System.Generic_Array_Operations is
begin
if X'Length /= Y'Length then
raise Constraint_Error with
- "vectors are of different length in elementwise operation";
+ "vectors are of different length in elementwise operation";
end if;
for J in R'Range loop
@@ -555,6 +591,57 @@ package body System.Generic_Array_Operations is
return R;
end Scalar_Vector_Elementwise_Operation;
+ ----------
+ -- Sqrt --
+ ----------
+
+ function Sqrt (X : Real'Base) return Real'Base is
+ Root, Next : Real'Base;
+
+ begin
+ -- Be defensive: any comparisons with NaN values will yield False.
+
+ if not (X > 0.0) then
+ if X = 0.0 then
+ return X;
+ else
+ raise Argument_Error;
+ end if;
+
+ elsif X > Real'Base'Last then
+
+ -- X is infinity, which is its own square root
+
+ return X;
+ end if;
+
+ -- Compute an initial estimate based on:
+
+ -- X = M * R**E and Sqrt (X) = Sqrt (M) * R**(E / 2.0),
+
+ -- where M is the mantissa, R is the radix and E the exponent.
+
+ -- By ignoring the mantissa and ignoring the case of an odd
+ -- exponent, we get a final error that is at most R. In other words,
+ -- the result has about a single bit precision.
+
+ Root := Real'Base (Real'Machine_Radix) ** (Real'Exponent (X) / 2);
+
+ -- Because of the poor initial estimate, use the Babylonian method of
+ -- computing the square root, as it is stable for all inputs. Every step
+ -- will roughly double the precision of the result. Just a few steps
+ -- suffice in most cases. Eight iterations should give about 2**8 bits
+ -- of precision.
+
+ for J in 1 .. 8 loop
+ Next := (Root + X / Root) / 2.0;
+ exit when Root = Next;
+ Root := Next;
+ end loop;
+
+ return Root;
+ end Sqrt;
+
---------------------------
-- Matrix_Matrix_Product --
---------------------------
@@ -568,7 +655,7 @@ package body System.Generic_Array_Operations is
begin
if Left'Length (2) /= Right'Length (1) then
raise Constraint_Error with
- "incompatible dimensions in matrix multiplication";
+ "incompatible dimensions in matrix multiplication";
end if;
for J in R'Range (1) loop
@@ -578,8 +665,8 @@ package body System.Generic_Array_Operations is
begin
for M in Left'Range (2) loop
- S := S + Left (J, M)
- * Right (M - Left'First (2) + Right'First (1), K);
+ S := S + Left (J, M) *
+ Right (M - Left'First (2) + Right'First (1), K);
end loop;
R (J, K) := S;
@@ -590,6 +677,75 @@ package body System.Generic_Array_Operations is
return R;
end Matrix_Matrix_Product;
+ ----------------------------
+ -- Matrix_Vector_Solution --
+ ----------------------------
+
+ function Matrix_Vector_Solution (A : Matrix; X : Vector) return Vector is
+ N : constant Natural := A'Length (1);
+ MA : Matrix := A;
+ MX : Matrix (A'Range (1), 1 .. 1);
+ R : Vector (A'Range (2));
+ Det : Scalar;
+
+ begin
+ if A'Length (2) /= N then
+ raise Constraint_Error with "matrix is not square";
+ end if;
+
+ if X'Length /= N then
+ raise Constraint_Error with "incompatible vector length";
+ end if;
+
+ for J in 0 .. MX'Length (1) - 1 loop
+ MX (MX'First (1) + J, 1) := X (X'First + J);
+ end loop;
+
+ Forward_Eliminate (MA, MX, Det);
+ Back_Substitute (MA, MX);
+
+ for J in 0 .. R'Length - 1 loop
+ R (R'First + J) := MX (MX'First (1) + J, 1);
+ end loop;
+
+ return R;
+ end Matrix_Vector_Solution;
+
+ ----------------------------
+ -- Matrix_Matrix_Solution --
+ ----------------------------
+
+ function Matrix_Matrix_Solution (A, X : Matrix) return Matrix is
+ N : constant Natural := A'Length (1);
+ MA : Matrix (A'Range (2), A'Range (2));
+ MB : Matrix (A'Range (2), X'Range (2));
+ Det : Scalar;
+
+ begin
+ if A'Length (2) /= N then
+ raise Constraint_Error with "matrix is not square";
+ end if;
+
+ if X'Length (1) /= N then
+ raise Constraint_Error with "matrices have unequal number of rows";
+ end if;
+
+ for J in 0 .. A'Length (1) - 1 loop
+ for K in MA'Range (2) loop
+ MA (MA'First (1) + J, K) := A (A'First (1) + J, K);
+ end loop;
+
+ for K in MB'Range (2) loop
+ MB (MB'First (1) + J, K) := X (X'First (1) + J, K);
+ end loop;
+ end loop;
+
+ Forward_Eliminate (MA, MB, Det);
+ Back_Substitute (MA, MB);
+
+ return MB;
+ end Matrix_Matrix_Solution;
+
---------------------------
-- Matrix_Vector_Product --
---------------------------
@@ -680,7 +836,7 @@ package body System.Generic_Array_Operations is
or else X'Length (2) /= Y'Length (2)
then
raise Constraint_Error with
- "matrices are of different dimension in update operation";
+ "matrices are of different dimension in update operation";
end if;
for J in X'Range (1) loop
@@ -699,7 +855,7 @@ package body System.Generic_Array_Operations is
begin
if X'Length /= Y'Length then
raise Constraint_Error with
- "vectors are of different length in update operation";
+ "vectors are of different length in update operation";
end if;
for J in X'Range loop
@@ -758,7 +914,7 @@ package body System.Generic_Array_Operations is
begin
if Left'Length /= Right'Length (2) then
raise Constraint_Error with
- "incompatible dimensions in vector-matrix multiplication";
+ "incompatible dimensions in vector-matrix multiplication";
end if;
for J in Right'Range (2) loop
diff --git a/gcc/ada/s-gearop.ads b/gcc/ada/s-gearop.ads
index 51e3b92c201..f401da219e3 100644
--- a/gcc/ada/s-gearop.ads
+++ b/gcc/ada/s-gearop.ads
@@ -65,12 +65,14 @@ pragma Pure (Generic_Array_Operations);
generic
type Scalar is private;
+ type Real is digits <>;
type Matrix is array (Integer range <>, Integer range <>) of Scalar;
+ with function "abs" (Right : Scalar) return Real'Base is <>;
with function "-" (Left, Right : Scalar) return Scalar is <>;
with function "*" (Left, Right : Scalar) return Scalar is <>;
with function "/" (Left, Right : Scalar) return Scalar is <>;
- with function "<" (Left, Right : Scalar) return Boolean is <>;
- Zero, One : Scalar;
+ Zero : Scalar;
+ One : Scalar;
procedure Forward_Eliminate
(M : in out Matrix;
N : in out Matrix;
@@ -291,11 +293,12 @@ pragma Pure (Generic_Array_Operations);
-------------
generic
- type Scalar is private;
- type Vector is array (Integer range <>) of Scalar;
- with function Inner_Product (Left, Right : Vector) return Scalar is <>;
- with function Sqrt (X : Scalar) return Scalar is <>;
- function L2_Norm (X : Vector) return Scalar;
+ type X_Scalar is private;
+ type Result_Real is digits <>;
+ type X_Vector is array (Integer range <>) of X_Scalar;
+ with function "abs" (Right : X_Scalar) return Result_Real is <>;
+ with function Sqrt (X : Result_Real'Base) return Result_Real'Base is <>;
+ function L2_Norm (X : X_Vector) return Result_Real'Base;
-------------------
-- Outer_Product --
@@ -387,6 +390,43 @@ pragma Pure (Generic_Array_Operations);
(Left : Left_Matrix;
Right : Right_Matrix) return Result_Matrix;
+ ----------------------------
+ -- Matrix_Vector_Solution --
+ ----------------------------
+
+ generic
+ type Scalar is private;
+ type Vector is array (Integer range <>) of Scalar;
+ type Matrix is array (Integer range <>, Integer range <>) of Scalar;
+ with procedure Back_Substitute (M, N : in out Matrix) is <>;
+ with procedure Forward_Eliminate
+ (M : in out Matrix;
+ N : in out Matrix;
+ Det : out Scalar) is <>;
+ function Matrix_Vector_Solution (A : Matrix; X : Vector) return Vector;
+
+ ----------------------------
+ -- Matrix_Matrix_Solution --
+ ----------------------------
+
+ generic
+ type Scalar is private;
+ type Matrix is array (Integer range <>, Integer range <>) of Scalar;
+ with procedure Back_Substitute (M, N : in out Matrix) is <>;
+ with procedure Forward_Eliminate
+ (M : in out Matrix;
+ N : in out Matrix;
+ Det : out Scalar) is <>;
+ function Matrix_Matrix_Solution (A : Matrix; X : Matrix) return Matrix;
+
+ ----------
+ -- Sqrt --
+ ----------
+
+ generic
+ type Real is digits <>;
+ function Sqrt (X : Real'Base) return Real'Base;
+
-----------------
-- Swap_Column --
-----------------
diff --git a/gcc/ada/s-linux-alpha.ads b/gcc/ada/s-linux-alpha.ads
index ba72719f8db..a700c9720e6 100644
--- a/gcc/ada/s-linux-alpha.ads
+++ b/gcc/ada/s-linux-alpha.ads
@@ -35,8 +35,6 @@
-- PLEASE DO NOT add any with-clauses to this package or remove the pragma
-- Preelaborate. This package is designed to be a bottom-level (leaf) package.
-with Interfaces.C;
-
package System.Linux is
pragma Preelaborate;
diff --git a/gcc/ada/s-linux-sparc.ads b/gcc/ada/s-linux-sparc.ads
index 756d69d8f30..3ba20da4d5c 100644
--- a/gcc/ada/s-linux-sparc.ads
+++ b/gcc/ada/s-linux-sparc.ads
@@ -35,8 +35,6 @@
-- PLEASE DO NOT add any with-clauses to this package or remove the pragma
-- Preelaborate. This package is designed to be a bottom-level (leaf) package
-with Interfaces.C;
-
package System.Linux is
pragma Preelaborate;
diff --git a/gcc/ada/s-osinte-lynxos-3.ads b/gcc/ada/s-osinte-lynxos-3.ads
index 8098a8fbe88..3d912eefee2 100644
--- a/gcc/ada/s-osinte-lynxos-3.ads
+++ b/gcc/ada/s-osinte-lynxos-3.ads
@@ -1,34 +1,32 @@
------------------------------------------------------------------------------
-- --
--- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
+-- GNAT RUN-TIME COMPONENTS --
-- --
-- S Y S T E M . O S _ I N T E R F A C E --
-- --
-- S p e c --
-- --
-- Copyright (C) 1991-1994, Florida State University --
--- Copyright (C) 1995-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 1995-2011, Free Software Foundation, Inc. --
-- --
--- GNARL is free software; you can redistribute it and/or modify it under --
+-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
--- ware Foundation; either version 2, or (at your option) any later ver- --
--- sion. GNARL is distributed in the hope that it will be useful, but WITH- --
+-- ware Foundation; either version 3, or (at your option) any later ver- --
+-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT 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 distributed with GNARL; see file COPYING. If not, write --
--- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, --
--- Boston, MA 02110-1301, USA. --
+-- or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
--- As a special exception, if other files instantiate generics from this --
--- unit, or you link this unit with other files to produce an executable, --
--- this unit 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 Public License. --
+-- As a special exception under Section 7 of GPL version 3, you are granted --
+-- additional permissions described in the GCC Runtime Library Exception, --
+-- version 3.1, as published by the Free Software Foundation. --
-- --
--- GNARL was developed by the GNARL team at Florida State University. --
--- Extensive contributions were provided by Ada Core Technologies, Inc. --
+-- You should have received a copy of the GNU General Public License and --
+-- a copy of the GCC Runtime Library Exception along with this program; --
+-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
+-- <http://www.gnu.org/licenses/>. --
+-- --
+-- GNAT was originally developed by the GNAT team at New York University. --
+-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
diff --git a/gcc/ada/s-regpat.adb b/gcc/ada/s-regpat.adb
index ac938be9114..cee229ef6b5 100755
--- a/gcc/ada/s-regpat.adb
+++ b/gcc/ada/s-regpat.adb
@@ -2013,11 +2013,13 @@ package body System.Regpat is
Must_Have_Length => Dummy.Must_Have_Length,
Paren_Count => Dummy.Paren_Count,
Flags => Dummy.Flags,
- Program => Dummy.Program
- (Dummy.Program'First .. Dummy.Program'First + Size - 1));
+ Program =>
+ Dummy.Program
+ (Dummy.Program'First .. Dummy.Program'First + Size - 1));
else
-- We have to recompile now that we know the size
- -- ??? Can we use Ada 05's return construct ?
+ -- ??? Can we use Ada 2005's return construct ?
+
declare
Result : Pattern_Matcher (Size);
begin
diff --git a/gcc/ada/s-rident.ads b/gcc/ada/s-rident.ads
index dd9ef16b22c..1c306e34664 100644
--- a/gcc/ada/s-rident.ads
+++ b/gcc/ada/s-rident.ads
@@ -41,6 +41,8 @@
-- so we can do the instantiation under control of Discard_Names to remove
-- the tables.
+pragma Compiler_Unit;
+
generic
package System.Rident is
pragma Preelaborate;
diff --git a/gcc/ada/s-stopoo.ads b/gcc/ada/s-stopoo.ads
index 1c4d12754a0..e2d66ff747d 100644
--- a/gcc/ada/s-stopoo.ads
+++ b/gcc/ada/s-stopoo.ads
@@ -65,6 +65,14 @@ private
type Root_Storage_Pool is abstract
new Ada.Finalization.Limited_Controlled with null record;
+ type Root_Storage_Pool_Ptr is access all Root_Storage_Pool'Class;
+ for Root_Storage_Pool_Ptr'Storage_Size use 0;
+ -- Type of the BIP_Storage_Pool extra parameter (see Exp_Ch6). The
+ -- Storage_Size clause is necessary, because otherwise we have a
+ -- chicken&egg problem; we can't be creating collection finalization code
+ -- in this low-level package, because that involves Pool_Global, which
+ -- imports this package.
+
-- ??? Are these two still needed? It might be possible to use Subpools.
-- Allocate_Any_Controlled / Deallocate_Any_Controlled for non-controlled
-- objects.
diff --git a/gcc/ada/s-stposu.adb b/gcc/ada/s-stposu.adb
index b8ad53d613b..4bbff767d96 100644
--- a/gcc/ada/s-stposu.adb
+++ b/gcc/ada/s-stposu.adb
@@ -109,6 +109,9 @@ package body System.Storage_Pools.Subpools is
N_Size : Storage_Count;
Subpool : Subpool_Handle := null;
+ Allocation_Locked : Boolean;
+ -- This flag stores the state of the associated collection
+
Header_And_Padding : Storage_Offset;
-- This offset includes the size of a FM_Node plus any additional
-- padding due to a larger alignment.
@@ -156,22 +159,22 @@ package body System.Storage_Pools.Subpools is
-- failed to create one. This is a serious error.
if Context_Master = null then
- raise Program_Error with "missing master in pool allocation";
- end if;
+ raise Program_Error
+ with "missing master in pool allocation";
-- If a subpool is present, then this is the result of erroneous
-- allocator expansion. This is not a serious error, but it should
-- still be detected.
- if Context_Subpool /= null then
- raise Program_Error with "subpool not required in pool allocation";
- end if;
+ elsif Context_Subpool /= null then
+ raise Program_Error
+ with "subpool not required in pool allocation";
-- If the allocation is intended to be on a subpool, but the access
-- type's pool does not support subpools, then this is the result of
-- erroneous end-user code.
- if On_Subpool then
+ elsif On_Subpool then
raise Program_Error
with "pool of access type does not support subpools";
end if;
@@ -187,10 +190,18 @@ package body System.Storage_Pools.Subpools is
if Is_Controlled then
+ -- Synchronization:
+ -- Read - allocation, finalization
+ -- Write - finalization
+
+ Lock_Task.all;
+ Allocation_Locked := Finalization_Started (Master.all);
+ Unlock_Task.all;
+
-- Do not allow the allocation of controlled objects while the
-- associated master is being finalized.
- if Finalization_Started (Master.all) then
+ if Allocation_Locked then
raise Program_Error with "allocation after finalization started";
end if;
@@ -240,6 +251,7 @@ package body System.Storage_Pools.Subpools is
-- Step 4: Attachment
if Is_Controlled then
+ Lock_Task.all;
-- Map the allocated memory into a FM_Node record. This converts the
-- top of the allocated bits into a list header. If there is padding
@@ -262,7 +274,10 @@ package body System.Storage_Pools.Subpools is
-- Prepend the allocated object to the finalization master
- Attach (N_Ptr, Objects (Master.all));
+ -- Synchronization:
+ -- Write - allocation, deallocation, finalization
+
+ Attach_Unprotected (N_Ptr, Objects (Master.all));
-- Move the address from the hidden list header to the start of the
-- object. This operation effectively hides the list header.
@@ -275,8 +290,17 @@ package body System.Storage_Pools.Subpools is
-- 2) Named access types
-- 3) Most cases of anonymous access types usage
+ -- Synchronization:
+ -- Read - allocation, finalization
+ -- Write - outside
+
if Master.Is_Homogeneous then
- Set_Finalize_Address (Master.all, Fin_Address);
+
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - allocation, outside
+
+ Set_Finalize_Address_Unprotected (Master.all, Fin_Address);
-- Heterogeneous masters service the following:
@@ -284,10 +308,16 @@ package body System.Storage_Pools.Subpools is
-- 2) Certain cases of anonymous access types usage
else
- Set_Heterogeneous_Finalize_Address (Addr, Fin_Address);
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - allocation, deallocation
+
+ Set_Heterogeneous_Finalize_Address_Unprotected (Addr, Fin_Address);
Finalize_Address_Table_In_Use := True;
end if;
+ Unlock_Task.all;
+
-- Non-controlled allocation
else
@@ -341,12 +371,18 @@ package body System.Storage_Pools.Subpools is
-- Step 1: Detachment
if Is_Controlled then
+ Lock_Task.all;
-- Destroy the relation pair object - Finalize_Address since it is no
-- longer needed.
if Finalize_Address_Table_In_Use then
- Delete_Finalize_Address (Addr);
+
+ -- Synchronization:
+ -- Read - finalization
+ -- Write - allocation, deallocation
+
+ Delete_Finalize_Address_Unprotected (Addr);
end if;
-- Account for possible padding space before the header due to a
@@ -376,7 +412,10 @@ package body System.Storage_Pools.Subpools is
-- action does not need to know the prior context used during
-- allocation.
- Detach (N_Ptr);
+ -- Synchronization:
+ -- Write - allocation, deallocation, finalization
+
+ Detach_Unprotected (N_Ptr);
-- Move the address from the object to the beginning of the list
-- header.
@@ -388,6 +427,8 @@ package body System.Storage_Pools.Subpools is
N_Size := Storage_Size + Header_And_Padding;
+ Unlock_Task.all;
+
else
N_Addr := Addr;
N_Size := Storage_Size;
diff --git a/gcc/ada/s-taprop-posix.adb b/gcc/ada/s-taprop-posix.adb
index 1dec99966ee..425508a32c2 100644
--- a/gcc/ada/s-taprop-posix.adb
+++ b/gcc/ada/s-taprop-posix.adb
@@ -1089,9 +1089,10 @@ package body System.Task_Primitives.Operations is
Result := pthread_mutex_destroy (S.L'Access);
pragma Assert (Result = 0);
- if Result = ENOMEM then
- raise Storage_Error;
- end if;
+ -- Storage_Error is propagated as intended if the allocation of the
+ -- underlying OS entities fails.
+
+ raise Storage_Error;
end if;
Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
@@ -1101,11 +1102,13 @@ package body System.Task_Primitives.Operations is
Result := pthread_mutex_destroy (S.L'Access);
pragma Assert (Result = 0);
- if Result = ENOMEM then
- Result := pthread_condattr_destroy (Cond_Attr'Access);
- pragma Assert (Result = 0);
- raise Storage_Error;
- end if;
+ Result := pthread_condattr_destroy (Cond_Attr'Access);
+ pragma Assert (Result = 0);
+
+ -- Storage_Error is propagated as intended if the allocation of the
+ -- underlying OS entities fails.
+
+ raise Storage_Error;
end if;
Result := pthread_condattr_destroy (Cond_Attr'Access);
diff --git a/gcc/ada/s-tasren.adb b/gcc/ada/s-tasren.adb
index 4034e61af17..e2541a106fd 100644
--- a/gcc/ada/s-tasren.adb
+++ b/gcc/ada/s-tasren.adb
@@ -1502,7 +1502,7 @@ package body System.Tasking.Rendezvous is
-- Null_Body. Defer abort until it gets into the accept body.
Uninterpreted_Data := Self_Id.Common.Call.Uninterpreted_Data;
- Initialization.Defer_Abort (Self_Id);
+ Initialization.Defer_Abort_Nestable (Self_Id);
STPO.Unlock (Self_Id);
when Accept_Alternative_Completed =>
diff --git a/gcc/ada/sem.adb b/gcc/ada/sem.adb
index be0c907f71a..b463d37a938 100644
--- a/gcc/ada/sem.adb
+++ b/gcc/ada/sem.adb
@@ -845,11 +845,9 @@ package body Sem is
return;
end if;
- -- First search the local entity suppress stack, we search this in
- -- reverse order so that we get the innermost entry that applies to
- -- this case if there are nested entries. Note that for the purpose
- -- of this procedure we are ONLY looking for entries corresponding
- -- to a two-argument Suppress, where the second argument matches From.
+ -- First search the global entity suppress table for a matching entry.
+ -- We also search this in reverse order so that if there are multiple
+ -- pragmas for the same entity, the last one applies.
Search_Stack (Global_Suppress_Stack_Top, Found);
@@ -857,9 +855,11 @@ package body Sem is
return;
end if;
- -- Now search the global entity suppress table for a matching entry.
- -- We also search this in reverse order so that if there are multiple
- -- pragmas for the same entity, the last one applies.
+ -- Now search the local entity suppress stack, we search this in
+ -- reverse order so that we get the innermost entry that applies to
+ -- this case if there are nested entries. Note that for the purpose
+ -- of this procedure we are ONLY looking for entries corresponding
+ -- to a two-argument Suppress, where the second argument matches From.
Search_Stack (Local_Suppress_Stack_Top, Found);
end Copy_Suppress_Status;
@@ -936,7 +936,6 @@ package body Sem is
else
Scop := Scope (E);
-
while Present (Scop) loop
if Scop = Outer_Generic_Scope then
return False;
@@ -966,7 +965,7 @@ package body Sem is
-- of the compiler (in the normal case this loop does nothing).
while Suppress_Stack_Entries /= null loop
- Next := Global_Suppress_Stack_Top.Next;
+ Next := Suppress_Stack_Entries.Next;
Free (Suppress_Stack_Entries);
Suppress_Stack_Entries := Next;
end loop;
diff --git a/gcc/ada/sem_aggr.adb b/gcc/ada/sem_aggr.adb
index f4d2ad8a0a5..011a444cf0d 100644
--- a/gcc/ada/sem_aggr.adb
+++ b/gcc/ada/sem_aggr.adb
@@ -1675,8 +1675,12 @@ package body Sem_Aggr is
-- unless the expression covers a single component, or the
-- expander is inactive.
+ -- In Alfa mode, expressions that can perform side-effects will be
+ -- recognized by the gnat2why back-end, and the whole subprogram
+ -- will be ignored. So semantic analysis can be performed safely.
+
if Single_Elmt
- or else not Expander_Active
+ or else not Full_Expander_Active
or else In_Spec_Expression
then
Analyze_And_Resolve (Expr, Component_Typ);
@@ -3121,6 +3125,13 @@ package body Sem_Aggr is
Expr := New_Copy_Tree (Expression (Parent (Compon)));
+ -- Component may have no default, in which case the
+ -- expression is empty and the component is default-
+ -- initialized, but an association for the component
+ -- exists, and it is not covered by an others clause.
+
+ return Expr;
+
else
if Present (Next (Selector_Name)) then
Expr := New_Copy_Tree (Expression (Assoc));
diff --git a/gcc/ada/sem_attr.adb b/gcc/ada/sem_attr.adb
index caacc45c4d2..ae7edbf9dc2 100644
--- a/gcc/ada/sem_attr.adb
+++ b/gcc/ada/sem_attr.adb
@@ -264,6 +264,10 @@ package body Sem_Attr is
-- If the prefix type is an enumeration type, set all its literals
-- as referenced, since the image function could possibly end up
-- referencing any of the literals indirectly. Same for Enum_Val.
+ -- Set the flag only if the reference is in the main code unit. Same
+ -- restriction when resolving 'Value; otherwise an improperly set
+ -- reference when analyzing an inlined body will lose a proper warning
+ -- on a useless with_clause.
procedure Check_Fixed_Point_Type;
-- Verify that prefix of attribute N is a fixed type
@@ -1225,8 +1229,17 @@ package body Sem_Attr is
procedure Check_Enum_Image is
Lit : Entity_Id;
+
begin
- if Is_Enumeration_Type (P_Base_Type) then
+ -- When an enumeration type appears in an attribute reference, all
+ -- literals of the type are marked as referenced. This must only be
+ -- done if the attribute reference appears in the current source.
+ -- Otherwise the information on references may differ between a
+ -- normal compilation and one that performs inlining.
+
+ if Is_Enumeration_Type (P_Base_Type)
+ and then In_Extended_Main_Code_Unit (N)
+ then
Lit := First_Literal (P_Base_Type);
while Present (Lit) loop
Set_Referenced (Lit);
@@ -5031,7 +5044,15 @@ package body Sem_Attr is
-- Case of enumeration type
- if Is_Enumeration_Type (P_Type) then
+ -- When an enumeration type appears in an attribute reference, all
+ -- literals of the type are marked as referenced. This must only be
+ -- done if the attribute reference appears in the current source.
+ -- Otherwise the information on references may differ between a
+ -- normal compilation and one that performs inlining.
+
+ if Is_Enumeration_Type (P_Type)
+ and then In_Extended_Main_Code_Unit (N)
+ then
Check_Restriction (No_Enumeration_Maps, N);
-- Mark all enumeration literals as referenced, since the use of
diff --git a/gcc/ada/sem_attr.ads b/gcc/ada/sem_attr.ads
index 0e8561ae729..a12d5a70a9e 100644
--- a/gcc/ada/sem_attr.ads
+++ b/gcc/ada/sem_attr.ads
@@ -607,12 +607,12 @@ package Sem_Attr is
(Typ : Entity_Id;
Nam : TSS_Name_Type;
Partial_View : Entity_Id := Empty) return Boolean;
- -- For a limited type Typ, return True iff the given attribute is
- -- available. For Ada 05, availability is defined by 13.13.2(36/1). For Ada
- -- 95, an attribute is considered to be available if it has been specified
- -- using an attribute definition clause for the type, or for its full view,
- -- or for an ancestor of either. Parameter Partial_View is used only
- -- internally, when checking for an attribute definition clause that is not
- -- visible (Ada 95 only).
+ -- For a limited type Typ, return True if and only if the given attribute
+ -- is available. For Ada 2005, availability is defined by 13.13.2(36/1).
+ -- For Ada 95, an attribute is considered to be available if it has been
+ -- specified using an attribute definition clause for the type, or for its
+ -- full view, or for an ancestor of either. Parameter Partial_View is used
+ -- only internally, when checking for an attribute definition clause that
+ -- is not visible (Ada 95 only).
end Sem_Attr;
diff --git a/gcc/ada/sem_ch10.adb b/gcc/ada/sem_ch10.adb
index 17fe12137e3..98a57e2556e 100644
--- a/gcc/ada/sem_ch10.adb
+++ b/gcc/ada/sem_ch10.adb
@@ -208,7 +208,7 @@ package body Sem_Ch10 is
-- Limited_With_Clauses --
--------------------------
- -- Limited_With clauses are the mechanism chosen for Ada 05 to support
+ -- Limited_With clauses are the mechanism chosen for Ada 2005 to support
-- mutually recursive types declared in different units. A limited_with
-- clause that names package P in the context of unit U makes the types
-- declared in the visible part of P available within U, but with the
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb
index 6dd6e7b5589..e62629e2a22 100644
--- a/gcc/ada/sem_ch12.adb
+++ b/gcc/ada/sem_ch12.adb
@@ -29,6 +29,7 @@ with Einfo; use Einfo;
with Elists; use Elists;
with Errout; use Errout;
with Expander; use Expander;
+with Exp_Disp; use Exp_Disp;
with Fname; use Fname;
with Fname.UF; use Fname.UF;
with Freeze; use Freeze;
@@ -399,6 +400,13 @@ package body Sem_Ch12 is
-- package cannot be inlined by the front-end because front-end inlining
-- requires a strict linear order of elaboration.
+ function Check_Hidden_Primitives (Assoc_List : List_Id) return Elist_Id;
+ -- Check if some association between formals and actuals requires to make
+ -- visible primitives of a tagged type, and make those primitives visible.
+ -- Return the list of primitives whose visibility is modified (to restore
+ -- their visibility later through Restore_Hidden_Primitives). If no
+ -- candidate is found then return No_Elist.
+
procedure Check_Hidden_Child_Unit
(N : Node_Id;
Gen_Unit : Entity_Id;
@@ -443,6 +451,12 @@ package body Sem_Ch12 is
-- an instantiation in the source, or the internal instantiation that
-- corresponds to the actual for a formal package.
+ function Earlier (N1, N2 : Node_Id) return Boolean;
+ -- Yields True if N1 and N2 appear in the same compilation unit,
+ -- ignoring subunits, and if N1 is to the left of N2 in a left-to-right
+ -- traversal of the tree for the unit. Used to determine the placement
+ -- of freeze nodes for instance bodies that may depend on other instances.
+
function Find_Actual_Type
(Typ : Entity_Id;
Gen_Type : Entity_Id) return Entity_Id;
@@ -465,9 +479,11 @@ package body Sem_Ch12 is
Inst : Node_Id) return Boolean;
-- True if the instantiation Inst and the given freeze_node F_Node appear
-- within the same declarative part, ignoring subunits, but with no inter-
- -- vening subprograms or concurrent units. If true, the freeze node
- -- of the instance can be placed after the freeze node of the parent,
- -- which it itself an instance.
+ -- vening subprograms or concurrent units. Used to find the proper plave
+ -- for the freeze node of an instance, when the generic is declared in a
+ -- previous instance. If predicate is true, the freeze node of the instance
+ -- can be placed after the freeze node of the previous instance, Otherwise
+ -- it has to be placed at the end of the current declarative part.
function In_Main_Context (E : Entity_Id) return Boolean;
-- Check whether an instantiation is in the context of the main unit.
@@ -556,6 +572,18 @@ package body Sem_Ch12 is
procedure Remove_Parent (In_Body : Boolean := False);
-- Reverse effect after instantiation of child is complete
+ procedure Install_Hidden_Primitives
+ (Prims_List : in out Elist_Id;
+ Gen_T : Entity_Id;
+ Act_T : Entity_Id);
+ -- Remove suffix 'P' from hidden primitives of Act_T to match the
+ -- visibility of primitives of Gen_T. The list of primitives to which
+ -- the suffix is removed is added to Prims_List to restore them later.
+
+ procedure Restore_Hidden_Primitives (Prims_List : in out Elist_Id);
+ -- Restore suffix 'P' to primitives of Prims_List and leave Prims_List
+ -- set to No_Elist.
+
procedure Inline_Instance_Body
(N : Node_Id;
Gen_Unit : Entity_Id;
@@ -709,6 +737,9 @@ package body Sem_Ch12 is
-- before installing parents of generics, that are not visible for the
-- actuals themselves.
+ function True_Parent (N : Node_Id) return Node_Id;
+ -- For a subunit, return parent of corresponding stub
+
procedure Valid_Default_Attribute (Nam : Entity_Id; Def : Node_Id);
-- Verify that an attribute that appears as the default for a formal
-- subprogram is a function or procedure with the correct profile.
@@ -884,7 +915,6 @@ package body Sem_Ch12 is
Formals : List_Id;
F_Copy : List_Id) return List_Id
is
-
Actual_Types : constant Elist_Id := New_Elmt_List;
Assoc : constant List_Id := New_List;
Default_Actuals : constant Elist_Id := New_Elmt_List;
@@ -1565,16 +1595,22 @@ package body Sem_Ch12 is
-- static. For all scalar types we introduce an anonymous base type, with
-- the same attributes. We choose the corresponding integer type to be
-- Standard_Integer.
+ -- Here and in other similar routines, the Sloc of the generated internal
+ -- type must be the same as the sloc of the defining identifier of the
+ -- formal type declaration, to provide proper source navigation.
procedure Analyze_Formal_Decimal_Fixed_Point_Type
(T : Entity_Id;
Def : Node_Id)
is
- Loc : constant Source_Ptr := Sloc (Def);
- Base : constant Entity_Id :=
- New_Internal_Entity
- (E_Decimal_Fixed_Point_Type,
- Current_Scope, Sloc (Def), 'G');
+ Loc : constant Source_Ptr := Sloc (Def);
+
+ Base : constant Entity_Id :=
+ New_Internal_Entity
+ (E_Decimal_Fixed_Point_Type,
+ Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
Int_Base : constant Entity_Id := Standard_Integer;
Delta_Val : constant Ureal := Ureal_1;
Digs_Val : constant Uint := Uint_6;
@@ -1714,7 +1750,9 @@ package body Sem_Ch12 is
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Floating_Point_Type, Current_Scope, Sloc (Def), 'G');
+ (E_Floating_Point_Type, Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
begin
Enter_Name (T);
Set_Ekind (T, E_Enumeration_Subtype);
@@ -1762,7 +1800,8 @@ package body Sem_Ch12 is
procedure Analyze_Formal_Floating_Type (T : Entity_Id; Def : Node_Id) is
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Floating_Point_Type, Current_Scope, Sloc (Def), 'G');
+ (E_Floating_Point_Type, Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
begin
-- The various semantic attributes are taken from the predefined type
@@ -1980,7 +2019,9 @@ package body Sem_Ch12 is
Loc : constant Source_Ptr := Sloc (Def);
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Ordinary_Fixed_Point_Type, Current_Scope, Sloc (Def), 'G');
+ (E_Ordinary_Fixed_Point_Type, Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
+
begin
-- The semantic attributes are set for completeness only, their values
-- will never be used, since all properties of the type are non-static.
@@ -2028,6 +2069,10 @@ package body Sem_Ch12 is
Renaming_In_Par : Entity_Id;
Associations : Boolean := True;
+ Vis_Prims_List : Elist_Id := No_Elist;
+ -- List of primitives made temporarily visible in the instantiation
+ -- to match the visibility of the formal type
+
function Build_Local_Package return Node_Id;
-- The formal package is rewritten so that its parameters are replaced
-- with corresponding declarations. For parameters with bona fide
@@ -2113,9 +2158,11 @@ package body Sem_Ch12 is
Decls :=
Analyze_Associations
- (Original_Node (N),
- Generic_Formal_Declarations (Act_Tree),
- Generic_Formal_Declarations (Gen_Decl));
+ (I_Node => Original_Node (N),
+ Formals => Generic_Formal_Declarations (Act_Tree),
+ F_Copy => Generic_Formal_Declarations (Gen_Decl));
+
+ Vis_Prims_List := Check_Hidden_Primitives (Decls);
end;
end if;
@@ -2252,6 +2299,7 @@ package body Sem_Ch12 is
Enter_Name (Formal);
Set_Ekind (Formal, E_Variable);
Set_Etype (Formal, Any_Type);
+ Restore_Hidden_Primitives (Vis_Prims_List);
if Parent_Installed then
Remove_Parent;
@@ -2325,6 +2373,7 @@ package body Sem_Ch12 is
end;
End_Package_Scope (Formal);
+ Restore_Hidden_Primitives (Vis_Prims_List);
if Parent_Installed then
Remove_Parent;
@@ -2403,7 +2452,9 @@ package body Sem_Ch12 is
is
Base : constant Entity_Id :=
New_Internal_Entity
- (E_Signed_Integer_Type, Current_Scope, Sloc (Def), 'G');
+ (E_Signed_Integer_Type,
+ Current_Scope,
+ Sloc (Defining_Identifier (Parent (Def))), 'G');
begin
Enter_Name (T);
@@ -3118,6 +3169,12 @@ package body Sem_Ch12 is
return False;
end Might_Inline_Subp;
+ -- Local declarations
+
+ Vis_Prims_List : Elist_Id := No_Elist;
+ -- List of primitives made temporarily visible in the instantiation
+ -- to match the visibility of the formal type
+
-- Start of processing for Analyze_Package_Instantiation
begin
@@ -3295,9 +3352,11 @@ package body Sem_Ch12 is
Renaming_List :=
Analyze_Associations
- (N,
- Generic_Formal_Declarations (Act_Tree),
- Generic_Formal_Declarations (Gen_Decl));
+ (I_Node => N,
+ Formals => Generic_Formal_Declarations (Act_Tree),
+ F_Copy => Generic_Formal_Declarations (Gen_Decl));
+
+ Vis_Prims_List := Check_Hidden_Primitives (Renaming_List);
Set_Instance_Env (Gen_Unit, Act_Decl_Id);
Set_Defining_Unit_Name (Act_Spec, Act_Decl_Name);
@@ -3683,6 +3742,7 @@ package body Sem_Ch12 is
Check_Formal_Packages (Act_Decl_Id);
+ Restore_Hidden_Primitives (Vis_Prims_List);
Restore_Private_Views (Act_Decl_Id);
Inherit_Context (Gen_Decl, N);
@@ -4264,6 +4324,12 @@ package body Sem_Ch12 is
end if;
end Analyze_Instance_And_Renamings;
+ -- Local variables
+
+ Vis_Prims_List : Elist_Id := No_Elist;
+ -- List of primitives made temporarily visible in the instantiation
+ -- to match the visibility of the formal type
+
-- Start of processing for Analyze_Subprogram_Instantiation
begin
@@ -4363,6 +4429,7 @@ package body Sem_Ch12 is
Error_Msg_NE
("circular Instantiation: & instantiated in &!", N, Gen_Unit);
Circularity_Detected := True;
+ Restore_Hidden_Primitives (Vis_Prims_List);
goto Leave;
end if;
@@ -4389,9 +4456,11 @@ package body Sem_Ch12 is
Renaming_List :=
Analyze_Associations
- (N,
- Generic_Formal_Declarations (Act_Tree),
- Generic_Formal_Declarations (Gen_Decl));
+ (I_Node => N,
+ Formals => Generic_Formal_Declarations (Act_Tree),
+ F_Copy => Generic_Formal_Declarations (Gen_Decl));
+
+ Vis_Prims_List := Check_Hidden_Primitives (Renaming_List);
-- The subprogram itself cannot contain a nested instance, so the
-- current parent is left empty.
@@ -4541,6 +4610,7 @@ package body Sem_Ch12 is
Remove_Parent;
end if;
+ Restore_Hidden_Primitives (Vis_Prims_List);
Restore_Env;
Env_Installed := False;
Generic_Renamings.Set_Last (0);
@@ -5843,6 +5913,49 @@ package body Sem_Ch12 is
end if;
end Check_Private_View;
+ -----------------------------
+ -- Check_Hidden_Primitives --
+ -----------------------------
+
+ function Check_Hidden_Primitives (Assoc_List : List_Id) return Elist_Id is
+ Actual : Node_Id;
+ Gen_T : Entity_Id;
+ Result : Elist_Id := No_Elist;
+
+ begin
+ if No (Assoc_List) then
+ return No_Elist;
+ end if;
+
+ -- Traverse the list of associations between formals and actuals
+ -- searching for renamings of tagged types
+
+ Actual := First (Assoc_List);
+ while Present (Actual) loop
+ if Nkind (Actual) = N_Subtype_Declaration then
+ Gen_T := Generic_Parent_Type (Actual);
+
+ if Present (Gen_T)
+ and then Is_Tagged_Type (Gen_T)
+ then
+ -- Traverse the list of primitives of the actual types
+ -- searching for hidden primitives that are visible in the
+ -- corresponding generic formal; leave them visible and
+ -- append them to Result to restore their decoration later.
+
+ Install_Hidden_Primitives
+ (Prims_List => Result,
+ Gen_T => Gen_T,
+ Act_T => Entity (Subtype_Indication (Actual)));
+ end if;
+ end if;
+
+ Next (Actual);
+ end loop;
+
+ return Result;
+ end Check_Hidden_Primitives;
+
--------------------------
-- Contains_Instance_Of --
--------------------------
@@ -6660,6 +6773,103 @@ package body Sem_Ch12 is
Expander_Mode_Restore;
end End_Generic;
+ -------------
+ -- Earlier --
+ -------------
+
+ function Earlier (N1, N2 : Node_Id) return Boolean is
+ D1 : Integer := 0;
+ D2 : Integer := 0;
+ P1 : Node_Id := N1;
+ P2 : Node_Id := N2;
+
+ procedure Find_Depth (P : in out Node_Id; D : in out Integer);
+ -- Find distance from given node to enclosing compilation unit
+
+ ----------------
+ -- Find_Depth --
+ ----------------
+
+ procedure Find_Depth (P : in out Node_Id; D : in out Integer) is
+ begin
+ while Present (P)
+ and then Nkind (P) /= N_Compilation_Unit
+ loop
+ P := True_Parent (P);
+ D := D + 1;
+ end loop;
+ end Find_Depth;
+
+ -- Start of processing for Earlier
+
+ begin
+ Find_Depth (P1, D1);
+ Find_Depth (P2, D2);
+
+ if P1 /= P2 then
+ return False;
+ else
+ P1 := N1;
+ P2 := N2;
+ end if;
+
+ while D1 > D2 loop
+ P1 := True_Parent (P1);
+ D1 := D1 - 1;
+ end loop;
+
+ while D2 > D1 loop
+ P2 := True_Parent (P2);
+ D2 := D2 - 1;
+ end loop;
+
+ -- At this point P1 and P2 are at the same distance from the root.
+ -- We examine their parents until we find a common declarative list,
+ -- at which point we can establish their relative placement by
+ -- comparing their ultimate slocs. If we reach the root, N1 and N2
+ -- do not descend from the same declarative list (e.g. one is nested
+ -- in the declarative part and the other is in a block in the
+ -- statement part) and the earlier one is already frozen.
+
+ while not Is_List_Member (P1)
+ or else not Is_List_Member (P2)
+ or else List_Containing (P1) /= List_Containing (P2)
+ loop
+ P1 := True_Parent (P1);
+ P2 := True_Parent (P2);
+
+ if Nkind (Parent (P1)) = N_Subunit then
+ P1 := Corresponding_Stub (Parent (P1));
+ end if;
+
+ if Nkind (Parent (P2)) = N_Subunit then
+ P2 := Corresponding_Stub (Parent (P2));
+ end if;
+
+ if P1 = P2 then
+ return False;
+ end if;
+ end loop;
+
+ -- If the sloc positions are different the result is unambiguous. If
+ -- the slocs are identical, one of them must not come from source, which
+ -- is the case for freeze nodes, whose sloc is unrelated to the point
+ -- point at which they are inserted in the tree. The source node is the
+ -- earlier one in the tree.
+
+ if Top_Level_Location (Sloc (P1)) < Top_Level_Location (Sloc (P2)) then
+ return True;
+
+ elsif
+ Top_Level_Location (Sloc (P1)) > Top_Level_Location (Sloc (P2))
+ then
+ return False;
+
+ else
+ return Comes_From_Source (P1);
+ end if;
+ end Earlier;
+
----------------------
-- Find_Actual_Type --
----------------------
@@ -6726,11 +6936,6 @@ package body Sem_Ch12 is
Enc_I : Node_Id;
F_Node : Node_Id;
- function Earlier (N1, N2 : Node_Id) return Boolean;
- -- Yields True if N1 and N2 appear in the same compilation unit,
- -- ignoring subunits, and if N1 is to the left of N2 in a left-to-right
- -- traversal of the tree for the unit.
-
function Enclosing_Body (N : Node_Id) return Node_Id;
-- Find innermost package body that encloses the given node, and which
-- is not a compilation unit. Freeze nodes for the instance, or for its
@@ -6741,91 +6946,6 @@ package body Sem_Ch12 is
-- Find entity for given package body, and locate or create a freeze
-- node for it.
- function True_Parent (N : Node_Id) return Node_Id;
- -- For a subunit, return parent of corresponding stub
-
- -------------
- -- Earlier --
- -------------
-
- function Earlier (N1, N2 : Node_Id) return Boolean is
- D1 : Integer := 0;
- D2 : Integer := 0;
- P1 : Node_Id := N1;
- P2 : Node_Id := N2;
-
- procedure Find_Depth (P : in out Node_Id; D : in out Integer);
- -- Find distance from given node to enclosing compilation unit
-
- ----------------
- -- Find_Depth --
- ----------------
-
- procedure Find_Depth (P : in out Node_Id; D : in out Integer) is
- begin
- while Present (P)
- and then Nkind (P) /= N_Compilation_Unit
- loop
- P := True_Parent (P);
- D := D + 1;
- end loop;
- end Find_Depth;
-
- -- Start of processing for Earlier
-
- begin
- Find_Depth (P1, D1);
- Find_Depth (P2, D2);
-
- if P1 /= P2 then
- return False;
- else
- P1 := N1;
- P2 := N2;
- end if;
-
- while D1 > D2 loop
- P1 := True_Parent (P1);
- D1 := D1 - 1;
- end loop;
-
- while D2 > D1 loop
- P2 := True_Parent (P2);
- D2 := D2 - 1;
- end loop;
-
- -- At this point P1 and P2 are at the same distance from the root.
- -- We examine their parents until we find a common declarative list,
- -- at which point we can establish their relative placement by
- -- comparing their ultimate slocs. If we reach the root, N1 and N2
- -- do not descend from the same declarative list (e.g. one is nested
- -- in the declarative part and the other is in a block in the
- -- statement part) and the earlier one is already frozen.
-
- while not Is_List_Member (P1)
- or else not Is_List_Member (P2)
- or else List_Containing (P1) /= List_Containing (P2)
- loop
- P1 := True_Parent (P1);
- P2 := True_Parent (P2);
-
- if Nkind (Parent (P1)) = N_Subunit then
- P1 := Corresponding_Stub (Parent (P1));
- end if;
-
- if Nkind (Parent (P2)) = N_Subunit then
- P2 := Corresponding_Stub (Parent (P2));
- end if;
-
- if P1 = P2 then
- return False;
- end if;
- end loop;
-
- return
- Top_Level_Location (Sloc (P1)) < Top_Level_Location (Sloc (P2));
- end Earlier;
-
--------------------
-- Enclosing_Body --
--------------------
@@ -6871,19 +6991,6 @@ package body Sem_Ch12 is
return Freeze_Node (Id);
end Package_Freeze_Node;
- -----------------
- -- True_Parent --
- -----------------
-
- function True_Parent (N : Node_Id) return Node_Id is
- begin
- if Nkind (Parent (N)) = N_Subunit then
- return Parent (Corresponding_Stub (Parent (N)));
- else
- return Parent (N);
- end if;
- end True_Parent;
-
-- Start of processing of Freeze_Subprogram_Body
begin
@@ -7234,6 +7341,7 @@ package body Sem_Ch12 is
elsif Nkind_In (Nod, N_Subprogram_Body,
N_Package_Body,
+ N_Package_Declaration,
N_Task_Body,
N_Protected_Body,
N_Block_Statement)
@@ -7376,12 +7484,91 @@ package body Sem_Ch12 is
Decls : List_Id;
Par_N : Node_Id;
+ function Previous_Instance (Gen : Entity_Id) return Entity_Id;
+ -- Find the local instance, if any, that declares the generic that is
+ -- being instantiated. If present, the freeze node for this instance
+ -- must follow the freeze node for the previous instance.
+
+ -----------------------
+ -- Previous_Instance --
+ -----------------------
+
+ function Previous_Instance (Gen : Entity_Id) return Entity_Id is
+ S : Entity_Id;
+ begin
+ S := Scope (Gen);
+ while Present (S)
+ and then S /= Standard_Standard
+ loop
+ if Is_Generic_Instance (S)
+ and then In_Same_Source_Unit (S, N)
+ then
+ return S;
+ end if;
+ S := Scope (S);
+ end loop;
+ return Empty;
+ end Previous_Instance;
+
begin
if not Is_List_Member (F_Node) then
Decls := List_Containing (N);
Par_N := Parent (Decls);
Decl := N;
+ -- If this is a package instance, check whether the generic is
+ -- declared in a previous instance and the current instance is
+ -- not within the previous one.
+
+ if Present (Generic_Parent (Parent (Inst)))
+ and then Is_In_Main_Unit (N)
+ then
+ declare
+ Par_I : constant Entity_Id :=
+ Previous_Instance (Generic_Parent (Parent (Inst)));
+ Scop : Entity_Id;
+
+ begin
+ if Present (Par_I)
+ and then Earlier (N, Freeze_Node (Par_I))
+ then
+ Scop := Scope (Inst);
+
+ -- If the current instance is within the one that contains
+ -- the generic, the freeze node for the current one must
+ -- appear in the current declarative part. Ditto, if the
+ -- current instance is within another package instance. In
+ -- both of these cases the freeze node of the previous
+ -- instance is not relevant.
+
+ while Present (Scop)
+ and then Scop /= Standard_Standard
+ loop
+ exit when Scop = Par_I
+ or else Is_Generic_Instance (Scop);
+ Scop := Scope (Scop);
+ end loop;
+
+ if Scop = Par_I then
+
+ -- Previous instance encloses current instance
+
+ null;
+
+ elsif Is_Generic_Instance (Scop) then
+
+ -- Current instance is within an unrelated instance
+
+ null;
+
+ else
+ Insert_After (Freeze_Node (Par_I), F_Node);
+ return;
+ end if;
+ end if;
+ end;
+ end if;
+
-- When the instantiation occurs in a package declaration, append the
-- freeze node to the private declarations (if any).
@@ -7398,9 +7585,9 @@ package body Sem_Ch12 is
-- adhere to the general rule of a package or subprogram body causing
-- freezing of anything before it in the same declarative region. In
-- this case, the proper freeze point of a package instantiation is
- -- before the first source body which follows. This ensures that
- -- entities coming from the instance are already frozen and usable
- -- in source bodies.
+ -- before the first source body which follows, or before a stub.
+ -- This ensures that entities coming from the instance are already
+ -- frozen and usable in source bodies.
if Nkind (Par_N) /= N_Package_Declaration
and then Ekind (Inst) = E_Package
@@ -7409,7 +7596,9 @@ package body Sem_Ch12 is
not In_Same_Source_Unit (Generic_Parent (Parent (Inst)), Inst)
then
while Present (Decl) loop
- if Nkind_In (Decl, N_Package_Body, N_Subprogram_Body)
+ if (Nkind (Decl) in N_Unit_Body
+ or else
+ Nkind (Decl) in N_Body_Stub)
and then Comes_From_Source (Decl)
then
Insert_Before (Decl, F_Node);
@@ -7423,6 +7612,7 @@ package body Sem_Ch12 is
-- In a package declaration, or if no previous body, insert at end
-- of list.
+ Set_Sloc (F_Node, Sloc (Last (Decls)));
Insert_After (Last (Decls), F_Node);
end if;
end Insert_Freeze_Node_For_Instance;
@@ -7880,6 +8070,140 @@ package body Sem_Ch12 is
end if;
end Install_Parent;
+ -------------------------------
+ -- Install_Hidden_Primitives --
+ -------------------------------
+
+ procedure Install_Hidden_Primitives
+ (Prims_List : in out Elist_Id;
+ Gen_T : Entity_Id;
+ Act_T : Entity_Id)
+ is
+ Elmt : Elmt_Id;
+ List : Elist_Id := No_Elist;
+ Prim_G_Elmt : Elmt_Id;
+ Prim_A_Elmt : Elmt_Id;
+ Prim_G : Node_Id;
+ Prim_A : Node_Id;
+
+ begin
+ -- No action needed in case of serious errors because we cannot trust
+ -- in the order of primitives
+
+ if Serious_Errors_Detected > 0 then
+ return;
+
+ -- No action possible if we don't have available the list of primitive
+ -- operations
+
+ elsif No (Gen_T)
+ or else not Is_Record_Type (Gen_T)
+ or else not Is_Tagged_Type (Gen_T)
+ or else not Is_Record_Type (Act_T)
+ or else not Is_Tagged_Type (Act_T)
+ then
+ return;
+
+ -- There is no need to handle interface types since their primitives
+ -- cannot be hidden
+
+ elsif Is_Interface (Gen_T) then
+ return;
+ end if;
+
+ Prim_G_Elmt := First_Elmt (Primitive_Operations (Gen_T));
+
+ if not Is_Class_Wide_Type (Act_T) then
+ Prim_A_Elmt := First_Elmt (Primitive_Operations (Act_T));
+ else
+ Prim_A_Elmt := First_Elmt (Primitive_Operations (Root_Type (Act_T)));
+ end if;
+
+ loop
+ -- Skip predefined primitives in the generic formal
+
+ while Present (Prim_G_Elmt)
+ and then Is_Predefined_Dispatching_Operation (Node (Prim_G_Elmt))
+ loop
+ Next_Elmt (Prim_G_Elmt);
+ end loop;
+
+ -- Skip predefined primitives in the generic actual
+
+ while Present (Prim_A_Elmt)
+ and then Is_Predefined_Dispatching_Operation (Node (Prim_A_Elmt))
+ loop
+ Next_Elmt (Prim_A_Elmt);
+ end loop;
+
+ exit when No (Prim_G_Elmt) or else No (Prim_A_Elmt);
+
+ Prim_G := Node (Prim_G_Elmt);
+ Prim_A := Node (Prim_A_Elmt);
+
+ -- There is no need to handle interface primitives because their
+ -- primitives are not hidden
+
+ exit when Present (Interface_Alias (Prim_G));
+
+ -- Here we install one hidden primitive
+
+ if Chars (Prim_G) /= Chars (Prim_A)
+ and then Has_Suffix (Prim_A, 'P')
+ and then Remove_Suffix (Prim_A, 'P') = Chars (Prim_G)
+ then
+ Set_Chars (Prim_A, Chars (Prim_G));
+
+ if List = No_Elist then
+ List := New_Elmt_List;
+ end if;
+
+ Append_Elmt (Prim_A, List);
+ end if;
+
+ Next_Elmt (Prim_A_Elmt);
+ Next_Elmt (Prim_G_Elmt);
+ end loop;
+
+ -- Append the elements to the list of temporarily visible primitives
+ -- avoiding duplicates.
+
+ if Present (List) then
+ if No (Prims_List) then
+ Prims_List := New_Elmt_List;
+ end if;
+
+ Elmt := First_Elmt (List);
+ while Present (Elmt) loop
+ Append_Unique_Elmt (Node (Elmt), Prims_List);
+ Next_Elmt (Elmt);
+ end loop;
+ end if;
+ end Install_Hidden_Primitives;
+
+ -------------------------------
+ -- Restore_Hidden_Primitives --
+ -------------------------------
+
+ procedure Restore_Hidden_Primitives (Prims_List : in out Elist_Id) is
+ Prim_Elmt : Elmt_Id;
+ Prim : Node_Id;
+
+ begin
+ if Prims_List /= No_Elist then
+ Prim_Elmt := First_Elmt (Prims_List);
+
+ while Present (Prim_Elmt) loop
+ Prim := Node (Prim_Elmt);
+ Set_Chars (Prim, Add_Suffix (Prim, 'P'));
+
+ Next_Elmt (Prim_Elmt);
+ end loop;
+
+ Prims_List := No_Elist;
+ end if;
+ end Restore_Hidden_Primitives;
+
--------------------------------
-- Instantiate_Formal_Package --
--------------------------------
@@ -9052,6 +9376,10 @@ package body Sem_Ch12 is
Par_Ent : Entity_Id := Empty;
Par_Vis : Boolean := False;
+ Vis_Prims_List : Elist_Id := No_Elist;
+ -- List of primitives made temporarily visible in the instantiation
+ -- to match the visibility of the formal type
+
begin
Gen_Body_Id := Corresponding_Body (Gen_Decl);
@@ -9121,6 +9449,29 @@ package body Sem_Ch12 is
Set_Corresponding_Spec (Act_Body, Act_Decl_Id);
Check_Generic_Actuals (Act_Decl_Id, False);
+ -- Install primitives hidden at the point of the instantiation but
+ -- visible when processing the generic formals
+
+ declare
+ E : Entity_Id;
+
+ begin
+ E := First_Entity (Act_Decl_Id);
+ while Present (E) loop
+ if Is_Type (E)
+ and then Is_Generic_Actual_Type (E)
+ and then Is_Tagged_Type (E)
+ then
+ Install_Hidden_Primitives
+ (Prims_List => Vis_Prims_List,
+ Gen_T => Generic_Parent_Type (Parent (E)),
+ Act_T => E);
+ end if;
+
+ Next_Entity (E);
+ end loop;
+ end;
+
-- If it is a child unit, make the parent instance (which is an
-- instance of the parent of the generic) visible. The parent
-- instance is the prefix of the name of the generic unit.
@@ -9213,6 +9564,7 @@ package body Sem_Ch12 is
Set_Is_Immediately_Visible (Par_Ent, Par_Vis);
end if;
+ Restore_Hidden_Primitives (Vis_Prims_List);
Restore_Private_Views (Act_Decl_Id);
-- Remove the current unit from visibility if this is an instance
@@ -12913,6 +13265,19 @@ package body Sem_Ch12 is
end loop;
end Switch_View;
+ -----------------
+ -- True_Parent --
+ -----------------
+
+ function True_Parent (N : Node_Id) return Node_Id is
+ begin
+ if Nkind (Parent (N)) = N_Subunit then
+ return Parent (Corresponding_Stub (Parent (N)));
+ else
+ return Parent (N);
+ end if;
+ end True_Parent;
+
-----------------------------
-- Valid_Default_Attribute --
-----------------------------
diff --git a/gcc/ada/sem_ch13.adb b/gcc/ada/sem_ch13.adb
index 0895eb68652..d30ba09635d 100644
--- a/gcc/ada/sem_ch13.adb
+++ b/gcc/ada/sem_ch13.adb
@@ -1403,7 +1403,10 @@ package body Sem_Ch13 is
Comp_Expr := First (Expressions (Expr));
while Present (Comp_Expr) loop
- Append (Relocate_Node (Comp_Expr), Args);
+ Append
+ (Make_Pragma_Argument_Association (Sloc (Comp_Expr),
+ Expression => Relocate_Node (Comp_Expr)),
+ Args);
Next (Comp_Expr);
end loop;
@@ -3365,10 +3368,22 @@ package body Sem_Ch13 is
-- No statements other than code statements, pragmas, and labels.
-- Again we allow certain internally generated statements.
+ -- In Ada 2012, qualified expressions are names, and the code
+ -- statement is initially parsed as a procedure call.
+
Stmt := First (Statements (HSS));
while Present (Stmt) loop
StmtO := Original_Node (Stmt);
- if Comes_From_Source (StmtO)
+
+ -- A procedure call transformed into a code statement is OK.
+
+ if Ada_Version >= Ada_2012
+ and then Nkind (StmtO) = N_Procedure_Call_Statement
+ and then Nkind (Name (StmtO)) = N_Qualified_Expression
+ then
+ null;
+
+ elsif Comes_From_Source (StmtO)
and then not Nkind_In (StmtO, N_Pragma,
N_Label,
N_Code_Statement)
diff --git a/gcc/ada/sem_ch3.adb b/gcc/ada/sem_ch3.adb
index fe4488b483e..488e6dc98cc 100644
--- a/gcc/ada/sem_ch3.adb
+++ b/gcc/ada/sem_ch3.adb
@@ -706,11 +706,9 @@ package body Sem_Ch3 is
(Related_Nod : Node_Id;
N : Node_Id) return Entity_Id
is
- Loc : constant Source_Ptr := Sloc (Related_Nod);
Anon_Type : Entity_Id;
Anon_Scope : Entity_Id;
Desig_Type : Entity_Id;
- Decl : Entity_Id;
Enclosing_Prot_Type : Entity_Id := Empty;
begin
@@ -889,7 +887,7 @@ package body Sem_Ch3 is
-- proper Master for the created tasks.
if Nkind (Related_Nod) = N_Object_Declaration
- and then Expander_Active
+ and then Expander_Active
then
if Is_Interface (Desig_Type)
and then Is_Limited_Record (Desig_Type)
@@ -901,28 +899,9 @@ package body Sem_Ch3 is
elsif Has_Task (Desig_Type)
and then Comes_From_Source (Related_Nod)
- and then not Restriction_Active (No_Task_Hierarchy)
then
- if not Has_Master_Entity (Current_Scope) then
- Decl :=
- Make_Object_Declaration (Loc,
- Defining_Identifier =>
- Make_Defining_Identifier (Loc, Name_uMaster),
- Constant_Present => True,
- Object_Definition =>
- New_Reference_To (RTE (RE_Master_Id), Loc),
- Expression =>
- Make_Explicit_Dereference (Loc,
- New_Reference_To (RTE (RE_Current_Master), Loc)));
-
- Insert_Before (Related_Nod, Decl);
- Analyze (Decl);
-
- Set_Master_Id (Anon_Type, Defining_Identifier (Decl));
- Set_Has_Master_Entity (Current_Scope);
- else
- Build_Master_Renaming (Related_Nod, Anon_Type);
- end if;
+ Build_Master_Entity (Defining_Identifier (Related_Nod));
+ Build_Master_Renaming (Anon_Type);
end if;
end if;
@@ -13339,18 +13318,18 @@ package body Sem_Ch3 is
-- Check for case of a derived subprogram for the instantiation of a
-- formal derived tagged type, if so mark the subprogram as dispatching
- -- and inherit the dispatching attributes of the parent subprogram. The
+ -- and inherit the dispatching attributes of the actual subprogram. The
-- derived subprogram is effectively renaming of the actual subprogram,
-- so it needs to have the same attributes as the actual.
if Present (Actual_Subp)
- and then Is_Dispatching_Operation (Parent_Subp)
+ and then Is_Dispatching_Operation (Actual_Subp)
then
Set_Is_Dispatching_Operation (New_Subp);
- if Present (DTC_Entity (Parent_Subp)) then
- Set_DTC_Entity (New_Subp, DTC_Entity (Parent_Subp));
- Set_DT_Position (New_Subp, DT_Position (Parent_Subp));
+ if Present (DTC_Entity (Actual_Subp)) then
+ Set_DTC_Entity (New_Subp, DTC_Entity (Actual_Subp));
+ Set_DT_Position (New_Subp, DT_Position (Actual_Subp));
end if;
end if;
@@ -16199,13 +16178,6 @@ package body Sem_Ch3 is
elsif not Comes_From_Source (Original_Comp) then
return True;
- -- If we are in the body of an instantiation, the component is visible
- -- even when the parent type (possibly defined in an enclosing unit or
- -- in a parent unit) might not.
-
- elsif In_Instance_Body then
- return True;
-
-- Discriminants are always visible
elsif Ekind (Original_Comp) = E_Discriminant
@@ -16213,6 +16185,35 @@ package body Sem_Ch3 is
then
return True;
+ -- If we are in the body of an instantiation, the component is visible
+ -- if the parent type is non-private, or in an enclosing scope. The
+ -- scope stack is not present when analyzing an instance body, so we
+ -- must inspect the chain of scopes explicitly.
+
+ elsif In_Instance_Body then
+ if not Is_Private_Type (Scope (C)) then
+ return True;
+
+ else
+ declare
+ S : Entity_Id;
+
+ begin
+ S := Current_Scope;
+ while Present (S)
+ and then S /= Standard_Standard
+ loop
+ if S = Type_Scope then
+ return True;
+ end if;
+
+ S := Scope (S);
+ end loop;
+
+ return False;
+ end;
+ end if;
+
-- If the component has been declared in an ancestor which is currently
-- a private type, then it is not visible. The same applies if the
-- component's containing type is not in an open scope and the original
@@ -16909,6 +16910,36 @@ package body Sem_Ch3 is
when N_Attribute_Reference =>
return Attribute_Name (Original_Node (Exp)) = Name_Input;
+ -- For a conditional expression, all dependent expressions must be
+ -- legal constructs.
+
+ when N_Conditional_Expression =>
+ declare
+ Then_Expr : constant Node_Id :=
+ Next (First (Expressions (Original_Node (Exp))));
+ Else_Expr : constant Node_Id := Next (Then_Expr);
+ begin
+ return OK_For_Limited_Init_In_05 (Typ, Then_Expr)
+ and then OK_For_Limited_Init_In_05 (Typ, Else_Expr);
+ end;
+
+ when N_Case_Expression =>
+ declare
+ Alt : Node_Id;
+
+ begin
+ Alt := First (Alternatives (Original_Node (Exp)));
+ while Present (Alt) loop
+ if not OK_For_Limited_Init_In_05 (Typ, Expression (Alt)) then
+ return False;
+ end if;
+
+ Next (Alt);
+ end loop;
+
+ return True;
+ end;
+
when others =>
return False;
end case;
@@ -19561,17 +19592,16 @@ package body Sem_Ch3 is
-- do not know the exact end points at the time of the declaration. This
-- is true for three reasons:
- -- A size clause may affect the fudging of the end-points
- -- A small clause may affect the values of the end-points
- -- We try to include the end-points if it does not affect the size
+ -- A size clause may affect the fudging of the end-points.
+ -- A small clause may affect the values of the end-points.
+ -- We try to include the end-points if it does not affect the size.
- -- This means that the actual end-points must be established at the point
- -- when the type is frozen. Meanwhile, we first narrow the range as
- -- permitted (so that it will fit if necessary in a small specified size),
- -- and then build a range subtree with these narrowed bounds.
-
- -- Set_Fixed_Range constructs the range from real literal values, and sets
- -- the range as the Scalar_Range of the given fixed-point type entity.
+ -- This means that the actual end-points must be established at the
+ -- point when the type is frozen. Meanwhile, we first narrow the range
+ -- as permitted (so that it will fit if necessary in a small specified
+ -- size), and then build a range subtree with these narrowed bounds.
+ -- Set_Fixed_Range constructs the range from real literal values, and
+ -- sets the range as the Scalar_Range of the given fixed-point type entity.
-- The parent of this range is set to point to the entity so that it is
-- properly hooked into the tree (unlike normal Scalar_Range entries for
@@ -19596,6 +19626,12 @@ package body Sem_Ch3 is
begin
Set_Scalar_Range (E, S);
Set_Parent (S, E);
+
+ -- Before the freeze point, the bounds of a fixed point are universal
+ -- and carry the corresponding type.
+
+ Set_Etype (Low_Bound (S), Universal_Real);
+ Set_Etype (High_Bound (S), Universal_Real);
end Set_Fixed_Range;
----------------------------------
diff --git a/gcc/ada/sem_ch4.adb b/gcc/ada/sem_ch4.adb
index 7f54ba517d6..efc76f11398 100644
--- a/gcc/ada/sem_ch4.adb
+++ b/gcc/ada/sem_ch4.adb
@@ -3114,63 +3114,61 @@ package body Sem_Ch4 is
if Present (Next_Actual (Act2)) then
return;
+ end if;
- elsif Op_Name = Name_Op_Add
- or else Op_Name = Name_Op_Subtract
- or else Op_Name = Name_Op_Multiply
- or else Op_Name = Name_Op_Divide
- or else Op_Name = Name_Op_Mod
- or else Op_Name = Name_Op_Rem
- or else Op_Name = Name_Op_Expon
- then
- Find_Arithmetic_Types (Act1, Act2, Op_Id, N);
+ -- Otherwise action depends on operator
- elsif Op_Name = Name_Op_And
- or else Op_Name = Name_Op_Or
- or else Op_Name = Name_Op_Xor
- then
- Find_Boolean_Types (Act1, Act2, Op_Id, N);
+ case Op_Name is
+ when Name_Op_Add |
+ Name_Op_Subtract |
+ Name_Op_Multiply |
+ Name_Op_Divide |
+ Name_Op_Mod |
+ Name_Op_Rem |
+ Name_Op_Expon =>
+ Find_Arithmetic_Types (Act1, Act2, Op_Id, N);
- elsif Op_Name = Name_Op_Lt
- or else Op_Name = Name_Op_Le
- or else Op_Name = Name_Op_Gt
- or else Op_Name = Name_Op_Ge
- then
- Find_Comparison_Types (Act1, Act2, Op_Id, N);
+ when Name_Op_And |
+ Name_Op_Or |
+ Name_Op_Xor =>
+ Find_Boolean_Types (Act1, Act2, Op_Id, N);
- elsif Op_Name = Name_Op_Eq
- or else Op_Name = Name_Op_Ne
- then
- Find_Equality_Types (Act1, Act2, Op_Id, N);
+ when Name_Op_Lt |
+ Name_Op_Le |
+ Name_Op_Gt |
+ Name_Op_Ge =>
+ Find_Comparison_Types (Act1, Act2, Op_Id, N);
- elsif Op_Name = Name_Op_Concat then
- Find_Concatenation_Types (Act1, Act2, Op_Id, N);
+ when Name_Op_Eq |
+ Name_Op_Ne =>
+ Find_Equality_Types (Act1, Act2, Op_Id, N);
- -- Is this else null correct, or should it be an abort???
+ when Name_Op_Concat =>
+ Find_Concatenation_Types (Act1, Act2, Op_Id, N);
- else
- null;
- end if;
+ -- Is this when others, or should it be an abort???
+
+ when others =>
+ null;
+ end case;
-- Unary operator case
else
- if Op_Name = Name_Op_Subtract or else
- Op_Name = Name_Op_Add or else
- Op_Name = Name_Op_Abs
- then
- Find_Unary_Types (Act1, Op_Id, N);
+ case Op_Name is
+ when Name_Op_Subtract |
+ Name_Op_Add |
+ Name_Op_Abs =>
+ Find_Unary_Types (Act1, Op_Id, N);
- elsif
- Op_Name = Name_Op_Not
- then
- Find_Negation_Types (Act1, Op_Id, N);
+ when Name_Op_Not =>
+ Find_Negation_Types (Act1, Op_Id, N);
- -- Is this else null correct, or should it be an abort???
+ -- Is this when others correct, or should it be an abort???
- else
- null;
- end if;
+ when others =>
+ null;
+ end case;
end if;
end Analyze_Operator_Call;
@@ -3434,8 +3432,8 @@ package body Sem_Ch4 is
-- of the high bound.
procedure Check_Universal_Expression (N : Node_Id);
- -- In Ada 83, reject bounds of a universal range that are not
- -- literals or entity names.
+ -- In Ada83, reject bounds of a universal range that are not literals or
+ -- entity names.
-----------------------
-- Check_Common_Type --
@@ -5548,9 +5546,15 @@ package body Sem_Ch4 is
end if;
if T1 /= Standard_Void_Type
- and then not Is_Limited_Type (T1)
- and then not Is_Limited_Composite (T1)
and then Has_Compatible_Type (R, T1)
+ and then
+ ((not Is_Limited_Type (T1)
+ and then not Is_Limited_Composite (T1))
+
+ or else
+ (Is_Array_Type (T1)
+ and then not Is_Limited_Type (Component_Type (T1))
+ and then Available_Full_View_Of_Component (T1)))
then
if Found
and then Base_Type (T1) /= Base_Type (T_F)
@@ -6428,7 +6432,7 @@ package body Sem_Ch4 is
begin
- -- Check whether type has a specified indexing aspect.
+ -- Check whether type has a specified indexing aspect
Func_Name := Empty;
Is_Var := False;
@@ -6437,7 +6441,7 @@ package body Sem_Ch4 is
while Present (Ritem) loop
if Nkind (Ritem) = N_Aspect_Specification then
- -- Prefer Variable_Indexing, but will settle for Constant.
+ -- Prefer Variable_Indexing, but will settle for Constant
if Get_Aspect_Id (Chars (Identifier (Ritem))) =
Aspect_Constant_Indexing
@@ -6523,7 +6527,7 @@ package body Sem_Ch4 is
if Success then
Set_Etype (Name (N), It.Typ);
- -- Add implicit dereference interpretation.
+ -- Add implicit dereference interpretation
Disc := First_Discriminant (Etype (It.Nam));
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 2fc3b96670d..3dbf782b60b 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -78,6 +78,7 @@ with Snames; use Snames;
with Stringt; use Stringt;
with Style;
with Stylesw; use Stylesw;
+with Targparm; use Targparm;
with Tbuild; use Tbuild;
with Uintp; use Uintp;
with Urealp; use Urealp;
@@ -387,9 +388,9 @@ package body Sem_Ch6 is
begin
Analyze (P);
- -- A call of the form A.B (X) may be an Ada 05 call, which is rewritten
- -- as B (A, X). If the rewriting is successful, the call has been
- -- analyzed and we just return.
+ -- A call of the form A.B (X) may be an Ada 2005 call, which is
+ -- rewritten as B (A, X). If the rewriting is successful, the call
+ -- has been analyzed and we just return.
if Nkind (P) = N_Selected_Component
and then Name (N) /= P
@@ -1340,6 +1341,15 @@ package body Sem_Ch6 is
Analyze (P);
Analyze_Call_And_Resolve;
+ -- In Ada 2012. a qualified expression is a name, but it cannot be a
+ -- procedure name, so the construct can only be a qualified expression.
+
+ elsif Nkind (P) = N_Qualified_Expression
+ and then Ada_Version >= Ada_2012
+ then
+ Rewrite (N, Make_Code_Statement (Loc, Expression => P));
+ Analyze (N);
+
-- Anything else is an error
else
@@ -6451,6 +6461,8 @@ package body Sem_Ch6 is
if Ada_Version >= Ada_2005 and then Is_Build_In_Place_Function (E) then
declare
Result_Subt : constant Entity_Id := Etype (E);
+ Full_Subt : constant Entity_Id := Available_View (Result_Subt);
+ Formal_Typ : Entity_Id;
Discard : Entity_Id;
pragma Warnings (Off, Discard);
@@ -6473,6 +6485,19 @@ package body Sem_Ch6 is
Add_Extra_Formal
(E, Standard_Natural,
E, BIP_Formal_Suffix (BIP_Alloc_Form));
+
+ -- Add BIP_Storage_Pool, in case BIP_Alloc_Form indicates to
+ -- use a user-defined pool. This formal is not added on
+ -- .NET/JVM/ZFP as those targets do not support pools.
+
+ if VM_Target = No_VM
+ and then RTE_Available (RE_Root_Storage_Pool_Ptr)
+ then
+ Discard :=
+ Add_Extra_Formal
+ (E, RTE (RE_Root_Storage_Pool_Ptr),
+ E, BIP_Formal_Suffix (BIP_Storage_Pool));
+ end if;
end if;
-- In the case of functions whose result type needs finalization,
@@ -6489,11 +6514,11 @@ package body Sem_Ch6 is
-- master of the tasks to be created, and the caller's activation
-- chain.
- if Has_Task (Available_View (Result_Subt)) then
+ if Has_Task (Full_Subt) then
Discard :=
Add_Extra_Formal
(E, RTE (RE_Master_Id),
- E, BIP_Formal_Suffix (BIP_Master));
+ E, BIP_Formal_Suffix (BIP_Task_Master));
Discard :=
Add_Extra_Formal
(E, RTE (RE_Activation_Chain_Access),
@@ -6503,31 +6528,27 @@ package body Sem_Ch6 is
-- All build-in-place functions get an extra formal that will be
-- passed the address of the return object within the caller.
- declare
- Formal_Type : constant Entity_Id :=
- Create_Itype
- (E_Anonymous_Access_Type, E,
- Scope_Id => Scope (E));
- begin
- Set_Directly_Designated_Type (Formal_Type, Result_Subt);
- Set_Etype (Formal_Type, Formal_Type);
- Set_Depends_On_Private
- (Formal_Type, Has_Private_Component (Formal_Type));
- Set_Is_Public (Formal_Type, Is_Public (Scope (Formal_Type)));
- Set_Is_Access_Constant (Formal_Type, False);
+ Formal_Typ :=
+ Create_Itype (E_Anonymous_Access_Type, E, Scope_Id => Scope (E));
- -- Ada 2005 (AI-50217): Propagate the attribute that indicates
- -- the designated type comes from the limited view (for
- -- back-end purposes).
+ Set_Directly_Designated_Type (Formal_Typ, Result_Subt);
+ Set_Etype (Formal_Typ, Formal_Typ);
+ Set_Depends_On_Private
+ (Formal_Typ, Has_Private_Component (Formal_Typ));
+ Set_Is_Public (Formal_Typ, Is_Public (Scope (Formal_Typ)));
+ Set_Is_Access_Constant (Formal_Typ, False);
- Set_From_With_Type (Formal_Type, From_With_Type (Result_Subt));
+ -- Ada 2005 (AI-50217): Propagate the attribute that indicates
+ -- the designated type comes from the limited view (for back-end
+ -- purposes).
- Layout_Type (Formal_Type);
+ Set_From_With_Type (Formal_Typ, From_With_Type (Result_Subt));
- Discard :=
- Add_Extra_Formal
- (E, Formal_Type, E, BIP_Formal_Suffix (BIP_Object_Access));
- end;
+ Layout_Type (Formal_Typ);
+
+ Discard :=
+ Add_Extra_Formal
+ (E, Formal_Typ, E, BIP_Formal_Suffix (BIP_Object_Access));
end;
end if;
end Create_Extra_Formals;
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index 6c561dafc71..17f802fc14e 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -2398,7 +2398,14 @@ package body Sem_Ch8 is
elsif not Is_Entity_Name (Nam)
or else not Is_Overloadable (Entity (Nam))
then
- Error_Msg_N ("expect valid subprogram name in renaming", N);
+ -- Do not mention the renaming if it comes from an instance
+
+ if not Is_Actual then
+ Error_Msg_N ("expect valid subprogram name in renaming", N);
+ else
+ Error_Msg_NE ("no visible subprogram for formal&", N, Nam);
+ end if;
+
return;
end if;
diff --git a/gcc/ada/sem_ch9.adb b/gcc/ada/sem_ch9.adb
index b4a4c456dc5..4b284cd9599 100644
--- a/gcc/ada/sem_ch9.adb
+++ b/gcc/ada/sem_ch9.adb
@@ -1163,7 +1163,12 @@ package body Sem_Ch9 is
begin
if No_Run_Time_Mode then
Error_Msg_CRT ("protected type", N);
- goto Leave;
+
+ if Has_Aspects (N) then
+ Analyze_Aspect_Specifications (N, Def_Id);
+ end if;
+
+ return;
end if;
Tasking_Used := True;
@@ -1205,6 +1210,13 @@ package body Sem_Ch9 is
Set_Is_Constrained (T, not Has_Discriminants (T));
+ -- If aspects are present, analyze them now. They can make references
+ -- to the discriminants of the type, but not to any components.
+
+ if Has_Aspects (N) then
+ Analyze_Aspect_Specifications (N, Def_Id);
+ end if;
+
Analyze (Protected_Definition (N));
-- In the case where the protected type is declared at a nested level
@@ -1287,11 +1299,6 @@ package body Sem_Ch9 is
Process_Full_View (N, T, Def_Id);
end if;
end if;
-
- <<Leave>>
- if Has_Aspects (N) then
- Analyze_Aspect_Specifications (N, Def_Id);
- end if;
end Analyze_Protected_Type_Declaration;
---------------------
@@ -2046,6 +2053,10 @@ package body Sem_Ch9 is
Set_Is_Constrained (T, not Has_Discriminants (T));
+ if Has_Aspects (N) then
+ Analyze_Aspect_Specifications (N, Def_Id);
+ end if;
+
if Present (Task_Definition (N)) then
Analyze_Task_Definition (Task_Definition (N));
end if;
@@ -2100,10 +2111,6 @@ package body Sem_Ch9 is
Process_Full_View (N, T, Def_Id);
end if;
end if;
-
- if Has_Aspects (N) then
- Analyze_Aspect_Specifications (N, Def_Id);
- end if;
end Analyze_Task_Type_Declaration;
-----------------------------------
diff --git a/gcc/ada/sem_disp.adb b/gcc/ada/sem_disp.adb
index 2d80676791c..c4dd8ede6ba 100644
--- a/gcc/ada/sem_disp.adb
+++ b/gcc/ada/sem_disp.adb
@@ -160,7 +160,7 @@ package body Sem_Disp is
while Present (Elmt) loop
Iface_Prim := Node (Elmt);
- if Chars (E) = Chars (Prim)
+ if Chars (Iface) = Chars (Prim)
and then Is_Interface_Conformant
(Tagged_Type, Iface_Prim, Prim)
then
diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
index 5be584307af..64db8d634b6 100644
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -250,27 +250,32 @@ package body Sem_Eval is
and not Range_Checks_Suppressed (T);
begin
- -- Ignore cases of non-scalar types or error types
+ -- Ignore cases of non-scalar types, error types, or universal real
+ -- types that have no usable bounds.
- if T = Any_Type or else not Is_Scalar_Type (T) then
+ if T = Any_Type
+ or else not Is_Scalar_Type (T)
+ or else T = Universal_Fixed
+ or else T = Universal_Real
+ then
return;
end if;
- -- At this stage we have a scalar type. If we have an expression
- -- that raises CE, then we already issued a warning or error msg
- -- so there is nothing more to be done in this routine.
+ -- At this stage we have a scalar type. If we have an expression that
+ -- raises CE, then we already issued a warning or error msg so there
+ -- is nothing more to be done in this routine.
if Raises_Constraint_Error (N) then
return;
end if;
- -- Now we have a scalar type which is not marked as raising a
- -- constraint error exception. The main purpose of this routine
- -- is to deal with static expressions appearing in a non-static
- -- context. That means that if we do not have a static expression
- -- then there is not much to do. The one case that we deal with
- -- here is that if we have a floating-point value that is out of
- -- range, then we post a warning that an infinity will result.
+ -- Now we have a scalar type which is not marked as raising a constraint
+ -- error exception. The main purpose of this routine is to deal with
+ -- static expressions appearing in a non-static context. That means
+ -- that if we do not have a static expression then there is not much
+ -- to do. The one case that we deal with here is that if we have a
+ -- floating-point value that is out of range, then we post a warning
+ -- that an infinity will result.
if not Is_Static_Expression (N) then
if Is_Floating_Point_Type (T)
@@ -283,17 +288,17 @@ package body Sem_Eval is
return;
end if;
- -- Here we have the case of outer level static expression of
- -- scalar type, where the processing of this procedure is needed.
+ -- Here we have the case of outer level static expression of scalar
+ -- type, where the processing of this procedure is needed.
-- For real types, this is where we convert the value to a machine
- -- number (see RM 4.9(38)). Also see ACVC test C490001. We should
- -- only need to do this if the parent is a constant declaration,
- -- since in other cases, gigi should do the necessary conversion
- -- correctly, but experimentation shows that this is not the case
- -- on all machines, in particular if we do not convert all literals
- -- to machine values in non-static contexts, then ACVC test C490001
- -- fails on Sparc/Solaris and SGI/Irix.
+ -- number (see RM 4.9(38)). Also see ACVC test C490001. We should only
+ -- need to do this if the parent is a constant declaration, since in
+ -- other cases, gigi should do the necessary conversion correctly, but
+ -- experimentation shows that this is not the case on all machines, in
+ -- particular if we do not convert all literals to machine values in
+ -- non-static contexts, then ACVC test C490001 fails on Sparc/Solaris
+ -- and SGI/Irix.
if Nkind (N) = N_Real_Literal
and then not Is_Machine_Number (N)
@@ -320,12 +325,12 @@ package body Sem_Eval is
elsif not UR_Is_Zero (Realval (N)) then
- -- Note: even though RM 4.9(38) specifies biased rounding,
- -- this has been modified by AI-100 in order to prevent
- -- confusing differences in rounding between static and
- -- non-static expressions. AI-100 specifies that the effect
- -- of such rounding is implementation dependent, and in GNAT
- -- we round to nearest even to match the run-time behavior.
+ -- Note: even though RM 4.9(38) specifies biased rounding, this
+ -- has been modified by AI-100 in order to prevent confusing
+ -- differences in rounding between static and non-static
+ -- expressions. AI-100 specifies that the effect of such rounding
+ -- is implementation dependent, and in GNAT we round to nearest
+ -- even to match the run-time behavior.
Set_Realval
(N, Machine (Base_Type (T), Realval (N), Round_Even, N));
@@ -455,10 +460,10 @@ package body Sem_Eval is
-- simple cases can be recognized.
function Is_Same_Value (L, R : Node_Id) return Boolean;
- -- Returns True iff L and R represent expressions that definitely
- -- have identical (but not necessarily compile time known) values
- -- Indeed the caller is expected to have already dealt with the
- -- cases of compile time known values, so these are not tested here.
+ -- Returns True iff L and R represent expressions that definitely have
+ -- identical (but not necessarily compile time known) values Indeed the
+ -- caller is expected to have already dealt with the cases of compile
+ -- time known values, so these are not tested here.
-----------------------
-- Compare_Decompose --
diff --git a/gcc/ada/sem_intr.adb b/gcc/ada/sem_intr.adb
index 19016822a3a..26f9ff4a74b 100644
--- a/gcc/ada/sem_intr.adb
+++ b/gcc/ada/sem_intr.adb
@@ -317,7 +317,11 @@ package body Sem_Intr is
return;
end if;
- if not Is_Numeric_Type (Underlying_Type (T1)) then
+ -- The type must be fully defined and numeric.
+
+ if No (Underlying_Type (T1))
+ or else not Is_Numeric_Type (Underlying_Type (T1))
+ then
Errint ("intrinsic operator can only apply to numeric types", E, N);
end if;
end Check_Intrinsic_Operator;
diff --git a/gcc/ada/sem_prag.adb b/gcc/ada/sem_prag.adb
index 46906943762..9de2f1f0320 100644
--- a/gcc/ada/sem_prag.adb
+++ b/gcc/ada/sem_prag.adb
@@ -750,6 +750,10 @@ package body Sem_Prag is
-- convention value in the specified entity or entities. On return
-- C is the convention, Ent is the referenced entity.
+ procedure Process_Disable_Enable_Atomic_Sync (Nam : Name_Id);
+ -- Common processing for Disable/Enable_Atomic_Synchronization. Nam is
+ -- Name_Suppress for Disable and Name_Unsuppress for Enable.
+
procedure Process_Extended_Import_Export_Exception_Pragma
(Arg_Internal : Node_Id;
Arg_External : Node_Id;
@@ -3566,6 +3570,35 @@ package body Sem_Prag is
end if;
end Process_Convention;
+ ----------------------------------------
+ -- Process_Disable_Enable_Atomic_Sync --
+ ----------------------------------------
+
+ procedure Process_Disable_Enable_Atomic_Sync (Nam : Name_Id) is
+ begin
+ GNAT_Pragma;
+ Check_No_Identifiers;
+ Check_At_Most_N_Arguments (1);
+
+ -- Modeled internally as
+ -- pragma Unsuppress (Atomic_Synchronization [,Entity])
+
+ Rewrite (N,
+ Make_Pragma (Loc,
+ Pragma_Identifier =>
+ Make_Identifier (Loc, Nam),
+ Pragma_Argument_Associations => New_List (
+ Make_Pragma_Argument_Association (Loc,
+ Expression =>
+ Make_Identifier (Loc, Name_Atomic_Synchronization)))));
+
+ if Present (Arg1) then
+ Append_To (Pragma_Argument_Associations (N), New_Copy (Arg1));
+ end if;
+
+ Analyze (N);
+ end Process_Disable_Enable_Atomic_Sync;
+
-----------------------------------------------------
-- Process_Extended_Import_Export_Exception_Pragma --
-----------------------------------------------------
@@ -5305,8 +5338,15 @@ package body Sem_Prag is
-- H.4(12). Restriction_Warnings never affects generated code
-- so this is done only in the real restriction case.
+ -- Atomic_Synchronization is not a real check, so it is not
+ -- affected by this processing).
+
if R_Id = No_Exceptions and then not Warn then
- Scope_Suppress := (others => True);
+ for J in Scope_Suppress'Range loop
+ if J /= Atomic_Synchronization then
+ Scope_Suppress (J) := True;
+ end if;
+ end loop;
end if;
-- Case of No_Dependence => unit-name. Note that the parser
@@ -5418,6 +5458,17 @@ package body Sem_Prag is
procedure Suppress_Unsuppress_Echeck (E : Entity_Id; C : Check_Id) is
begin
+ -- Check for error of trying to set atomic synchronization for
+ -- a non-atomic variable.
+
+ if C = Atomic_Synchronization
+ and then not Is_Atomic (E)
+ then
+ Error_Msg_N
+ ("pragma & requires atomic variable",
+ Pragma_Identifier (Original_Node (N)));
+ end if;
+
Set_Checks_May_Be_Suppressed (E);
if In_Package_Spec then
@@ -5425,7 +5476,6 @@ package body Sem_Prag is
(Entity => E,
Check => C,
Suppress => Suppress_Case);
-
else
Push_Local_Suppress_Stack_Entry
(Entity => E,
@@ -5493,18 +5543,26 @@ package body Sem_Prag is
-- the exception of Elaboration_Check, which is handled
-- specially because of not wanting All_Checks to have the
-- effect of deactivating static elaboration order processing.
+ -- Atomic_Synchronization is also not affected, since this is
+ -- not a real check.
for J in Scope_Suppress'Range loop
- if J /= Elaboration_Check then
+ if J /= Elaboration_Check
+ and then J /= Atomic_Synchronization
+ then
Scope_Suppress (J) := Suppress_Case;
end if;
end loop;
-- If not All_Checks, and predefined check, then set appropriate
-- scope entry. Note that we will set Elaboration_Check if this
- -- is explicitly specified.
+ -- is explicitly specified. Atomic_Synchronization is allowed
+ -- only if internally generated and entity is atomic.
- elsif C in Predefined_Check_Id then
+ elsif C in Predefined_Check_Id
+ and then (not Comes_From_Source (N)
+ or else C /= Atomic_Synchronization)
+ then
Scope_Suppress (C) := Suppress_Case;
end if;
@@ -6918,7 +6976,6 @@ package body Sem_Prag is
Error_Pragma_Arg ("inappropriate entity for pragma%", Arg1);
end if;
end Atomic_Components;
-
--------------------
-- Attach_Handler --
--------------------
@@ -7827,7 +7884,8 @@ package body Sem_Prag is
-- All other cases: diagnose error
Error_Msg
- ("argument of pragma% is not procedure call", Sloc (Call));
+ ("argument of pragma ""Debug"" is not procedure call",
+ Sloc (Call));
return;
end if;
@@ -7942,6 +8000,15 @@ package body Sem_Prag is
Check_Arg_Is_Static_Expression (Arg3, Standard_Integer);
Check_Arg_Is_Static_Expression (Arg4, Standard_Integer);
+ ------------------------------------
+ -- Disable_Atomic_Synchronization --
+ ------------------------------------
+
+ -- pragma Disable_Atomic_Synchronization [(Entity)];
+
+ when Pragma_Disable_Atomic_Synchronization =>
+ Process_Disable_Enable_Atomic_Sync (Name_Suppress);
+
-------------------
-- Discard_Names --
-------------------
@@ -8364,6 +8431,15 @@ package body Sem_Prag is
Source_Location);
end Eliminate;
+ -----------------------------------
+ -- Enable_Atomic_Synchronization --
+ -----------------------------------
+
+ -- pragma Enable_Atomic_Synchronization [(Entity)];
+
+ when Pragma_Enable_Atomic_Synchronization =>
+ Process_Disable_Enable_Atomic_Sync (Name_Unsuppress);
+
------------
-- Export --
------------
@@ -13762,19 +13838,18 @@ package body Sem_Prag is
Error_Msg_N ("Unchecked_Union must not be tagged", Typ);
return;
- elsif Is_Limited_Type (Typ) then
+ elsif not Has_Discriminants (Typ) then
Error_Msg_N
- ("Unchecked_Union must not be limited record type", Typ);
- Explain_Limited_Type (Typ, Typ);
+ ("Unchecked_Union must have one discriminant", Typ);
return;
- else
- if not Has_Discriminants (Typ) then
- Error_Msg_N
- ("Unchecked_Union must have one discriminant", Typ);
- return;
- end if;
+ -- Note: in previous versions of GNAT we used to check for limited
+ -- types and give an error, but in fact the standard does allow
+ -- Unchecked_Union on limited types, so this check was removed.
+
+ -- Proceed with basic error checks completed
+ else
Discr := First_Discriminant (Typ);
while Present (Discr) loop
if No (Discriminant_Default_Value (Discr)) then
@@ -14153,16 +14228,12 @@ package body Sem_Prag is
end;
elsif Nkind (A) = N_Identifier then
-
if Chars (A) = Name_All_Checks then
Set_Validity_Check_Options ("a");
-
elsif Chars (A) = Name_On then
Validity_Checks_On := True;
-
elsif Chars (A) = Name_Off then
Validity_Checks_On := False;
-
end if;
end if;
end Validity_Checks;
@@ -14679,194 +14750,196 @@ package body Sem_Prag is
-- 99 special processing required (e.g. for pragma Check)
Sig_Flags : constant array (Pragma_Id) of Int :=
- (Pragma_AST_Entry => -1,
- Pragma_Abort_Defer => -1,
- Pragma_Ada_83 => -1,
- Pragma_Ada_95 => -1,
- Pragma_Ada_05 => -1,
- Pragma_Ada_2005 => -1,
- Pragma_Ada_12 => -1,
- Pragma_Ada_2012 => -1,
- Pragma_All_Calls_Remote => -1,
- Pragma_Annotate => -1,
- Pragma_Assert => -1,
- Pragma_Assertion_Policy => 0,
- Pragma_Assume_No_Invalid_Values => 0,
- Pragma_Asynchronous => -1,
- Pragma_Atomic => 0,
- Pragma_Atomic_Components => 0,
- Pragma_Attach_Handler => -1,
- Pragma_Check => 99,
- Pragma_Check_Name => 0,
- Pragma_Check_Policy => 0,
- Pragma_CIL_Constructor => -1,
- Pragma_CPP_Class => 0,
- Pragma_CPP_Constructor => 0,
- Pragma_CPP_Virtual => 0,
- Pragma_CPP_Vtable => 0,
- Pragma_CPU => -1,
- Pragma_C_Pass_By_Copy => 0,
- Pragma_Comment => 0,
- Pragma_Common_Object => -1,
- Pragma_Compile_Time_Error => -1,
- Pragma_Compile_Time_Warning => -1,
- Pragma_Compiler_Unit => 0,
- Pragma_Complete_Representation => 0,
- Pragma_Complex_Representation => 0,
- Pragma_Component_Alignment => -1,
- Pragma_Controlled => 0,
- Pragma_Convention => 0,
- Pragma_Convention_Identifier => 0,
- Pragma_Debug => -1,
- Pragma_Debug_Policy => 0,
- Pragma_Detect_Blocking => -1,
- Pragma_Default_Storage_Pool => -1,
- Pragma_Dimension => -1,
- Pragma_Discard_Names => 0,
- Pragma_Dispatching_Domain => -1,
- Pragma_Elaborate => -1,
- Pragma_Elaborate_All => -1,
- Pragma_Elaborate_Body => -1,
- Pragma_Elaboration_Checks => -1,
- Pragma_Eliminate => -1,
- Pragma_Export => -1,
- Pragma_Export_Exception => -1,
- Pragma_Export_Function => -1,
- Pragma_Export_Object => -1,
- Pragma_Export_Procedure => -1,
- Pragma_Export_Value => -1,
- Pragma_Export_Valued_Procedure => -1,
- Pragma_Extend_System => -1,
- Pragma_Extensions_Allowed => -1,
- Pragma_External => -1,
- Pragma_Favor_Top_Level => -1,
- Pragma_External_Name_Casing => -1,
- Pragma_Fast_Math => -1,
- Pragma_Finalize_Storage_Only => 0,
- Pragma_Float_Representation => 0,
- Pragma_Ident => -1,
- Pragma_Implementation_Defined => -1,
- Pragma_Implemented => -1,
- Pragma_Implicit_Packing => 0,
- Pragma_Import => +2,
- Pragma_Import_Exception => 0,
- Pragma_Import_Function => 0,
- Pragma_Import_Object => 0,
- Pragma_Import_Procedure => 0,
- Pragma_Import_Valued_Procedure => 0,
- Pragma_Independent => 0,
- Pragma_Independent_Components => 0,
- Pragma_Initialize_Scalars => -1,
- Pragma_Inline => 0,
- Pragma_Inline_Always => 0,
- Pragma_Inline_Generic => 0,
- Pragma_Inspection_Point => -1,
- Pragma_Interface => +2,
- Pragma_Interface_Name => +2,
- Pragma_Interrupt_Handler => -1,
- Pragma_Interrupt_Priority => -1,
- Pragma_Interrupt_State => -1,
- Pragma_Invariant => -1,
- Pragma_Java_Constructor => -1,
- Pragma_Java_Interface => -1,
- Pragma_Keep_Names => 0,
- Pragma_License => -1,
- Pragma_Link_With => -1,
- Pragma_Linker_Alias => -1,
- Pragma_Linker_Constructor => -1,
- Pragma_Linker_Destructor => -1,
- Pragma_Linker_Options => -1,
- Pragma_Linker_Section => -1,
- Pragma_List => -1,
- Pragma_Locking_Policy => -1,
- Pragma_Long_Float => -1,
- Pragma_Machine_Attribute => -1,
- Pragma_Main => -1,
- Pragma_Main_Storage => -1,
- Pragma_Memory_Size => -1,
- Pragma_No_Return => 0,
- Pragma_No_Body => 0,
- Pragma_No_Run_Time => -1,
- Pragma_No_Strict_Aliasing => -1,
- Pragma_Normalize_Scalars => -1,
- Pragma_Obsolescent => 0,
- Pragma_Optimize => -1,
- Pragma_Optimize_Alignment => -1,
- Pragma_Ordered => 0,
- Pragma_Pack => 0,
- Pragma_Page => -1,
- Pragma_Passive => -1,
- Pragma_Preelaborable_Initialization => -1,
- Pragma_Polling => -1,
- Pragma_Persistent_BSS => 0,
- Pragma_Postcondition => -1,
- Pragma_Precondition => -1,
- Pragma_Predicate => -1,
- Pragma_Preelaborate => -1,
- Pragma_Preelaborate_05 => -1,
- Pragma_Priority => -1,
- Pragma_Priority_Specific_Dispatching => -1,
- Pragma_Profile => 0,
- Pragma_Profile_Warnings => 0,
- Pragma_Propagate_Exceptions => -1,
- Pragma_Psect_Object => -1,
- Pragma_Pure => -1,
- Pragma_Pure_05 => -1,
- Pragma_Pure_Function => -1,
- Pragma_Queuing_Policy => -1,
- Pragma_Ravenscar => -1,
- Pragma_Relative_Deadline => -1,
- Pragma_Remote_Call_Interface => -1,
- Pragma_Remote_Types => -1,
- Pragma_Restricted_Run_Time => -1,
- Pragma_Restriction_Warnings => -1,
- Pragma_Restrictions => -1,
- Pragma_Reviewable => -1,
- Pragma_Short_Circuit_And_Or => -1,
- Pragma_Share_Generic => -1,
- Pragma_Shared => -1,
- Pragma_Shared_Passive => -1,
- Pragma_Short_Descriptors => 0,
- Pragma_Source_File_Name => -1,
- Pragma_Source_File_Name_Project => -1,
- Pragma_Source_Reference => -1,
- Pragma_Storage_Size => -1,
- Pragma_Storage_Unit => -1,
- Pragma_Static_Elaboration_Desired => -1,
- Pragma_Stream_Convert => -1,
- Pragma_Style_Checks => -1,
- Pragma_Subtitle => -1,
- Pragma_Suppress => 0,
- Pragma_Suppress_Exception_Locations => 0,
- Pragma_Suppress_All => -1,
- Pragma_Suppress_Debug_Info => 0,
- Pragma_Suppress_Initialization => 0,
- Pragma_System_Name => -1,
- Pragma_Task_Dispatching_Policy => -1,
- Pragma_Task_Info => -1,
- Pragma_Task_Name => -1,
- Pragma_Task_Storage => 0,
- Pragma_Test_Case => -1,
- Pragma_Thread_Local_Storage => 0,
- Pragma_Time_Slice => -1,
- Pragma_Title => -1,
- Pragma_Unchecked_Union => 0,
- Pragma_Unimplemented_Unit => -1,
- Pragma_Universal_Aliasing => -1,
- Pragma_Universal_Data => -1,
- Pragma_Unmodified => -1,
- Pragma_Unreferenced => -1,
- Pragma_Unreferenced_Objects => -1,
- Pragma_Unreserve_All_Interrupts => -1,
- Pragma_Unsuppress => 0,
- Pragma_Use_VADS_Size => -1,
- Pragma_Validity_Checks => -1,
- Pragma_Volatile => 0,
- Pragma_Volatile_Components => 0,
- Pragma_Warnings => -1,
- Pragma_Weak_External => -1,
- Pragma_Wide_Character_Encoding => 0,
- Unknown_Pragma => 0);
+ (Pragma_AST_Entry => -1,
+ Pragma_Abort_Defer => -1,
+ Pragma_Ada_83 => -1,
+ Pragma_Ada_95 => -1,
+ Pragma_Ada_05 => -1,
+ Pragma_Ada_2005 => -1,
+ Pragma_Ada_12 => -1,
+ Pragma_Ada_2012 => -1,
+ Pragma_All_Calls_Remote => -1,
+ Pragma_Annotate => -1,
+ Pragma_Assert => -1,
+ Pragma_Assertion_Policy => 0,
+ Pragma_Assume_No_Invalid_Values => 0,
+ Pragma_Asynchronous => -1,
+ Pragma_Atomic => 0,
+ Pragma_Atomic_Components => 0,
+ Pragma_Attach_Handler => -1,
+ Pragma_Check => 99,
+ Pragma_Check_Name => 0,
+ Pragma_Check_Policy => 0,
+ Pragma_CIL_Constructor => -1,
+ Pragma_CPP_Class => 0,
+ Pragma_CPP_Constructor => 0,
+ Pragma_CPP_Virtual => 0,
+ Pragma_CPP_Vtable => 0,
+ Pragma_CPU => -1,
+ Pragma_C_Pass_By_Copy => 0,
+ Pragma_Comment => 0,
+ Pragma_Common_Object => -1,
+ Pragma_Compile_Time_Error => -1,
+ Pragma_Compile_Time_Warning => -1,
+ Pragma_Compiler_Unit => 0,
+ Pragma_Complete_Representation => 0,
+ Pragma_Complex_Representation => 0,
+ Pragma_Component_Alignment => -1,
+ Pragma_Controlled => 0,
+ Pragma_Convention => 0,
+ Pragma_Convention_Identifier => 0,
+ Pragma_Debug => -1,
+ Pragma_Debug_Policy => 0,
+ Pragma_Detect_Blocking => -1,
+ Pragma_Default_Storage_Pool => -1,
+ Pragma_Dimension => -1,
+ Pragma_Disable_Atomic_Synchronization => -1,
+ Pragma_Discard_Names => 0,
+ Pragma_Dispatching_Domain => -1,
+ Pragma_Elaborate => -1,
+ Pragma_Elaborate_All => -1,
+ Pragma_Elaborate_Body => -1,
+ Pragma_Elaboration_Checks => -1,
+ Pragma_Eliminate => -1,
+ Pragma_Enable_Atomic_Synchronization => -1,
+ Pragma_Export => -1,
+ Pragma_Export_Exception => -1,
+ Pragma_Export_Function => -1,
+ Pragma_Export_Object => -1,
+ Pragma_Export_Procedure => -1,
+ Pragma_Export_Value => -1,
+ Pragma_Export_Valued_Procedure => -1,
+ Pragma_Extend_System => -1,
+ Pragma_Extensions_Allowed => -1,
+ Pragma_External => -1,
+ Pragma_Favor_Top_Level => -1,
+ Pragma_External_Name_Casing => -1,
+ Pragma_Fast_Math => -1,
+ Pragma_Finalize_Storage_Only => 0,
+ Pragma_Float_Representation => 0,
+ Pragma_Ident => -1,
+ Pragma_Implementation_Defined => -1,
+ Pragma_Implemented => -1,
+ Pragma_Implicit_Packing => 0,
+ Pragma_Import => +2,
+ Pragma_Import_Exception => 0,
+ Pragma_Import_Function => 0,
+ Pragma_Import_Object => 0,
+ Pragma_Import_Procedure => 0,
+ Pragma_Import_Valued_Procedure => 0,
+ Pragma_Independent => 0,
+ Pragma_Independent_Components => 0,
+ Pragma_Initialize_Scalars => -1,
+ Pragma_Inline => 0,
+ Pragma_Inline_Always => 0,
+ Pragma_Inline_Generic => 0,
+ Pragma_Inspection_Point => -1,
+ Pragma_Interface => +2,
+ Pragma_Interface_Name => +2,
+ Pragma_Interrupt_Handler => -1,
+ Pragma_Interrupt_Priority => -1,
+ Pragma_Interrupt_State => -1,
+ Pragma_Invariant => -1,
+ Pragma_Java_Constructor => -1,
+ Pragma_Java_Interface => -1,
+ Pragma_Keep_Names => 0,
+ Pragma_License => -1,
+ Pragma_Link_With => -1,
+ Pragma_Linker_Alias => -1,
+ Pragma_Linker_Constructor => -1,
+ Pragma_Linker_Destructor => -1,
+ Pragma_Linker_Options => -1,
+ Pragma_Linker_Section => -1,
+ Pragma_List => -1,
+ Pragma_Locking_Policy => -1,
+ Pragma_Long_Float => -1,
+ Pragma_Machine_Attribute => -1,
+ Pragma_Main => -1,
+ Pragma_Main_Storage => -1,
+ Pragma_Memory_Size => -1,
+ Pragma_No_Return => 0,
+ Pragma_No_Body => 0,
+ Pragma_No_Run_Time => -1,
+ Pragma_No_Strict_Aliasing => -1,
+ Pragma_Normalize_Scalars => -1,
+ Pragma_Obsolescent => 0,
+ Pragma_Optimize => -1,
+ Pragma_Optimize_Alignment => -1,
+ Pragma_Ordered => 0,
+ Pragma_Pack => 0,
+ Pragma_Page => -1,
+ Pragma_Passive => -1,
+ Pragma_Preelaborable_Initialization => -1,
+ Pragma_Polling => -1,
+ Pragma_Persistent_BSS => 0,
+ Pragma_Postcondition => -1,
+ Pragma_Precondition => -1,
+ Pragma_Predicate => -1,
+ Pragma_Preelaborate => -1,
+ Pragma_Preelaborate_05 => -1,
+ Pragma_Priority => -1,
+ Pragma_Priority_Specific_Dispatching => -1,
+ Pragma_Profile => 0,
+ Pragma_Profile_Warnings => 0,
+ Pragma_Propagate_Exceptions => -1,
+ Pragma_Psect_Object => -1,
+ Pragma_Pure => -1,
+ Pragma_Pure_05 => -1,
+ Pragma_Pure_Function => -1,
+ Pragma_Queuing_Policy => -1,
+ Pragma_Ravenscar => -1,
+ Pragma_Relative_Deadline => -1,
+ Pragma_Remote_Call_Interface => -1,
+ Pragma_Remote_Types => -1,
+ Pragma_Restricted_Run_Time => -1,
+ Pragma_Restriction_Warnings => -1,
+ Pragma_Restrictions => -1,
+ Pragma_Reviewable => -1,
+ Pragma_Short_Circuit_And_Or => -1,
+ Pragma_Share_Generic => -1,
+ Pragma_Shared => -1,
+ Pragma_Shared_Passive => -1,
+ Pragma_Short_Descriptors => 0,
+ Pragma_Source_File_Name => -1,
+ Pragma_Source_File_Name_Project => -1,
+ Pragma_Source_Reference => -1,
+ Pragma_Storage_Size => -1,
+ Pragma_Storage_Unit => -1,
+ Pragma_Static_Elaboration_Desired => -1,
+ Pragma_Stream_Convert => -1,
+ Pragma_Style_Checks => -1,
+ Pragma_Subtitle => -1,
+ Pragma_Suppress => 0,
+ Pragma_Suppress_Exception_Locations => 0,
+ Pragma_Suppress_All => -1,
+ Pragma_Suppress_Debug_Info => 0,
+ Pragma_Suppress_Initialization => 0,
+ Pragma_System_Name => -1,
+ Pragma_Task_Dispatching_Policy => -1,
+ Pragma_Task_Info => -1,
+ Pragma_Task_Name => -1,
+ Pragma_Task_Storage => 0,
+ Pragma_Test_Case => -1,
+ Pragma_Thread_Local_Storage => 0,
+ Pragma_Time_Slice => -1,
+ Pragma_Title => -1,
+ Pragma_Unchecked_Union => 0,
+ Pragma_Unimplemented_Unit => -1,
+ Pragma_Universal_Aliasing => -1,
+ Pragma_Universal_Data => -1,
+ Pragma_Unmodified => -1,
+ Pragma_Unreferenced => -1,
+ Pragma_Unreferenced_Objects => -1,
+ Pragma_Unreserve_All_Interrupts => -1,
+ Pragma_Unsuppress => 0,
+ Pragma_Use_VADS_Size => -1,
+ Pragma_Validity_Checks => -1,
+ Pragma_Volatile => 0,
+ Pragma_Volatile_Components => 0,
+ Pragma_Warnings => -1,
+ Pragma_Weak_External => -1,
+ Pragma_Wide_Character_Encoding => 0,
+ Unknown_Pragma => 0);
function Is_Non_Significant_Pragma_Reference (N : Node_Id) return Boolean is
Id : Pragma_Id;
diff --git a/gcc/ada/sem_res.adb b/gcc/ada/sem_res.adb
index 7f10c266225..d94a6bfa328 100644
--- a/gcc/ada/sem_res.adb
+++ b/gcc/ada/sem_res.adb
@@ -7356,6 +7356,48 @@ package body Sem_Res is
Check_For_Visible_Operator (N, B_Typ);
end if;
+ -- Replace AND by AND THEN, or OR by OR ELSE, if Short_Circuit_And_Or
+ -- is active and the result type is standard Boolean (do not mess with
+ -- ops that return a nonstandard Boolean type, because something strange
+ -- is going on).
+
+ -- Note: you might expect this replacement to be done during expansion,
+ -- but that doesn't work, because when the pragma Short_Circuit_And_Or
+ -- is used, no part of the right operand of an "and" or "or" operator
+ -- should be executed if the left operand would short-circuit the
+ -- evaluation of the corresponding "and then" or "or else". If we left
+ -- the replacement to expansion time, then run-time checks associated
+ -- with such operands would be evaluated unconditionally, due to being
+ -- before the condition prior to the rewriting as short-circuit forms
+ -- during expansion.
+
+ if Short_Circuit_And_Or
+ and then B_Typ = Standard_Boolean
+ and then Nkind_In (N, N_Op_And, N_Op_Or)
+ then
+ if Nkind (N) = N_Op_And then
+ Rewrite (N,
+ Make_And_Then (Sloc (N),
+ Left_Opnd => Relocate_Node (Left_Opnd (N)),
+ Right_Opnd => Relocate_Node (Right_Opnd (N))));
+ Analyze_And_Resolve (N, B_Typ);
+
+ -- Case of OR changed to OR ELSE
+
+ else
+ Rewrite (N,
+ Make_Or_Else (Sloc (N),
+ Left_Opnd => Relocate_Node (Left_Opnd (N)),
+ Right_Opnd => Relocate_Node (Right_Opnd (N))));
+ Analyze_And_Resolve (N, B_Typ);
+ end if;
+
+ -- Return now, since analysis of the rewritten ops will take care of
+ -- other reference bookkeeping and expression folding.
+
+ return;
+ end if;
+
Resolve (Left_Opnd (N), B_Typ);
Resolve (Right_Opnd (N), B_Typ);
diff --git a/gcc/ada/sem_type.adb b/gcc/ada/sem_type.adb
index 067a2d4f853..c391163ea4b 100644
--- a/gcc/ada/sem_type.adb
+++ b/gcc/ada/sem_type.adb
@@ -1992,8 +1992,8 @@ package body Sem_Type is
-- exclude the universal_fixed operator, which often causes ambiguities
-- in legacy code.
- -- Ditto in Ada 2012, where an ambiguity may arise for an operation on
- -- a partial view that is completed with a fixed point type. See
+ -- Ditto in Ada 2012, where an ambiguity may arise for an operation
+ -- on a partial view that is completed with a fixed point type. See
-- AI05-0020 and AI05-0209. The ambiguity is resolved in favor of the
-- user-defined subprogram so that a client of the package has the
-- same resulution as the body of the package.
@@ -3372,18 +3372,28 @@ package body Sem_Type is
function Valid_Boolean_Arg (T : Entity_Id) return Boolean is
begin
- return Is_Boolean_Type (T)
- or else T = Any_Composite
- or else (Is_Array_Type (T)
- and then T /= Any_String
- and then Number_Dimensions (T) = 1
- and then Is_Boolean_Type (Component_Type (T))
- and then (not Is_Private_Composite (T)
- or else In_Instance)
- and then (not Is_Limited_Composite (T)
- or else In_Instance))
+ if Is_Boolean_Type (T)
or else Is_Modular_Integer_Type (T)
- or else T = Universal_Integer;
+ or else T = Universal_Integer
+ or else T = Any_Composite
+ then
+ return True;
+
+ elsif Is_Array_Type (T)
+ and then T /= Any_String
+ and then Number_Dimensions (T) = 1
+ and then Is_Boolean_Type (Component_Type (T))
+ and then
+ ((not Is_Private_Composite (T)
+ and then not Is_Limited_Composite (T))
+ or else In_Instance
+ or else Available_Full_View_Of_Component (T))
+ then
+ return True;
+
+ else
+ return False;
+ end if;
end Valid_Boolean_Arg;
--------------------------
@@ -3395,10 +3405,12 @@ package body Sem_Type is
if T = Any_Composite then
return False;
+
elsif Is_Discrete_Type (T)
or else Is_Real_Type (T)
then
return True;
+
elsif Is_Array_Type (T)
and then Number_Dimensions (T) = 1
and then Is_Discrete_Type (Component_Type (T))
@@ -3408,6 +3420,14 @@ package body Sem_Type is
or else In_Instance)
then
return True;
+
+ elsif Is_Array_Type (T)
+ and then Number_Dimensions (T) = 1
+ and then Is_Discrete_Type (Component_Type (T))
+ and then Available_Full_View_Of_Component (T)
+ then
+ return True;
+
elsif Is_String_Type (T) then
return True;
else
diff --git a/gcc/ada/sem_util.adb b/gcc/ada/sem_util.adb
index 1881563aa88..9dfecd3d956 100644
--- a/gcc/ada/sem_util.adb
+++ b/gcc/ada/sem_util.adb
@@ -333,6 +333,19 @@ package body Sem_Util is
end if;
end Apply_Compile_Time_Constraint_Error;
+ --------------------------------------
+ -- Available_Full_View_Of_Component --
+ --------------------------------------
+
+ function Available_Full_View_Of_Component (T : Entity_Id) return Boolean is
+ ST : constant Entity_Id := Scope (T);
+ SCT : constant Entity_Id := Scope (Component_Type (T));
+ begin
+ return In_Open_Scopes (ST)
+ and then In_Open_Scopes (SCT)
+ and then Scope_Depth (ST) >= Scope_Depth (SCT);
+ end Available_Full_View_Of_Component;
+
--------------------------------
-- Bad_Predicated_Subtype_Use --
--------------------------------
@@ -2739,7 +2752,7 @@ package body Sem_Util is
end if;
elsif Is_Entity_Name (A2) then
- return Denotes_Same_Prefix (A2, A1);
+ return Denotes_Same_Prefix (A1 => A2, A2 => A1);
elsif Nkind_In (A1, N_Selected_Component, N_Indexed_Component, N_Slice)
and then
@@ -3012,7 +3025,8 @@ package body Sem_Util is
function Effective_Extra_Accessibility (Id : Entity_Id) return Entity_Id is
begin
if Present (Renamed_Object (Id))
- and then Is_Entity_Name (Renamed_Object (Id)) then
+ and then Is_Entity_Name (Renamed_Object (Id))
+ then
return Effective_Extra_Accessibility (Entity (Renamed_Object (Id)));
end if;
@@ -3896,8 +3910,8 @@ package body Sem_Util is
end if;
end loop;
- -- This loop checks the form of the prefix for an entity,
- -- using recursion to deal with intermediate components.
+ -- This loop checks the form of the prefix for an entity, using
+ -- recursion to deal with intermediate components.
loop
-- Check for Y where Y is an entity
@@ -3909,8 +3923,8 @@ package body Sem_Util is
-- Check for components
elsif
- Nkind_In (Expr, N_Selected_Component, N_Indexed_Component) then
-
+ Nkind_In (Expr, N_Selected_Component, N_Indexed_Component)
+ then
Expr := Prefix (Expr);
Off := True;
@@ -5951,6 +5965,29 @@ package body Sem_Util is
return Name_Buffer (Name_Len) = Suffix;
end Has_Suffix;
+ ----------------
+ -- Add_Suffix --
+ ----------------
+
+ function Add_Suffix (E : Entity_Id; Suffix : Character) return Name_Id is
+ begin
+ Get_Name_String (Chars (E));
+ Add_Char_To_Name_Buffer (Suffix);
+ return Name_Find;
+ end Add_Suffix;
+
+ -------------------
+ -- Remove_Suffix --
+ -------------------
+
+ function Remove_Suffix (E : Entity_Id; Suffix : Character) return Name_Id is
+ begin
+ pragma Assert (Has_Suffix (E, Suffix));
+ Get_Name_String (Chars (E));
+ Name_Len := Name_Len - 1;
+ return Name_Find;
+ end Remove_Suffix;
+
--------------------------
-- Has_Tagged_Component --
--------------------------
@@ -6554,19 +6591,18 @@ package body Sem_Util is
(Is_Object (E)
and then
(Is_Aliased (E)
- or else (Present (Renamed_Object (E))
- and then Is_Aliased_View (Renamed_Object (E)))))
+ or else (Present (Renamed_Object (E))
+ and then Is_Aliased_View (Renamed_Object (E)))))
or else ((Is_Formal (E)
or else Ekind (E) = E_Generic_In_Out_Parameter
or else Ekind (E) = E_Generic_In_Parameter)
and then Is_Tagged_Type (Etype (E)))
- or else (Is_Concurrent_Type (E)
- and then In_Open_Scopes (E))
+ or else (Is_Concurrent_Type (E) and then In_Open_Scopes (E))
- -- Current instance of type, either directly or as rewritten
- -- reference to the current object.
+ -- Current instance of type, either directly or as rewritten
+ -- reference to the current object.
or else (Is_Entity_Name (Original_Node (Obj))
and then Present (Entity (Original_Node (Obj)))
@@ -6575,7 +6611,13 @@ package body Sem_Util is
or else (Is_Type (E) and then E = Current_Scope)
or else (Is_Incomplete_Or_Private_Type (E)
- and then Full_View (E) = Current_Scope);
+ and then Full_View (E) = Current_Scope)
+
+ -- Ada 2012 AI05-0053: the return object of an extended return
+ -- statement is aliased if its type is immutably limited.
+
+ or else (Is_Return_Object (E)
+ and then Is_Immutably_Limited_Type (Etype (E)));
elsif Nkind (Obj) = N_Selected_Component then
return Is_Aliased (Entity (Selector_Name (Obj)));
@@ -7345,6 +7387,34 @@ package body Sem_Util is
end if;
end Is_Fully_Initialized_Variant;
+ ----------------------------
+ -- Is_Inherited_Operation --
+ ----------------------------
+
+ function Is_Inherited_Operation (E : Entity_Id) return Boolean is
+ pragma Assert (Is_Overloadable (E));
+ Kind : constant Node_Kind := Nkind (Parent (E));
+ begin
+ return Kind = N_Full_Type_Declaration
+ or else Kind = N_Private_Extension_Declaration
+ or else Kind = N_Subtype_Declaration
+ or else (Ekind (E) = E_Enumeration_Literal
+ and then Is_Derived_Type (Etype (E)));
+ end Is_Inherited_Operation;
+
+ -------------------------------------
+ -- Is_Inherited_Operation_For_Type --
+ -------------------------------------
+
+ function Is_Inherited_Operation_For_Type
+ (E : Entity_Id;
+ Typ : Entity_Id) return Boolean
+ is
+ begin
+ return Is_Inherited_Operation (E)
+ and then Etype (Parent (E)) = Typ;
+ end Is_Inherited_Operation_For_Type;
+
-----------------
-- Is_Iterator --
-----------------
@@ -7415,33 +7485,6 @@ package body Sem_Util is
end if;
end Is_LHS;
- ----------------------------
- -- Is_Inherited_Operation --
- ----------------------------
-
- function Is_Inherited_Operation (E : Entity_Id) return Boolean is
- Kind : constant Node_Kind := Nkind (Parent (E));
- begin
- pragma Assert (Is_Overloadable (E));
- return Kind = N_Full_Type_Declaration
- or else Kind = N_Private_Extension_Declaration
- or else Kind = N_Subtype_Declaration
- or else (Ekind (E) = E_Enumeration_Literal
- and then Is_Derived_Type (Etype (E)));
- end Is_Inherited_Operation;
-
- -------------------------------------
- -- Is_Inherited_Operation_For_Type --
- -------------------------------------
-
- function Is_Inherited_Operation_For_Type
- (E : Entity_Id; Typ : Entity_Id) return Boolean
- is
- begin
- return Is_Inherited_Operation (E)
- and then Etype (Parent (E)) = Typ;
- end Is_Inherited_Operation_For_Type;
-
-----------------------------
-- Is_Library_Level_Entity --
-----------------------------
@@ -7462,6 +7505,17 @@ package body Sem_Util is
return Enclosing_Dynamic_Scope (E) = Standard_Standard;
end Is_Library_Level_Entity;
+ --------------------------------
+ -- Is_Limited_Class_Wide_Type --
+ --------------------------------
+
+ function Is_Limited_Class_Wide_Type (Typ : Entity_Id) return Boolean is
+ begin
+ return
+ Is_Class_Wide_Type (Typ)
+ and then Is_Limited_Type (Typ);
+ end Is_Limited_Class_Wide_Type;
+
---------------------------------
-- Is_Local_Variable_Reference --
---------------------------------
diff --git a/gcc/ada/sem_util.ads b/gcc/ada/sem_util.ads
index 77f26b40e8b..c7f610d52f0 100644
--- a/gcc/ada/sem_util.ads
+++ b/gcc/ada/sem_util.ads
@@ -94,6 +94,15 @@ package Sem_Util is
-- not end with a ? (this is used when the caller wants to parameterize
-- whether an error or warning is given.
+ function Available_Full_View_Of_Component (T : Entity_Id) return Boolean;
+ -- If at the point of declaration an array type has a private or limited
+ -- component, several array operations are not avaiable on the type, and
+ -- the array type is flagged accordingly. If in the immediate scope of
+ -- the array type the component becomes non-private or non-limited, these
+ -- operations become avaiable. This can happen if the scopes of both types
+ -- are open, and the scope of the array is not outside the scope of the
+ -- component.
+
procedure Bad_Predicated_Subtype_Use
(Msg : String;
N : Node_Id;
@@ -682,6 +691,12 @@ package Sem_Util is
function Has_Suffix (E : Entity_Id; Suffix : Character) return Boolean;
-- Returns true if the last character of E is Suffix. Used in Assertions.
+ function Add_Suffix (E : Entity_Id; Suffix : Character) return Name_Id;
+ -- Returns the name of E adding Suffix
+
+ function Remove_Suffix (E : Entity_Id; Suffix : Character) return Name_Id;
+ -- Returns the name of E without Suffix
+
function Has_Tagged_Component (Typ : Entity_Id) return Boolean;
-- Returns True if Typ is a composite type (array or record) which is
-- either itself a tagged type, or has a component (recursively) which is
@@ -836,8 +851,8 @@ package Sem_Util is
-- by the derived type declaration for type Typ.
function Is_Iterator (Typ : Entity_Id) return Boolean;
- -- AI05-0139-2: Check whether Typ is derived from the predefined interface
- -- Ada.Iterator_Interfaces.Forward_Iterator.
+ -- AI05-0139-2: Check whether Typ is one of the predefined interfaces in
+ -- Ada.Iterator_Interfaces, or it is derived from one.
function Is_LHS (N : Node_Id) return Boolean;
-- Returns True iff N is used as Name in an assignment statement
@@ -846,6 +861,9 @@ package Sem_Util is
-- A library-level declaration is one that is accessible from Standard,
-- i.e. a library unit or an entity declared in a library package.
+ function Is_Limited_Class_Wide_Type (Typ : Entity_Id) return Boolean;
+ -- Determine whether a given arbitrary type is a limited class-wide type
+
function Is_Local_Variable_Reference (Expr : Node_Id) return Boolean;
-- Determines whether Expr is a reference to a variable or IN OUT mode
-- parameter of the current enclosing subprogram.
diff --git a/gcc/ada/sem_warn.adb b/gcc/ada/sem_warn.adb
index d58a14d7bca..9f0b259311c 100644
--- a/gcc/ada/sem_warn.adb
+++ b/gcc/ada/sem_warn.adb
@@ -1407,7 +1407,7 @@ package body Sem_Warn is
-- Case of warning on any unread OUT parameter (note
-- such indications are only set if the appropriate
- -- warning options were set, so no need to recheck here.
+ -- warning options were set, so no need to recheck here.)
or else
Referenced_As_Out_Parameter_Check_Spec (E1))
diff --git a/gcc/ada/sigtramp-ppcvxw.c b/gcc/ada/sigtramp-ppcvxw.c
new file mode 100644
index 00000000000..57a02a7d162
--- /dev/null
+++ b/gcc/ada/sigtramp-ppcvxw.c
@@ -0,0 +1,256 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * S I G T R A M P *
+ * *
+ * Asm Implementation File *
+ * *
+ * Copyright (C) 2011, Free Software Foundation, Inc. *
+ * *
+ * GNAT is free software; you can redistribute it and/or modify it under *
+ * terms of the GNU General Public License as published by the Free Soft- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
+ * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * In particular, you can freely distribute your programs built with the *
+ * GNAT Pro compiler, including any required library run-time units, using *
+ * any licensing terms of your choosing. See the AdaCore Software License *
+ * for full details. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/**********************************************************
+ * PowerPC-VxWorks version of the __gnat_sigtramp service *
+ **********************************************************/
+
+#include "sigtramp.h"
+
+#include <vxWorks.h>
+#include <arch/../regs.h>
+#include <sigLib.h>
+
+/* ----------------------
+ -- General comments --
+ ----------------------
+
+ Stubs are generated from toplevel asms and .cfi directives, much simpler
+ to use and check for correctness than manual encodings of CFI byte
+ sequences. The general idea is to establish CFA as sigcontext->sc_pregs
+ and state where to find the registers as offsets from there.
+
+ As of today, we support a single stub, providing CFI info for common
+ registers (GPRs, LR, ...). We might need variants with support for floating
+ point or altivec registers as well at some point.
+
+ Checking which variant should apply and getting at sc_pregs is simpler
+ to express in C (we can't use offsetof in toplevel asms and hardcoding
+ constants is not workable with the flurry of VxWorks variants), so this
+ is the choice for our toplevel interface. */
+
+/* -----------------------------------------
+ -- Protypes for our internal asm stubs --
+ -----------------------------------------
+
+ SC_PREGS is always expected to be SIGCONTEXT->sc_pregs. Eventhough our
+ symbols will remain local, the prototype claims "extern" and not
+ "static" to prevent compiler complaints about a symbol used but never
+ defined. */
+
+/* sigtramp stub providing CFI info for common registers. */
+
+extern void __gnat_sigtramp_common
+(int signo, void *siginfo, void *sigcontext,
+ sighandler_t * handler, void * sc_pregs);
+
+
+/* -------------------------------------
+ -- Common interface implementation --
+ -------------------------------------
+
+ We enforce optimization to minimize the overhead of the extra layer. */
+
+void __gnat_sigtramp (int signo, void *si, void *sc,
+ sighandler_t * handler)
+ __attribute__((optimize(2)));
+
+void __gnat_sigtramp (int signo, void *si, void *sc,
+ sighandler_t * handler)
+{
+ struct sigcontext * sctx = (struct sigcontext *) sc;
+
+ __gnat_sigtramp_common (signo, si, sctx, handler, sctx->sc_pregs);
+}
+
+
+/* ---------------------------
+ -- And now the asm stubs --
+ ---------------------------
+
+ They all have a common structure with blocks of asm sequences queued one
+ after the others. Typically:
+
+ SYMBOL_START
+
+ CFI_DIRECTIVES
+ CFI_DEF_CFA,
+ CFI_COMMON_REGISTERS,
+ ...
+
+ STUB_BODY
+ asm code to establish frame, setup the cfa reg value,
+ call the real signal handler, ...
+
+ SYMBOL_END
+*/
+
+/*--------------------------------
+ -- Misc constants and helpers --
+ -------------------------------- */
+
+/* REGNO constants, dwarf column numbers for registers of interest. */
+
+#define REGNO_LR 65
+#define REGNO_XER 76
+#define REGNO_CR 70
+#define REGNO_GR(N) (N)
+
+#define REGNO_PC 67 /* ARG_POINTER_REGNUM */
+
+/* asm string contruction helpers. */
+
+#define STR(TEXT) #TEXT
+/* stringify expanded TEXT, surrounding it with double quotes. */
+
+#define S(E) STR(E)
+/* stringify E, which will resolve as text but may contain macros
+ still to be expanded. */
+
+/* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
+ multine contents: */
+#define TAB(S) "\t" S
+#define CR(S) S "\n"
+#define TCR(S) TAB(CR(S))
+
+/*------------------------------
+ -- Stub construction blocks --
+ ------------------------------ */
+
+/* CFA setup block
+ ---------------
+ Only non-volatile registers are suitable for a CFA base. We use r14
+ here and set it to the value we need in stub body that follows. */
+
+#define CFI_DEF_CFA \
+CR(".cfi_def_cfa 14, 0")
+
+/* Register location blocks
+ ------------------------
+ Rules to find registers of interest from the CFA. This should
+ comprise all the non-volatile registers relevant to the interrupted
+ context. */
+
+#define COMMON_CFI(REG) \
+ ".cfi_offset " S(REGNO_##REG) "," S(REG_SET_##REG)
+
+#define CFI_COMMON_REGS \
+CR("# CFI for common registers\n") \
+TCR(COMMON_CFI(GR(1))) \
+TCR(COMMON_CFI(GR(14))) \
+TCR(COMMON_CFI(GR(15))) \
+TCR(COMMON_CFI(GR(16))) \
+TCR(COMMON_CFI(GR(17))) \
+TCR(COMMON_CFI(GR(18))) \
+TCR(COMMON_CFI(GR(19))) \
+TCR(COMMON_CFI(GR(20))) \
+TCR(COMMON_CFI(GR(21))) \
+TCR(COMMON_CFI(GR(22))) \
+TCR(COMMON_CFI(GR(23))) \
+TCR(COMMON_CFI(GR(24))) \
+TCR(COMMON_CFI(GR(25))) \
+TCR(COMMON_CFI(GR(26))) \
+TCR(COMMON_CFI(GR(27))) \
+TCR(COMMON_CFI(GR(28))) \
+TCR(COMMON_CFI(GR(29))) \
+TCR(COMMON_CFI(GR(30))) \
+TCR(COMMON_CFI(GR(31))) \
+TCR(COMMON_CFI(LR)) \
+TCR(COMMON_CFI(CR)) \
+TCR(COMMON_CFI(PC)) \
+TCR(".cfi_return_column " S(REGNO_PC))
+
+/* Trampoline body block
+ --------------------- */
+
+#define SIGTRAMP_BODY \
+CR("") \
+TCR("# Allocate frame and save the non-volatile") \
+TCR("# registers we're going to modify") \
+TCR("stwu %r1,-16(%r1)") \
+TCR("mflr %r0") \
+TCR("stw %r0,20(%r1)") \
+TCR("stw %r14,8(%r1)") \
+TCR("") \
+TCR("# Setup r14 = sc_pregs, that we'll retrieve as our CFA value") \
+TCR("mr %r14, %r7") \
+TCR("") \
+TCR("# Call the real handler. The signo, siginfo and sigcontext") \
+TCR("# arguments are the same as those we received in r3, r4 and r5") \
+TCR("mtctr %r6") \
+TCR("bctrl") \
+TCR("") \
+TCR("# Restore our callee-saved items, release our frame and return") \
+TCR("lwz %r14,8(%r1)") \
+TCR("lwz %r0,20(%r1)") \
+TCR("mtlr %r0") \
+TCR("") \
+TCR("addi %r1,%r1,16") \
+TCR("blr")
+
+/* Symbol definition block
+ ----------------------- */
+
+#define SIGTRAMP_START(SYM) \
+CR("# " S(SYM) " cfi trampoline") \
+TCR(".type " S(SYM) ", @function") \
+CR("") \
+CR(S(SYM) ":") \
+TCR(".cfi_startproc") \
+TCR(".cfi_signal_frame")
+
+/* Symbol termination block
+ ------------------------ */
+
+#define SIGTRAMP_END(SYM) \
+CR(".cfi_endproc") \
+TCR(".size " S(SYM) ", .-" S(SYM))
+
+/*----------------------------
+ -- And now, the real code --
+ ---------------------------- */
+
+/* Text section start. The compiler isn't aware of that switch. */
+
+asm (".text\n"
+ TCR(".align 2"));
+
+/* sigtramp stub for common registers. */
+
+#define TRAMP_COMMON __gnat_sigtramp_common
+
+asm (SIGTRAMP_START(TRAMP_COMMON));
+asm (CFI_DEF_CFA);
+asm (CFI_COMMON_REGS);
+asm (SIGTRAMP_BODY);
+asm (SIGTRAMP_END(TRAMP_COMMON));
+
+
diff --git a/gcc/ada/sigtramp.h b/gcc/ada/sigtramp.h
new file mode 100644
index 00000000000..5e3cc5b77c9
--- /dev/null
+++ b/gcc/ada/sigtramp.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+ * *
+ * GNAT COMPILER COMPONENTS *
+ * *
+ * S I G T R A M P *
+ * *
+ * C Header File *
+ * *
+ * Copyright (C) 2011, Free Software Foundation, Inc. *
+ * *
+ * GNAT is free software; you can redistribute it and/or modify it under *
+ * terms of the GNU General Public License as published by the Free Soft- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
+ * sion. GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
+ * *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * In particular, you can freely distribute your programs built with the *
+ * GNAT Pro compiler, including any required library run-time units, using *
+ * any licensing terms of your choosing. See the AdaCore Software License *
+ * for full details. *
+ * *
+ * GNAT was originally developed by the GNAT team at New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc. *
+ * *
+ ****************************************************************************/
+
+/* On targets where this is implemented, we resort to a signal handler
+ trampoline to set-up the DWARF Call Frame Information that let unwinders
+ walk through the signal frame up into the interrupted application code.
+ This file introduces the relevant declarations. */
+
+/* This file should only be #included on targets that do implement the
+ trampoline, which needs to expose the following interface: */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef void sighandler_t (int signo, void *siginfo, void *sigcontext);
+
+ void __gnat_sigtramp (int signo, void *siginfo, void *sigcontext,
+ sighandler_t * handler);
+
+ /* To be called from an established signal handler. Setup the DWARF CFI
+ bits letting unwinders walk through the signal frame up into the
+ interrupted application code, and then call HANDLER (SIGNO, SIGINFO,
+ SIGCONTEXT). */
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb
index 75433470b71..916e0ae5843 100644
--- a/gcc/ada/sinfo.adb
+++ b/gcc/ada/sinfo.adb
@@ -249,6 +249,15 @@ package body Sinfo is
return Node3 (N);
end Ancestor_Part;
+ function Atomic_Sync_Required
+ (N : Node_Id) return Boolean is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Expanded_Name
+ or else NT (N).Nkind = N_Identifier);
+ return Flag14 (N);
+ end Atomic_Sync_Required;
+
function Array_Aggregate
(N : Node_Id) return Node_Id is
begin
@@ -3309,6 +3318,15 @@ package body Sinfo is
Set_Node3_With_Parent (N, Val);
end Set_Ancestor_Part;
+ procedure Set_Atomic_Sync_Required
+ (N : Node_Id; Val : Boolean := True) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Expanded_Name
+ or else NT (N).Nkind = N_Identifier);
+ Set_Flag14 (N, Val);
+ end Set_Atomic_Sync_Required;
+
procedure Set_Array_Aggregate
(N : Node_Id; Val : Node_Id) is
begin
diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads
index 3a03c04c7e6..0b5a52f5dc7 100644
--- a/gcc/ada/sinfo.ads
+++ b/gcc/ada/sinfo.ads
@@ -605,6 +605,12 @@ package Sinfo is
-- Since the back end is expected to ignore generic templates, this is
-- harmless.
+ -- Atomic_Sync_Required (Flag14-Sem)
+ -- This flag is set in an identifier or expanded name node if the
+ -- corresponding reference (or assignment when on the left side of
+ -- an assignment) requires atomic synchronization, as a result of
+ -- Atomic_Synchronization being enabled for the corresponding entity.
+
-- At_End_Proc (Node1)
-- This field is present in an N_Handled_Sequence_Of_Statements node.
-- It contains an identifier reference for the cleanup procedure to be
@@ -1917,6 +1923,7 @@ package Sinfo is
-- Associated_Node (Node4-Sem)
-- Original_Discriminant (Node2-Sem)
-- Redundant_Use (Flag13-Sem)
+ -- Atomic_Sync_Required (Flag14-Sem)
-- Has_Private_View (Flag11-Sem) (set in generic units)
-- plus fields for expression
@@ -6982,8 +6989,9 @@ package Sinfo is
-- Selector_Name (Node2)
-- Entity (Node4-Sem)
-- Associated_Node (Node4-Sem)
- -- Redundant_Use (Flag13-Sem)
-- Has_Private_View (Flag11-Sem) set in generic units.
+ -- Redundant_Use (Flag13-Sem)
+ -- Atomic_Sync_Required (Flag14-Sem)
-- plus fields for expression
-----------------------------
@@ -8121,6 +8129,9 @@ package Sinfo is
function Ancestor_Part
(N : Node_Id) return Node_Id; -- Node3
+ function Atomic_Sync_Required
+ (N : Node_Id) return Boolean; -- Flag14
+
function Array_Aggregate
(N : Node_Id) return Node_Id; -- Node3
@@ -9096,6 +9107,9 @@ package Sinfo is
procedure Set_Ancestor_Part
(N : Node_Id; Val : Node_Id); -- Node3
+ procedure Set_Atomic_Sync_Required
+ (N : Node_Id; Val : Boolean := True); -- Flag14
+
procedure Set_Array_Aggregate
(N : Node_Id; Val : Node_Id); -- Node3
@@ -11764,6 +11778,7 @@ package Sinfo is
pragma Inline (All_Present);
pragma Inline (Alternatives);
pragma Inline (Ancestor_Part);
+ pragma Inline (Atomic_Sync_Required);
pragma Inline (Array_Aggregate);
pragma Inline (Aspect_Rep_Item);
pragma Inline (Assignment_OK);
@@ -12086,6 +12101,7 @@ package Sinfo is
pragma Inline (Set_All_Present);
pragma Inline (Set_Alternatives);
pragma Inline (Set_Ancestor_Part);
+ pragma Inline (Set_Atomic_Sync_Required);
pragma Inline (Set_Array_Aggregate);
pragma Inline (Set_Aspect_Rep_Item);
pragma Inline (Set_Assignment_OK);
diff --git a/gcc/ada/snames.ads-tmpl b/gcc/ada/snames.ads-tmpl
index f7c441e97aa..3ed2a668e00 100644
--- a/gcc/ada/snames.ads-tmpl
+++ b/gcc/ada/snames.ads-tmpl
@@ -361,10 +361,12 @@ package Snames is
Name_Debug_Policy : constant Name_Id := N + $; -- GNAT
Name_Detect_Blocking : constant Name_Id := N + $; -- Ada 05
Name_Default_Storage_Pool : constant Name_Id := N + $; -- Ada 12
+ Name_Disable_Atomic_Synchronization : constant Name_Id := N + $; -- GNAT
Name_Discard_Names : constant Name_Id := N + $;
Name_Dispatching_Domain : constant Name_Id := N + $; -- Ada 12
Name_Elaboration_Checks : constant Name_Id := N + $; -- GNAT
Name_Eliminate : constant Name_Id := N + $; -- GNAT
+ Name_Enable_Atomic_Synchronization : constant Name_Id := N + $; -- GNAT
Name_Extend_System : constant Name_Id := N + $; -- GNAT
Name_Extensions_Allowed : constant Name_Id := N + $; -- GNAT
Name_External_Name_Casing : constant Name_Id := N + $; -- GNAT
@@ -941,10 +943,14 @@ package Snames is
-- Names of recognized checks for pragma Suppress
+ -- Note: the name Atomic_Synchronization can only be specified internally
+ -- as a result of using pragma Enable/Disable_Atomic_Synchronization.
+
First_Check_Name : constant Name_Id := N + $;
Name_Access_Check : constant Name_Id := N + $;
Name_Accessibility_Check : constant Name_Id := N + $;
Name_Alignment_Check : constant Name_Id := N + $; -- GNAT
+ Name_Atomic_Synchronization : constant Name_Id := N + $; -- GNAT
Name_Discriminant_Check : constant Name_Id := N + $;
Name_Division_Check : constant Name_Id := N + $;
Name_Elaboration_Check : constant Name_Id := N + $;
@@ -1532,10 +1538,12 @@ package Snames is
Pragma_Debug_Policy,
Pragma_Detect_Blocking,
Pragma_Default_Storage_Pool,
+ Pragma_Disable_Atomic_Synchronization,
Pragma_Discard_Names,
Pragma_Dispatching_Domain,
Pragma_Elaboration_Checks,
Pragma_Eliminate,
+ Pragma_Enable_Atomic_Synchronization,
Pragma_Extend_System,
Pragma_Extensions_Allowed,
Pragma_External_Name_Casing,
diff --git a/gcc/ada/switch-c.adb b/gcc/ada/switch-c.adb
index 58d4e13e7ac..e900faa4bd2 100644
--- a/gcc/ada/switch-c.adb
+++ b/gcc/ada/switch-c.adb
@@ -440,6 +440,11 @@ package body Switch.C is
-- Ptr := Ptr + 1;
-- Generate_SCIL := True;
+ -- -gnated switch (disable atomic synchronization)
+
+ when 'd' =>
+ Suppress_Options (Atomic_Synchronization) := True;
+
-- -gnateD switch (preprocessing symbol definition)
when 'D' =>
@@ -743,10 +748,14 @@ package body Switch.C is
-- Set all specific options as well as All_Checks in the
-- Suppress_Options array, excluding Elaboration_Check,
-- since this is treated specially because we do not want
- -- -gnatp to disable static elaboration processing.
+ -- -gnatp to disable static elaboration processing. Also
+ -- exclude Atomic_Synchronization, since this is not a real
+ -- check.
for J in Suppress_Options'Range loop
- if J /= Elaboration_Check then
+ if J /= Elaboration_Check
+ and then J /= Atomic_Synchronization
+ then
Suppress_Options (J) := True;
end if;
end loop;
diff --git a/gcc/ada/switch-m.adb b/gcc/ada/switch-m.adb
index 93583f0ada7..3dbecc31cc9 100644
--- a/gcc/ada/switch-m.adb
+++ b/gcc/ada/switch-m.adb
@@ -196,6 +196,24 @@ package body Switch.M is
Add_Switch_Component ("-mrtp");
end if;
+ -- Switch for universal addressing on AAMP target
+
+ elsif Switch_Chars'Length >= 5
+ and then
+ Switch_Chars
+ (Switch_Chars'First .. Switch_Chars'First + 4) = "-univ"
+ then
+ Add_Switch_Component (Switch_Chars);
+
+ -- Switch for specifying AAMP target library
+
+ elsif Switch_Chars'Length > 13
+ and then
+ Switch_Chars (Switch_Chars'First .. Switch_Chars'First + 12)
+ = "-aamp_target="
+ then
+ Add_Switch_Component (Switch_Chars);
+
-- Take only into account switches that are transmitted to
-- gnat1 by the gcc driver and stored by gnat1 in the ALI file.
diff --git a/gcc/ada/sysdep.c b/gcc/ada/sysdep.c
index 696630ec298..4d383fd0608 100644
--- a/gcc/ada/sysdep.c
+++ b/gcc/ada/sysdep.c
@@ -911,8 +911,7 @@ __gnat_get_task_options (void)
/* Force VX_FP_TASK because it is almost always required */
options |= VX_FP_TASK;
-#if defined (__SPE__) && (! defined (__VXWORKSMILS__)) \
- && (! defined (VTHREADS))
+#if defined (__SPE__) && (! defined (__VXWORKSMILS__))
options |= VX_SPE_TASK;
#endif
diff --git a/gcc/ada/tb-alvms.c b/gcc/ada/tb-alvms.c
index d69128b9271..1fd837e150c 100644
--- a/gcc/ada/tb-alvms.c
+++ b/gcc/ada/tb-alvms.c
@@ -1,29 +1,28 @@
/****************************************************************************
* *
- * GNAT COMPILER COMPONENTS *
+ * GNAT RUN-TIME COMPONENTS *
* *
* T R A C E B A C K - A l p h a / V M S *
* *
* C Implementation File *
* *
- * Copyright (C) 2003-2007, AdaCore *
+ * Copyright (C) 2003-2011, AdaCore *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
- * ware Foundation; either version 2, or (at your option) any later ver- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
* sion. GNAT is distributed in the hope that it will be useful, but WITH- *
* OUT 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 distributed with GNAT; see file COPYING. If not, write *
- * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
- * Boston, MA 02110-1301, USA. *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
* *
- * As a special exception, if you link this file with other files to *
- * produce an executable, this file does not by itself cause the resulting *
- * executable to be covered by the GNU General Public License. This except- *
- * ion does not however invalidate any other reasons why the executable *
- * file might be covered by the GNU Public License. *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
* *
* GNAT was originally developed by the GNAT team at New York University. *
* Extensive contributions were provided by Ada Core Technologies Inc. *
diff --git a/gcc/ada/tb-alvxw.c b/gcc/ada/tb-alvxw.c
index 381c9b0406a..4f743a110a7 100644
--- a/gcc/ada/tb-alvxw.c
+++ b/gcc/ada/tb-alvxw.c
@@ -1,29 +1,28 @@
/****************************************************************************
* *
- * GNAT COMPILER COMPONENTS *
+ * GNAT RUN-TIME COMPONENTS *
* *
* T R A C E B A C K - A l p h a / V x W o r k s *
* *
* C Implementation File *
* *
- * Copyright (C) 2000-2006, AdaCore *
+ * Copyright (C) 2000-2011, AdaCore *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
- * ware Foundation; either version 2, or (at your option) any later ver- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
* sion. GNAT is distributed in the hope that it will be useful, but WITH- *
* OUT 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 distributed with GNAT; see file COPYING. If not, write *
- * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
- * Boston, MA 02110-1301, USA. *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
* *
- * As a special exception, if you link this file with other files to *
- * produce an executable, this file does not by itself cause the resulting *
- * executable to be covered by the GNU General Public License. This except- *
- * ion does not however invalidate any other reasons why the executable *
- * file might be covered by the GNU Public License. *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
* *
* GNAT was originally developed by the GNAT team at New York University. *
* Extensive contributions were provided by Ada Core Technologies Inc. *
diff --git a/gcc/ada/tb-gcc.c b/gcc/ada/tb-gcc.c
index 22432b4e6ad..7b7c27ad24c 100644
--- a/gcc/ada/tb-gcc.c
+++ b/gcc/ada/tb-gcc.c
@@ -1,29 +1,28 @@
/****************************************************************************
* *
- * GNAT COMPILER COMPONENTS *
+ * GNAT RUN-TIME COMPONENTS *
* *
* T R A C E B A C K - G C C t a b l e s *
* *
* C Implementation File *
* *
- * Copyright (C) 2004-2009, Free Software Foundation, Inc. *
+ * Copyright (C) 2004-2011, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
- * ware Foundation; either version 2, or (at your option) any later ver- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
* sion. GNAT is distributed in the hope that it will be useful, but WITH- *
* OUT 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 distributed with GNAT; see file COPYING. If not, write *
- * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
- * Boston, MA 02110-1301, USA. *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
* *
- * As a special exception, if you link this file with other files to *
- * produce an executable, this file does not by itself cause the resulting *
- * executable to be covered by the GNU General Public License. This except- *
- * ion does not however invalidate any other reasons why the executable *
- * file might be covered by the GNU Public License. *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
* *
* GNAT was originally developed by the GNAT team at New York University. *
* Extensive contributions were provided by Ada Core Technologies Inc. *
diff --git a/gcc/ada/tb-ivms.c b/gcc/ada/tb-ivms.c
index 24afdb54e05..3d55c6e8627 100644
--- a/gcc/ada/tb-ivms.c
+++ b/gcc/ada/tb-ivms.c
@@ -1,29 +1,28 @@
/****************************************************************************
* *
- * GNAT COMPILER COMPONENTS *
+ * GNAT RUN-TIME COMPONENTS *
* *
* T R A C E B A C K - I t a n i u m / V M S *
* *
* C Implementation File *
* *
- * Copyright (C) 2007, AdaCore *
+ * Copyright (C) 2007-2011, AdaCore *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
- * ware Foundation; either version 2, or (at your option) any later ver- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
* sion. GNAT is distributed in the hope that it will be useful, but WITH- *
* OUT 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 distributed with GNAT; see file COPYING. If not, write *
- * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
- * Boston, MA 02110-1301, USA. *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
* *
- * As a special exception, if you link this file with other files to *
- * produce an executable, this file does not by itself cause the resulting *
- * executable to be covered by the GNU General Public License. This except- *
- * ion does not however invalidate any other reasons why the executable *
- * file might be covered by the GNU Public License. *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
* *
* GNAT was originally developed by the GNAT team at New York University. *
* Extensive contributions were provided by Ada Core Technologies Inc. *
diff --git a/gcc/ada/tracebak.c b/gcc/ada/tracebak.c
index ea7bbfe51c3..ff2a3b6cfdb 100644
--- a/gcc/ada/tracebak.c
+++ b/gcc/ada/tracebak.c
@@ -1,6 +1,6 @@
/****************************************************************************
* *
- * GNAT COMPILER COMPONENTS *
+ * GNAT RUN-TIME COMPONENTS *
* *
* T R A C E B A C K *
* *
@@ -10,20 +10,19 @@
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
- * ware Foundation; either version 2, or (at your option) any later ver- *
+ * ware Foundation; either version 3, or (at your option) any later ver- *
* sion. GNAT is distributed in the hope that it will be useful, but WITH- *
* OUT 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 distributed with GNAT; see file COPYING. If not, write *
- * to the Free Software Foundation, 51 Franklin Street, Fifth Floor, *
- * Boston, MA 02110-1301, USA. *
+ * or FITNESS FOR A PARTICULAR PURPOSE. *
* *
- * As a special exception, if you link this file with other files to *
- * produce an executable, this file does not by itself cause the resulting *
- * executable to be covered by the GNU General Public License. This except- *
- * ion does not however invalidate any other reasons why the executable *
- * file might be covered by the GNU Public License. *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception, *
+ * version 3.1, as published by the Free Software Foundation. *
+ * *
+ * You should have received a copy of the GNU General Public License and *
+ * a copy of the GCC Runtime Library Exception along with this program; *
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
+ * <http://www.gnu.org/licenses/>. *
* *
* GNAT was originally developed by the GNAT team at New York University. *
* Extensive contributions were provided by Ada Core Technologies Inc. *
@@ -207,7 +206,7 @@ extern void (*Unlock_Task) (void);
#if defined (__APPLE__) \
&& defined (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) \
&& __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040
-
+
#define USE_GCC_UNWINDER
#if defined (__i386__) || defined (__x86_64__)
diff --git a/gcc/ada/types.ads b/gcc/ada/types.ads
index 0422d82b7e8..05d3dbe1b9d 100644
--- a/gcc/ada/types.ads
+++ b/gcc/ada/types.ads
@@ -660,22 +660,25 @@ package Types is
No_Check_Id : constant := 0;
-- Check_Id value used to indicate no check
- Access_Check : constant := 1;
- Accessibility_Check : constant := 2;
- Alignment_Check : constant := 3;
- Discriminant_Check : constant := 4;
- Division_Check : constant := 5;
- Elaboration_Check : constant := 6;
- Index_Check : constant := 7;
- Length_Check : constant := 8;
- Overflow_Check : constant := 9;
- Range_Check : constant := 10;
- Storage_Check : constant := 11;
- Tag_Check : constant := 12;
- Validity_Check : constant := 13;
- -- Values used to represent individual predefined checks
-
- All_Checks : constant := 14;
+ Access_Check : constant := 1;
+ Accessibility_Check : constant := 2;
+ Alignment_Check : constant := 3;
+ Atomic_Synchronization : constant := 4;
+ Discriminant_Check : constant := 5;
+ Division_Check : constant := 6;
+ Elaboration_Check : constant := 7;
+ Index_Check : constant := 8;
+ Length_Check : constant := 9;
+ Overflow_Check : constant := 10;
+ Range_Check : constant := 11;
+ Storage_Check : constant := 12;
+ Tag_Check : constant := 13;
+ Validity_Check : constant := 14;
+ -- Values used to represent individual predefined checks (including the
+ -- setting of Atomic_Synchronization, which is implemented internally using
+ -- a "check" whose name is Atomic_Synchronization.
+
+ All_Checks : constant := 15;
-- Value used to represent All_Checks value
subtype Predefined_Check_Id is Check_Id range 1 .. All_Checks;
diff --git a/gcc/ada/usage.adb b/gcc/ada/usage.adb
index 146b0c043f3..2c20136af7e 100644
--- a/gcc/ada/usage.adb
+++ b/gcc/ada/usage.adb
@@ -172,6 +172,11 @@ begin
Write_Switch_Char ("ec=?");
Write_Line ("Specify configuration pragmas file, e.g. -gnatec=/x/f.adc");
+ -- Line for -gnated switch
+
+ Write_Switch_Char ("ed");
+ Write_Line ("Disable synchronization of atomic variables");
+
-- Line for -gnateD switch
Write_Switch_Char ("eD?");
diff --git a/gcc/ada/vms_data.ads b/gcc/ada/vms_data.ads
index 1da9855245a..bfda0a73c56 100644
--- a/gcc/ada/vms_data.ads
+++ b/gcc/ada/vms_data.ads
@@ -6119,6 +6119,30 @@ package VMS_Data is
-- See 'HELP GNAT COMPILE /WIDE_CHARACTER_ENCODING' for an explanation
-- about the different character encoding methods.
+ S_Pretty_Enums : aliased constant S := "/ENUM_CASING=" &
+ "AS_DECLARED " &
+ "-neD " &
+ "LOWER_CASE " &
+ "-neL " &
+ "UPPER_CASE " &
+ "-neU " &
+ "MIXED_CASE " &
+ "-neM";
+ -- /ENUM_CASING=name-option
+ --
+ -- Specify the casing of enumeration literals. If not specified, the
+ -- casing of enumeration literals is defined by the NAME_CASING option.
+ -- 'name-option' may be one of:
+ --
+ -- AS_DECLARED Literals casing for defining occurrences are
+ -- as they appear in the source file.
+ --
+ -- LOWER_CASE Literals are in lower case.
+ --
+ -- UPPER_CASE Literals are in upper case.
+ --
+ -- MIXED_CASE Literals are in mixed case.
+
S_Pretty_Files : aliased constant S := "/FILES=@" &
"-files=@";
-- /FILES=filename
@@ -6369,6 +6393,7 @@ package VMS_Data is
S_Pretty_Eol 'Access,
S_Pretty_Ext 'Access,
S_Pretty_Encoding 'Access,
+ S_Pretty_Enums 'Access,
S_Pretty_Files 'Access,
S_Pretty_Follow 'Access,
S_Pretty_Forced 'Access,
diff --git a/gcc/ada/warnsw.adb b/gcc/ada/warnsw.adb
index 711b9438dbd..703ce0c257e 100644
--- a/gcc/ada/warnsw.adb
+++ b/gcc/ada/warnsw.adb
@@ -67,6 +67,7 @@ package body Warnsw is
Warn_On_All_Unread_Out_Parameters := True;
Warn_On_Assertion_Failure := True;
Warn_On_Assumed_Low_Bound := True;
+ Warn_On_Atomic_Synchronization := True;
Warn_On_Bad_Fixed_Value := True;
Warn_On_Biased_Representation := True;
Warn_On_Constant := True;
@@ -120,6 +121,12 @@ package body Warnsw is
when 'M' =>
Warn_On_Suspicious_Modulus_Value := False;
+ when 'n' =>
+ Warn_On_Atomic_Synchronization := True;
+
+ when 'N' =>
+ Warn_On_Atomic_Synchronization := False;
+
when 'o' =>
Warn_On_All_Unread_Out_Parameters := True;
@@ -202,6 +209,7 @@ package body Warnsw is
Warn_On_All_Unread_Out_Parameters := False;
Warn_On_Assertion_Failure := True;
Warn_On_Assumed_Low_Bound := True;
+ Warn_On_Atomic_Synchronization := False;
Warn_On_Bad_Fixed_Value := True;
Warn_On_Biased_Representation := True;
Warn_On_Constant := True;
@@ -212,12 +220,16 @@ package body Warnsw is
Warn_On_Modified_Unread := True;
Warn_On_No_Value_Assigned := True;
Warn_On_Non_Local_Exception := False;
- Warn_On_Object_Renames_Function := False;
+ Warn_On_Object_Renames_Function := True;
Warn_On_Obsolescent_Feature := True;
+ Warn_On_Overlap := True;
+ Warn_On_Overridden_Size := True;
+ Warn_On_Parameter_Order := True;
Warn_On_Questionable_Missing_Parens := True;
+ Warn_On_Record_Holes := False;
Warn_On_Redundant_Constructs := True;
Warn_On_Reverse_Bit_Order := False;
- Warn_On_Object_Renames_Function := True;
+ Warn_On_Suspicious_Contract := True;
Warn_On_Unchecked_Conversion := True;
Warn_On_Unordered_Enumeration_Type := False;
Warn_On_Unrecognized_Pragma := True;
diff --git a/gcc/ada/warnsw.ads b/gcc/ada/warnsw.ads
index f1449f8ef3f..9fd998bf457 100644
--- a/gcc/ada/warnsw.ads
+++ b/gcc/ada/warnsw.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1999-2010, Free Software Foundation, Inc. --
+-- Copyright (C) 1999-2011, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -65,6 +65,10 @@ package Warnsw is
procedure Set_GNAT_Mode_Warnings;
-- This is called in -gnatg mode to set the warnings for gnat mode. It is
- -- also used to set the proper warning statuses for -gnatw.g.
+ -- also used to set the proper warning statuses for -gnatw.g. Note that
+ -- this set of warnings is disjoint from -gnatwa, it enables warnings that
+ -- are not included in -gnatwa, and it disables warnings that are included
+ -- in -gnatwa (such as Warn_On_Implementation_Units, which we clearly want
+ -- to be False for units built with -gnatg).
end Warnsw;
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 6a9d5657d3f..7d23469e053 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -9031,7 +9031,7 @@ fold_builtin_memchr (location_t loc, tree arg1, tree arg2, tree len, tree type)
if (target_char_cast (arg2, &c))
return NULL_TREE;
- r = (char *) memchr (p1, c, tree_low_cst (len, 1));
+ r = (const char *) memchr (p1, c, tree_low_cst (len, 1));
if (r == NULL)
return build_int_cst (TREE_TYPE (arg1), 0);
@@ -14109,8 +14109,7 @@ set_builtin_user_assembler_name (tree decl, const char *asmspec)
&& asmspec != 0);
builtin = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
- set_user_assembler_name (
-builtin, asmspec);
+ set_user_assembler_name (builtin, asmspec);
switch (DECL_FUNCTION_CODE (decl))
{
case BUILT_IN_MEMCPY:
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 3a26e170ecc..472ed282d5e 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,120 @@
+2011-11-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/44277
+ * c.opt: Add Wzero-as-null-pointer-constant.
+
+2011-10-31 Jason Merrill <jason@redhat.com>
+
+ * c.opt (-fdeduce-init-list): Off by default.
+
+ PR c++/50920
+ * c-common.h (cxx_dialect): Add cxx11 and cxx03.
+ * c.opt: Add -std=c++11, -std=gnu++11, -std=gnu++03,
+ and -Wc++11-compat.
+ * c-opts.c (set_std_cxx11): Rename from set_std_cxx0x.
+
+2011-10-27 Roberto Agostino Vitillo <ravitillo@lbl.gov>
+
+ PR c++/30066
+ * c.opt (fvisibility-inlines-hidden): Description change.
+
+2011-10-26 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++11 user-defined literals.
+ * c-common.c (build_userdef_literal): New.
+ * c-common.def: New tree code.
+ * c-common.h (tree_userdef_literal): New tree struct and accessors.
+ * c-lex.c (interpret_float): Add suffix parm.
+ (c_lex_with_flags): Build literal tokens.
+
+2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50841
+ Revert:
+ 2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50810
+ * c-opts.c (c_common_handle_option): Enable -Wnarrowing as part
+ of -Wall; include -Wnarrowing in -Wc++0x-compat; adjust default
+ Wnarrowing for C++0x and C++98.
+ * c.opt ([Wnarrowing]): Update.
+
+2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50810
+ * c-opts.c (c_common_handle_option): Enable -Wnarrowing as part
+ of -Wall; include -Wnarrowing in -Wc++0x-compat; adjust default
+ Wnarrowing for C++0x and C++98.
+ * c.opt ([Wnarrowing]): Update.
+
+2011-10-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/45385
+ * c-common.c (conversion_warning): Remove code looking for
+ artificial operands.
+
+2011-10-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR bootstrap/50760
+ * c-lex.c (fe_file_change): Use LINEMAP_SYSP when
+ !NO_IMPLICIT_EXTERN_C.
+
+2011-10-17 Michael Spertus <mike_spertus@symantec.com>
+
+ * c-common.c (c_common_reswords): Add __bases,
+ __direct_bases.
+ * c-common.h: Add RID_BASES and RID_DIRECT_BASES.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50757
+ * c.opt ([Wnonnull]): Add C++ and Objective-C++.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * c.opt (fdebug-cpp): New option.
+ * c-opts.c (c_common_handle_option): Handle the option.
+ * c-ppoutput.c (maybe_print_line_1): New static function. Takes an
+ output stream in parameter. Factorized from ...
+ (maybe_print_line): ... this. Dump location debug information when
+ -fdebug-cpp is in effect.
+ (print_line_1): New static function. Takes an output stream in
+ parameter. Factorized from ...
+ (print_line): ... here. Dump location information when -fdebug-cpp
+ is in effect.
+ (scan_translation_unit): Dump location information when
+ -fdebug-cpp is in effect.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * c.opt (ftrack-macro-expansion): New option. Handle it with and
+ without argument.
+ * c-opts.c (c_common_handle_option)<case
+ OPT_ftrack_macro_expansion_, case OPT_ftrack_macro_expansion>: New
+ cases. Handle -ftrack-macro-expansion with and without argument.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * c-ppoutput.c (scan_translation_unit, maybe_print_line)
+ (print_line, cb_define, do_line_change): Adjust to avoid touching
+ the internals of struct line_map. Use the public API instead.
+ * c-pch.c (c_common_read_pch): Likewise.
+ * c-lex.c (fe_file_change): Likewise.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/17212
+ * c.opt ([Wformat-zero-length]): Add C++ and Objective-C++.
+
+2011-10-11 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/33067
+ * c-pretty-print.c (pp_c_floating_constant): Output
+ max_digits10 (in the ISO C++ WG N1822 sense) decimal digits.
+
2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
* c-common.c (def_builtin_1): Delete old interface with two
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 855b5d6f325..1a10729b34d 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -423,6 +423,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__asm__", RID_ASM, 0 },
{ "__attribute", RID_ATTRIBUTE, 0 },
{ "__attribute__", RID_ATTRIBUTE, 0 },
+ { "__bases", RID_BASES, D_CXXONLY },
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
{ "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
{ "__builtin_shuffle", RID_BUILTIN_SHUFFLE, D_CONLY },
@@ -434,6 +435,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__const", RID_CONST, 0 },
{ "__const__", RID_CONST, 0 },
{ "__decltype", RID_DECLTYPE, D_CXXONLY },
+ { "__direct_bases", RID_DIRECT_BASES, D_CXXONLY },
{ "__extension__", RID_EXTENSION, 0 },
{ "__func__", RID_C99_FUNCTION_NAME, 0 },
{ "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
@@ -2119,23 +2121,12 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns)
static void
conversion_warning (tree type, tree expr)
{
- int i;
- const int expr_num_operands = TREE_OPERAND_LENGTH (expr);
tree expr_type = TREE_TYPE (expr);
location_t loc = EXPR_LOC_OR_HERE (expr);
if (!warn_conversion && !warn_sign_conversion)
return;
- /* If any operand is artificial, then this expression was generated
- by the compiler and we do not warn. */
- for (i = 0; i < expr_num_operands; i++)
- {
- tree op = TREE_OPERAND (expr, i);
- if (op && DECL_P (op) && DECL_ARTIFICIAL (op))
- return;
- }
-
switch (TREE_CODE (expr))
{
case EQ_EXPR:
@@ -10395,4 +10386,17 @@ c_common_init_ts (void)
MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
}
+/* Build a user-defined numeric literal out of an integer constant type VALUE
+ with identifier SUFFIX. */
+
+tree
+build_userdef_literal (tree suffix_id, tree value, tree num_string)
+{
+ tree literal = make_node (USERDEF_LITERAL);
+ USERDEF_LITERAL_SUFFIX_ID (literal) = suffix_id;
+ USERDEF_LITERAL_VALUE (literal) = value;
+ USERDEF_LITERAL_NUM_STRING (literal) = num_string;
+ return literal;
+}
+
#include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def
index c7e01b693ca..2a7df882d0a 100644
--- a/gcc/c-family/c-common.def
+++ b/gcc/c-family/c-common.def
@@ -47,6 +47,12 @@ DEFTREECODE (C_MAYBE_CONST_EXPR, "c_maybe_const_expr", tcc_expression, 2)
evaluated. */
DEFTREECODE (EXCESS_PRECISION_EXPR, "excess_precision_expr", tcc_expression, 1)
+/* Used to represent a user-defined literal.
+ The operands are an IDENTIFIER for the suffix, the VALUE of the literal,
+ and for numeric literals the original string representation of the
+ number. */
+DEFTREECODE (USERDEF_LITERAL, "userdef_literal", tcc_exceptional, 3)
+
/*
Local variables:
mode:c
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 8996eefd22b..71746a949d3 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -128,12 +128,13 @@ enum rid
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
/* C++ extensions */
+ RID_BASES, RID_DIRECT_BASES,
RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_VIRTUAL_DESTRUCTOR,
RID_IS_ABSTRACT, RID_IS_BASE_OF,
- RID_IS_CONVERTIBLE_TO, RID_IS_CLASS,
+ RID_IS_CLASS, RID_IS_CONVERTIBLE_TO,
RID_IS_EMPTY, RID_IS_ENUM,
RID_IS_LITERAL_TYPE, RID_IS_POD,
RID_IS_POLYMORPHIC, RID_IS_STD_LAYOUT,
@@ -642,11 +643,12 @@ extern int flag_use_repository;
/* The supported C++ dialects. */
enum cxx_dialect {
- /* C++98 */
+ /* C++98 with TC1 */
cxx98,
- /* Experimental features that are likely to become part of
- C++0x. */
- cxx0x
+ cxx03 = cxx98,
+ /* C++11 */
+ cxx0x,
+ cxx11 = cxx0x
};
/* The C++ dialect being used. C++98 is the default. */
@@ -1066,4 +1068,27 @@ c_tree_chain_next (tree t)
return NULL;
}
+/* A suffix-identifier value doublet that represents user-defined literals
+ for C++-0x. */
+struct GTY(()) tree_userdef_literal {
+ struct tree_base base;
+ tree suffix_id;
+ tree value;
+ tree num_string;
+};
+
+#define USERDEF_LITERAL_SUFFIX_ID(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->suffix_id)
+
+#define USERDEF_LITERAL_VALUE(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->value)
+
+#define USERDEF_LITERAL_NUM_STRING(NODE) \
+ (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string)
+
+#define USERDEF_LITERAL_TYPE(NODE) \
+ (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE)))
+
+extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string);
+
#endif /* ! GCC_C_COMMON_H */
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index e60dcc53588..7b220abd4b8 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -45,7 +45,7 @@ int pending_lang_change; /* If we need to switch languages - C++ only */
int c_header_level; /* depth in C headers - C++ only */
static tree interpret_integer (const cpp_token *, unsigned int);
-static tree interpret_float (const cpp_token *, unsigned int);
+static tree interpret_float (const cpp_token *, unsigned int, const char *);
static tree interpret_fixed (const cpp_token *, unsigned int);
static enum integer_type_kind narrowest_unsigned_type
(unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, unsigned int);
@@ -207,11 +207,11 @@ fe_file_change (const struct line_map *new_map)
line = SOURCE_LINE (new_map - 1, included_at);
input_location = new_map->start_location;
- (*debug_hooks->start_source_file) (line, new_map->to_file);
+ (*debug_hooks->start_source_file) (line, LINEMAP_FILE (new_map));
#ifndef NO_IMPLICIT_EXTERN_C
if (c_header_level)
++c_header_level;
- else if (new_map->sysp == 2)
+ else if (LINEMAP_SYSP (new_map) == 2)
{
c_header_level = 1;
++pending_lang_change;
@@ -224,17 +224,17 @@ fe_file_change (const struct line_map *new_map)
#ifndef NO_IMPLICIT_EXTERN_C
if (c_header_level && --c_header_level == 0)
{
- if (new_map->sysp == 2)
+ if (LINEMAP_SYSP (new_map) == 2)
warning (0, "badly nested C headers from preprocessor");
--pending_lang_change;
}
#endif
input_location = new_map->start_location;
- (*debug_hooks->end_source_file) (new_map->to_line);
+ (*debug_hooks->end_source_file) (LINEMAP_LINE (new_map));
}
- update_header_times (new_map->to_file);
+ update_header_times (LINEMAP_FILE (new_map));
input_location = new_map->start_location;
}
@@ -314,7 +314,8 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
case CPP_NUMBER:
{
- unsigned int flags = cpp_classify_number (parse_in, tok);
+ const char *suffix = NULL;
+ unsigned int flags = cpp_classify_number (parse_in, tok, &suffix);
switch (flags & CPP_N_CATEGORY)
{
@@ -332,12 +333,29 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
break;
case CPP_N_FLOATING:
- *value = interpret_float (tok, flags);
+ *value = interpret_float (tok, flags, suffix);
break;
default:
gcc_unreachable ();
}
+
+ if (flags & CPP_N_USERDEF)
+ {
+ tree suffix_id = get_identifier (suffix);
+ int len = tok->val.str.len - strlen (suffix);
+ /* If this is going to be used as a C string to pass to a
+ raw literal operator, we need to add a trailing NUL. */
+ tree num_string = build_string (len + 1,
+ (const char *) tok->val.str.text);
+ TREE_TYPE (num_string) = char_array_type_node;
+ num_string = fix_string_type (num_string);
+ char *str = CONST_CAST (char *, TREE_STRING_POINTER (num_string));
+ str[len] = '\0';
+ tree literal = build_userdef_literal (suffix_id, *value,
+ num_string);
+ *value = literal;
+ }
}
break;
@@ -415,6 +433,22 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
}
goto retry;
+ case CPP_CHAR_USERDEF:
+ case CPP_WCHAR_USERDEF:
+ case CPP_CHAR16_USERDEF:
+ case CPP_CHAR32_USERDEF:
+ {
+ tree literal;
+ cpp_token temp_tok = *tok;
+ const char *suffix = cpp_get_userdef_suffix (tok);
+ temp_tok.val.str.len -= strlen (suffix);
+ temp_tok.type = cpp_userdef_char_remove_type (type);
+ literal = build_userdef_literal (get_identifier (suffix),
+ lex_charconst (&temp_tok), NULL_TREE);
+ *value = literal;
+ }
+ break;
+
case CPP_CHAR:
case CPP_WCHAR:
case CPP_CHAR16:
@@ -422,6 +456,22 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags,
*value = lex_charconst (tok);
break;
+ case CPP_STRING_USERDEF:
+ case CPP_WSTRING_USERDEF:
+ case CPP_STRING16_USERDEF:
+ case CPP_STRING32_USERDEF:
+ case CPP_UTF8STRING_USERDEF:
+ {
+ tree literal, string;
+ const char *suffix = cpp_get_userdef_suffix (tok);
+ string = build_string (tok->val.str.len - strlen (suffix),
+ (const char *) tok->val.str.text);
+ literal = build_userdef_literal (get_identifier (suffix),
+ string, NULL_TREE);
+ *value = literal;
+ }
+ break;
+
case CPP_STRING:
case CPP_WSTRING:
case CPP_STRING16:
@@ -621,9 +671,10 @@ interpret_integer (const cpp_token *token, unsigned int flags)
}
/* Interpret TOKEN, a floating point number with FLAGS as classified
- by cpplib. */
+ by cpplib. For C++0X SUFFIX may contain a user-defined literal suffix. */
static tree
-interpret_float (const cpp_token *token, unsigned int flags)
+interpret_float (const cpp_token *token, unsigned int flags,
+ const char *suffix)
{
tree type;
tree const_type;
@@ -702,7 +753,9 @@ interpret_float (const cpp_token *token, unsigned int flags)
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_DFLOAT)
+ if (flags & CPP_N_USERDEF)
+ copylen -= strlen (suffix);
+ else if (flags & CPP_N_DFLOAT)
copylen -= 2;
else
{
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 49ff80dda7e..b56aec79906 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -110,7 +110,7 @@ static size_t include_cursor;
static void handle_OPT_d (const char *);
static void set_std_cxx98 (int);
-static void set_std_cxx0x (int);
+static void set_std_cxx11 (int);
static void set_std_c89 (int, int);
static void set_std_c99 (int);
static void set_std_c1x (int);
@@ -628,6 +628,22 @@ c_common_handle_option (size_t scode, const char *arg, int value,
cpp_opts->preprocessed = value;
break;
+ case OPT_fdebug_cpp:
+ cpp_opts->debug = 1;
+ break;
+
+ case OPT_ftrack_macro_expansion:
+ if (value)
+ value = 2;
+ /* Fall Through. */
+
+ case OPT_ftrack_macro_expansion_:
+ if (arg && *arg != '\0')
+ cpp_opts->track_macro_expansion = value;
+ else
+ cpp_opts->track_macro_expansion = 2;
+ break;
+
case OPT_frepo:
flag_use_repository = value;
if (value)
@@ -759,10 +775,10 @@ c_common_handle_option (size_t scode, const char *arg, int value,
set_std_cxx98 (code == OPT_std_c__98 /* ISO */);
break;
- case OPT_std_c__0x:
- case OPT_std_gnu__0x:
+ case OPT_std_c__11:
+ case OPT_std_gnu__11:
if (!preprocessing_asm_p)
- set_std_cxx0x (code == OPT_std_c__0x /* ISO */);
+ set_std_cxx11 (code == OPT_std_c__11 /* ISO */);
break;
case OPT_std_c90:
@@ -1485,18 +1501,18 @@ set_std_cxx98 (int iso)
cxx_dialect = cxx98;
}
-/* Set the C++ 0x working draft "standard" (without GNU extensions if ISO). */
+/* Set the C++ 2011 standard (without GNU extensions if ISO). */
static void
-set_std_cxx0x (int iso)
+set_std_cxx11 (int iso)
{
- cpp_set_lang (parse_in, iso ? CLK_CXX0X: CLK_GNUCXX0X);
+ cpp_set_lang (parse_in, iso ? CLK_CXX11: CLK_GNUCXX11);
flag_no_gnu_keywords = iso;
flag_no_nonansi_builtin = iso;
flag_iso = iso;
- /* C++0x includes the C99 standard library. */
+ /* C++11 includes the C99 standard library. */
flag_isoc94 = 1;
flag_isoc99 = 1;
- cxx_dialect = cxx0x;
+ cxx_dialect = cxx11;
}
/* Args to -d specify what to dump. Silently ignore
diff --git a/gcc/c-family/c-ppoutput.c b/gcc/c-family/c-ppoutput.c
index 16d4f7de994..df46ce4c1f5 100644
--- a/gcc/c-family/c-ppoutput.c
+++ b/gcc/c-family/c-ppoutput.c
@@ -59,7 +59,9 @@ static void account_for_newlines (const unsigned char *, size_t);
static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
static void dump_queued_macros (cpp_reader *);
+static void print_line_1 (source_location, const char*, FILE *);
static void print_line (source_location, const char *);
+static void maybe_print_line_1 (source_location, FILE *);
static void maybe_print_line (source_location);
static void do_line_change (cpp_reader *, const cpp_token *,
source_location, int);
@@ -190,9 +192,7 @@ scan_translation_unit (cpp_reader *pfile)
/* Subtle logic to output a space if and only if necessary. */
if (avoid_paste)
{
- const struct line_map *map
- = linemap_lookup (line_table, loc);
- int src_line = SOURCE_LINE (map, loc);
+ int src_line = LOCATION_LINE (loc);
if (print.source == NULL)
print.source = token;
@@ -212,9 +212,7 @@ scan_translation_unit (cpp_reader *pfile)
}
else if (token->flags & PREV_WHITE)
{
- const struct line_map *map
- = linemap_lookup (line_table, loc);
- int src_line = SOURCE_LINE (map, loc);
+ int src_line = LOCATION_LINE (loc);
if (src_line != print.src_line
&& do_line_adjustments
@@ -247,7 +245,12 @@ scan_translation_unit (cpp_reader *pfile)
in_pragma = false;
}
else
- cpp_output_token (token, print.outf);
+ {
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, token->src_loc,
+ print.outf);
+ cpp_output_token (token, print.outf);
+ }
if (token->type == CPP_COMMENT)
account_for_newlines (token->val.str.text, token->val.str.len);
@@ -301,15 +304,17 @@ scan_translation_unit_trad (cpp_reader *pfile)
/* 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 (source_location src_loc)
+maybe_print_line_1 (source_location src_loc, FILE *stream)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
- int src_line = SOURCE_LINE (map, src_loc);
+ int src_line = LOCATION_LINE (src_loc);
+ const char *src_file = LOCATION_FILE (src_loc);
+
/* End the previous line of text. */
if (print.printed)
{
- putc ('\n', print.outf);
+ putc ('\n', stream);
print.src_line++;
print.printed = 0;
}
@@ -317,58 +322,87 @@ maybe_print_line (source_location src_loc)
if (!flag_no_line_commands
&& src_line >= print.src_line
&& src_line < print.src_line + 8
- && strcmp (map->to_file, print.src_file) == 0)
+ && strcmp (src_file, print.src_file) == 0)
{
while (src_line > print.src_line)
{
- putc ('\n', print.outf);
+ putc ('\n', stream);
print.src_line++;
}
}
else
- print_line (src_loc, "");
+ print_line_1 (src_loc, "", stream);
+
+}
+
+/* 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 (source_location src_loc)
+{
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, src_loc,
+ print.outf);
+ maybe_print_line_1 (src_loc, print.outf);
}
/* Output a line marker for logical line LINE. Special flags are "1"
or "2" indicating entering or leaving a file. */
+
static void
-print_line (source_location src_loc, const char *special_flags)
+print_line_1 (source_location src_loc, const char *special_flags, FILE *stream)
{
/* End any previous line of text. */
if (print.printed)
- putc ('\n', print.outf);
+ putc ('\n', stream);
print.printed = 0;
if (!flag_no_line_commands)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
-
- size_t to_file_len = strlen (map->to_file);
+ const char *file_path = LOCATION_FILE (src_loc);
+ int sysp;
+ size_t to_file_len = strlen (file_path);
unsigned char *to_file_quoted =
(unsigned char *) alloca (to_file_len * 4 + 1);
unsigned char *p;
- print.src_line = SOURCE_LINE (map, src_loc);
- print.src_file = map->to_file;
+ print.src_line = LOCATION_LINE (src_loc);
+ print.src_file = file_path;
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
- (const unsigned char *) map->to_file, to_file_len);
+ (const unsigned char *) file_path,
+ to_file_len);
*p = '\0';
- fprintf (print.outf, "# %u \"%s\"%s",
+ fprintf (stream, "# %u \"%s\"%s",
print.src_line == 0 ? 1 : print.src_line,
to_file_quoted, special_flags);
- if (map->sysp == 2)
- fputs (" 3 4", print.outf);
- else if (map->sysp == 1)
- fputs (" 3", print.outf);
+ sysp = in_system_header_at (src_loc);
+ if (sysp == 2)
+ fputs (" 3 4", stream);
+ else if (sysp == 1)
+ fputs (" 3", stream);
- putc ('\n', print.outf);
+ putc ('\n', stream);
}
}
+/* Output a line marker for logical line LINE. Special flags are "1"
+ or "2" indicating entering or leaving a file. */
+
+static void
+print_line (source_location src_loc, const char *special_flags)
+{
+ if (cpp_get_options (parse_in)->debug)
+ linemap_dump_location (line_table, src_loc,
+ print.outf);
+ print_line_1 (src_loc, special_flags, print.outf);
+}
+
/* Helper function for cb_line_change and scan_translation_unit. */
static void
do_line_change (cpp_reader *pfile, const cpp_token *token,
@@ -391,8 +425,7 @@ do_line_change (cpp_reader *pfile, const cpp_token *token,
ought to care. Some things do care; the fault lies with them. */
if (!CPP_OPTION (pfile, traditional))
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
- int spaces = SOURCE_COLUMN (map, src_loc) - 2;
+ int spaces = LOCATION_COLUMN (src_loc) - 2;
print.printed = 1;
while (-- spaces >= 0)
@@ -421,6 +454,8 @@ cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
static void
cb_define (cpp_reader *pfile, source_location line, cpp_hashnode *node)
{
+ const struct line_map *map;
+
maybe_print_line (line);
fputs ("#define ", print.outf);
@@ -432,7 +467,10 @@ cb_define (cpp_reader *pfile, source_location line, cpp_hashnode *node)
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- if (linemap_lookup (line_table, line)->to_line != 0)
+ linemap_resolve_location (line_table, line,
+ LRK_MACRO_DEFINITION_LOCATION,
+ &map);
+ if (LINEMAP_LINE (map) != 0)
print.src_line++;
}
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 79287c40422..438b8b003e9 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -289,7 +289,11 @@ Warn about C constructs that are not in the common subset of C and C++
Wc++0x-compat
C++ ObjC++ Var(warn_cxx0x_compat) Warning
-Warn about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 200x
+Deprecated in favor of -Wc++11-compat
+
+Wc++11-compat
+C++ ObjC++ Warning Alias(Wc++0x-compat)
+Warn about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 2011
Wcast-qual
C ObjC C++ ObjC++ Var(warn_cast_qual) Warning
@@ -396,7 +400,7 @@ C ObjC C++ ObjC++ Var(warn_format_y2k) Warning
Warn about strftime formats yielding 2-digit years
Wformat-zero-length
-C ObjC Var(warn_format_zero_length) Warning
+C ObjC C++ ObjC++ Var(warn_format_zero_length) Warning
Warn about zero-length formats
Wformat=
@@ -510,7 +514,7 @@ C++ ObjC++ Var(warn_nonvdtor) Warning
Warn about non-virtual destructors
Wnonnull
-C ObjC Var(warn_nonnull) Warning
+C ObjC C++ ObjC++ Var(warn_nonnull) Warning
Warn about NULL being passed to argument slots marked as requiring non-NULL
Wnormalized=
@@ -685,6 +689,10 @@ Wpointer-sign
C ObjC Var(warn_pointer_sign) Init(-1) Warning
Warn when a pointer differs in signedness in an assignment
+Wzero-as-null-pointer-constant
+C++ ObjC++ Var(warn_zero_as_null_pointer_constant) Warning
+Warn when a literal '0' is used as null pointer
+
ansi
C ObjC C++ ObjC++
A synonym for -std=c89 (for C) or -std=c++98 (for C++)
@@ -743,9 +751,13 @@ fconstexpr-depth=
C++ ObjC++ Joined RejectNegative UInteger Var(max_constexpr_depth) Init(512)
-fconstexpr-depth=<number> Specify maximum constexpr recursion depth
+fdebug-cpp
+C ObjC C++ ObjC++
+Emit debug annotations during preprocessing
+
fdeduce-init-list
-C++ ObjC++ Var(flag_deduce_init_list) Init(1)
--fno-deduce-init-list disable deduction of std::initializer_list for a template type parameter from a brace-enclosed initializer-list
+C++ ObjC++ Var(flag_deduce_init_list) Init(0)
+-fdeduce-init-list enable deduction of std::initializer_list for a template type parameter from a brace-enclosed initializer-list
fdefault-inline
C++ ObjC++ Ignore
@@ -945,6 +957,14 @@ fpreprocessed
C ObjC C++ ObjC++
Treat the input file as already preprocessed
+ftrack-macro-expansion
+C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
+; converted into ftrack-macro-expansion=
+
+ftrack-macro-expansion=
+C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
+-ftrack-macro-expansion=<0|1|2> Track locations of tokens coming from macro expansion and display them in error messages
+
fpretty-templates
C++ ObjC++ Var(flag_pretty_templates) Init(1)
-fno-pretty-templates Do not pretty-print template specializations as the template signature followed by the arguments
@@ -1031,7 +1051,7 @@ Use __cxa_get_exception_ptr in exception handling
fvisibility-inlines-hidden
C++ ObjC++
-Marks all inlined methods as having hidden visibility
+Marks all inlined functions and methods as having hidden visibility
fvisibility-ms-compat
C++ ObjC++ Var(flag_visibility_ms_compat)
@@ -1163,12 +1183,13 @@ std=c++03
C++ ObjC++ Alias(std=c++98)
Conform to the ISO 1998 C++ standard revised by the 2003 technical corrigendum
-std=c++0x
+std=c++11
C++ ObjC++
-Conform to the ISO 1998 C++ standard, with extensions that are likely to
-become a part of the upcoming ISO C++ standard, dubbed C++0x. Note that the
-extensions enabled by this mode are experimental and may be removed in
-future releases of GCC.
+Conform to the ISO 2011 C++ standard (experimental and incomplete support)
+
+std=c++0x
+C++ ObjC++ Alias(std=c++11)
+Deprecated in favor of -std=c++11
std=c1x
C ObjC
@@ -1192,14 +1213,21 @@ Deprecated in favor of -std=c99
std=gnu++98
C++ ObjC++
-Conform to the ISO 1998 C++ standard with GNU extensions
+Conform to the ISO 1998 C++ standard revised by the 2003 technical
+corrigendum with GNU extensions
-std=gnu++0x
+std=gnu++03
+C++ ObjC++ Alias(std=gnu++98)
+Conform to the ISO 1998 C++ standard revised by the 2003 technical
+corrigendum with GNU extensions
+
+std=gnu++11
C++ ObjC++
-Conform to the ISO 1998 C++ standard, with GNU extensions and
-extensions that are likely to become a part of the upcoming ISO C++
-standard, dubbed C++0x. Note that the extensions enabled by this mode
-are experimental and may be removed in future releases of GCC.
+Conform to the ISO 2011 C++ standard with GNU extensions (experimental and incomplete support)
+
+std=gnu++0x
+C++ ObjC++ Alias(std=gnu++11)
+Deprecated in favor of -std=gnu++11
std=gnu1x
C ObjC
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 4089b40dc41..6fb9ee0c5a1 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -530,7 +530,7 @@ update_alias_info_with_stack_vars (void)
/* Make the SSA name point to all partition members. */
pi = get_ptr_info (name);
- pt_solution_set (&pi->pt, part, false, false);
+ pt_solution_set (&pi->pt, part, false);
}
/* Make all points-to sets that contain one member of a partition
@@ -3265,6 +3265,9 @@ expand_debug_expr (tree exp)
case VEC_UNPACK_LO_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ case VEC_PERM_EXPR:
return NULL;
/* Misc codes. */
@@ -3319,6 +3322,7 @@ expand_debug_expr (tree exp)
return NULL;
case WIDEN_SUM_EXPR:
+ case WIDEN_LSHIFT_EXPR:
if (SCALAR_INT_MODE_P (GET_MODE (op0))
&& SCALAR_INT_MODE_P (mode))
{
@@ -3327,7 +3331,8 @@ expand_debug_expr (tree exp)
0)))
? ZERO_EXTEND : SIGN_EXTEND, mode, op0,
inner_mode);
- return simplify_gen_binary (PLUS, mode, op0, op1);
+ return simplify_gen_binary (TREE_CODE (exp) == WIDEN_LSHIFT_EXPR
+ ? ASHIFT : PLUS, mode, op0, op1);
}
return NULL;
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index b3f045bbbcb..f06dbc83b1d 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -1273,7 +1273,7 @@ force_nonfallthru_and_redirect (edge e, basic_block target, rtx jump_label)
gcc_unreachable ();
#endif
}
- JUMP_LABEL (BB_END (jump_block)) = jump_label;
+ set_return_jump_label (BB_END (jump_block));
}
else
{
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 84d6bd5198a..f056d3db58e 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1838,6 +1838,8 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
fprintf (f, " only_called_at_startup");
if (node->only_called_at_exit)
fprintf (f, " only_called_at_exit");
+ else if (node->alias)
+ fprintf (f, " alias");
fprintf (f, "\n");
@@ -2567,7 +2569,7 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
for (e = node->callers; e; e = e->next_caller)
if (e->caller->thunk.thunk_p
&& (include_overwritable
- || cgraph_function_body_availability (e->caller)))
+ || cgraph_function_body_availability (e->caller) > AVAIL_OVERWRITABLE))
if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data,
include_overwritable))
return true;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index c75c1300408..83c47ab66fd 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1219,7 +1219,6 @@ handle_alias_pairs (void)
for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);)
{
if (TREE_CODE (p->decl) == FUNCTION_DECL
- && !lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))
&& (target_node = cgraph_node_for_asm (p->target)) != NULL)
{
src_node = cgraph_get_node (p->decl);
@@ -1231,12 +1230,12 @@ handle_alias_pairs (void)
However for weakref we insist on EXTERNAL flag being set.
See gcc.dg/attr-alias-5.c */
if (DECL_EXTERNAL (p->decl))
- DECL_EXTERNAL (p->decl) = 0;
+ DECL_EXTERNAL (p->decl) = lookup_attribute ("weakref",
+ DECL_ATTRIBUTES (p->decl)) != NULL;
cgraph_create_function_alias (p->decl, target_node->decl);
VEC_unordered_remove (alias_pair, alias_pairs, i);
}
else if (TREE_CODE (p->decl) == VAR_DECL
- && !lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))
&& (target_vnode = varpool_node_for_asm (p->target)) != NULL)
{
/* Normally EXTERNAL flag is used to mark external inlines,
@@ -1245,10 +1244,26 @@ handle_alias_pairs (void)
However for weakref we insist on EXTERNAL flag being set.
See gcc.dg/attr-alias-5.c */
if (DECL_EXTERNAL (p->decl))
- DECL_EXTERNAL (p->decl) = 0;
+ DECL_EXTERNAL (p->decl) = lookup_attribute ("weakref",
+ DECL_ATTRIBUTES (p->decl)) != NULL;
varpool_create_variable_alias (p->decl, target_vnode->decl);
VEC_unordered_remove (alias_pair, alias_pairs, i);
}
+ /* Weakrefs with target not defined in current unit are easy to handle; they
+ behave just as external variables except we need to note the alias flag
+ to later output the weakref pseudo op into asm file. */
+ else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL
+ && (TREE_CODE (p->decl) == FUNCTION_DECL
+ ? (varpool_node_for_asm (p->target) == NULL)
+ : (cgraph_node_for_asm (p->target) == NULL)))
+ {
+ if (TREE_CODE (p->decl) == FUNCTION_DECL)
+ cgraph_get_create_node (p->decl)->alias = true;
+ else
+ varpool_get_node (p->decl)->alias = true;
+ DECL_EXTERNAL (p->decl) = 1;
+ VEC_unordered_remove (alias_pair, alias_pairs, i);
+ }
else
{
if (dump_file)
@@ -1798,7 +1813,6 @@ cgraph_expand_function (struct cgraph_node *node)
announce_function (decl);
node->process = 0;
- assemble_thunks_and_aliases (node);
gcc_assert (node->lowered);
/* Generate RTL for the body of DECL. */
@@ -1808,6 +1822,14 @@ cgraph_expand_function (struct cgraph_node *node)
gcc_assert (TREE_ASM_WRITTEN (decl));
current_function_decl = NULL;
gcc_assert (!cgraph_preserve_function_body_p (node));
+
+ /* It would make a lot more sense to output thunks before function body to get more
+ forward and lest backwarding jumps. This is however would need solving problem
+ with comdats. See PR48668. Also aliases must come after function itself to
+ make one pass assemblers, like one on AIX happy. See PR 50689.
+ FIXME: Perhaps thunks should be move before function IFF they are not in comdat
+ groups. */
+ assemble_thunks_and_aliases (node);
cgraph_release_function_body (node);
/* Eliminate all call edges. This is important so the GIMPLE_CALL no longer
points to the dead function body. */
@@ -2058,6 +2080,40 @@ ipa_passes (void)
}
+/* Return string alias is alias of. */
+
+static tree
+get_alias_symbol (tree decl)
+{
+ tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
+ return get_identifier (TREE_STRING_POINTER
+ (TREE_VALUE (TREE_VALUE (alias))));
+}
+
+
+/* Weakrefs may be associated to external decls and thus not output
+ at expansion time. Emit all neccesary aliases. */
+
+static void
+output_weakrefs (void)
+{
+ struct cgraph_node *node;
+ struct varpool_node *vnode;
+ for (node = cgraph_nodes; node; node = node->next)
+ if (node->alias && DECL_EXTERNAL (node->decl)
+ && !TREE_ASM_WRITTEN (node->decl))
+ assemble_alias (node->decl,
+ node->thunk.alias ? DECL_ASSEMBLER_NAME (node->thunk.alias)
+ : get_alias_symbol (node->decl));
+ for (vnode = varpool_nodes; vnode; vnode = vnode->next)
+ if (vnode->alias && DECL_EXTERNAL (vnode->decl)
+ && !TREE_ASM_WRITTEN (vnode->decl))
+ assemble_alias (vnode->decl,
+ vnode->alias_of ? DECL_ASSEMBLER_NAME (vnode->alias_of)
+ : get_alias_symbol (vnode->decl));
+}
+
+
/* Perform simple optimizations based on callgraph. */
void
@@ -2143,6 +2199,8 @@ cgraph_optimize (void)
varpool_assemble_pending_decls ();
}
+
+ output_weakrefs ();
cgraph_process_new_functions ();
cgraph_state = CGRAPH_STATE_FINISHED;
@@ -2308,6 +2366,10 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
SET_DECL_RTL (new_decl, NULL);
+ /* When the old decl was a con-/destructor make sure the clone isn't. */
+ DECL_STATIC_CONSTRUCTOR(new_decl) = 0;
+ DECL_STATIC_DESTRUCTOR(new_decl) = 0;
+
/* Create the new version's call-graph node.
and update the edges of the new node. */
new_version_node =
diff --git a/gcc/combine.c b/gcc/combine.c
index 6c3b17ca6ea..29411149173 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -13274,13 +13274,14 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2, rtx elim_i2,
break;
case REG_ARGS_SIZE:
- {
- /* ??? How to distribute between i3-i1. Assume i3 contains the
- entire adjustment. Assert i3 contains at least some adjust. */
- int old_size, args_size = INTVAL (XEXP (note, 0));
- old_size = fixup_args_size_notes (PREV_INSN (i3), i3, args_size);
- gcc_assert (old_size != args_size);
- }
+ /* ??? How to distribute between i3-i1. Assume i3 contains the
+ entire adjustment. Assert i3 contains at least some adjust. */
+ if (!noop_move_p (i3))
+ {
+ int old_size, args_size = INTVAL (XEXP (note, 0));
+ old_size = fixup_args_size_notes (PREV_INSN (i3), i3, args_size);
+ gcc_assert (old_size != args_size);
+ }
break;
case REG_NORETURN:
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 8099ed790b3..c1a77ff4db2 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -84,12 +84,6 @@
# build-directory files by prefixing them with "./".
# All other files should relative to $srcdir/config.
#
-# libgcc_tm_file A list of target macro files used only for code
-# built for the target, not the host. These files
-# are relative to $srcdir/../libgcc/config and
-# must not have the same names as files in
-# $srcdir/config.
-#
# tm_p_file Location of file with declarations for functions
# in $out_file.
#
@@ -138,9 +132,6 @@
# extra_passes List of extra executables compiled for this target
# machine, used for compiling from source to object.
#
-# extra_parts List of extra object files that should be compiled
-# for this target machine.
-#
# extra_programs Like extra_passes, but these are used when linking.
#
# extra_options List of target-dependent .opt files.
@@ -186,6 +177,13 @@
# configure_default_options
# Set to an initializer for configure_default_options
# in configargs.h, based on --with-cpu et cetera.
+#
+# native_system_header_dir
+# Where system header files are found for this
+# target. This defaults to /usr/include. If
+# the --with-sysroot configure option or the
+# --sysroot command line option is used this
+# will be relative to the sysroot.
# The following variables are used in each case-construct to build up the
# outgoing variables:
@@ -208,7 +206,6 @@ user_headers_inc_next_post=
use_gcc_tgmath=yes
use_gcc_stdint=none
extra_passes=
-extra_parts=
extra_programs=
extra_objs=
extra_gcc_objs=
@@ -220,7 +217,6 @@ target_has_targetcm=no
target_has_targetm_common=yes
tm_defines=
xm_defines=
-libgcc_tm_file=
# Set this to force installation and use of collect2.
use_collect2=
# Set this to override the default target model.
@@ -238,6 +234,7 @@ default_gnu_indirect_function=no
target_gtfiles=
need_64bit_hwint=
need_64bit_isa=
+native_system_header_dir=/usr/include
# Don't carry these over build->host->target. Please.
xm_file=
@@ -548,24 +545,15 @@ case ${target} in
# pleases around the provided core setting.
gas=yes
gnu_ld=yes
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o"
fbsd_major=`echo ${target} | sed -e 's/.*freebsd//g' | sed -e 's/\..*//g'`
tm_defines="${tm_defines} FBSD_MAJOR=${fbsd_major}"
- tmake_file="t-slibgcc-elf-ver t-freebsd"
+ tmake_file="t-slibgcc"
case ${enable_threads} in
no)
fbsd_tm_file="${fbsd_tm_file} freebsd-nthr.h"
;;
"" | yes | posix)
thread_file='posix'
- tmake_file="${tmake_file} t-freebsd-thread"
- # Before 5.0, FreeBSD can't bind shared libraries to -lc
- # when "optionally" threaded via weak pthread_* checks.
- case ${target} in
- *-*-freebsd[34] | *-*-freebsd[34].*)
- tmake_file="${tmake_file} t-slibgcc-nolc-override"
- ;;
- esac
;;
*)
echo 'Unknown thread configuration for FreeBSD'
@@ -585,18 +573,18 @@ case ${target} in
;;
*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu | *-*-gnu* | *-*-kopensolaris*-gnu)
extra_options="$extra_options gnu-user.opt"
- extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
gas=yes
gnu_ld=yes
case ${enable_threads} in
"" | yes | posix) thread_file='posix' ;;
esac
- tmake_file="t-slibgcc-elf-ver t-linux"
+ tmake_file="t-slibgcc"
case $target in
*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu | *-*-kopensolaris*-gnu)
:;;
*-*-gnu*)
- tmake_file="$tmake_file t-gnu";;
+ native_system_header_dir=/include
+ ;;
esac
# glibc / uclibc / bionic switch.
# uclibc and bionic aren't usable for GNU/Hurd and neither for GNU/k*BSD.
@@ -638,7 +626,7 @@ case ${target} in
esac
;;
*-*-netbsd*)
- tmake_file="t-slibgcc-elf-ver t-libc-ok t-netbsd t-libgcc-pic"
+ tmake_file="t-slibgcc"
gas=yes
gnu_ld=yes
@@ -659,15 +647,6 @@ case ${target} in
;;
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 ${target} in
- *-*-netbsd*1.[7-9]* | *-*-netbsd[2-9]* | *-*-netbsdelf[2-9]*)
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
- ;;
- esac
-
# NetBSD 2.0 and later provide __cxa_atexit(), which we use by
# default (unless overridden by --disable-__cxa_atexit).
case ${target} in
@@ -677,11 +656,10 @@ case ${target} in
esac
;;
*-*-openbsd*)
- tmake_file="t-libc-ok t-openbsd t-libgcc-pic"
+ tmake_file="t-openbsd"
case ${enable_threads} in
yes)
thread_file='posix'
- tmake_file="${tmake_file} t-openbsd-thread"
;;
esac
case ${target} in
@@ -721,7 +699,7 @@ case ${target} in
tm_file="usegas.h ${tm_file}"
fi
tm_p_file="${tm_p_file} sol2-protos.h"
- tmake_file="${tmake_file} t-sol2 t-slibgcc-dummy"
+ tmake_file="${tmake_file} t-sol2 t-slibgcc"
c_target_objs="${c_target_objs} sol2-c.o"
cxx_target_objs="${cxx_target_objs} sol2-c.o sol2-cxx.o"
extra_objs="sol2.o sol2-stubs.o"
@@ -735,7 +713,7 @@ case ${target} in
*-*-*vms*)
extra_options="${extra_options} vms/vms.opt"
xmake_file=vms/x-vms
- tmake_file="vms/t-vms"
+ tmake_file="vms/t-vms t-slibgcc"
extra_objs="vms.o"
target_gtfiles="$target_gtfiles \$(srcdir)/config/vms/vms.c"
tm_p_file="${tm_p_file} vms/vms-protos.h"
@@ -768,22 +746,17 @@ alpha*-*-linux*)
tm_file="${tm_file} alpha/elf.h alpha/linux.h alpha/linux-elf.h glibc-stdint.h"
extra_options="${extra_options} alpha/elf.opt"
target_cpu_default="MASK_GAS"
- tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee alpha/t-linux"
- extra_parts="${extra_parts} crtfastmath.o"
;;
alpha*-*-freebsd*)
tm_file="${tm_file} ${fbsd_tm_file} alpha/elf.h alpha/freebsd.h"
extra_options="${extra_options} alpha/elf.opt"
target_cpu_default="MASK_GAS"
- tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee"
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o crtfastmath.o"
;;
alpha*-*-netbsd*)
tm_file="${tm_file} netbsd.h alpha/elf.h netbsd-elf.h alpha/netbsd.h"
extra_options="${extra_options} netbsd.opt netbsd-elf.opt \
alpha/elf.opt"
target_cpu_default="MASK_GAS"
- tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee"
;;
alpha*-*-openbsd*)
tm_defines="${tm_defines} OBSD_HAS_DECLARE_FUNCTION_NAME OBSD_HAS_DECLARE_FUNCTION_SIZE OBSD_HAS_DECLARE_OBJECT"
@@ -791,7 +764,6 @@ alpha*-*-openbsd*)
extra_options="${extra_options} openbsd.opt alpha/elf.opt"
# default x-alpha is only appropriate for dec-osf.
target_cpu_default="MASK_GAS"
- tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee"
;;
alpha*-dec-osf5.1*)
if test x$stabs = xyes
@@ -805,7 +777,7 @@ alpha*-dec-osf5.1*)
extra_passes="mips-tfile mips-tdump"
fi
use_collect2=yes
- tmake_file="t-slibgcc-dummy"
+ tmake_file="t-slibgcc"
tm_file="${tm_file} alpha/osf5.h"
tm_defines="${tm_defines} TARGET_SUPPORT_ARCH=1"
extra_options="${extra_options} rpath.opt alpha/osf5.opt"
@@ -820,12 +792,12 @@ alpha*-dec-osf5.1*)
alpha64-dec-*vms*)
tm_file="${tm_file} alpha/vms.h alpha/vms64.h"
xm_file="alpha/xm-vms.h vms/xm-vms64.h"
- tmake_file="${tmake_file} alpha/t-alpha vms/t-vms64 alpha/t-vms alpha/t-ieee"
+ tmake_file="${tmake_file} vms/t-vms64 alpha/t-vms"
;;
alpha*-dec-*vms*)
tm_file="${tm_file} alpha/vms.h"
xm_file="alpha/xm-vms.h"
- tmake_file="${tmake_file} alpha/t-alpha alpha/t-vms alpha/t-ieee"
+ tmake_file="${tmake_file} alpha/t-vms"
;;
arm-wrs-vxworks)
tm_file="elfos.h arm/elf.h arm/aout.h ${tm_file} vx-common.h vxworks.h arm/vxworks.h"
@@ -839,7 +811,7 @@ arm*-*-freebsd*)
arm*-*-netbsdelf*)
tm_file="dbxelf.h elfos.h netbsd.h netbsd-elf.h arm/elf.h arm/aout.h arm/arm.h arm/netbsd-elf.h"
extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
- tmake_file="${tmake_file} arm/t-arm arm/t-netbsd"
+ tmake_file="${tmake_file} arm/t-arm"
;;
arm*-*-linux*) # ARM GNU/Linux with ELF
tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arm/elf.h arm/linux-gas.h arm/linux-elf.h"
@@ -848,12 +820,11 @@ arm*-*-linux*) # ARM GNU/Linux with ELF
tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1"
;;
esac
- tmake_file="${tmake_file} t-linux arm/t-arm"
+ tmake_file="${tmake_file} arm/t-arm"
case ${target} in
arm*-*-linux-*eabi)
tm_file="$tm_file arm/bpabi.h arm/linux-eabi.h"
- libgcc_tm_file="$libgcc_tm_file arm/bpabi-lib.h"
- tmake_file="$tmake_file arm/t-arm-elf arm/t-bpabi arm/t-linux-eabi t-slibgcc-libgcc"
+ tmake_file="$tmake_file arm/t-arm-elf arm/t-linux-eabi"
# Define multilib configuration for arm-linux-androideabi.
case ${target} in
*-androideabi)
@@ -880,8 +851,6 @@ arm*-*-uclinux*) # ARM ucLinux
case ${target} in
arm*-*-uclinux*eabi)
tm_file="$tm_file arm/bpabi.h arm/uclinux-eabi.h"
- libgcc_tm_file="$libgcc_tm_file arm/bpabi-lib.h"
- tmake_file="$tmake_file arm/t-bpabi"
# The BPABI long long divmod functions return a 128-bit value in
# registers r0-r3. Correctly modeling that requires the use of
# TImode.
@@ -902,17 +871,14 @@ arm*-*-eabi* | arm*-*-symbianelf* )
need_64bit_hwint=yes
default_use_cxa_atexit=yes
tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h"
- libgcc_tm_file="$libgcc_tm_file arm/bpabi-lib.h"
tmake_file="arm/t-arm arm/t-arm-elf"
case ${target} in
arm*-*-eabi*)
tm_file="$tm_file newlib-stdint.h"
- tmake_file="${tmake_file} arm/t-bpabi"
use_gcc_stdint=wrap
;;
arm*-*-symbianelf*)
tm_file="${tm_file} arm/symbian.h"
- libgcc_tm_file="$libgcc_tm_file arm/symbian-lib.h"
# We do not include t-bpabi for Symbian OS because the system
# provides its own implementation of the BPABI functions.
tmake_file="${tmake_file} arm/t-symbian"
@@ -936,14 +902,12 @@ arm*-wince-pe*)
;;
avr-*-rtems*)
tm_file="elfos.h avr/elf.h avr/avr.h dbxelf.h avr/rtems.h rtems.h newlib-stdint.h"
- libgcc_tm_file="$libgcc_tm_file avr/avr-lib.h"
tmake_file="avr/t-avr t-rtems avr/t-rtems"
extra_gcc_objs="driver-avr.o avr-devices.o"
extra_objs="avr-devices.o avr-log.o"
;;
avr-*-*)
tm_file="elfos.h avr/elf.h avr/avr.h dbxelf.h newlib-stdint.h"
- libgcc_tm_file="$libgcc_tm_file avr/avr-lib.h"
use_gcc_stdint=wrap
extra_gcc_objs="driver-avr.o avr-devices.o"
extra_objs="avr-devices.o avr-log.o"
@@ -960,17 +924,15 @@ bfin*-uclinux*)
;;
bfin*-linux-uclibc*)
tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h gnu-user.h linux.h glibc-stdint.h bfin/linux.h ./linux-sysroot-suffix.h"
- tmake_file="t-slibgcc-elf-ver bfin/t-bfin-linux"
- extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ tmake_file="bfin/t-bfin-linux t-slibgcc"
use_collect2=no
;;
bfin*-rtems*)
tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h bfin/rtems.h rtems.h newlib-stdint.h"
- tmake_file="bfin/t-bfin t-rtems bfin/t-rtems"
+ tmake_file="t-rtems bfin/t-rtems"
;;
bfin*-*)
tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h bfin/elf.h"
- tmake_file=bfin/t-bfin
use_collect2=no
use_gcc_stdint=wrap
;;
@@ -992,7 +954,7 @@ cris-*-elf | cris-*-none)
crisv32-*-linux* | cris-*-linux*)
tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h cris/linux.h"
# We need to avoid using t-linux, so override default tmake_file
- tmake_file="cris/t-cris t-slibgcc-elf-ver cris/t-linux"
+ tmake_file="cris/t-cris cris/t-linux t-slibgcc"
extra_options="${extra_options} cris/linux.opt"
case $target in
cris-*-*)
@@ -1005,32 +967,26 @@ crisv32-*-linux* | cris-*-linux*)
;;
fr30-*-elf)
tm_file="dbxelf.h elfos.h newlib-stdint.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 newlib-stdint.h ${tm_file}"
- libgcc_tm_file="${libgcc_tm_file} frv/frv-abi.h"
tmake_file=frv/t-frv
;;
frv-*-*linux*)
tm_file="dbxelf.h elfos.h ${tm_file} \
gnu-user.h linux.h glibc-stdint.h frv/linux.h"
- libgcc_tm_file="${libgcc_tm_file} frv/frv-abi.h"
tmake_file="${tmake_file} frv/t-frv frv/t-linux"
;;
moxie-*-elf)
gas=yes
gnu_ld=yes
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
- extra_parts="crti.o crtn.o crtbegin.o crtend.o"
tmake_file="${tmake_file} moxie/t-moxie"
;;
moxie-*-uclinux*)
gas=yes
gnu_ld=yes
tm_file="dbxelf.h elfos.h ${tm_file} gnu-user.h linux.h glibc-stdint.h moxie/uclinux.h"
- extra_parts="crti.o crtn.o crtbegin.o crtend.o"
tmake_file="${tmake_file} moxie/t-moxie"
;;
moxie-*-rtems*)
@@ -1038,21 +994,18 @@ moxie-*-rtems*)
tm_file="moxie/moxie.h dbxelf.h elfos.h moxie/rtems.h rtems.h newlib-stdint.h"
;;
h8300-*-rtems*)
- tmake_file="h8300/t-h8300 h8300/t-elf t-rtems h8300/t-rtems"
+ tmake_file="h8300/t-h8300 t-rtems h8300/t-rtems"
tm_file="h8300/h8300.h dbxelf.h elfos.h h8300/elf.h h8300/rtems.h rtems.h newlib-stdint.h"
- libgcc_tm_file="$libgcc_tm_file h8300/h8300-lib.h"
;;
h8300-*-elf*)
- tmake_file="h8300/t-h8300 h8300/t-elf"
+ tmake_file="h8300/t-h8300"
tm_file="h8300/h8300.h dbxelf.h elfos.h newlib-stdint.h h8300/elf.h"
- libgcc_tm_file="$libgcc_tm_file h8300/h8300-lib.h"
;;
hppa*64*-*-linux*)
target_cpu_default="MASK_PA_11|MASK_PA_20"
tm_file="pa/pa64-start.h ${tm_file} dbxelf.h elfos.h gnu-user.h linux.h \
glibc-stdint.h pa/pa-linux.h pa/pa64-regs.h pa/pa-64.h \
pa/pa64-linux.h"
- tmake_file="${tmake_file} pa/t-linux64"
gas=yes gnu_ld=yes
need_64bit_hwint=yes
;;
@@ -1060,13 +1013,6 @@ hppa*-*-linux*)
target_cpu_default="MASK_PA_11|MASK_NO_SPACE_REGS"
tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h pa/pa-linux.h \
pa/pa32-regs.h pa/pa32-linux.h"
- tmake_file="${tmake_file} pa/t-linux t-slibgcc-libgcc"
- # Set the libgcc version number
- if test x$sjlj = x1; then
- tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
- else
- tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
- fi
;;
# port not yet contributed.
#hppa*-*-openbsd*)
@@ -1089,7 +1035,7 @@ hppa[12]*-*-hpux10*)
esac
use_gcc_stdint=provide
tm_file="${tm_file} hpux-stdint.h"
- tmake_file="pa/t-pa-hpux10 pa/t-pa-hpux pa/t-hpux-shlib"
+ tmake_file="t-slibgcc"
case ${enable_threads} in
"")
if test x$have_pthread_h = xyes ; then
@@ -1100,12 +1046,6 @@ hppa[12]*-*-hpux10*)
tmake_file="${tmake_file} pa/t-dce-thr"
;;
esac
- # Set the libgcc version number
- if test x$sjlj = x1; then
- tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
- else
- tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
- fi
use_collect2=yes
gas=yes
if test "x$with_dwarf2" != x; then
@@ -1138,15 +1078,7 @@ hppa*64*-*-hpux11*)
extra_options="${extra_options} pa/pa-hpux.opt \
pa/pa-hpux1010.opt pa/pa64-hpux.opt hpux11.opt"
need_64bit_hwint=yes
- tmake_file="pa/t-pa64 pa/t-pa-hpux pa/t-hpux-shlib"
- # Set the libgcc version number
- if test x$sjlj = x1; then
- tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
- else
- tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
- fi
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o \
- libgcc_stub.a"
+ tmake_file="t-slibgcc"
case x${enable_threads} in
x | xyes | xposix )
thread_file=posix
@@ -1184,14 +1116,7 @@ hppa[12]*-*-hpux11*)
extra_options="${extra_options} pa/pa-hpux1131.opt"
;;
esac
- tmake_file="pa/t-pa-hpux11 pa/t-pa-hpux pa/t-hpux-shlib"
- # Set the libgcc version number
- if test x$sjlj = x1; then
- tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
- else
- tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
- fi
- extra_parts="libgcc_stub.a"
+ tmake_file="t-slibgcc"
case x${enable_threads} in
x | xyes | xposix )
thread_file=posix
@@ -1218,30 +1143,24 @@ i[34567]86-*-darwin*)
need_64bit_isa=yes
# Baseline choice for a machine that allows m64 support.
with_cpu=${with_cpu:-core2}
- tmake_file="${tmake_file} t-slibgcc-dummy"
- libgcc_tm_file="$libgcc_tm_file i386/darwin-lib.h"
+ tmake_file="${tmake_file} t-slibgcc"
;;
x86_64-*-darwin*)
with_cpu=${with_cpu:-core2}
- tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-dummy"
+ tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc"
tm_file="${tm_file} ${cpu_type}/darwin64.h"
- libgcc_tm_file="$libgcc_tm_file i386/darwin-lib.h"
;;
i[34567]86-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h"
- tmake_file="${tmake_file} i386/t-i386elf i386/t-crtstuff t-svr4"
;;
x86_64-*-elf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h"
- tmake_file="${tmake_file} i386/t-i386elf i386/t-crtstuff t-svr4"
;;
i[34567]86-*-freebsd*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h ${fbsd_tm_file} i386/freebsd.h"
- tmake_file="${tmake_file} i386/t-crtstuff"
;;
x86_64-*-freebsd*)
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"
- tmake_file="${tmake_file} i386/t-crtstuff"
;;
i[34567]86-*-netbsdelf*)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h netbsd.h netbsd-elf.h i386/netbsd-elf.h"
@@ -1250,13 +1169,12 @@ i[34567]86-*-netbsdelf*)
x86_64-*-netbsd*)
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"
extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
- tmake_file="${tmake_file} i386/t-crtstuff"
;;
i[34567]86-*-openbsd2.*|i[34567]86-*openbsd3.[0123])
tm_file="i386/i386.h i386/unix.h i386/bsd.h i386/gas.h i386/gstabs.h openbsd-oldgas.h openbsd.h i386/openbsd.h"
extra_options="${extra_options} openbsd.opt"
# needed to unconfuse gdb
- tmake_file="${tmake_file} t-libc-ok t-openbsd i386/t-openbsd"
+ tmake_file="${tmake_file} t-openbsd i386/t-openbsd"
# we need collect2 until our bug is fixed...
use_collect2=yes
;;
@@ -1328,10 +1246,6 @@ i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i
tm_file="$tm_file i386/gnu-user.h gnu.h i386/gnu.h"
;;
esac
- tmake_file="${tmake_file} i386/t-crtstuff"
- # This is a hack to avoid a configuration mismatch
- # until the toplevel libgcc move is complete.
- extra_parts="${extra_parts} crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
;;
x86_64-*-linux* | x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu)
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h gnu-user.h glibc-stdint.h \
@@ -1349,7 +1263,7 @@ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu)
tm_file="${tm_file} knetbsd-gnu.h"
;;
esac
- tmake_file="${tmake_file} i386/t-linux64 i386/t-crtstuff"
+ tmake_file="${tmake_file} i386/t-linux64"
x86_multilibs="${with_multilib_list}"
if test "$x86_multilibs" = "default"; then
x86_multilibs="m64,m32"
@@ -1370,7 +1284,7 @@ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu)
i[34567]86-pc-msdosdjgpp*)
xm_file=i386/xm-djgpp.h
tm_file="dbxcoff.h ${tm_file} i386/unix.h i386/bsd.h i386/gas.h i386/djgpp.h i386/djgpp-stdint.h"
- tmake_file="${tmake_file} i386/t-djgpp"
+ native_system_header_dir=/dev/env/DJDIR/include
extra_options="${extra_options} i386/djgpp.opt"
gnu_ld=yes
gas=yes
@@ -1379,8 +1293,7 @@ i[34567]86-pc-msdosdjgpp*)
i[34567]86-*-lynxos*)
xm_defines=POSIX
tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/lynx.h lynx.h"
- tmake_file="${tmake_file} i386/t-crtstuff t-lynx"
- extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ tmake_file="${tmake_file} t-lynx"
extra_options="${extra_options} lynx.opt"
thread_file=lynx
gnu_ld=yes
@@ -1389,7 +1302,6 @@ i[34567]86-*-lynxos*)
i[34567]86-*-nto-qnx*)
tm_file="${tm_file} i386/att.h dbxelf.h tm-dwarf2.h elfos.h i386/unix.h i386/nto.h"
extra_options="${extra_options} i386/nto.opt"
- tmake_file="${tmake_file} i386/t-nto"
gnu_ld=yes
gas=yes
;;
@@ -1451,19 +1363,7 @@ i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae)
i[34567]86-*-cygwin*)
tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/cygwin.h i386/cygwin-stdint.h"
xm_file=i386/xm-cygwin.h
- # This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
- if test x$sjlj = x0; then
- tmake_eh_file="i386/t-dw2-eh"
- else
- tmake_eh_file="i386/t-sjlj-eh"
- fi
- # Shared libgcc DLL install dir depends on cross/native build.
- if test x${host} = x${target} ; then
- tmake_dlldir_file="i386/t-dlldir"
- else
- tmake_dlldir_file="i386/t-dlldir-x"
- fi
- tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_dlldir_file} i386/t-cygming i386/t-cygwin"
+ tmake_file="${tmake_file} i386/t-cygming t-slibgcc"
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
extra_options="${extra_options} i386/cygming.opt"
extra_objs="winnt.o winnt-stubs.o"
@@ -1516,19 +1416,7 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
;;
esac
tm_file="${tm_file} i386/mingw-stdint.h"
- # This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
- if test x$sjlj = x0; then
- tmake_eh_file="i386/t-dw2-eh"
- else
- tmake_eh_file="i386/t-sjlj-eh"
- fi
- # Shared libgcc DLL install dir depends on cross/native build.
- if test x${host} = x${target} ; then
- tmake_dlldir_file="i386/t-dlldir"
- else
- tmake_dlldir_file="i386/t-dlldir-x"
- fi
- tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_dlldir_file} i386/t-cygming"
+ tmake_file="${tmake_file} i386/t-cygming t-slibgcc"
case ${target} in
x86_64-w64-*)
tmake_file="${tmake_file} i386/t-mingw-w64"
@@ -1536,10 +1424,8 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
i[34567]86-w64-*)
tmake_file="${tmake_file} i386/t-mingw-w32"
;;
- *)
- tmake_file="${tmake_file} i386/t-mingw32"
- ;;
esac
+ native_system_header_dir=/mingw/include
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
extra_options="${extra_options} i386/cygming.opt i386/mingw.opt"
case ${target} in
@@ -1555,12 +1441,11 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
default_use_cxa_atexit=yes
use_gcc_stdint=wrap
case ${enable_threads} in
- "" | yes | win32) thread_file='win32'
- tmake_file="${tmake_file} i386/t-gthr-win32"
+ "" | yes | win32)
+ thread_file='win32'
;;
posix)
thread_file='posix'
- tmake_file="i386/t-mingw-pthread ${tmake_file}"
;;
esac
case ${target} in
@@ -1596,23 +1481,20 @@ ia64*-*-elf*)
then
target_cpu_default="${target_cpu_default}|MASK_GNU_LD"
fi
- 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"
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
;;
ia64*-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ia64/sysv4.h ia64/linux.h"
- tmake_file="${tmake_file} ia64/t-ia64 t-libunwind ia64/t-glibc"
+ tmake_file="${tmake_file} ia64/t-ia64 t-libunwind"
target_cpu_default="MASK_GNU_AS|MASK_GNU_LD"
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
;;
ia64*-*-hpux*)
tm_file="${tm_file} dbxelf.h elfos.h ia64/sysv4.h ia64/hpux.h"
- tmake_file="ia64/t-ia64 ia64/t-hpux"
+ tmake_file="ia64/t-ia64 ia64/t-hpux t-slibgcc"
target_cpu_default="MASK_GNU_AS"
case x$enable_threads in
x | xyes | xposix )
@@ -1634,7 +1516,7 @@ ia64*-*-hpux*)
ia64-hp-*vms*)
tm_file="${tm_file} elfos.h ia64/sysv4.h ia64/elf.h ia64/vms.h ia64/vms64.h"
xm_file="vms/xm-vms.h vms/xm-vms64.h"
- tmake_file="${tmake_file} vms/t-vms64 ia64/t-ia64 ia64/t-vms"
+ tmake_file="${tmake_file} vms/t-vms64 ia64/t-ia64"
target_cpu_default="0"
if test x$gas = xyes
then
@@ -1644,7 +1526,6 @@ ia64-hp-*vms*)
;;
iq2000*-*-elf*)
tm_file="elfos.h newlib-stdint.h iq2000/iq2000.h"
- tmake_file=iq2000/t-iq2000
out_file=iq2000/iq2000.c
md_file=iq2000/iq2000.md
;;
@@ -1663,21 +1544,18 @@ lm32-*-uclinux*)
;;
m32r-*-elf*)
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
- extra_parts="crtinit.o crtfini.o"
;;
m32rle-*-elf*)
tm_file="dbxelf.h elfos.h newlib-stdint.h m32r/little.h ${tm_file}"
- extra_parts="crtinit.o crtfini.o m32rx/crtinit.o m32rx/crtfini.o"
;;
m32r-*-rtems*)
tm_file="dbxelf.h elfos.h ${tm_file} m32r/rtems.h rtems.h newlib-stdint.h"
tmake_file="m32r/t-m32r t-rtems"
- extra_parts="crtinit.o crtfini.o"
;;
m32r-*-linux*)
tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} m32r/linux.h"
# We override the tmake_file for linux -- why?
- tmake_file="t-slibgcc-elf-ver m32r/t-linux"
+ tmake_file="m32r/t-linux t-slibgcc"
gnu_ld=yes
if test x$enable_threads = xyes; then
thread_file='posix'
@@ -1686,7 +1564,7 @@ m32r-*-linux*)
m32rle-*-linux*)
tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h m32r/little.h ${tm_file} m32r/linux.h"
# We override the tmake_file for linux -- why?
- tmake_file="t-slibgcc-elf-ver m32r/t-linux"
+ tmake_file="m32r/t-linux t-slibgcc"
gnu_ld=yes
if test x$enable_threads = xyes; then
thread_file='posix'
@@ -1722,7 +1600,6 @@ m68k-*-elf* | fido-*-elf*)
tmake_file="$tmake_file m68k/t-mlibs"
;;
esac
- extra_parts="crtbegin.o crtend.o"
;;
m68k*-*-netbsdelf*)
default_m68k_cpu=68020
@@ -1738,7 +1615,7 @@ m68k*-*-openbsd*)
tm_defines="${tm_defines} OBSD_OLD_GAS"
tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h m68k/openbsd.h"
extra_options="${extra_options} openbsd.opt"
- tmake_file="t-libc-ok t-openbsd m68k/t-openbsd"
+ tmake_file="t-openbsd m68k/t-openbsd"
# we need collect2 until our bug is fixed...
use_collect2=yes
;;
@@ -1752,7 +1629,7 @@ m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux
tm_defines="${tm_defines} MOTOROLA=1"
tmake_file="m68k/t-floatlib m68k/t-uclinux m68k/t-mlibs"
;;
-m68k-*-linux*) # Motorola m68k's running GNU/Linux
+m68k-*-linux*) # Motorola m68k's running GNU/Linux
# with ELF format using glibc 2
# aka the GNU/Linux C library 6.
default_m68k_cpu=68020
@@ -1762,11 +1639,6 @@ m68k-*-linux*) # Motorola m68k's running GNU/Linux
extra_options="${extra_options} m68k/ieee.opt"
tm_defines="${tm_defines} MOTOROLA=1"
tmake_file="${tmake_file} m68k/t-floatlib m68k/t-linux m68k/t-mlibs"
- # if not configured with --enable-sjlj-exceptions, bump the
- # libgcc version number
- if test x$sjlj != x1; then
- tmake_file="$tmake_file m68k/t-slibgcc-elf-ver"
- fi
;;
m68k-*-rtems*)
default_m68k_cpu=68020
@@ -1774,7 +1646,6 @@ m68k-*-rtems*)
tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-crtstuff t-rtems m68k/t-rtems m68k/t-mlibs"
tm_file="${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 newlib-stdint.h"
tm_defines="${tm_defines} MOTOROLA=1"
- extra_parts="crtbegin.o crtend.o"
;;
mcore-*-elf)
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file} mcore/mcore-elf.h"
@@ -1784,7 +1655,6 @@ mcore-*-elf)
mep-*-*)
tm_file="dbxelf.h elfos.h ${tm_file}"
tmake_file=mep/t-mep
- extra_parts="crtbegin.o crtend.o"
c_target_objs="mep-pragma.o"
cxx_target_objs="mep-pragma.o"
if test -d "${srcdir}/../newlib/libc/include" &&
@@ -1797,8 +1667,6 @@ microblaze*-linux*)
tm_file="${tm_file} dbxelf.h gnu-user.h linux.h microblaze/linux.h"
c_target_objs="${c_target_objs} microblaze-c.o"
cxx_target_objs="${cxx_target_objs} microblaze-c.o"
- tmake_file="${tmake_file} t-slibgcc-elf-ver t-slibgcc-nolc-override t-linux microblaze/t-microblaze"
- extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o crtbeginT.o"
;;
microblaze*-*-*)
tm_file="${tm_file} dbxelf.h"
@@ -1808,7 +1676,7 @@ microblaze*-*-*)
;;
mips-sgi-irix6.5*)
tm_file="elfos.h ${tm_file} mips/iris6.h"
- tmake_file="mips/t-irix6 t-slibgcc-dummy"
+ tmake_file="mips/t-irix6 t-slibgcc"
extra_options="${extra_options} rpath.opt mips/iris6.opt"
target_cpu_default="MASK_ABICALLS"
tm_defines="${tm_defines} MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_N32"
@@ -1833,7 +1701,7 @@ mips*-*-netbsd*) # NetBSD/mips, either endian.
;;
mips64*-*-linux* | mipsisa64*-*-linux*)
tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/gnu-user64.h mips/linux64.h"
- tmake_file="${tmake_file} mips/t-linux64 mips/t-libgcc-mips16"
+ tmake_file="${tmake_file} mips/t-linux64"
tm_defines="${tm_defines} MIPS_ABI_DEFAULT=ABI_N32"
case ${target} in
mips64el-st-linux-gnu)
@@ -1848,14 +1716,12 @@ mips64*-*-linux* | mipsisa64*-*-linux*)
tm_defines="${tm_defines} MIPS_ISA_DEFAULT=65"
;;
esac
- extra_parts="$extra_parts crtfastmath.o"
gnu_ld=yes
gas=yes
test x$with_llsc != x || with_llsc=yes
;;
mips*-*-linux*) # Linux MIPS, either endian.
tm_file="dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h ${tm_file} mips/gnu-user.h mips/linux.h"
- tmake_file="${tmake_file} mips/t-libgcc-mips16"
if test x$enable_targets = xall; then
tm_file="${tm_file} mips/gnu-user64.h mips/linux64.h"
tmake_file="${tmake_file} mips/t-linux64"
@@ -1867,7 +1733,6 @@ mips*-*-linux*) # Linux MIPS, either endian.
mipsisa32*)
tm_defines="${tm_defines} MIPS_ISA_DEFAULT=32"
esac
- extra_parts="$extra_parts crtfastmath.o"
test x$with_llsc != x || with_llsc=yes
;;
mips*-*-openbsd*)
@@ -1883,7 +1748,7 @@ mips*-*-openbsd*)
;;
mips*-sde-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/sde.h"
- tmake_file="mips/t-sde mips/t-libgcc-mips16"
+ tmake_file="mips/t-sde"
extra_options="${extra_options} mips/sde.opt"
case "${with_newlib}" in
yes)
@@ -1920,7 +1785,7 @@ mipsisa32r2-*-elf* | mipsisa32r2el-*-elf* | \
mipsisa64-*-elf* | mipsisa64el-*-elf* | \
mipsisa64r2-*-elf* | mipsisa64r2el-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
- tmake_file="mips/t-isa3264 mips/t-libgcc-mips16"
+ tmake_file="mips/t-isa3264"
case ${target} in
mipsisa32r2*)
tm_defines="${tm_defines} MIPS_ISA_DEFAULT=33"
@@ -1957,17 +1822,17 @@ mipsisa64sr71k-*-elf*)
;;
mipsisa64sb1-*-elf* | mipsisa64sb1el-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
- tmake_file="mips/t-elf mips/t-libgcc-mips16 mips/t-sb1"
+ tmake_file="mips/t-elf mips/t-sb1"
target_cpu_default="MASK_64BIT|MASK_FLOAT64"
tm_defines="${tm_defines} MIPS_ISA_DEFAULT=64 MIPS_CPU_STRING_DEFAULT=\\\"sb1\\\" MIPS_ABI_DEFAULT=ABI_O64"
;;
mips-*-elf* | mipsel-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
- tmake_file="mips/t-elf mips/t-libgcc-mips16"
+ tmake_file="mips/t-elf"
;;
mips64-*-elf* | mips64el-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h"
- tmake_file="mips/t-elf mips/t-libgcc-mips16"
+ tmake_file="mips/t-elf"
target_cpu_default="MASK_64BIT|MASK_FLOAT64"
tm_defines="${tm_defines} MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_O64"
;;
@@ -1978,13 +1843,13 @@ mips64vr-*-elf* | mips64vrel-*-elf*)
;;
mips64orion-*-elf* | mips64orionel-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elforion.h mips/elf.h"
- tmake_file="mips/t-elf mips/t-libgcc-mips16"
+ tmake_file="mips/t-elf"
target_cpu_default="MASK_64BIT|MASK_FLOAT64"
tm_defines="${tm_defines} MIPS_ISA_DEFAULT=3 MIPS_ABI_DEFAULT=ABI_O64"
;;
mips*-*-rtems*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/elf.h mips/rtems.h rtems.h"
- tmake_file="mips/t-elf mips/t-libgcc-mips16 t-rtems mips/t-rtems"
+ tmake_file="mips/t-elf t-rtems mips/t-rtems"
;;
mips-wrs-vxworks)
tm_file="elfos.h ${tm_file} mips/elf.h vx-common.h vxworks.h mips/vxworks.h"
@@ -1992,7 +1857,7 @@ mips-wrs-vxworks)
;;
mipstx39-*-elf* | mipstx39el-*-elf*)
tm_file="elfos.h newlib-stdint.h ${tm_file} mips/r3900.h mips/elf.h"
- tmake_file="mips/t-r3900 mips/t-libgcc-mips16"
+ tmake_file="mips/t-r3900"
;;
mmix-knuth-mmixware)
tm_file="${tm_file} newlib-stdint.h"
@@ -2035,19 +1900,18 @@ powerpc-*-darwin*)
*-darwin[0-6]*)
;;
esac
- tmake_file="${tmake_file} t-slibgcc-dummy"
+ tmake_file="${tmake_file} t-slibgcc"
extra_headers=altivec.h
;;
powerpc64-*-darwin*)
extra_options="${extra_options} ${cpu_type}/darwin.opt"
- tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc-dummy"
+ tmake_file="${tmake_file} ${cpu_type}/t-darwin64 t-slibgcc"
tm_file="${tm_file} ${cpu_type}/darwin8.h ${cpu_type}/darwin64.h"
extra_headers=altivec.h
;;
powerpc-*-freebsd*)
tm_file="${tm_file} dbxelf.h elfos.h ${fbsd_tm_file} rs6000/sysv4.h rs6000/freebsd.h"
tmake_file="rs6000/t-fprules rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
- tmake_file="${tmake_file} t-slibgcc-libgcc"
extra_options="${extra_options} rs6000/sysv4.opt"
;;
powerpc-*-netbsd*)
@@ -2133,8 +1997,10 @@ powerpc-*-linux* | powerpc64-*-linux*)
tm_file="${tm_file} rs6000/linux.h glibc-stdint.h"
;;
esac
- tmake_file="${tmake_file} t-slibgcc-libgcc"
case ${target} in
+ powerpc*-*-linux*ppc476*)
+ tm_file="${tm_file} rs6000/476.h"
+ extra_options="${extra_options} rs6000/476.opt" ;;
powerpc*-*-linux*altivec*)
tm_file="${tm_file} rs6000/linuxaltivec.h" ;;
powerpc*-*-linux*spe*)
@@ -2166,7 +2032,6 @@ powerpc-*-lynxos*)
tm_file="${tm_file} dbxelf.h elfos.h rs6000/sysv4.h rs6000/lynx.h lynx.h"
tmake_file="t-lynx rs6000/t-lynx"
extra_options="${extra_options} rs6000/sysv4.opt lynx.opt"
- extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
thread_file=lynx
gnu_ld=yes
gas=yes
@@ -2190,7 +2055,7 @@ powerpcle-*-eabi*)
;;
rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
tm_file="rs6000/biarch64.h ${tm_file} rs6000/aix.h rs6000/aix43.h rs6000/xcoff.h rs6000/aix-stdint.h"
- tmake_file=rs6000/t-aix43
+ tmake_file="rs6000/t-aix43 t-slibgcc"
extra_options="${extra_options} rs6000/aix64.opt"
use_collect2=yes
thread_file='aix'
@@ -2200,7 +2065,7 @@ rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
tm_file="rs6000/biarch64.h ${tm_file} rs6000/aix.h rs6000/aix51.h rs6000/xcoff.h rs6000/aix-stdint.h"
extra_options="${extra_options} rs6000/aix64.opt"
- tmake_file=rs6000/t-aix43
+ tmake_file="rs6000/t-aix43 t-slibgcc"
use_collect2=yes
thread_file='aix'
use_gcc_stdint=wrap
@@ -2208,7 +2073,7 @@ rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
;;
rs6000-ibm-aix5.2.* | powerpc-ibm-aix5.2.*)
tm_file="${tm_file} rs6000/aix.h rs6000/aix52.h rs6000/xcoff.h rs6000/aix-stdint.h"
- tmake_file=rs6000/t-aix52
+ tmake_file="rs6000/t-aix52 t-slibgcc"
extra_options="${extra_options} rs6000/aix64.opt"
use_collect2=yes
thread_file='aix'
@@ -2217,7 +2082,7 @@ rs6000-ibm-aix5.2.* | powerpc-ibm-aix5.2.*)
;;
rs6000-ibm-aix5.3.* | powerpc-ibm-aix5.3.*)
tm_file="${tm_file} rs6000/aix.h rs6000/aix53.h rs6000/xcoff.h rs6000/aix-stdint.h"
- tmake_file=rs6000/t-aix52
+ tmake_file="rs6000/t-aix52 t-slibgcc"
extra_options="${extra_options} rs6000/aix64.opt"
use_collect2=yes
thread_file='aix'
@@ -2226,7 +2091,7 @@ rs6000-ibm-aix5.3.* | powerpc-ibm-aix5.3.*)
;;
rs6000-ibm-aix[6789].* | powerpc-ibm-aix[6789].*)
tm_file="${tm_file} rs6000/aix.h rs6000/aix61.h rs6000/xcoff.h rs6000/aix-stdint.h"
- tmake_file=rs6000/t-aix52
+ tmake_file="rs6000/t-aix52 t-slibgcc"
extra_options="${extra_options} rs6000/aix64.opt"
use_collect2=yes
thread_file='aix'
@@ -2235,7 +2100,6 @@ rs6000-ibm-aix[6789].* | powerpc-ibm-aix[6789].*)
;;
rx-*-elf*)
tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}"
- libgcc_tm_file="${libgcc_tm_file} rx/rx-abi.h rx/rx-lib.h"
tmake_file="${tmake_file} rx/t-rx"
;;
s390-*-linux*)
@@ -2258,7 +2122,6 @@ s390x-ibm-tpf*)
md_file=s390/s390.md
extra_modes=s390/s390-modes.def
out_file=s390/s390.c
- extra_parts="crtbeginS.o crtendS.o"
thread_file='tpf'
extra_options="${extra_options} s390/tpf.opt"
;;
@@ -2266,13 +2129,11 @@ score-*-elf)
gas=yes
gnu_ld=yes
tm_file="dbxelf.h elfos.h score/elf.h score/score.h newlib-stdint.h"
- extra_parts="crti.o crtn.o crtbegin.o crtend.o"
- tmake_file="${tmake_file} score/t-score-elf"
;;
sh-*-elf* | sh[12346l]*-*-elf* | \
sh-*-linux* | sh[2346lbe]*-*-linux* | \
sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
- sh64-*-netbsd* | sh64l*-*-netbsd*)
+ sh64-*-netbsd* | sh64l*-*-netbsd*)
tmake_file="${tmake_file} sh/t-sh sh/t-elf"
if test x${with_endian} = x; then
case ${target} in
@@ -2313,7 +2174,6 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
fi
tm_file="${tm_file} sh/embed-elf.h"
tm_file="${tm_file} sh/superh.h"
- tmake_file="${tmake_file} sh/t-superh"
extra_options="${extra_options} sh/superh.opt" ;;
*) if test x$with_newlib = xyes \
&& test x$with_libgloss = xyes; then
@@ -2324,17 +2184,16 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
case ${target} in
sh5*-*-netbsd*)
# SHmedia, 32-bit ABI
- tmake_file="${tmake_file} sh/t-sh64 sh/t-netbsd"
+ tmake_file="${tmake_file} sh/t-sh64"
;;
sh64*-netbsd*)
# SHmedia, 64-bit ABI
- tmake_file="${tmake_file} sh/t-sh64 sh/t-netbsd sh/t-netbsd-sh5-64"
+ tmake_file="${tmake_file} sh/t-sh64 sh/t-netbsd-sh5-64"
;;
*-*-netbsd)
- tmake_file="${tmake_file} sh/t-netbsd"
;;
sh64*-*-linux*)
- tmake_file="${tmake_file} sh/t-sh64 sh/t-linux64"
+ tmake_file="${tmake_file} sh/t-sh64"
tm_file="${tm_file} sh/sh64.h"
extra_headers="shmedia.h ushmedia.h sshmedia.h"
;;
@@ -2448,11 +2307,11 @@ sh-*-elf* | sh[12346l]*-*-elf* | \
tmake_file="$tmake_file t-sysroot-suffix"
;;
sh-*-rtems*)
- tmake_file="sh/t-sh sh/t-elf t-rtems sh/t-rtems"
+ tmake_file="sh/t-sh t-rtems sh/t-rtems"
tm_file="${tm_file} dbxelf.h elfos.h sh/elf.h sh/embed-elf.h sh/rtemself.h rtems.h newlib-stdint.h"
;;
sh-wrs-vxworks)
- tmake_file="$tmake_file sh/t-sh sh/t-elf sh/t-vxworks"
+ tmake_file="$tmake_file sh/t-sh sh/t-vxworks"
tm_file="${tm_file} elfos.h sh/elf.h sh/embed-elf.h vx-common.h vxworks.h sh/vxworks.h"
;;
sparc-*-elf*)
@@ -2484,7 +2343,7 @@ sparc-*-linux*)
tmake_file="${tmake_file} sparc/t-sparc sparc/t-leon3"
;;
*)
- tmake_file="${tmake_file} sparc/t-sparc sparc/t-linux"
+ tmake_file="${tmake_file} sparc/t-sparc"
;;
esac
if test x$enable_targets = xall; then
@@ -2493,7 +2352,6 @@ sparc-*-linux*)
else
tm_file="${tm_file} sparc/linux.h"
fi
- extra_parts="${extra_parts} crtfastmath.o"
;;
sparc-*-netbsdelf*)
tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h netbsd.h netbsd-elf.h sparc/netbsd-elf.h"
@@ -2519,19 +2377,18 @@ sparc-wrs-vxworks)
;;
sparc64-*-elf*)
tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h"
- extra_options="${extra_options} sparc/little-endian.opt"
+ extra_options="${extra_options}"
tmake_file="${tmake_file} sparc/t-sparc"
;;
sparc64-*-rtems*)
tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h sparc/sysv4.h sparc/sp64-elf.h sparc/rtemself.h rtems.h"
- extra_options="${extra_options} sparc/little-endian.opt"
+ extra_options="${extra_options}"
tmake_file="${tmake_file} sparc/t-sparc t-rtems"
;;
sparc64-*-linux*)
tm_file="sparc/biarch64.h ${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/default-64.h sparc/linux64.h"
extra_options="${extra_options} sparc/long-double-switch.opt"
- tmake_file="${tmake_file} sparc/t-sparc sparc/t-linux sparc/t-linux64"
- extra_parts="${extra_parts} crtfastmath.o"
+ tmake_file="${tmake_file} sparc/t-sparc sparc/t-linux64"
;;
sparc64-*-freebsd*|ultrasparc-*-freebsd*)
tm_file="${tm_file} ${fbsd_tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/freebsd.h"
@@ -2541,7 +2398,6 @@ sparc64-*-freebsd*|ultrasparc-*-freebsd*)
x) with_cpu=ultrasparc ;;
*) echo "$with_cpu not supported for freebsd target"; exit 1 ;;
esac
- extra_parts="${extra_parts} crtfastmath.o"
tmake_file="${tmake_file} sparc/t-sparc"
;;
sparc64-*-netbsd*)
@@ -2555,7 +2411,7 @@ sparc64-*-openbsd*)
tm_file="sparc/openbsd1-64.h ${tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/sp64-elf.h"
tm_file="${tm_file} openbsd.h openbsd-stdint.h openbsd-libpthread.h sparc/openbsd64.h"
extra_options="${extra_options} openbsd.opt"
- extra_options="${extra_options} sparc/little-endian.opt"
+ extra_options="${extra_options}"
gas=yes gnu_ld=yes
with_cpu=ultrasparc
tmake_file="${tmake_file} sparc/t-sparc"
@@ -2563,6 +2419,7 @@ sparc64-*-openbsd*)
spu-*-elf*)
tm_file="dbxelf.h elfos.h spu/spu-elf.h spu/spu.h newlib-stdint.h"
tmake_file="spu/t-spu-elf"
+ native_system_header_dir=/include
extra_headers="spu_intrinsics.h spu_internals.h vmx2spu.h spu_mfcio.h vec_types.h spu_cache.h"
extra_modes=spu/spu-modes.def
c_target_objs="${c_target_objs} spu-c.o"
@@ -2571,7 +2428,6 @@ spu-*-elf*)
tic6x-*-elf)
tm_file="elfos.h ${tm_file} c6x/elf-common.h c6x/elf.h"
tm_file="${tm_file} dbxelf.h tm-dwarf2.h newlib-stdint.h"
- libgcc_tm_file="${libgcc_tm_file} c6x/c6x-abi.h"
tmake_file="c6x/t-c6x c6x/t-c6x-elf"
use_collect2=no
;;
@@ -2579,8 +2435,7 @@ tic6x-*-uclinux)
tm_file="elfos.h ${tm_file} gnu-user.h linux.h c6x/elf-common.h c6x/uclinux-elf.h"
tm_file="${tm_file} dbxelf.h tm-dwarf2.h glibc-stdint.h"
tm_file="${tm_file} ./sysroot-suffix.h"
- libgcc_tm_file="${libgcc_tm_file} c6x/c6x-abi.h"
- tmake_file="t-slibgcc-elf-ver t-sysroot-suffix"
+ tmake_file="t-sysroot-suffix t-slibgcc"
tmake_file="${tmake_file} c6x/t-c6x c6x/t-c6x-elf c6x/t-c6x-uclinux"
use_collect2=no
;;
@@ -2615,7 +2470,6 @@ v850*-*-*)
vax-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h vax/elf.h vax/linux.h"
extra_options="${extra_options} vax/elf.opt"
- tmake_file="${tmake_file} vax/t-linux"
;;
vax-*-netbsdelf*)
tm_file="${tm_file} elfos.h netbsd.h netbsd-elf.h vax/elf.h vax/netbsd-elf.h"
@@ -2634,21 +2488,18 @@ xstormy16-*-elf)
out_file=stormy16/stormy16.c
extra_options=stormy16/stormy16.opt
tmake_file="stormy16/t-stormy16"
- extra_parts="crtbegin.o crtend.o"
;;
xtensa*-*-elf*)
tm_file="${tm_file} dbxelf.h elfos.h newlib-stdint.h xtensa/elf.h"
extra_options="${extra_options} xtensa/elf.opt"
- tmake_file="xtensa/t-xtensa xtensa/t-elf"
;;
xtensa*-*-linux*)
tm_file="${tm_file} dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h xtensa/linux.h"
- tmake_file="${tmake_file} xtensa/t-xtensa xtensa/t-linux"
+ tmake_file="${tmake_file} xtensa/t-xtensa"
;;
am33_2.0-*-linux*)
tm_file="mn10300/mn10300.h dbxelf.h elfos.h gnu-user.h linux.h glibc-stdint.h mn10300/linux.h"
gas=yes gnu_ld=yes
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o"
use_collect2=no
;;
m32c-*-rtems*)
@@ -2671,7 +2522,6 @@ esac
case ${target} in
i[34567]86-*-linux* | x86_64-*-linux*)
tmake_file="${tmake_file} i386/t-pmm_malloc i386/t-i386"
- libgcc_tm_file="${libgcc_tm_file} i386/value-unwind.h"
;;
i[34567]86-*-* | x86_64-*-*)
tmake_file="${tmake_file} i386/t-gmm_malloc i386/t-i386"
@@ -3596,7 +3446,6 @@ case ${target} in
i[34567]86-*-linux* | x86_64-*-linux* | \
i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu | \
i[34567]86-*-gnu*)
- tmake_file="${tmake_file} i386/t-linux"
;;
i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
;;
diff --git a/gcc/config.host b/gcc/config.host
index df8ba8fa801..696c79e3507 100644
--- a/gcc/config.host
+++ b/gcc/config.host
@@ -100,6 +100,14 @@ case ${host} in
esac
case ${host} in
+ arm*-*-linux*)
+ case ${target} in
+ arm*-*-*)
+ host_extra_gcc_objs="driver-arm.o"
+ host_xmake_file="${host_xmake_file} arm/x-arm"
+ ;;
+ esac
+ ;;
alpha*-*-linux* | alpha*-dec-osf*)
case ${target} in
alpha*-*-linux* | alpha*-dec-osf*)
diff --git a/gcc/config.in b/gcc/config.in
index f2847d87895..3950e289b7c 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -753,6 +753,13 @@
#endif
+/* Define to 1 if we found a declaration for 'madvise', otherwise define to 0.
+ */
+#ifndef USED_FOR_TARGET
+#undef HAVE_DECL_MADVISE
+#endif
+
+
/* Define to 1 if we found a declaration for 'malloc', otherwise define to 0.
*/
#ifndef USED_FOR_TARGET
@@ -1276,6 +1283,12 @@
#endif
+/* Define to 1 if you have the `madvise' function. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_MADVISE
+#endif
+
+
/* Define to 1 if you have the <malloc.h> header file. */
#ifndef USED_FOR_TARGET
#undef HAVE_MALLOC_H
diff --git a/gcc/config/alpha/t-alpha b/gcc/config/alpha/t-alpha
deleted file mode 100644
index d0b58d69a4e..00000000000
--- a/gcc/config/alpha/t-alpha
+++ /dev/null
@@ -1,2 +0,0 @@
-# This is a support routine for longlong.h, used by libgcc2.c.
-LIB2FUNCS_EXTRA = $(srcdir)/config/alpha/qrnnd.asm
diff --git a/gcc/config/alpha/t-ieee b/gcc/config/alpha/t-ieee
deleted file mode 100644
index fe549dfc992..00000000000
--- a/gcc/config/alpha/t-ieee
+++ /dev/null
@@ -1,2 +0,0 @@
-# All alphas get an IEEE complaint set of libraries.
-TARGET_LIBGCC2_CFLAGS += -mieee
diff --git a/gcc/config/alpha/t-vms b/gcc/config/alpha/t-vms
index 410e219ff5b..760f943d063 100644
--- a/gcc/config/alpha/t-vms
+++ b/gcc/config/alpha/t-vms
@@ -1,5 +1,5 @@
# Copyright (C) 1996, 1997, 1998, 2001, 2002,
-# 2007, 2009 Free Software Foundation, Inc.
+# 2007, 2009, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -17,49 +17,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB2FUNCS_EXTRA = $(srcdir)/config/alpha/vms-gcc_shell_handler.c
-
-EXTRA_PARTS = vms-dwarf2.o vms-dwarf2eh.o $(VMS_EXTRA_PARTS) \
- crtbegin.o crtbeginS.o crtend.o crtendS.o
-
-# This object must be linked with in order to make the executable debuggable.
-# vms-ld handles it automatically when passed -g.
-$(T)vms-dwarf2.o : $(srcdir)/config/alpha/vms-dwarf2.asm
- $(GCC_FOR_TARGET) -c -x assembler $< -o $@
-
-$(T)vms-dwarf2eh.o : $(srcdir)/config/alpha/vms-dwarf2eh.asm
- $(GCC_FOR_TARGET) -c -x assembler $< -o $@
-
MULTILIB_OPTIONS = mcpu=ev6
MULTILIB_DIRNAMES = ev6
MULTILIB_OSDIRNAMES = ev6
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-shlib_version:=$(shell echo $(BASEVER_c) | sed -e 's/\./,/' -e 's/\.//g')
-SHLIB_EXT = .exe
-SHLIB_OBJS = @shlib_objs@
-SHLIB_NAME = @shlib_base_name@.exe
-SHLIB_MULTILIB =
-SHLIB_INSTALL = $(INSTALL_DATA) $(SHLIB_NAME) $$(DESTDIR)$$(libsubdir)/$(SHLIB_NAME)
-SHLIB_SYMVEC = \
- grep -F -e "\$$BSS\$$" -e "\$$DATA\$$" -e " sdata " -e " data.rel " -e " data.rel.ro " -e " sbss " \
- -e "\$$LINK\$$" -e "\$$READONLY\$$" | \
- sed -e "s/.*\$$LINK\$$ \(.*\)/SYMBOL_VECTOR=(\1=PROCEDURE)/" \
- -e "s/.*\$$DATA\$$ \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
- -e "s/.* sbss \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
- -e "s/.* sdata \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
- -e "s/.* data.rel \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
- -e "s/.* data.rel.ro \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
- -e "s/.*\$$BSS\$$ \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
- -e "s/.*\$$READONLY\$$ \(.*\)/SYMBOL_VECTOR=(\1=DATA)/"
-SHLIB_SYMVECX2 := $(subst $$,$$$$,$(SHLIB_SYMVEC))
-SHLIB_LINK = \
- echo "case_sensitive=yes" > SYMVEC_$$$$$$$$.opt; \
- objdump --syms $(SHLIB_OBJS) | \
- $(SHLIB_SYMVECX2) >> SYMVEC_$$$$$$$$.opt ; \
- echo "case_sensitive=NO" >> SYMVEC_$$$$$$$$.opt; \
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -nodefaultlibs \
- -shared --for-linker=/noinform -o $(SHLIB_NAME) $(SHLIB_OBJS) \
- --for-linker=SYMVEC_$$$$$$$$.opt \
- --for-linker=gsmatch=equal,$(shlib_version)
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index ad733dad1d0..5f0d5629462 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -10766,6 +10766,335 @@ gen_const_stm_seq (rtx *operands, int nops)
return true;
}
+/* Copy a block of memory using plain ldr/str/ldrh/strh instructions, to permit
+ unaligned copies on processors which support unaligned semantics for those
+ instructions. INTERLEAVE_FACTOR can be used to attempt to hide load latency
+ (using more registers) by doing e.g. load/load/store/store for a factor of 2.
+ An interleave factor of 1 (the minimum) will perform no interleaving.
+ Load/store multiple are used for aligned addresses where possible. */
+
+static void
+arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase,
+ HOST_WIDE_INT length,
+ unsigned int interleave_factor)
+{
+ rtx *regs = XALLOCAVEC (rtx, interleave_factor);
+ int *regnos = XALLOCAVEC (int, interleave_factor);
+ HOST_WIDE_INT block_size_bytes = interleave_factor * UNITS_PER_WORD;
+ HOST_WIDE_INT i, j;
+ HOST_WIDE_INT remaining = length, words;
+ rtx halfword_tmp = NULL, byte_tmp = NULL;
+ rtx dst, src;
+ bool src_aligned = MEM_ALIGN (srcbase) >= BITS_PER_WORD;
+ bool dst_aligned = MEM_ALIGN (dstbase) >= BITS_PER_WORD;
+ HOST_WIDE_INT srcoffset, dstoffset;
+ HOST_WIDE_INT src_autoinc, dst_autoinc;
+ rtx mem, addr;
+
+ gcc_assert (1 <= interleave_factor && interleave_factor <= 4);
+
+ /* Use hard registers if we have aligned source or destination so we can use
+ load/store multiple with contiguous registers. */
+ if (dst_aligned || src_aligned)
+ for (i = 0; i < interleave_factor; i++)
+ regs[i] = gen_rtx_REG (SImode, i);
+ else
+ for (i = 0; i < interleave_factor; i++)
+ regs[i] = gen_reg_rtx (SImode);
+
+ dst = copy_addr_to_reg (XEXP (dstbase, 0));
+ src = copy_addr_to_reg (XEXP (srcbase, 0));
+
+ srcoffset = dstoffset = 0;
+
+ /* Calls to arm_gen_load_multiple and arm_gen_store_multiple update SRC/DST.
+ For copying the last bytes we want to subtract this offset again. */
+ src_autoinc = dst_autoinc = 0;
+
+ for (i = 0; i < interleave_factor; i++)
+ regnos[i] = i;
+
+ /* Copy BLOCK_SIZE_BYTES chunks. */
+
+ for (i = 0; i + block_size_bytes <= length; i += block_size_bytes)
+ {
+ /* Load words. */
+ if (src_aligned && interleave_factor > 1)
+ {
+ emit_insn (arm_gen_load_multiple (regnos, interleave_factor, src,
+ TRUE, srcbase, &srcoffset));
+ src_autoinc += UNITS_PER_WORD * interleave_factor;
+ }
+ else
+ {
+ for (j = 0; j < interleave_factor; j++)
+ {
+ addr = plus_constant (src, srcoffset + j * UNITS_PER_WORD
+ - src_autoinc);
+ mem = adjust_automodify_address (srcbase, SImode, addr,
+ srcoffset + j * UNITS_PER_WORD);
+ emit_insn (gen_unaligned_loadsi (regs[j], mem));
+ }
+ srcoffset += block_size_bytes;
+ }
+
+ /* Store words. */
+ if (dst_aligned && interleave_factor > 1)
+ {
+ emit_insn (arm_gen_store_multiple (regnos, interleave_factor, dst,
+ TRUE, dstbase, &dstoffset));
+ dst_autoinc += UNITS_PER_WORD * interleave_factor;
+ }
+ else
+ {
+ for (j = 0; j < interleave_factor; j++)
+ {
+ addr = plus_constant (dst, dstoffset + j * UNITS_PER_WORD
+ - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, SImode, addr,
+ dstoffset + j * UNITS_PER_WORD);
+ emit_insn (gen_unaligned_storesi (mem, regs[j]));
+ }
+ dstoffset += block_size_bytes;
+ }
+
+ remaining -= block_size_bytes;
+ }
+
+ /* Copy any whole words left (note these aren't interleaved with any
+ subsequent halfword/byte load/stores in the interests of simplicity). */
+
+ words = remaining / UNITS_PER_WORD;
+
+ gcc_assert (words < interleave_factor);
+
+ if (src_aligned && words > 1)
+ {
+ emit_insn (arm_gen_load_multiple (regnos, words, src, TRUE, srcbase,
+ &srcoffset));
+ src_autoinc += UNITS_PER_WORD * words;
+ }
+ else
+ {
+ for (j = 0; j < words; j++)
+ {
+ addr = plus_constant (src,
+ srcoffset + j * UNITS_PER_WORD - src_autoinc);
+ mem = adjust_automodify_address (srcbase, SImode, addr,
+ srcoffset + j * UNITS_PER_WORD);
+ emit_insn (gen_unaligned_loadsi (regs[j], mem));
+ }
+ srcoffset += words * UNITS_PER_WORD;
+ }
+
+ if (dst_aligned && words > 1)
+ {
+ emit_insn (arm_gen_store_multiple (regnos, words, dst, TRUE, dstbase,
+ &dstoffset));
+ dst_autoinc += words * UNITS_PER_WORD;
+ }
+ else
+ {
+ for (j = 0; j < words; j++)
+ {
+ addr = plus_constant (dst,
+ dstoffset + j * UNITS_PER_WORD - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, SImode, addr,
+ dstoffset + j * UNITS_PER_WORD);
+ emit_insn (gen_unaligned_storesi (mem, regs[j]));
+ }
+ dstoffset += words * UNITS_PER_WORD;
+ }
+
+ remaining -= words * UNITS_PER_WORD;
+
+ gcc_assert (remaining < 4);
+
+ /* Copy a halfword if necessary. */
+
+ if (remaining >= 2)
+ {
+ halfword_tmp = gen_reg_rtx (SImode);
+
+ addr = plus_constant (src, srcoffset - src_autoinc);
+ mem = adjust_automodify_address (srcbase, HImode, addr, srcoffset);
+ emit_insn (gen_unaligned_loadhiu (halfword_tmp, mem));
+
+ /* Either write out immediately, or delay until we've loaded the last
+ byte, depending on interleave factor. */
+ if (interleave_factor == 1)
+ {
+ addr = plus_constant (dst, dstoffset - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, HImode, addr, dstoffset);
+ emit_insn (gen_unaligned_storehi (mem,
+ gen_lowpart (HImode, halfword_tmp)));
+ halfword_tmp = NULL;
+ dstoffset += 2;
+ }
+
+ remaining -= 2;
+ srcoffset += 2;
+ }
+
+ gcc_assert (remaining < 2);
+
+ /* Copy last byte. */
+
+ if ((remaining & 1) != 0)
+ {
+ byte_tmp = gen_reg_rtx (SImode);
+
+ addr = plus_constant (src, srcoffset - src_autoinc);
+ mem = adjust_automodify_address (srcbase, QImode, addr, srcoffset);
+ emit_move_insn (gen_lowpart (QImode, byte_tmp), mem);
+
+ if (interleave_factor == 1)
+ {
+ addr = plus_constant (dst, dstoffset - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, QImode, addr, dstoffset);
+ emit_move_insn (mem, gen_lowpart (QImode, byte_tmp));
+ byte_tmp = NULL;
+ dstoffset++;
+ }
+
+ remaining--;
+ srcoffset++;
+ }
+
+ /* Store last halfword if we haven't done so already. */
+
+ if (halfword_tmp)
+ {
+ addr = plus_constant (dst, dstoffset - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, HImode, addr, dstoffset);
+ emit_insn (gen_unaligned_storehi (mem,
+ gen_lowpart (HImode, halfword_tmp)));
+ dstoffset += 2;
+ }
+
+ /* Likewise for last byte. */
+
+ if (byte_tmp)
+ {
+ addr = plus_constant (dst, dstoffset - dst_autoinc);
+ mem = adjust_automodify_address (dstbase, QImode, addr, dstoffset);
+ emit_move_insn (mem, gen_lowpart (QImode, byte_tmp));
+ dstoffset++;
+ }
+
+ gcc_assert (remaining == 0 && srcoffset == dstoffset);
+}
+
+/* From mips_adjust_block_mem:
+
+ Helper function for doing a loop-based block operation on memory
+ reference MEM. Each iteration of the loop will operate on LENGTH
+ bytes of MEM.
+
+ Create a new base register for use within the loop and point it to
+ the start of MEM. Create a new memory reference that uses this
+ register. Store them in *LOOP_REG and *LOOP_MEM respectively. */
+
+static void
+arm_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg,
+ rtx *loop_mem)
+{
+ *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
+
+ /* Although the new mem does not refer to a known location,
+ it does keep up to LENGTH bytes of alignment. */
+ *loop_mem = change_address (mem, BLKmode, *loop_reg);
+ set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT));
+}
+
+/* From mips_block_move_loop:
+
+ Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER
+ bytes at a time. LENGTH must be at least BYTES_PER_ITER. Assume that
+ the memory regions do not overlap. */
+
+static void
+arm_block_move_unaligned_loop (rtx dest, rtx src, HOST_WIDE_INT length,
+ unsigned int interleave_factor,
+ HOST_WIDE_INT bytes_per_iter)
+{
+ rtx label, src_reg, dest_reg, final_src, test;
+ HOST_WIDE_INT leftover;
+
+ leftover = length % bytes_per_iter;
+ length -= leftover;
+
+ /* Create registers and memory references for use within the loop. */
+ arm_adjust_block_mem (src, bytes_per_iter, &src_reg, &src);
+ arm_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest);
+
+ /* Calculate the value that SRC_REG should have after the last iteration of
+ the loop. */
+ final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length),
+ 0, 0, OPTAB_WIDEN);
+
+ /* Emit the start of the loop. */
+ label = gen_label_rtx ();
+ emit_label (label);
+
+ /* Emit the loop body. */
+ arm_block_move_unaligned_straight (dest, src, bytes_per_iter,
+ interleave_factor);
+
+ /* Move on to the next block. */
+ emit_move_insn (src_reg, plus_constant (src_reg, bytes_per_iter));
+ emit_move_insn (dest_reg, plus_constant (dest_reg, bytes_per_iter));
+
+ /* Emit the loop condition. */
+ test = gen_rtx_NE (VOIDmode, src_reg, final_src);
+ emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label));
+
+ /* Mop up any left-over bytes. */
+ if (leftover)
+ arm_block_move_unaligned_straight (dest, src, leftover, interleave_factor);
+}
+
+/* Emit a block move when either the source or destination is unaligned (not
+ aligned to a four-byte boundary). This may need further tuning depending on
+ core type, optimize_size setting, etc. */
+
+static int
+arm_movmemqi_unaligned (rtx *operands)
+{
+ HOST_WIDE_INT length = INTVAL (operands[2]);
+
+ if (optimize_size)
+ {
+ bool src_aligned = MEM_ALIGN (operands[1]) >= BITS_PER_WORD;
+ bool dst_aligned = MEM_ALIGN (operands[0]) >= BITS_PER_WORD;
+ /* Inlined memcpy using ldr/str/ldrh/strh can be quite big: try to limit
+ size of code if optimizing for size. We'll use ldm/stm if src_aligned
+ or dst_aligned though: allow more interleaving in those cases since the
+ resulting code can be smaller. */
+ unsigned int interleave_factor = (src_aligned || dst_aligned) ? 2 : 1;
+ HOST_WIDE_INT bytes_per_iter = (src_aligned || dst_aligned) ? 8 : 4;
+
+ if (length > 12)
+ arm_block_move_unaligned_loop (operands[0], operands[1], length,
+ interleave_factor, bytes_per_iter);
+ else
+ arm_block_move_unaligned_straight (operands[0], operands[1], length,
+ interleave_factor);
+ }
+ else
+ {
+ /* Note that the loop created by arm_block_move_unaligned_loop may be
+ subject to loop unrolling, which makes tuning this condition a little
+ redundant. */
+ if (length > 32)
+ arm_block_move_unaligned_loop (operands[0], operands[1], length, 4, 16);
+ else
+ arm_block_move_unaligned_straight (operands[0], operands[1], length, 4);
+ }
+
+ return 1;
+}
+
int
arm_gen_movmemqi (rtx *operands)
{
@@ -10778,8 +11107,13 @@ arm_gen_movmemqi (rtx *operands)
if (GET_CODE (operands[2]) != CONST_INT
|| GET_CODE (operands[3]) != CONST_INT
- || INTVAL (operands[2]) > 64
- || INTVAL (operands[3]) & 3)
+ || INTVAL (operands[2]) > 64)
+ return 0;
+
+ if (unaligned_access && (INTVAL (operands[3]) & 3) != 0)
+ return arm_movmemqi_unaligned (operands);
+
+ if (INTVAL (operands[3]) & 3)
return 0;
dstbase = operands[0];
@@ -21318,7 +21652,8 @@ thumb_unexpanded_epilogue (void)
if (extra_pop > 0)
{
unsigned long extra_mask = (1 << extra_pop) - 1;
- live_regs_mask |= extra_mask << (size / UNITS_PER_WORD);
+ live_regs_mask |= extra_mask << ((size + UNITS_PER_WORD - 1)
+ / UNITS_PER_WORD);
}
/* The prolog may have pushed some high registers to use as
@@ -23160,7 +23495,7 @@ arm_small_register_classes_for_mode_p (enum machine_mode mode ATTRIBUTE_UNUSED)
/* Implement TARGET_SHIFT_TRUNCATION_MASK. SImode shifts use normal
ARM insns and therefore guarantee that the shift count is modulo 256.
- DImode shifts (those implemented by lib1funcs.asm or by optabs.c)
+ DImode shifts (those implemented by lib1funcs.S or by optabs.c)
guarantee no particular behavior for out-of-range counts. */
static unsigned HOST_WIDE_INT
@@ -24042,12 +24377,26 @@ arm_output_ldrex (emit_f emit,
rtx target,
rtx memory)
{
- const char *suffix = arm_ldrex_suffix (mode);
- rtx operands[2];
+ rtx operands[3];
operands[0] = target;
- operands[1] = memory;
- arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix);
+ if (mode != DImode)
+ {
+ const char *suffix = arm_ldrex_suffix (mode);
+ operands[1] = memory;
+ arm_output_asm_insn (emit, 0, operands, "ldrex%s\t%%0, %%C1", suffix);
+ }
+ else
+ {
+ /* The restrictions on target registers in ARM mode are that the two
+ registers are consecutive and the first one is even; Thumb is
+ actually more flexible, but DI should give us this anyway.
+ Note that the 1st register always gets the lowest word in memory. */
+ gcc_assert ((REGNO (target) & 1) == 0);
+ operands[1] = gen_rtx_REG (SImode, REGNO (target) + 1);
+ operands[2] = memory;
+ arm_output_asm_insn (emit, 0, operands, "ldrexd\t%%0, %%1, %%C2");
+ }
}
/* Emit a strex{b,h,d, } instruction appropriate for the specified
@@ -24060,14 +24409,41 @@ arm_output_strex (emit_f emit,
rtx value,
rtx memory)
{
- const char *suffix = arm_ldrex_suffix (mode);
- rtx operands[3];
+ rtx operands[4];
operands[0] = result;
operands[1] = value;
- operands[2] = memory;
- arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2", suffix,
- cc);
+ if (mode != DImode)
+ {
+ const char *suffix = arm_ldrex_suffix (mode);
+ operands[2] = memory;
+ arm_output_asm_insn (emit, 0, operands, "strex%s%s\t%%0, %%1, %%C2",
+ suffix, cc);
+ }
+ else
+ {
+ /* The restrictions on target registers in ARM mode are that the two
+ registers are consecutive and the first one is even; Thumb is
+ actually more flexible, but DI should give us this anyway.
+ Note that the 1st register always gets the lowest word in memory. */
+ gcc_assert ((REGNO (value) & 1) == 0 || TARGET_THUMB2);
+ operands[2] = gen_rtx_REG (SImode, REGNO (value) + 1);
+ operands[3] = memory;
+ arm_output_asm_insn (emit, 0, operands, "strexd%s\t%%0, %%1, %%2, %%C3",
+ cc);
+ }
+}
+
+/* Helper to emit an it instruction in Thumb2 mode only; although the assembler
+ will ignore it in ARM mode, emitting it will mess up instruction counts we
+ sometimes keep 'flags' are the extra t's and e's if it's more than one
+ instruction that is conditional. */
+static void
+arm_output_it (emit_f emit, const char *flags, const char *cond)
+{
+ rtx operands[1]; /* Don't actually use the operand. */
+ if (TARGET_THUMB2)
+ arm_output_asm_insn (emit, 0, operands, "it%s\t%s", flags, cond);
}
/* Helper to emit a two operand instruction. */
@@ -24109,7 +24485,7 @@ arm_output_op3 (emit_f emit, const char *mnemonic, rtx d, rtx a, rtx b)
required_value:
- RTX register or const_int representing the required old_value for
+ RTX register representing the required old_value for
the modify to continue, if NULL no comparsion is performed. */
static void
arm_output_sync_loop (emit_f emit,
@@ -24123,7 +24499,13 @@ arm_output_sync_loop (emit_f emit,
enum attr_sync_op sync_op,
int early_barrier_required)
{
- rtx operands[1];
+ rtx operands[2];
+ /* We'll use the lo for the normal rtx in the none-DI case
+ as well as the least-sig word in the DI case. */
+ rtx old_value_lo, required_value_lo, new_value_lo, t1_lo;
+ rtx old_value_hi, required_value_hi, new_value_hi, t1_hi;
+
+ bool is_di = mode == DImode;
gcc_assert (t1 != t2);
@@ -24134,82 +24516,142 @@ arm_output_sync_loop (emit_f emit,
arm_output_ldrex (emit, mode, old_value, memory);
+ if (is_di)
+ {
+ old_value_lo = gen_lowpart (SImode, old_value);
+ old_value_hi = gen_highpart (SImode, old_value);
+ if (required_value)
+ {
+ required_value_lo = gen_lowpart (SImode, required_value);
+ required_value_hi = gen_highpart (SImode, required_value);
+ }
+ else
+ {
+ /* Silence false potentially unused warning. */
+ required_value_lo = NULL_RTX;
+ required_value_hi = NULL_RTX;
+ }
+ new_value_lo = gen_lowpart (SImode, new_value);
+ new_value_hi = gen_highpart (SImode, new_value);
+ t1_lo = gen_lowpart (SImode, t1);
+ t1_hi = gen_highpart (SImode, t1);
+ }
+ else
+ {
+ old_value_lo = old_value;
+ new_value_lo = new_value;
+ required_value_lo = required_value;
+ t1_lo = t1;
+
+ /* Silence false potentially unused warning. */
+ t1_hi = NULL_RTX;
+ new_value_hi = NULL_RTX;
+ required_value_hi = NULL_RTX;
+ old_value_hi = NULL_RTX;
+ }
+
if (required_value)
{
- rtx operands[2];
+ operands[0] = old_value_lo;
+ operands[1] = required_value_lo;
- operands[0] = old_value;
- operands[1] = required_value;
arm_output_asm_insn (emit, 0, operands, "cmp\t%%0, %%1");
+ if (is_di)
+ {
+ arm_output_it (emit, "", "eq");
+ arm_output_op2 (emit, "cmpeq", old_value_hi, required_value_hi);
+ }
arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYB%%=", LOCAL_LABEL_PREFIX);
}
switch (sync_op)
{
case SYNC_OP_ADD:
- arm_output_op3 (emit, "add", t1, old_value, new_value);
+ arm_output_op3 (emit, is_di ? "adds" : "add",
+ t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "adc", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_SUB:
- arm_output_op3 (emit, "sub", t1, old_value, new_value);
+ arm_output_op3 (emit, is_di ? "subs" : "sub",
+ t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "sbc", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_IOR:
- arm_output_op3 (emit, "orr", t1, old_value, new_value);
+ arm_output_op3 (emit, "orr", t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "orr", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_XOR:
- arm_output_op3 (emit, "eor", t1, old_value, new_value);
+ arm_output_op3 (emit, "eor", t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "eor", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_AND:
- arm_output_op3 (emit,"and", t1, old_value, new_value);
+ arm_output_op3 (emit,"and", t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "and", t1_hi, old_value_hi, new_value_hi);
break;
case SYNC_OP_NAND:
- arm_output_op3 (emit, "and", t1, old_value, new_value);
- arm_output_op2 (emit, "mvn", t1, t1);
+ arm_output_op3 (emit, "and", t1_lo, old_value_lo, new_value_lo);
+ if (is_di)
+ arm_output_op3 (emit, "and", t1_hi, old_value_hi, new_value_hi);
+ arm_output_op2 (emit, "mvn", t1_lo, t1_lo);
+ if (is_di)
+ arm_output_op2 (emit, "mvn", t1_hi, t1_hi);
break;
case SYNC_OP_NONE:
t1 = new_value;
+ t1_lo = new_value_lo;
+ if (is_di)
+ t1_hi = new_value_hi;
break;
}
+ /* Note that the result of strex is a 0/1 flag that's always 1 register. */
if (t2)
{
- arm_output_strex (emit, mode, "", t2, t1, memory);
- operands[0] = t2;
- arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
- arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
- LOCAL_LABEL_PREFIX);
+ arm_output_strex (emit, mode, "", t2, t1, memory);
+ operands[0] = t2;
+ arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
+ arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
+ LOCAL_LABEL_PREFIX);
}
else
{
/* Use old_value for the return value because for some operations
the old_value can easily be restored. This saves one register. */
- arm_output_strex (emit, mode, "", old_value, t1, memory);
- operands[0] = old_value;
+ arm_output_strex (emit, mode, "", old_value_lo, t1, memory);
+ operands[0] = old_value_lo;
arm_output_asm_insn (emit, 0, operands, "teq\t%%0, #0");
arm_output_asm_insn (emit, 0, operands, "bne\t%sLSYT%%=",
LOCAL_LABEL_PREFIX);
+ /* Note that we only used the _lo half of old_value as a temporary
+ so in DI we don't have to restore the _hi part. */
switch (sync_op)
{
case SYNC_OP_ADD:
- arm_output_op3 (emit, "sub", old_value, t1, new_value);
+ arm_output_op3 (emit, "sub", old_value_lo, t1_lo, new_value_lo);
break;
case SYNC_OP_SUB:
- arm_output_op3 (emit, "add", old_value, t1, new_value);
+ arm_output_op3 (emit, "add", old_value_lo, t1_lo, new_value_lo);
break;
case SYNC_OP_XOR:
- arm_output_op3 (emit, "eor", old_value, t1, new_value);
+ arm_output_op3 (emit, "eor", old_value_lo, t1_lo, new_value_lo);
break;
case SYNC_OP_NONE:
- arm_output_op2 (emit, "mov", old_value, required_value);
+ arm_output_op2 (emit, "mov", old_value_lo, required_value_lo);
break;
default:
@@ -24217,8 +24659,11 @@ arm_output_sync_loop (emit_f emit,
}
}
- arm_process_output_memory_barrier (emit, NULL);
+ /* Note: label is before barrier so that in cmp failure case we still get
+ a barrier to stop subsequent loads floating upwards past the ldrex
+ PR target/48126. */
arm_output_asm_insn (emit, 1, operands, "%sLSYB%%=:", LOCAL_LABEL_PREFIX);
+ arm_process_output_memory_barrier (emit, NULL);
}
static rtx
@@ -24312,7 +24757,7 @@ arm_expand_sync (enum machine_mode mode,
target = gen_reg_rtx (mode);
memory = arm_legitimize_sync_memory (memory);
- if (mode != SImode)
+ if (mode != SImode && mode != DImode)
{
rtx load_temp = gen_reg_rtx (SImode);
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 8ce2b3e3e97..85e2b9971c4 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -288,7 +288,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
#define TARGET_HAVE_DMB (arm_arch7)
/* Nonzero if this chip implements a memory barrier via CP15. */
-#define TARGET_HAVE_DMB_MCR (arm_arch6k && ! TARGET_HAVE_DMB)
+#define TARGET_HAVE_DMB_MCR (arm_arch6 && ! TARGET_HAVE_DMB \
+ && ! TARGET_THUMB1)
/* Nonzero if this chip implements a memory barrier instruction. */
#define TARGET_HAVE_MEMORY_BARRIER (TARGET_HAVE_DMB || TARGET_HAVE_DMB_MCR)
@@ -296,8 +297,12 @@ extern void (*arm_lang_output_object_attributes_hook)(void);
/* Nonzero if this chip supports ldrex and strex */
#define TARGET_HAVE_LDREX ((arm_arch6 && TARGET_ARM) || arm_arch7)
-/* Nonzero if this chip supports ldrex{bhd} and strex{bhd}. */
-#define TARGET_HAVE_LDREXBHD ((arm_arch6k && TARGET_ARM) || arm_arch7)
+/* Nonzero if this chip supports ldrex{bh} and strex{bh}. */
+#define TARGET_HAVE_LDREXBH ((arm_arch6k && TARGET_ARM) || arm_arch7)
+
+/* Nonzero if this chip supports ldrexd and strexd. */
+#define TARGET_HAVE_LDREXD (((arm_arch6k && TARGET_ARM) || arm_arch7) \
+ && arm_arch_notm)
/* Nonzero if integer division instructions supported. */
#define TARGET_IDIV ((TARGET_ARM && arm_arch_arm_hwdiv) \
@@ -2250,4 +2255,21 @@ extern int making_const_table;
} \
while (0)
+/* -mcpu=native handling only makes sense with compiler running on
+ an ARM chip. */
+#if defined(__arm__)
+extern const char *host_detect_local_cpu (int argc, const char **argv);
+# define EXTRA_SPEC_FUNCTIONS \
+ { "local_cpu_detect", host_detect_local_cpu },
+
+# define MCPU_MTUNE_NATIVE_SPECS \
+ " %{march=native:%<march=native %:local_cpu_detect(arch)}" \
+ " %{mcpu=native:%<mcpu=native %:local_cpu_detect(cpu)}" \
+ " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}"
+#else
+# define MCPU_MTUNE_NATIVE_SPECS ""
+#endif
+
+#define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS
+
#endif /* ! GCC_ARM_H */
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index e33b460520f..934aa35775e 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -80,6 +80,11 @@ march=
Target RejectNegative Joined Enum(arm_arch) Var(arm_arch_option)
Specify the name of the target architecture
+; Other arm_arch values are loaded from arm-tables.opt
+; but that is a generated file and this is an odd-one-out.
+EnumValue
+Enum(arm_arch) String(native) Value(-1) DriverOnly
+
marm
Target Report RejectNegative InverseMask(THUMB)
Generate code in 32 bit ARM state.
@@ -233,6 +238,11 @@ mtune=
Target RejectNegative Joined Enum(processor_type) Var(arm_tune_option) Init(arm_none)
Tune code for the given processor
+; Other processor_type values are loaded from arm-tables.opt
+; but that is a generated file and this is an odd-one-out.
+EnumValue
+Enum(processor_type) String(native) Value(-1) DriverOnly
+
mwords-little-endian
Target Report RejectNegative Mask(LITTLE_WORDS)
Assume big endian bytes, little endian words. This option is deprecated.
diff --git a/gcc/config/arm/bpabi.h b/gcc/config/arm/bpabi.h
index 20ff2f82929..64d7df4b251 100644
--- a/gcc/config/arm/bpabi.h
+++ b/gcc/config/arm/bpabi.h
@@ -58,6 +58,7 @@
#define BE8_LINK_SPEC \
" %{mbig-endian:%{march=armv7-a|mcpu=cortex-a5 \
|mcpu=cortex-a8|mcpu=cortex-a9|mcpu=cortex-a15 \
+ |mcpu=generic-armv7-a \
|march=armv7-m|mcpu=cortex-m3 \
|march=armv7e-m|mcpu=cortex-m4 \
|march=armv6-m|mcpu=cortex-m0 \
diff --git a/gcc/config/arm/crti.asm b/gcc/config/arm/crti.asm
deleted file mode 100644
index 9454273dd29..00000000000
--- a/gcc/config/arm/crti.asm
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright (C) 2001, 2008, 2009, 2010 Free Software Foundation, Inc.
-# Written By Nick Clifton
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-/* An executable stack is *not* required for these functions. */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
-
-# This file just make a stack frame for the contents of the .fini and
-# .init sections. Users may put any desired instructions in those
-# sections.
-
-#ifdef __ELF__
-#define TYPE(x) .type x,function
-#else
-#define TYPE(x)
-#endif
-#ifdef __ARM_EABI__
-/* Some attributes that are common to all routines in this file. */
- /* Tag_ABI_align_needed: This code does not require 8-byte
- alignment from the caller. */
- /* .eabi_attribute 24, 0 -- default setting. */
- /* Tag_ABI_align_preserved: This code preserves 8-byte
- alignment in any callee. */
- .eabi_attribute 25, 1
-#endif /* __ARM_EABI__ */
-
- # 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
-#ifdef __thumb__
- .thumb
-
- push {r3, r4, r5, r6, r7, lr}
-#else
- .arm
- # Create a stack frame and save any call-preserved registers
- mov ip, sp
- stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
- sub fp, ip, #4
-#endif
-.endm
-
- .section ".init"
- .align 2
- .global _init
-#ifdef __thumb__
- .thumb_func
-#endif
- TYPE(_init)
-_init:
- FUNC_START
-
-
- .section ".fini"
- .align 2
- .global _fini
-#ifdef __thumb__
- .thumb_func
-#endif
- TYPE(_fini)
-_fini:
- FUNC_START
-
-# end of crti.asm
diff --git a/gcc/config/arm/crtn.asm b/gcc/config/arm/crtn.asm
deleted file mode 100644
index c7f90814d79..00000000000
--- a/gcc/config/arm/crtn.asm
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright (C) 2001, 2004, 2008, 2009, 2010 Free Software Foundation, Inc.
-# Written By Nick Clifton
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-/* An executable stack is *not* required for these functions. */
-#if defined(__ELF__) && defined(__linux__)
-.section .note.GNU-stack,"",%progbits
-.previous
-#endif
-
-#ifdef __ARM_EABI__
-/* Some attributes that are common to all routines in this file. */
- /* Tag_ABI_align_needed: This code does not require 8-byte
- alignment from the caller. */
- /* .eabi_attribute 24, 0 -- default setting. */
- /* Tag_ABI_align_preserved: This code preserves 8-byte
- alignment in any callee. */
- .eabi_attribute 25, 1
-#endif /* __ARM_EABI__ */
-
-# This file just makes sure that the .fini and .init sections do in
-# fact return. Users may put any desired instructions in those sections.
-# This file is the last thing linked into any executable.
-
- # 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.
- #
- # Note - we do not try any fancy optimizations of the return
- # sequences here, it is just not worth it. Instead keep things
- # simple. Restore all the save resgisters, including the link
- # register and then perform the correct function return instruction.
- # We also save/restore r3 to ensure stack alignment.
-.macro FUNC_END
-#ifdef __thumb__
- .thumb
-
- pop {r3, r4, r5, r6, r7}
- pop {r3}
- mov lr, r3
-#else
- .arm
-
- sub sp, fp, #40
- ldmfd sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr}
-#endif
-
-#if defined __THUMB_INTERWORK__ || defined __thumb__
- bx lr
-#else
- mov pc, lr
-#endif
-.endm
-
-
- .section ".init"
- ;;
- FUNC_END
-
- .section ".fini"
- ;;
- FUNC_END
-
-# end of crtn.asm
diff --git a/gcc/config/arm/driver-arm.c b/gcc/config/arm/driver-arm.c
new file mode 100644
index 00000000000..3e14b14593c
--- /dev/null
+++ b/gcc/config/arm/driver-arm.c
@@ -0,0 +1,149 @@
+/* Subroutines for the gcc driver.
+ Copyright (C) 2011 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 3, 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 COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "configargs.h"
+
+struct vendor_cpu {
+ const char *part_no;
+ const char *arch_name;
+ const char *cpu_name;
+};
+
+static struct vendor_cpu arm_cpu_table[] = {
+ {"0x926", "armv5te", "arm926ej-s"},
+ {"0xa26", "armv5te", "arm1026ej-s"},
+ {"0xb02", "armv6k", "mpcore"},
+ {"0xb36", "armv6j", "arm1136j-s"},
+ {"0xb56", "armv6t2", "arm1156t2-s"},
+ {"0xb76", "armv6zk", "arm1176jz-s"},
+ {"0xc05", "armv7-a", "cortex-a5"},
+ {"0xc08", "armv7-a", "cortex-a8"},
+ {"0xc09", "armv7-a", "cortex-a9"},
+ {"0xc0f", "armv7-a", "cortex-a15"},
+ {"0xc14", "armv7-r", "cortex-r4"},
+ {"0xc15", "armv7-r", "cortex-r5"},
+ {"0xc20", "armv6-m", "cortex-m0"},
+ {"0xc21", "armv6-m", "cortex-m1"},
+ {"0xc23", "armv7-m", "cortex-m3"},
+ {"0xc24", "armv7e-m", "cortex-m4"},
+ {NULL, NULL, NULL}
+};
+
+static struct {
+ const char *vendor_no;
+ const struct vendor_cpu *vendor_parts;
+} vendors[] = {
+ {"0x41", arm_cpu_table},
+ {NULL, NULL}
+};
+
+/* This will be called by the spec parser in gcc.c when it sees
+ a %:local_cpu_detect(args) construct. Currently it will be called
+ with either "arch", "cpu" or "tune" as argument depending on if
+ -march=native, -mcpu=native or -mtune=native is to be substituted.
+
+ It returns a string containing new command line parameters to be
+ put at the place of the above two options, depending on what CPU
+ this is executed. E.g. "-march=armv7-a" on a Cortex-A8 for
+ -march=native. If the routine can't detect a known processor,
+ the -march or -mtune option is discarded.
+
+ ARGC and ARGV are set depending on the actual arguments given
+ in the spec. */
+const char *
+host_detect_local_cpu (int argc, const char **argv)
+{
+ const char *val = NULL;
+ char buf[128];
+ FILE *f = NULL;
+ bool arch;
+ const struct vendor_cpu *cpu_table = NULL;
+
+ if (argc < 1)
+ goto not_found;
+
+ arch = strcmp (argv[0], "arch") == 0;
+ if (!arch && strcmp (argv[0], "cpu") != 0 && strcmp (argv[0], "tune"))
+ goto not_found;
+
+ f = fopen ("/proc/cpuinfo", "r");
+ if (f == NULL)
+ goto not_found;
+
+ while (fgets (buf, sizeof (buf), f) != NULL)
+ {
+ /* Ensure that CPU implementer is ARM (0x41). */
+ if (strncmp (buf, "CPU implementer", sizeof ("CPU implementer") - 1) == 0)
+ {
+ int i;
+ for (i = 0; vendors[i].vendor_no != NULL; i++)
+ if (strstr (buf, vendors[i].vendor_no) != NULL)
+ {
+ cpu_table = vendors[i].vendor_parts;
+ break;
+ }
+ }
+
+ /* Detect arch/cpu. */
+ if (strncmp (buf, "CPU part", sizeof ("CPU part") - 1) == 0)
+ {
+ int i;
+
+ if (cpu_table == NULL)
+ goto not_found;
+
+ for (i = 0; cpu_table[i].part_no != NULL; i++)
+ if (strstr (buf, cpu_table[i].part_no) != NULL)
+ {
+ val = arch ? cpu_table[i].arch_name : cpu_table[i].cpu_name;
+ break;
+ }
+ break;
+ }
+ }
+
+ fclose (f);
+
+ if (val == NULL)
+ goto not_found;
+
+ return concat ("-m", argv[0], "=", val, NULL);
+
+not_found:
+ {
+ unsigned int i;
+ unsigned int opt;
+ const char *search[] = {NULL, "arch"};
+
+ if (f)
+ fclose (f);
+
+ search[0] = argv[0];
+ for (opt = 0; opt < ARRAY_SIZE (search); opt++)
+ for (i = 0; i < ARRAY_SIZE (configure_default_options); i++)
+ if (strcmp (configure_default_options[i].name, search[opt]) == 0)
+ return concat ("-m", search[opt], "=",
+ configure_default_options[i].value, NULL);
+ return NULL;
+ }
+}
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index da1f7af9b7a..08874ff0411 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -33,6 +33,15 @@
;; A list of integer modes that are up to one word long
(define_mode_iterator QHSI [QI HI SI])
+;; A list of integer modes that are less than a word
+(define_mode_iterator NARROW [QI HI])
+
+;; A list of all the integer modes upto 64bit
+(define_mode_iterator QHSD [QI HI SI DI])
+
+;; A list of the 32bit and 64bit integer modes
+(define_mode_iterator SIDI [SI DI])
+
;; Integer element sizes implemented by IWMMXT.
(define_mode_iterator VMMX [V2SI V4HI V8QI])
@@ -405,6 +414,9 @@
(V4QQ "8") (V2HQ "16") (QQ "8") (HQ "16")
(V2HA "16") (HA "16") (SQ "") (SA "")])
+;; Mode attribute for vshll.
+(define_mode_attr V_innermode [(V8QI "QI") (V4HI "HI") (V2SI "SI")])
+
;;----------------------------------------------------------------------------
;; Code attributes
;;----------------------------------------------------------------------------
diff --git a/gcc/config/arm/linux-atomic.c b/gcc/config/arm/linux-atomic.c
deleted file mode 100644
index 57065a6e8a0..00000000000
--- a/gcc/config/arm/linux-atomic.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* Linux-specific atomic operations for ARM EABI.
- Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
- Contributed by CodeSourcery.
-
-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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* Kernel helper for compare-and-exchange. */
-typedef int (__kernel_cmpxchg_t) (int oldval, int newval, int *ptr);
-#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)
-
-/* Kernel helper for memory barrier. */
-typedef void (__kernel_dmb_t) (void);
-#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0)
-
-/* Note: we implement byte, short and int versions of atomic operations using
- the above kernel helpers, but there is no support for "long long" (64-bit)
- operations as yet. */
-
-#define HIDDEN __attribute__ ((visibility ("hidden")))
-
-#ifdef __ARMEL__
-#define INVERT_MASK_1 0
-#define INVERT_MASK_2 0
-#else
-#define INVERT_MASK_1 24
-#define INVERT_MASK_2 16
-#endif
-
-#define MASK_1 0xffu
-#define MASK_2 0xffffu
-
-#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP) \
- int HIDDEN \
- __sync_fetch_and_##OP##_4 (int *ptr, int val) \
- { \
- int failure, tmp; \
- \
- do { \
- tmp = *ptr; \
- failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \
- } while (failure != 0); \
- \
- return tmp; \
- }
-
-FETCH_AND_OP_WORD (add, , +)
-FETCH_AND_OP_WORD (sub, , -)
-FETCH_AND_OP_WORD (or, , |)
-FETCH_AND_OP_WORD (and, , &)
-FETCH_AND_OP_WORD (xor, , ^)
-FETCH_AND_OP_WORD (nand, ~, &)
-
-#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
-#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
-
-/* Implement both __sync_<op>_and_fetch and __sync_fetch_and_<op> for
- subword-sized quantities. */
-
-#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN) \
- TYPE HIDDEN \
- NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val) \
- { \
- int *wordptr = (int *) ((unsigned int) ptr & ~3); \
- unsigned int mask, shift, oldval, newval; \
- int failure; \
- \
- shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
- mask = MASK_##WIDTH << shift; \
- \
- do { \
- oldval = *wordptr; \
- newval = ((PFX_OP (((oldval & mask) >> shift) \
- INF_OP (unsigned int) val)) << shift) & mask; \
- newval |= oldval & ~mask; \
- failure = __kernel_cmpxchg (oldval, newval, wordptr); \
- } while (failure != 0); \
- \
- return (RETURN & mask) >> shift; \
- }
-
-SUBWORD_SYNC_OP (add, , +, unsigned short, 2, oldval)
-SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, oldval)
-SUBWORD_SYNC_OP (or, , |, unsigned short, 2, oldval)
-SUBWORD_SYNC_OP (and, , &, unsigned short, 2, oldval)
-SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, oldval)
-SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, oldval)
-
-SUBWORD_SYNC_OP (add, , +, unsigned char, 1, oldval)
-SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, oldval)
-SUBWORD_SYNC_OP (or, , |, unsigned char, 1, oldval)
-SUBWORD_SYNC_OP (and, , &, unsigned char, 1, oldval)
-SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, oldval)
-SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, oldval)
-
-#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \
- int HIDDEN \
- __sync_##OP##_and_fetch_4 (int *ptr, int val) \
- { \
- int tmp, failure; \
- \
- do { \
- tmp = *ptr; \
- failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \
- } while (failure != 0); \
- \
- return PFX_OP (tmp INF_OP val); \
- }
-
-OP_AND_FETCH_WORD (add, , +)
-OP_AND_FETCH_WORD (sub, , -)
-OP_AND_FETCH_WORD (or, , |)
-OP_AND_FETCH_WORD (and, , &)
-OP_AND_FETCH_WORD (xor, , ^)
-OP_AND_FETCH_WORD (nand, ~, &)
-
-SUBWORD_SYNC_OP (add, , +, unsigned short, 2, newval)
-SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, newval)
-SUBWORD_SYNC_OP (or, , |, unsigned short, 2, newval)
-SUBWORD_SYNC_OP (and, , &, unsigned short, 2, newval)
-SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, newval)
-SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, newval)
-
-SUBWORD_SYNC_OP (add, , +, unsigned char, 1, newval)
-SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, newval)
-SUBWORD_SYNC_OP (or, , |, unsigned char, 1, newval)
-SUBWORD_SYNC_OP (and, , &, unsigned char, 1, newval)
-SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, newval)
-SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, newval)
-
-int HIDDEN
-__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval)
-{
- int actual_oldval, fail;
-
- while (1)
- {
- actual_oldval = *ptr;
-
- if (__builtin_expect (oldval != actual_oldval, 0))
- return actual_oldval;
-
- fail = __kernel_cmpxchg (actual_oldval, newval, ptr);
-
- if (__builtin_expect (!fail, 1))
- return oldval;
- }
-}
-
-#define SUBWORD_VAL_CAS(TYPE, WIDTH) \
- TYPE HIDDEN \
- __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \
- TYPE newval) \
- { \
- int *wordptr = (int *)((unsigned int) ptr & ~3), fail; \
- unsigned int mask, shift, actual_oldval, actual_newval; \
- \
- shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
- mask = MASK_##WIDTH << shift; \
- \
- while (1) \
- { \
- actual_oldval = *wordptr; \
- \
- if (__builtin_expect (((actual_oldval & mask) >> shift) != \
- (unsigned int) oldval, 0)) \
- return (actual_oldval & mask) >> shift; \
- \
- actual_newval = (actual_oldval & ~mask) \
- | (((unsigned int) newval << shift) & mask); \
- \
- fail = __kernel_cmpxchg (actual_oldval, actual_newval, \
- wordptr); \
- \
- if (__builtin_expect (!fail, 1)) \
- return oldval; \
- } \
- }
-
-SUBWORD_VAL_CAS (unsigned short, 2)
-SUBWORD_VAL_CAS (unsigned char, 1)
-
-typedef unsigned char bool;
-
-bool HIDDEN
-__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval)
-{
- int failure = __kernel_cmpxchg (oldval, newval, ptr);
- return (failure == 0);
-}
-
-#define SUBWORD_BOOL_CAS(TYPE, WIDTH) \
- bool HIDDEN \
- __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \
- TYPE newval) \
- { \
- TYPE actual_oldval \
- = __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval); \
- return (oldval == actual_oldval); \
- }
-
-SUBWORD_BOOL_CAS (unsigned short, 2)
-SUBWORD_BOOL_CAS (unsigned char, 1)
-
-void HIDDEN
-__sync_synchronize (void)
-{
- __kernel_dmb ();
-}
-
-int HIDDEN
-__sync_lock_test_and_set_4 (int *ptr, int val)
-{
- int failure, oldval;
-
- do {
- oldval = *ptr;
- failure = __kernel_cmpxchg (oldval, val, ptr);
- } while (failure != 0);
-
- return oldval;
-}
-
-#define SUBWORD_TEST_AND_SET(TYPE, WIDTH) \
- TYPE HIDDEN \
- __sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val) \
- { \
- int failure; \
- unsigned int oldval, newval, shift, mask; \
- int *wordptr = (int *) ((unsigned int) ptr & ~3); \
- \
- shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
- mask = MASK_##WIDTH << shift; \
- \
- do { \
- oldval = *wordptr; \
- newval = (oldval & ~mask) \
- | (((unsigned int) val << shift) & mask); \
- failure = __kernel_cmpxchg (oldval, newval, wordptr); \
- } while (failure != 0); \
- \
- return (oldval & mask) >> shift; \
- }
-
-SUBWORD_TEST_AND_SET (unsigned short, 2)
-SUBWORD_TEST_AND_SET (unsigned char, 1)
-
-#define SYNC_LOCK_RELEASE(TYPE, WIDTH) \
- void HIDDEN \
- __sync_lock_release_##WIDTH (TYPE *ptr) \
- { \
- /* All writes before this point must be seen before we release \
- the lock itself. */ \
- __kernel_dmb (); \
- *ptr = 0; \
- }
-
-SYNC_LOCK_RELEASE (int, 4)
-SYNC_LOCK_RELEASE (short, 2)
-SYNC_LOCK_RELEASE (char, 1)
diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h
index a3830955948..80bd8259375 100644
--- a/gcc/config/arm/linux-eabi.h
+++ b/gcc/config/arm/linux-eabi.h
@@ -97,7 +97,7 @@
#undef LIBGCC_SPEC
/* Clear the instruction cache from `beg' to `end'. This is
- implemented in lib1funcs.asm, so ensure an error if this definition
+ implemented in lib1funcs.S, so ensure an error if this definition
is used. */
#undef CLEAR_INSN_CACHE
#define CLEAR_INSN_CACHE(BEG, END) not_used
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index ea09da246ff..5cbe5bed2cc 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -5335,6 +5335,44 @@
}
)
+(define_insn "neon_vec_<US>shiftl_<mode>"
+ [(set (match_operand:<V_widen> 0 "register_operand" "=w")
+ (SE:<V_widen> (ashift:VW (match_operand:VW 1 "register_operand" "w")
+ (match_operand:<V_innermode> 2 "const_neon_scalar_shift_amount_operand" ""))))]
+ "TARGET_NEON"
+{
+ return "vshll.<US><V_sz_elem> %q0, %P1, %2";
+}
+ [(set_attr "neon_type" "neon_shift_1")]
+)
+
+(define_expand "vec_widen_<US>shiftl_lo_<mode>"
+ [(match_operand:<V_unpack> 0 "register_operand" "")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
+ (match_operand:SI 2 "immediate_operand" "i")]
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ {
+ emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
+ simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode, 0),
+ operands[2]));
+ DONE;
+ }
+)
+
+(define_expand "vec_widen_<US>shiftl_hi_<mode>"
+ [(match_operand:<V_unpack> 0 "register_operand" "")
+ (SE:<V_unpack> (match_operand:VU 1 "register_operand" ""))
+ (match_operand:SI 2 "immediate_operand" "i")]
+ "TARGET_NEON && !BYTES_BIG_ENDIAN"
+ {
+ emit_insn (gen_neon_vec_<US>shiftl_<V_half> (operands[0],
+ simplify_gen_subreg (<V_HALF>mode, operands[1], <MODE>mode,
+ GET_MODE_SIZE (<V_HALF>mode)),
+ operands[2]));
+ DONE;
+ }
+)
+
;; Vectorize for non-neon-quad case
(define_insn "neon_unpack<US>_<mode>"
[(set (match_operand:<V_widen> 0 "register_operand" "=w")
@@ -5411,6 +5449,34 @@
}
)
+(define_expand "vec_widen_<US>shiftl_hi_<mode>"
+ [(match_operand:<V_double_width> 0 "register_operand" "")
+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
+ (match_operand:SI 2 "immediate_operand" "i")]
+ "TARGET_NEON"
+ {
+ rtx tmpreg = gen_reg_rtx (<V_widen>mode);
+ emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
+ emit_insn (gen_neon_vget_high<V_widen_l> (operands[0], tmpreg));
+
+ DONE;
+ }
+)
+
+(define_expand "vec_widen_<US>shiftl_lo_<mode>"
+ [(match_operand:<V_double_width> 0 "register_operand" "")
+ (SE:<V_double_width> (match_operand:VDI 1 "register_operand" ""))
+ (match_operand:SI 2 "immediate_operand" "i")]
+ "TARGET_NEON"
+ {
+ rtx tmpreg = gen_reg_rtx (<V_widen>mode);
+ emit_insn (gen_neon_vec_<US>shiftl_<mode> (tmpreg, operands[1], operands[2]));
+ emit_insn (gen_neon_vget_low<V_widen_l> (operands[0], tmpreg));
+
+ DONE;
+ }
+)
+
; FIXME: These instruction patterns can't be used safely in big-endian mode
; because the ordering of vector elements in Q registers is different from what
; the semantics of the instructions require.
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 2c1a138b0df..92eb004ae14 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -136,6 +136,11 @@
(match_operand 0 "s_register_operand"))
(match_operand 0 "const_int_operand")))
+(define_predicate "const_neon_scalar_shift_amount_operand"
+ (and (match_code "const_int")
+ (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) <= GET_MODE_BITSIZE (mode)
+ && ((unsigned HOST_WIDE_INT) INTVAL (op)) > 0")))
+
(define_predicate "arm_add_operand"
(ior (match_operand 0 "arm_rhs_operand")
(match_operand 0 "arm_neg_immediate_operand")))
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md
index 689a235c16f..40ee93c35d1 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -1,6 +1,7 @@
;; Machine description for ARM processor synchronization primitives.
;; Copyright (C) 2010 Free Software Foundation, Inc.
;; Written by Marcus Shawcroft (marcus.shawcroft@arm.com)
+;; 64bit Atomics by Dave Gilbert (david.gilbert@linaro.org)
;;
;; This file is part of GCC.
;;
@@ -33,31 +34,24 @@
MEM_VOLATILE_P (operands[0]) = 1;
})
-(define_expand "sync_compare_and_swapsi"
- [(set (match_operand:SI 0 "s_register_operand")
- (unspec_volatile:SI [(match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (match_operand:SI 3 "s_register_operand")]
- VUNSPEC_SYNC_COMPARE_AND_SWAP))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omrn;
- generator.u.omrn = gen_arm_sync_compare_and_swapsi;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], operands[2],
- operands[3]);
- DONE;
- })
-(define_mode_iterator NARROW [QI HI])
+(define_mode_attr sync_predtab [(SI "TARGET_HAVE_LDREX &&
+ TARGET_HAVE_MEMORY_BARRIER")
+ (QI "TARGET_HAVE_LDREXBH &&
+ TARGET_HAVE_MEMORY_BARRIER")
+ (HI "TARGET_HAVE_LDREXBH &&
+ TARGET_HAVE_MEMORY_BARRIER")
+ (DI "TARGET_HAVE_LDREXD &&
+ ARM_DOUBLEWORD_ALIGN &&
+ TARGET_HAVE_MEMORY_BARRIER")])
(define_expand "sync_compare_and_swap<mode>"
- [(set (match_operand:NARROW 0 "s_register_operand")
- (unspec_volatile:NARROW [(match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (match_operand:NARROW 3 "s_register_operand")]
+ [(set (match_operand:QHSD 0 "s_register_operand")
+ (unspec_volatile:QHSD [(match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (match_operand:QHSD 3 "s_register_operand")]
VUNSPEC_SYNC_COMPARE_AND_SWAP))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omrn;
@@ -67,25 +61,11 @@
DONE;
})
-(define_expand "sync_lock_test_and_setsi"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_lock_test_and_setsi;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
(define_expand "sync_lock_test_and_set<mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
@@ -115,51 +95,25 @@
(plus "*")
(minus "*")])
-(define_expand "sync_<sync_optab>si"
- [(match_operand:SI 0 "memory_operand")
- (match_operand:SI 1 "s_register_operand")
- (syncop:SI (match_dup 0) (match_dup 1))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_new_<sync_optab>si;
- arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]);
- DONE;
- })
-
-(define_expand "sync_nandsi"
- [(match_operand:SI 0 "memory_operand")
- (match_operand:SI 1 "s_register_operand")
- (not:SI (and:SI (match_dup 0) (match_dup 1)))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_new_nandsi;
- arm_expand_sync (SImode, &generator, NULL, operands[0], NULL, operands[1]);
- DONE;
- })
-
(define_expand "sync_<sync_optab><mode>"
- [(match_operand:NARROW 0 "memory_operand")
- (match_operand:NARROW 1 "s_register_operand")
- (syncop:NARROW (match_dup 0) (match_dup 1))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "memory_operand")
+ (match_operand:QHSD 1 "s_register_operand")
+ (syncop:QHSD (match_dup 0) (match_dup 1))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
generator.u.omn = gen_arm_sync_new_<sync_optab><mode>;
arm_expand_sync (<MODE>mode, &generator, NULL, operands[0], NULL,
- operands[1]);
+ operands[1]);
DONE;
})
(define_expand "sync_nand<mode>"
- [(match_operand:NARROW 0 "memory_operand")
- (match_operand:NARROW 1 "s_register_operand")
- (not:NARROW (and:NARROW (match_dup 0) (match_dup 1)))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "memory_operand")
+ (match_operand:QHSD 1 "s_register_operand")
+ (not:QHSD (and:QHSD (match_dup 0) (match_dup 1)))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
@@ -169,57 +123,27 @@
DONE;
})
-(define_expand "sync_new_<sync_optab>si"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (syncop:SI (match_dup 1) (match_dup 2))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_new_<sync_optab>si;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
-(define_expand "sync_new_nandsi"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (not:SI (and:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_new_nandsi;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
(define_expand "sync_new_<sync_optab><mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (syncop:NARROW (match_dup 1) (match_dup 2))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (syncop:QHSD (match_dup 1) (match_dup 2))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
generator.u.omn = gen_arm_sync_new_<sync_optab><mode>;
arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
- NULL, operands[2]);
+ NULL, operands[2]);
DONE;
})
(define_expand "sync_new_nand<mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (not:QHSD (and:QHSD (match_dup 1) (match_dup 2)))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
@@ -229,57 +153,27 @@
DONE;
});
-(define_expand "sync_old_<sync_optab>si"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (syncop:SI (match_dup 1) (match_dup 2))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_old_<sync_optab>si;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
-(define_expand "sync_old_nandsi"
- [(match_operand:SI 0 "s_register_operand")
- (match_operand:SI 1 "memory_operand")
- (match_operand:SI 2 "s_register_operand")
- (not:SI (and:SI (match_dup 1) (match_dup 2)))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
- {
- struct arm_sync_generator generator;
- generator.op = arm_sync_generator_omn;
- generator.u.omn = gen_arm_sync_old_nandsi;
- arm_expand_sync (SImode, &generator, operands[0], operands[1], NULL,
- operands[2]);
- DONE;
- })
-
(define_expand "sync_old_<sync_optab><mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (syncop:NARROW (match_dup 1) (match_dup 2))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (syncop:QHSD (match_dup 1) (match_dup 2))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
generator.u.omn = gen_arm_sync_old_<sync_optab><mode>;
arm_expand_sync (<MODE>mode, &generator, operands[0], operands[1],
- NULL, operands[2]);
+ NULL, operands[2]);
DONE;
})
(define_expand "sync_old_nand<mode>"
- [(match_operand:NARROW 0 "s_register_operand")
- (match_operand:NARROW 1 "memory_operand")
- (match_operand:NARROW 2 "s_register_operand")
- (not:NARROW (and:NARROW (match_dup 1) (match_dup 2)))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ [(match_operand:QHSD 0 "s_register_operand")
+ (match_operand:QHSD 1 "memory_operand")
+ (match_operand:QHSD 2 "s_register_operand")
+ (not:QHSD (and:QHSD (match_dup 1) (match_dup 2)))]
+ "<sync_predtab>"
{
struct arm_sync_generator generator;
generator.op = arm_sync_generator_omn;
@@ -289,22 +183,22 @@
DONE;
})
-(define_insn "arm_sync_compare_and_swapsi"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI
- [(match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "s_register_operand" "r")]
- VUNSPEC_SYNC_COMPARE_AND_SWAP))
- (set (match_dup 1) (unspec_volatile:SI [(match_dup 2)]
+(define_insn "arm_sync_compare_and_swap<mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI
+ [(match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r")
+ (match_operand:SIDI 3 "s_register_operand" "r")]
+ VUNSPEC_SYNC_COMPARE_AND_SWAP))
+ (set (match_dup 1) (unspec_volatile:SIDI [(match_dup 2)]
VUNSPEC_SYNC_COMPARE_AND_SWAP))
(set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
VUNSPEC_SYNC_COMPARE_AND_SWAP))
]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_required_value" "2")
@@ -318,7 +212,7 @@
(zero_extend:SI
(unspec_volatile:NARROW
[(match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 2 "s_register_operand" "r")
(match_operand:SI 3 "s_register_operand" "r")]
VUNSPEC_SYNC_COMPARE_AND_SWAP)))
(set (match_dup 1) (unspec_volatile:NARROW [(match_dup 2)]
@@ -326,10 +220,10 @@
(set (reg:CC CC_REGNUM) (unspec_volatile:CC [(match_dup 1)]
VUNSPEC_SYNC_COMPARE_AND_SWAP))
]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_required_value" "2")
@@ -338,18 +232,18 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_lock_test_and_setsi"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q"))
+(define_insn "arm_sync_lock_test_and_set<mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q"))
(set (match_dup 1)
- (unspec_volatile:SI [(match_operand:SI 2 "s_register_operand" "r")]
- VUNSPEC_SYNC_LOCK))
+ (unspec_volatile:SIDI [(match_operand:SIDI 2 "s_register_operand" "r")]
+ VUNSPEC_SYNC_LOCK))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_release_barrier" "no")
(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
@@ -364,10 +258,10 @@
(zero_extend:SI (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q")))
(set (match_dup 1)
(unspec_volatile:NARROW [(match_operand:SI 2 "s_register_operand" "r")]
- VUNSPEC_SYNC_LOCK))
+ VUNSPEC_SYNC_LOCK))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
@@ -380,22 +274,22 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_new_<sync_optab>si"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(syncop:SI
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r"))
- ]
- VUNSPEC_SYNC_NEW_OP))
+(define_insn "arm_sync_new_<sync_optab><mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI [(syncop:SIDI
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r"))
+ ]
+ VUNSPEC_SYNC_NEW_OP))
(set (match_dup 1)
- (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_NEW_OP))
+ (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_NEW_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
@@ -405,54 +299,54 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_new_nandsi"
+(define_insn "arm_sync_new_<sync_optab><mode>"
[(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(not:SI (and:SI
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r")))
- ]
- VUNSPEC_SYNC_NEW_OP))
+ (unspec_volatile:SI [(syncop:SI
+ (zero_extend:SI
+ (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
+ (match_operand:SI 2 "s_register_operand" "r"))
+ ]
+ VUNSPEC_SYNC_NEW_OP))
(set (match_dup 1)
- (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_NEW_OP))
+ (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_NEW_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
(set_attr "sync_t1" "0")
(set_attr "sync_t2" "3")
- (set_attr "sync_op" "nand")
+ (set_attr "sync_op" "<sync_optab>")
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_new_<sync_optab><mode>"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(syncop:SI
- (zero_extend:SI
- (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
- (match_operand:SI 2 "s_register_operand" "r"))
- ]
- VUNSPEC_SYNC_NEW_OP))
+(define_insn "arm_sync_new_nand<mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI [(not:SIDI (and:SIDI
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r")))
+ ]
+ VUNSPEC_SYNC_NEW_OP))
(set (match_dup 1)
- (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_NEW_OP))
+ (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_NEW_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
(set_attr "sync_t1" "0")
(set_attr "sync_t2" "3")
- (set_attr "sync_op" "<sync_optab>")
+ (set_attr "sync_op" "nand")
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
@@ -461,19 +355,19 @@
(unspec_volatile:SI
[(not:SI
(and:SI
- (zero_extend:SI
- (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
- (match_operand:SI 2 "s_register_operand" "r")))
+ (zero_extend:SI
+ (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
+ (match_operand:SI 2 "s_register_operand" "r")))
] VUNSPEC_SYNC_NEW_OP))
(set (match_dup 1)
(unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_NEW_OP))
+ VUNSPEC_SYNC_NEW_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
- }
+ }
[(set_attr "sync_result" "0")
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
@@ -483,20 +377,20 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_old_<sync_optab>si"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(syncop:SI
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r"))
- ]
- VUNSPEC_SYNC_OLD_OP))
+(define_insn "arm_sync_old_<sync_optab><mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI [(syncop:SIDI
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r"))
+ ]
+ VUNSPEC_SYNC_OLD_OP))
(set (match_dup 1)
- (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_OLD_OP))
(clobber (reg:CC CC_REGNUM))
- (clobber (match_scratch:SI 3 "=&r"))
+ (clobber (match_scratch:SIDI 3 "=&r"))
(clobber (match_scratch:SI 4 "<sync_clobber>"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
@@ -509,20 +403,21 @@
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_old_nandsi"
+(define_insn "arm_sync_old_<sync_optab><mode>"
[(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(not:SI (and:SI
- (match_operand:SI 1 "arm_sync_memory_operand" "+Q")
- (match_operand:SI 2 "s_register_operand" "r")))
- ]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:SI [(syncop:SI
+ (zero_extend:SI
+ (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
+ (match_operand:SI 2 "s_register_operand" "r"))
+ ]
+ VUNSPEC_SYNC_OLD_OP))
(set (match_dup 1)
- (unspec_volatile:SI [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_OLD_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))
- (clobber (match_scratch:SI 4 "=&r"))]
- "TARGET_HAVE_LDREX && TARGET_HAVE_MEMORY_BARRIER"
+ (clobber (match_scratch:SI 4 "<sync_clobber>"))]
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
@@ -530,26 +425,25 @@
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
(set_attr "sync_t1" "3")
- (set_attr "sync_t2" "4")
- (set_attr "sync_op" "nand")
+ (set_attr "sync_t2" "<sync_t2_reqd>")
+ (set_attr "sync_op" "<sync_optab>")
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
-(define_insn "arm_sync_old_<sync_optab><mode>"
- [(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(syncop:SI
- (zero_extend:SI
- (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
- (match_operand:SI 2 "s_register_operand" "r"))
- ]
- VUNSPEC_SYNC_OLD_OP))
+(define_insn "arm_sync_old_nand<mode>"
+ [(set (match_operand:SIDI 0 "s_register_operand" "=&r")
+ (unspec_volatile:SIDI [(not:SIDI (and:SIDI
+ (match_operand:SIDI 1 "arm_sync_memory_operand" "+Q")
+ (match_operand:SIDI 2 "s_register_operand" "r")))
+ ]
+ VUNSPEC_SYNC_OLD_OP))
(set (match_dup 1)
- (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
+ (unspec_volatile:SIDI [(match_dup 1) (match_dup 2)]
VUNSPEC_SYNC_OLD_OP))
(clobber (reg:CC CC_REGNUM))
- (clobber (match_scratch:SI 3 "=&r"))
- (clobber (match_scratch:SI 4 "<sync_clobber>"))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ (clobber (match_scratch:SIDI 3 "=&r"))
+ (clobber (match_scratch:SI 4 "=&r"))]
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
@@ -557,26 +451,26 @@
(set_attr "sync_memory" "1")
(set_attr "sync_new_value" "2")
(set_attr "sync_t1" "3")
- (set_attr "sync_t2" "<sync_t2_reqd>")
- (set_attr "sync_op" "<sync_optab>")
+ (set_attr "sync_t2" "4")
+ (set_attr "sync_op" "nand")
(set_attr "conds" "clob")
(set_attr "predicable" "no")])
(define_insn "arm_sync_old_nand<mode>"
[(set (match_operand:SI 0 "s_register_operand" "=&r")
- (unspec_volatile:SI [(not:SI (and:SI
- (zero_extend:SI
- (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
- (match_operand:SI 2 "s_register_operand" "r")))
- ]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:SI [(not:SI (and:SI
+ (zero_extend:SI
+ (match_operand:NARROW 1 "arm_sync_memory_operand" "+Q"))
+ (match_operand:SI 2 "s_register_operand" "r")))
+ ]
+ VUNSPEC_SYNC_OLD_OP))
(set (match_dup 1)
- (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
- VUNSPEC_SYNC_OLD_OP))
+ (unspec_volatile:NARROW [(match_dup 1) (match_dup 2)]
+ VUNSPEC_SYNC_OLD_OP))
(clobber (reg:CC CC_REGNUM))
(clobber (match_scratch:SI 3 "=&r"))
(clobber (match_scratch:SI 4 "=&r"))]
- "TARGET_HAVE_LDREXBHD && TARGET_HAVE_MEMORY_BARRIER"
+ "<sync_predtab>"
{
return arm_output_sync_insn (insn, operands);
}
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index b970ec26a35..a9a174d473d 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -40,9 +40,6 @@ MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
$(srcdir)/config/arm/thumb2.md \
$(srcdir)/config/arm/arm-fixed.md
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _thumb1_case_sqi _thumb1_case_uqi _thumb1_case_shi \
- _thumb1_case_uhi _thumb1_case_si
s-config s-conditions s-flags s-codes s-constants s-emit s-recog s-preds \
s-opinit s-extract s-peep s-attr s-attrtab s-output: $(MD_INCLUDES)
diff --git a/gcc/config/arm/t-arm-elf b/gcc/config/arm/t-arm-elf
index ab85293ee91..25b7acb5da4 100644
--- a/gcc/config/arm/t-arm-elf
+++ b/gcc/config/arm/t-arm-elf
@@ -17,20 +17,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# For most CPUs we have an assembly soft-float implementations.
-# However this is not true for ARMv6M. Here we want to use the soft-fp C
-# implementation. The soft-fp code is only build for ARMv6M. This pulls
-# in the asm implementation for other CPUs.
-LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
- _call_via_rX _interwork_call_via_rX \
- _lshrdi3 _ashrdi3 _ashldi3 \
- _arm_negdf2 _arm_addsubdf3 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
- _arm_fixdfsi _arm_fixunsdfsi \
- _arm_truncdfsf2 _arm_negsf2 _arm_addsubsf3 _arm_muldivsf3 \
- _arm_cmpsf2 _arm_unordsf2 _arm_fixsfsi _arm_fixunssfsi \
- _arm_floatdidf _arm_floatdisf _arm_floatundidf _arm_floatundisf \
- _clzsi2 _clzdi2
-
MULTILIB_OPTIONS = marm/mthumb
MULTILIB_DIRNAMES = arm thumb
MULTILIB_EXCEPTIONS =
@@ -103,26 +89,3 @@ MULTILIB_EXCEPTIONS += *mthumb/*mfloat-abi=hard*
# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm600
# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm610
# MULTILIB_MATCHES += mcpu?arm7=mcpu?arm620
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-# If EXTRA_MULTILIB_PARTS is not defined above then define EXTRA_PARTS here
-# EXTRA_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Currently there is a bug somewhere in GCC's alias analysis
-# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
-# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -fno-inline
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/arm/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/arm/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/arm/crtn.asm
-
diff --git a/gcc/config/arm/t-bpabi b/gcc/config/arm/t-bpabi
deleted file mode 100644
index d8a1be45dcd..00000000000
--- a/gcc/config/arm/t-bpabi
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2004, 2005, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Add the bpabi.S functions.
-LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
-
-# Add the BPABI C functions.
-LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c \
- $(srcdir)/config/arm/unaligned-funcs.c
-
-LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c
-
-# Add the BPABI names.
-SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
-
-EXTRA_HEADERS += $(srcdir)/ginclude/unwind-arm-common.h
diff --git a/gcc/config/arm/t-linux b/gcc/config/arm/t-linux
deleted file mode 100644
index 9a2cb1aed10..00000000000
--- a/gcc/config/arm/t-linux
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2006,
-# 2008, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Just for these, we omit the frame pointer since it makes such a big
-# difference.
-TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC
-
-LIB1ASMSRC = arm/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \
- _arm_addsubdf3 _arm_addsubsf3
-
-# MULTILIB_OPTIONS = mfloat-abi=hard/mfloat-abi=soft
-# MULTILIB_DIRNAMES = hard-float soft-float
-
-# EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-
-# LIBGCC = stmp-multilib
-# INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/arm/t-linux-eabi b/gcc/config/arm/t-linux-eabi
index a328a000552..8004a7d0155 100644
--- a/gcc/config/arm/t-linux-eabi
+++ b/gcc/config/arm/t-linux-eabi
@@ -1,4 +1,4 @@
-# Copyright (C) 2005, 2009, 2010 Free Software Foundation, Inc.
+# Copyright (C) 2005, 2009, 2010, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,9 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# These functions are included in shared libraries.
-TARGET_LIBGCC2_CFLAGS = -fPIC
-
# We do not build a Thumb multilib for Linux because the definition of
# CLEAR_INSN_CACHE in linux-gas.h does not work in Thumb mode.
MULTILIB_OPTIONS =
@@ -27,12 +24,3 @@ MULTILIB_DIRNAMES =
#MULTILIB_OPTIONS += mcpu=fa606te/mcpu=fa626te/mcpu=fmp626/mcpu=fa726te
#MULTILIB_DIRNAMES += fa606te fa626te fmp626 fa726te
#MULTILIB_EXCEPTIONS += *mthumb/*mcpu=fa606te *mthumb/*mcpu=fa626te *mthumb/*mcpu=fmp626 *mthumb/*mcpu=fa726te*
-
-# Use a version of div0 which raises SIGFPE, and a special __clear_cache.
-LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx _clear_cache
-
-# Multilib the standard Linux files. Don't include crti.o or crtn.o,
-# which are provided by glibc.
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
-
-LIB2FUNCS_STATIC_EXTRA += $(srcdir)/config/arm/linux-atomic.c
diff --git a/gcc/config/arm/t-netbsd b/gcc/config/arm/t-netbsd
deleted file mode 100644
index 22bbbe7dd4b..00000000000
--- a/gcc/config/arm/t-netbsd
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005,
-# 2006 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Just for these, we omit the frame pointer since it makes such a big
-# difference. It is then pointless adding debugging.
-TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fpic
-LIBGCC2_DEBUG_CFLAGS = -g0
-LIB2FUNCS_EXTRA = $(srcdir)/config/floatunsidf.c $(srcdir)/config/floatunsisf.c
-
-# Build a shared libgcc library.
-SHLIB_EXT = .so
-SHLIB_NAME = @shlib_base_name@.so
-SHLIB_SONAME = @shlib_base_name@.so.1
-SHLIB_OBJS = @shlib_objs@
-
-SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,-soname,$(SHLIB_SONAME) \
- -o $(SHLIB_NAME).tmp @multilib_flags@ $(SHLIB_OBJS) -lc && \
- rm -f $(SHLIB_SONAME) && \
- if [ -f $(SHLIB_NAME) ]; then \
- mv -f $(SHLIB_NAME) $(SHLIB_NAME).backup; \
- else true; fi && \
- mv $(SHLIB_NAME).tmp $(SHLIB_NAME) && \
- $(LN_S) $(SHLIB_NAME) $(SHLIB_SONAME)
-# $(slibdir) double quoted to protect it from expansion while building
-# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = \
- $$(mkinstalldirs) $$(DESTDIR)$$(slibdir); \
- $(INSTALL_DATA) $(SHLIB_NAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_SONAME); \
- rm -f $$(DESTDIR)$$(slibdir)/$(SHLIB_NAME); \
- $(LN_S) $(SHLIB_SONAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_NAME)
diff --git a/gcc/config/arm/t-strongarm-elf b/gcc/config/arm/t-strongarm-elf
index 4a4f4533ec1..0639e695800 100644
--- a/gcc/config/arm/t-strongarm-elf
+++ b/gcc/config/arm/t-strongarm-elf
@@ -17,27 +17,7 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _clzsi2 _clzdi2
-
MULTILIB_OPTIONS = mlittle-endian/mbig-endian mfloat-abi=hard/mfloat-abi=soft
MULTILIB_DIRNAMES = le be fpu soft
MULTILIB_EXCEPTIONS =
MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# Currently there is a bug somewhere in GCC's alias analysis
-# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
-# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -fno-inline
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/arm/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/arm/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/arm/crtn.asm
diff --git a/gcc/config/arm/t-symbian b/gcc/config/arm/t-symbian
index e37d473eca0..473957e3290 100644
--- a/gcc/config/arm/t-symbian
+++ b/gcc/config/arm/t-symbian
@@ -16,23 +16,7 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMFUNCS += _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
-
-# These functions have __aeabi equivalents and will never be called by GCC.
-# By putting them in LIB1ASMFUNCS, we avoid the standard libgcc2.c code being
-# used -- and we make sure that definitions are not available in lib1funcs.asm,
-# either, so they end up undefined.
-LIB1ASMFUNCS += \
- _ashldi3 _ashrdi3 _divdi3 _floatdidf _udivmoddi4 _umoddi3 \
- _udivdi3 _lshrdi3 _moddi3 _muldi3 _negdi2 _cmpdi2 \
- _fixdfdi _fixsfdi _fixunsdfdi _fixunssfdi _floatdisf \
- _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
- _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
- _fixsfsi _fixunssfsi
-
EXTRA_HEADERS += $(srcdir)/ginclude/unwind-arm-common.h
-# Include half-float helpers.
-LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c
# Create a multilib for processors with VFP floating-point, and a
# multilib for those without -- using the soft-float ABI in both
@@ -40,10 +24,3 @@ LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/arm/fp16.c
# enabled, so there are no separate thumb-mode libraries.
MULTILIB_OPTIONS = mfloat-abi=softfp
MULTILIB_DIRNAMES = softfp
-
-# There is no C library to link against on Symbian OS -- at least when
-# building GCC.
-SHLIB_LC =
-
-# Symbian OS provides its own startup code.
-EXTRA_MULTILIB_PARTS=
diff --git a/gcc/config/arm/t-vxworks b/gcc/config/arm/t-vxworks
index 8ac0d9bcec5..0900ffe15ed 100644
--- a/gcc/config/arm/t-vxworks
+++ b/gcc/config/arm/t-vxworks
@@ -16,8 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
-
MULTILIB_OPTIONS = \
mrtp fPIC \
t4/t4be/t4t/t4tbe/t5/t5be/t5t/t5tbe/tstrongarm/txscale/txscalebe
diff --git a/gcc/config/arm/t-wince-pe b/gcc/config/arm/t-wince-pe
index 9ce1f313140..becda7f25a4 100644
--- a/gcc/config/arm/t-wince-pe
+++ b/gcc/config/arm/t-wince-pe
@@ -17,8 +17,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
-
pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) output.h flags.h $(TREE_H) expr.h $(TM_P_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
@@ -31,7 +29,3 @@ MULTILIB_DIRNAMES = fpu
# yet...
# MULTILIB_OPTIONS += thumb
# MULTILIB_DIRNAMES += thumb
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-TARGET_LIBGCC2_CFLAGS =
diff --git a/gcc/config/arm/x-arm b/gcc/config/arm/x-arm
new file mode 100644
index 00000000000..51cff1ed48b
--- /dev/null
+++ b/gcc/config/arm/x-arm
@@ -0,0 +1,3 @@
+driver-arm.o: $(srcdir)/config/arm/driver-arm.c \
+ $(CONFIG_H) $(SYSTEM_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index a799fb2a937..b32e697f9ca 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -32,6 +32,7 @@ extern int avr_initial_elimination_offset (int from, int to);
extern int avr_simple_epilogue (void);
extern int avr_hard_regno_rename_ok (unsigned int, unsigned int);
extern rtx avr_return_addr_rtx (int count, rtx tem);
+extern bool avr_accumulate_outgoing_args (void);
#ifdef TREE_CODE
extern void avr_asm_output_aligned_decl_common (FILE*, const_tree, const char*, unsigned HOST_WIDE_INT, unsigned int, bool);
@@ -77,12 +78,14 @@ extern bool avr_rotate_bytes (rtx operands[]);
extern void expand_prologue (void);
extern void expand_epilogue (bool);
extern int avr_epilogue_uses (int regno);
+extern int avr_starting_frame_offset (void);
extern void avr_output_bld (rtx operands[], int bit_nr);
extern void avr_output_addr_vec_elt (FILE *stream, int value);
extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]);
extern const char* avr_out_bitop (rtx, rtx*, int*);
extern const char* avr_out_plus (rtx*, int*, int*);
+extern const char* avr_out_plus_noclobber (rtx*, int*, int*);
extern const char* avr_out_addto_sp (rtx*, int*);
extern bool avr_popcount_each_byte (rtx, int, int);
@@ -109,7 +112,7 @@ extern void out_shift_with_cnt (const char *templ, rtx insn,
extern reg_class_t avr_mode_code_base_reg_class (enum machine_mode, RTX_CODE, RTX_CODE);
extern bool avr_regno_mode_code_ok_for_base_p (int, enum machine_mode, RTX_CODE, RTX_CODE);
extern rtx avr_incoming_return_addr_rtx (void);
-extern rtx avr_legitimize_reload_address (rtx, enum machine_mode, int, int, int, int, rtx (*)(rtx,int));
+extern rtx avr_legitimize_reload_address (rtx*, enum machine_mode, int, int, int, int, rtx (*)(rtx,int));
#endif /* RTX_CODE */
#ifdef REAL_VALUE_TYPE
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 4a93c0aa8dc..6435c4854f5 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -56,7 +56,9 @@
#define AVR_SECTION_PROGMEM (SECTION_MACH_DEP << 0)
-static void avr_option_override (void);
+
+/* Prototypes for local helper functions. */
+
static int avr_naked_function_p (tree);
static int interrupt_function_p (tree);
static int signal_function_p (tree);
@@ -68,53 +70,15 @@ static int sequent_regs_live (void);
static const char *ptrreg_to_str (int);
static const char *cond_string (enum rtx_code);
static int avr_num_arg_regs (enum machine_mode, const_tree);
-
-static rtx avr_legitimize_address (rtx, rtx, enum machine_mode);
-static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
-static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
-static tree avr_handle_fntype_attribute (tree *, tree, tree, int, bool *);
-static bool avr_assemble_integer (rtx, unsigned int, int);
-static void avr_file_start (void);
-static void avr_file_end (void);
-static bool avr_legitimate_address_p (enum machine_mode, rtx, bool);
-static void avr_asm_function_end_prologue (FILE *);
-static void avr_asm_function_begin_epilogue (FILE *);
-static bool avr_cannot_modify_jumps_p (void);
-static rtx avr_function_value (const_tree, const_tree, bool);
-static rtx avr_libcall_value (enum machine_mode, const_rtx);
-static bool avr_function_value_regno_p (const unsigned int);
-static void avr_insert_attributes (tree, tree *);
-static void avr_asm_init_sections (void);
-static unsigned int avr_section_type_flags (tree, const char *, int);
-
-static void avr_reorg (void);
-static void avr_asm_out_ctor (rtx, int);
-static void avr_asm_out_dtor (rtx, int);
-static int avr_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
-static int avr_memory_move_cost (enum machine_mode, reg_class_t, bool);
static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code,
int, bool);
-static bool avr_rtx_costs (rtx, int, int, int, int *, bool);
-static int avr_address_cost (rtx, bool);
-static bool avr_return_in_memory (const_tree, const_tree);
static struct machine_function * avr_init_machine_status (void);
-static void avr_init_builtins (void);
-static rtx avr_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-static rtx avr_builtin_setjmp_frame_value (void);
-static bool avr_hard_regno_scratch_ok (unsigned int);
-static unsigned int avr_case_values_threshold (void);
-static bool avr_frame_pointer_required_p (void);
-static bool avr_can_eliminate (const int, const int);
-static bool avr_class_likely_spilled_p (reg_class_t c);
-static rtx avr_function_arg (cumulative_args_t , enum machine_mode,
- const_tree, bool);
-static void avr_function_arg_advance (cumulative_args_t, enum machine_mode,
- const_tree, bool);
-static bool avr_function_ok_for_sibcall (tree, tree);
-static void avr_asm_named_section (const char *name, unsigned int flags, tree decl);
-static void avr_encode_section_info (tree, rtx, int);
-static section* avr_asm_function_rodata_section (tree);
-static section* avr_asm_select_section (tree, int, unsigned HOST_WIDE_INT);
+
+
+/* Prototypes for hook implementors if needed before their implementation. */
+
+static bool avr_rtx_costs (rtx, int, int, int, int *, bool);
+
/* Allocate registers from r25 to r8 for parameters for function calls. */
#define FIRST_CUM_REG 26
@@ -147,25 +111,6 @@ static GTY(()) section *progmem_section;
bool avr_need_clear_bss_p = false;
bool avr_need_copy_data_p = false;
-/* AVR attributes. */
-static const struct attribute_spec avr_attribute_table[] =
-{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
- affects_type_identity } */
- { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
- false },
- { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
- false },
- { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
- false },
- { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
- false },
- { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
- false },
- { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
- false },
- { NULL, 0, 0, false, false, false, NULL, false }
-};
/* Initialize the GCC target structure. */
#undef TARGET_ASM_ALIGNED_HI_OP
@@ -197,8 +142,6 @@ static const struct attribute_spec avr_attribute_table[] =
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
-#undef TARGET_ASM_FUNCTION_RODATA_SECTION
-#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
#undef TARGET_INSERT_ATTRIBUTES
#define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
#undef TARGET_SECTION_TYPE_FLAGS
@@ -274,7 +217,6 @@ static const struct attribute_spec avr_attribute_table[] =
#undef TARGET_ASM_FUNCTION_RODATA_SECTION
#define TARGET_ASM_FUNCTION_RODATA_SECTION avr_asm_function_rodata_section
-struct gcc_target targetm = TARGET_INITIALIZER;
/* Custom function to replace string prefix.
@@ -351,6 +293,17 @@ avr_option_override (void)
{
flag_delete_null_pointer_checks = 0;
+ /* caller-save.c looks for call-clobbered hard registers that are assigned
+ to pseudos that cross calls and tries so save-restore them around calls
+ in order to reduce the number of stack slots needed.
+
+ This might leads to situations where reload is no more able to cope
+ with the challenge of AVR's very few address registers and fails to
+ perform the requested spills. */
+
+ if (avr_strict_X)
+ flag_caller_saves = 0;
+
/* Unwind tables currently require a frame pointer for correctness,
see toplev.c:process_options(). */
@@ -361,10 +314,6 @@ avr_option_override (void)
{
flag_omit_frame_pointer = 0;
}
- else
- {
- flag_omit_frame_pointer = (optimize >= 1);
- }
avr_current_device = &avr_mcu_types[avr_mcu_index];
avr_current_arch = &avr_arch_types[avr_current_device->arch];
@@ -484,6 +433,47 @@ avr_OS_main_function_p (tree func)
return avr_lookup_function_attribute1 (func, "OS_main");
}
+
+/* Implement `ACCUMULATE_OUTGOING_ARGS'. */
+bool
+avr_accumulate_outgoing_args (void)
+{
+ if (!cfun)
+ return TARGET_ACCUMULATE_OUTGOING_ARGS;
+
+ /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
+ what offset is correct. In some cases it is relative to
+ virtual_outgoing_args_rtx and in others it is relative to
+ virtual_stack_vars_rtx. For example code see
+ gcc.c-torture/execute/built-in-setjmp.c
+ gcc.c-torture/execute/builtins/sprintf-chk.c */
+
+ return (TARGET_ACCUMULATE_OUTGOING_ARGS
+ && !(cfun->calls_setjmp
+ || cfun->has_nonlocal_label));
+}
+
+
+/* Report contribution of accumulated outgoing arguments to stack size. */
+
+static inline int
+avr_outgoing_args_size (void)
+{
+ return ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0;
+}
+
+
+/* Implement `STARTING_FRAME_OFFSET'. */
+/* This is the offset from the frame pointer register to the first stack slot
+ that contains a variable living in the frame. */
+
+int
+avr_starting_frame_offset (void)
+{
+ return 1 + avr_outgoing_args_size ();
+}
+
+
/* Return the number of hard registers to push/pop in the prologue/epilogue
of the current function, and optionally store these registers in SET. */
@@ -492,7 +482,7 @@ avr_regs_to_save (HARD_REG_SET *set)
{
int reg, count;
int int_or_sig_p = (interrupt_function_p (current_function_decl)
- || signal_function_p (current_function_decl));
+ || signal_function_p (current_function_decl));
if (set)
CLEAR_HARD_REG_SET (*set);
@@ -508,33 +498,36 @@ avr_regs_to_save (HARD_REG_SET *set)
for (reg = 0; reg < 32; reg++)
{
/* Do not push/pop __tmp_reg__, __zero_reg__, as well as
- any global register variables. */
+ any global register variables. */
if (fixed_regs[reg])
- continue;
+ continue;
if ((int_or_sig_p && !current_function_is_leaf && call_used_regs[reg])
- || (df_regs_ever_live_p (reg)
- && (int_or_sig_p || !call_used_regs[reg])
- && !(frame_pointer_needed
- && (reg == REG_Y || reg == (REG_Y+1)))))
- {
- if (set)
- SET_HARD_REG_BIT (*set, reg);
- count++;
- }
+ || (df_regs_ever_live_p (reg)
+ && (int_or_sig_p || !call_used_regs[reg])
+ /* Don't record frame pointer registers here. They are treated
+ indivitually in prologue. */
+ && !(frame_pointer_needed
+ && (reg == REG_Y || reg == (REG_Y+1)))))
+ {
+ if (set)
+ SET_HARD_REG_BIT (*set, reg);
+ count++;
+ }
}
return count;
}
/* Return true if register FROM can be eliminated via register TO. */
-bool
+static bool
avr_can_eliminate (const int from, const int to)
{
return ((from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
- || ((from == FRAME_POINTER_REGNUM
- || from == FRAME_POINTER_REGNUM + 1)
- && !frame_pointer_needed));
+ || (frame_pointer_needed && to == FRAME_POINTER_REGNUM)
+ || ((from == FRAME_POINTER_REGNUM
+ || from == FRAME_POINTER_REGNUM + 1)
+ && !frame_pointer_needed));
}
/* Compute offset between arg_pointer and frame_pointer. */
@@ -548,9 +541,10 @@ avr_initial_elimination_offset (int from, int to)
{
int offset = frame_pointer_needed ? 2 : 0;
int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
-
+
offset += avr_regs_to_save (NULL);
- return get_frame_size () + (avr_pc_size) + 1 + offset;
+ return (get_frame_size () + avr_outgoing_args_size()
+ + avr_pc_size + 1 + offset);
}
}
@@ -559,10 +553,11 @@ avr_initial_elimination_offset (int from, int to)
Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
avoids creating add/sub of offset in nonlocal goto and setjmp. */
-rtx avr_builtin_setjmp_frame_value (void)
+static rtx
+avr_builtin_setjmp_frame_value (void)
{
return gen_rtx_MINUS (Pmode, virtual_stack_vars_rtx,
- gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
+ gen_int_mode (STARTING_FRAME_OFFSET, Pmode));
}
/* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3 byte PC).
@@ -596,12 +591,13 @@ int
avr_simple_epilogue (void)
{
return (! frame_pointer_needed
- && get_frame_size () == 0
- && avr_regs_to_save (NULL) == 0
- && ! interrupt_function_p (current_function_decl)
- && ! signal_function_p (current_function_decl)
- && ! avr_naked_function_p (current_function_decl)
- && ! TREE_THIS_VOLATILE (current_function_decl));
+ && get_frame_size () == 0
+ && avr_outgoing_args_size() == 0
+ && avr_regs_to_save (NULL) == 0
+ && ! interrupt_function_p (current_function_decl)
+ && ! signal_function_p (current_function_decl)
+ && ! avr_naked_function_p (current_function_decl)
+ && ! TREE_THIS_VOLATILE (current_function_decl));
}
/* This function checks sequence of live registers. */
@@ -706,17 +702,238 @@ emit_push_byte (unsigned regno, bool frame_related_p)
cfun->machine->stack_usage++;
}
+static void
+avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
+{
+ rtx insn;
+ bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
+ int live_seq = sequent_regs_live ();
+
+ bool minimize = (TARGET_CALL_PROLOGUES
+ && live_seq
+ && !isr_p
+ && !cfun->machine->is_OS_task
+ && !cfun->machine->is_OS_main);
+
+ if (minimize
+ && (frame_pointer_needed
+ || avr_outgoing_args_size() > 8
+ || (AVR_2_BYTE_PC && live_seq > 6)
+ || live_seq > 7))
+ {
+ rtx pattern;
+ int first_reg, reg, offset;
+
+ emit_move_insn (gen_rtx_REG (HImode, REG_X),
+ gen_int_mode (size, HImode));
+
+ pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
+ gen_int_mode (live_seq+size, HImode));
+ insn = emit_insn (pattern);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ /* Describe the effect of the unspec_volatile call to prologue_saves.
+ Note that this formulation assumes that add_reg_note pushes the
+ notes to the front. Thus we build them in the reverse order of
+ how we want dwarf2out to process them. */
+
+ /* The function does always set frame_pointer_rtx, but whether that
+ is going to be permanent in the function is frame_pointer_needed. */
+
+ add_reg_note (insn, REG_CFA_ADJUST_CFA,
+ gen_rtx_SET (VOIDmode, (frame_pointer_needed
+ ? frame_pointer_rtx
+ : stack_pointer_rtx),
+ plus_constant (stack_pointer_rtx,
+ -(size + live_seq))));
+
+ /* Note that live_seq always contains r28+r29, but the other
+ registers to be saved are all below 18. */
+
+ first_reg = 18 - (live_seq - 2);
+
+ for (reg = 29, offset = -live_seq + 1;
+ reg >= first_reg;
+ reg = (reg == 28 ? 17 : reg - 1), ++offset)
+ {
+ rtx m, r;
+
+ m = gen_rtx_MEM (QImode, plus_constant (stack_pointer_rtx, offset));
+ r = gen_rtx_REG (QImode, reg);
+ add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, m, r));
+ }
+
+ cfun->machine->stack_usage += size + live_seq;
+ }
+ else /* !minimize */
+ {
+ int reg;
+
+ for (reg = 0; reg < 32; ++reg)
+ if (TEST_HARD_REG_BIT (set, reg))
+ emit_push_byte (reg, true);
+
+ if (frame_pointer_needed
+ && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
+ {
+ /* Push frame pointer. Always be consistent about the
+ ordering of pushes -- epilogue_restores expects the
+ register pair to be pushed low byte first. */
+
+ emit_push_byte (REG_Y, true);
+ emit_push_byte (REG_Y + 1, true);
+ }
+
+ if (frame_pointer_needed
+ && size == 0)
+ {
+ insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ if (size != 0)
+ {
+ /* Creating a frame can be done by direct manipulation of the
+ stack or via the frame pointer. These two methods are:
+ fp = sp
+ fp -= size
+ sp = fp
+ or
+ sp -= size
+ fp = sp (*)
+ the optimum method depends on function type, stack and
+ frame size. To avoid a complex logic, both methods are
+ tested and shortest is selected.
+
+ There is also the case where SIZE != 0 and no frame pointer is
+ needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
+ In that case, insn (*) is not needed in that case.
+ We use the X register as scratch. This is save because in X
+ is call-clobbered.
+ In an interrupt routine, the case of SIZE != 0 together with
+ !frame_pointer_needed can only occur if the function is not a
+ leaf function and thus X has already been saved. */
+
+ rtx fp_plus_insns, fp, my_fp;
+ rtx sp_minus_size = plus_constant (stack_pointer_rtx, -size);
+
+ gcc_assert (frame_pointer_needed
+ || !isr_p
+ || !current_function_is_leaf);
+
+ fp = my_fp = (frame_pointer_needed
+ ? frame_pointer_rtx
+ : gen_rtx_REG (Pmode, REG_X));
+
+ if (AVR_HAVE_8BIT_SP)
+ {
+ /* The high byte (r29) does not change:
+ Prefer SUBI (1 cycle) over ABIW (2 cycles, same size). */
+
+ my_fp = simplify_gen_subreg (QImode, fp, Pmode, 0);
+ }
+
+ /************ Method 1: Adjust frame pointer ************/
+
+ start_sequence ();
+
+ /* Normally, the dwarf2out frame-related-expr interpreter does
+ not expect to have the CFA change once the frame pointer is
+ set up. Thus, we avoid marking the move insn below and
+ instead indicate that the entire operation is complete after
+ the frame pointer subtraction is done. */
+
+ insn = emit_move_insn (fp, stack_pointer_rtx);
+ if (!frame_pointer_needed)
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ insn = emit_move_insn (my_fp, plus_constant (my_fp, -size));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (frame_pointer_needed)
+ {
+ add_reg_note (insn, REG_CFA_ADJUST_CFA,
+ gen_rtx_SET (VOIDmode, fp, sp_minus_size));
+ }
+
+ /* Copy to stack pointer. Note that since we've already
+ changed the CFA to the frame pointer this operation
+ need not be annotated if frame pointer is needed. */
+
+ if (AVR_HAVE_8BIT_SP)
+ {
+ insn = emit_move_insn (stack_pointer_rtx, fp);
+ }
+ else if (TARGET_NO_INTERRUPTS
+ || isr_p
+ || cfun->machine->is_OS_main)
+ {
+ rtx irqs_are_on = GEN_INT (!!cfun->machine->is_interrupt);
+
+ insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
+ fp, irqs_are_on));
+ }
+ else
+ {
+ insn = emit_move_insn (stack_pointer_rtx, fp);
+ }
+
+ if (!frame_pointer_needed)
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ fp_plus_insns = get_insns ();
+ end_sequence ();
+
+ /************ Method 2: Adjust Stack pointer ************/
+
+ /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
+ can only handle specific offsets. */
+
+ if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode))
+ {
+ rtx sp_plus_insns;
+
+ start_sequence ();
+
+ insn = emit_move_insn (stack_pointer_rtx, sp_minus_size);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (frame_pointer_needed)
+ {
+ insn = emit_move_insn (fp, stack_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ sp_plus_insns = get_insns ();
+ end_sequence ();
+
+ /************ Use shortest method ************/
+
+ emit_insn (get_sequence_length (sp_plus_insns)
+ < get_sequence_length (fp_plus_insns)
+ ? sp_plus_insns
+ : fp_plus_insns);
+ }
+ else
+ {
+ emit_insn (fp_plus_insns);
+ }
+
+ cfun->machine->stack_usage += size;
+ } /* !minimize && size != 0 */
+ } /* !minimize */
+}
+
/* Output function prologue. */
void
expand_prologue (void)
{
- int live_seq;
HARD_REG_SET set;
- int minimize;
- HOST_WIDE_INT size = get_frame_size();
- rtx insn;
+ HOST_WIDE_INT size;
+
+ size = get_frame_size() + avr_outgoing_args_size();
/* Init cfun->machine. */
cfun->machine->is_naked = avr_naked_function_p (current_function_decl);
@@ -733,20 +950,13 @@ expand_prologue (void)
}
avr_regs_to_save (&set);
- live_seq = sequent_regs_live ();
- minimize = (TARGET_CALL_PROLOGUES
- && !cfun->machine->is_interrupt
- && !cfun->machine->is_signal
- && !cfun->machine->is_OS_task
- && !cfun->machine->is_OS_main
- && live_seq);
if (cfun->machine->is_interrupt || cfun->machine->is_signal)
{
/* Enable interrupts. */
if (cfun->machine->is_interrupt)
- emit_insn (gen_enable_interrupt ());
-
+ emit_insn (gen_enable_interrupt ());
+
/* Push zero reg. */
emit_push_byte (ZERO_REGNO, true);
@@ -765,189 +975,19 @@ expand_prologue (void)
&& TEST_HARD_REG_BIT (set, REG_Z + 1))
{
emit_move_insn (tmp_reg_rtx,
- gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)));
- emit_push_byte (TMP_REGNO, false);
+ gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)));
+ emit_push_byte (TMP_REGNO, false);
}
-
+
/* Clear zero reg. */
emit_move_insn (zero_reg_rtx, const0_rtx);
/* Prevent any attempt to delete the setting of ZERO_REG! */
emit_use (zero_reg_rtx);
}
- if (minimize && (frame_pointer_needed
- || (AVR_2_BYTE_PC && live_seq > 6)
- || live_seq > 7))
- {
- int first_reg, reg, offset;
-
- emit_move_insn (gen_rtx_REG (HImode, REG_X),
- gen_int_mode (size, HImode));
-
- insn = emit_insn (gen_call_prologue_saves
- (gen_int_mode (live_seq, HImode),
- gen_int_mode (size + live_seq, HImode)));
- RTX_FRAME_RELATED_P (insn) = 1;
-
- /* Describe the effect of the unspec_volatile call to prologue_saves.
- Note that this formulation assumes that add_reg_note pushes the
- notes to the front. Thus we build them in the reverse order of
- how we want dwarf2out to process them. */
-
- /* The function does always set frame_pointer_rtx, but whether that
- is going to be permanent in the function is frame_pointer_needed. */
- add_reg_note (insn, REG_CFA_ADJUST_CFA,
- gen_rtx_SET (VOIDmode,
- (frame_pointer_needed
- ? frame_pointer_rtx : stack_pointer_rtx),
- plus_constant (stack_pointer_rtx,
- -(size + live_seq))));
-
- /* Note that live_seq always contains r28+r29, but the other
- registers to be saved are all below 18. */
- first_reg = 18 - (live_seq - 2);
-
- for (reg = 29, offset = -live_seq + 1;
- reg >= first_reg;
- reg = (reg == 28 ? 17 : reg - 1), ++offset)
- {
- rtx m, r;
-
- m = gen_rtx_MEM (QImode, plus_constant (stack_pointer_rtx, offset));
- r = gen_rtx_REG (QImode, reg);
- add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, m, r));
- }
-
- cfun->machine->stack_usage += size + live_seq;
- }
- else
- {
- int reg;
- for (reg = 0; reg < 32; ++reg)
- if (TEST_HARD_REG_BIT (set, reg))
- emit_push_byte (reg, true);
-
- if (frame_pointer_needed)
- {
- if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
- {
- /* Push frame pointer. Always be consistent about the
- ordering of pushes -- epilogue_restores expects the
- register pair to be pushed low byte first. */
- emit_push_byte (REG_Y, true);
- emit_push_byte (REG_Y + 1, true);
- }
-
- if (!size)
- {
- insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- else
- {
- /* Creating a frame can be done by direct manipulation of the
- stack or via the frame pointer. These two methods are:
- fp=sp
- fp-=size
- sp=fp
- OR
- sp-=size
- fp=sp
- the optimum method depends on function type, stack and frame size.
- To avoid a complex logic, both methods are tested and shortest
- is selected. */
- rtx myfp;
- rtx fp_plus_insns;
-
- if (AVR_HAVE_8BIT_SP)
- {
- /* The high byte (r29) doesn't change. Prefer 'subi'
- (1 cycle) over 'sbiw' (2 cycles, same size). */
- myfp = gen_rtx_REG (QImode, FRAME_POINTER_REGNUM);
- }
- else
- {
- /* Normal sized addition. */
- myfp = frame_pointer_rtx;
- }
-
- /* Method 1-Adjust frame pointer. */
- start_sequence ();
-
- /* Normally the dwarf2out frame-related-expr interpreter does
- not expect to have the CFA change once the frame pointer is
- set up. Thus we avoid marking the move insn below and
- instead indicate that the entire operation is complete after
- the frame pointer subtraction is done. */
-
- emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
-
- insn = emit_move_insn (myfp, plus_constant (myfp, -size));
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_CFA_ADJUST_CFA,
- gen_rtx_SET (VOIDmode, frame_pointer_rtx,
- plus_constant (stack_pointer_rtx,
- -size)));
-
- /* Copy to stack pointer. Note that since we've already
- changed the CFA to the frame pointer this operation
- need not be annotated at all. */
- if (AVR_HAVE_8BIT_SP)
- {
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- }
- else if (TARGET_NO_INTERRUPTS
- || cfun->machine->is_signal
- || cfun->machine->is_OS_main)
- {
- emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
- frame_pointer_rtx));
- }
- else if (cfun->machine->is_interrupt)
- {
- emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
- frame_pointer_rtx));
- }
- else
- {
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- }
-
- fp_plus_insns = get_insns ();
- end_sequence ();
-
- /* Method 2-Adjust Stack pointer. */
- if (size <= 6)
- {
- rtx sp_plus_insns;
-
- start_sequence ();
-
- insn = plus_constant (stack_pointer_rtx, -size);
- insn = emit_move_insn (stack_pointer_rtx, insn);
- RTX_FRAME_RELATED_P (insn) = 1;
-
- insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
-
- sp_plus_insns = get_insns ();
- end_sequence ();
-
- /* Use shortest method. */
- if (get_sequence_length (sp_plus_insns)
- < get_sequence_length (fp_plus_insns))
- emit_insn (sp_plus_insns);
- else
- emit_insn (fp_plus_insns);
- }
- else
- emit_insn (fp_plus_insns);
-
- cfun->machine->stack_usage += size;
- }
- }
- }
+ avr_prologue_setup_frame (size, set);
+
if (flag_stack_usage_info)
current_function_static_stack_size = cfun->machine->stack_usage;
}
@@ -974,6 +1014,11 @@ avr_asm_function_end_prologue (FILE *file)
else
fputs ("/* prologue: function */\n", file);
}
+
+ if (ACCUMULATE_OUTGOING_ARGS)
+ fprintf (file, "/* outgoing args size = %d */\n",
+ avr_outgoing_args_size());
+
fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
get_frame_size());
fprintf (file, "/* stack size = %d */\n",
@@ -1019,7 +1064,10 @@ expand_epilogue (bool sibcall_p)
int live_seq;
HARD_REG_SET set;
int minimize;
- HOST_WIDE_INT size = get_frame_size();
+ HOST_WIDE_INT size;
+ bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
+
+ size = get_frame_size() + avr_outgoing_args_size();
/* epilogue: naked */
if (cfun->machine->is_naked)
@@ -1032,145 +1080,158 @@ expand_epilogue (bool sibcall_p)
avr_regs_to_save (&set);
live_seq = sequent_regs_live ();
+
minimize = (TARGET_CALL_PROLOGUES
- && !cfun->machine->is_interrupt
- && !cfun->machine->is_signal
- && !cfun->machine->is_OS_task
- && !cfun->machine->is_OS_main
- && live_seq);
+ && live_seq
+ && !isr_p
+ && !cfun->machine->is_OS_task
+ && !cfun->machine->is_OS_main);
- if (minimize && (frame_pointer_needed || live_seq > 4))
+ if (minimize
+ && (live_seq > 4
+ || frame_pointer_needed
+ || size))
{
- if (frame_pointer_needed)
- {
- /* Get rid of frame. */
- emit_move_insn(frame_pointer_rtx,
- gen_rtx_PLUS (HImode, frame_pointer_rtx,
- gen_int_mode (size, HImode)));
- }
- else
- {
+ /* Get rid of frame. */
+
+ if (!frame_pointer_needed)
+ {
emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
- }
-
+ }
+
+ if (size)
+ {
+ emit_move_insn (frame_pointer_rtx,
+ plus_constant (frame_pointer_rtx, size));
+ }
+
emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
+ return;
}
- else
+
+ if (size)
{
- if (frame_pointer_needed)
- {
- if (size)
- {
- /* Try two methods to adjust stack and select shortest. */
- rtx myfp;
- rtx fp_plus_insns;
+ /* Try two methods to adjust stack and select shortest. */
+
+ rtx fp, my_fp;
+ rtx fp_plus_insns;
- if (AVR_HAVE_8BIT_SP)
- {
- /* The high byte (r29) doesn't change - prefer 'subi'
- (1 cycle) over 'sbiw' (2 cycles, same size). */
- myfp = gen_rtx_REG (QImode, FRAME_POINTER_REGNUM);
- }
- else
- {
- /* Normal sized addition. */
- myfp = frame_pointer_rtx;
- }
-
- /* Method 1-Adjust frame pointer. */
- start_sequence ();
+ gcc_assert (frame_pointer_needed
+ || !isr_p
+ || !current_function_is_leaf);
+
+ fp = my_fp = (frame_pointer_needed
+ ? frame_pointer_rtx
+ : gen_rtx_REG (Pmode, REG_X));
- emit_move_insn (myfp, plus_constant (myfp, size));
+ if (AVR_HAVE_8BIT_SP)
+ {
+ /* The high byte (r29) does not change:
+ Prefer SUBI (1 cycle) over SBIW (2 cycles). */
+
+ my_fp = simplify_gen_subreg (QImode, fp, Pmode, 0);
+ }
+
+ /********** Method 1: Adjust fp register **********/
+
+ start_sequence ();
- /* Copy to stack pointer. */
- if (AVR_HAVE_8BIT_SP)
- {
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- }
- else if (TARGET_NO_INTERRUPTS
- || cfun->machine->is_signal)
- {
- emit_insn (gen_movhi_sp_r_irq_off (stack_pointer_rtx,
- frame_pointer_rtx));
- }
- else if (cfun->machine->is_interrupt)
- {
- emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx,
- frame_pointer_rtx));
- }
- else
- {
- emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
- }
+ if (!frame_pointer_needed)
+ emit_move_insn (fp, stack_pointer_rtx);
- fp_plus_insns = get_insns ();
- end_sequence ();
+ emit_move_insn (my_fp, plus_constant (my_fp, size));
- /* Method 2-Adjust Stack pointer. */
- if (size <= 5)
- {
- rtx sp_plus_insns;
+ /* Copy to stack pointer. */
+
+ if (AVR_HAVE_8BIT_SP)
+ {
+ emit_move_insn (stack_pointer_rtx, fp);
+ }
+ else if (TARGET_NO_INTERRUPTS
+ || isr_p
+ || cfun->machine->is_OS_main)
+ {
+ rtx irqs_are_on = GEN_INT (!!cfun->machine->is_interrupt);
+
+ emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp, irqs_are_on));
+ }
+ else
+ {
+ emit_move_insn (stack_pointer_rtx, fp);
+ }
+
+ fp_plus_insns = get_insns ();
+ end_sequence ();
- start_sequence ();
+ /********** Method 2: Adjust Stack pointer **********/
+
+ if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
+ {
+ rtx sp_plus_insns;
- emit_move_insn (stack_pointer_rtx,
- plus_constant (stack_pointer_rtx, size));
+ start_sequence ();
- sp_plus_insns = get_insns ();
- end_sequence ();
+ emit_move_insn (stack_pointer_rtx,
+ plus_constant (stack_pointer_rtx, size));
- /* Use shortest method. */
- if (get_sequence_length (sp_plus_insns)
- < get_sequence_length (fp_plus_insns))
- emit_insn (sp_plus_insns);
- else
- emit_insn (fp_plus_insns);
- }
- else
- emit_insn (fp_plus_insns);
- }
- if (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
- {
- /* Restore previous frame_pointer. See expand_prologue for
- rationale for not using pophi. */
- emit_pop_byte (REG_Y + 1);
- emit_pop_byte (REG_Y);
- }
- }
+ sp_plus_insns = get_insns ();
+ end_sequence ();
- /* Restore used registers. */
- for (reg = 31; reg >= 0; --reg)
- if (TEST_HARD_REG_BIT (set, reg))
- emit_pop_byte (reg);
+ /************ Use shortest method ************/
+
+ emit_insn (get_sequence_length (sp_plus_insns)
+ < get_sequence_length (fp_plus_insns)
+ ? sp_plus_insns
+ : fp_plus_insns);
+ }
+ else
+ emit_insn (fp_plus_insns);
+ } /* size != 0 */
+
+ if (frame_pointer_needed
+ && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
+ {
+ /* Restore previous frame_pointer. See expand_prologue for
+ rationale for not using pophi. */
+
+ emit_pop_byte (REG_Y + 1);
+ emit_pop_byte (REG_Y);
+ }
- if (cfun->machine->is_interrupt || cfun->machine->is_signal)
- {
- /* Restore RAMPZ using tmp reg as scratch. */
- if (AVR_HAVE_RAMPZ
- && TEST_HARD_REG_BIT (set, REG_Z)
- && TEST_HARD_REG_BIT (set, REG_Z + 1))
- {
- emit_pop_byte (TMP_REGNO);
- emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)),
- tmp_reg_rtx);
- }
+ /* Restore used registers. */
+
+ for (reg = 31; reg >= 0; --reg)
+ if (TEST_HARD_REG_BIT (set, reg))
+ emit_pop_byte (reg);
- /* Restore SREG using tmp reg as scratch. */
- emit_pop_byte (TMP_REGNO);
+ if (isr_p)
+ {
+ /* Restore RAMPZ using tmp reg as scratch. */
- emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)),
- tmp_reg_rtx);
-
- /* Restore tmp REG. */
+ if (AVR_HAVE_RAMPZ
+ && TEST_HARD_REG_BIT (set, REG_Z)
+ && TEST_HARD_REG_BIT (set, REG_Z + 1))
+ {
emit_pop_byte (TMP_REGNO);
-
- /* Restore zero REG. */
- emit_pop_byte (ZERO_REGNO);
+ emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (RAMPZ_ADDR)),
+ tmp_reg_rtx);
}
- if (!sibcall_p)
- emit_jump_insn (gen_return ());
+ /* Restore SREG using tmp reg as scratch. */
+
+ emit_pop_byte (TMP_REGNO);
+ emit_move_insn (gen_rtx_MEM (QImode, GEN_INT (SREG_ADDR)),
+ tmp_reg_rtx);
+
+ /* Restore tmp REG. */
+ emit_pop_byte (TMP_REGNO);
+
+ /* Restore zero REG. */
+ emit_pop_byte (ZERO_REGNO);
}
+
+ if (!sibcall_p)
+ emit_jump_insn (gen_return ());
}
/* Output summary messages at beginning of function epilogue. */
@@ -1205,11 +1266,12 @@ avr_cannot_modify_jumps_p (void)
/* Helper function for `avr_legitimate_address_p'. */
static inline bool
-avr_reg_ok_for_addr_p (rtx reg, addr_space_t as ATTRIBUTE_UNUSED, int strict)
+avr_reg_ok_for_addr_p (rtx reg, addr_space_t as ATTRIBUTE_UNUSED,
+ RTX_CODE outer_code, bool strict)
{
return (REG_P (reg)
&& (avr_regno_mode_code_ok_for_base_p (REGNO (reg),
- QImode, MEM, UNKNOWN)
+ QImode, outer_code, UNKNOWN)
|| (!strict
&& REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
}
@@ -1221,58 +1283,69 @@ avr_reg_ok_for_addr_p (rtx reg, addr_space_t as ATTRIBUTE_UNUSED, int strict)
static bool
avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
- reg_class_t r = NO_REGS;
+ bool ok = CONSTANT_ADDRESS_P (x);
- if (REG_P (x)
- && avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC, strict))
- {
- r = POINTER_REGS;
- }
- else if (CONSTANT_ADDRESS_P (x))
+ switch (GET_CODE (x))
{
- r = ALL_REGS;
- }
- else if (GET_CODE (x) == PLUS
- && REG_P (XEXP (x, 0))
- && CONST_INT_P (XEXP (x, 1))
- && INTVAL (XEXP (x, 1)) >= 0)
- {
- rtx reg = XEXP (x, 0);
- bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
-
- if (fit)
- {
- if (! strict
- || REGNO (reg) == REG_X
- || REGNO (reg) == REG_Y
- || REGNO (reg) == REG_Z)
- {
- r = BASE_POINTER_REGS;
- }
-
- if (reg == frame_pointer_rtx
- || reg == arg_pointer_rtx)
- {
- r = BASE_POINTER_REGS;
- }
- }
- else if (frame_pointer_needed && reg == frame_pointer_rtx)
+ case REG:
+ ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
+ MEM, strict);
+
+ if (strict
+ && DImode == mode
+ && REG_X == REGNO (x))
{
- r = POINTER_Y_REGS;
+ ok = false;
}
- }
- else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
- && REG_P (XEXP (x, 0))
- && avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC, strict))
- {
- r = POINTER_REGS;
- }
+ break;
+ case POST_INC:
+ case PRE_DEC:
+ ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
+ GET_CODE (x), strict);
+ break;
+
+ case PLUS:
+ {
+ rtx reg = XEXP (x, 0);
+ rtx op1 = XEXP (x, 1);
+
+ if (REG_P (reg)
+ && CONST_INT_P (op1)
+ && INTVAL (op1) >= 0)
+ {
+ bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
+
+ if (fit)
+ {
+ ok = (! strict
+ || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
+ PLUS, strict));
+
+ if (reg == frame_pointer_rtx
+ || reg == arg_pointer_rtx)
+ {
+ ok = true;
+ }
+ }
+ else if (frame_pointer_needed
+ && reg == frame_pointer_rtx)
+ {
+ ok = true;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
if (avr_log.legitimate_address_p)
{
- avr_edump ("\n%?: ret=%d=%R, mode=%m strict=%d "
+ avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
"reload_completed=%d reload_in_progress=%d %s:",
- !!r, r, mode, strict, reload_completed, reload_in_progress,
+ ok, mode, strict, reload_completed, reload_in_progress,
reg_renumber ? "(reg_renumber)" : "");
if (GET_CODE (x) == PLUS
@@ -1288,7 +1361,7 @@ avr_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
avr_edump ("\n%r\n", x);
}
- return r == NO_REGS ? 0 : (int)r;
+ return ok;
}
/* Attempts to replace X with a valid
@@ -1336,11 +1409,13 @@ avr_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
than 63 bytes or for R++ or --R addressing. */
rtx
-avr_legitimize_reload_address (rtx x, enum machine_mode mode,
+avr_legitimize_reload_address (rtx *px, enum machine_mode mode,
int opnum, int type, int addr_type,
int ind_levels ATTRIBUTE_UNUSED,
rtx (*mk_memloc)(rtx,int))
{
+ rtx x = *px;
+
if (avr_log.legitimize_reload_address)
avr_edump ("\n%?:%m %r\n", mode, x);
@@ -1352,7 +1427,7 @@ avr_legitimize_reload_address (rtx x, enum machine_mode mode,
opnum, RELOAD_OTHER);
if (avr_log.legitimize_reload_address)
- avr_edump (" RCLASS = %R\n IN = %r\n OUT = %r\n",
+ avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
return x;
@@ -1378,7 +1453,7 @@ avr_legitimize_reload_address (rtx x, enum machine_mode mode,
1, addr_type);
if (avr_log.legitimize_reload_address)
- avr_edump (" RCLASS = %R\n IN = %r\n OUT = %r\n",
+ avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
POINTER_REGS, XEXP (mem, 0), NULL_RTX);
push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
@@ -1386,7 +1461,7 @@ avr_legitimize_reload_address (rtx x, enum machine_mode mode,
opnum, type);
if (avr_log.legitimize_reload_address)
- avr_edump (" RCLASS = %R\n IN = %r\n OUT = %r\n",
+ avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
BASE_POINTER_REGS, mem, NULL_RTX);
return x;
@@ -1395,12 +1470,12 @@ avr_legitimize_reload_address (rtx x, enum machine_mode mode,
else if (! (frame_pointer_needed
&& XEXP (x, 0) == frame_pointer_rtx))
{
- push_reload (x, NULL_RTX, &x, NULL,
+ push_reload (x, NULL_RTX, px, NULL,
POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
opnum, type);
if (avr_log.legitimize_reload_address)
- avr_edump (" RCLASS = %R\n IN = %r\n OUT = %r\n",
+ avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
POINTER_REGS, x, NULL_RTX);
return x;
@@ -1452,7 +1527,8 @@ ptrreg_to_str (int regno)
case REG_Y: return "Y";
case REG_Z: return "Z";
default:
- output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
+ output_operand_lossage ("address operand requires constraint for"
+ " X, Y, or Z register");
}
return NULL;
}
@@ -1517,14 +1593,15 @@ print_operand_address (FILE *file, rtx addr)
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
{
/* Assembler gs() will implant word address. Make offset
- a byte offset inside gs() for assembler. This is
- needed because the more logical (constant+gs(sym)) is not
- accepted by gas. For 128K and lower devices this is ok. For
- large devices it will create a Trampoline to offset from symbol
- which may not be what the user really wanted. */
+ a byte offset inside gs() for assembler. This is
+ needed because the more logical (constant+gs(sym)) is not
+ accepted by gas. For 128K and lower devices this is ok.
+ For large devices it will create a Trampoline to offset
+ from symbol which may not be what the user really wanted. */
fprintf (file, "gs(");
output_addr_const (file, XEXP (x,0));
- fprintf (file,"+" HOST_WIDE_INT_PRINT_DEC ")", 2 * INTVAL (XEXP (x,1)));
+ fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
+ 2 * INTVAL (XEXP (x, 1)));
if (AVR_3_BYTE_PC)
if (warning (0, "pointer offset from symbol maybe incorrect"))
{
@@ -1576,19 +1653,21 @@ print_operand (FILE *file, rtx x, int code)
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
else if (GET_CODE (x) == MEM)
{
- rtx addr = XEXP (x,0);
+ rtx addr = XEXP (x, 0);
+
if (code == 'm')
{
- if (!CONSTANT_P (addr))
- fatal_insn ("bad address, not a constant):", addr);
- /* Assembler template with m-code is data - not progmem section */
- if (text_segment_operand (addr, VOIDmode))
- if (warning ( 0, "accessing data memory with program memory address"))
- {
- output_addr_const (stderr, addr);
- fprintf(stderr,"\n");
- }
- output_addr_const (file, addr);
+ if (!CONSTANT_P (addr))
+ fatal_insn ("bad address, not a constant):", addr);
+ /* Assembler template with m-code is data - not progmem section */
+ if (text_segment_operand (addr, VOIDmode))
+ if (warning (0, "accessing data memory with"
+ " program memory address"))
+ {
+ output_addr_const (stderr, addr);
+ fprintf(stderr,"\n");
+ }
+ output_addr_const (file, addr);
}
else if (code == 'o')
{
@@ -1623,7 +1702,8 @@ print_operand (FILE *file, rtx x, int code)
{
/* Constant progmem address - like used in jmp or call */
if (0 == text_segment_operand (x, VOIDmode))
- if (warning ( 0, "accessing program memory with data memory address"))
+ if (warning (0, "accessing program memory"
+ " with data memory address"))
{
output_addr_const (stderr, x);
fprintf(stderr,"\n");
@@ -1663,14 +1743,19 @@ notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
break;
case CC_OUT_PLUS:
+ case CC_OUT_PLUS_NOCLOBBER:
{
rtx *op = recog_data.operand;
int len_dummy, icc;
/* Extract insn's operands. */
extract_constrain_insn_cached (insn);
+
+ if (CC_OUT_PLUS == cc)
+ avr_out_plus (op, &len_dummy, &icc);
+ else
+ avr_out_plus_noclobber (op, &len_dummy, &icc);
- avr_out_plus (op, &len_dummy, &icc);
cc = (enum attr_cc) icc;
break;
@@ -3090,12 +3175,14 @@ out_movhi_mr_r (rtx insn, rtx op[], int *l)
/* Return 1 if frame pointer for current function required. */
-bool
+static bool
avr_frame_pointer_required_p (void)
{
return (cfun->calls_alloca
- || crtl->args.info.nregs == 0
- || get_frame_size () > 0);
+ || cfun->calls_setjmp
+ || cfun->has_nonlocal_label
+ || crtl->args.info.nregs == 0
+ || get_frame_size () > 0);
}
/* Returns the condition of compare insn INSN, or UNKNOWN. */
@@ -4754,7 +4841,8 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc)
/* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
rtx xval = xop[2];
- /* Addition does not set cc0 in a usable way. */
+ /* Except in the case of ADIW with 16-bit register (see below)
+ addition does not set cc0 in a usable way. */
*pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
@@ -4802,6 +4890,9 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc)
started = true;
avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
op, plen, 1);
+
+ if (n_bytes == 2 && PLUS == code)
+ *pcc = CC_SET_ZN;
}
i++;
@@ -4817,6 +4908,14 @@ avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc)
op, plen, 1);
continue;
}
+ else if ((val8 == 1 || val8 == 0xff)
+ && !started
+ && i == n_bytes - 1)
+ {
+ avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
+ op, plen, 1);
+ break;
+ }
switch (code)
{
@@ -4905,6 +5004,22 @@ avr_out_plus (rtx *xop, int *plen, int *pcc)
}
+/* Same as above but XOP has just 3 entries.
+ Supply a dummy 4th operand. */
+
+const char*
+avr_out_plus_noclobber (rtx *xop, int *plen, int *pcc)
+{
+ rtx op[4];
+
+ op[0] = xop[0];
+ op[1] = xop[1];
+ op[2] = xop[2];
+ op[3] = NULL_RTX;
+
+ return avr_out_plus (op, plen, pcc);
+}
+
/* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
time constant XOP[2]:
@@ -5289,6 +5404,8 @@ adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
case ADJUST_LEN_OUT_PLUS: avr_out_plus (op, &len, NULL); break;
+ case ADJUST_LEN_OUT_PLUS_NOCLOBBER:
+ avr_out_plus_noclobber (op, &len, NULL); break;
case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
@@ -5312,6 +5429,8 @@ adjust_insn_length (rtx insn, int len)
case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
+ case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
+
default:
gcc_unreachable();
}
@@ -5577,6 +5696,28 @@ avr_handle_fntype_attribute (tree *node, tree name,
return NULL_TREE;
}
+
+/* AVR attributes. */
+static const struct attribute_spec
+avr_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+ affects_type_identity } */
+ { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
+ false },
+ { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
+ false },
+ { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
+ false },
+ { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
+ false },
+ { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
+ false },
+ { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
+ false },
+ { NULL, 0, 0, false, false, false, NULL, false }
+};
+
/* Look for attribute `progmem' in DECL
if found return 1, otherwise 0. */
@@ -5642,8 +5783,10 @@ avr_insert_attributes (tree node, tree *attributes)
/* Track need of __do_clear_bss. */
void
-avr_asm_output_aligned_decl_common (FILE * stream, const_tree decl ATTRIBUTE_UNUSED,
- const char *name, unsigned HOST_WIDE_INT size,
+avr_asm_output_aligned_decl_common (FILE * stream,
+ const_tree decl ATTRIBUTE_UNUSED,
+ const char *name,
+ unsigned HOST_WIDE_INT size,
unsigned int align, bool local_p)
{
avr_need_clear_bss_p = true;
@@ -5762,7 +5905,8 @@ avr_asm_function_rodata_section (tree decl)
if (STR_PREFIX_P (name, old_prefix))
{
- const char *rname = avr_replace_prefix (name, old_prefix, new_prefix);
+ const char *rname = avr_replace_prefix (name,
+ old_prefix, new_prefix);
flags &= ~SECTION_CODE;
flags |= AVR_HAVE_JMP_CALL ? 0 : SECTION_CODE;
@@ -5877,7 +6021,8 @@ avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
if (STR_PREFIX_P (name, old_prefix))
{
- const char *sname = avr_replace_prefix (name, old_prefix, new_prefix);
+ const char *sname = avr_replace_prefix (name,
+ old_prefix, new_prefix);
return get_section (sname, sect->common.flags, sect->named.decl);
}
@@ -6003,7 +6148,8 @@ avr_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
/* Implement `TARGET_MEMORY_MOVE_COST' */
static int
-avr_memory_move_cost (enum machine_mode mode, reg_class_t rclass ATTRIBUTE_UNUSED,
+avr_memory_move_cost (enum machine_mode mode,
+ reg_class_t rclass ATTRIBUTE_UNUSED,
bool in ATTRIBUTE_UNUSED)
{
return (mode == QImode ? 2
@@ -6331,11 +6477,16 @@ avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
case UDIV:
case UMOD:
if (!speed)
- *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
+ *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
else
- return false;
+ *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
*total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
+ /* For div/mod with const-int divisor we have at least the cost of
+ loading the divisor. */
+ if (CONST_INT_P (XEXP (x, 1)))
+ *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
+ /* Add some overall penaly for clobbering and moving around registers */
+ *total += COSTS_N_INSNS (2);
return true;
case ROTATE:
@@ -7304,10 +7455,13 @@ avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
reg_class_t
avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
- RTX_CODE outer_code ATTRIBUTE_UNUSED,
+ RTX_CODE outer_code,
RTX_CODE index_code ATTRIBUTE_UNUSED)
{
- return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
+ if (!avr_strict_X)
+ return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
+
+ return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
}
@@ -7316,19 +7470,20 @@ avr_mode_code_base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
bool
avr_regno_mode_code_ok_for_base_p (int regno,
enum machine_mode mode ATTRIBUTE_UNUSED,
- RTX_CODE outer_code ATTRIBUTE_UNUSED,
+ RTX_CODE outer_code,
RTX_CODE index_code ATTRIBUTE_UNUSED)
{
+ bool ok = false;
+
if (regno < FIRST_PSEUDO_REGISTER
&& (regno == REG_X
|| regno == REG_Y
|| regno == REG_Z
|| regno == ARG_POINTER_REGNUM))
{
- return true;
+ ok = true;
}
-
- if (reg_renumber)
+ else if (reg_renumber)
{
regno = reg_renumber[regno];
@@ -7337,11 +7492,18 @@ avr_regno_mode_code_ok_for_base_p (int regno,
|| regno == REG_Z
|| regno == ARG_POINTER_REGNUM)
{
- return true;
+ ok = true;
}
}
-
- return false;
+
+ if (avr_strict_X
+ && PLUS == outer_code
+ && regno == REG_X)
+ {
+ ok = false;
+ }
+
+ return ok;
}
@@ -7680,7 +7842,7 @@ avr_output_addr_vec_elt (FILE *stream, int value)
/* Returns true if SCRATCH are safe to be allocated as a scratch
registers (for a define_peephole2) in the current function. */
-bool
+static bool
avr_hard_regno_scratch_ok (unsigned int regno)
{
/* Interrupt functions can only use registers that have already been saved
@@ -7834,7 +7996,8 @@ avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
/* Worker function for CASE_VALUES_THRESHOLD. */
-unsigned int avr_case_values_threshold (void)
+static unsigned int
+avr_case_values_threshold (void)
{
return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17;
}
@@ -8140,7 +8303,8 @@ avr_expand_builtin (tree exp, rtx target,
op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
if (! CONST_INT_P (op0))
- error ("__builtin_avr_delay_cycles expects a compile time integer constant.");
+ error ("__builtin_avr_delay_cycles expects a"
+ " compile time integer constant.");
avr_expand_delay_cycles (op0);
return 0;
@@ -8158,5 +8322,6 @@ avr_expand_builtin (tree exp, rtx target,
gcc_unreachable ();
}
+struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-avr.h"
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index 015f12b5fe5..47ca8ff759a 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -324,7 +324,7 @@ enum reg_class {
#define STACK_GROWS_DOWNWARD
-#define STARTING_FRAME_OFFSET 1
+#define STARTING_FRAME_OFFSET avr_starting_frame_offset()
#define STACK_POINTER_OFFSET 1
@@ -375,7 +375,7 @@ typedef struct avr_args {
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_L,WIN) \
do { \
- rtx new_x = avr_legitimize_reload_address (X, MODE, OPNUM, TYPE, \
+ rtx new_x = avr_legitimize_reload_address (&(X), MODE, OPNUM, TYPE, \
ADDR_TYPE (TYPE), \
IND_L, make_memloc); \
if (new_x) \
@@ -385,7 +385,7 @@ typedef struct avr_args {
} \
} while (0)
-#define BRANCH_COST(speed_p, predictable_p) 0
+#define BRANCH_COST(speed_p, predictable_p) avr_branch_cost
#define SLOW_BYTE_ACCESS 0
@@ -454,8 +454,6 @@ typedef struct avr_args {
#define PRINT_OPERAND_ADDRESS(STREAM, X) print_operand_address(STREAM, X)
-#define ASSEMBLER_DIALECT AVR_HAVE_MOVW
-
#define ASM_OUTPUT_REG_PUSH(STREAM, REGNO) \
{ \
gcc_assert (REGNO < 32); \
@@ -637,3 +635,5 @@ struct GTY(()) machine_function
/* AVR does not round pushes, but the existance of this macro is
required in order for pushes to be generated. */
#define PUSH_ROUNDING(X) (X)
+
+#define ACCUMULATE_OUTGOING_ARGS avr_accumulate_outgoing_args()
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 1052378de65..f3edbbcd026 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -62,8 +62,7 @@
(define_c_enum "unspecv"
[UNSPECV_PROLOGUE_SAVES
UNSPECV_EPILOGUE_RESTORES
- UNSPECV_WRITE_SP_IRQ_ON
- UNSPECV_WRITE_SP_IRQ_OFF
+ UNSPECV_WRITE_SP
UNSPECV_GOTO_RECEIVER
UNSPECV_ENABLE_IRQS
UNSPECV_NOP
@@ -78,23 +77,12 @@
;; Condition code settings.
(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
- out_plus"
+ out_plus, out_plus_noclobber"
(const_string "none"))
(define_attr "type" "branch,branch1,arith,xcall"
(const_string "arith"))
-(define_attr "mcu_have_movw" "yes,no"
- (const (if_then_else (symbol_ref "AVR_HAVE_MOVW")
- (const_string "yes")
- (const_string "no"))))
-
-(define_attr "mcu_mega" "yes,no"
- (const (if_then_else (symbol_ref "AVR_HAVE_JMP_CALL")
- (const_string "yes")
- (const_string "no"))))
-
-
;; The size of instructions in bytes.
;; XXX may depend from "cc"
@@ -124,7 +112,7 @@
(const_int 3)
(const_int 4)))
(eq_attr "type" "xcall")
- (if_then_else (eq_attr "mcu_mega" "no")
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
(const_int 1)
(const_int 2))]
(const_int 2)))
@@ -133,11 +121,11 @@
;; Following insn attribute tells if and how the adjustment has to be
;; done:
;; no No adjustment needed; attribute "length" is fine.
-;; yes Analyse pattern in adjust_insn_length by hand.
;; Otherwise do special processing depending on the attribute.
(define_attr "adjust_len"
- "out_bitop, out_plus, addto_sp, tsthi, tstsi, compare,
+ "out_bitop, out_plus, out_plus_noclobber, addto_sp,
+ tsthi, tstsi, compare, call,
mov8, mov16, mov32, reload_in16, reload_in32,
ashlqi, ashrqi, lshrqi,
ashlhi, ashrhi, lshrhi,
@@ -145,6 +133,50 @@
no"
(const_string "no"))
+;; Flavours of instruction set architecture (ISA), used in enabled attribute
+
+;; mov: ISA has no MOVW
+;; movw: ISA has MOVW
+;; rjmp: ISA has no CALL/JMP
+;; jmp: ISA has CALL/JMP
+;; ijmp: ISA has no EICALL/EIJMP
+;; eijmp: ISA has EICALL/EIJMP
+
+(define_attr "isa"
+ "mov,movw, rjmp,jmp, ijmp,eijmp,
+ standard"
+ (const_string "standard"))
+
+(define_attr "enabled" ""
+ (cond [(eq_attr "isa" "standard")
+ (const_int 1)
+
+ (and (eq_attr "isa" "mov")
+ (match_test "!AVR_HAVE_MOVW"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "movw")
+ (match_test "AVR_HAVE_MOVW"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "rjmp")
+ (match_test "!AVR_HAVE_JMP_CALL"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "jmp")
+ (match_test "AVR_HAVE_JMP_CALL"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "ijmp")
+ (match_test "!AVR_HAVE_EIJMP_EICALL"))
+ (const_int 1)
+
+ (and (eq_attr "isa" "eijmp")
+ (match_test "AVR_HAVE_EIJMP_EICALL"))
+ (const_int 1)
+ ] (const_int 0)))
+
+
;; Define mode iterators
(define_mode_iterator QIHI [(QI "") (HI "")])
(define_mode_iterator QIHI2 [(QI "") (HI "")])
@@ -347,26 +379,24 @@
}
}")
-(define_insn "movhi_sp_r_irq_off"
- [(set (match_operand:HI 0 "stack_register_operand" "=q")
- (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r")]
- UNSPECV_WRITE_SP_IRQ_OFF))]
- ""
- "out __SP_H__, %B1
- out __SP_L__, %A1"
- [(set_attr "length" "2")
- (set_attr "cc" "none")])
-(define_insn "movhi_sp_r_irq_on"
- [(set (match_operand:HI 0 "stack_register_operand" "=q")
- (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r")]
- UNSPECV_WRITE_SP_IRQ_ON))]
+;; Move register $1 to the Stack Pointer register SP.
+;; This insn is emit during function prologue/epilogue generation.
+;; $2 = 0: We know that IRQs are off
+;; $2 = 1: We know that IRQs are on
+;; Remaining cases when the state of the I-Flag is unknown are
+;; handled by generic movhi insn.
+
+(define_insn "movhi_sp_r"
+ [(set (match_operand:HI 0 "stack_register_operand" "=q,q")
+ (unspec_volatile:HI [(match_operand:HI 1 "register_operand" "r,r")
+ (match_operand:HI 2 "const_int_operand" "L,P")]
+ UNSPECV_WRITE_SP))]
""
- "cli
- out __SP_H__, %B1
- sei
- out __SP_L__, %A1"
- [(set_attr "length" "4")
+ "@
+ out __SP_H__,%B1\;out __SP_L__,%A1
+ cli\;out __SP_H__,%B1\;sei\;out __SP_L__,%A1"
+ [(set_attr "length" "2,4")
(set_attr "cc" "none")])
(define_peephole2
@@ -727,64 +757,138 @@
(plus:HI (match_operand:HI 1 "register_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")))]
""
- "
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- short tmp = INTVAL (operands[2]);
- operands[2] = GEN_INT(tmp);
- }
-}")
+ {
+ if (CONST_INT_P (operands[2]))
+ {
+ operands[2] = gen_int_mode (INTVAL (operands[2]), HImode);
+
+ if (can_create_pseudo_p()
+ && !stack_register_operand (operands[0], HImode)
+ && !stack_register_operand (operands[1], HImode)
+ && !d_register_operand (operands[0], HImode)
+ && !d_register_operand (operands[1], HImode))
+ {
+ emit_insn (gen_addhi3_clobber (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ }
+ })
(define_insn "*addhi3_zero_extend"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (plus:HI (zero_extend:HI
- (match_operand:QI 1 "register_operand" "r"))
- (match_operand:HI 2 "register_operand" "0")))]
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (plus:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:HI 2 "register_operand" "0")))]
""
- "add %A0,%1
- adc %B0,__zero_reg__"
+ "add %A0,%1\;adc %B0,__zero_reg__"
[(set_attr "length" "2")
(set_attr "cc" "set_n")])
(define_insn "*addhi3_zero_extend1"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (plus:HI (match_operand:HI 1 "register_operand" "%0")
- (zero_extend:HI
- (match_operand:QI 2 "register_operand" "r"))))]
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (plus:HI (match_operand:HI 1 "register_operand" "0")
+ (zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
""
- "add %A0,%2
- adc %B0,__zero_reg__"
+ "add %A0,%2\;adc %B0,__zero_reg__"
[(set_attr "length" "2")
(set_attr "cc" "set_n")])
-(define_insn "*addhi3_sp_R"
- [(set (match_operand:HI 1 "stack_register_operand" "=q")
- (plus:HI (match_operand:HI 2 "stack_register_operand" "q")
- (match_operand:HI 0 "avr_sp_immediate_operand" "R")))]
+(define_insn "*addhi3.sign_extend1"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (plus:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "r"))
+ (match_operand:HI 2 "register_operand" "0")))]
""
{
- return avr_out_addto_sp (operands, NULL);
+ return reg_overlap_mentioned_p (operands[0], operands[1])
+ ? "mov __tmp_reg__,%1\;add %A0,%1\;adc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;dec %B0"
+ : "add %A0,%1\;adc %B0,__zero_reg__\;sbrc %1,7\;dec %B0";
}
[(set_attr "length" "5")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*addhi3_sp"
+ [(set (match_operand:HI 1 "stack_register_operand" "=q")
+ (plus:HI (match_operand:HI 2 "stack_register_operand" "q")
+ (match_operand:HI 0 "avr_sp_immediate_operand" "Csp")))]
+ ""
+ {
+ return avr_out_addto_sp (operands, NULL);
+ }
+ [(set_attr "length" "6")
(set_attr "adjust_len" "addto_sp")])
(define_insn "*addhi3"
- [(set (match_operand:HI 0 "register_operand" "=r,!w,!w,d,r,r")
- (plus:HI
- (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:HI 2 "nonmemory_operand" "r,I,J,i,P,N")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,d,d")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
+ (match_operand:HI 2 "nonmemory_operand" "r,s,n")))]
""
- "@
- add %A0,%A2\;adc %B0,%B2
- adiw %A0,%2
- sbiw %A0,%n2
- subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))
- sec\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__
- sec\;sbc %A0,__zero_reg__\;sbc %B0,__zero_reg__"
- [(set_attr "length" "2,1,1,2,3,3")
- (set_attr "cc" "set_n,set_czn,set_czn,set_czn,set_n,set_n")])
+ {
+ static const char * const asm_code[] =
+ {
+ "add %A0,%A2\;adc %B0,%B2",
+ "subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))",
+ ""
+ };
+
+ if (*asm_code[which_alternative])
+ return asm_code[which_alternative];
+
+ return avr_out_plus_noclobber (operands, NULL, NULL);
+ }
+ [(set_attr "length" "2,2,2")
+ (set_attr "adjust_len" "*,*,out_plus_noclobber")
+ (set_attr "cc" "set_n,set_czn,out_plus_noclobber")])
+
+;; Adding a constant to NO_LD_REGS might have lead to a reload of
+;; that constant to LD_REGS. We don't add a scratch to *addhi3
+;; itself because that insn is special to reload.
+
+(define_peephole2 ; addhi3_clobber
+ [(set (match_operand:HI 0 "d_register_operand" "")
+ (match_operand:HI 1 "const_int_operand" ""))
+ (set (match_operand:HI 2 "l_register_operand" "")
+ (plus:HI (match_dup 2)
+ (match_dup 0)))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(set (match_dup 2)
+ (plus:HI (match_dup 2)
+ (match_dup 1)))
+ (clobber (match_dup 3))])]
+ {
+ operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, 0);
+ })
+
+;; Same, but with reload to NO_LD_REGS
+;; Combine *reload_inhi with *addhi3
+
+(define_peephole2 ; addhi3_clobber
+ [(parallel [(set (match_operand:HI 0 "l_register_operand" "")
+ (match_operand:HI 1 "const_int_operand" ""))
+ (clobber (match_operand:QI 2 "d_register_operand" ""))])
+ (set (match_operand:HI 3 "l_register_operand" "")
+ (plus:HI (match_dup 3)
+ (match_dup 0)))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(set (match_dup 3)
+ (plus:HI (match_dup 3)
+ (match_dup 1)))
+ (clobber (match_dup 2))])])
+
+(define_insn "addhi3_clobber"
+ [(set (match_operand:HI 0 "register_operand" "=d,l")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "const_int_operand" "n,n")))
+ (clobber (match_scratch:QI 3 "=X,&d"))]
+ ""
+ {
+ gcc_assert (REGNO (operands[0]) == REGNO (operands[1]));
+
+ return avr_out_plus (operands, NULL, NULL);
+ }
+ [(set_attr "length" "4")
+ (set_attr "adjust_len" "out_plus")
+ (set_attr "cc" "out_plus")])
+
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=r,d ,d,r")
@@ -861,6 +965,19 @@
[(set_attr "length" "2")
(set_attr "cc" "set_czn")])
+(define_insn "*subhi3.sign_extend2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (minus:HI (match_operand:HI 1 "register_operand" "0")
+ (sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
+ ""
+ {
+ return reg_overlap_mentioned_p (operands[0], operands[2])
+ ? "mov __tmp_reg__,%2\;sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc __tmp_reg__,7\;inc %B0"
+ : "sub %A0,%2\;sbc %B0,__zero_reg__\;sbrc %2,7\;inc %B0";
+ }
+ [(set_attr "length" "5")
+ (set_attr "cc" "clobber")])
+
(define_insn "subsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "register_operand" "0")
@@ -959,6 +1076,41 @@
[(set_attr "length" "2")
(set_attr "cc" "clobber")])
+(define_insn "*addqi3.lt0"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (plus:QI (lt:QI (match_operand:QI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:QI 2 "register_operand" "0")))]
+ ""
+ "sbrc %1,7\;inc %0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*addhi3.lt0"
+ [(set (match_operand:HI 0 "register_operand" "=w,r")
+ (plus:HI (lt:HI (match_operand:QI 1 "register_operand" "r,r")
+ (const_int 0))
+ (match_operand:HI 2 "register_operand" "0,0")))
+ (clobber (match_scratch:QI 3 "=X,&1"))]
+ ""
+ "@
+ sbrc %1,7\;adiw %0,1
+ lsl %1\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__"
+ [(set_attr "length" "2,3")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*addsi3.lt0"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 31))
+ (match_operand:SI 2 "register_operand" "0")))]
+ ""
+ "mov __tmp_reg__,%D1\;lsl __tmp_reg__
+ adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__"
+ [(set_attr "length" "6")
+ (set_attr "cc" "clobber")])
+
+
;; "umulqihi3"
;; "mulqihi3"
(define_insn "<extend_u>mulqihi3"
@@ -2949,20 +3101,17 @@
(set_attr "cc" "set_czn,set_n,set_czn")])
(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=!d,r,&r")
- (neg:SI (match_operand:SI 1 "register_operand" "0,0,r")))]
+ [(set (match_operand:SI 0 "register_operand" "=!d,r,&r,&r")
+ (neg:SI (match_operand:SI 1 "register_operand" "0,0,r ,r")))]
""
"@
com %D0\;com %C0\;com %B0\;neg %A0\;sbci %B0,lo8(-1)\;sbci %C0,lo8(-1)\;sbci %D0,lo8(-1)
com %D0\;com %C0\;com %B0\;com %A0\;adc %A0,__zero_reg__\;adc %B0,__zero_reg__\;adc %C0,__zero_reg__\;adc %D0,__zero_reg__
- clr %A0\;clr %B0\;{clr %C0\;clr %D0|movw %C0,%A0}\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1"
- [(set_attr_alternative "length"
- [(const_int 7)
- (const_int 8)
- (if_then_else (eq_attr "mcu_have_movw" "yes")
- (const_int 7)
- (const_int 8))])
- (set_attr "cc" "set_czn,set_n,set_czn")])
+ clr %A0\;clr %B0\;clr %C0\;clr %D0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1
+ clr %A0\;clr %B0\;movw %C0,%A0\;sub %A0,%A1\;sbc %B0,%B1\;sbc %C0,%C1\;sbc %D0,%D1"
+ [(set_attr "length" "7,8,8,7")
+ (set_attr "isa" "*,*,mov,movw")
+ (set_attr "cc" "set_czn,set_n,set_czn,set_czn")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=d,r")
@@ -3036,18 +3185,16 @@
(set_attr "cc" "set_n,set_n")])
(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r ,r")
+ (sign_extend:SI (match_operand:HI 1 "combine_pseudo_register_operand" "0,*r,*r")))]
""
"@
clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
- {mov %A0,%A1\;mov %B0,%B1|movw %A0,%A1}\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0"
- [(set_attr_alternative "length"
- [(const_int 4)
- (if_then_else (eq_attr "mcu_have_movw" "yes")
- (const_int 5)
- (const_int 6))])
- (set_attr "cc" "set_n,set_n")])
+ mov %A0,%A1\;mov %B0,%B1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0
+ movw %A0,%A1\;clr %C0\;sbrc %B0,7\;com %C0\;mov %D0,%C0"
+ [(set_attr "length" "4,6,5")
+ (set_attr "isa" "*,mov,movw")
+ (set_attr "cc" "set_n")])
;; xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x xx<---x
;; zero extend
@@ -3356,7 +3503,7 @@
(if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
(le (minus (pc) (match_dup 3)) (const_int 2046)))
(const_int 2)
- (if_then_else (eq_attr "mcu_mega" "no")
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
(const_int 2)
(const_int 4))))
(set_attr "cc" "clobber")])
@@ -3386,7 +3533,7 @@
(if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
(le (minus (pc) (match_dup 3)) (const_int 2046)))
(const_int 2)
- (if_then_else (eq_attr "mcu_mega" "no")
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
(const_int 2)
(const_int 4))))
(set_attr "cc" "clobber")])
@@ -3569,20 +3716,20 @@
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
- "*{
- if (AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1)
- return AS1 (jmp,%x0);
- return AS1 (rjmp,%x0);
-}"
+ {
+ return AVR_HAVE_JMP_CALL && get_attr_length (insn) != 1
+ ? "jmp %x0"
+ : "rjmp %x0";
+ }
[(set (attr "length")
(if_then_else (match_operand 0 "symbol_ref_operand" "")
- (if_then_else (eq_attr "mcu_mega" "no")
- (const_int 1)
- (const_int 2))
- (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047))
- (le (minus (pc) (match_dup 0)) (const_int 2047)))
- (const_int 1)
- (const_int 2))))
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
+ (const_int 1)
+ (const_int 2))
+ (if_then_else (and (ge (minus (pc) (match_dup 0)) (const_int -2047))
+ (le (minus (pc) (match_dup 0)) (const_int 2047)))
+ (const_int 1)
+ (const_int 2))))
(set_attr "cc" "none")])
;; call
@@ -3640,15 +3787,8 @@
%!ijmp
%~jmp %x0"
[(set_attr "cc" "clobber")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))
- (const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))])])
+ (set_attr "length" "1,*,1,*")
+ (set_attr "adjust_len" "*,call,*,call")])
(define_insn "call_value_insn"
[(parallel[(set (match_operand 0 "register_operand" "=r,r,r,r")
@@ -3664,15 +3804,8 @@
%!ijmp
%~jmp %x1"
[(set_attr "cc" "clobber")
- (set_attr_alternative "length"
- [(const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))
- (const_int 1)
- (if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 2)
- (const_int 1))])])
+ (set_attr "length" "1,*,1,*")
+ (set_attr "adjust_len" "*,call,*,call")])
(define_insn "nop"
[(const_int 0)]
@@ -3684,69 +3817,51 @@
; indirect jump
(define_expand "indirect_jump"
- [(set (pc) (match_operand:HI 0 "nonmemory_operand" ""))]
+ [(set (pc)
+ (match_operand:HI 0 "nonmemory_operand" ""))]
""
- " if ((!AVR_HAVE_JMP_CALL) && !register_operand(operand0, HImode))
- {
- operands[0] = copy_to_mode_reg(HImode, operand0);
- }"
-)
+ {
+ if (!AVR_HAVE_JMP_CALL && !register_operand (operands[0], HImode))
+ {
+ operands[0] = copy_to_mode_reg (HImode, operands[0]);
+ }
+ })
; indirect jump
-(define_insn "*jcindirect_jump"
- [(set (pc) (match_operand:HI 0 "immediate_operand" "i"))]
+(define_insn "*indirect_jump"
+ [(set (pc)
+ (match_operand:HI 0 "nonmemory_operand" "i,i,!z,*r,z"))]
""
- "%~jmp %x0"
- [(set_attr "length" "2")
- (set_attr "cc" "none")])
-
-;;
-(define_insn "*njcindirect_jump"
- [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))]
- "!AVR_HAVE_EIJMP_EICALL"
"@
+ rjmp %x0
+ jmp %x0
ijmp
- push %A0\;push %B0\;ret"
- [(set_attr "length" "1,3")
- (set_attr "cc" "none,none")])
-
-(define_insn "*indirect_jump_avr6"
- [(set (pc) (match_operand:HI 0 "register_operand" "z"))]
- "AVR_HAVE_EIJMP_EICALL"
- "eijmp"
- [(set_attr "length" "1")
+ push %A0\;push %B0\;ret
+ eijmp"
+ [(set_attr "length" "1,2,1,3,1")
+ (set_attr "isa" "rjmp,jmp,ijmp,ijmp,eijmp")
(set_attr "cc" "none")])
;; table jump
;; For entries in jump table see avr_output_addr_vec_elt.
-;; Table made from "rjmp .L<n>" instructions for <= 8K devices.
-(define_insn "*tablejump_rjmp"
+;; Table made from
+;; "rjmp .L<n>" instructions for <= 8K devices
+;; ".word gs(.L<n>)" addresses for > 8K devices
+(define_insn "*tablejump"
[(set (pc)
- (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r")]
+ (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")]
UNSPEC_INDEX_JMP))
(use (label_ref (match_operand 1 "" "")))
(clobber (match_dup 0))]
- "!AVR_HAVE_JMP_CALL"
+ ""
"@
ijmp
- push %A0\;push %B0\;ret"
- [(set_attr "length" "1,3")
- (set_attr "cc" "none,none")])
-
-;; Move the common piece of code to libgcc.
-;; Table made from ".word gs(.L<n>)" addresses for > 8K devices.
-;; Read jump address from table and perform indirect jump.
-(define_insn "*tablejump_lib"
- [(set (pc)
- (unspec:HI [(match_operand:HI 0 "register_operand" "z")]
- UNSPEC_INDEX_JMP))
- (use (label_ref (match_operand 1 "" "")))
- (clobber (match_dup 0))]
- "AVR_HAVE_JMP_CALL"
- "jmp __tablejump2__"
- [(set_attr "length" "2")
- (set_attr "cc" "clobber")])
+ push %A0\;push %B0\;ret
+ jmp __tablejump2__"
+ [(set_attr "length" "1,3,2")
+ (set_attr "isa" "rjmp,rjmp,jmp")
+ (set_attr "cc" "none,none,clobber")])
(define_expand "casesi"
@@ -3829,11 +3944,11 @@
"* return avr_out_sbxx_branch (insn, operands);"
[(set (attr "length")
(if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
- (le (minus (pc) (match_dup 3)) (const_int 2046)))
- (const_int 2)
- (if_then_else (eq_attr "mcu_mega" "no")
- (const_int 2)
- (const_int 4))))
+ (le (minus (pc) (match_dup 3)) (const_int 2046)))
+ (const_int 2)
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
+ (const_int 2)
+ (const_int 4))))
(set_attr "cc" "clobber")])
;; Tests of bit 7 are pessimized to sign tests, so we need this too...
@@ -3853,11 +3968,11 @@
}
[(set (attr "length")
(if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
- (le (minus (pc) (match_dup 2)) (const_int 2046)))
- (const_int 2)
- (if_then_else (eq_attr "mcu_mega" "no")
- (const_int 2)
- (const_int 4))))
+ (le (minus (pc) (match_dup 2)) (const_int 2046)))
+ (const_int 2)
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
+ (const_int 2)
+ (const_int 4))))
(set_attr "cc" "clobber")])
;; Upper half of the I/O space - read port to __tmp_reg__ and use sbrc/sbrs.
@@ -3876,11 +3991,11 @@
"* return avr_out_sbxx_branch (insn, operands);"
[(set (attr "length")
(if_then_else (and (ge (minus (pc) (match_dup 3)) (const_int -2046))
- (le (minus (pc) (match_dup 3)) (const_int 2045)))
- (const_int 3)
- (if_then_else (eq_attr "mcu_mega" "no")
- (const_int 3)
- (const_int 5))))
+ (le (minus (pc) (match_dup 3)) (const_int 2045)))
+ (const_int 3)
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
+ (const_int 3)
+ (const_int 5))))
(set_attr "cc" "clobber")])
(define_insn "*sbix_branch_tmp_bit7"
@@ -3901,7 +4016,7 @@
(if_then_else (and (ge (minus (pc) (match_dup 2)) (const_int -2046))
(le (minus (pc) (match_dup 2)) (const_int 2045)))
(const_int 3)
- (if_then_else (eq_attr "mcu_mega" "no")
+ (if_then_else (match_test "!AVR_HAVE_JMP_CALL")
(const_int 3)
(const_int 5))))
(set_attr "cc" "clobber")])
@@ -4064,10 +4179,10 @@
;; Library prologue saves
(define_insn "call_prologue_saves"
[(unspec_volatile:HI [(const_int 0)] UNSPECV_PROLOGUE_SAVES)
- (match_operand:HI 0 "immediate_operand" "")
- (set (reg:HI REG_SP) (minus:HI
- (reg:HI REG_SP)
- (match_operand:HI 1 "immediate_operand" "")))
+ (match_operand:HI 0 "immediate_operand" "i,i")
+ (set (reg:HI REG_SP)
+ (minus:HI (reg:HI REG_SP)
+ (match_operand:HI 1 "immediate_operand" "i,i")))
(use (reg:HI REG_X))
(clobber (reg:HI REG_Z))]
""
@@ -4075,30 +4190,26 @@
ldi r31,hi8(gs(1f))
%~jmp __prologue_saves__+((18 - %0) * 2)
1:"
- [(set_attr_alternative "length"
- [(if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 6)
- (const_int 5))])
- (set_attr "cc" "clobber")
- ])
+ [(set_attr "length" "5,6")
+ (set_attr "cc" "clobber")
+ (set_attr "isa" "rjmp,jmp")])
; epilogue restores using library
(define_insn "epilogue_restores"
[(unspec_volatile:QI [(const_int 0)] UNSPECV_EPILOGUE_RESTORES)
- (set (reg:HI REG_Y ) (plus:HI
- (reg:HI REG_Y)
- (match_operand:HI 0 "immediate_operand" "")))
- (set (reg:HI REG_SP) (reg:HI REG_Y))
- (clobber (reg:QI REG_Z))]
+ (set (reg:HI REG_Y)
+ (plus:HI (reg:HI REG_Y)
+ (match_operand:HI 0 "immediate_operand" "i,i")))
+ (set (reg:HI REG_SP)
+ (plus:HI (reg:HI REG_Y)
+ (match_dup 0)))
+ (clobber (reg:QI REG_Z))]
""
"ldi r30, lo8(%0)
%~jmp __epilogue_restores__ + ((18 - %0) * 2)"
- [(set_attr_alternative "length"
- [(if_then_else (eq_attr "mcu_mega" "yes")
- (const_int 3)
- (const_int 2))])
- (set_attr "cc" "clobber")
- ])
+ [(set_attr "length" "2,3")
+ (set_attr "cc" "clobber")
+ (set_attr "isa" "rjmp,jmp")])
; return
(define_insn "return"
@@ -4140,11 +4251,10 @@
(define_expand "prologue"
[(const_int 0)]
""
- "
{
expand_prologue ();
DONE;
- }")
+ })
(define_expand "epilogue"
[(const_int 0)]
@@ -4232,15 +4342,41 @@
;; Parity
+;; Postpone expansion of 16-bit parity to libgcc call until after combine for
+;; better 8-bit parity recognition.
+
(define_expand "parityhi2"
+ [(parallel [(set (match_operand:HI 0 "register_operand" "")
+ (parity:HI (match_operand:HI 1 "register_operand" "")))
+ (clobber (reg:HI 24))])])
+
+(define_insn_and_split "*parityhi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (parity:HI (match_operand:HI 1 "register_operand" "r")))
+ (clobber (reg:HI 24))]
+ "!reload_completed"
+ { gcc_unreachable(); }
+ "&& 1"
[(set (reg:HI 24)
- (match_operand:HI 1 "register_operand" ""))
+ (match_dup 1))
(set (reg:HI 24)
(parity:HI (reg:HI 24)))
- (set (match_operand:HI 0 "register_operand" "")
- (reg:HI 24))]
- ""
- "")
+ (set (match_dup 0)
+ (reg:HI 24))])
+
+(define_insn_and_split "*parityqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (parity:HI (match_operand:QI 1 "register_operand" "r")))
+ (clobber (reg:HI 24))]
+ "!reload_completed"
+ { gcc_unreachable(); }
+ "&& 1"
+ [(set (reg:QI 24)
+ (match_dup 1))
+ (set (reg:HI 24)
+ (zero_extend:HI (parity:QI (reg:QI 24))))
+ (set (match_dup 0)
+ (reg:HI 24))])
(define_expand "paritysi2"
[(set (reg:SI 22)
diff --git a/gcc/config/avr/avr.opt b/gcc/config/avr/avr.opt
index 1128dd3bf02..bb9c90ec36f 100644
--- a/gcc/config/avr/avr.opt
+++ b/gcc/config/avr/avr.opt
@@ -40,6 +40,10 @@ mno-interrupts
Target Report RejectNegative Mask(NO_INTERRUPTS)
Change the stack pointer without disabling interrupts
+mbranch-cost=
+Target Report Joined RejectNegative UInteger Var(avr_branch_cost) Init(0)
+Set the branch costs for conditional branch instructions. Reasonable values are small, non-negative integers. The default branch cost is 0.
+
morder1
Target Report Undocumented Mask(ORDER_1)
@@ -61,3 +65,15 @@ Relax branches
mpmem-wrap-around
Target Report
Make the linker relaxation machine assume that a program counter wrap-around occurs.
+
+maccumulate-args
+Target Report Mask(ACCUMULATE_OUTGOING_ARGS)
+Accumulate outgoing function arguments and acquire/release the needed stack space for outpoing function arguments in function prologue/epilogue. Without this option, outgoing arguments are pushed before calling a function and popped afterwards. This option can lead to reduced code size for functions that call many functions that get their arguments on the stack like, for example printf.
+
+mstrict-X
+Target Report Var(avr_strict_X) Init(0)
+When accessing RAM, use X as imposed by the hardware, i.e. just use pre-decrement, post-increment and indirect addressing with the X register. Without this option, the compiler may assume that there is an addressing mode X+const similar to Y+const and Z+const and emit instructions to emulate such an addressing mode for X.
+
+mbranch-cost=
+Target Report RejectNegative Joined UInteger Var(avr_branch_cost) Init(0)
+Set the cost of a branch instruction. Default value is 0.
diff --git a/gcc/config/avr/constraints.md b/gcc/config/avr/constraints.md
index f02c1978673..d26bff3ca19 100644
--- a/gcc/config/avr/constraints.md
+++ b/gcc/config/avr/constraints.md
@@ -98,11 +98,6 @@
(and (match_code "const_double")
(match_test "op == CONST0_RTX (SFmode)")))
-(define_constraint "R"
- "Integer constant in the range -6 @dots{} 5."
- (and (match_code "const_int")
- (match_test "ival >= -6 && ival <= 5")))
-
(define_memory_constraint "Q"
"A memory address based on Y or Z pointer with displacement."
(and (match_code "mem")
@@ -162,3 +157,8 @@
"Constant 4-byte integer that allows XOR without clobber register."
(and (match_code "const_int")
(match_test "avr_popcount_each_byte (op, 4, (1<<0) | (1<<8))")))
+
+(define_constraint "Csp"
+ "Integer constant in the range -6 @dots{} 6."
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (ival, -6, 6)")))
diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S
deleted file mode 100644
index 8df36072370..00000000000
--- a/gcc/config/avr/libgcc.S
+++ /dev/null
@@ -1,1535 +0,0 @@
-/* -*- Mode: Asm -*- */
-/* Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009
- Free Software Foundation, Inc.
- Contributed by Denis Chertykov <chertykov@gmail.com>
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3, or (at your option) any
-later version.
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#define __zero_reg__ r1
-#define __tmp_reg__ r0
-#define __SREG__ 0x3f
-#define __SP_H__ 0x3e
-#define __SP_L__ 0x3d
-#define __RAMPZ__ 0x3B
-
-/* Most of the functions here are called directly from avr.md
- patterns, instead of using the standard libcall mechanisms.
- This can make better code because GCC knows exactly which
- of the call-used registers (not all of them) are clobbered. */
-
-/* FIXME: At present, there is no SORT directive in the linker
- script so that we must not assume that different modules
- in the same input section like .libgcc.text.mul will be
- located close together. Therefore, we cannot use
- RCALL/RJMP to call a function like __udivmodhi4 from
- __divmodhi4 and have to use lengthy XCALL/XJMP even
- though they are in the same input section and all same
- input sections together are small enough to reach every
- location with a RCALL/RJMP instruction. */
-
- .macro mov_l r_dest, r_src
-#if defined (__AVR_HAVE_MOVW__)
- movw \r_dest, \r_src
-#else
- mov \r_dest, \r_src
-#endif
- .endm
-
- .macro mov_h r_dest, r_src
-#if defined (__AVR_HAVE_MOVW__)
- ; empty
-#else
- mov \r_dest, \r_src
-#endif
- .endm
-
-#if defined (__AVR_HAVE_JMP_CALL__)
-#define XCALL call
-#define XJMP jmp
-#else
-#define XCALL rcall
-#define XJMP rjmp
-#endif
-
-.macro DEFUN name
-.global \name
-.func \name
-\name:
-.endm
-
-.macro ENDF name
-.size \name, .-\name
-.endfunc
-.endm
-
-
-.section .text.libgcc.mul, "ax", @progbits
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-/* Note: mulqi3, mulhi3 are open-coded on the enhanced core. */
-#if !defined (__AVR_HAVE_MUL__)
-/*******************************************************
- Multiplication 8 x 8 without MUL
-*******************************************************/
-#if defined (L_mulqi3)
-
-#define r_arg2 r22 /* multiplicand */
-#define r_arg1 r24 /* multiplier */
-#define r_res __tmp_reg__ /* result */
-
-DEFUN __mulqi3
- clr r_res ; clear result
-__mulqi3_loop:
- sbrc r_arg1,0
- add r_res,r_arg2
- add r_arg2,r_arg2 ; shift multiplicand
- breq __mulqi3_exit ; while multiplicand != 0
- lsr r_arg1 ;
- brne __mulqi3_loop ; exit if multiplier = 0
-__mulqi3_exit:
- mov r_arg1,r_res ; result to return register
- ret
-ENDF __mulqi3
-
-#undef r_arg2
-#undef r_arg1
-#undef r_res
-
-#endif /* defined (L_mulqi3) */
-
-#if defined (L_mulqihi3)
-DEFUN __mulqihi3
- clr r25
- sbrc r24, 7
- dec r25
- clr r23
- sbrc r22, 7
- dec r22
- XJMP __mulhi3
-ENDF __mulqihi3:
-#endif /* defined (L_mulqihi3) */
-
-#if defined (L_umulqihi3)
-DEFUN __umulqihi3
- clr r25
- clr r23
- XJMP __mulhi3
-ENDF __umulqihi3
-#endif /* defined (L_umulqihi3) */
-
-/*******************************************************
- Multiplication 16 x 16 without MUL
-*******************************************************/
-#if defined (L_mulhi3)
-#define r_arg1L r24 /* multiplier Low */
-#define r_arg1H r25 /* multiplier High */
-#define r_arg2L r22 /* multiplicand Low */
-#define r_arg2H r23 /* multiplicand High */
-#define r_resL __tmp_reg__ /* result Low */
-#define r_resH r21 /* result High */
-
-DEFUN __mulhi3
- clr r_resH ; clear result
- clr r_resL ; clear result
-__mulhi3_loop:
- sbrs r_arg1L,0
- rjmp __mulhi3_skip1
- add r_resL,r_arg2L ; result + multiplicand
- adc r_resH,r_arg2H
-__mulhi3_skip1:
- add r_arg2L,r_arg2L ; shift multiplicand
- adc r_arg2H,r_arg2H
-
- cp r_arg2L,__zero_reg__
- cpc r_arg2H,__zero_reg__
- breq __mulhi3_exit ; while multiplicand != 0
-
- lsr r_arg1H ; gets LSB of multiplier
- ror r_arg1L
- sbiw r_arg1L,0
- brne __mulhi3_loop ; exit if multiplier = 0
-__mulhi3_exit:
- mov r_arg1H,r_resH ; result to return register
- mov r_arg1L,r_resL
- ret
-ENDF __mulhi3
-
-#undef r_arg1L
-#undef r_arg1H
-#undef r_arg2L
-#undef r_arg2H
-#undef r_resL
-#undef r_resH
-
-#endif /* defined (L_mulhi3) */
-
-/*******************************************************
- Widening Multiplication 32 = 16 x 16 without MUL
-*******************************************************/
-
-#if defined (L_mulhisi3)
-DEFUN __mulhisi3
-;;; FIXME: This is dead code (noone calls it)
- mov_l r18, r24
- mov_h r19, r25
- clr r24
- sbrc r23, 7
- dec r24
- mov r25, r24
- clr r20
- sbrc r19, 7
- dec r20
- mov r21, r20
- XJMP __mulsi3
-ENDF __mulhisi3
-#endif /* defined (L_mulhisi3) */
-
-#if defined (L_umulhisi3)
-DEFUN __umulhisi3
-;;; FIXME: This is dead code (noone calls it)
- mov_l r18, r24
- mov_h r19, r25
- clr r24
- clr r25
- mov_l r20, r24
- mov_h r21, r25
- XJMP __mulsi3
-ENDF __umulhisi3
-#endif /* defined (L_umulhisi3) */
-
-#if defined (L_mulsi3)
-/*******************************************************
- Multiplication 32 x 32 without MUL
-*******************************************************/
-#define r_arg1L r22 /* multiplier Low */
-#define r_arg1H r23
-#define r_arg1HL r24
-#define r_arg1HH r25 /* multiplier High */
-
-#define r_arg2L r18 /* multiplicand Low */
-#define r_arg2H r19
-#define r_arg2HL r20
-#define r_arg2HH r21 /* multiplicand High */
-
-#define r_resL r26 /* result Low */
-#define r_resH r27
-#define r_resHL r30
-#define r_resHH r31 /* result High */
-
-DEFUN __mulsi3
- clr r_resHH ; clear result
- clr r_resHL ; clear result
- clr r_resH ; clear result
- clr r_resL ; clear result
-__mulsi3_loop:
- sbrs r_arg1L,0
- rjmp __mulsi3_skip1
- add r_resL,r_arg2L ; result + multiplicand
- adc r_resH,r_arg2H
- adc r_resHL,r_arg2HL
- adc r_resHH,r_arg2HH
-__mulsi3_skip1:
- add r_arg2L,r_arg2L ; shift multiplicand
- adc r_arg2H,r_arg2H
- adc r_arg2HL,r_arg2HL
- adc r_arg2HH,r_arg2HH
-
- lsr r_arg1HH ; gets LSB of multiplier
- ror r_arg1HL
- ror r_arg1H
- ror r_arg1L
- brne __mulsi3_loop
- sbiw r_arg1HL,0
- cpc r_arg1H,r_arg1L
- brne __mulsi3_loop ; exit if multiplier = 0
-__mulsi3_exit:
- mov_h r_arg1HH,r_resHH ; result to return register
- mov_l r_arg1HL,r_resHL
- mov_h r_arg1H,r_resH
- mov_l r_arg1L,r_resL
- ret
-ENDF __mulsi3
-
-#undef r_arg1L
-#undef r_arg1H
-#undef r_arg1HL
-#undef r_arg1HH
-
-#undef r_arg2L
-#undef r_arg2H
-#undef r_arg2HL
-#undef r_arg2HH
-
-#undef r_resL
-#undef r_resH
-#undef r_resHL
-#undef r_resHH
-
-#endif /* defined (L_mulsi3) */
-
-#endif /* !defined (__AVR_HAVE_MUL__) */
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-#if defined (__AVR_HAVE_MUL__)
-#define A0 26
-#define B0 18
-#define C0 22
-
-#define A1 A0+1
-
-#define B1 B0+1
-#define B2 B0+2
-#define B3 B0+3
-
-#define C1 C0+1
-#define C2 C0+2
-#define C3 C0+3
-
-/*******************************************************
- Widening Multiplication 32 = 16 x 16
-*******************************************************/
-
-#if defined (L_mulhisi3)
-;;; R25:R22 = (signed long) R27:R26 * (signed long) R19:R18
-;;; C3:C0 = (signed long) A1:A0 * (signed long) B1:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __mulhisi3
- XCALL __umulhisi3
- ;; Sign-extend B
- tst B1
- brpl 1f
- sub C2, A0
- sbc C3, A1
-1: ;; Sign-extend A
- XJMP __usmulhisi3_tail
-ENDF __mulhisi3
-#endif /* L_mulhisi3 */
-
-#if defined (L_usmulhisi3)
-;;; R25:R22 = (signed long) R27:R26 * (unsigned long) R19:R18
-;;; C3:C0 = (signed long) A1:A0 * (unsigned long) B1:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __usmulhisi3
- XCALL __umulhisi3
- ;; FALLTHRU
-ENDF __usmulhisi3
-
-DEFUN __usmulhisi3_tail
- ;; Sign-extend A
- sbrs A1, 7
- ret
- sub C2, B0
- sbc C3, B1
- ret
-ENDF __usmulhisi3_tail
-#endif /* L_usmulhisi3 */
-
-#if defined (L_umulhisi3)
-;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18
-;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __umulhisi3
- mul A0, B0
- movw C0, r0
- mul A1, B1
- movw C2, r0
- mul A0, B1
- rcall 1f
- mul A1, B0
-1: add C1, r0
- adc C2, r1
- clr __zero_reg__
- adc C3, __zero_reg__
- ret
-ENDF __umulhisi3
-#endif /* L_umulhisi3 */
-
-/*******************************************************
- Widening Multiplication 32 = 16 x 32
-*******************************************************/
-
-#if defined (L_mulshisi3)
-;;; R25:R22 = (signed long) R27:R26 * R21:R18
-;;; (C3:C0) = (signed long) A1:A0 * B3:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __mulshisi3
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- ;; Some cores have problem skipping 2-word instruction
- tst A1
- brmi __mulohisi3
-#else
- sbrs A1, 7
-#endif /* __AVR_HAVE_JMP_CALL__ */
- XJMP __muluhisi3
- ;; FALLTHRU
-ENDF __mulshisi3
-
-;;; R25:R22 = (one-extended long) R27:R26 * R21:R18
-;;; (C3:C0) = (one-extended long) A1:A0 * B3:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __mulohisi3
- XCALL __muluhisi3
- ;; One-extend R27:R26 (A1:A0)
- sub C2, B0
- sbc C3, B1
- ret
-ENDF __mulohisi3
-#endif /* L_mulshisi3 */
-
-#if defined (L_muluhisi3)
-;;; R25:R22 = (unsigned long) R27:R26 * R21:R18
-;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0
-;;; Clobbers: __tmp_reg__
-DEFUN __muluhisi3
- XCALL __umulhisi3
- mul A0, B3
- add C3, r0
- mul A1, B2
- add C3, r0
- mul A0, B2
- add C2, r0
- adc C3, r1
- clr __zero_reg__
- ret
-ENDF __muluhisi3
-#endif /* L_muluhisi3 */
-
-/*******************************************************
- Multiplication 32 x 32
-*******************************************************/
-
-#if defined (L_mulsi3)
-;;; R25:R22 = R25:R22 * R21:R18
-;;; (C3:C0) = C3:C0 * B3:B0
-;;; Clobbers: R26, R27, __tmp_reg__
-DEFUN __mulsi3
- movw A0, C0
- push C2
- push C3
- XCALL __muluhisi3
- pop A1
- pop A0
- ;; A1:A0 now contains the high word of A
- mul A0, B0
- add C2, r0
- adc C3, r1
- mul A0, B1
- add C3, r0
- mul A1, B0
- add C3, r0
- clr __zero_reg__
- ret
-ENDF __mulsi3
-#endif /* L_mulsi3 */
-
-#undef A0
-#undef A1
-
-#undef B0
-#undef B1
-#undef B2
-#undef B3
-
-#undef C0
-#undef C1
-#undef C2
-#undef C3
-
-#endif /* __AVR_HAVE_MUL__ */
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-.section .text.libgcc.div, "ax", @progbits
-
-/*******************************************************
- Division 8 / 8 => (result + remainder)
-*******************************************************/
-#define r_rem r25 /* remainder */
-#define r_arg1 r24 /* dividend, quotient */
-#define r_arg2 r22 /* divisor */
-#define r_cnt r23 /* loop count */
-
-#if defined (L_udivmodqi4)
-DEFUN __udivmodqi4
- sub r_rem,r_rem ; clear remainder and carry
- ldi r_cnt,9 ; init loop counter
- rjmp __udivmodqi4_ep ; jump to entry point
-__udivmodqi4_loop:
- rol r_rem ; shift dividend into remainder
- cp r_rem,r_arg2 ; compare remainder & divisor
- brcs __udivmodqi4_ep ; remainder <= divisor
- sub r_rem,r_arg2 ; restore remainder
-__udivmodqi4_ep:
- rol r_arg1 ; shift dividend (with CARRY)
- dec r_cnt ; decrement loop counter
- brne __udivmodqi4_loop
- com r_arg1 ; complement result
- ; because C flag was complemented in loop
- ret
-ENDF __udivmodqi4
-#endif /* defined (L_udivmodqi4) */
-
-#if defined (L_divmodqi4)
-DEFUN __divmodqi4
- bst r_arg1,7 ; store sign of dividend
- mov __tmp_reg__,r_arg1
- eor __tmp_reg__,r_arg2; r0.7 is sign of result
- sbrc r_arg1,7
- neg r_arg1 ; dividend negative : negate
- sbrc r_arg2,7
- neg r_arg2 ; divisor negative : negate
- XCALL __udivmodqi4 ; do the unsigned div/mod
- brtc __divmodqi4_1
- neg r_rem ; correct remainder sign
-__divmodqi4_1:
- sbrc __tmp_reg__,7
- neg r_arg1 ; correct result sign
-__divmodqi4_exit:
- ret
-ENDF __divmodqi4
-#endif /* defined (L_divmodqi4) */
-
-#undef r_rem
-#undef r_arg1
-#undef r_arg2
-#undef r_cnt
-
-
-/*******************************************************
- Division 16 / 16 => (result + remainder)
-*******************************************************/
-#define r_remL r26 /* remainder Low */
-#define r_remH r27 /* remainder High */
-
-/* return: remainder */
-#define r_arg1L r24 /* dividend Low */
-#define r_arg1H r25 /* dividend High */
-
-/* return: quotient */
-#define r_arg2L r22 /* divisor Low */
-#define r_arg2H r23 /* divisor High */
-
-#define r_cnt r21 /* loop count */
-
-#if defined (L_udivmodhi4)
-DEFUN __udivmodhi4
- sub r_remL,r_remL
- sub r_remH,r_remH ; clear remainder and carry
- ldi r_cnt,17 ; init loop counter
- rjmp __udivmodhi4_ep ; jump to entry point
-__udivmodhi4_loop:
- rol r_remL ; shift dividend into remainder
- rol r_remH
- cp r_remL,r_arg2L ; compare remainder & divisor
- cpc r_remH,r_arg2H
- brcs __udivmodhi4_ep ; remainder < divisor
- sub r_remL,r_arg2L ; restore remainder
- sbc r_remH,r_arg2H
-__udivmodhi4_ep:
- rol r_arg1L ; shift dividend (with CARRY)
- rol r_arg1H
- dec r_cnt ; decrement loop counter
- brne __udivmodhi4_loop
- com r_arg1L
- com r_arg1H
-; div/mod results to return registers, as for the div() function
- mov_l r_arg2L, r_arg1L ; quotient
- mov_h r_arg2H, r_arg1H
- mov_l r_arg1L, r_remL ; remainder
- mov_h r_arg1H, r_remH
- ret
-ENDF __udivmodhi4
-#endif /* defined (L_udivmodhi4) */
-
-#if defined (L_divmodhi4)
-DEFUN __divmodhi4
- .global _div
-_div:
- bst r_arg1H,7 ; store sign of dividend
- mov __tmp_reg__,r_arg1H
- eor __tmp_reg__,r_arg2H ; r0.7 is sign of result
- rcall __divmodhi4_neg1 ; dividend negative : negate
- sbrc r_arg2H,7
- rcall __divmodhi4_neg2 ; divisor negative : negate
- XCALL __udivmodhi4 ; do the unsigned div/mod
- rcall __divmodhi4_neg1 ; correct remainder sign
- tst __tmp_reg__
- brpl __divmodhi4_exit
-__divmodhi4_neg2:
- com r_arg2H
- neg r_arg2L ; correct divisor/result sign
- sbci r_arg2H,0xff
-__divmodhi4_exit:
- ret
-__divmodhi4_neg1:
- brtc __divmodhi4_exit
- com r_arg1H
- neg r_arg1L ; correct dividend/remainder sign
- sbci r_arg1H,0xff
- ret
-ENDF __divmodhi4
-#endif /* defined (L_divmodhi4) */
-
-#undef r_remH
-#undef r_remL
-
-#undef r_arg1H
-#undef r_arg1L
-
-#undef r_arg2H
-#undef r_arg2L
-
-#undef r_cnt
-
-/*******************************************************
- Division 32 / 32 => (result + remainder)
-*******************************************************/
-#define r_remHH r31 /* remainder High */
-#define r_remHL r30
-#define r_remH r27
-#define r_remL r26 /* remainder Low */
-
-/* return: remainder */
-#define r_arg1HH r25 /* dividend High */
-#define r_arg1HL r24
-#define r_arg1H r23
-#define r_arg1L r22 /* dividend Low */
-
-/* return: quotient */
-#define r_arg2HH r21 /* divisor High */
-#define r_arg2HL r20
-#define r_arg2H r19
-#define r_arg2L r18 /* divisor Low */
-
-#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
-
-#if defined (L_udivmodsi4)
-DEFUN __udivmodsi4
- ldi r_remL, 33 ; init loop counter
- mov r_cnt, r_remL
- sub r_remL,r_remL
- sub r_remH,r_remH ; clear remainder and carry
- mov_l r_remHL, r_remL
- mov_h r_remHH, r_remH
- rjmp __udivmodsi4_ep ; jump to entry point
-__udivmodsi4_loop:
- rol r_remL ; shift dividend into remainder
- rol r_remH
- rol r_remHL
- rol r_remHH
- cp r_remL,r_arg2L ; compare remainder & divisor
- cpc r_remH,r_arg2H
- cpc r_remHL,r_arg2HL
- cpc r_remHH,r_arg2HH
- brcs __udivmodsi4_ep ; remainder <= divisor
- sub r_remL,r_arg2L ; restore remainder
- sbc r_remH,r_arg2H
- sbc r_remHL,r_arg2HL
- sbc r_remHH,r_arg2HH
-__udivmodsi4_ep:
- rol r_arg1L ; shift dividend (with CARRY)
- rol r_arg1H
- rol r_arg1HL
- rol r_arg1HH
- dec r_cnt ; decrement loop counter
- brne __udivmodsi4_loop
- ; __zero_reg__ now restored (r_cnt == 0)
- com r_arg1L
- com r_arg1H
- com r_arg1HL
- com r_arg1HH
-; div/mod results to return registers, as for the ldiv() function
- mov_l r_arg2L, r_arg1L ; quotient
- mov_h r_arg2H, r_arg1H
- mov_l r_arg2HL, r_arg1HL
- mov_h r_arg2HH, r_arg1HH
- mov_l r_arg1L, r_remL ; remainder
- mov_h r_arg1H, r_remH
- mov_l r_arg1HL, r_remHL
- mov_h r_arg1HH, r_remHH
- ret
-ENDF __udivmodsi4
-#endif /* defined (L_udivmodsi4) */
-
-#if defined (L_divmodsi4)
-DEFUN __divmodsi4
- bst r_arg1HH,7 ; store sign of dividend
- mov __tmp_reg__,r_arg1HH
- eor __tmp_reg__,r_arg2HH ; r0.7 is sign of result
- rcall __divmodsi4_neg1 ; dividend negative : negate
- sbrc r_arg2HH,7
- rcall __divmodsi4_neg2 ; divisor negative : negate
- XCALL __udivmodsi4 ; do the unsigned div/mod
- rcall __divmodsi4_neg1 ; correct remainder sign
- rol __tmp_reg__
- brcc __divmodsi4_exit
-__divmodsi4_neg2:
- com r_arg2HH
- com r_arg2HL
- com r_arg2H
- neg r_arg2L ; correct divisor/quotient sign
- sbci r_arg2H,0xff
- sbci r_arg2HL,0xff
- sbci r_arg2HH,0xff
-__divmodsi4_exit:
- ret
-__divmodsi4_neg1:
- brtc __divmodsi4_exit
- com r_arg1HH
- com r_arg1HL
- com r_arg1H
- neg r_arg1L ; correct dividend/remainder sign
- sbci r_arg1H, 0xff
- sbci r_arg1HL,0xff
- sbci r_arg1HH,0xff
- ret
-ENDF __divmodsi4
-#endif /* defined (L_divmodsi4) */
-
-
-.section .text.libgcc.prologue, "ax", @progbits
-
-/**********************************
- * This is a prologue subroutine
- **********************************/
-#if defined (L_prologue)
-
-DEFUN __prologue_saves__
- push r2
- push r3
- push r4
- push r5
- push r6
- push r7
- push r8
- push r9
- push r10
- push r11
- push r12
- push r13
- push r14
- push r15
- push r16
- push r17
- push r28
- push r29
- in r28,__SP_L__
- in r29,__SP_H__
- sub r28,r26
- sbc r29,r27
- in __tmp_reg__,__SREG__
- cli
- out __SP_H__,r29
- out __SREG__,__tmp_reg__
- out __SP_L__,r28
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- eijmp
-#else
- ijmp
-#endif
-
-ENDF __prologue_saves__
-#endif /* defined (L_prologue) */
-
-/*
- * This is an epilogue subroutine
- */
-#if defined (L_epilogue)
-
-DEFUN __epilogue_restores__
- ldd r2,Y+18
- ldd r3,Y+17
- ldd r4,Y+16
- ldd r5,Y+15
- ldd r6,Y+14
- ldd r7,Y+13
- ldd r8,Y+12
- ldd r9,Y+11
- ldd r10,Y+10
- ldd r11,Y+9
- ldd r12,Y+8
- ldd r13,Y+7
- ldd r14,Y+6
- ldd r15,Y+5
- ldd r16,Y+4
- ldd r17,Y+3
- ldd r26,Y+2
- ldd r27,Y+1
- add r28,r30
- adc r29,__zero_reg__
- in __tmp_reg__,__SREG__
- cli
- out __SP_H__,r29
- out __SREG__,__tmp_reg__
- out __SP_L__,r28
- mov_l r28, r26
- mov_h r29, r27
- ret
-ENDF __epilogue_restores__
-#endif /* defined (L_epilogue) */
-
-#ifdef L_exit
- .section .fini9,"ax",@progbits
-DEFUN _exit
- .weak exit
-exit:
-ENDF _exit
-
- /* Code from .fini8 ... .fini1 sections inserted by ld script. */
-
- .section .fini0,"ax",@progbits
- cli
-__stop_program:
- rjmp __stop_program
-#endif /* defined (L_exit) */
-
-#ifdef L_cleanup
- .weak _cleanup
- .func _cleanup
-_cleanup:
- ret
-.endfunc
-#endif /* defined (L_cleanup) */
-
-
-.section .text.libgcc, "ax", @progbits
-
-#ifdef L_tablejump
-DEFUN __tablejump2__
- lsl r30
- rol r31
- ;; FALLTHRU
-ENDF __tablejump2__
-
-DEFUN __tablejump__
-#if defined (__AVR_HAVE_LPMX__)
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- lpm __tmp_reg__, Z+
- push __tmp_reg__
- lpm __tmp_reg__, Z
- push __tmp_reg__
- push __zero_reg__
- ret
-#else
- lpm __tmp_reg__, Z+
- lpm r31, Z
- mov r30, __tmp_reg__
- ijmp
-#endif
-
-#else /* !HAVE_LPMX */
- lpm
- adiw r30, 1
- push r0
- lpm
- push r0
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- push __zero_reg__
-#endif
- ret
-#endif /* !HAVE_LPMX */
-ENDF __tablejump__
-#endif /* defined (L_tablejump) */
-
-#ifdef L_copy_data
- .section .init4,"ax",@progbits
-DEFUN __do_copy_data
-#if defined(__AVR_HAVE_ELPMX__)
- ldi r17, hi8(__data_end)
- ldi r26, lo8(__data_start)
- ldi r27, hi8(__data_start)
- ldi r30, lo8(__data_load_start)
- ldi r31, hi8(__data_load_start)
- ldi r16, hh8(__data_load_start)
- out __RAMPZ__, r16
- rjmp .L__do_copy_data_start
-.L__do_copy_data_loop:
- elpm r0, Z+
- st X+, r0
-.L__do_copy_data_start:
- cpi r26, lo8(__data_end)
- cpc r27, r17
- brne .L__do_copy_data_loop
-#elif !defined(__AVR_HAVE_ELPMX__) && defined(__AVR_HAVE_ELPM__)
- ldi r17, hi8(__data_end)
- ldi r26, lo8(__data_start)
- ldi r27, hi8(__data_start)
- ldi r30, lo8(__data_load_start)
- ldi r31, hi8(__data_load_start)
- ldi r16, hh8(__data_load_start - 0x10000)
-.L__do_copy_data_carry:
- inc r16
- out __RAMPZ__, r16
- rjmp .L__do_copy_data_start
-.L__do_copy_data_loop:
- elpm
- st X+, r0
- adiw r30, 1
- brcs .L__do_copy_data_carry
-.L__do_copy_data_start:
- cpi r26, lo8(__data_end)
- cpc r27, r17
- brne .L__do_copy_data_loop
-#elif !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__)
- ldi r17, hi8(__data_end)
- ldi r26, lo8(__data_start)
- ldi r27, hi8(__data_start)
- ldi r30, lo8(__data_load_start)
- ldi r31, hi8(__data_load_start)
- rjmp .L__do_copy_data_start
-.L__do_copy_data_loop:
-#if defined (__AVR_HAVE_LPMX__)
- lpm r0, Z+
-#else
- lpm
- adiw r30, 1
-#endif
- st X+, r0
-.L__do_copy_data_start:
- cpi r26, lo8(__data_end)
- cpc r27, r17
- brne .L__do_copy_data_loop
-#endif /* !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__) */
-ENDF __do_copy_data
-#endif /* L_copy_data */
-
-/* __do_clear_bss is only necessary if there is anything in .bss section. */
-
-#ifdef L_clear_bss
- .section .init4,"ax",@progbits
-DEFUN __do_clear_bss
- ldi r17, hi8(__bss_end)
- ldi r26, lo8(__bss_start)
- ldi r27, hi8(__bss_start)
- rjmp .do_clear_bss_start
-.do_clear_bss_loop:
- st X+, __zero_reg__
-.do_clear_bss_start:
- cpi r26, lo8(__bss_end)
- cpc r27, r17
- brne .do_clear_bss_loop
-ENDF __do_clear_bss
-#endif /* L_clear_bss */
-
-/* __do_global_ctors and __do_global_dtors are only necessary
- if there are any constructors/destructors. */
-
-#ifdef L_ctors
- .section .init6,"ax",@progbits
-DEFUN __do_global_ctors
-#if defined(__AVR_HAVE_RAMPZ__)
- ldi r17, hi8(__ctors_start)
- ldi r28, lo8(__ctors_end)
- ldi r29, hi8(__ctors_end)
- ldi r16, hh8(__ctors_end)
- rjmp .L__do_global_ctors_start
-.L__do_global_ctors_loop:
- sbiw r28, 2
- sbc r16, __zero_reg__
- mov_h r31, r29
- mov_l r30, r28
- out __RAMPZ__, r16
- XCALL __tablejump_elpm__
-.L__do_global_ctors_start:
- cpi r28, lo8(__ctors_start)
- cpc r29, r17
- ldi r24, hh8(__ctors_start)
- cpc r16, r24
- brne .L__do_global_ctors_loop
-#else
- ldi r17, hi8(__ctors_start)
- ldi r28, lo8(__ctors_end)
- ldi r29, hi8(__ctors_end)
- rjmp .L__do_global_ctors_start
-.L__do_global_ctors_loop:
- sbiw r28, 2
- mov_h r31, r29
- mov_l r30, r28
- XCALL __tablejump__
-.L__do_global_ctors_start:
- cpi r28, lo8(__ctors_start)
- cpc r29, r17
- brne .L__do_global_ctors_loop
-#endif /* defined(__AVR_HAVE_RAMPZ__) */
-ENDF __do_global_ctors
-#endif /* L_ctors */
-
-#ifdef L_dtors
- .section .fini6,"ax",@progbits
-DEFUN __do_global_dtors
-#if defined(__AVR_HAVE_RAMPZ__)
- ldi r17, hi8(__dtors_end)
- ldi r28, lo8(__dtors_start)
- ldi r29, hi8(__dtors_start)
- ldi r16, hh8(__dtors_start)
- rjmp .L__do_global_dtors_start
-.L__do_global_dtors_loop:
- sbiw r28, 2
- sbc r16, __zero_reg__
- mov_h r31, r29
- mov_l r30, r28
- out __RAMPZ__, r16
- XCALL __tablejump_elpm__
-.L__do_global_dtors_start:
- cpi r28, lo8(__dtors_end)
- cpc r29, r17
- ldi r24, hh8(__dtors_end)
- cpc r16, r24
- brne .L__do_global_dtors_loop
-#else
- ldi r17, hi8(__dtors_end)
- ldi r28, lo8(__dtors_start)
- ldi r29, hi8(__dtors_start)
- rjmp .L__do_global_dtors_start
-.L__do_global_dtors_loop:
- mov_h r31, r29
- mov_l r30, r28
- XCALL __tablejump__
- adiw r28, 2
-.L__do_global_dtors_start:
- cpi r28, lo8(__dtors_end)
- cpc r29, r17
- brne .L__do_global_dtors_loop
-#endif /* defined(__AVR_HAVE_RAMPZ__) */
-ENDF __do_global_dtors
-#endif /* L_dtors */
-
-.section .text.libgcc, "ax", @progbits
-
-#ifdef L_tablejump_elpm
-DEFUN __tablejump_elpm__
-#if defined (__AVR_HAVE_ELPM__)
-#if defined (__AVR_HAVE_LPMX__)
- elpm __tmp_reg__, Z+
- elpm r31, Z
- mov r30, __tmp_reg__
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- eijmp
-#else
- ijmp
-#endif
-
-#else
- elpm
- adiw r30, 1
- push r0
- elpm
- push r0
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
- push __zero_reg__
-#endif
- ret
-#endif
-#endif /* defined (__AVR_HAVE_ELPM__) */
-ENDF __tablejump_elpm__
-#endif /* defined (L_tablejump_elpm) */
-
-
-.section .text.libgcc.builtins, "ax", @progbits
-
-/**********************************
- * Find first set Bit (ffs)
- **********************************/
-
-#if defined (L_ffssi2)
-;; find first set bit
-;; r25:r24 = ffs32 (r25:r22)
-;; clobbers: r22, r26
-DEFUN __ffssi2
- clr r26
- tst r22
- brne 1f
- subi r26, -8
- or r22, r23
- brne 1f
- subi r26, -8
- or r22, r24
- brne 1f
- subi r26, -8
- or r22, r25
- brne 1f
- ret
-1: mov r24, r22
- XJMP __loop_ffsqi2
-ENDF __ffssi2
-#endif /* defined (L_ffssi2) */
-
-#if defined (L_ffshi2)
-;; find first set bit
-;; r25:r24 = ffs16 (r25:r24)
-;; clobbers: r26
-DEFUN __ffshi2
- clr r26
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- ;; Some cores have problem skipping 2-word instruction
- tst r24
- breq 2f
-#else
- cpse r24, __zero_reg__
-#endif /* __AVR_HAVE_JMP_CALL__ */
-1: XJMP __loop_ffsqi2
-2: ldi r26, 8
- or r24, r25
- brne 1b
- ret
-ENDF __ffshi2
-#endif /* defined (L_ffshi2) */
-
-#if defined (L_loop_ffsqi2)
-;; Helper for ffshi2, ffssi2
-;; r25:r24 = r26 + zero_extend16 (ffs8(r24))
-;; r24 must be != 0
-;; clobbers: r26
-DEFUN __loop_ffsqi2
- inc r26
- lsr r24
- brcc __loop_ffsqi2
- mov r24, r26
- clr r25
- ret
-ENDF __loop_ffsqi2
-#endif /* defined (L_loop_ffsqi2) */
-
-
-/**********************************
- * Count trailing Zeros (ctz)
- **********************************/
-
-#if defined (L_ctzsi2)
-;; count trailing zeros
-;; r25:r24 = ctz32 (r25:r22)
-;; clobbers: r26, r22
-;; ctz(0) = 255
-;; Note that ctz(0) in undefined for GCC
-DEFUN __ctzsi2
- XCALL __ffssi2
- dec r24
- ret
-ENDF __ctzsi2
-#endif /* defined (L_ctzsi2) */
-
-#if defined (L_ctzhi2)
-;; count trailing zeros
-;; r25:r24 = ctz16 (r25:r24)
-;; clobbers: r26
-;; ctz(0) = 255
-;; Note that ctz(0) in undefined for GCC
-DEFUN __ctzhi2
- XCALL __ffshi2
- dec r24
- ret
-ENDF __ctzhi2
-#endif /* defined (L_ctzhi2) */
-
-
-/**********************************
- * Count leading Zeros (clz)
- **********************************/
-
-#if defined (L_clzdi2)
-;; count leading zeros
-;; r25:r24 = clz64 (r25:r18)
-;; clobbers: r22, r23, r26
-DEFUN __clzdi2
- XCALL __clzsi2
- sbrs r24, 5
- ret
- mov_l r22, r18
- mov_h r23, r19
- mov_l r24, r20
- mov_h r25, r21
- XCALL __clzsi2
- subi r24, -32
- ret
-ENDF __clzdi2
-#endif /* defined (L_clzdi2) */
-
-#if defined (L_clzsi2)
-;; count leading zeros
-;; r25:r24 = clz32 (r25:r22)
-;; clobbers: r26
-DEFUN __clzsi2
- XCALL __clzhi2
- sbrs r24, 4
- ret
- mov_l r24, r22
- mov_h r25, r23
- XCALL __clzhi2
- subi r24, -16
- ret
-ENDF __clzsi2
-#endif /* defined (L_clzsi2) */
-
-#if defined (L_clzhi2)
-;; count leading zeros
-;; r25:r24 = clz16 (r25:r24)
-;; clobbers: r26
-DEFUN __clzhi2
- clr r26
- tst r25
- brne 1f
- subi r26, -8
- or r25, r24
- brne 1f
- ldi r24, 16
- ret
-1: cpi r25, 16
- brsh 3f
- subi r26, -3
- swap r25
-2: inc r26
-3: lsl r25
- brcc 2b
- mov r24, r26
- clr r25
- ret
-ENDF __clzhi2
-#endif /* defined (L_clzhi2) */
-
-
-/**********************************
- * Parity
- **********************************/
-
-#if defined (L_paritydi2)
-;; r25:r24 = parity64 (r25:r18)
-;; clobbers: __tmp_reg__
-DEFUN __paritydi2
- eor r24, r18
- eor r24, r19
- eor r24, r20
- eor r24, r21
- XJMP __paritysi2
-ENDF __paritydi2
-#endif /* defined (L_paritydi2) */
-
-#if defined (L_paritysi2)
-;; r25:r24 = parity32 (r25:r22)
-;; clobbers: __tmp_reg__
-DEFUN __paritysi2
- eor r24, r22
- eor r24, r23
- XJMP __parityhi2
-ENDF __paritysi2
-#endif /* defined (L_paritysi2) */
-
-#if defined (L_parityhi2)
-;; r25:r24 = parity16 (r25:r24)
-;; clobbers: __tmp_reg__
-DEFUN __parityhi2
- eor r24, r25
-;; FALLTHRU
-ENDF __parityhi2
-
-;; r25:r24 = parity8 (r24)
-;; clobbers: __tmp_reg__
-DEFUN __parityqi2
- ;; parity is in r24[0..7]
- mov __tmp_reg__, r24
- swap __tmp_reg__
- eor r24, __tmp_reg__
- ;; parity is in r24[0..3]
- subi r24, -4
- andi r24, -5
- subi r24, -6
- ;; parity is in r24[0,3]
- sbrc r24, 3
- inc r24
- ;; parity is in r24[0]
- andi r24, 1
- clr r25
- ret
-ENDF __parityqi2
-#endif /* defined (L_parityhi2) */
-
-
-/**********************************
- * Population Count
- **********************************/
-
-#if defined (L_popcounthi2)
-;; population count
-;; r25:r24 = popcount16 (r25:r24)
-;; clobbers: __tmp_reg__
-DEFUN __popcounthi2
- XCALL __popcountqi2
- push r24
- mov r24, r25
- XCALL __popcountqi2
- clr r25
- ;; FALLTHRU
-ENDF __popcounthi2
-
-DEFUN __popcounthi2_tail
- pop __tmp_reg__
- add r24, __tmp_reg__
- ret
-ENDF __popcounthi2_tail
-#endif /* defined (L_popcounthi2) */
-
-#if defined (L_popcountsi2)
-;; population count
-;; r25:r24 = popcount32 (r25:r22)
-;; clobbers: __tmp_reg__
-DEFUN __popcountsi2
- XCALL __popcounthi2
- push r24
- mov_l r24, r22
- mov_h r25, r23
- XCALL __popcounthi2
- XJMP __popcounthi2_tail
-ENDF __popcountsi2
-#endif /* defined (L_popcountsi2) */
-
-#if defined (L_popcountdi2)
-;; population count
-;; r25:r24 = popcount64 (r25:r18)
-;; clobbers: r22, r23, __tmp_reg__
-DEFUN __popcountdi2
- XCALL __popcountsi2
- push r24
- mov_l r22, r18
- mov_h r23, r19
- mov_l r24, r20
- mov_h r25, r21
- XCALL __popcountsi2
- XJMP __popcounthi2_tail
-ENDF __popcountdi2
-#endif /* defined (L_popcountdi2) */
-
-#if defined (L_popcountqi2)
-;; population count
-;; r24 = popcount8 (r24)
-;; clobbers: __tmp_reg__
-DEFUN __popcountqi2
- mov __tmp_reg__, r24
- andi r24, 1
- lsr __tmp_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __zero_reg__
- lsr __tmp_reg__
- adc r24, __tmp_reg__
- ret
-ENDF __popcountqi2
-#endif /* defined (L_popcountqi2) */
-
-
-/**********************************
- * Swap bytes
- **********************************/
-
-;; swap two registers with different register number
-.macro bswap a, b
- eor \a, \b
- eor \b, \a
- eor \a, \b
-.endm
-
-#if defined (L_bswapsi2)
-;; swap bytes
-;; r25:r22 = bswap32 (r25:r22)
-DEFUN __bswapsi2
- bswap r22, r25
- bswap r23, r24
- ret
-ENDF __bswapsi2
-#endif /* defined (L_bswapsi2) */
-
-#if defined (L_bswapdi2)
-;; swap bytes
-;; r25:r18 = bswap64 (r25:r18)
-DEFUN __bswapdi2
- bswap r18, r25
- bswap r19, r24
- bswap r20, r23
- bswap r21, r22
- ret
-ENDF __bswapdi2
-#endif /* defined (L_bswapdi2) */
-
-
-/**********************************
- * 64-bit shifts
- **********************************/
-
-#if defined (L_ashrdi3)
-;; Arithmetic shift right
-;; r25:r18 = ashr64 (r25:r18, r17:r16)
-DEFUN __ashrdi3
- push r16
- andi r16, 63
- breq 2f
-1: asr r25
- ror r24
- ror r23
- ror r22
- ror r21
- ror r20
- ror r19
- ror r18
- dec r16
- brne 1b
-2: pop r16
- ret
-ENDF __ashrdi3
-#endif /* defined (L_ashrdi3) */
-
-#if defined (L_lshrdi3)
-;; Logic shift right
-;; r25:r18 = lshr64 (r25:r18, r17:r16)
-DEFUN __lshrdi3
- push r16
- andi r16, 63
- breq 2f
-1: lsr r25
- ror r24
- ror r23
- ror r22
- ror r21
- ror r20
- ror r19
- ror r18
- dec r16
- brne 1b
-2: pop r16
- ret
-ENDF __lshrdi3
-#endif /* defined (L_lshrdi3) */
-
-#if defined (L_ashldi3)
-;; Shift left
-;; r25:r18 = ashl64 (r25:r18, r17:r16)
-DEFUN __ashldi3
- push r16
- andi r16, 63
- breq 2f
-1: lsl r18
- rol r19
- rol r20
- rol r21
- rol r22
- rol r23
- rol r24
- rol r25
- dec r16
- brne 1b
-2: pop r16
- ret
-ENDF __ashldi3
-#endif /* defined (L_ashldi3) */
-
-
-.section .text.libgcc.fmul, "ax", @progbits
-
-/***********************************************************/
-;;; Softmul versions of FMUL, FMULS and FMULSU to implement
-;;; __builtin_avr_fmul* if !AVR_HAVE_MUL
-/***********************************************************/
-
-#define A1 24
-#define B1 25
-#define C0 22
-#define C1 23
-#define A0 __tmp_reg__
-
-#ifdef L_fmuls
-;;; r23:r22 = fmuls (r24, r25) like in FMULS instruction
-;;; Clobbers: r24, r25, __tmp_reg__
-DEFUN __fmuls
- ;; A0.7 = negate result?
- mov A0, A1
- eor A0, B1
- ;; B1 = |B1|
- sbrc B1, 7
- neg B1
- XJMP __fmulsu_exit
-ENDF __fmuls
-#endif /* L_fmuls */
-
-#ifdef L_fmulsu
-;;; r23:r22 = fmulsu (r24, r25) like in FMULSU instruction
-;;; Clobbers: r24, r25, __tmp_reg__
-DEFUN __fmulsu
- ;; A0.7 = negate result?
- mov A0, A1
-;; FALLTHRU
-ENDF __fmulsu
-
-;; Helper for __fmuls and __fmulsu
-DEFUN __fmulsu_exit
- ;; A1 = |A1|
- sbrc A1, 7
- neg A1
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- ;; Some cores have problem skipping 2-word instruction
- tst A0
- brmi 1f
-#else
- sbrs A0, 7
-#endif /* __AVR_HAVE_JMP_CALL__ */
- XJMP __fmul
-1: XCALL __fmul
- ;; C = -C iff A0.7 = 1
- com C1
- neg C0
- sbci C1, -1
- ret
-ENDF __fmulsu_exit
-#endif /* L_fmulsu */
-
-
-#ifdef L_fmul
-;;; r22:r23 = fmul (r24, r25) like in FMUL instruction
-;;; Clobbers: r24, r25, __tmp_reg__
-DEFUN __fmul
- ; clear result
- clr C0
- clr C1
- clr A0
-1: tst B1
- ;; 1.0 = 0x80, so test for bit 7 of B to see if A must to be added to C.
-2: brpl 3f
- ;; C += A
- add C0, A0
- adc C1, A1
-3: ;; A >>= 1
- lsr A1
- ror A0
- ;; B <<= 1
- lsl B1
- brne 2b
- ret
-ENDF __fmul
-#endif /* L_fmul */
-
-#undef A0
-#undef A1
-#undef B1
-#undef C0
-#undef C1
diff --git a/gcc/config/avr/predicates.md b/gcc/config/avr/predicates.md
index 1881e8b5162..55a25b8b05a 100644
--- a/gcc/config/avr/predicates.md
+++ b/gcc/config/avr/predicates.md
@@ -135,7 +135,7 @@
;;
(define_predicate "avr_sp_immediate_operand"
(and (match_code "const_int")
- (match_test "INTVAL (op) >= -6 && INTVAL (op) <= 5")))
+ (match_test "satisfies_constraint_Csp (op)")))
;; True for EQ & NE
(define_predicate "eqne_operator"
diff --git a/gcc/config/avr/t-avr b/gcc/config/avr/t-avr
index 30e8d96447e..ee2dc56ced6 100644
--- a/gcc/config/avr/t-avr
+++ b/gcc/config/avr/t-avr
@@ -39,62 +39,6 @@ $(srcdir)/config/avr/avr-tables.opt: $(srcdir)/config/avr/genopt.sh \
$(SHELL) $(srcdir)/config/avr/genopt.sh $(srcdir)/config/avr > \
$(srcdir)/config/avr/avr-tables.opt
-LIB1ASMSRC = avr/libgcc.S
-LIB1ASMFUNCS = \
- _mulqi3 \
- _mulhi3 \
- _mulhisi3 \
- _umulhisi3 \
- _usmulhisi3 \
- _muluhisi3 \
- _mulshisi3 \
- _mulsi3 \
- _udivmodqi4 \
- _divmodqi4 \
- _udivmodhi4 \
- _divmodhi4 \
- _udivmodsi4 \
- _divmodsi4 \
- _prologue \
- _epilogue \
- _exit \
- _cleanup \
- _tablejump \
- _tablejump_elpm \
- _copy_data \
- _clear_bss \
- _ctors \
- _dtors \
- _ffssi2 \
- _ffshi2 \
- _loop_ffsqi2 \
- _ctzsi2 \
- _ctzhi2 \
- _clzdi2 \
- _clzsi2 \
- _clzhi2 \
- _paritydi2 \
- _paritysi2 \
- _parityhi2 \
- _popcounthi2 \
- _popcountsi2 \
- _popcountdi2 \
- _popcountqi2 \
- _bswapsi2 \
- _bswapdi2 \
- _ashldi3 \
- _ashrdi3 \
- _lshrdi3 \
- _fmul _fmuls _fmulsu
-
-LIB2FUNCS_EXCLUDE = \
- _clz
-
-# We do not have the DF type.
-# Most of the C functions in libgcc2 use almost all registers,
-# so use -mcall-prologues for smaller code size.
-TARGET_LIBGCC2_CFLAGS = -DDF=SF -Dinhibit_libc -mcall-prologues -Os
-
MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6
MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6
@@ -243,6 +187,3 @@ MULTILIB_MATCHES = \
mmcu?avr6=mmcu?atmega2561
MULTILIB_EXCEPTIONS =
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/bfin/t-bfin b/gcc/config/bfin/t-bfin
deleted file mode 100644
index 730043e4b63..00000000000
--- a/gcc/config/bfin/t-bfin
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2005, 2007, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-## Target part of the Makefile
-
-LIB1ASMSRC = bfin/lib1funcs.asm
-LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3 _muldi3 _umulsi3_highpart
-LIB1ASMFUNCS += _smulsi3_highpart
-
-EXTRA_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/bfin/crti.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/bfin/crti.s
-
-$(T)crtn.o: $(srcdir)/config/bfin/crtn.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/bfin/crtn.s
diff --git a/gcc/config/bfin/t-bfin-elf b/gcc/config/bfin/t-bfin-elf
index 61797bfad2a..742740ebc44 100644
--- a/gcc/config/bfin/t-bfin-elf
+++ b/gcc/config/bfin/t-bfin-elf
@@ -18,13 +18,6 @@
## Target part of the Makefile
-LIB1ASMSRC = bfin/lib1funcs.asm
-LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3 _muldi3 _umulsi3_highpart
-LIB1ASMFUNCS += _smulsi3_highpart
-
-CRTSTUFF_T_CFLAGS = -fpic
-TARGET_LIBGCC2_CFLAGS = -fpic
-
MULTILIB_OPTIONS=mcpu=bf532-none
MULTILIB_OPTIONS+=mid-shared-library/msep-data/mfdpic mleaf-id-shared-library
MULTILIB_DIRNAMES=bf532-none mid-shared-library msep-data mfdpic mleaf-id-shared-library
@@ -54,19 +47,3 @@ MULTILIB_EXCEPTIONS=mleaf-id-shared-library*
MULTILIB_EXCEPTIONS+=mcpu=bf532-none/mleaf-id-shared-library*
MULTILIB_EXCEPTIONS+=*mfdpic/mleaf-id-shared-library*
MULTILIB_EXCEPTIONS+=*msep-data/mleaf-id-shared-library*
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/bfin/crti.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/bfin/crti.s
-
-$(T)crtn.o: $(srcdir)/config/bfin/crtn.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/bfin/crtn.s
-
-$(T)crtlibid.o: $(srcdir)/config/bfin/crtlibid.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtlibid.o -x assembler-with-cpp \
- $(srcdir)/config/bfin/crtlibid.s
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o crtlibid.o
diff --git a/gcc/config/bfin/t-bfin-linux b/gcc/config/bfin/t-bfin-linux
index e7e705ef1d4..7d25358c265 100644
--- a/gcc/config/bfin/t-bfin-linux
+++ b/gcc/config/bfin/t-bfin-linux
@@ -18,13 +18,6 @@
## Target part of the Makefile
-LIB1ASMSRC = bfin/lib1funcs.asm
-LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3 _muldi3 _umulsi3_highpart
-LIB1ASMFUNCS += _smulsi3_highpart
-
-CRTSTUFF_T_CFLAGS = -fpic
-TARGET_LIBGCC2_CFLAGS = -fpic
-
MULTILIB_OPTIONS=mcpu=bf532-none
MULTILIB_DIRNAMES=bf532-none
@@ -49,10 +42,6 @@ MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf549m-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf561-none
MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf592-none
-SHLIB_MAPFILES=$(srcdir)/config/bfin/libgcc-bfin.ver
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o
-
# This rule uses MULTILIB_MATCHES to generate a definition of
# SYSROOT_SUFFIX_SPEC.
linux-sysroot-suffix.h: $(srcdir)/config/bfin/print-sysroot-suffix.sh
diff --git a/gcc/config/bfin/t-bfin-uclinux b/gcc/config/bfin/t-bfin-uclinux
index a46d7b3ac15..e3e9b13e712 100644
--- a/gcc/config/bfin/t-bfin-uclinux
+++ b/gcc/config/bfin/t-bfin-uclinux
@@ -18,13 +18,6 @@
## Target part of the Makefile
-LIB1ASMSRC = bfin/lib1funcs.asm
-LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3 _muldi3 _umulsi3_highpart
-LIB1ASMFUNCS += _smulsi3_highpart
-
-CRTSTUFF_T_CFLAGS = -fpic
-TARGET_LIBGCC2_CFLAGS = -fpic
-
MULTILIB_OPTIONS=mcpu=bf532-none
MULTILIB_OPTIONS+=mid-shared-library/msep-data mleaf-id-shared-library
MULTILIB_DIRNAMES=bf532-none mid-shared-library msep-data mleaf-id-shared-library
@@ -53,11 +46,3 @@ MULTILIB_MATCHES+=mcpu?bf532-none=mcpu?bf592-none
MULTILIB_EXCEPTIONS=mleaf-id-shared-library*
MULTILIB_EXCEPTIONS+=mcpu=bf532-none/mleaf-id-shared-library*
MULTILIB_EXCEPTIONS+=*msep-data/mleaf-id-shared-library*
-
-# Assemble startup files.
-$(T)crtlibid.o: $(srcdir)/config/bfin/crtlibid.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtlibid.o -x assembler-with-cpp \
- $(srcdir)/config/bfin/crtlibid.s
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crtlibid.o
diff --git a/gcc/config/c6x/c6x-mult.md b/gcc/config/c6x/c6x-mult.md
index ec18ba31a7e..7cf66f1ff4d 100644
--- a/gcc/config/c6x/c6x-mult.md
+++ b/gcc/config/c6x/c6x-mult.md
@@ -81,6 +81,7 @@
"%|%.\\tmpy\\t%$\\t%2, %1, %0"
[(set_attr "type" "mpy2")
(set_attr "units" "m")
+ (set_attr "op_pattern" "sxs")
(set_attr "cross" "n,n,y,y")])
(define_insn "mulhisi3_const"
@@ -104,6 +105,7 @@
"%|%.\\tmpy\\t%$\\t%1, %2, %0"
[(set_attr "type" "mpy2")
(set_attr "units" "m")
+ (set_attr "op_pattern" "ssx")
(set_attr "cross" "n,n,y,y")])
(define_insn "mulhisi3_lh"
@@ -500,6 +502,7 @@
"%|%.\\tmpy\\t%$\\t%2, %1, %k0"
[(set_attr "type" "mpy2")
(set_attr "units" "m")
+ (set_attr "op_pattern" "sxs")
(set_attr "cross" "n,n,y,y")])
(define_insn "mulhisi3_const_real"
@@ -523,6 +526,7 @@
"%|%.\\tmpy\\t%$\\t%1, %2, %k0"
[(set_attr "type" "mpy2")
(set_attr "units" "m")
+ (set_attr "op_pattern" "ssx")
(set_attr "cross" "n,n,y,y")])
(define_insn "mulhisi3_lh_real"
diff --git a/gcc/config/c6x/c6x-mult.md.in b/gcc/config/c6x/c6x-mult.md.in
index 96de44fd368..e9a1dc4a40e 100644
--- a/gcc/config/c6x/c6x-mult.md.in
+++ b/gcc/config/c6x/c6x-mult.md.in
@@ -79,6 +79,7 @@
"%|%.\\tmpy\\t%$\\t%2, %1, %_MODk_0"
[(set_attr "type" "mpy2")
(set_attr "units" "m")
+ (set_attr "op_pattern" "sxs")
(set_attr "cross" "n,n,y,y")])
(define_insn "mulhisi3_const_VARIANT_"
@@ -102,6 +103,7 @@
"%|%.\\tmpy\\t%$\\t%1, %2, %_MODk_0"
[(set_attr "type" "mpy2")
(set_attr "units" "m")
+ (set_attr "op_pattern" "ssx")
(set_attr "cross" "n,n,y,y")])
(define_insn "mulhisi3_lh_VARIANT_"
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 57e62d9b98d..c128890d929 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -51,6 +51,7 @@
#include "debug.h"
#include "opts.h"
#include "hw-doloop.h"
+#include "regrename.h"
/* Table of supported architecture variants. */
typedef struct
@@ -3312,6 +3313,25 @@ merge_unit_reqs (unit_req_table reqs)
}
}
+/* Examine the table REQS and return a measure of unit imbalance by comparing
+ the two sides of the machine. If, for example, D1 is used twice and D2
+ used not at all, the return value should be 1 in the absence of other
+ imbalances. */
+static int
+unit_req_imbalance (unit_req_table reqs)
+{
+ int val = 0;
+ int i;
+
+ for (i = 0; i < UNIT_REQ_MAX; i++)
+ {
+ int factor = unit_req_factor ((enum unitreqs) i);
+ int diff = abs (reqs[0][i] - reqs[1][i]);
+ val += (diff + factor - 1) / factor / 2;
+ }
+ return val;
+}
+
/* Return the resource-constrained minimum iteration interval given the
data in the REQS table. This must have been processed with
merge_unit_reqs already. */
@@ -3323,12 +3343,239 @@ res_mii (unit_req_table reqs)
for (side = 0; side < 2; side++)
for (req = 0; req < UNIT_REQ_MAX; req++)
{
- int factor = unit_req_factor (req);
+ int factor = unit_req_factor ((enum unitreqs) req);
worst = MAX ((reqs[side][UNIT_REQ_D] + factor - 1) / factor, worst);
}
return worst;
}
+
+/* Examine INSN, and store in PMASK1 and PMASK2 bitmasks that represent
+ the operands that are involved in the (up to) two reservations, as
+ found by get_unit_reqs. Return true if we did this successfully, false
+ if we couldn't identify what to do with INSN. */
+static bool
+get_unit_operand_masks (rtx insn, unsigned int *pmask1, unsigned int *pmask2)
+{
+ enum attr_op_pattern op_pat;
+
+ if (recog_memoized (insn) < 0)
+ return 0;
+ if (GET_CODE (PATTERN (insn)) == COND_EXEC)
+ return false;
+ extract_insn (insn);
+ op_pat = get_attr_op_pattern (insn);
+ if (op_pat == OP_PATTERN_DT)
+ {
+ gcc_assert (recog_data.n_operands == 2);
+ *pmask1 = 1 << 0;
+ *pmask2 = 1 << 1;
+ return true;
+ }
+ else if (op_pat == OP_PATTERN_TD)
+ {
+ gcc_assert (recog_data.n_operands == 2);
+ *pmask1 = 1 << 1;
+ *pmask2 = 1 << 0;
+ return true;
+ }
+ else if (op_pat == OP_PATTERN_SXS)
+ {
+ gcc_assert (recog_data.n_operands == 3);
+ *pmask1 = (1 << 0) | (1 << 2);
+ *pmask2 = 1 << 1;
+ return true;
+ }
+ else if (op_pat == OP_PATTERN_SX)
+ {
+ gcc_assert (recog_data.n_operands == 2);
+ *pmask1 = 1 << 0;
+ *pmask2 = 1 << 1;
+ return true;
+ }
+ else if (op_pat == OP_PATTERN_SSX)
+ {
+ gcc_assert (recog_data.n_operands == 3);
+ *pmask1 = (1 << 0) | (1 << 1);
+ *pmask2 = 1 << 2;
+ return true;
+ }
+ return false;
+}
+
+/* Try to replace a register in INSN, which has corresponding rename info
+ from regrename_analyze in INFO. OP_MASK and ORIG_SIDE provide information
+ about the operands that must be renamed and the side they are on.
+ REQS is the table of unit reservations in the loop between HEAD and TAIL.
+ We recompute this information locally after our transformation, and keep
+ it only if we managed to improve the balance. */
+static void
+try_rename_operands (rtx head, rtx tail, unit_req_table reqs, rtx insn,
+ insn_rr_info *info, unsigned int op_mask, int orig_side)
+{
+ enum reg_class super_class = orig_side == 0 ? B_REGS : A_REGS;
+ HARD_REG_SET unavailable;
+ du_head_p this_head;
+ struct du_chain *chain;
+ int i;
+ unsigned tmp_mask;
+ int best_reg, old_reg;
+ VEC (du_head_p, heap) *involved_chains = NULL;
+ unit_req_table new_reqs;
+
+ for (i = 0, tmp_mask = op_mask; tmp_mask; i++)
+ {
+ du_head_p op_chain;
+ if ((tmp_mask & (1 << i)) == 0)
+ continue;
+ if (info->op_info[i].n_chains != 1)
+ goto out_fail;
+ op_chain = regrename_chain_from_id (info->op_info[i].heads[0]->id);
+ VEC_safe_push (du_head_p, heap, involved_chains, op_chain);
+ tmp_mask &= ~(1 << i);
+ }
+
+ if (VEC_length (du_head_p, involved_chains) > 1)
+ goto out_fail;
+
+ this_head = VEC_index (du_head_p, involved_chains, 0);
+ if (this_head->cannot_rename)
+ goto out_fail;
+
+ for (chain = this_head->first; chain; chain = chain->next_use)
+ {
+ unsigned int mask1, mask2, mask_changed;
+ int count, side1, side2, req1, req2;
+ insn_rr_info *this_rr = VEC_index (insn_rr_info, insn_rr,
+ INSN_UID (chain->insn));
+
+ count = get_unit_reqs (chain->insn, &req1, &side1, &req2, &side2);
+
+ if (count == 0)
+ goto out_fail;
+
+ if (!get_unit_operand_masks (chain->insn, &mask1, &mask2))
+ goto out_fail;
+
+ extract_insn (chain->insn);
+
+ mask_changed = 0;
+ for (i = 0; i < recog_data.n_operands; i++)
+ {
+ int j;
+ int n_this_op = this_rr->op_info[i].n_chains;
+ for (j = 0; j < n_this_op; j++)
+ {
+ du_head_p other = this_rr->op_info[i].heads[j];
+ if (regrename_chain_from_id (other->id) == this_head)
+ break;
+ }
+ if (j == n_this_op)
+ continue;
+
+ if (n_this_op != 1)
+ goto out_fail;
+ mask_changed |= 1 << i;
+ }
+ gcc_assert (mask_changed != 0);
+ if (mask_changed != mask1 && mask_changed != mask2)
+ goto out_fail;
+ }
+
+ /* If we get here, we can do the renaming. */
+ COMPL_HARD_REG_SET (unavailable, reg_class_contents[(int) super_class]);
+
+ old_reg = this_head->regno;
+ best_reg = find_best_rename_reg (this_head, super_class, &unavailable, old_reg);
+
+ regrename_do_replace (this_head, best_reg);
+
+ count_unit_reqs (new_reqs, head, PREV_INSN (tail));
+ merge_unit_reqs (new_reqs);
+ if (dump_file)
+ {
+ fprintf (dump_file, "reshuffle for insn %d, op_mask %x, "
+ "original side %d, new reg %d\n",
+ INSN_UID (insn), op_mask, orig_side, best_reg);
+ fprintf (dump_file, " imbalance %d -> %d\n",
+ unit_req_imbalance (reqs), unit_req_imbalance (new_reqs));
+ }
+ if (unit_req_imbalance (new_reqs) > unit_req_imbalance (reqs))
+ regrename_do_replace (this_head, old_reg);
+ else
+ memcpy (reqs, new_reqs, sizeof (unit_req_table));
+
+ out_fail:
+ VEC_free (du_head_p, heap, involved_chains);
+}
+
+/* Find insns in LOOP which would, if shifted to the other side
+ of the machine, reduce an imbalance in the unit reservations. */
+static void
+reshuffle_units (basic_block loop)
+{
+ rtx head = BB_HEAD (loop);
+ rtx tail = BB_END (loop);
+ rtx insn;
+ unit_req_table reqs;
+ edge e;
+ edge_iterator ei;
+ bitmap_head bbs;
+
+ count_unit_reqs (reqs, head, PREV_INSN (tail));
+ merge_unit_reqs (reqs);
+
+ regrename_init (true);
+
+ bitmap_initialize (&bbs, &bitmap_default_obstack);
+
+ FOR_EACH_EDGE (e, ei, loop->preds)
+ bitmap_set_bit (&bbs, e->src->index);
+
+ bitmap_set_bit (&bbs, loop->index);
+ regrename_analyze (&bbs);
+
+ for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
+ {
+ enum attr_units units;
+ int count, side1, side2, req1, req2;
+ unsigned int mask1, mask2;
+ insn_rr_info *info;
+
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+
+ count = get_unit_reqs (insn, &req1, &side1, &req2, &side2);
+
+ if (count == 0)
+ continue;
+
+ if (!get_unit_operand_masks (insn, &mask1, &mask2))
+ continue;
+
+ info = VEC_index (insn_rr_info, insn_rr, INSN_UID (insn));
+ if (info->op_info == NULL)
+ continue;
+
+ if (reqs[side1][req1] > 1
+ && reqs[side1][req1] > 2 * reqs[side1 ^ 1][req1])
+ {
+ try_rename_operands (head, tail, reqs, insn, info, mask1, side1);
+ }
+
+ units = get_attr_units (insn);
+ if (units == UNITS_D_ADDR)
+ {
+ gcc_assert (count == 2);
+ if (reqs[side2][req2] > 1
+ && reqs[side2][req2] > 2 * reqs[side2 ^ 1][req2])
+ {
+ try_rename_operands (head, tail, reqs, insn, info, mask2, side2);
+ }
+ }
+ }
+ regrename_finish ();
+}
/* Backend scheduling state. */
typedef struct c6x_sched_context
@@ -3672,7 +3919,7 @@ c6x_set_sched_flags (spec_info_t spec_info)
if (*flags & SCHED_EBB)
{
- *flags |= DO_BACKTRACKING;
+ *flags |= DO_BACKTRACKING | DO_PREDICATION;
}
spec_info->mask = 0;
@@ -5222,6 +5469,26 @@ filter_insns_above (basic_block bb, int max_uid)
}
}
+/* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY. */
+
+static void
+c6x_asm_emit_except_personality (rtx personality)
+{
+ fputs ("\t.personality\t", asm_out_file);
+ output_addr_const (asm_out_file, personality);
+ fputc ('\n', asm_out_file);
+}
+
+/* Use a special assembly directive rather than a regular setion for
+ unwind table data. */
+
+static void
+c6x_asm_init_sections (void)
+{
+ exception_section = get_unnamed_section (0, output_section_asm_op,
+ "\t.handlerdata");
+}
+
/* A callback for the hw-doloop pass. Called to optimize LOOP in a
machine-specific fashion; returns true if successful and false if
the hwloop_fail function should be called. */
@@ -5232,7 +5499,7 @@ hwloop_optimize (hwloop_info loop)
basic_block entry_bb, bb;
rtx seq, insn, prev, entry_after, end_packet;
rtx head_insn, tail_insn, new_insns, last_insn;
- int loop_earliest, entry_earliest, entry_end_cycle;
+ int loop_earliest;
int n_execute_packets;
edge entry_edge;
unsigned ix;
@@ -5263,6 +5530,8 @@ hwloop_optimize (hwloop_info loop)
if (entry_edge == NULL)
return false;
+ reshuffle_units (loop->head);
+
schedule_ebbs_init ();
schedule_ebb (BB_HEAD (loop->tail), loop->loop_end, true);
schedule_ebbs_finish ();
@@ -5632,11 +5901,14 @@ c6x_reorg (void)
compute_bb_for_insn ();
df_clear_flags (DF_LR_RUN_DCE);
+ df_note_add_problem ();
/* If optimizing, we'll have split before scheduling. */
if (optimize == 0)
split_all_insns ();
+ df_analyze ();
+
if (c6x_flag_schedule_insns2)
{
int sz = get_max_uid () * 3 / 2 + 1;
@@ -6537,6 +6809,12 @@ c6x_debug_unwind_info (void)
#undef TARGET_ARM_EABI_UNWINDER
#define TARGET_ARM_EABI_UNWINDER true
+#undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY
+#define TARGET_ASM_EMIT_EXCEPT_PERSONALITY c6x_asm_emit_except_personality
+
+#undef TARGET_ASM_INIT_SECTIONS
+#define TARGET_ASM_INIT_SECTIONS c6x_asm_init_sections
+
#undef TARGET_DEBUG_UNWIND_INFO
#define TARGET_DEBUG_UNWIND_INFO c6x_debug_unwind_info
diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md
index c2196ac6fe2..ec3d04e90ac 100644
--- a/gcc/config/c6x/c6x.md
+++ b/gcc/config/c6x/c6x.md
@@ -166,6 +166,17 @@
"n,y"
(const_string "n"))
+;; This describes the relationship between operands and register files.
+;; For example, "sxs" means that operands 0 and 2 determine the side of
+;; the machine, and operand 1 can optionally use the cross path. "dt" and
+;; "td" are used to describe loads and stores.
+;; Used for register renaming in loops for improving modulo scheduling.
+(define_attr "op_pattern"
+ "unknown,dt,td,sx,sxs,ssx"
+ (cond [(eq_attr "type" "load") (const_string "td")
+ (eq_attr "type" "store") (const_string "dt")]
+ (const_string "unknown")))
+
(define_attr "has_shadow"
"n,y"
(const_string "n"))
@@ -567,6 +578,7 @@
%|%.\\tadda%D2\\t%$\\t%1, %2, %0"
[(set_attr "units" "d")
(set_attr "cross" "y,n")
+ (set_attr "op_pattern" "unknown")
(set_attr "predicable" "no")])
;; Move instruction patterns
@@ -599,6 +611,7 @@
[(set_attr "type" "*,*,*,*,*,*,load,load,load,load,store,store,store,store")
(set_attr "units62" "dls,dls,ls,ls,s,s,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
(set_attr "units64" "dls,dls,ls,ls,dl,s,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
+ (set_attr "op_pattern" "sx,sx,sx,sx,*,*,*,*,*,*,*,*,*,*")
(set_attr "addr_regfile" "*,*,*,*,*,*,a,b,b,a,a,b,b,a")
(set_attr "dest_regfile" "*,*,*,*,*,*,a,a,b,b,a,a,b,b")
(set_attr "cross" "n,n,y,y,n,n,n,y,n,y,n,y,n,y")])
@@ -631,6 +644,7 @@
[(set_attr "type" "*,*,*,*,*,*,*,*,*,load,load,load,load,store,store,store,store")
(set_attr "units62" "dls,dls,ls,ls,s,s,d,d,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
(set_attr "units64" "dls,dls,ls,ls,dl,s,d,d,*,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr,d_addr")
+ (set_attr "op_pattern" "sx,sx,sx,sx,*,*,*,*,*,*,*,*,*,*,*,*,*")
(set_attr "addr_regfile" "*,*,*,*,*,*,*,*,*,a,b,b,a,a,b,b,a")
(set_attr "dest_regfile" "*,*,*,*,*,*,*,*,*,a,a,b,b,a,a,b,b")
(set_attr "cross" "n,n,y,y,n,n,y,n,*,n,y,n,y,n,y,n,y")
@@ -855,7 +869,7 @@
(define_insn "<ext_name><mode>si2"
[(set (match_operand:SI 0 "register_operand" "=a,b,a,?a, b,?b")
- (any_ext: SI (match_operand:QIHIM 1 "nonimmediate_operand" "a,b,Q, R, R, Q")))]
+ (any_ext:SI (match_operand:QIHIM 1 "nonimmediate_operand" "a,b,Q, R, R, Q")))]
""
"@
%|%.\\text<u>\\t%$\\t%1, <ext_shift>, <ext_shift>, %0
diff --git a/gcc/config/c6x/t-c6x-elf b/gcc/config/c6x/t-c6x-elf
index 030a39ce18c..be52588ea30 100644
--- a/gcc/config/c6x/t-c6x-elf
+++ b/gcc/config/c6x/t-c6x-elf
@@ -18,25 +18,8 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = c6x/lib1funcs.asm
-LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3 _udivmodsi4 _divmodsi4
-LIB1ASMFUNCS += _strasgi _strasgi_64plus _clzsi2 _clzdi2 _clz
-LIB1ASMFUNCS += _push_rts _pop_rts _call_stub
-
-LIB2FUNCS_EXCLUDE = _cmpdi2 _ucmpdi2 _gcc_bcmp _eprintf _clzsi _clzdi
EXTRA_HEADERS += $(srcdir)/ginclude/unwind-arm-common.h
-LIB2FUNCS_EXTRA = $(srcdir)/config/c6x/gef.c \
- $(srcdir)/config/c6x/gtf.c \
- $(srcdir)/config/c6x/lef.c \
- $(srcdir)/config/c6x/ltf.c \
- $(srcdir)/config/c6x/eqf.c \
- $(srcdir)/config/c6x/ged.c \
- $(srcdir)/config/c6x/gtd.c \
- $(srcdir)/config/c6x/led.c \
- $(srcdir)/config/c6x/ltd.c \
- $(srcdir)/config/c6x/eqd.c
-
# Use this variant for fully testing all CPU types
#MULTILIB_OPTIONS = mbig-endian march=c674x/march=c64x/march=c67x/march=c67x+/march=c62x
#MULTILIB_DIRNAMES = be c674x c64x c67x c67x+ c62x
@@ -45,23 +28,3 @@ MULTILIB_OPTIONS = mbig-endian march=c674x
MULTILIB_DIRNAMES = be c674x
MULTILIB_EXCEPTIONS =
MULTILIB_MATCHES =
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/c6x/crti.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o $(CRTSTUFF_T_CFLAGS) -x assembler-with-cpp \
- $(srcdir)/config/c6x/crti.s
-
-$(T)crtn.o: $(srcdir)/config/c6x/crtn.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o $(CRTSTUFF_T_CFLAGS) -x assembler-with-cpp \
- $(srcdir)/config/c6x/crtn.s
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o
-
-# Avoid failures when the user's GOT becomes too large.
-CRTSTUFF_T_CFLAGS = -msdata=none
-CRTSTUFF_T_CFLAGS_S = -msdata=none
-TARGET_LIBGCC2_CFLAGS = -msdata=none
-
-SHLIB_MAPFILES += $(srcdir)/config/c6x/libgcc-c6xeabi.ver
diff --git a/gcc/config/c6x/t-c6x-uclinux b/gcc/config/c6x/t-c6x-uclinux
index fdc447ac62c..e4b93908f43 100644
--- a/gcc/config/c6x/t-c6x-uclinux
+++ b/gcc/config/c6x/t-c6x-uclinux
@@ -1,7 +1,3 @@
MULTILIB_OSDIRNAMES = march.c674x=!c674x
MULTILIB_OSDIRNAMES += mbig-endian=!be
MULTILIB_OSDIRNAMES += mbig-endian/march.c674x=!be/c674x
-
-CRTSTUFF_T_CFLAGS = -fPIC -msdata=none
-CRTSTUFF_T_CFLAGS_S = -fPIC -msdata=none
-TARGET_LIBGCC2_CFLAGS = -fPIC -msdata=none
diff --git a/gcc/config/cris/cris-protos.h b/gcc/config/cris/cris-protos.h
index f37927e1971..291981d5707 100644
--- a/gcc/config/cris/cris-protos.h
+++ b/gcc/config/cris/cris-protos.h
@@ -33,8 +33,13 @@ extern bool cris_cc0_user_requires_cmp (rtx);
extern rtx cris_return_addr_rtx (int, rtx);
extern rtx cris_split_movdx (rtx *);
extern int cris_legitimate_pic_operand (rtx);
-extern enum cris_pic_symbol_type cris_pic_symbol_type_of (rtx);
-extern bool cris_valid_pic_const (rtx, bool);
+extern enum cris_pic_symbol_type cris_pic_symbol_type_of (const_rtx);
+extern bool cris_valid_pic_const (const_rtx, bool);
+extern bool cris_constant_index_p (const_rtx);
+extern bool cris_base_p (const_rtx, bool);
+extern bool cris_base_or_autoincr_p (const_rtx, bool);
+extern bool cris_bdap_index_p (const_rtx, bool);
+extern bool cris_biap_index_p (const_rtx, bool);
extern bool cris_store_multiple_op_p (rtx);
extern bool cris_movem_load_rest_p (rtx, int);
extern void cris_asm_output_symbol_ref (FILE *, rtx);
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 35ecaa8e2fd..4a08ae03aee 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -125,6 +125,8 @@ static void cris_init_libfuncs (void);
static reg_class_t cris_preferred_reload_class (rtx, reg_class_t);
+static bool cris_legitimate_address_p (enum machine_mode, rtx, bool);
+
static int cris_register_move_cost (enum machine_mode, reg_class_t, reg_class_t);
static int cris_memory_move_cost (enum machine_mode, reg_class_t, bool);
static bool cris_rtx_costs (rtx, int, int, int, int *, bool);
@@ -200,6 +202,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS cris_init_libfuncs
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P cris_legitimate_address_p
+
#undef TARGET_PREFERRED_RELOAD_CLASS
#define TARGET_PREFERRED_RELOAD_CLASS cris_preferred_reload_class
@@ -1122,7 +1127,7 @@ cris_print_operand_address (FILE *file, rtx x)
if (CONSTANT_ADDRESS_P (x))
cris_output_addr_const (file, x);
- else if (BASE_OR_AUTOINCR_P (x))
+ else if (cris_base_or_autoincr_p (x, true))
cris_print_base (x, file);
else if (GET_CODE (x) == PLUS)
{
@@ -1130,12 +1135,12 @@ cris_print_operand_address (FILE *file, rtx x)
x1 = XEXP (x, 0);
x2 = XEXP (x, 1);
- if (BASE_P (x1))
+ if (cris_base_p (x1, true))
{
cris_print_base (x1, file);
cris_print_index (x2, file);
}
- else if (BASE_P (x2))
+ else if (cris_base_p (x2, true))
{
cris_print_base (x2, file);
cris_print_index (x1, file);
@@ -1272,6 +1277,136 @@ cris_initial_elimination_offset (int fromreg, int toreg)
gcc_unreachable ();
}
+/* Nonzero if X is a hard reg that can be used as an index. */
+static inline bool
+reg_ok_for_base_p (const_rtx x, bool strict)
+{
+ return ((! strict && ! HARD_REGISTER_P (x))
+ || REGNO_OK_FOR_BASE_P (REGNO (x)));
+}
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+static inline bool
+reg_ok_for_index_p (const_rtx x, bool strict)
+{
+ return reg_ok_for_base_p (x, strict);
+}
+
+/* No symbol can be used as an index (or more correct, as a base) together
+ with a register with PIC; the PIC register must be there. */
+
+bool
+cris_constant_index_p (const_rtx x)
+{
+ return (CONSTANT_P (x) && (!flag_pic || cris_valid_pic_const (x, true)));
+}
+
+/* True if X is a valid base register. */
+
+bool
+cris_base_p (const_rtx x, bool strict)
+{
+ return (REG_P (x) && reg_ok_for_base_p (x, strict));
+}
+
+/* True if X is a valid index register. */
+
+static inline bool
+cris_index_p (const_rtx x, bool strict)
+{
+ return (REG_P (x) && reg_ok_for_index_p (x, strict));
+}
+
+/* True if X is a valid base register with or without autoincrement. */
+
+bool
+cris_base_or_autoincr_p (const_rtx x, bool strict)
+{
+ return (cris_base_p (x, strict)
+ || (GET_CODE (x) == POST_INC
+ && cris_base_p (XEXP (x, 0), strict)
+ && REGNO (XEXP (x, 0)) != CRIS_ACR_REGNUM));
+}
+
+/* True if X is a valid (register) index for BDAP, i.e. [Rs].S or [Rs+].S. */
+
+bool
+cris_bdap_index_p (const_rtx x, bool strict)
+{
+ return ((MEM_P (x)
+ && GET_MODE (x) == SImode
+ && cris_base_or_autoincr_p (XEXP (x, 0), strict))
+ || (GET_CODE (x) == SIGN_EXTEND
+ && MEM_P (XEXP (x, 0))
+ && (GET_MODE (XEXP (x, 0)) == HImode
+ || GET_MODE (XEXP (x, 0)) == QImode)
+ && cris_base_or_autoincr_p (XEXP (XEXP (x, 0), 0), strict)));
+}
+
+/* True if X is a valid (register) index for BIAP, i.e. Rd.m. */
+
+bool
+cris_biap_index_p (const_rtx x, bool strict)
+{
+ return (cris_index_p (x, strict)
+ || (GET_CODE (x) == MULT
+ && cris_index_p (XEXP (x, 0), strict)
+ && cris_scale_int_operand (XEXP (x, 1), VOIDmode)));
+}
+
+/* Worker function for TARGET_LEGITIMATE_ADDRESS_P.
+
+ A PIC operand looks like a normal symbol here. At output we dress it
+ in "[rPIC+symbol:GOT]" (global symbol) or "rPIC+symbol:GOTOFF" (local
+ symbol) so we exclude all addressing modes where we can't replace a
+ plain "symbol" with that. A global PIC symbol does not fit anywhere
+ here (but is thankfully a general_operand in itself). A local PIC
+ symbol is valid for the plain "symbol + offset" case. */
+
+static bool
+cris_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
+{
+ const_rtx x1, x2;
+
+ if (cris_base_or_autoincr_p (x, strict))
+ return true;
+ else if (TARGET_V32)
+ /* Nothing else is valid then. */
+ return false;
+ else if (cris_constant_index_p (x))
+ return true;
+ /* Indexed? */
+ else if (GET_CODE (x) == PLUS)
+ {
+ x1 = XEXP (x, 0);
+ x2 = XEXP (x, 1);
+ /* BDAP o, Rd. */
+ if ((cris_base_p (x1, strict) && cris_constant_index_p (x2))
+ || (cris_base_p (x2, strict) && cris_constant_index_p (x1))
+ /* BDAP Rs[+], Rd. */
+ || (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+ && ((cris_base_p (x1, strict)
+ && cris_bdap_index_p (x2, strict))
+ || (cris_base_p (x2, strict)
+ && cris_bdap_index_p (x1, strict))
+ /* BIAP.m Rs, Rd */
+ || (cris_base_p (x1, strict)
+ && cris_biap_index_p (x2, strict))
+ || (cris_base_p (x2, strict)
+ && cris_biap_index_p (x1, strict)))))
+ return true;
+ }
+ else if (MEM_P (x))
+ {
+ /* DIP (Rs). Reject [[reg+]] and [[reg]] for DImode (long long). */
+ if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+ && cris_base_or_autoincr_p (XEXP (x, 0), strict))
+ return true;
+ }
+
+ return false;
+}
+
/* Worker function for LEGITIMIZE_RELOAD_ADDRESS. */
bool
@@ -1860,7 +1995,7 @@ cris_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
FIXME: this case is a stop-gap for 4.3 and 4.4, this whole
function should be rewritten. */
- if (outer_code == PLUS && BIAP_INDEX_P (x))
+ if (outer_code == PLUS && cris_biap_index_p (x, false))
{
*total = 0;
return true;
@@ -1942,7 +2077,7 @@ cris_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
loop there, without apparent reason. */
/* The cheapest addressing modes get 0, since nothing extra is needed. */
- if (BASE_OR_AUTOINCR_P (x))
+ if (cris_base_or_autoincr_p (x, false))
return 0;
/* An indirect mem must be a DIP. This means two bytes extra for code,
@@ -1972,7 +2107,7 @@ cris_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
/* A BIAP is 2 extra bytes for the prefix insn, nothing more. We
recognize the typical MULT which is always in tem1 because of
insn canonicalization. */
- if ((GET_CODE (tem1) == MULT && BIAP_INDEX_P (tem1))
+ if ((GET_CODE (tem1) == MULT && cris_biap_index_p (tem1, false))
|| REG_P (tem2))
return 2 / 2;
@@ -2030,12 +2165,12 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
/* The operands may be swapped. Canonicalize them in reg_rtx and
val_rtx, where reg_rtx always is a reg (for this constraint to
match). */
- if (! BASE_P (reg_rtx))
+ if (! cris_base_p (reg_rtx, reload_in_progress || reload_completed))
reg_rtx = val_rtx, val_rtx = ops[rreg];
/* Don't forget to check that reg_rtx really is a reg. If it isn't,
we have no business. */
- if (! BASE_P (reg_rtx))
+ if (! cris_base_p (reg_rtx, reload_in_progress || reload_completed))
return 0;
/* Don't do this when -mno-split. */
@@ -2060,8 +2195,9 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
/* Check if the lvalue register is the same as the "other
operand". If so, the result is undefined and we shouldn't do
this. FIXME: Check again. */
- if ((BASE_P (ops[lreg])
- && BASE_P (ops[other_op])
+ if ((cris_base_p (ops[lreg], reload_in_progress || reload_completed)
+ && cris_base_p (ops[other_op],
+ reload_in_progress || reload_completed)
&& REGNO (ops[lreg]) == REGNO (ops[other_op]))
|| rtx_equal_p (ops[other_op], ops[lreg]))
return 0;
@@ -2074,7 +2210,7 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
return 0;
if (code == PLUS
- && ! BASE_P (val_rtx))
+ && ! cris_base_p (val_rtx, reload_in_progress || reload_completed))
{
/* Do not allow rx = rx + n if a normal add or sub with same size
@@ -2088,19 +2224,24 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
if (CONSTANT_P (val_rtx))
return 1;
- if (MEM_P (val_rtx) && BASE_OR_AUTOINCR_P (XEXP (val_rtx, 0)))
+ if (MEM_P (val_rtx)
+ && cris_base_or_autoincr_p (XEXP (val_rtx, 0),
+ reload_in_progress || reload_completed))
return 1;
if (GET_CODE (val_rtx) == SIGN_EXTEND
&& MEM_P (XEXP (val_rtx, 0))
- && BASE_OR_AUTOINCR_P (XEXP (XEXP (val_rtx, 0), 0)))
+ && cris_base_or_autoincr_p (XEXP (XEXP (val_rtx, 0), 0),
+ reload_in_progress || reload_completed))
return 1;
/* If we got here, it's not a valid addressing mode. */
return 0;
}
else if (code == MULT
- || (code == PLUS && BASE_P (val_rtx)))
+ || (code == PLUS
+ && cris_base_p (val_rtx,
+ reload_in_progress || reload_completed)))
{
/* Do not allow rx = rx + ry.S, since it doesn't give better code. */
if (rtx_equal_p (ops[lreg], reg_rtx)
@@ -2112,7 +2253,7 @@ cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
return 0;
/* Only allow r + ... */
- if (! BASE_P (reg_rtx))
+ if (! cris_base_p (reg_rtx, reload_in_progress || reload_completed))
return 0;
/* If we got here, all seems ok.
@@ -2202,7 +2343,7 @@ cris_target_asm_named_section (const char *name, unsigned int flags,
elsewhere. */
bool
-cris_valid_pic_const (rtx x, bool any_operand)
+cris_valid_pic_const (const_rtx x, bool any_operand)
{
gcc_assert (flag_pic);
@@ -2252,7 +2393,7 @@ cris_valid_pic_const (rtx x, bool any_operand)
given the original (non-PIC) representation. */
enum cris_pic_symbol_type
-cris_pic_symbol_type_of (rtx x)
+cris_pic_symbol_type_of (const_rtx x)
{
switch (GET_CODE (x))
{
diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h
index 4c28e4530ab..135b03bb1a4 100644
--- a/gcc/config/cris/cris.h
+++ b/gcc/config/cris/cris.h
@@ -84,11 +84,7 @@ extern int cris_cpu_version;
/* Changing the order used to be necessary to put the fourth __make_dp
argument (a DImode parameter) in registers, to fit with the libfunc
parameter passing scheme used for intrinsic functions. FIXME: Check
- performance and maybe remove definition from TARGET_LIBGCC2_CFLAGS now
- that it isn't strictly necessary. We used to do this through
- TARGET_LIBGCC2_CFLAGS, but that became increasingly difficult as the
- parenthesis (that needed quoting) travels through several layers of
- make and shell invocations. */
+ performance. */
#ifdef IN_LIBGCC2
#define __make_dp(a,b,c,d) __cris_make_dp(d,a,b,c)
#endif
@@ -676,17 +672,18 @@ enum reg_class
/* Just an indirect register (happens to also be \
"all" slottable memory addressing modes not \
covered by other constraints, i.e. '>'). */ \
- MEM_P (X) && BASE_P (XEXP (X, 0)) \
+ MEM_P (X) \
+ && cris_base_p (XEXP (X, 0), reload_in_progress || reload_completed) \
)
#define EXTRA_CONSTRAINT_R(X) \
( \
/* An operand to BDAP or BIAP: \
A BIAP; r.S? */ \
- BIAP_INDEX_P (X) \
+ cris_biap_index_p (X, reload_in_progress || reload_completed) \
/* A [reg] or (int) [reg], maybe with post-increment. */ \
- || BDAP_INDEX_P (X) \
- || CONSTANT_INDEX_P (X) \
+ || cris_bdap_index_p (X, reload_in_progress || reload_completed) \
+ || cris_constant_index_p (X) \
)
#define EXTRA_CONSTRAINT_T(X) \
@@ -695,25 +692,33 @@ enum reg_class
MEM_P (X) \
&& ((MEM_P (XEXP (X, 0)) \
/* Double indirect: [[reg]] or [[reg+]]? */ \
- && (BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0)))) \
+ && (cris_base_or_autoincr_p (XEXP (XEXP (X, 0), 0), \
+ reload_in_progress || reload_completed))) \
/* Just an explicit indirect reference: [const]? */ \
|| CONSTANT_P (XEXP (X, 0)) \
/* Something that is indexed; [...+...]? */ \
|| (GET_CODE (XEXP (X, 0)) == PLUS \
/* A BDAP constant: [reg+(8|16|32)bit offset]? */ \
- && ((BASE_P (XEXP (XEXP (X, 0), 0)) \
- && CONSTANT_INDEX_P (XEXP (XEXP (X, 0), 1))) \
+ && ((cris_base_p (XEXP (XEXP (X, 0), 0), \
+ reload_in_progress || reload_completed) \
+ && cris_constant_index_p (XEXP (XEXP (X, 0), 1))) \
/* A BDAP register: [reg+[reg(+)].S]? */ \
- || (BASE_P (XEXP (XEXP (X, 0), 0)) \
- && BDAP_INDEX_P(XEXP(XEXP(X, 0), 1))) \
+ || (cris_base_p (XEXP (XEXP (X, 0), 0), \
+ reload_in_progress || reload_completed) \
+ && cris_bdap_index_p (XEXP(XEXP(X, 0), 1), \
+ reload_in_progress || reload_completed)) \
/* Same, but with swapped arguments (no canonical \
ordering between e.g. REG and MEM as of LAST_UPDATED \
"Thu May 12 03:59:11 UTC 2005"). */ \
- || (BASE_P (XEXP (XEXP (X, 0), 1)) \
- && BDAP_INDEX_P (XEXP (XEXP (X, 0), 0))) \
+ || (cris_base_p (XEXP (XEXP (X, 0), 1), \
+ reload_in_progress | reload_completed) \
+ && cris_bdap_index_p (XEXP (XEXP (X, 0), 0), \
+ reload_in_progress || reload_completed)) \
/* A BIAP: [reg+reg.S] (MULT comes first). */ \
- || (BASE_P (XEXP (XEXP (X, 0), 1)) \
- && BIAP_INDEX_P (XEXP (XEXP (X, 0), 0)))))) \
+ || (cris_base_p (XEXP (XEXP (X, 0), 1), \
+ reload_in_progress || reload_completed) \
+ && cris_biap_index_p (XEXP (XEXP (X, 0), 0), \
+ reload_in_progress || reload_completed))))) \
)
/* PIC-constructs for symbols. */
@@ -888,118 +893,6 @@ struct cum_args {int regs;};
among all CRIS variants. */
#define MAX_REGS_PER_ADDRESS 2
-/* There are helper macros defined here which are used only in
- GO_IF_LEGITIMATE_ADDRESS.
-
- Note that you *have to* reject invalid addressing modes for mode
- MODE, even if it is legal for normal addressing modes. You cannot
- rely on the constraints to do this work. They can only be used to
- doublecheck your intentions. One example is that you HAVE TO reject
- (mem:DI (plus:SI (reg:SI x) (reg:SI y))) because for some reason
- this cannot be reloaded. (Which of course you can argue that gcc
- should have done.) FIXME: Strange. Check. */
-
-/* No symbol can be used as an index (or more correct, as a base) together
- with a register with PIC; the PIC register must be there. */
-#define CONSTANT_INDEX_P(X) \
- (CONSTANT_P (X) && (!flag_pic || cris_valid_pic_const (X, true)))
-
-/* True if X is a valid base register. */
-#define BASE_P(X) \
- (REG_P (X) && REG_OK_FOR_BASE_P (X))
-
-/* True if X is a valid base register with or without autoincrement. */
-#define BASE_OR_AUTOINCR_P(X) \
- (BASE_P (X) \
- || (GET_CODE (X) == POST_INC \
- && BASE_P (XEXP (X, 0)) \
- && REGNO (XEXP (X, 0)) != CRIS_ACR_REGNUM))
-
-/* True if X is a valid (register) index for BDAP, i.e. [Rs].S or [Rs+].S. */
-#define BDAP_INDEX_P(X) \
- ((MEM_P (X) && GET_MODE (X) == SImode \
- && BASE_OR_AUTOINCR_P (XEXP (X, 0))) \
- || (GET_CODE (X) == SIGN_EXTEND \
- && MEM_P (XEXP (X, 0)) \
- && (GET_MODE (XEXP (X, 0)) == HImode \
- || GET_MODE (XEXP (X, 0)) == QImode) \
- && BASE_OR_AUTOINCR_P (XEXP (XEXP (X, 0), 0))))
-
-/* True if X is a valid (register) index for BIAP, i.e. Rd.m. */
-#define BIAP_INDEX_P(X) \
- ((BASE_P (X) && REG_OK_FOR_INDEX_P (X)) \
- || (GET_CODE (X) == MULT \
- && BASE_P (XEXP (X, 0)) \
- && REG_OK_FOR_INDEX_P (XEXP (X, 0)) \
- && CONST_INT_P (XEXP (X, 1)) \
- && (INTVAL (XEXP (X, 1)) == 2 \
- || INTVAL (XEXP (X, 1)) == 4)))
-
-/* A PIC operand looks like a normal symbol here. At output we dress it
- in "[rPIC+symbol:GOT]" (global symbol) or "rPIC+symbol:GOTOFF" (local
- symbol) so we exclude all addressing modes where we can't replace a
- plain "symbol" with that. A global PIC symbol does not fit anywhere
- here (but is thankfully a general_operand in itself). A local PIC
- symbol is valid for the plain "symbol + offset" case. */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- { \
- rtx x1, x2; \
- if (BASE_OR_AUTOINCR_P (X)) \
- goto ADDR; \
- else if (TARGET_V32) \
- /* Nothing else is valid then. */ \
- ; \
- else if (CONSTANT_INDEX_P (X)) \
- goto ADDR; \
- /* Indexed? */ \
- else if (GET_CODE (X) == PLUS) \
- { \
- x1 = XEXP (X, 0); \
- x2 = XEXP (X, 1); \
- /* BDAP o, Rd. */ \
- if ((BASE_P (x1) && CONSTANT_INDEX_P (x2)) \
- || (BASE_P (x2) && CONSTANT_INDEX_P (x1)) \
- /* BDAP Rs[+], Rd. */ \
- || (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \
- && ((BASE_P (x1) && BDAP_INDEX_P (x2)) \
- || (BASE_P (x2) && BDAP_INDEX_P (x1)) \
- /* BIAP.m Rs, Rd */ \
- || (BASE_P (x1) && BIAP_INDEX_P (x2)) \
- || (BASE_P (x2) && BIAP_INDEX_P (x1))))) \
- goto ADDR; \
- } \
- else if (MEM_P (X)) \
- { \
- /* DIP (Rs). Reject [[reg+]] and [[reg]] for \
- DImode (long long). */ \
- if (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD \
- && (BASE_P (XEXP (X, 0)) \
- || BASE_OR_AUTOINCR_P (XEXP (X, 0)))) \
- goto ADDR; \
- } \
- }
-
-#ifndef REG_OK_STRICT
- /* Nonzero if X is a hard reg that can be used as a base reg
- or if it is a pseudo reg. */
-# define REG_OK_FOR_BASE_P(X) \
- (REGNO (X) <= CRIS_LAST_GENERAL_REGISTER \
- || REGNO (X) == ARG_POINTER_REGNUM \
- || REGNO (X) >= FIRST_PSEUDO_REGISTER)
-#else
- /* Nonzero if X is a hard reg that can be used as a base reg. */
-# define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
-#endif
-
-#ifndef REG_OK_STRICT
- /* Nonzero if X is a hard reg that can be used as an index
- or if it is a pseudo reg. */
-# define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
-#else
- /* Nonzero if X is a hard reg that can be used as an index. */
-# define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
-#endif
-
/* Fix reloads known to cause suboptimal spilling. */
#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, INDL, WIN) \
do \
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index 592bbadf489..428132c2eb4 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -4680,7 +4680,7 @@
(match_operator 4 "cris_mem_op" [(match_dup 0)]))]
"GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
&& REGNO (operands[3]) != REGNO (operands[0])
- && (BASE_P (operands[1]) || BASE_P (operands[2]))
+ && (cris_base_p (operands[1], true) || cris_base_p (operands[2], true))
&& !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
&& !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
&& (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
@@ -4716,7 +4716,7 @@
(match_operand 4 "register_operand" ""))]
"GET_MODE_SIZE (GET_MODE (operands[4])) <= UNITS_PER_WORD
&& REGNO (operands[4]) != REGNO (operands[0])
- && (BASE_P (operands[1]) || BASE_P (operands[2]))
+ && (cris_base_p (operands[1], true) || cris_base_p (operands[2], true))
&& !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')
&& !CRIS_CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N')
&& (INTVAL (operands[2]) >= -128 && INTVAL (operands[2]) < 128)
diff --git a/gcc/config/cris/cris_abi_symbol.c b/gcc/config/cris/cris_abi_symbol.c
deleted file mode 100644
index db9db2cfe56..00000000000
--- a/gcc/config/cris/cris_abi_symbol.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Define symbol to recognize CRIS ABI version 2, for a.out use.
- Contributed by Axis Communications.
- Written by Hans-Peter Nilsson <hp@axis.se>, c:a 1992.
-
- Copyright (C) 2000, 2001, 2003, 2009 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 3, or (at your option) any
-later version.
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "tconfig.h"
-#include "tm.h"
-
-#ifdef __AOUT__
-
-/* ELF support was not released before the ABI was changed, so we
- restrict this awkwardness to a.out. This symbol is for gdb to
- recognize, so it can debug both old and new programs successfully. */
-__asm__ (".global " CRIS_ABI_VERSION_SYMBOL_STRING);
-__asm__ (".set " CRIS_ABI_VERSION_SYMBOL_STRING ",0");
-
-#else /* not __AOUT__ */
-
-/* The file must not be empty (declaration/definition-wise) according to
- ISO, IIRC. */
-extern int _Dummy;
-
-#endif /* not __AOUT__ */
diff --git a/gcc/config/cris/t-cris b/gcc/config/cris/t-cris
index 19d44ce8320..fdaa54e5ce3 100644
--- a/gcc/config/cris/t-cris
+++ b/gcc/config/cris/t-cris
@@ -25,17 +25,5 @@
# section "Target Fragment" in the gcc info-files (or the paper copy) of
# "Using and Porting GCC"
-LIB2FUNCS_EXTRA = _udivsi3.c _divsi3.c _umodsi3.c _modsi3.c
-CRIS_LIB1CSRC = $(srcdir)/config/cris/arit.c
-
-# The fixed-point arithmetic code is in one file, arit.c,
-# similar to libgcc2.c (or the old libgcc1.c). We need to
-# "split it up" with one file per define.
-$(LIB2FUNCS_EXTRA): $(CRIS_LIB1CSRC)
- name=`echo $@ | sed -e 's,.*/,,' | sed -e 's,.c$$,,'`; \
- echo "#define L$$name" > tmp-$@ \
- && echo '#include "$<"' >> tmp-$@ \
- && mv -f tmp-$@ $@
-
$(out_object_file): gt-cris.h
gt-cris.h : s-gtype ; @true
diff --git a/gcc/config/cris/t-elfmulti b/gcc/config/cris/t-elfmulti
index 90eeaaedf44..29ed57dec2f 100644
--- a/gcc/config/cris/t-elfmulti
+++ b/gcc/config/cris/t-elfmulti
@@ -16,7 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/cris/mulsi3.asm
MULTILIB_OPTIONS = march=v10/march=v32
MULTILIB_DIRNAMES = v10 v32
MULTILIB_MATCHES = \
@@ -29,6 +28,3 @@ MULTILIB_MATCHES = \
march?v10=mcpu?v10 \
march?v32=mcpu?v32
MULTILIB_EXTRA_OPTS = mbest-lib-options
-INSTALL_LIBGCC = install-multilib
-LIBGCC = stmp-multilib
-CRTSTUFF_T_CFLAGS = -moverride-best-lib-options
diff --git a/gcc/config/cris/t-linux b/gcc/config/cris/t-linux
index 96e861a4283..71a964936db 100644
--- a/gcc/config/cris/t-linux
+++ b/gcc/config/cris/t-linux
@@ -1,7 +1,3 @@
-TARGET_LIBGCC2_CFLAGS += -fPIC
-CRTSTUFF_T_CFLAGS_S = $(TARGET_LIBGCC2_CFLAGS)
-SHLIB_MAPFILES += $(srcdir)/config/cris/libgcc.ver
-
# We *know* we have a limits.h in the glibc library, with extra
# definitions needed for e.g. libgfortran.
ifneq ($(inhibit_libc),true)
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index d8e5cd974a2..7c33a533fff 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -1753,19 +1753,51 @@ darwin_label_is_anonymous_local_objc_name (const char *name)
return (!strncmp ((const char *)p, "_OBJC_", 6));
}
-/* LTO support for Mach-O. */
+/* LTO support for Mach-O.
-/* Section names for LTO sections. */
-static unsigned int lto_section_names_offset = 0;
+ This version uses three mach-o sections to encapsulate the (unlimited
+ number of) lto sections.
-/* This is the obstack which we use to allocate the many strings. */
-static struct obstack lto_section_names_obstack;
+ __GNU_LTO, __lto_sections contains the concatented GNU LTO section data.
+ __GNU_LTO, __section_names contains the GNU LTO section names.
+ __GNU_LTO, __section_index contains an array of values that index these.
-/* Segment name for LTO sections. */
+ Indexed thus:
+ <section offset from the start of __GNU_LTO, __lto_sections>,
+ <section length>
+ <name offset from the start of __GNU_LTO, __section_names,
+ <name length>.
+
+ At present, for both m32 and m64 mach-o files each of these fields is
+ represented by a uint32_t. This is because, AFAICT, a mach-o object
+ cannot exceed 4Gb because the section_64 offset field (see below) is 32bits.
+
+ uint32_t offset;
+ "offset An integer specifying the offset to this section in the file." */
+
+/* Count lto section numbers. */
+static unsigned int lto_section_num = 0;
+
+/* A vector of information about LTO sections, at present, we only have
+ the name. TODO: see if we can get the data length somehow. */
+typedef struct GTY (()) darwin_lto_section_e {
+ const char *sectname;
+} darwin_lto_section_e ;
+DEF_VEC_O(darwin_lto_section_e);
+DEF_VEC_ALLOC_O(darwin_lto_section_e, gc);
+
+static GTY (()) VEC (darwin_lto_section_e, gc) * lto_section_names;
+
+/* Segment for LTO data. */
#define LTO_SEGMENT_NAME "__GNU_LTO"
-/* Section name for LTO section names section. */
-#define LTO_NAMES_SECTION "__section_names"
+/* Section wrapper scheme (used here to wrap the unlimited number of LTO
+ sections into three Mach-O ones).
+ NOTE: These names MUST be kept in sync with those in
+ libiberty/simple-object-mach-o. */
+#define LTO_SECTS_SECTION "__wrapper_sects"
+#define LTO_NAMES_SECTION "__wrapper_names"
+#define LTO_INDEX_SECTION "__wrapper_index"
/* File to temporarily store LTO data. This is appended to asm_out_file
in darwin_end_file. */
@@ -1808,37 +1840,38 @@ darwin_asm_named_section (const char *name,
unsigned int flags,
tree decl ATTRIBUTE_UNUSED)
{
- /* LTO sections go in a special segment __GNU_LTO. We want to replace the
- section name with something we can use to represent arbitrary-length
- names (section names in Mach-O are at most 16 characters long). */
+ /* LTO sections go in a special section that encapsulates the (unlimited)
+ number of GNU LTO sections within a single mach-o one. */
if (strncmp (name, LTO_SECTION_NAME_PREFIX,
strlen (LTO_SECTION_NAME_PREFIX)) == 0)
{
+ darwin_lto_section_e e;
/* We expect certain flags to be set... */
gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
== (SECTION_DEBUG | SECTION_NAMED));
- /* Add the section name to the things to output when we end the
- current assembler output file.
- This is all not very efficient, but that doesn't matter -- this
- shouldn't be a hot path in the compiler... */
- obstack_1grow (&lto_section_names_obstack, '\t');
- obstack_grow (&lto_section_names_obstack, ".ascii ", 7);
- obstack_1grow (&lto_section_names_obstack, '"');
- obstack_grow (&lto_section_names_obstack, name, strlen (name));
- obstack_grow (&lto_section_names_obstack, "\\0\"\n", 4);
-
- /* Output the dummy section name. */
- fprintf (asm_out_file, "\t# %s\n", name);
- fprintf (asm_out_file, "\t.section %s,__%08X,regular,debug\n",
- LTO_SEGMENT_NAME, lto_section_names_offset);
-
- /* Update the offset for the next section name. Make sure we stay
- within reasonable length. */
- lto_section_names_offset += strlen (name) + 1;
- gcc_assert (lto_section_names_offset > 0
- && lto_section_names_offset < ((unsigned) 1 << 31));
- }
+ /* Switch to our combined section. */
+ fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+ LTO_SEGMENT_NAME, LTO_SECTS_SECTION);
+ /* Output a label for the start of this sub-section. */
+ fprintf (asm_out_file, "L_GNU_LTO%d:\t;# %s\n",
+ lto_section_num, name);
+ /* We have to jump through hoops to get the values of the intra-section
+ offsets... */
+ fprintf (asm_out_file, "\t.set L$gnu$lto$offs%d,L_GNU_LTO%d-L_GNU_LTO0\n",
+ lto_section_num, lto_section_num);
+ fprintf (asm_out_file,
+ "\t.set L$gnu$lto$size%d,L_GNU_LTO%d-L_GNU_LTO%d\n",
+ lto_section_num, lto_section_num+1, lto_section_num);
+ lto_section_num++;
+ e.sectname = xstrdup (name);
+ /* Keep the names, we'll need to make a table later.
+ TODO: check that we do not revisit sections, that would break
+ the assumption of how this is done. */
+ if (lto_section_names == NULL)
+ lto_section_names = VEC_alloc (darwin_lto_section_e, gc, 16);
+ VEC_safe_push (darwin_lto_section_e, gc, lto_section_names, &e);
+ }
else if (strncmp (name, "__DWARF,", 8) == 0)
darwin_asm_dwarf_section (name, flags, decl);
else
@@ -2711,16 +2744,12 @@ darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
darwin_asm_output_dwarf_delta (file, size, lab, sname);
}
-/* Called from the within the TARGET_ASM_FILE_START for each target.
- Initialize the stuff we need for LTO long section names support. */
+/* Called from the within the TARGET_ASM_FILE_START for each target. */
void
darwin_file_start (void)
{
- /* We fill this obstack with the complete section text for the lto section
- names to write in darwin_file_end. */
- obstack_init (&lto_section_names_obstack);
- lto_section_names_offset = 0;
+ /* Nothing to do. */
}
/* Called for the TARGET_ASM_FILE_END hook.
@@ -2731,8 +2760,6 @@ darwin_file_start (void)
void
darwin_file_end (void)
{
- const char *lto_section_names;
-
machopic_finish (asm_out_file);
if (strcmp (lang_hooks.name, "GNU C++") == 0)
{
@@ -2762,6 +2789,13 @@ darwin_file_end (void)
lto_asm_txt = buf = (char *) xmalloc (n + 1);
while (fgets (lto_asm_txt, n, lto_asm_out_file))
fputs (lto_asm_txt, asm_out_file);
+ /* Put a termination label. */
+ fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+ LTO_SEGMENT_NAME, LTO_SECTS_SECTION);
+ fprintf (asm_out_file, "L_GNU_LTO%d:\t;# end of lto\n",
+ lto_section_num);
+ /* Make sure our termination label stays in this section. */
+ fputs ("\t.space\t1\n", asm_out_file);
}
/* Remove the temporary file. */
@@ -2770,21 +2804,50 @@ darwin_file_end (void)
free (lto_asm_out_name);
}
- /* Finish the LTO section names obstack. Don't output anything if
- there are no recorded section names. */
- obstack_1grow (&lto_section_names_obstack, '\0');
- lto_section_names = XOBFINISH (&lto_section_names_obstack, const char *);
- if (strlen (lto_section_names) > 0)
+ /* Output the names and indices. */
+ if (lto_section_names && VEC_length (darwin_lto_section_e, lto_section_names))
{
- fprintf (asm_out_file,
- "\t.section %s,%s,regular,debug\n",
+ int count;
+ darwin_lto_section_e *ref;
+ /* For now, we'll make the offsets 4 bytes and unaligned - we'll fix
+ the latter up ourselves. */
+ const char *op = integer_asm_op (4,0);
+
+ /* Emit the names. */
+ fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
LTO_SEGMENT_NAME, LTO_NAMES_SECTION);
- fprintf (asm_out_file,
- "\t# Section names in %s are offsets into this table\n",
- LTO_SEGMENT_NAME);
- fprintf (asm_out_file, "%s\n", lto_section_names);
+ FOR_EACH_VEC_ELT (darwin_lto_section_e, lto_section_names, count, ref)
+ {
+ fprintf (asm_out_file, "L_GNU_LTO_NAME%d:\n", count);
+ /* We have to jump through hoops to get the values of the intra-section
+ offsets... */
+ fprintf (asm_out_file,
+ "\t.set L$gnu$lto$noff%d,L_GNU_LTO_NAME%d-L_GNU_LTO_NAME0\n",
+ count, count);
+ fprintf (asm_out_file,
+ "\t.set L$gnu$lto$nsiz%d,L_GNU_LTO_NAME%d-L_GNU_LTO_NAME%d\n",
+ count, count+1, count);
+ fprintf (asm_out_file, "\t.asciz\t\"%s\"\n", ref->sectname);
+ }
+ fprintf (asm_out_file, "L_GNU_LTO_NAME%d:\t;# end\n", lto_section_num);
+ /* make sure our termination label stays in this section. */
+ fputs ("\t.space\t1\n", asm_out_file);
+
+ /* Emit the Index. */
+ fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+ LTO_SEGMENT_NAME, LTO_INDEX_SECTION);
+ fputs ("\t.align\t2\n", asm_out_file);
+ fputs ("# Section offset, Section length, Name offset, Name length\n",
+ asm_out_file);
+ FOR_EACH_VEC_ELT (darwin_lto_section_e, lto_section_names, count, ref)
+ {
+ fprintf (asm_out_file, "%s L$gnu$lto$offs%d\t;# %s\n",
+ op, count, ref->sectname);
+ fprintf (asm_out_file, "%s L$gnu$lto$size%d\n", op, count);
+ fprintf (asm_out_file, "%s L$gnu$lto$noff%d\n", op, count);
+ fprintf (asm_out_file, "%s L$gnu$lto$nsiz%d\n", op, count);
+ }
}
- obstack_free (&lto_section_names_obstack, NULL);
/* If we have section anchors, then we must prevent the linker from
re-arranging data. */
@@ -2957,10 +3020,11 @@ darwin_override_options (void)
darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
}
-/* Add $LDBL128 suffix to long double builtins. */
+#if DARWIN_PPC
+/* Add $LDBL128 suffix to long double builtins for ppc darwin. */
static void
-darwin_patch_builtin (int fncode)
+darwin_patch_builtin (enum built_in_function fncode)
{
tree fn = builtin_decl_explicit (fncode);
tree sym;
@@ -2998,6 +3062,7 @@ darwin_patch_builtins (void)
#undef PATCH_BUILTIN_NO64
#undef PATCH_BUILTIN_VARIADIC
}
+#endif
/* CFStrings implementation. */
static GTY(()) tree cfstring_class_reference = NULL_TREE;
diff --git a/gcc/config/fr30/crtn.asm b/gcc/config/fr30/crtn.asm
deleted file mode 100644
index ac2712186c3..00000000000
--- a/gcc/config/fr30/crtn.asm
+++ /dev/null
@@ -1,44 +0,0 @@
-# crtn.asm for ELF
-
-# Copyright (C) 1992, 1999, 2008, 2009 Free Software Foundation, Inc.
-# Written By David Vinayak Henkel-Wallace, June 1992
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file just makes sure that the .fini and .init sections do in
-# fact return. Users may put any desired instructions in those sections.
-# This file is the last thing linked into any executable.
-
- .section ".init"
- .align 4
-
- leave
- ld @r15+,rp
- ret
-
-
- .section ".fini"
- .align 4
-
- leave
- ld @r15+,rp
- ret
-
-# Th-th-th-that is all folks!
diff --git a/gcc/config/fr30/t-fr30 b/gcc/config/fr30/t-fr30
deleted file mode 100644
index fa786d6e50a..00000000000
--- a/gcc/config/fr30/t-fr30
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright (C) 1999, 2001, 2007, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMSRC = fr30/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/fr30/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o $(T)crti.o -x assembler $(srcdir)/config/fr30/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/fr30/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -o $(T)crtn.o -x assembler $(srcdir)/config/fr30/crtn.asm
-
-# If any special flags are necessary when building libgcc2 put them here.
-#
-# TARGET_LIBGCC2_CFLAGS
-
-# 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 =
-# MULTILIB_DIRNAMES =
-# MULTILIB_MATCHES =
-# MULTILIB_EXCEPTIONS =
-# MULTILIB_EXTRA_OPTS =
-#
-# LIBGCC = stmp-multilib
-# INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/frv/t-frv b/gcc/config/frv/t-frv
index 395a679747a..c5c7bdc237c 100644
--- a/gcc/config/frv/t-frv
+++ b/gcc/config/frv/t-frv
@@ -16,66 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# 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
-
-# If any special flags are necessary when building libgcc2 put them here.
-TARGET_LIBGCC2_CFLAGS =
-
-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 $(srcdir)/../libgcc/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 $(srcdir)/../libgcc/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.
@@ -93,7 +33,4 @@ MULTILIB_MATCHES = mcpu?simple=mcpu?fr300 \
mcpu?fr400=mcpu?fr405 mcpu?fr400=mcpu?fr450
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
diff --git a/gcc/config/frv/t-linux b/gcc/config/frv/t-linux
index 5b094518a1d..4f18e4baf9a 100644
--- a/gcc/config/frv/t-linux
+++ b/gcc/config/frv/t-linux
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2007, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -22,12 +22,3 @@ MULTILIB_DIRNAMES=
MULTILIB_MATCHES=
MULTILIB_EXCEPTIONS=
MULTILIB_EXTRA_OPTS=
-
-# We don't use frvbegin.o or frvend.o.
-EXTRA_MULTILIB_PARTS =
-
-CRTSTUFF_T_CFLAGS = -fPIC
-TARGET_LIBGCC2_CFLAGS = -fPIC
-
-SHLIB_MAPFILES = $$(libgcc_objdir)/libgcc-std.ver \
- $(srcdir)/config/frv/libgcc-frv.ver
diff --git a/gcc/config/gnu.h b/gcc/config/gnu.h
index 8b1d079ee89..dddbcbf5a49 100644
--- a/gcc/config/gnu.h
+++ b/gcc/config/gnu.h
@@ -28,10 +28,6 @@ along with GCC. If not, see <http://www.gnu.org/licenses/>.
#undef LIB_SPEC
#define LIB_SPEC "%{pthread:-lpthread} %{pg|p|profile:-lc_p;:-lc}"
-/* Standard include directory. In GNU, "/usr" is a four-letter word. */
-#undef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/include"
-
#undef GNU_USER_TARGET_OS_CPP_BUILTINS
#define GNU_USER_TARGET_OS_CPP_BUILTINS() \
do { \
diff --git a/gcc/config/h8300/crti.asm b/gcc/config/h8300/crti.asm
deleted file mode 100644
index 7ee3ae74503..00000000000
--- a/gcc/config/h8300/crti.asm
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (C) 2001, 2002, 2009 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* The code in sections .init and .fini is supposed to be a single
- regular function. The function in .init is called directly from
- start in crt0.asm. The function in .fini is atexit()ed in crt0.asm
- too.
-
- crti.asm contributes the prologue of a function to these sections,
- and crtn.asm comes up the epilogue. STARTFILE_SPEC should list
- crti.o before any other object files that might add code to .init
- or .fini sections, and ENDFILE_SPEC should list crtn.o after any
- such object files. */
-
-#ifdef __H8300H__
-#ifdef __NORMAL_MODE__
- .h8300hn
-#else
- .h8300h
-#endif
-#endif
-
-#ifdef __H8300S__
-#ifdef __NORMAL_MODE__
- .h8300sn
-#else
- .h8300s
-#endif
-#endif
-#ifdef __H8300SX__
-#ifdef __NORMAL_MODE__
- .h8300sxn
-#else
- .h8300sx
-#endif
-#endif
-
- .section .init, "ax", @progbits
- .global __init
-__init:
- .section .fini, "ax", @progbits
- .global __fini
-__fini:
diff --git a/gcc/config/h8300/crtn.asm b/gcc/config/h8300/crtn.asm
deleted file mode 100644
index 173fde13b5b..00000000000
--- a/gcc/config/h8300/crtn.asm
+++ /dev/null
@@ -1,53 +0,0 @@
-/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
- This file was adapted from glibc sources.
-
-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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* See an explanation about .init and .fini in crti.asm. */
-
-#ifdef __H8300H__
-#ifdef __NORMAL_MODE__
- .h8300hn
-#else
- .h8300h
-#endif
-#endif
-
-#ifdef __H8300S__
-#ifdef __NORMAL_MODE__
- .h8300sn
-#else
- .h8300s
-#endif
-#endif
-#ifdef __H8300SX__
-#ifdef __NORMAL_MODE__
- .h8300sxn
-#else
- .h8300sx
-#endif
-#endif
- .section .init, "ax", @progbits
- rts
-
- .section .fini, "ax", @progbits
- rts
diff --git a/gcc/config/h8300/fixunssfsi.c b/gcc/config/h8300/fixunssfsi.c
deleted file mode 100644
index 2fe62b7a1a8..00000000000
--- a/gcc/config/h8300/fixunssfsi.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* More subroutines needed by GCC output code on some machines. */
-/* Compile this one with gcc. */
-/* Copyright (C) 1989, 1992, 2001, 2002, 2003, 2004, 2009
- 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* The libgcc2.c implementation gets confused by our type setup and creates
- a directly recursive call, so we do our own implementation. For
- the H8/300, that's in lib1funcs.asm, for H8/300H and H8S, it's here. */
-
-#ifndef __H8300__
-long __fixunssfsi (float a);
-
-long
-__fixunssfsi (float a)
-{
- if (a >= (float) 32768L)
- return (long) (a - 32768L) + 32768L;
- return (long) a;
-}
-#endif
diff --git a/gcc/config/h8300/t-elf b/gcc/config/h8300/t-elf
deleted file mode 100644
index c1f1dac32c7..00000000000
--- a/gcc/config/h8300/t-elf
+++ /dev/null
@@ -1,6 +0,0 @@
-EXTRA_MULTILIB_PARTS= crti.o crtn.o crtbegin.o crtend.o
-
-$(T)crti.o: $(srcdir)/config/h8300/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/h8300/crti.asm
-$(T)crtn.o: $(srcdir)/config/h8300/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/h8300/crtn.asm
diff --git a/gcc/config/h8300/t-h8300 b/gcc/config/h8300/t-h8300
index 616849007b4..e29cd2d335c 100644
--- a/gcc/config/h8300/t-h8300
+++ b/gcc/config/h8300/t-h8300
@@ -17,27 +17,10 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = h8300/lib1funcs.asm
-LIB1ASMFUNCS = _cmpsi2 _ucmpsi2 _divhi3 _divsi3 _mulhi3 _mulsi3 \
- _fixunssfsi_asm
-
-LIB2FUNCS_EXTRA = \
- $(srcdir)/config/h8300/clzhi2.c \
- $(srcdir)/config/h8300/ctzhi2.c \
- $(srcdir)/config/h8300/parityhi2.c \
- $(srcdir)/config/h8300/popcounthi2.c \
- $(srcdir)/config/h8300/fixunssfsi.c
-
-# We do not have DF type, so fake out the libgcc2 compilation.
-TARGET_LIBGCC2_CFLAGS = -DDF=SF
-
MULTILIB_OPTIONS = mh/ms/msx mn mint32
MULTILIB_DIRNAMES = h8300h h8300s h8sx normal int32
MULTILIB_EXCEPTIONS = mint32 mn mn/mint32
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
s-config s-conditions s-flags s-codes s-constants s-emit s-recog \
s-opinit s-extract s-peep s-attr s-attrtab s-output: \
$(srcdir)/config/h8300/mova.md
diff --git a/gcc/config/i386/cygming-crtbegin.c b/gcc/config/i386/cygming-crtbegin.c
deleted file mode 100644
index fc36cce257d..00000000000
--- a/gcc/config/i386/cygming-crtbegin.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* crtbegin object for windows32 targets.
- Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
-
- Contributed 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* Target machine header files require this define. */
-#define IN_LIBGCC2
-
-#include "auto-host.h"
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "unwind-dw2-fde.h"
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-#ifndef LIBGCC_SONAME
-#define LIBGCC_SONAME "libgcc_s.dll"
-#endif
-
-#ifndef LIBGCJ_SONAME
-#define LIBGCJ_SONAME "libgcj_s.dll"
-#endif
-
-
-/* Make the declarations weak. This is critical for
- _Jv_RegisterClasses because it lives in libgcj.a */
-extern void __register_frame_info (const void *, struct object *)
- TARGET_ATTRIBUTE_WEAK;
-extern void *__deregister_frame_info (const void *)
- TARGET_ATTRIBUTE_WEAK;
-extern void _Jv_RegisterClasses (const void *) TARGET_ATTRIBUTE_WEAK;
-
-#if defined(HAVE_LD_RO_RW_SECTION_MIXING)
-# define EH_FRAME_SECTION_CONST const
-#else
-# define EH_FRAME_SECTION_CONST
-#endif
-
-/* Stick a label at the beginning of the frame unwind info so we can
- register/deregister it with the exception handling library code. */
-#if DWARF2_UNWIND_INFO
-static EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
- __attribute__((used, section(EH_FRAME_SECTION_NAME), aligned(4)))
- = { };
-
-static struct object obj;
-#endif
-
-#if TARGET_USE_JCR_SECTION
-static void *__JCR_LIST__[]
- __attribute__ ((used, section(JCR_SECTION_NAME), aligned(4)))
- = { };
-#endif
-
-/* Pull in references from libgcc.a(unwind-dw2-fde.o) in the
- startfile. These are referenced by a ctor and dtor in crtend.o. */
-extern void __gcc_register_frame (void);
-extern void __gcc_deregister_frame (void);
-
-void
-__gcc_register_frame (void)
-{
-#if DWARF2_UNWIND_INFO
-/* Weak undefined symbols won't be pulled in from dlls; hence
- we first test if the dll is already loaded and, if so,
- get the symbol's address at run-time. If the dll is not loaded,
- fallback to weak linkage to static archive. */
-
- void (*register_frame_fn) (const void *, struct object *);
- HANDLE h = GetModuleHandle (LIBGCC_SONAME);
- if (h)
- register_frame_fn = (void (*) (const void *, struct object *))
- GetProcAddress (h, "__register_frame_info");
- else
- register_frame_fn = __register_frame_info;
- if (register_frame_fn)
- register_frame_fn (__EH_FRAME_BEGIN__, &obj);
-#endif
-
-#if TARGET_USE_JCR_SECTION
- if (__JCR_LIST__[0])
- {
- void (*register_class_fn) (const void *);
- HANDLE h = GetModuleHandle (LIBGCJ_SONAME);
- if (h)
- register_class_fn = (void (*) (const void *))
- GetProcAddress (h, "_Jv_RegisterClasses");
- else
- register_class_fn = _Jv_RegisterClasses;
-
- if (register_class_fn)
- register_class_fn (__JCR_LIST__);
- }
-#endif
-}
-
-void
-__gcc_deregister_frame (void)
-{
-#if DWARF2_UNWIND_INFO
- void * (*deregister_frame_fn) (const void *);
- HANDLE h = GetModuleHandle (LIBGCC_SONAME);
- if (h)
- deregister_frame_fn = (void* (*) (const void *))
- GetProcAddress (h, "__deregister_frame_info");
- else
- deregister_frame_fn = __deregister_frame_info;
- if (deregister_frame_fn)
- deregister_frame_fn (__EH_FRAME_BEGIN__);
-#endif
-}
diff --git a/gcc/config/i386/cygming-crtend.c b/gcc/config/i386/cygming-crtend.c
deleted file mode 100644
index 8545420b271..00000000000
--- a/gcc/config/i386/cygming-crtend.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* crtend object for windows32 targets.
- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
-
- Contributed 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* Target machine header files require this define. */
-#define IN_LIBGCC2
-
-/* auto-host.h is needed by cygming.h for HAVE_GAS_WEAK and here
- for HAVE_LD_RO_RW_SECTION_MIXING. */
-#include "auto-host.h"
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "unwind-dw2-fde.h"
-
-#if defined(HAVE_LD_RO_RW_SECTION_MIXING)
-# define EH_FRAME_SECTION_CONST const
-#else
-# define EH_FRAME_SECTION_CONST
-#endif
-
-#if DWARF2_UNWIND_INFO
-/* Terminate the frame unwind info section with a 0 as a sentinel;
- this would be the 'length' field in a real FDE. */
-
-static EH_FRAME_SECTION_CONST int __FRAME_END__[]
- __attribute__ ((used, section(EH_FRAME_SECTION_NAME),
- aligned(4)))
- = { 0 };
-#endif
-
-#if TARGET_USE_JCR_SECTION
-/* Null terminate the .jcr section array. */
-static void *__JCR_END__[1]
- __attribute__ ((used, section(JCR_SECTION_NAME),
- aligned(sizeof(void *))))
- = { 0 };
-#endif
-
-extern void __gcc_register_frame (void);
-extern void __gcc_deregister_frame (void);
-
-static void register_frame_ctor (void) __attribute__ ((constructor (0)));
-
-static void
-register_frame_ctor (void)
-{
- __gcc_register_frame ();
-#if DEFAULT_USE_CXA_ATEXIT
- /* If we use the __cxa_atexit method to register C++ dtors
- at object construction, also use atexit to register eh frame
- info cleanup. */
- atexit (__gcc_deregister_frame);
-#endif
-}
-
-#if !DEFAULT_USE_CXA_ATEXIT
-static void deregister_frame_dtor (void) __attribute__ ((destructor (0)));
-
-static void
-deregister_frame_dtor (void)
-{
- __gcc_deregister_frame ();
-}
-#endif
diff --git a/gcc/config/i386/djgpp.h b/gcc/config/i386/djgpp.h
index d1109a2ff3f..c770219657c 100644
--- a/gcc/config/i386/djgpp.h
+++ b/gcc/config/i386/djgpp.h
@@ -48,10 +48,6 @@ along with GCC; see the file COPYING3. If not see
/* We override default /usr or /usr/local part with /dev/env/DJDIR which */
/* points to actual DJGPP installation directory. */
-/* Standard include directory */
-#undef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/dev/env/DJDIR/include/"
-
/* Search for as.exe and ld.exe in DJGPP's binary directory. */
#undef MD_EXEC_PREFIX
#define MD_EXEC_PREFIX "/dev/env/DJDIR/bin/"
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 8107ecee7c9..5f14c76fe55 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -451,6 +451,15 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_sse = edx & bit_SSE;
has_sse2 = edx & bit_SSE2;
+ if (max_level >= 7)
+ {
+ __cpuid_count (7, 0, eax, ebx, ecx, edx);
+
+ has_bmi = ebx & bit_BMI;
+ has_avx2 = ebx & bit_AVX2;
+ has_bmi2 = ebx & bit_BMI2;
+ }
+
/* Check cpuid level of extended features. */
__cpuid (0x80000000, ext_level, ebx, ecx, edx);
@@ -470,12 +479,6 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_longmode = edx & bit_LM;
has_3dnowp = edx & bit_3DNOWP;
has_3dnow = edx & bit_3DNOW;
-
- __cpuid (0x7, eax, ebx, ecx, edx);
-
- has_bmi = ebx & bit_BMI;
- has_avx2 = ebx & bit_AVX2;
- has_bmi2 = ebx & bit_BMI2;
}
if (!arch)
diff --git a/gcc/config/i386/freebsd64.h b/gcc/config/i386/freebsd64.h
index 853f214f4e0..b6f0c3f1160 100644
--- a/gcc/config/i386/freebsd64.h
+++ b/gcc/config/i386/freebsd64.h
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see
#undef LINK_SPEC
#define LINK_SPEC "\
%{m32:-m elf_i386_fbsd} \
+ %{p:%nconsider using '-pg' instead of '-p' with gprof(1)} \
%{v:-V} \
%{assert*} %{R*} %{rpath*} %{defsym*} \
%{shared:-Bshareable %{h*} %{soname*}} \
diff --git a/gcc/config/i386/gthr-win32.c b/gcc/config/i386/gthr-win32.c
deleted file mode 100644
index 46ecb0d4b26..00000000000
--- a/gcc/config/i386/gthr-win32.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/* Implementation of W32-specific threads compatibility routines for
- libgcc2. */
-
-/* Copyright (C) 1999, 2000, 2002, 2004, 2008, 2009 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include <windows.h>
-#ifndef __GTHREAD_HIDE_WIN32API
-# define __GTHREAD_HIDE_WIN32API 1
-#endif
-#undef __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
-#define __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
-#include <gthr-win32.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 are currently using a special mutex instead of the Critical
- Sections, since Win9x does not support TryEnterCriticalSection
- (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 *) __attribute__((unused)))
-{
- 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)
-{
- if (TlsSetValue (key, CONST_CAST2(void *, const void *, ptr)) != 0)
- return 0;
- else
- return GetLastError ();
-}
-
-void
-__gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
-{
- mutex->counter = -1;
- mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
-}
-
-void
-__gthr_win32_mutex_destroy (__gthread_mutex_t *mutex)
-{
- CloseHandle ((HANDLE) mutex->sema);
-}
-
-int
-__gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
-{
- if (InterlockedIncrement (&mutex->counter) == 0 ||
- WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
- return 0;
- else
- {
- /* WaitForSingleObject returns WAIT_FAILED, and we can only do
- some best-effort cleanup here. */
- InterlockedDecrement (&mutex->counter);
- return 1;
- }
-}
-
-int
-__gthr_win32_mutex_trylock (__gthread_mutex_t *mutex)
-{
- if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
- return 0;
- else
- return 1;
-}
-
-int
-__gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
-{
- if (InterlockedDecrement (&mutex->counter) >= 0)
- return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
- else
- return 0;
-}
-
-void
-__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
-{
- mutex->counter = -1;
- mutex->depth = 0;
- mutex->owner = 0;
- mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
-}
-
-int
-__gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
-{
- DWORD me = GetCurrentThreadId();
- if (InterlockedIncrement (&mutex->counter) == 0)
- {
- mutex->depth = 1;
- mutex->owner = me;
- }
- else if (mutex->owner == me)
- {
- InterlockedDecrement (&mutex->counter);
- ++(mutex->depth);
- }
- else if (WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
- {
- mutex->depth = 1;
- mutex->owner = me;
- }
- else
- {
- /* WaitForSingleObject returns WAIT_FAILED, and we can only do
- some best-effort cleanup here. */
- InterlockedDecrement (&mutex->counter);
- return 1;
- }
- return 0;
-}
-
-int
-__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
-{
- DWORD me = GetCurrentThreadId();
- if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
- {
- mutex->depth = 1;
- mutex->owner = me;
- }
- else if (mutex->owner == me)
- ++(mutex->depth);
- else
- return 1;
-
- return 0;
-}
-
-int
-__gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
-{
- --(mutex->depth);
- if (mutex->depth == 0)
- {
- mutex->owner = 0;
-
- if (InterlockedDecrement (&mutex->counter) >= 0)
- return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
- }
-
- return 0;
-}
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index eea038e3ab4..5486e618dc8 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -109,6 +109,7 @@ extern void ix86_expand_convert_uns_sixf_sse (rtx, rtx);
extern void ix86_expand_convert_uns_sidf_sse (rtx, rtx);
extern void ix86_expand_convert_uns_sisf_sse (rtx, rtx);
extern void ix86_expand_convert_sign_didf_sse (rtx, rtx);
+extern rtx ix86_expand_adjust_ufix_to_sfix_si (rtx);
extern enum ix86_fpcmp_strategy ix86_fp_comparison_strategy (enum rtx_code);
extern void ix86_expand_fp_absneg_operator (enum rtx_code, enum machine_mode,
rtx[]);
@@ -124,6 +125,7 @@ extern bool ix86_expand_fp_movcc (rtx[]);
extern bool ix86_expand_fp_vcond (rtx[]);
extern bool ix86_expand_int_vcond (rtx[]);
extern void ix86_expand_vec_perm (rtx[]);
+extern bool ix86_expand_vec_perm_const (rtx[]);
extern void ix86_expand_sse_unpack (rtx[], bool, bool);
extern bool ix86_expand_int_addcc (rtx[]);
extern rtx ix86_expand_call (rtx, rtx, rtx, rtx, rtx, bool);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 625c55e76d9..01f4fbea9e0 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1672,7 +1672,7 @@ struct processor_costs atom_cost = {
COSTS_N_INSNS (1), /* cost of movzx */
8, /* "large" insn */
17, /* MOVE_RATIO */
- 2, /* cost for loading QImode using movzbl */
+ 4, /* cost for loading QImode using movzbl */
{4, 4, 4}, /* cost of loading integer registers
in QImode, HImode and SImode.
Relative to reg-reg move (2). */
@@ -2509,7 +2509,6 @@ static void ix86_compute_frame_layout (struct ix86_frame *);
static bool ix86_expand_vector_init_one_nonzero (bool, enum machine_mode,
rtx, rtx, int);
static void ix86_add_new_builtins (HOST_WIDE_INT);
-static rtx ix86_expand_vec_perm_builtin (tree);
static tree ix86_canonical_va_list_type (tree);
static void predict_jump (int);
static unsigned int split_stack_prologue_scratch_regno (void);
@@ -2596,7 +2595,7 @@ static const struct ptt processor_target_table[PROCESSOR_max] =
{&bdver1_cost, 32, 24, 32, 7, 32},
{&bdver2_cost, 32, 24, 32, 7, 32},
{&btver1_cost, 32, 24, 32, 7, 32},
- {&atom_cost, 16, 7, 16, 7, 16}
+ {&atom_cost, 16, 15, 16, 7, 16}
};
static const char *const cpu_names[TARGET_CPU_DEFAULT_max] =
@@ -8391,6 +8390,10 @@ ix86_frame_pointer_required (void)
if (SUBTARGET_FRAME_POINTER_REQUIRED)
return true;
+ /* For older 32-bit runtimes setjmp requires valid frame-pointer. */
+ if (TARGET_32BIT_MS_ABI && cfun->calls_setjmp)
+ return true;
+
/* In ix86_option_override_internal, 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. */
@@ -14115,13 +14118,18 @@ ix86_print_operand (FILE *file, rtx x, int code)
gcc_unreachable ();
}
- /* Check for explicit size override (codes 'b', 'w' and 'k') */
+ /* Check for explicit size override (codes 'b', 'w', 'k',
+ 'q' and 'x') */
if (code == 'b')
size = "BYTE";
else if (code == 'w')
size = "WORD";
else if (code == 'k')
size = "DWORD";
+ else if (code == 'q')
+ size = "QWORD";
+ else if (code == 'x')
+ size = "XMMWORD";
fputs (size, file);
fputs (" PTR ", file);
@@ -14228,7 +14236,20 @@ ix86_print_operand_address (FILE *file, rtx addr)
struct ix86_address parts;
rtx base, index, disp;
int scale;
- int ok = ix86_decompose_address (addr, &parts);
+ int ok;
+ bool vsib = false;
+
+ if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_VSIBADDR)
+ {
+ ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts);
+ gcc_assert (parts.index == NULL_RTX);
+ parts.index = XVECEXP (addr, 0, 1);
+ parts.scale = INTVAL (XVECEXP (addr, 0, 2));
+ addr = XVECEXP (addr, 0, 0);
+ vsib = true;
+ }
+ else
+ ok = ix86_decompose_address (addr, &parts);
gcc_assert (ok);
@@ -14325,8 +14346,8 @@ ix86_print_operand_address (FILE *file, rtx addr)
if (index)
{
putc (',', file);
- print_reg (index, code, file);
- if (scale != 1)
+ print_reg (index, vsib ? 0 : code, file);
+ if (scale != 1 || vsib)
fprintf (file, ",%d", scale);
}
putc (')', file);
@@ -14376,8 +14397,8 @@ ix86_print_operand_address (FILE *file, rtx addr)
if (index)
{
putc ('+', file);
- print_reg (index, code, file);
- if (scale != 1)
+ print_reg (index, vsib ? 0 : code, file);
+ if (scale != 1 || vsib)
fprintf (file, "*%d", scale);
}
putc (']', file);
@@ -16836,7 +16857,7 @@ ix86_split_convert_uns_si_sse (rtx operands[])
x = gen_rtx_REG (V4SImode, REGNO (value));
if (vecmode == V4SFmode)
- emit_insn (gen_sse2_cvttps2dq (x, value));
+ emit_insn (gen_fix_truncv4sfv4si2 (x, value));
else
emit_insn (gen_sse2_cvttpd2dq (x, value));
value = x;
@@ -16995,6 +17016,46 @@ ix86_expand_convert_uns_sisf_sse (rtx target, rtx input)
emit_move_insn (target, fp_hi);
}
+/* Adjust a V*SFmode/V*DFmode value VAL so that *sfix_trunc* resp. fix_trunc*
+ pattern can be used on it instead of *ufix_trunc* resp. fixuns_trunc*.
+ This is done by subtracting 0x1p32 from VAL if VAL is greater or equal
+ (non-signalling) than 0x1p31. */
+
+rtx
+ix86_expand_adjust_ufix_to_sfix_si (rtx val)
+{
+ REAL_VALUE_TYPE MTWO32r, TWO31r;
+ rtx two31r, mtwo32r, tmp[3];
+ enum machine_mode mode = GET_MODE (val);
+ enum machine_mode scalarmode = GET_MODE_INNER (mode);
+ rtx (*cmp) (rtx, rtx, rtx, rtx);
+ int i;
+
+ for (i = 0; i < 3; i++)
+ tmp[i] = gen_reg_rtx (mode);
+ real_ldexp (&TWO31r, &dconst1, 31);
+ two31r = const_double_from_real_value (TWO31r, scalarmode);
+ two31r = ix86_build_const_vector (mode, 1, two31r);
+ two31r = force_reg (mode, two31r);
+ real_ldexp (&MTWO32r, &dconstm1, 32);
+ mtwo32r = const_double_from_real_value (MTWO32r, scalarmode);
+ mtwo32r = ix86_build_const_vector (mode, 1, mtwo32r);
+ mtwo32r = force_reg (mode, mtwo32r);
+ switch (mode)
+ {
+ case V8SFmode: cmp = gen_avx_cmpv8sf3; break;
+ case V4SFmode: cmp = gen_avx_cmpv4sf3; break;
+ case V4DFmode: cmp = gen_avx_cmpv4df3; break;
+ case V2DFmode: cmp = gen_avx_cmpv2df3; break;
+ default: gcc_unreachable ();
+ }
+ emit_insn (cmp (tmp[0], val, two31r, GEN_INT (29)));
+ tmp[1] = expand_simple_binop (mode, AND, tmp[0], mtwo32r, tmp[1],
+ 0, OPTAB_DIRECT);
+ return expand_simple_binop (mode, PLUS, val, tmp[1], tmp[2],
+ 0, OPTAB_DIRECT);
+}
+
/* A subroutine of ix86_build_signbit_mask. If VECT is true,
then replicate the value for all elements of the vector
register. */
@@ -17008,6 +17069,10 @@ ix86_build_const_vector (enum machine_mode mode, bool vect, rtx value)
switch (mode)
{
+ case V32QImode:
+ case V16QImode:
+ case V16HImode:
+ case V8HImode:
case V8SImode:
case V4SImode:
case V4DImode:
@@ -19334,7 +19399,7 @@ ix86_expand_vec_perm (rtx operands[])
rtx op0 = operands[1];
rtx op1 = operands[2];
rtx mask = operands[3];
- rtx t1, t2, vt, vec[16];
+ rtx t1, t2, t3, t4, vt, vt2, vec[32];
enum machine_mode mode = GET_MODE (op0);
enum machine_mode maskmode = GET_MODE (mask);
int w, e, i;
@@ -19343,50 +19408,68 @@ ix86_expand_vec_perm (rtx operands[])
/* Number of elements in the vector. */
w = GET_MODE_NUNITS (mode);
e = GET_MODE_UNIT_SIZE (mode);
- gcc_assert (w <= 16);
+ gcc_assert (w <= 32);
if (TARGET_AVX2)
{
- if (mode == V4DImode || mode == V4DFmode)
+ if (mode == V4DImode || mode == V4DFmode || mode == V16HImode)
{
/* Unfortunately, the VPERMQ and VPERMPD instructions only support
an constant shuffle operand. With a tiny bit of effort we can
use VPERMD instead. A re-interpretation stall for V4DFmode is
- unfortunate but there's no avoiding it. */
- t1 = gen_reg_rtx (V8SImode);
+ unfortunate but there's no avoiding it.
+ Similarly for V16HImode we don't have instructions for variable
+ shuffling, while for V32QImode we can use after preparing suitable
+ masks vpshufb; vpshufb; vpermq; vpor. */
+
+ if (mode == V16HImode)
+ {
+ maskmode = mode = V32QImode;
+ w = 32;
+ e = 1;
+ }
+ else
+ {
+ maskmode = mode = V8SImode;
+ w = 8;
+ e = 4;
+ }
+ t1 = gen_reg_rtx (maskmode);
/* Replicate the low bits of the V4DImode mask into V8SImode:
mask = { A B C D }
t1 = { A A B B C C D D }. */
- for (i = 0; i < 4; ++i)
+ for (i = 0; i < w / 2; ++i)
vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2);
- vt = gen_rtx_CONST_VECTOR (V8SImode, gen_rtvec_v (8, vec));
- vt = force_reg (V8SImode, vt);
- mask = gen_lowpart (V8SImode, mask);
- emit_insn (gen_avx2_permvarv8si (t1, vt, mask));
+ vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
+ vt = force_reg (maskmode, vt);
+ mask = gen_lowpart (maskmode, mask);
+ if (maskmode == V8SImode)
+ emit_insn (gen_avx2_permvarv8si (t1, vt, mask));
+ else
+ emit_insn (gen_avx2_pshufbv32qi3 (t1, mask, vt));
/* Multiply the shuffle indicies by two. */
- emit_insn (gen_avx2_lshlv8si3 (t1, t1, const1_rtx));
+ t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1,
+ OPTAB_DIRECT);
/* Add one to the odd shuffle indicies:
t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */
- for (i = 0; i < 4; ++i)
+ for (i = 0; i < w / 2; ++i)
{
vec[i * 2] = const0_rtx;
vec[i * 2 + 1] = const1_rtx;
}
- vt = gen_rtx_CONST_VECTOR (V8SImode, gen_rtvec_v (8, vec));
- vt = force_const_mem (V8SImode, vt);
- emit_insn (gen_addv8si3 (t1, t1, vt));
+ vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec));
+ vt = force_const_mem (maskmode, vt);
+ t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1,
+ OPTAB_DIRECT);
- /* Continue as if V8SImode was used initially. */
+ /* Continue as if V8SImode (resp. V32QImode) was used initially. */
operands[3] = mask = t1;
- target = gen_lowpart (V8SImode, target);
- op0 = gen_lowpart (V8SImode, op0);
- op1 = gen_lowpart (V8SImode, op1);
- maskmode = mode = V8SImode;
- w = 8;
- e = 4;
+ target = gen_lowpart (mode, target);
+ op0 = gen_lowpart (mode, op0);
+ op1 = gen_lowpart (mode, op1);
}
switch (mode)
@@ -19443,6 +19526,92 @@ ix86_expand_vec_perm (rtx operands[])
emit_insn (gen_avx_vextractf128v8sf (target, t1, const0_rtx));
return;
+ case V32QImode:
+ t1 = gen_reg_rtx (V32QImode);
+ t2 = gen_reg_rtx (V32QImode);
+ t3 = gen_reg_rtx (V32QImode);
+ vt2 = GEN_INT (128);
+ for (i = 0; i < 32; i++)
+ vec[i] = vt2;
+ vt = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
+ vt = force_reg (V32QImode, vt);
+ for (i = 0; i < 32; i++)
+ vec[i] = i < 16 ? vt2 : const0_rtx;
+ vt2 = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec));
+ vt2 = force_reg (V32QImode, vt2);
+ /* From mask create two adjusted masks, which contain the same
+ bits as mask in the low 7 bits of each vector element.
+ The first mask will have the most significant bit clear
+ if it requests element from the same 128-bit lane
+ and MSB set if it requests element from the other 128-bit lane.
+ The second mask will have the opposite values of the MSB,
+ and additionally will have its 128-bit lanes swapped.
+ E.g. { 07 12 1e 09 ... | 17 19 05 1f ... } mask vector will have
+ t1 { 07 92 9e 09 ... | 17 19 85 1f ... } and
+ t3 { 97 99 05 9f ... | 87 12 1e 89 ... } where each ...
+ stands for other 12 bytes. */
+ /* The bit whether element is from the same lane or the other
+ lane is bit 4, so shift it up by 3 to the MSB position. */
+ emit_insn (gen_ashlv4di3 (gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, mask),
+ GEN_INT (3)));
+ /* Clear MSB bits from the mask just in case it had them set. */
+ emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask));
+ /* After this t1 will have MSB set for elements from other lane. */
+ emit_insn (gen_xorv32qi3 (t1, t1, vt2));
+ /* Clear bits other than MSB. */
+ emit_insn (gen_andv32qi3 (t1, t1, vt));
+ /* Or in the lower bits from mask into t3. */
+ emit_insn (gen_iorv32qi3 (t3, t1, t2));
+ /* And invert MSB bits in t1, so MSB is set for elements from the same
+ lane. */
+ emit_insn (gen_xorv32qi3 (t1, t1, vt));
+ /* Swap 128-bit lanes in t3. */
+ emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
+ gen_lowpart (V4DImode, t3),
+ const2_rtx, GEN_INT (3),
+ const0_rtx, const1_rtx));
+ /* And or in the lower bits from mask into t1. */
+ emit_insn (gen_iorv32qi3 (t1, t1, t2));
+ if (one_operand_shuffle)
+ {
+ /* Each of these shuffles will put 0s in places where
+ element from the other 128-bit lane is needed, otherwise
+ will shuffle in the requested value. */
+ emit_insn (gen_avx2_pshufbv32qi3 (t3, op0, t3));
+ emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1));
+ /* For t3 the 128-bit lanes are swapped again. */
+ emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
+ gen_lowpart (V4DImode, t3),
+ const2_rtx, GEN_INT (3),
+ const0_rtx, const1_rtx));
+ /* And oring both together leads to the result. */
+ emit_insn (gen_iorv32qi3 (target, t1, t3));
+ return;
+ }
+
+ t4 = gen_reg_rtx (V32QImode);
+ /* Similarly to the above one_operand_shuffle code,
+ just for repeated twice for each operand. merge_two:
+ code will merge the two results together. */
+ emit_insn (gen_avx2_pshufbv32qi3 (t4, op0, t3));
+ emit_insn (gen_avx2_pshufbv32qi3 (t3, op1, t3));
+ emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1));
+ emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1));
+ emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t4),
+ gen_lowpart (V4DImode, t4),
+ const2_rtx, GEN_INT (3),
+ const0_rtx, const1_rtx));
+ emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3),
+ gen_lowpart (V4DImode, t3),
+ const2_rtx, GEN_INT (3),
+ const0_rtx, const1_rtx));
+ emit_insn (gen_iorv32qi3 (t4, t2, t4));
+ emit_insn (gen_iorv32qi3 (t3, t1, t3));
+ t1 = t4;
+ t2 = t3;
+ goto merge_two;
+
default:
gcc_assert (GET_MODE_SIZE (mode) <= 16);
break;
@@ -19555,7 +19724,7 @@ ix86_expand_vec_perm (rtx operands[])
mask = expand_simple_binop (maskmode, AND, mask, vt,
NULL_RTX, 0, OPTAB_DIRECT);
- xops[0] = operands[0];
+ xops[0] = gen_lowpart (mode, operands[0]);
xops[1] = gen_lowpart (mode, t2);
xops[2] = gen_lowpart (mode, t1);
xops[3] = gen_rtx_EQ (maskmode, mask, vt);
@@ -19579,9 +19748,38 @@ ix86_expand_sse_unpack (rtx operands[2], bool unsigned_p, bool high_p)
if (TARGET_SSE4_1)
{
rtx (*unpack)(rtx, rtx);
+ rtx (*extract)(rtx, rtx) = NULL;
+ enum machine_mode halfmode = BLKmode;
switch (imode)
{
+ case V32QImode:
+ if (unsigned_p)
+ unpack = gen_avx2_zero_extendv16qiv16hi2;
+ else
+ unpack = gen_avx2_sign_extendv16qiv16hi2;
+ halfmode = V16QImode;
+ extract
+ = high_p ? gen_vec_extract_hi_v32qi : gen_vec_extract_lo_v32qi;
+ break;
+ case V16HImode:
+ if (unsigned_p)
+ unpack = gen_avx2_zero_extendv8hiv8si2;
+ else
+ unpack = gen_avx2_sign_extendv8hiv8si2;
+ halfmode = V8HImode;
+ extract
+ = high_p ? gen_vec_extract_hi_v16hi : gen_vec_extract_lo_v16hi;
+ break;
+ case V8SImode:
+ if (unsigned_p)
+ unpack = gen_avx2_zero_extendv4siv4di2;
+ else
+ unpack = gen_avx2_sign_extendv4siv4di2;
+ halfmode = V4SImode;
+ extract
+ = high_p ? gen_vec_extract_hi_v8si : gen_vec_extract_lo_v8si;
+ break;
case V16QImode:
if (unsigned_p)
unpack = gen_sse4_1_zero_extendv8qiv8hi2;
@@ -19604,7 +19802,12 @@ ix86_expand_sse_unpack (rtx operands[2], bool unsigned_p, bool high_p)
gcc_unreachable ();
}
- if (high_p)
+ if (GET_MODE_SIZE (imode) == 32)
+ {
+ tmp = gen_reg_rtx (halfmode);
+ emit_insn (extract (tmp, operands[1]));
+ }
+ else if (high_p)
{
/* Shift higher 8 bytes to lower 8 bytes. */
tmp = gen_reg_rtx (imode);
@@ -24914,21 +25117,6 @@ enum ix86_builtins
IX86_BUILTIN_CPYSGNPS256,
IX86_BUILTIN_CPYSGNPD256,
- IX86_BUILTIN_CVTUDQ2PS,
-
- IX86_BUILTIN_VEC_PERM_V2DF,
- IX86_BUILTIN_VEC_PERM_V4SF,
- IX86_BUILTIN_VEC_PERM_V2DI,
- IX86_BUILTIN_VEC_PERM_V4SI,
- IX86_BUILTIN_VEC_PERM_V8HI,
- IX86_BUILTIN_VEC_PERM_V16QI,
- IX86_BUILTIN_VEC_PERM_V2DI_U,
- IX86_BUILTIN_VEC_PERM_V4SI_U,
- IX86_BUILTIN_VEC_PERM_V8HI_U,
- IX86_BUILTIN_VEC_PERM_V16QI_U,
- IX86_BUILTIN_VEC_PERM_V4DF,
- IX86_BUILTIN_VEC_PERM_V8SF,
-
/* FMA4 instructions. */
IX86_BUILTIN_VFMADDSS,
IX86_BUILTIN_VFMADDSD,
@@ -25637,25 +25825,11 @@ static const struct builtin_description bdesc_args[] =
/* SSE2 */
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_shufpd, "__builtin_ia32_shufpd", IX86_BUILTIN_SHUFPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v2df", IX86_BUILTIN_VEC_PERM_V2DF, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_V2DI },
- { OPTION_MASK_ISA_SSE, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v4sf", IX86_BUILTIN_VEC_PERM_V4SF, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_V4SI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v2di", IX86_BUILTIN_VEC_PERM_V2DI, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v4si", IX86_BUILTIN_VEC_PERM_V4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v8hi", IX86_BUILTIN_VEC_PERM_V8HI, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v16qi", IX86_BUILTIN_VEC_PERM_V16QI, UNKNOWN, (int) V16QI_FTYPE_V16QI_V16QI_V16QI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v2di_u", IX86_BUILTIN_VEC_PERM_V2DI_U, UNKNOWN, (int) V2UDI_FTYPE_V2UDI_V2UDI_V2UDI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v4si_u", IX86_BUILTIN_VEC_PERM_V4SI_U, UNKNOWN, (int) V4USI_FTYPE_V4USI_V4USI_V4USI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v8hi_u", IX86_BUILTIN_VEC_PERM_V8HI_U, UNKNOWN, (int) V8UHI_FTYPE_V8UHI_V8UHI_V8UHI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v16qi_u", IX86_BUILTIN_VEC_PERM_V16QI_U, UNKNOWN, (int) V16UQI_FTYPE_V16UQI_V16UQI_V16UQI },
- { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v4df", IX86_BUILTIN_VEC_PERM_V4DF, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_V4DI },
- { OPTION_MASK_ISA_AVX, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v8sf", IX86_BUILTIN_VEC_PERM_V8SF, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_V8SI },
-
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movmskpd, "__builtin_ia32_movmskpd", IX86_BUILTIN_MOVMSKPD, UNKNOWN, (int) INT_FTYPE_V2DF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_pmovmskb, "__builtin_ia32_pmovmskb128", IX86_BUILTIN_PMOVMSKB128, UNKNOWN, (int) INT_FTYPE_V16QI },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sqrtv2df2, "__builtin_ia32_sqrtpd", IX86_BUILTIN_SQRTPD, UNKNOWN, (int) V2DF_FTYPE_V2DF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtdq2pd, "__builtin_ia32_cvtdq2pd", IX86_BUILTIN_CVTDQ2PD, UNKNOWN, (int) V2DF_FTYPE_V4SI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtdq2ps, "__builtin_ia32_cvtdq2ps", IX86_BUILTIN_CVTDQ2PS, UNKNOWN, (int) V4SF_FTYPE_V4SI },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtudq2ps, "__builtin_ia32_cvtudq2ps", IX86_BUILTIN_CVTUDQ2PS, UNKNOWN, (int) V4SF_FTYPE_V4SI },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_floatv4siv4sf2, "__builtin_ia32_cvtdq2ps", IX86_BUILTIN_CVTDQ2PS, UNKNOWN, (int) V4SF_FTYPE_V4SI },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtpd2dq, "__builtin_ia32_cvtpd2dq", IX86_BUILTIN_CVTPD2DQ, UNKNOWN, (int) V4SI_FTYPE_V2DF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtpd2pi, "__builtin_ia32_cvtpd2pi", IX86_BUILTIN_CVTPD2PI, UNKNOWN, (int) V2SI_FTYPE_V2DF },
@@ -25672,7 +25846,7 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtps2dq, "__builtin_ia32_cvtps2dq", IX86_BUILTIN_CVTPS2DQ, UNKNOWN, (int) V4SI_FTYPE_V4SF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvtps2pd, "__builtin_ia32_cvtps2pd", IX86_BUILTIN_CVTPS2PD, UNKNOWN, (int) V2DF_FTYPE_V4SF },
- { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_cvttps2dq, "__builtin_ia32_cvttps2dq", IX86_BUILTIN_CVTTPS2DQ, UNKNOWN, (int) V4SI_FTYPE_V4SF },
+ { OPTION_MASK_ISA_SSE2, CODE_FOR_fix_truncv4sfv4si2, "__builtin_ia32_cvttps2dq", IX86_BUILTIN_CVTTPS2DQ, UNKNOWN, (int) V4SI_FTYPE_V4SF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_addv2df3, "__builtin_ia32_addpd", IX86_BUILTIN_ADDPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF },
{ OPTION_MASK_ISA_SSE2, CODE_FOR_subv2df3, "__builtin_ia32_subpd", IX86_BUILTIN_SUBPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF },
@@ -26010,14 +26184,14 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vextractf128v4df, "__builtin_ia32_vextractf128_pd256", IX86_BUILTIN_EXTRACTF128PD256, UNKNOWN, (int) V2DF_FTYPE_V4DF_INT },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vextractf128v8sf, "__builtin_ia32_vextractf128_ps256", IX86_BUILTIN_EXTRACTF128PS256, UNKNOWN, (int) V4SF_FTYPE_V8SF_INT },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vextractf128v8si, "__builtin_ia32_vextractf128_si256", IX86_BUILTIN_EXTRACTF128SI256, UNKNOWN, (int) V4SI_FTYPE_V8SI_INT },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtdq2pd256, "__builtin_ia32_cvtdq2pd256", IX86_BUILTIN_CVTDQ2PD256, UNKNOWN, (int) V4DF_FTYPE_V4SI },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtdq2ps256, "__builtin_ia32_cvtdq2ps256", IX86_BUILTIN_CVTDQ2PS256, UNKNOWN, (int) V8SF_FTYPE_V8SI },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_floatv4siv4df2, "__builtin_ia32_cvtdq2pd256", IX86_BUILTIN_CVTDQ2PD256, UNKNOWN, (int) V4DF_FTYPE_V4SI },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_floatv8siv8sf2, "__builtin_ia32_cvtdq2ps256", IX86_BUILTIN_CVTDQ2PS256, UNKNOWN, (int) V8SF_FTYPE_V8SI },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtpd2ps256, "__builtin_ia32_cvtpd2ps256", IX86_BUILTIN_CVTPD2PS256, UNKNOWN, (int) V4SF_FTYPE_V4DF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtps2dq256, "__builtin_ia32_cvtps2dq256", IX86_BUILTIN_CVTPS2DQ256, UNKNOWN, (int) V8SI_FTYPE_V8SF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtps2pd256, "__builtin_ia32_cvtps2pd256", IX86_BUILTIN_CVTPS2PD256, UNKNOWN, (int) V4DF_FTYPE_V4SF },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvttpd2dq256, "__builtin_ia32_cvttpd2dq256", IX86_BUILTIN_CVTTPD2DQ256, UNKNOWN, (int) V4SI_FTYPE_V4DF },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_fix_truncv4dfv4si2, "__builtin_ia32_cvttpd2dq256", IX86_BUILTIN_CVTTPD2DQ256, UNKNOWN, (int) V4SI_FTYPE_V4DF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvtpd2dq256, "__builtin_ia32_cvtpd2dq256", IX86_BUILTIN_CVTPD2DQ256, UNKNOWN, (int) V4SI_FTYPE_V4DF },
- { OPTION_MASK_ISA_AVX, CODE_FOR_avx_cvttps2dq256, "__builtin_ia32_cvttps2dq256", IX86_BUILTIN_CVTTPS2DQ256, UNKNOWN, (int) V8SI_FTYPE_V8SF },
+ { OPTION_MASK_ISA_AVX, CODE_FOR_fix_truncv8sfv8si2, "__builtin_ia32_cvttps2dq256", IX86_BUILTIN_CVTTPS2DQ256, UNKNOWN, (int) V8SI_FTYPE_V8SF },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vperm2f128v4df3, "__builtin_ia32_vperm2f128_pd256", IX86_BUILTIN_VPERM2F128PD256, UNKNOWN, (int) V4DF_FTYPE_V4DF_V4DF_INT },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vperm2f128v8sf3, "__builtin_ia32_vperm2f128_ps256", IX86_BUILTIN_VPERM2F128PS256, UNKNOWN, (int) V8SF_FTYPE_V8SF_V8SF_INT },
{ OPTION_MASK_ISA_AVX, CODE_FOR_avx_vperm2f128v8si3, "__builtin_ia32_vperm2f128_si256", IX86_BUILTIN_VPERM2F128SI256, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI_INT },
@@ -26174,12 +26348,12 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_psignv16hi3, "__builtin_ia32_psignw256", IX86_BUILTIN_PSIGNW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V16HI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_psignv8si3 , "__builtin_ia32_psignd256", IX86_BUILTIN_PSIGND256, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ashlv2ti3, "__builtin_ia32_pslldqi256", IX86_BUILTIN_PSLLDQI256, UNKNOWN, (int) V4DI_FTYPE_V4DI_INT_CONVERT },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv16hi3, "__builtin_ia32_psllwi256", IX86_BUILTIN_PSLLWI256 , UNKNOWN, (int) V16HI_FTYPE_V16HI_SI_COUNT },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv16hi3, "__builtin_ia32_psllw256", IX86_BUILTIN_PSLLW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V8HI_COUNT },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv8si3, "__builtin_ia32_pslldi256", IX86_BUILTIN_PSLLDI256, UNKNOWN, (int) V8SI_FTYPE_V8SI_SI_COUNT },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv8si3, "__builtin_ia32_pslld256", IX86_BUILTIN_PSLLD256, UNKNOWN, (int) V8SI_FTYPE_V8SI_V4SI_COUNT },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv4di3, "__builtin_ia32_psllqi256", IX86_BUILTIN_PSLLQI256, UNKNOWN, (int) V4DI_FTYPE_V4DI_INT_COUNT },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlv4di3, "__builtin_ia32_psllq256", IX86_BUILTIN_PSLLQ256, UNKNOWN, (int) V4DI_FTYPE_V4DI_V2DI_COUNT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_ashlv16hi3, "__builtin_ia32_psllwi256", IX86_BUILTIN_PSLLWI256 , UNKNOWN, (int) V16HI_FTYPE_V16HI_SI_COUNT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_ashlv16hi3, "__builtin_ia32_psllw256", IX86_BUILTIN_PSLLW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V8HI_COUNT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_ashlv8si3, "__builtin_ia32_pslldi256", IX86_BUILTIN_PSLLDI256, UNKNOWN, (int) V8SI_FTYPE_V8SI_SI_COUNT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_ashlv8si3, "__builtin_ia32_pslld256", IX86_BUILTIN_PSLLD256, UNKNOWN, (int) V8SI_FTYPE_V8SI_V4SI_COUNT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_ashlv4di3, "__builtin_ia32_psllqi256", IX86_BUILTIN_PSLLQI256, UNKNOWN, (int) V4DI_FTYPE_V4DI_INT_COUNT },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_ashlv4di3, "__builtin_ia32_psllq256", IX86_BUILTIN_PSLLQ256, UNKNOWN, (int) V4DI_FTYPE_V4DI_V2DI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_ashrv16hi3, "__builtin_ia32_psrawi256", IX86_BUILTIN_PSRAWI256, UNKNOWN, (int) V16HI_FTYPE_V16HI_SI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_ashrv16hi3, "__builtin_ia32_psraw256", IX86_BUILTIN_PSRAW256, UNKNOWN, (int) V16HI_FTYPE_V16HI_V8HI_COUNT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_ashrv8si3, "__builtin_ia32_psradi256", IX86_BUILTIN_PSRADI256, UNKNOWN, (int) V8SI_FTYPE_V8SI_SI_COUNT },
@@ -26229,10 +26403,10 @@ static const struct builtin_description bdesc_args[] =
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_permv2ti, "__builtin_ia32_permti256", IX86_BUILTIN_VPERMTI256, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI_INT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_extracti128, "__builtin_ia32_extract128i256", IX86_BUILTIN_VEXTRACT128I256, UNKNOWN, (int) V2DI_FTYPE_V4DI_INT },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_inserti128, "__builtin_ia32_insert128i256", IX86_BUILTIN_VINSERT128I256, UNKNOWN, (int) V4DI_FTYPE_V4DI_V2DI_INT },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlvv4di, "__builtin_ia32_psllv4di", IX86_BUILTIN_PSLLVV4DI, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlvv2di, "__builtin_ia32_psllv2di", IX86_BUILTIN_PSLLVV2DI, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlvv8si, "__builtin_ia32_psllv8si", IX86_BUILTIN_PSLLVV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI },
- { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshlvv4si, "__builtin_ia32_psllv4si", IX86_BUILTIN_PSLLVV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ashlvv4di, "__builtin_ia32_psllv4di", IX86_BUILTIN_PSLLVV4DI, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ashlvv2di, "__builtin_ia32_psllv2di", IX86_BUILTIN_PSLLVV2DI, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ashlvv8si, "__builtin_ia32_psllv8si", IX86_BUILTIN_PSLLVV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI },
+ { OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ashlvv4si, "__builtin_ia32_psllv4si", IX86_BUILTIN_PSLLVV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ashrvv8si, "__builtin_ia32_psrav8si", IX86_BUILTIN_PSRAVV8SI, UNKNOWN, (int) V8SI_FTYPE_V8SI_V8SI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_ashrvv4si, "__builtin_ia32_psrav4si", IX86_BUILTIN_PSRAVV4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI },
{ OPTION_MASK_ISA_AVX2, CODE_FOR_avx2_lshrvv4di, "__builtin_ia32_psrlv4di", IX86_BUILTIN_PSRLVV4DI, UNKNOWN, (int) V4DI_FTYPE_V4DI_V4DI },
@@ -26401,14 +26575,14 @@ static const struct builtin_description bdesc_multi_arg[] =
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_rotlv4si3, "__builtin_ia32_vprotdi", IX86_BUILTIN_VPROTD_IMM, UNKNOWN, (int)MULTI_ARG_2_SI_IMM },
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_rotlv8hi3, "__builtin_ia32_vprotwi", IX86_BUILTIN_VPROTW_IMM, UNKNOWN, (int)MULTI_ARG_2_HI_IMM },
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_rotlv16qi3, "__builtin_ia32_vprotbi", IX86_BUILTIN_VPROTB_IMM, UNKNOWN, (int)MULTI_ARG_2_QI_IMM },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_ashlv2di3, "__builtin_ia32_vpshaq", IX86_BUILTIN_VPSHAQ, UNKNOWN, (int)MULTI_ARG_2_DI },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_ashlv4si3, "__builtin_ia32_vpshad", IX86_BUILTIN_VPSHAD, UNKNOWN, (int)MULTI_ARG_2_SI },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_ashlv8hi3, "__builtin_ia32_vpshaw", IX86_BUILTIN_VPSHAW, UNKNOWN, (int)MULTI_ARG_2_HI },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_ashlv16qi3, "__builtin_ia32_vpshab", IX86_BUILTIN_VPSHAB, UNKNOWN, (int)MULTI_ARG_2_QI },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_lshlv2di3, "__builtin_ia32_vpshlq", IX86_BUILTIN_VPSHLQ, UNKNOWN, (int)MULTI_ARG_2_DI },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_lshlv4si3, "__builtin_ia32_vpshld", IX86_BUILTIN_VPSHLD, UNKNOWN, (int)MULTI_ARG_2_SI },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_lshlv8hi3, "__builtin_ia32_vpshlw", IX86_BUILTIN_VPSHLW, UNKNOWN, (int)MULTI_ARG_2_HI },
- { OPTION_MASK_ISA_XOP, CODE_FOR_xop_lshlv16qi3, "__builtin_ia32_vpshlb", IX86_BUILTIN_VPSHLB, UNKNOWN, (int)MULTI_ARG_2_QI },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shav2di3, "__builtin_ia32_vpshaq", IX86_BUILTIN_VPSHAQ, UNKNOWN, (int)MULTI_ARG_2_DI },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shav4si3, "__builtin_ia32_vpshad", IX86_BUILTIN_VPSHAD, UNKNOWN, (int)MULTI_ARG_2_SI },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shav8hi3, "__builtin_ia32_vpshaw", IX86_BUILTIN_VPSHAW, UNKNOWN, (int)MULTI_ARG_2_HI },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shav16qi3, "__builtin_ia32_vpshab", IX86_BUILTIN_VPSHAB, UNKNOWN, (int)MULTI_ARG_2_QI },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv2di3, "__builtin_ia32_vpshlq", IX86_BUILTIN_VPSHLQ, UNKNOWN, (int)MULTI_ARG_2_DI },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv4si3, "__builtin_ia32_vpshld", IX86_BUILTIN_VPSHLD, UNKNOWN, (int)MULTI_ARG_2_SI },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv8hi3, "__builtin_ia32_vpshlw", IX86_BUILTIN_VPSHLW, UNKNOWN, (int)MULTI_ARG_2_HI },
+ { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv16qi3, "__builtin_ia32_vpshlb", IX86_BUILTIN_VPSHLB, UNKNOWN, (int)MULTI_ARG_2_QI },
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv4sf2, "__builtin_ia32_vfrczss", IX86_BUILTIN_VFRCZSS, UNKNOWN, (int)MULTI_ARG_2_SF },
{ OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv2df2, "__builtin_ia32_vfrczsd", IX86_BUILTIN_VFRCZSD, UNKNOWN, (int)MULTI_ARG_2_DF },
@@ -28558,20 +28732,6 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
case IX86_BUILTIN_VEC_SET_V16QI:
return ix86_expand_vec_set_builtin (exp);
- case IX86_BUILTIN_VEC_PERM_V2DF:
- case IX86_BUILTIN_VEC_PERM_V4SF:
- case IX86_BUILTIN_VEC_PERM_V2DI:
- case IX86_BUILTIN_VEC_PERM_V4SI:
- case IX86_BUILTIN_VEC_PERM_V8HI:
- case IX86_BUILTIN_VEC_PERM_V16QI:
- case IX86_BUILTIN_VEC_PERM_V2DI_U:
- case IX86_BUILTIN_VEC_PERM_V4SI_U:
- case IX86_BUILTIN_VEC_PERM_V8HI_U:
- case IX86_BUILTIN_VEC_PERM_V16QI_U:
- case IX86_BUILTIN_VEC_PERM_V4DF:
- case IX86_BUILTIN_VEC_PERM_V8SF:
- return ix86_expand_vec_perm_builtin (exp);
-
case IX86_BUILTIN_INFQ:
case IX86_BUILTIN_HUGE_VALQ:
{
@@ -28748,7 +28908,6 @@ rdrand_step:
op4 = expand_normal (arg4);
/* Note the arg order is different from the operand order. */
mode0 = insn_data[icode].operand[1].mode;
- mode1 = insn_data[icode].operand[2].mode;
mode2 = insn_data[icode].operand[3].mode;
mode3 = insn_data[icode].operand[4].mode;
mode4 = insn_data[icode].operand[5].mode;
@@ -28762,12 +28921,11 @@ rdrand_step:
if (GET_MODE (op1) != Pmode)
op1 = convert_to_mode (Pmode, op1, 1);
op1 = force_reg (Pmode, op1);
- op1 = gen_rtx_MEM (mode1, op1);
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);
+ if (!insn_data[icode].operand[2].predicate (op1, Pmode))
+ op1 = copy_to_mode_reg (Pmode, op1);
if (!insn_data[icode].operand[3].predicate (op2, mode2))
op2 = copy_to_mode_reg (mode2, op2);
if (!insn_data[icode].operand[4].predicate (op3, mode3))
@@ -29285,96 +29443,6 @@ ix86_veclibabi_acml (enum built_in_function fn, tree type_out, tree type_in)
return new_fndecl;
}
-
-/* Returns a decl of a function that implements conversion of an integer vector
- into a floating-point vector, or vice-versa. DEST_TYPE and SRC_TYPE
- are the types involved when converting according to CODE.
- Return NULL_TREE if it is not available. */
-
-static tree
-ix86_vectorize_builtin_conversion (unsigned int code,
- tree dest_type, tree src_type)
-{
- if (! TARGET_SSE2)
- return NULL_TREE;
-
- switch (code)
- {
- case FLOAT_EXPR:
- switch (TYPE_MODE (src_type))
- {
- case V4SImode:
- switch (TYPE_MODE (dest_type))
- {
- case V4SFmode:
- return (TYPE_UNSIGNED (src_type)
- ? ix86_builtins[IX86_BUILTIN_CVTUDQ2PS]
- : ix86_builtins[IX86_BUILTIN_CVTDQ2PS]);
- case V4DFmode:
- return (TYPE_UNSIGNED (src_type)
- ? NULL_TREE
- : ix86_builtins[IX86_BUILTIN_CVTDQ2PD256]);
- default:
- return NULL_TREE;
- }
- break;
- case V8SImode:
- switch (TYPE_MODE (dest_type))
- {
- case V8SFmode:
- return (TYPE_UNSIGNED (src_type)
- ? NULL_TREE
- : ix86_builtins[IX86_BUILTIN_CVTDQ2PS256]);
- default:
- return NULL_TREE;
- }
- break;
- default:
- return NULL_TREE;
- }
-
- case FIX_TRUNC_EXPR:
- switch (TYPE_MODE (dest_type))
- {
- case V4SImode:
- switch (TYPE_MODE (src_type))
- {
- case V4SFmode:
- return (TYPE_UNSIGNED (dest_type)
- ? NULL_TREE
- : ix86_builtins[IX86_BUILTIN_CVTTPS2DQ]);
- case V4DFmode:
- return (TYPE_UNSIGNED (dest_type)
- ? NULL_TREE
- : ix86_builtins[IX86_BUILTIN_CVTTPD2DQ256]);
- default:
- return NULL_TREE;
- }
- break;
-
- case V8SImode:
- switch (TYPE_MODE (src_type))
- {
- case V8SFmode:
- return (TYPE_UNSIGNED (dest_type)
- ? NULL_TREE
- : ix86_builtins[IX86_BUILTIN_CVTTPS2DQ256]);
- default:
- return NULL_TREE;
- }
- break;
-
- default:
- return NULL_TREE;
- }
-
- default:
- return NULL_TREE;
- }
-
- return NULL_TREE;
-}
-
/* Returns a code for a target-specific builtin that implements
reciprocal of the function, or NULL_TREE if not available. */
@@ -31775,9 +31843,9 @@ x86_emit_floatuns (rtx operands[2])
emit_label (donelab);
}
-/* AVX does not support 32-byte integer vector operations,
- thus the longest vector we are faced with is V16QImode. */
-#define MAX_VECT_LEN 16
+/* AVX2 does support 32-byte integer vector operations,
+ thus the longest vector we are faced with is V32QImode. */
+#define MAX_VECT_LEN 32
struct expand_vec_perm_d
{
@@ -31790,9 +31858,6 @@ struct expand_vec_perm_d
static bool expand_vec_perm_1 (struct expand_vec_perm_d *d);
static bool expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d);
-static int extract_vec_perm_cst (struct expand_vec_perm_d *, tree);
-static bool ix86_vectorize_builtin_vec_perm_ok (tree vec_type, tree mask);
-
/* Get a vector mode of the same size as the original but with elements
twice as wide. This is only guaranteed to apply to integral vectors. */
@@ -33114,72 +33179,100 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt)
}
}
-/* Expand a vector reduction. FN is the binary pattern to reduce;
- DEST is the destination; IN is the input vector. */
+/* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC
+ to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode.
+ The upper bits of DEST are undefined, though they shouldn't cause
+ exceptions (some bits from src or all zeros are ok). */
-void
-ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
+static void
+emit_reduc_half (rtx dest, rtx src, int i)
{
- rtx tmp1, tmp2, tmp3, tmp4, tmp5;
- enum machine_mode mode = GET_MODE (in);
- int i;
-
- tmp1 = gen_reg_rtx (mode);
- tmp2 = gen_reg_rtx (mode);
- tmp3 = gen_reg_rtx (mode);
-
- switch (mode)
+ rtx tem;
+ switch (GET_MODE (src))
{
case V4SFmode:
- emit_insn (gen_sse_movhlps (tmp1, in, in));
- emit_insn (fn (tmp2, tmp1, in));
- emit_insn (gen_sse_shufps_v4sf (tmp3, tmp2, tmp2,
- const1_rtx, const1_rtx,
- GEN_INT (1+4), GEN_INT (1+4)));
+ if (i == 128)
+ tem = gen_sse_movhlps (dest, src, src);
+ else
+ tem = gen_sse_shufps_v4sf (dest, src, src, const1_rtx, const1_rtx,
+ GEN_INT (1 + 4), GEN_INT (1 + 4));
+ break;
+ case V2DFmode:
+ tem = gen_vec_interleave_highv2df (dest, src, src);
+ break;
+ case V16QImode:
+ case V8HImode:
+ case V4SImode:
+ case V2DImode:
+ tem = gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, dest),
+ gen_lowpart (V1TImode, src),
+ GEN_INT (i / 2));
break;
case V8SFmode:
- tmp4 = gen_reg_rtx (mode);
- tmp5 = gen_reg_rtx (mode);
- emit_insn (gen_avx_vperm2f128v8sf3 (tmp4, in, in, const1_rtx));
- emit_insn (fn (tmp5, tmp4, in));
- emit_insn (gen_avx_shufps256 (tmp1, tmp5, tmp5, GEN_INT (2+12)));
- emit_insn (fn (tmp2, tmp1, tmp5));
- emit_insn (gen_avx_shufps256 (tmp3, tmp2, tmp2, const1_rtx));
+ if (i == 256)
+ tem = gen_avx_vperm2f128v8sf3 (dest, src, src, const1_rtx);
+ else
+ tem = gen_avx_shufps256 (dest, src, src,
+ GEN_INT (i == 128 ? 2 + (3 << 2) : 1));
break;
case V4DFmode:
- emit_insn (gen_avx_vperm2f128v4df3 (tmp1, in, in, const1_rtx));
- emit_insn (fn (tmp2, tmp1, in));
- emit_insn (gen_avx_shufpd256 (tmp3, tmp2, tmp2, const1_rtx));
+ if (i == 256)
+ tem = gen_avx_vperm2f128v4df3 (dest, src, src, const1_rtx);
+ else
+ tem = gen_avx_shufpd256 (dest, src, src, const1_rtx);
break;
case V32QImode:
case V16HImode:
case V8SImode:
case V4DImode:
- emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, tmp1),
- gen_lowpart (V4DImode, in),
- gen_lowpart (V4DImode, in),
- const1_rtx));
- tmp4 = in;
- tmp5 = tmp1;
- for (i = 64; i >= GET_MODE_BITSIZE (GET_MODE_INNER (mode)); i >>= 1)
- {
- if (i != 64)
- {
- tmp2 = gen_reg_rtx (mode);
- tmp3 = gen_reg_rtx (mode);
- }
- emit_insn (fn (tmp2, tmp4, tmp5));
- emit_insn (gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, tmp3),
- gen_lowpart (V2TImode, tmp2),
- GEN_INT (i)));
- tmp4 = tmp2;
- tmp5 = tmp3;
- }
+ if (i == 256)
+ tem = gen_avx2_permv2ti (gen_lowpart (V4DImode, dest),
+ gen_lowpart (V4DImode, src),
+ gen_lowpart (V4DImode, src),
+ const1_rtx);
+ else
+ tem = gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, dest),
+ gen_lowpart (V2TImode, src),
+ GEN_INT (i / 2));
break;
default:
gcc_unreachable ();
}
- emit_insn (fn (dest, tmp2, tmp3));
+ emit_insn (tem);
+}
+
+/* Expand a vector reduction. FN is the binary pattern to reduce;
+ DEST is the destination; IN is the input vector. */
+
+void
+ix86_expand_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in)
+{
+ rtx half, dst, vec = in;
+ enum machine_mode mode = GET_MODE (in);
+ int i;
+
+ /* SSE4 has a special instruction for V8HImode UMIN reduction. */
+ if (TARGET_SSE4_1
+ && mode == V8HImode
+ && fn == gen_uminv8hi3)
+ {
+ emit_insn (gen_sse4_1_phminposuw (dest, in));
+ return;
+ }
+
+ for (i = GET_MODE_BITSIZE (mode);
+ i > GET_MODE_BITSIZE (GET_MODE_INNER (mode));
+ i >>= 1)
+ {
+ half = gen_reg_rtx (mode);
+ emit_reduc_half (half, vec, i);
+ if (i == GET_MODE_BITSIZE (GET_MODE_INNER (mode)) * 2)
+ dst = dest;
+ else
+ dst = gen_reg_rtx (mode);
+ emit_insn (fn (dst, half, vec));
+ vec = dst;
+ }
}
/* Target hook for scalar_mode_supported_p. */
@@ -33514,6 +33607,8 @@ void ix86_emit_swdivsf (rtx res, rtx a, rtx b, enum machine_mode mode)
/* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
+ b = force_reg (mode, b);
+
/* x0 = rcp(b) estimate */
emit_insn (gen_rtx_SET (VOIDmode, x0,
gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
@@ -33569,6 +33664,8 @@ void ix86_emit_swsqrtsf (rtx res, rtx a, enum machine_mode mode,
/* sqrt(a) = -0.5 * a * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0)
rsqrt(a) = -0.5 * rsqrtss(a) * (a * rsqrtss(a) * rsqrtss(a) - 3.0) */
+ a = force_reg (mode, a);
+
/* x0 = rsqrt(a) estimate */
emit_insn (gen_rtx_SET (VOIDmode, x0,
gen_rtx_UNSPEC (mode, gen_rtvec (1, a),
@@ -34453,64 +34550,6 @@ ix86_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
}
-/* Implement targetm.vectorize.builtin_vec_perm. */
-
-static tree
-ix86_vectorize_builtin_vec_perm (tree vec_type, tree *mask_type)
-{
- tree itype = TREE_TYPE (vec_type);
- bool u = TYPE_UNSIGNED (itype);
- enum machine_mode vmode = TYPE_MODE (vec_type);
- enum ix86_builtins fcode;
- bool ok = TARGET_SSE2;
-
- switch (vmode)
- {
- case V4DFmode:
- ok = TARGET_AVX;
- fcode = IX86_BUILTIN_VEC_PERM_V4DF;
- goto get_di;
- case V2DFmode:
- fcode = IX86_BUILTIN_VEC_PERM_V2DF;
- get_di:
- itype = ix86_get_builtin_type (IX86_BT_DI);
- break;
-
- case V8SFmode:
- ok = TARGET_AVX;
- fcode = IX86_BUILTIN_VEC_PERM_V8SF;
- goto get_si;
- case V4SFmode:
- ok = TARGET_SSE;
- fcode = IX86_BUILTIN_VEC_PERM_V4SF;
- get_si:
- itype = ix86_get_builtin_type (IX86_BT_SI);
- break;
-
- case V2DImode:
- fcode = u ? IX86_BUILTIN_VEC_PERM_V2DI_U : IX86_BUILTIN_VEC_PERM_V2DI;
- break;
- case V4SImode:
- fcode = u ? IX86_BUILTIN_VEC_PERM_V4SI_U : IX86_BUILTIN_VEC_PERM_V4SI;
- break;
- case V8HImode:
- fcode = u ? IX86_BUILTIN_VEC_PERM_V8HI_U : IX86_BUILTIN_VEC_PERM_V8HI;
- break;
- case V16QImode:
- fcode = u ? IX86_BUILTIN_VEC_PERM_V16QI_U : IX86_BUILTIN_VEC_PERM_V16QI;
- break;
- default:
- ok = false;
- break;
- }
-
- if (!ok)
- return NULL_TREE;
-
- *mask_type = itype;
- return ix86_builtins[(int) fcode];
-}
-
/* Return a vector mode with twice as many elements as VMODE. */
/* ??? Consider moving this to a table generated by genmodes.c. */
@@ -34584,7 +34623,7 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
}
/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to implement D
- in terms of blendp[sd] / pblendw / pblendvb. */
+ in terms of blendp[sd] / pblendw / pblendvb / vpblendd. */
static bool
expand_vec_perm_blend (struct expand_vec_perm_d *d)
@@ -34592,10 +34631,17 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
enum machine_mode vmode = d->vmode;
unsigned i, mask, nelt = d->nelt;
rtx target, op0, op1, x;
+ rtx rperm[32], vperm;
- if (!TARGET_SSE4_1 || d->op0 == d->op1)
+ if (d->op0 == d->op1)
return false;
- if (!(GET_MODE_SIZE (vmode) == 16 || vmode == V4DFmode || vmode == V8SFmode))
+ if (TARGET_AVX2 && GET_MODE_SIZE (vmode) == 32)
+ ;
+ else if (TARGET_AVX && (vmode == V4DFmode || vmode == V8SFmode))
+ ;
+ else if (TARGET_SSE4_1 && GET_MODE_SIZE (vmode) == 16)
+ ;
+ else
return false;
/* This is a blend, not a permute. Elements must stay in their
@@ -34613,30 +34659,6 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
/* ??? Without SSE4.1, we could implement this with and/andn/or. This
decision should be extracted elsewhere, so that we only try that
sequence once all budget==3 options have been tried. */
-
- /* For bytes, see if bytes move in pairs so we can use pblendw with
- an immediate argument, rather than pblendvb with a vector argument. */
- if (vmode == V16QImode)
- {
- bool pblendw_ok = true;
- for (i = 0; i < 16 && pblendw_ok; i += 2)
- pblendw_ok = (d->perm[i] + 1 == d->perm[i + 1]);
-
- if (!pblendw_ok)
- {
- rtx rperm[16], vperm;
-
- for (i = 0; i < nelt; ++i)
- rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
-
- vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm));
- vperm = force_reg (V16QImode, vperm);
-
- emit_insn (gen_sse4_1_pblendvb (d->target, d->op0, d->op1, vperm));
- return true;
- }
- }
-
target = d->target;
op0 = d->op0;
op1 = d->op1;
@@ -34649,6 +34671,7 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
case V2DFmode:
case V4SFmode:
case V8HImode:
+ case V8SImode:
for (i = 0; i < nelt; ++i)
mask |= (d->perm[i] >= nelt) << i;
break;
@@ -34656,24 +34679,122 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d)
case V2DImode:
for (i = 0; i < 2; ++i)
mask |= (d->perm[i] >= 2 ? 15 : 0) << (i * 4);
+ vmode = V8HImode;
goto do_subreg;
case V4SImode:
for (i = 0; i < 4; ++i)
mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
+ vmode = V8HImode;
goto do_subreg;
case V16QImode:
+ /* See if bytes move in pairs so we can use pblendw with
+ an immediate argument, rather than pblendvb with a vector
+ argument. */
+ for (i = 0; i < 16; i += 2)
+ if (d->perm[i] + 1 != d->perm[i + 1])
+ {
+ use_pblendvb:
+ for (i = 0; i < nelt; ++i)
+ rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
+
+ finish_pblendvb:
+ vperm = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm));
+ vperm = force_reg (vmode, vperm);
+
+ if (GET_MODE_SIZE (vmode) == 16)
+ emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm));
+ else
+ emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm));
+ return true;
+ }
+
for (i = 0; i < 8; ++i)
mask |= (d->perm[i * 2] >= 16) << i;
+ vmode = V8HImode;
+ /* FALLTHRU */
do_subreg:
- vmode = V8HImode;
target = gen_lowpart (vmode, target);
op0 = gen_lowpart (vmode, op0);
op1 = gen_lowpart (vmode, op1);
break;
+ case V32QImode:
+ /* See if bytes move in pairs. If not, vpblendvb must be used. */
+ for (i = 0; i < 32; i += 2)
+ if (d->perm[i] + 1 != d->perm[i + 1])
+ goto use_pblendvb;
+ /* See if bytes move in quadruplets. If yes, vpblendd
+ with immediate can be used. */
+ for (i = 0; i < 32; i += 4)
+ if (d->perm[i] + 2 != d->perm[i + 2])
+ break;
+ if (i < 32)
+ {
+ /* See if bytes move the same in both lanes. If yes,
+ vpblendw with immediate can be used. */
+ for (i = 0; i < 16; i += 2)
+ if (d->perm[i] + 16 != d->perm[i + 16])
+ goto use_pblendvb;
+
+ /* Use vpblendw. */
+ for (i = 0; i < 16; ++i)
+ mask |= (d->perm[i * 2] >= 32) << i;
+ vmode = V16HImode;
+ goto do_subreg;
+ }
+
+ /* Use vpblendd. */
+ for (i = 0; i < 8; ++i)
+ mask |= (d->perm[i * 4] >= 32) << i;
+ vmode = V8SImode;
+ goto do_subreg;
+
+ case V16HImode:
+ /* See if words move in pairs. If yes, vpblendd can be used. */
+ for (i = 0; i < 16; i += 2)
+ if (d->perm[i] + 1 != d->perm[i + 1])
+ break;
+ if (i < 16)
+ {
+ /* See if words move the same in both lanes. If not,
+ vpblendvb must be used. */
+ for (i = 0; i < 8; i++)
+ if (d->perm[i] + 8 != d->perm[i + 8])
+ {
+ /* Use vpblendvb. */
+ for (i = 0; i < 32; ++i)
+ rperm[i] = (d->perm[i / 2] < 16 ? const0_rtx : constm1_rtx);
+
+ vmode = V32QImode;
+ nelt = 32;
+ target = gen_lowpart (vmode, target);
+ op0 = gen_lowpart (vmode, op0);
+ op1 = gen_lowpart (vmode, op1);
+ goto finish_pblendvb;
+ }
+
+ /* Use vpblendw. */
+ for (i = 0; i < 16; ++i)
+ mask |= (d->perm[i] >= 16) << i;
+ break;
+ }
+
+ /* Use vpblendd. */
+ for (i = 0; i < 8; ++i)
+ mask |= (d->perm[i * 2] >= 16) << i;
+ vmode = V8SImode;
+ goto do_subreg;
+
+ case V4DImode:
+ /* Use vpblendd. */
+ for (i = 0; i < 4; ++i)
+ mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
+ vmode = V8SImode;
+ goto do_subreg;
+
default:
gcc_unreachable ();
}
@@ -34734,43 +34855,165 @@ expand_vec_perm_vpermil (struct expand_vec_perm_d *d)
return true;
}
-/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to implement D
- in terms of pshufb or vpperm. */
+/* Return true if permutation D can be performed as VMODE permutation
+ instead. */
static bool
-expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
+valid_perm_using_mode_p (enum machine_mode vmode, struct expand_vec_perm_d *d)
{
- unsigned i, nelt, eltsz;
- rtx rperm[16], vperm, target, op0, op1;
+ unsigned int i, j, chunk;
- if (!(d->op0 == d->op1 ? TARGET_SSSE3 : TARGET_XOP))
- return false;
- if (GET_MODE_SIZE (d->vmode) != 16)
+ if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT
+ || GET_MODE_CLASS (d->vmode) != MODE_VECTOR_INT
+ || GET_MODE_SIZE (vmode) != GET_MODE_SIZE (d->vmode))
return false;
- if (d->testing_p)
+ if (GET_MODE_NUNITS (vmode) >= d->nelt)
return true;
+ chunk = d->nelt / GET_MODE_NUNITS (vmode);
+ for (i = 0; i < d->nelt; i += chunk)
+ if (d->perm[i] & (chunk - 1))
+ return false;
+ else
+ for (j = 1; j < chunk; ++j)
+ if (d->perm[i] + j != d->perm[i + j])
+ return false;
+
+ return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to implement D
+ in terms of pshufb, vpperm, vpermq, vpermd or vperm2i128. */
+
+static bool
+expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
+{
+ unsigned i, nelt, eltsz, mask;
+ unsigned char perm[32];
+ enum machine_mode vmode = V16QImode;
+ rtx rperm[32], vperm, target, op0, op1;
+
nelt = d->nelt;
- eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
- for (i = 0; i < nelt; ++i)
+ if (d->op0 != d->op1)
{
- unsigned j, e = d->perm[i];
- for (j = 0; j < eltsz; ++j)
- rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
+ if (!TARGET_XOP || GET_MODE_SIZE (d->vmode) != 16)
+ {
+ if (TARGET_AVX2
+ && valid_perm_using_mode_p (V2TImode, d))
+ {
+ if (d->testing_p)
+ return true;
+
+ /* Use vperm2i128 insn. The pattern uses
+ V4DImode instead of V2TImode. */
+ target = gen_lowpart (V4DImode, d->target);
+ op0 = gen_lowpart (V4DImode, d->op0);
+ op1 = gen_lowpart (V4DImode, d->op1);
+ rperm[0]
+ = GEN_INT (((d->perm[0] & (nelt / 2)) ? 1 : 0)
+ || ((d->perm[nelt / 2] & (nelt / 2)) ? 2 : 0));
+ emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0]));
+ return true;
+ }
+ return false;
+ }
}
+ else
+ {
+ if (GET_MODE_SIZE (d->vmode) == 16)
+ {
+ if (!TARGET_SSSE3)
+ return false;
+ }
+ else if (GET_MODE_SIZE (d->vmode) == 32)
+ {
+ if (!TARGET_AVX2)
+ return false;
- vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm));
- vperm = force_reg (V16QImode, vperm);
+ /* V4DImode should be already handled through
+ expand_vselect by vpermq instruction. */
+ gcc_assert (d->vmode != V4DImode);
+
+ vmode = V32QImode;
+ if (d->vmode == V8SImode
+ || d->vmode == V16HImode
+ || d->vmode == V32QImode)
+ {
+ /* First see if vpermq can be used for
+ V8SImode/V16HImode/V32QImode. */
+ if (valid_perm_using_mode_p (V4DImode, d))
+ {
+ for (i = 0; i < 4; i++)
+ perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3;
+ if (d->testing_p)
+ return true;
+ return expand_vselect (gen_lowpart (V4DImode, d->target),
+ gen_lowpart (V4DImode, d->op0),
+ perm, 4);
+ }
+
+ /* Next see if vpermd can be used. */
+ if (valid_perm_using_mode_p (V8SImode, d))
+ vmode = V8SImode;
+ }
+
+ if (vmode == V32QImode)
+ {
+ /* vpshufb only works intra lanes, it is not
+ possible to shuffle bytes in between the lanes. */
+ for (i = 0; i < nelt; ++i)
+ if ((d->perm[i] ^ i) & (nelt / 2))
+ return false;
+ }
+ }
+ else
+ return false;
+ }
- target = gen_lowpart (V16QImode, d->target);
- op0 = gen_lowpart (V16QImode, d->op0);
+ if (d->testing_p)
+ return true;
+
+ if (vmode == V8SImode)
+ for (i = 0; i < 8; ++i)
+ rperm[i] = GEN_INT ((d->perm[i * nelt / 8] * 8 / nelt) & 7);
+ else
+ {
+ eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+ if (d->op0 != d->op1)
+ mask = 2 * nelt - 1;
+ else if (vmode == V16QImode)
+ mask = nelt - 1;
+ else
+ mask = nelt / 2 - 1;
+
+ for (i = 0; i < nelt; ++i)
+ {
+ unsigned j, e = d->perm[i] & mask;
+ for (j = 0; j < eltsz; ++j)
+ rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
+ }
+ }
+
+ vperm = gen_rtx_CONST_VECTOR (vmode,
+ gen_rtvec_v (GET_MODE_NUNITS (vmode), rperm));
+ vperm = force_reg (vmode, vperm);
+
+ target = gen_lowpart (vmode, d->target);
+ op0 = gen_lowpart (vmode, d->op0);
if (d->op0 == d->op1)
- emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, vperm));
+ {
+ if (vmode == V16QImode)
+ emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, vperm));
+ else if (vmode == V32QImode)
+ emit_insn (gen_avx2_pshufbv32qi3 (target, op0, vperm));
+ else
+ emit_insn (gen_avx2_permvarv8si (target, vperm, op0));
+ }
else
{
- op1 = gen_lowpart (V16QImode, d->op1);
+ op1 = gen_lowpart (vmode, d->op1);
emit_insn (gen_xop_pperm (target, op0, op1, vperm));
}
@@ -34792,9 +35035,58 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
if (d->op0 == d->op1)
{
int mask = nelt - 1;
+ bool identity_perm = true;
+ bool broadcast_perm = true;
for (i = 0; i < nelt; i++)
- perm2[i] = d->perm[i] & mask;
+ {
+ perm2[i] = d->perm[i] & mask;
+ if (perm2[i] != i)
+ identity_perm = false;
+ if (perm2[i])
+ broadcast_perm = false;
+ }
+
+ if (identity_perm)
+ {
+ if (!d->testing_p)
+ emit_move_insn (d->target, d->op0);
+ return true;
+ }
+ else if (broadcast_perm && TARGET_AVX2)
+ {
+ /* Use vpbroadcast{b,w,d}. */
+ rtx op = d->op0, (*gen) (rtx, rtx) = NULL;
+ switch (d->vmode)
+ {
+ case V32QImode:
+ op = gen_lowpart (V16QImode, op);
+ gen = gen_avx2_pbroadcastv32qi;
+ break;
+ case V16HImode:
+ op = gen_lowpart (V8HImode, op);
+ gen = gen_avx2_pbroadcastv16hi;
+ break;
+ case V8SImode:
+ op = gen_lowpart (V4SImode, op);
+ gen = gen_avx2_pbroadcastv8si;
+ break;
+ case V16QImode:
+ gen = gen_avx2_pbroadcastv16qi;
+ break;
+ case V8HImode:
+ gen = gen_avx2_pbroadcastv8hi;
+ break;
+ /* For other modes prefer other shuffles this function creates. */
+ default: break;
+ }
+ if (gen != NULL)
+ {
+ if (!d->testing_p)
+ emit_insn (gen (d->target, op));
+ return true;
+ }
+ }
if (expand_vselect (d->target, d->op0, perm2, nelt))
return true;
@@ -34858,7 +35150,8 @@ expand_vec_perm_1 (struct expand_vec_perm_d *d)
if (expand_vec_perm_vpermil (d))
return true;
- /* Try the SSSE3 pshufb or XOP vpperm variable permutation. */
+ /* Try the SSSE3 pshufb or XOP vpperm or AVX2 vperm2i128,
+ vpshufb, vpermd or vpermq variable permutation. */
if (expand_vec_perm_pshufb (d))
return true;
@@ -34977,93 +35270,210 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
{
struct expand_vec_perm_d dremap, dfinal;
unsigned i, nelt = d->nelt, nelt2 = nelt / 2;
- unsigned contents, h1, h2, h3, h4;
+ unsigned HOST_WIDE_INT contents;
unsigned char remap[2 * MAX_VECT_LEN];
rtx seq;
- bool ok;
-
- if (d->op0 == d->op1)
- return false;
+ bool ok, same_halves = false;
- /* The 256-bit unpck[lh]p[sd] instructions only operate within the 128-bit
- lanes. We can use similar techniques with the vperm2f128 instruction,
- but it requires slightly different logic. */
- if (GET_MODE_SIZE (d->vmode) != 16)
+ if (GET_MODE_SIZE (d->vmode) == 16)
+ {
+ if (d->op0 == d->op1)
+ return false;
+ }
+ else if (GET_MODE_SIZE (d->vmode) == 32)
+ {
+ if (!TARGET_AVX)
+ return false;
+ /* For 32-byte modes allow even d->op0 == d->op1.
+ The lack of cross-lane shuffling in some instructions
+ might prevent a single insn shuffle. */
+ }
+ else
return false;
/* Examine from whence the elements come. */
contents = 0;
for (i = 0; i < nelt; ++i)
- contents |= 1u << d->perm[i];
-
- /* Split the two input vectors into 4 halves. */
- h1 = (1u << nelt2) - 1;
- h2 = h1 << nelt2;
- h3 = h2 << nelt2;
- h4 = h3 << nelt2;
+ contents |= ((unsigned HOST_WIDE_INT) 1) << d->perm[i];
memset (remap, 0xff, sizeof (remap));
dremap = *d;
- /* If the elements from the low halves use interleave low, and similarly
- for interleave high. If the elements are from mis-matched halves, we
- can use shufps for V4SF/V4SI or do a DImode shuffle. */
- if ((contents & (h1 | h3)) == contents)
+ if (GET_MODE_SIZE (d->vmode) == 16)
{
- for (i = 0; i < nelt2; ++i)
+ unsigned HOST_WIDE_INT h1, h2, h3, h4;
+
+ /* Split the two input vectors into 4 halves. */
+ h1 = (((unsigned HOST_WIDE_INT) 1) << nelt2) - 1;
+ h2 = h1 << nelt2;
+ h3 = h2 << nelt2;
+ h4 = h3 << nelt2;
+
+ /* If the elements from the low halves use interleave low, and similarly
+ for interleave high. If the elements are from mis-matched halves, we
+ can use shufps for V4SF/V4SI or do a DImode shuffle. */
+ if ((contents & (h1 | h3)) == contents)
{
- remap[i] = i * 2;
- remap[i + nelt] = i * 2 + 1;
- dremap.perm[i * 2] = i;
- dremap.perm[i * 2 + 1] = i + nelt;
+ /* punpckl* */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i] = i * 2;
+ remap[i + nelt] = i * 2 + 1;
+ dremap.perm[i * 2] = i;
+ dremap.perm[i * 2 + 1] = i + nelt;
+ }
}
- }
- else if ((contents & (h2 | h4)) == contents)
- {
- for (i = 0; i < nelt2; ++i)
+ else if ((contents & (h2 | h4)) == contents)
{
- remap[i + nelt2] = i * 2;
- remap[i + nelt + nelt2] = i * 2 + 1;
- dremap.perm[i * 2] = i + nelt2;
- dremap.perm[i * 2 + 1] = i + nelt + nelt2;
+ /* punpckh* */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i + nelt2] = i * 2;
+ remap[i + nelt + nelt2] = i * 2 + 1;
+ dremap.perm[i * 2] = i + nelt2;
+ dremap.perm[i * 2 + 1] = i + nelt + nelt2;
+ }
}
- }
- else if ((contents & (h1 | h4)) == contents)
- {
- for (i = 0; i < nelt2; ++i)
+ else if ((contents & (h1 | h4)) == contents)
{
- remap[i] = i;
- remap[i + nelt + nelt2] = i + nelt2;
- dremap.perm[i] = i;
- dremap.perm[i + nelt2] = i + nelt + nelt2;
+ /* shufps */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i] = i;
+ remap[i + nelt + nelt2] = i + nelt2;
+ dremap.perm[i] = i;
+ dremap.perm[i + nelt2] = i + nelt + nelt2;
+ }
+ if (nelt != 4)
+ {
+ /* shufpd */
+ dremap.vmode = V2DImode;
+ dremap.nelt = 2;
+ dremap.perm[0] = 0;
+ dremap.perm[1] = 3;
+ }
}
- if (nelt != 4)
+ else if ((contents & (h2 | h3)) == contents)
{
- dremap.vmode = V2DImode;
- dremap.nelt = 2;
- dremap.perm[0] = 0;
- dremap.perm[1] = 3;
+ /* shufps */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i + nelt2] = i;
+ remap[i + nelt] = i + nelt2;
+ dremap.perm[i] = i + nelt2;
+ dremap.perm[i + nelt2] = i + nelt;
+ }
+ if (nelt != 4)
+ {
+ /* shufpd */
+ dremap.vmode = V2DImode;
+ dremap.nelt = 2;
+ dremap.perm[0] = 1;
+ dremap.perm[1] = 2;
+ }
}
+ else
+ return false;
}
- else if ((contents & (h2 | h3)) == contents)
+ else
{
- for (i = 0; i < nelt2; ++i)
+ unsigned int nelt4 = nelt / 4, nzcnt = 0;
+ unsigned HOST_WIDE_INT q[8];
+ unsigned int nonzero_halves[4];
+
+ /* Split the two input vectors into 8 quarters. */
+ q[0] = (((unsigned HOST_WIDE_INT) 1) << nelt4) - 1;
+ for (i = 1; i < 8; ++i)
+ q[i] = q[0] << (nelt4 * i);
+ for (i = 0; i < 4; ++i)
+ if (((q[2 * i] | q[2 * i + 1]) & contents) != 0)
+ {
+ nonzero_halves[nzcnt] = i;
+ ++nzcnt;
+ }
+
+ if (nzcnt == 1)
{
- remap[i + nelt2] = i;
- remap[i + nelt] = i + nelt2;
- dremap.perm[i] = i + nelt2;
- dremap.perm[i + nelt2] = i + nelt;
+ gcc_assert (d->op0 == d->op1);
+ nonzero_halves[1] = nonzero_halves[0];
+ same_halves = true;
}
- if (nelt != 4)
+ else if (d->op0 == d->op1)
{
- dremap.vmode = V2DImode;
- dremap.nelt = 2;
- dremap.perm[0] = 1;
- dremap.perm[1] = 2;
+ gcc_assert (nonzero_halves[0] == 0);
+ gcc_assert (nonzero_halves[1] == 1);
}
+
+ if (nzcnt <= 2)
+ {
+ if (d->perm[0] / nelt2 == nonzero_halves[1])
+ {
+ /* Attempt to increase the likelyhood that dfinal
+ shuffle will be intra-lane. */
+ char tmph = nonzero_halves[0];
+ nonzero_halves[0] = nonzero_halves[1];
+ nonzero_halves[1] = tmph;
+ }
+
+ /* vperm2f128 or vperm2i128. */
+ for (i = 0; i < nelt2; ++i)
+ {
+ remap[i + nonzero_halves[1] * nelt2] = i + nelt2;
+ remap[i + nonzero_halves[0] * nelt2] = i;
+ dremap.perm[i + nelt2] = i + nonzero_halves[1] * nelt2;
+ dremap.perm[i] = i + nonzero_halves[0] * nelt2;
+ }
+
+ if (d->vmode != V8SFmode
+ && d->vmode != V4DFmode
+ && d->vmode != V8SImode)
+ {
+ dremap.vmode = V8SImode;
+ dremap.nelt = 8;
+ for (i = 0; i < 4; ++i)
+ {
+ dremap.perm[i] = i + nonzero_halves[0] * 4;
+ dremap.perm[i + 4] = i + nonzero_halves[1] * 4;
+ }
+ }
+ }
+ else if (d->op0 == d->op1)
+ return false;
+ else if (TARGET_AVX2
+ && (contents & (q[0] | q[2] | q[4] | q[6])) == contents)
+ {
+ /* vpunpckl* */
+ for (i = 0; i < nelt4; ++i)
+ {
+ remap[i] = i * 2;
+ remap[i + nelt] = i * 2 + 1;
+ remap[i + nelt2] = i * 2 + nelt2;
+ remap[i + nelt + nelt2] = i * 2 + nelt2 + 1;
+ dremap.perm[i * 2] = i;
+ dremap.perm[i * 2 + 1] = i + nelt;
+ dremap.perm[i * 2 + nelt2] = i + nelt2;
+ dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2;
+ }
+ }
+ else if (TARGET_AVX2
+ && (contents & (q[1] | q[3] | q[5] | q[7])) == contents)
+ {
+ /* vpunpckh* */
+ for (i = 0; i < nelt4; ++i)
+ {
+ remap[i + nelt4] = i * 2;
+ remap[i + nelt + nelt4] = i * 2 + 1;
+ remap[i + nelt2 + nelt4] = i * 2 + nelt2;
+ remap[i + nelt + nelt2 + nelt4] = i * 2 + nelt2 + 1;
+ dremap.perm[i * 2] = i + nelt4;
+ dremap.perm[i * 2 + 1] = i + nelt + nelt4;
+ dremap.perm[i * 2 + nelt2] = i + nelt2 + nelt4;
+ dremap.perm[i * 2 + nelt2 + 1] = i + nelt + nelt2 + nelt4;
+ }
+ }
+ else
+ return false;
}
- else
- return false;
/* Use the remapping array set up above to move the elements from their
swizzled locations into their final destinations. */
@@ -35072,7 +35482,15 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
{
unsigned e = remap[d->perm[i]];
gcc_assert (e < nelt);
- dfinal.perm[i] = e;
+ /* If same_halves is true, both halves of the remapped vector are the
+ same. Avoid cross-lane accesses if possible. */
+ if (same_halves && i >= nelt2)
+ {
+ gcc_assert (e < nelt2);
+ dfinal.perm[i] = e + nelt2;
+ }
+ else
+ dfinal.perm[i] = e;
}
dfinal.op0 = gen_reg_rtx (dfinal.vmode);
dfinal.op1 = dfinal.op0;
@@ -35088,6 +35506,9 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
if (!ok)
return false;
+ if (d->testing_p)
+ return true;
+
if (dremap.vmode != dfinal.vmode)
{
dremap.target = gen_lowpart (dremap.vmode, dremap.target);
@@ -35102,6 +35523,159 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
return true;
}
+/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to simplify
+ a single vector cross-lane permutation into vpermq followed
+ by any of the single insn permutations. */
+
+static bool
+expand_vec_perm_vpermq_perm_1 (struct expand_vec_perm_d *d)
+{
+ struct expand_vec_perm_d dremap, dfinal;
+ unsigned i, j, nelt = d->nelt, nelt2 = nelt / 2, nelt4 = nelt / 4;
+ unsigned contents[2];
+ bool ok;
+
+ if (!(TARGET_AVX2
+ && (d->vmode == V32QImode || d->vmode == V16HImode)
+ && d->op0 == d->op1))
+ return false;
+
+ contents[0] = 0;
+ contents[1] = 0;
+ for (i = 0; i < nelt2; ++i)
+ {
+ contents[0] |= 1u << (d->perm[i] / nelt4);
+ contents[1] |= 1u << (d->perm[i + nelt2] / nelt4);
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ unsigned int cnt = 0;
+ for (j = 0; j < 4; ++j)
+ if ((contents[i] & (1u << j)) != 0 && ++cnt > 2)
+ return false;
+ }
+
+ if (d->testing_p)
+ return true;
+
+ dremap = *d;
+ dremap.vmode = V4DImode;
+ dremap.nelt = 4;
+ dremap.target = gen_reg_rtx (V4DImode);
+ dremap.op0 = gen_lowpart (V4DImode, d->op0);
+ dremap.op1 = dremap.op0;
+ for (i = 0; i < 2; ++i)
+ {
+ unsigned int cnt = 0;
+ for (j = 0; j < 4; ++j)
+ if ((contents[i] & (1u << j)) != 0)
+ dremap.perm[2 * i + cnt++] = j;
+ for (; cnt < 2; ++cnt)
+ dremap.perm[2 * i + cnt] = 0;
+ }
+
+ dfinal = *d;
+ dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target);
+ dfinal.op1 = dfinal.op0;
+ for (i = 0, j = 0; i < nelt; ++i)
+ {
+ if (i == nelt2)
+ j = 2;
+ dfinal.perm[i] = (d->perm[i] & (nelt4 - 1)) | (j ? nelt2 : 0);
+ if ((d->perm[i] / nelt4) == dremap.perm[j])
+ ;
+ else if ((d->perm[i] / nelt4) == dremap.perm[j + 1])
+ dfinal.perm[i] |= nelt4;
+ else
+ gcc_unreachable ();
+ }
+
+ ok = expand_vec_perm_1 (&dremap);
+ gcc_assert (ok);
+
+ ok = expand_vec_perm_1 (&dfinal);
+ gcc_assert (ok);
+
+ return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1. Try to simplify
+ a two vector permutation using 2 intra-lane interleave insns
+ and cross-lane shuffle for 32-byte vectors. */
+
+static bool
+expand_vec_perm_interleave3 (struct expand_vec_perm_d *d)
+{
+ unsigned i, nelt;
+ rtx (*gen) (rtx, rtx, rtx);
+
+ if (d->op0 == d->op1)
+ return false;
+ if (TARGET_AVX2 && GET_MODE_SIZE (d->vmode) == 32)
+ ;
+ else if (TARGET_AVX && (d->vmode == V8SFmode || d->vmode == V4DFmode))
+ ;
+ else
+ return false;
+
+ nelt = d->nelt;
+ if (d->perm[0] != 0 && d->perm[0] != nelt / 2)
+ return false;
+ for (i = 0; i < nelt; i += 2)
+ if (d->perm[i] != d->perm[0] + i / 2
+ || d->perm[i + 1] != d->perm[0] + i / 2 + nelt)
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ switch (d->vmode)
+ {
+ case V32QImode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv32qi;
+ else
+ gen = gen_vec_interleave_lowv32qi;
+ break;
+ case V16HImode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv16hi;
+ else
+ gen = gen_vec_interleave_lowv16hi;
+ break;
+ case V8SImode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv8si;
+ else
+ gen = gen_vec_interleave_lowv8si;
+ break;
+ case V4DImode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv4di;
+ else
+ gen = gen_vec_interleave_lowv4di;
+ break;
+ case V8SFmode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv8sf;
+ else
+ gen = gen_vec_interleave_lowv8sf;
+ break;
+ case V4DFmode:
+ if (d->perm[0])
+ gen = gen_vec_interleave_highv4df;
+ else
+ gen = gen_vec_interleave_lowv4df;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ emit_insn (gen (d->target, d->op0, d->op1));
+ return true;
+}
+
/* A subroutine of expand_vec_perm_even_odd_1. Implement the double-word
permutation with two pshufb insns and an ior. We should have already
failed all two instruction sequences. */
@@ -35158,6 +35732,152 @@ expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
return true;
}
+/* Implement arbitrary permutation of one V32QImode and V16QImode operand
+ with two vpshufb insns, vpermq and vpor. We should have already failed
+ all two or three instruction sequences. */
+
+static bool
+expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d)
+{
+ rtx rperm[2][32], vperm, l, h, hp, op, m128;
+ unsigned int i, nelt, eltsz;
+
+ if (!TARGET_AVX2
+ || d->op0 != d->op1
+ || (d->vmode != V32QImode && d->vmode != V16HImode))
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ nelt = d->nelt;
+ eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+
+ /* Generate two permutation masks. If the required element is within
+ the same lane, it is shuffled in. If the required element from the
+ other lane, force a zero by setting bit 7 in the permutation mask.
+ In the other mask the mask has non-negative elements if element
+ is requested from the other lane, but also moved to the other lane,
+ so that the result of vpshufb can have the two V2TImode halves
+ swapped. */
+ m128 = GEN_INT (-128);
+ for (i = 0; i < nelt; ++i)
+ {
+ unsigned j, e = d->perm[i] & (nelt / 2 - 1);
+ unsigned which = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
+
+ for (j = 0; j < eltsz; ++j)
+ {
+ rperm[!!which][(i * eltsz + j) ^ which] = GEN_INT (e * eltsz + j);
+ rperm[!which][(i * eltsz + j) ^ (which ^ 16)] = m128;
+ }
+ }
+
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
+ vperm = force_reg (V32QImode, vperm);
+
+ h = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
+
+ /* Swap the 128-byte lanes of h into hp. */
+ hp = gen_reg_rtx (V4DImode);
+ op = gen_lowpart (V4DImode, h);
+ emit_insn (gen_avx2_permv4di_1 (hp, op, const2_rtx, GEN_INT (3), const0_rtx,
+ const1_rtx));
+
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
+ vperm = force_reg (V32QImode, vperm);
+
+ l = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
+
+ op = gen_lowpart (V32QImode, d->target);
+ emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp)));
+
+ return true;
+}
+
+/* A subroutine of expand_vec_perm_even_odd_1. Implement extract-even
+ and extract-odd permutations of two V32QImode and V16QImode operand
+ with two vpshufb insns, vpor and vpermq. We should have already
+ failed all two or three instruction sequences. */
+
+static bool
+expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d)
+{
+ rtx rperm[2][32], vperm, l, h, ior, op, m128;
+ unsigned int i, nelt, eltsz;
+
+ if (!TARGET_AVX2
+ || d->op0 == d->op1
+ || (d->vmode != V32QImode && d->vmode != V16HImode))
+ return false;
+
+ for (i = 0; i < d->nelt; ++i)
+ if ((d->perm[i] ^ (i * 2)) & (3 * d->nelt / 2))
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ nelt = d->nelt;
+ eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+
+ /* Generate two permutation masks. In the first permutation mask
+ the first quarter will contain indexes for the first half
+ of the op0, the second quarter will contain bit 7 set, third quarter
+ will contain indexes for the second half of the op0 and the
+ last quarter bit 7 set. In the second permutation mask
+ the first quarter will contain bit 7 set, the second quarter
+ indexes for the first half of the op1, the third quarter bit 7 set
+ and last quarter indexes for the second half of the op1.
+ I.e. the first mask e.g. for V32QImode extract even will be:
+ 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128
+ (all values masked with 0xf except for -128) and second mask
+ for extract even will be
+ -128, ..., -128, 0, 2, ..., 0xe, -128, ..., -128, 0, 2, ..., 0xe. */
+ m128 = GEN_INT (-128);
+ for (i = 0; i < nelt; ++i)
+ {
+ unsigned j, e = d->perm[i] & (nelt / 2 - 1);
+ unsigned which = d->perm[i] >= nelt;
+ unsigned xorv = (i >= nelt / 4 && i < 3 * nelt / 4) ? 24 : 0;
+
+ for (j = 0; j < eltsz; ++j)
+ {
+ rperm[which][(i * eltsz + j) ^ xorv] = GEN_INT (e * eltsz + j);
+ rperm[1 - which][(i * eltsz + j) ^ xorv] = m128;
+ }
+ }
+
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[0]));
+ vperm = force_reg (V32QImode, vperm);
+
+ l = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm));
+
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[1]));
+ vperm = force_reg (V32QImode, vperm);
+
+ h = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, d->op1);
+ emit_insn (gen_avx2_pshufbv32qi3 (h, op, vperm));
+
+ ior = gen_reg_rtx (V32QImode);
+ emit_insn (gen_iorv32qi3 (ior, l, h));
+
+ /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */
+ op = gen_lowpart (V4DImode, d->target);
+ ior = gen_lowpart (V4DImode, ior);
+ emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+
+ return true;
+}
+
/* A subroutine of ix86_expand_vec_perm_builtin_1. Implement extract-even
and extract-odd permutations. */
@@ -35267,6 +35987,81 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
}
break;
+ case V16HImode:
+ case V32QImode:
+ return expand_vec_perm_vpshufb2_vpermq_even_odd (d);
+
+ case V4DImode:
+ if (!TARGET_AVX2)
+ {
+ struct expand_vec_perm_d d_copy = *d;
+ d_copy.vmode = V4DFmode;
+ d_copy.target = gen_lowpart (V4DFmode, d->target);
+ d_copy.op0 = gen_lowpart (V4DFmode, d->op0);
+ d_copy.op1 = gen_lowpart (V4DFmode, d->op1);
+ return expand_vec_perm_even_odd_1 (&d_copy, odd);
+ }
+
+ t1 = gen_reg_rtx (V4DImode);
+ t2 = gen_reg_rtx (V4DImode);
+
+ /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }. */
+ emit_insn (gen_avx2_permv2ti (t1, d->op0, d->op1, GEN_INT (0x20)));
+ emit_insn (gen_avx2_permv2ti (t2, d->op0, d->op1, GEN_INT (0x31)));
+
+ /* Now an vpunpck[lh]qdq will produce the result required. */
+ if (odd)
+ t3 = gen_avx2_interleave_highv4di (d->target, t1, t2);
+ else
+ t3 = gen_avx2_interleave_lowv4di (d->target, t1, t2);
+ emit_insn (t3);
+ break;
+
+ case V8SImode:
+ if (!TARGET_AVX2)
+ {
+ struct expand_vec_perm_d d_copy = *d;
+ d_copy.vmode = V8SFmode;
+ d_copy.target = gen_lowpart (V8SFmode, d->target);
+ d_copy.op0 = gen_lowpart (V8SFmode, d->op0);
+ d_copy.op1 = gen_lowpart (V8SFmode, d->op1);
+ return expand_vec_perm_even_odd_1 (&d_copy, odd);
+ }
+
+ t1 = gen_reg_rtx (V8SImode);
+ t2 = gen_reg_rtx (V8SImode);
+
+ /* Shuffle the lanes around into
+ { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */
+ emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, d->op0),
+ gen_lowpart (V4DImode, d->op1),
+ GEN_INT (0x20)));
+ emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t2),
+ gen_lowpart (V4DImode, d->op0),
+ gen_lowpart (V4DImode, d->op1),
+ GEN_INT (0x31)));
+
+ /* Swap the 2nd and 3rd position in each lane into
+ { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */
+ emit_insn (gen_avx2_pshufdv3 (t1, t1,
+ GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
+ emit_insn (gen_avx2_pshufdv3 (t2, t2,
+ GEN_INT (2 * 4 + 1 * 16 + 3 * 64)));
+
+ /* Now an vpunpck[lh]qdq will produce
+ { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */
+ if (odd)
+ t3 = gen_avx2_interleave_highv4di (gen_lowpart (V4DImode, d->target),
+ gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2));
+ else
+ t3 = gen_avx2_interleave_lowv4di (gen_lowpart (V4DImode, d->target),
+ gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2));
+ emit_insn (t3);
+ break;
+
default:
gcc_unreachable ();
}
@@ -35347,6 +36142,15 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d)
gcc_assert (ok);
return true;
+ case V32QImode:
+ case V16HImode:
+ case V8SImode:
+ case V4DImode:
+ /* For AVX2 broadcasts of the first element vpbroadcast* or
+ vpermq should be used by expand_vec_perm_1. */
+ gcc_assert (!TARGET_AVX2 || d->perm[0]);
+ return false;
+
default:
gcc_unreachable ();
}
@@ -35371,12 +36175,123 @@ expand_vec_perm_broadcast (struct expand_vec_perm_d *d)
return expand_vec_perm_broadcast_1 (d);
}
-/* The guts of ix86_expand_vec_perm_builtin, also used by the ok hook.
+/* Implement arbitrary permutation of two V32QImode and V16QImode operands
+ with 4 vpshufb insns, 2 vpermq and 3 vpor. We should have already failed
+ all the shorter instruction sequences. */
+
+static bool
+expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d)
+{
+ rtx rperm[4][32], vperm, l[2], h[2], op, m128;
+ unsigned int i, nelt, eltsz;
+ bool used[4];
+
+ if (!TARGET_AVX2
+ || d->op0 == d->op1
+ || (d->vmode != V32QImode && d->vmode != V16HImode))
+ return false;
+
+ if (d->testing_p)
+ return true;
+
+ nelt = d->nelt;
+ eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+
+ /* Generate 4 permutation masks. If the required element is within
+ the same lane, it is shuffled in. If the required element from the
+ other lane, force a zero by setting bit 7 in the permutation mask.
+ In the other mask the mask has non-negative elements if element
+ is requested from the other lane, but also moved to the other lane,
+ so that the result of vpshufb can have the two V2TImode halves
+ swapped. */
+ m128 = GEN_INT (-128);
+ for (i = 0; i < 32; ++i)
+ {
+ rperm[0][i] = m128;
+ rperm[1][i] = m128;
+ rperm[2][i] = m128;
+ rperm[3][i] = m128;
+ }
+ used[0] = false;
+ used[1] = false;
+ used[2] = false;
+ used[3] = false;
+ for (i = 0; i < nelt; ++i)
+ {
+ unsigned j, e = d->perm[i] & (nelt / 2 - 1);
+ unsigned xlane = ((d->perm[i] ^ i) & (nelt / 2)) * eltsz;
+ unsigned int which = ((d->perm[i] & nelt) ? 2 : 0) + (xlane ? 1 : 0);
+
+ for (j = 0; j < eltsz; ++j)
+ rperm[which][(i * eltsz + j) ^ xlane] = GEN_INT (e * eltsz + j);
+ used[which] = true;
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (!used[2 * i + 1])
+ {
+ h[i] = NULL_RTX;
+ continue;
+ }
+ vperm = gen_rtx_CONST_VECTOR (V32QImode,
+ gen_rtvec_v (32, rperm[2 * i + 1]));
+ vperm = force_reg (V32QImode, vperm);
+ h[i] = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (h[i], op, vperm));
+ }
+
+ /* Swap the 128-byte lanes of h[X]. */
+ for (i = 0; i < 2; ++i)
+ {
+ if (h[i] == NULL_RTX)
+ continue;
+ op = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_permv4di_1 (op, gen_lowpart (V4DImode, h[i]),
+ const2_rtx, GEN_INT (3), const0_rtx,
+ const1_rtx));
+ h[i] = gen_lowpart (V32QImode, op);
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (!used[2 * i])
+ {
+ l[i] = NULL_RTX;
+ continue;
+ }
+ vperm = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, rperm[2 * i]));
+ vperm = force_reg (V32QImode, vperm);
+ l[i] = gen_reg_rtx (V32QImode);
+ op = gen_lowpart (V32QImode, i ? d->op1 : d->op0);
+ emit_insn (gen_avx2_pshufbv32qi3 (l[i], op, vperm));
+ }
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (h[i] && l[i])
+ {
+ op = gen_reg_rtx (V32QImode);
+ emit_insn (gen_iorv32qi3 (op, l[i], h[i]));
+ l[i] = op;
+ }
+ else if (h[i])
+ l[i] = h[i];
+ }
+
+ gcc_assert (l[0] && l[1]);
+ op = gen_lowpart (V32QImode, d->target);
+ emit_insn (gen_iorv32qi3 (op, l[0], l[1]));
+ return true;
+}
+
+/* The guts of ix86_expand_vec_perm_const, also used by the ok hook.
With all of the interface bits taken care of, perform the expansion
in D and return true on success. */
static bool
-ix86_expand_vec_perm_builtin_1 (struct expand_vec_perm_d *d)
+ix86_expand_vec_perm_const_1 (struct expand_vec_perm_d *d)
{
/* Try a single instruction expansion. */
if (expand_vec_perm_1 (d))
@@ -35396,11 +36311,25 @@ ix86_expand_vec_perm_builtin_1 (struct expand_vec_perm_d *d)
if (expand_vec_perm_broadcast (d))
return true;
+ if (expand_vec_perm_vpermq_perm_1 (d))
+ return true;
+
/* Try sequences of three instructions. */
if (expand_vec_perm_pshufb2 (d))
return true;
+ if (expand_vec_perm_interleave3 (d))
+ return true;
+
+ /* Try sequences of four instructions. */
+
+ if (expand_vec_perm_vpshufb2_vpermq (d))
+ return true;
+
+ if (expand_vec_perm_vpshufb2_vpermq_even_odd (d))
+ return true;
+
/* ??? Look for narrow permutations whose element orderings would
allow the promotion to a wider mode. */
@@ -35414,156 +36343,114 @@ ix86_expand_vec_perm_builtin_1 (struct expand_vec_perm_d *d)
if (expand_vec_perm_even_odd (d))
return true;
- return false;
-}
-
-/* Extract the values from the vector CST into the permutation array in D.
- Return 0 on error, 1 if all values from the permutation come from the
- first vector, 2 if all values from the second vector, and 3 otherwise. */
-
-static int
-extract_vec_perm_cst (struct expand_vec_perm_d *d, tree cst)
-{
- tree list = TREE_VECTOR_CST_ELTS (cst);
- unsigned i, nelt = d->nelt;
- int ret = 0;
-
- for (i = 0; i < nelt; ++i, list = TREE_CHAIN (list))
- {
- unsigned HOST_WIDE_INT e;
-
- if (!host_integerp (TREE_VALUE (list), 1))
- return 0;
- e = tree_low_cst (TREE_VALUE (list), 1);
- if (e >= 2 * nelt)
- return 0;
-
- ret |= (e < nelt ? 1 : 2);
- d->perm[i] = e;
- }
- gcc_assert (list == NULL);
-
- /* For all elements from second vector, fold the elements to first. */
- if (ret == 2)
- for (i = 0; i < nelt; ++i)
- d->perm[i] -= nelt;
+ /* Even longer sequences. */
+ if (expand_vec_perm_vpshufb4_vpermq2 (d))
+ return true;
- return ret;
+ return false;
}
-static rtx
-ix86_expand_vec_perm_builtin (tree exp)
+bool
+ix86_expand_vec_perm_const (rtx operands[4])
{
struct expand_vec_perm_d d;
- tree arg0, arg1, arg2;
+ unsigned char perm[MAX_VECT_LEN];
+ int i, nelt, which;
+ rtx sel;
- arg0 = CALL_EXPR_ARG (exp, 0);
- arg1 = CALL_EXPR_ARG (exp, 1);
- arg2 = CALL_EXPR_ARG (exp, 2);
+ d.target = operands[0];
+ d.op0 = operands[1];
+ d.op1 = operands[2];
+ sel = operands[3];
- d.vmode = TYPE_MODE (TREE_TYPE (arg0));
- d.nelt = GET_MODE_NUNITS (d.vmode);
- d.testing_p = false;
+ d.vmode = GET_MODE (d.target);
gcc_assert (VECTOR_MODE_P (d.vmode));
+ d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
+ d.testing_p = false;
+
+ gcc_assert (GET_CODE (sel) == CONST_VECTOR);
+ gcc_assert (XVECLEN (sel, 0) == nelt);
+ gcc_checking_assert (sizeof (d.perm) == sizeof (perm));
- if (TREE_CODE (arg2) != VECTOR_CST)
+ for (i = which = 0; i < nelt; ++i)
{
- error_at (EXPR_LOCATION (exp),
- "vector permutation requires vector constant");
- goto exit_error;
+ rtx e = XVECEXP (sel, 0, i);
+ int ei = INTVAL (e) & (2 * nelt - 1);
+
+ which |= (ei < nelt ? 1 : 2);
+ d.perm[i] = ei;
+ perm[i] = ei;
}
- switch (extract_vec_perm_cst (&d, arg2))
+ switch (which)
{
default:
gcc_unreachable();
- case 0:
- error_at (EXPR_LOCATION (exp), "invalid vector permutation constant");
- goto exit_error;
-
case 3:
- if (!operand_equal_p (arg0, arg1, 0))
- {
- d.op0 = expand_expr (arg0, NULL_RTX, d.vmode, EXPAND_NORMAL);
- d.op0 = force_reg (d.vmode, d.op0);
- d.op1 = expand_expr (arg1, NULL_RTX, d.vmode, EXPAND_NORMAL);
- d.op1 = force_reg (d.vmode, d.op1);
- break;
- }
+ if (!rtx_equal_p (d.op0, d.op1))
+ break;
/* The elements of PERM do not suggest that only the first operand
is used, but both operands are identical. Allow easier matching
of the permutation by folding the permutation into the single
input vector. */
- {
- unsigned i, nelt = d.nelt;
- for (i = 0; i < nelt; ++i)
- if (d.perm[i] >= nelt)
- d.perm[i] -= nelt;
- }
+ for (i = 0; i < nelt; ++i)
+ if (d.perm[i] >= nelt)
+ d.perm[i] -= nelt;
/* FALLTHRU */
case 1:
- d.op0 = expand_expr (arg0, NULL_RTX, d.vmode, EXPAND_NORMAL);
- d.op0 = force_reg (d.vmode, d.op0);
d.op1 = d.op0;
break;
case 2:
- d.op0 = expand_expr (arg1, NULL_RTX, d.vmode, EXPAND_NORMAL);
- d.op0 = force_reg (d.vmode, d.op0);
- d.op1 = d.op0;
+ for (i = 0; i < nelt; ++i)
+ d.perm[i] -= nelt;
+ d.op0 = d.op1;
break;
}
- d.target = gen_reg_rtx (d.vmode);
- if (ix86_expand_vec_perm_builtin_1 (&d))
- return d.target;
+ if (ix86_expand_vec_perm_const_1 (&d))
+ return true;
- /* For compiler generated permutations, we should never got here, because
- the compiler should also be checking the ok hook. But since this is a
- builtin the user has access too, so don't abort. */
- switch (d.nelt)
+ /* If the mask says both arguments are needed, but they are the same,
+ the above tried to expand with d.op0 == d.op1. If that didn't work,
+ retry with d.op0 != d.op1 as that is what testing has been done with. */
+ if (which == 3 && d.op0 == d.op1)
{
- case 2:
- sorry ("vector permutation (%d %d)", d.perm[0], d.perm[1]);
- break;
- case 4:
- sorry ("vector permutation (%d %d %d %d)",
- d.perm[0], d.perm[1], d.perm[2], d.perm[3]);
- break;
- case 8:
- sorry ("vector permutation (%d %d %d %d %d %d %d %d)",
- d.perm[0], d.perm[1], d.perm[2], d.perm[3],
- d.perm[4], d.perm[5], d.perm[6], d.perm[7]);
- break;
- case 16:
- sorry ("vector permutation "
- "(%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)",
- d.perm[0], d.perm[1], d.perm[2], d.perm[3],
- d.perm[4], d.perm[5], d.perm[6], d.perm[7],
- d.perm[8], d.perm[9], d.perm[10], d.perm[11],
- d.perm[12], d.perm[13], d.perm[14], d.perm[15]);
- break;
- default:
- gcc_unreachable ();
+ rtx seq;
+ bool ok;
+
+ memcpy (d.perm, perm, sizeof (perm));
+ d.op1 = gen_reg_rtx (d.vmode);
+ start_sequence ();
+ ok = ix86_expand_vec_perm_const_1 (&d);
+ seq = get_insns ();
+ end_sequence ();
+ if (ok)
+ {
+ emit_move_insn (d.op1, d.op0);
+ emit_insn (seq);
+ return true;
+ }
}
- exit_error:
- return CONST0_RTX (d.vmode);
+
+ return false;
}
-/* Implement targetm.vectorize.builtin_vec_perm_ok. */
+/* Implement targetm.vectorize.vec_perm_const_ok. */
static bool
-ix86_vectorize_builtin_vec_perm_ok (tree vec_type, tree mask)
+ix86_vectorize_vec_perm_const_ok (enum machine_mode vmode,
+ const unsigned char *sel)
{
struct expand_vec_perm_d d;
- int vec_mask;
+ unsigned int i, nelt, which;
bool ret, one_vec;
- d.vmode = TYPE_MODE (vec_type);
- d.nelt = GET_MODE_NUNITS (d.vmode);
+ d.vmode = vmode;
+ d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
d.testing_p = true;
/* Given sufficient ISA support we can just return true here
@@ -35581,13 +36468,23 @@ ix86_vectorize_builtin_vec_perm_ok (tree vec_type, tree mask)
return true;
}
- vec_mask = extract_vec_perm_cst (&d, mask);
+ /* Extract the values from the vector CST into the permutation
+ array in D. */
+ memcpy (d.perm, sel, nelt);
+ for (i = which = 0; i < nelt; ++i)
+ {
+ unsigned char e = d.perm[i];
+ gcc_assert (e < 2 * nelt);
+ which |= (e < nelt ? 1 : 2);
+ }
- /* Check whether the mask can be applied to the vector type. */
- if (vec_mask < 0 || vec_mask > 3)
- return false;
+ /* For all elements from second vector, fold the elements to first. */
+ if (which == 2)
+ for (i = 0; i < nelt; ++i)
+ d.perm[i] -= nelt;
- one_vec = (vec_mask != 3);
+ /* Check whether the mask can be applied to the vector type. */
+ one_vec = (which != 3);
/* Implementable with shufps or pshufd. */
if (one_vec && (d.vmode == V4SFmode || d.vmode == V4SImode))
@@ -35601,7 +36498,7 @@ ix86_vectorize_builtin_vec_perm_ok (tree vec_type, tree mask)
d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
start_sequence ();
- ret = ix86_expand_vec_perm_builtin_1 (&d);
+ ret = ix86_expand_vec_perm_const_1 (&d);
end_sequence ();
return ret;
@@ -36745,9 +37642,6 @@ ix86_autovectorize_vector_sizes (void)
#define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \
ix86_builtin_vectorized_function
-#undef TARGET_VECTORIZE_BUILTIN_CONVERSION
-#define TARGET_VECTORIZE_BUILTIN_CONVERSION ix86_vectorize_builtin_conversion
-
#undef TARGET_BUILTIN_RECIPROCAL
#define TARGET_BUILTIN_RECIPROCAL ix86_builtin_reciprocal
@@ -36969,12 +37863,9 @@ ix86_autovectorize_vector_sizes (void)
#undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
#define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \
ix86_builtin_vectorization_cost
-#undef TARGET_VECTORIZE_BUILTIN_VEC_PERM
-#define TARGET_VECTORIZE_BUILTIN_VEC_PERM \
- ix86_vectorize_builtin_vec_perm
-#undef TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK
-#define TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK \
- ix86_vectorize_builtin_vec_perm_ok
+#undef TARGET_VECTORIZE_VEC_PERM_CONST_OK
+#define TARGET_VECTORIZE_VEC_PERM_CONST_OK \
+ ix86_vectorize_vec_perm_const_ok
#undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
#define TARGET_VECTORIZE_PREFERRED_SIMD_MODE \
ix86_preferred_simd_mode
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index bd69ec2b5e3..7721c465832 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2322,6 +2322,7 @@ extern void debug_dispatch_window (int);
#define RECIP_MASK_VEC_SQRT 0x08
#define RECIP_MASK_ALL (RECIP_MASK_DIV | RECIP_MASK_SQRT \
| RECIP_MASK_VEC_DIV | RECIP_MASK_VEC_SQRT)
+#define RECIP_MASK_DEFAULT (RECIP_MASK_VEC_DIV | RECIP_MASK_VEC_SQRT)
#define TARGET_RECIP_DIV ((recip_mask & RECIP_MASK_DIV) != 0)
#define TARGET_RECIP_SQRT ((recip_mask & RECIP_MASK_SQRT) != 0)
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 7ce57d89714..f11998cd2a5 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -235,9 +235,9 @@
UNSPEC_VPERMSI
UNSPEC_VPERMDF
UNSPEC_VPERMSF
- UNSPEC_VPERMDI
UNSPEC_VPERMTI
UNSPEC_GATHER
+ UNSPEC_VSIBADDR
;; For BMI support
UNSPEC_BEXTR
@@ -775,14 +775,19 @@
;; Base name for insn mnemonic.
(define_code_attr logic [(and "and") (ior "or") (xor "xor")])
+;; Mapping of logic-shift operators
+(define_code_iterator any_lshift [ashift lshiftrt])
+
;; Mapping of shift-right operators
(define_code_iterator any_shiftrt [lshiftrt ashiftrt])
;; Base name for define_insn
-(define_code_attr shiftrt_insn [(lshiftrt "lshr") (ashiftrt "ashr")])
+(define_code_attr shift_insn
+ [(ashift "ashl") (lshiftrt "lshr") (ashiftrt "ashr")])
;; Base name for insn mnemonic.
-(define_code_attr shiftrt [(lshiftrt "shr") (ashiftrt "sar")])
+(define_code_attr shift [(ashift "sll") (lshiftrt "shr") (ashiftrt "sar")])
+(define_code_attr vshift [(ashift "sll") (lshiftrt "srl") (ashiftrt "sra")])
;; Mapping of rotate operators
(define_code_iterator any_rotate [rotate rotatert])
@@ -4920,7 +4925,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(set (match_dup 0) (float:MODEF (match_dup 1)))])
(define_split
@@ -4933,7 +4938,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (float:MODEF (match_dup 2)))])
@@ -5024,7 +5029,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(const_int 0)]
{
rtx op1 = operands[1];
@@ -5051,8 +5056,10 @@
emit_insn (gen_sse2_loadld (operands[4],
CONST0_RTX (V4SImode), operands[2]));
}
- emit_insn
- (gen_sse2_cvtdq2<ssevecmodesuffix> (operands[3], operands[4]));
+ if (<ssevecmode>mode == V4SFmode)
+ emit_insn (gen_floatv4siv4sf2 (operands[3], operands[4]));
+ else
+ emit_insn (gen_sse2_cvtdq2pd (operands[3], operands[4]));
DONE;
})
@@ -5065,7 +5072,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(const_int 0)]
{
operands[3] = simplify_gen_subreg (<ssevecmode>mode, operands[0],
@@ -5074,8 +5081,10 @@
emit_insn (gen_sse2_loadld (operands[4],
CONST0_RTX (V4SImode), operands[1]));
- emit_insn
- (gen_sse2_cvtdq2<ssevecmodesuffix> (operands[3], operands[4]));
+ if (<ssevecmode>mode == V4SFmode)
+ emit_insn (gen_floatv4siv4sf2 (operands[3], operands[4]));
+ else
+ emit_insn (gen_sse2_cvtdq2pd (operands[3], operands[4]));
DONE;
})
@@ -5087,7 +5096,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(const_int 0)]
{
rtx op1 = operands[1];
@@ -5118,8 +5127,10 @@
operands[4] = simplify_gen_subreg (V4SImode, operands[1], SImode, 0);
else
gcc_unreachable ();
- emit_insn
- (gen_sse2_cvtdq2<ssevecmodesuffix> (operands[3], operands[4]));
+ if (<ssevecmode>mode == V4SFmode)
+ emit_insn (gen_floatv4siv4sf2 (operands[3], operands[4]));
+ else
+ emit_insn (gen_sse2_cvtdq2pd (operands[3], operands[4]));
DONE;
})
@@ -5131,7 +5142,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(const_int 0)]
{
operands[3] = simplify_gen_subreg (<ssevecmode>mode, operands[0],
@@ -5140,8 +5151,10 @@
emit_insn (gen_sse2_loadld (operands[4],
CONST0_RTX (V4SImode), operands[1]));
- emit_insn
- (gen_sse2_cvtdq2<ssevecmodesuffix> (operands[3], operands[4]));
+ if (<ssevecmode>mode == V4SFmode)
+ emit_insn (gen_floatv4siv4sf2 (operands[3], operands[4]));
+ else
+ emit_insn (gen_sse2_cvtdq2pd (operands[3], operands[4]));
DONE;
})
@@ -5192,7 +5205,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(set (match_dup 0) (float:MODEF (match_dup 1)))])
(define_insn "*float<SWI48x:mode><MODEF:mode>2_sse_nointerunit"
@@ -5227,7 +5240,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (float:MODEF (match_dup 2)))])
@@ -5240,7 +5253,7 @@
&& reload_completed
&& (SSE_REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
- && SSE_REG_P (operands[0])))"
+ && SSE_REG_P (SUBREG_REG (operands[0]))))"
[(set (match_dup 0) (float:MODEF (match_dup 1)))])
(define_insn "*float<SWI48x:mode><X87MODEF:mode>2_i387_with_temp"
@@ -9582,7 +9595,7 @@
;; See comment above `ashl<mode>3' about how this works.
-(define_expand "<shiftrt_insn><mode>3"
+(define_expand "<shift_insn><mode>3"
[(set (match_operand:SDWIM 0 "<shift_operand>" "")
(any_shiftrt:SDWIM (match_operand:SDWIM 1 "<shift_operand>" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
@@ -9590,7 +9603,7 @@
"ix86_expand_binary_operator (<CODE>, <MODE>mode, operands); DONE;")
;; Avoid useless masking of count operand.
-(define_insn_and_split "*<shiftrt_insn><mode>3_mask"
+(define_insn_and_split "*<shift_insn><mode>3_mask"
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm")
(any_shiftrt:SWI48
(match_operand:SWI48 1 "nonimmediate_operand" "0")
@@ -9616,7 +9629,7 @@
[(set_attr "type" "ishift")
(set_attr "mode" "<MODE>")])
-(define_insn_and_split "*<shiftrt_insn><mode>3_doubleword"
+(define_insn_and_split "*<shift_insn><mode>3_doubleword"
[(set (match_operand:DWI 0 "register_operand" "=r")
(any_shiftrt:DWI (match_operand:DWI 1 "register_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "<S>c")))
@@ -9625,7 +9638,7 @@
"#"
"(optimize && flag_peephole2) ? epilogue_completed : reload_completed"
[(const_int 0)]
- "ix86_split_<shiftrt_insn> (operands, NULL_RTX, <MODE>mode); DONE;"
+ "ix86_split_<shift_insn> (operands, NULL_RTX, <MODE>mode); DONE;"
[(set_attr "type" "multi")])
;; By default we don't ask for a scratch register, because when DWImode
@@ -9642,7 +9655,7 @@
(match_dup 3)]
"TARGET_CMOVE"
[(const_int 0)]
- "ix86_split_<shiftrt_insn> (operands, operands[3], <DWI>mode); DONE;")
+ "ix86_split_<shift_insn> (operands, operands[3], <DWI>mode); DONE;")
(define_insn "x86_64_shrd"
[(set (match_operand:DI 0 "nonimmediate_operand" "+r*m")
@@ -9758,16 +9771,16 @@
DONE;
})
-(define_insn "*bmi2_<shiftrt_insn><mode>3_1"
+(define_insn "*bmi2_<shift_insn><mode>3_1"
[(set (match_operand:SWI48 0 "register_operand" "=r")
(any_shiftrt:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "rm")
(match_operand:SWI48 2 "register_operand" "r")))]
"TARGET_BMI2"
- "<shiftrt>x\t{%2, %1, %0|%0, %1, %2}"
+ "<shift>x\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "ishiftx")
(set_attr "mode" "<MODE>")])
-(define_insn "*<shiftrt_insn><mode>3_1"
+(define_insn "*<shift_insn><mode>3_1"
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r")
(any_shiftrt:SWI48
(match_operand:SWI48 1 "nonimmediate_operand" "0,rm")
@@ -9783,9 +9796,9 @@
default:
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<shiftrt>{<imodesuffix>}\t%0";
+ return "<shift>{<imodesuffix>}\t%0";
else
- return "<shiftrt>{<imodesuffix>}\t{%2, %0|%0, %2}";
+ return "<shift>{<imodesuffix>}\t{%2, %0|%0, %2}";
}
}
[(set_attr "isa" "*,bmi2")
@@ -9810,17 +9823,17 @@
(any_shiftrt:SWI48 (match_dup 1) (match_dup 2)))]
"operands[2] = gen_lowpart (<MODE>mode, operands[2]);")
-(define_insn "*bmi2_<shiftrt_insn>si3_1_zext"
+(define_insn "*bmi2_<shift_insn>si3_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI
(any_shiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "rm")
(match_operand:SI 2 "register_operand" "r"))))]
"TARGET_64BIT && TARGET_BMI2"
- "<shiftrt>x\t{%2, %1, %k0|%k0, %1, %2}"
+ "<shift>x\t{%2, %1, %k0|%k0, %1, %2}"
[(set_attr "type" "ishiftx")
(set_attr "mode" "SI")])
-(define_insn "*<shiftrt_insn>si3_1_zext"
+(define_insn "*<shift_insn>si3_1_zext"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI
(any_shiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,rm")
@@ -9836,9 +9849,9 @@
default:
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<shiftrt>{l}\t%k0";
+ return "<shift>{l}\t%k0";
else
- return "<shiftrt>{l}\t{%2, %k0|%k0, %2}";
+ return "<shift>{l}\t{%2, %k0|%k0, %2}";
}
}
[(set_attr "isa" "*,bmi2")
@@ -9864,7 +9877,7 @@
(zero_extend:DI (any_shiftrt:SI (match_dup 1) (match_dup 2))))]
"operands[2] = gen_lowpart (SImode, operands[2]);")
-(define_insn "*<shiftrt_insn><mode>3_1"
+(define_insn "*<shift_insn><mode>3_1"
[(set (match_operand:SWI12 0 "nonimmediate_operand" "=<r>m")
(any_shiftrt:SWI12
(match_operand:SWI12 1 "nonimmediate_operand" "0")
@@ -9874,9 +9887,9 @@
{
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<shiftrt>{<imodesuffix>}\t%0";
+ return "<shift>{<imodesuffix>}\t%0";
else
- return "<shiftrt>{<imodesuffix>}\t{%2, %0|%0, %2}";
+ return "<shift>{<imodesuffix>}\t{%2, %0|%0, %2}";
}
[(set_attr "type" "ishift")
(set (attr "length_immediate")
@@ -9888,7 +9901,7 @@
(const_string "*")))
(set_attr "mode" "<MODE>")])
-(define_insn "*<shiftrt_insn>qi3_1_slp"
+(define_insn "*<shift_insn>qi3_1_slp"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
(any_shiftrt:QI (match_dup 0)
(match_operand:QI 1 "nonmemory_operand" "cI")))
@@ -9900,9 +9913,9 @@
{
if (operands[1] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<shiftrt>{b}\t%0";
+ return "<shift>{b}\t%0";
else
- return "<shiftrt>{b}\t{%1, %0|%0, %1}";
+ return "<shift>{b}\t{%1, %0|%0, %1}";
}
[(set_attr "type" "ishift1")
(set (attr "length_immediate")
@@ -9917,7 +9930,7 @@
;; 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.
-(define_insn "*<shiftrt_insn><mode>3_cmp"
+(define_insn "*<shift_insn><mode>3_cmp"
[(set (reg FLAGS_REG)
(compare
(any_shiftrt:SWI
@@ -9935,9 +9948,9 @@
{
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<shiftrt>{<imodesuffix>}\t%0";
+ return "<shift>{<imodesuffix>}\t%0";
else
- return "<shiftrt>{<imodesuffix>}\t{%2, %0|%0, %2}";
+ return "<shift>{<imodesuffix>}\t{%2, %0|%0, %2}";
}
[(set_attr "type" "ishift")
(set (attr "length_immediate")
@@ -9949,7 +9962,7 @@
(const_string "*")))
(set_attr "mode" "<MODE>")])
-(define_insn "*<shiftrt_insn>si3_cmp_zext"
+(define_insn "*<shift_insn>si3_cmp_zext"
[(set (reg FLAGS_REG)
(compare
(any_shiftrt:SI (match_operand:SI 1 "register_operand" "0")
@@ -9967,9 +9980,9 @@
{
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<shiftrt>{l}\t%k0";
+ return "<shift>{l}\t%k0";
else
- return "<shiftrt>{l}\t{%2, %k0|%k0, %2}";
+ return "<shift>{l}\t{%2, %k0|%k0, %2}";
}
[(set_attr "type" "ishift")
(set (attr "length_immediate")
@@ -9981,7 +9994,7 @@
(const_string "*")))
(set_attr "mode" "SI")])
-(define_insn "*<shiftrt_insn><mode>3_cconly"
+(define_insn "*<shift_insn><mode>3_cconly"
[(set (reg FLAGS_REG)
(compare
(any_shiftrt:SWI
@@ -9997,9 +10010,9 @@
{
if (operands[2] == const1_rtx
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
- return "<shiftrt>{<imodesuffix>}\t%0";
+ return "<shift>{<imodesuffix>}\t%0";
else
- return "<shiftrt>{<imodesuffix>}\t{%2, %0|%0, %2}";
+ return "<shift>{<imodesuffix>}\t{%2, %0|%0, %2}";
}
[(set_attr "type" "ishift")
(set (attr "length_immediate")
@@ -11711,9 +11724,13 @@
}
})
+;; We need to disable this for TARGET_SEH, as otherwise
+;; shrink-wrapped prologue gets enabled too. This might exceed
+;; the maximum size of prologue in unwind information.
+
(define_expand "simple_return"
[(simple_return)]
- ""
+ "!TARGET_SEH"
{
if (crtl->args.pops_args)
{
@@ -12099,8 +12116,8 @@
(define_insn "bmi_bextr_<mode>"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (unspec:SWI48 [(match_operand:SWI48 1 "nonimmediate_operand" "rm")
- (match_operand:SWI48 2 "register_operand" "r")]
+ (unspec:SWI48 [(match_operand:SWI48 1 "register_operand" "r")
+ (match_operand:SWI48 2 "nonimmediate_operand" "rm")]
UNSPEC_BEXTR))
(clobber (reg:CC FLAGS_REG))]
"TARGET_BMI"
@@ -12149,9 +12166,9 @@
;; BMI2 instructions.
(define_insn "bmi2_bzhi_<mode>3"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (and:SWI48 (match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (and:SWI48 (match_operand:SWI48 1 "register_operand" "r")
(lshiftrt:SWI48 (const_int -1)
- (match_operand:SWI48 2 "register_operand" "r"))))
+ (match_operand:SWI48 2 "nonimmediate_operand" "rm"))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_BMI2"
"bzhi\t{%2, %1, %0|%0, %1, %2}"
@@ -12161,8 +12178,8 @@
(define_insn "bmi2_pdep_<mode>3"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (unspec:SWI48 [(match_operand:SWI48 1 "nonimmediate_operand" "rm")
- (match_operand:SWI48 2 "register_operand" "r")]
+ (unspec:SWI48 [(match_operand:SWI48 1 "register_operand" "r")
+ (match_operand:SWI48 2 "nonimmediate_operand" "rm")]
UNSPEC_PDEP))]
"TARGET_BMI2"
"pdep\t{%2, %1, %0|%0, %1, %2}"
@@ -12172,8 +12189,8 @@
(define_insn "bmi2_pext_<mode>3"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (unspec:SWI48 [(match_operand:SWI48 1 "nonimmediate_operand" "rm")
- (match_operand:SWI48 2 "register_operand" "r")]
+ (unspec:SWI48 [(match_operand:SWI48 1 "register_operand" "r")
+ (match_operand:SWI48 2 "nonimmediate_operand" "rm")]
UNSPEC_PEXT))]
"TARGET_BMI2"
"pext\t{%2, %1, %0|%0, %1, %2}"
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 43009a3c2a6..6c516e7b869 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -32,7 +32,7 @@ Variable
HOST_WIDE_INT ix86_isa_flags_explicit
TargetVariable
-int recip_mask
+int recip_mask = RECIP_MASK_DEFAULT
Variable
int recip_mask_explicit
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
index 371cb72248b..d9f10c834af 100644
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -78,12 +78,8 @@ along with GCC; see the file COPYING3. If not see
#define SUB_LINK_ENTRY SUB_LINK_ENTRY32
#endif
-/* Override the standard choice of /usr/include as the default prefix
- to try when searching for header files. */
-#undef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/mingw/include"
-#undef STANDARD_INCLUDE_COMPONENT
-#define STANDARD_INCLUDE_COMPONENT "MINGW"
+#undef NATIVE_SYSTEM_HEADER_COMPONENT
+#define NATIVE_SYSTEM_HEADER_COMPONENT "MINGW"
#undef CPP_SPEC
#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} " \
@@ -235,4 +231,3 @@ do { \
/* We should find a way to not have to update this manually. */
#define LIBGCJ_SONAME "libgcj" /*LIBGCC_EH_EXTN*/ "-12.dll"
-
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index f092c0f4f85..f76834e5ab2 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -1037,27 +1037,13 @@
(const_string "0")))
(set_attr "mode" "DI")])
-(define_insn "mmx_lshr<mode>3"
+(define_insn "mmx_<shift_insn><mode>3"
[(set (match_operand:MMXMODE248 0 "register_operand" "=y")
- (lshiftrt:MMXMODE248
+ (any_lshift:MMXMODE248
(match_operand:MMXMODE248 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "yN")))]
"TARGET_MMX"
- "psrl<mmxvecsize>\t{%2, %0|%0, %2}"
- [(set_attr "type" "mmxshft")
- (set (attr "length_immediate")
- (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "1")
- (const_string "0")))
- (set_attr "mode" "DI")])
-
-(define_insn "mmx_ashl<mode>3"
- [(set (match_operand:MMXMODE248 0 "register_operand" "=y")
- (ashift:MMXMODE248
- (match_operand:MMXMODE248 1 "register_operand" "0")
- (match_operand:SI 2 "nonmemory_operand" "yN")))]
- "TARGET_MMX"
- "psll<mmxvecsize>\t{%2, %0|%0, %2}"
+ "p<vshift><mmxvecsize>\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxshft")
(set (attr "length_immediate")
(if_then_else (match_operand 2 "const_int_operand" "")
@@ -1656,24 +1642,12 @@
"TARGET_SSE || TARGET_3DNOW_A")
(define_insn "*mmx_maskmovq"
- [(set (mem:V8QI (match_operand:SI 0 "register_operand" "D"))
+ [(set (mem:V8QI (match_operand:P 0 "register_operand" "D"))
(unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
(match_operand:V8QI 2 "register_operand" "y")
(mem:V8QI (match_dup 0))]
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" "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")
- (mem:V8QI (match_dup 0))]
- UNSPEC_MASKMOV))]
- "(TARGET_SSE || TARGET_3DNOW_A) && TARGET_64BIT"
+ "TARGET_SSE || TARGET_3DNOW_A"
;; @@@ check ordering of operands in intel/nonintel syntax
"maskmovq\t{%2, %1|%1, %2}"
[(set_attr "type" "mmxcvt")
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 349f5b0c427..3745b497c19 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -825,6 +825,42 @@
return parts.seg == SEG_DEFAULT;
})
+;; Return true if op if a valid base register, displacement or
+;; sum of base register and displacement for VSIB addressing.
+(define_predicate "vsib_address_operand"
+ (match_operand 0 "address_operand")
+{
+ struct ix86_address parts;
+ int ok;
+ rtx disp;
+
+ ok = ix86_decompose_address (op, &parts);
+ gcc_assert (ok);
+ if (parts.index || parts.seg != SEG_DEFAULT)
+ return false;
+
+ /* VSIB addressing doesn't support (%rip). */
+ if (parts.disp && GET_CODE (parts.disp) == CONST)
+ {
+ disp = XEXP (parts.disp, 0);
+ if (GET_CODE (disp) == PLUS)
+ disp = XEXP (disp, 0);
+ if (GET_CODE (disp) == UNSPEC)
+ switch (XINT (disp, 1))
+ {
+ case UNSPEC_GOTPCREL:
+ case UNSPEC_PCREL:
+ case UNSPEC_GOTNTPOFF:
+ return false;
+ }
+ }
+
+ return true;
+})
+
+(define_predicate "vsib_mem_operator"
+ (match_code "mem"))
+
;; Return true if the rtx is known to be at least 32 bits aligned.
(define_predicate "aligned_operand"
(match_operand 0 "general_operand")
@@ -1126,7 +1162,7 @@
;; Return true if OP is a binary operator that can be promoted to wider mode.
(define_predicate "promotable_binary_operator"
- (ior (match_code "plus,and,ior,xor,ashift")
+ (ior (match_code "plus,minus,and,ior,xor,ashift")
(and (match_code "mult")
(match_test "TARGET_TUNE_PROMOTE_HIMODE_IMUL"))))
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 9153352d9a8..33c2e94b369 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -126,10 +126,8 @@
(V4DI "TARGET_AVX2") V2DI])
(define_mode_iterator VI48_AVX2
- [V8SI V4SI V4DI V2DI])
-
-(define_mode_iterator VI4SD_AVX2
- [V4SI V4DI])
+ [(V8SI "TARGET_AVX2") V4SI
+ (V4DI "TARGET_AVX2") V2DI])
(define_mode_iterator V48_AVX2
[V4SF V2DF
@@ -163,14 +161,11 @@
(V4SI "avx2") (V2DI "avx2")
(V8SI "avx2") (V4DI "avx2")])
-;; Mapping of logic-shift operators
-(define_code_iterator lshift [lshiftrt ashift])
-
-;; Base name for define_insn
-(define_code_attr lshift_insn [(lshiftrt "srl") (ashift "sll")])
-
-;; Base name for insn mnemonic
-(define_code_attr lshift [(lshiftrt "lshr") (ashift "lshl")])
+(define_mode_attr vec_avx2
+ [(V16QI "vec") (V32QI "avx2")
+ (V8HI "vec") (V16HI "avx2")
+ (V4SI "vec") (V8SI "avx2")
+ (V2DI "vec") (V4DI "avx2")])
(define_mode_attr ssedoublemode
[(V16HI "V16SI") (V8HI "V8SI")])
@@ -188,12 +183,14 @@
(define_mode_iterator VI12_128 [V16QI V8HI])
(define_mode_iterator VI14_128 [V16QI V4SI])
(define_mode_iterator VI124_128 [V16QI V8HI V4SI])
+(define_mode_iterator VI128_128 [V16QI V8HI V2DI])
(define_mode_iterator VI24_128 [V8HI V4SI])
(define_mode_iterator VI248_128 [V8HI V4SI V2DI])
+(define_mode_iterator VI48_128 [V4SI V2DI])
;; Random 256bit vector integer mode combinations
(define_mode_iterator VI124_256 [V32QI V16HI V8SI])
-(define_mode_iterator VI248_256 [V16HI V8SI V4DI])
+(define_mode_iterator VI48_256 [V8SI V4DI])
;; Int-float size matches
(define_mode_iterator VI4F_128 [V4SI V4SF])
@@ -236,12 +233,18 @@
(define_mode_attr sseintvecmode
[(V8SF "V8SI") (V4DF "V4DI")
(V4SF "V4SI") (V2DF "V2DI")
- (V4DF "V4DI") (V8SF "V8SI")
(V8SI "V8SI") (V4DI "V4DI")
(V4SI "V4SI") (V2DI "V2DI")
(V16HI "V16HI") (V8HI "V8HI")
- (V32QI "V32QI") (V16QI "V16QI")
- ])
+ (V32QI "V32QI") (V16QI "V16QI")])
+
+(define_mode_attr sseintvecmodelower
+ [(V8SF "v8si") (V4DF "v4di")
+ (V4SF "v4si") (V2DF "v2di")
+ (V8SI "v8si") (V4DI "v4di")
+ (V4SI "v4si") (V2DI "v2di")
+ (V16HI "v16hi") (V8HI "v8hi")
+ (V32QI "v32qi") (V16QI "v16qi")])
;; Mapping of vector modes to a vector mode of double size
(define_mode_attr ssedoublevecmode
@@ -271,6 +274,13 @@
(V8SF "8") (V4DF "4")
(V4SF "4") (V2DF "2")])
+;; SSE prefix for integer vector modes
+(define_mode_attr sseintprefix
+ [(V2DI "p") (V2DF "")
+ (V4DI "p") (V4DF "")
+ (V4SI "p") (V4SF "")
+ (V8SI "p") (V8SF "")])
+
;; SSE scalar suffix for vector modes
(define_mode_attr ssescalarmodesuffix
[(SF "ss") (DF "sd")
@@ -313,16 +323,6 @@
(V4DI "V4DI") (V4DF "V4DI")
(V4SI "V2DI") (V4SF "V2DI")
(V8SI "V4DI") (V8SF "V4DI")])
-(define_mode_attr gthrfirstp
- [(V2DI "p") (V2DF "")
- (V4DI "p") (V4DF "")
- (V4SI "p") (V4SF "")
- (V8SI "p") (V8SF "")])
-(define_mode_attr gthrlastp
- [(V2DI "q") (V2DF "pd")
- (V4DI "q") (V4DF "pd")
- (V4SI "d") (V4SF "ps")
- (V8SI "d") (V8SF "ps")])
(define_mode_iterator FMAMODE [SF DF V4SF V2DF V8SF V4DF])
@@ -1297,6 +1297,16 @@
DONE;
})
+(define_expand "reduc_umin_v8hi"
+ [(umin:V8HI
+ (match_operand:V8HI 0 "register_operand" "")
+ (match_operand:V8HI 1 "register_operand" ""))]
+ "TARGET_SSE4_1"
+{
+ ix86_expand_reduc (gen_uminv8hi3, operands[0], operands[1]);
+ DONE;
+})
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel floating point comparisons
@@ -2221,33 +2231,26 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "DI")])
-(define_insn "avx_cvtdq2ps256"
- [(set (match_operand:V8SF 0 "register_operand" "=x")
- (float:V8SF (match_operand:V8SI 1 "nonimmediate_operand" "xm")))]
- "TARGET_AVX"
- "vcvtdq2ps\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "prefix" "vex")
- (set_attr "mode" "V8SF")])
-
-(define_insn "sse2_cvtdq2ps"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (float:V4SF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))]
+(define_insn "float<sseintvecmodelower><mode>2"
+ [(set (match_operand:VF1 0 "register_operand" "=x")
+ (float:VF1
+ (match_operand:<sseintvecmode> 1 "nonimmediate_operand" "xm")))]
"TARGET_SSE2"
"%vcvtdq2ps\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
(set_attr "prefix" "maybe_vex")
- (set_attr "mode" "V4SF")])
+ (set_attr "mode" "<sseinsnmode>")])
-(define_expand "sse2_cvtudq2ps"
+(define_expand "floatuns<sseintvecmodelower><mode>2"
[(set (match_dup 5)
- (float:V4SF (match_operand:V4SI 1 "nonimmediate_operand" "")))
+ (float:VF1
+ (match_operand:<sseintvecmode> 1 "nonimmediate_operand" "")))
(set (match_dup 6)
- (lt:V4SF (match_dup 5) (match_dup 3)))
+ (lt:VF1 (match_dup 5) (match_dup 3)))
(set (match_dup 7)
- (and:V4SF (match_dup 6) (match_dup 4)))
- (set (match_operand:V4SF 0 "register_operand" "")
- (plus:V4SF (match_dup 5) (match_dup 7)))]
+ (and:VF1 (match_dup 6) (match_dup 4)))
+ (set (match_operand:VF1 0 "register_operand" "")
+ (plus:VF1 (match_dup 5) (match_dup 7)))]
"TARGET_SSE2"
{
REAL_VALUE_TYPE TWO32r;
@@ -2257,12 +2260,12 @@
real_ldexp (&TWO32r, &dconst1, 32);
x = const_double_from_real_value (TWO32r, SFmode);
- operands[3] = force_reg (V4SFmode, CONST0_RTX (V4SFmode));
- operands[4] = force_reg (V4SFmode,
- ix86_build_const_vector (V4SFmode, 1, x));
+ operands[3] = force_reg (<MODE>mode, CONST0_RTX (<MODE>mode));
+ operands[4] = force_reg (<MODE>mode,
+ ix86_build_const_vector (<MODE>mode, 1, x));
for (i = 5; i < 8; i++)
- operands[i] = gen_reg_rtx (V4SFmode);
+ operands[i] = gen_reg_rtx (<MODE>mode);
})
(define_insn "avx_cvtps2dq256"
@@ -2290,7 +2293,7 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
-(define_insn "avx_cvttps2dq256"
+(define_insn "fix_truncv8sfv8si2"
[(set (match_operand:V8SI 0 "register_operand" "=x")
(fix:V8SI (match_operand:V8SF 1 "nonimmediate_operand" "xm")))]
"TARGET_AVX"
@@ -2299,7 +2302,7 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
-(define_insn "sse2_cvttps2dq"
+(define_insn "fix_truncv4sfv4si2"
[(set (match_operand:V4SI 0 "register_operand" "=x")
(fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
"TARGET_SSE2"
@@ -2319,6 +2322,16 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
+(define_expand "fixuns_trunc<mode><sseintvecmodelower>2"
+ [(match_operand:<sseintvecmode> 0 "register_operand" "")
+ (match_operand:VF1 1 "register_operand" "")]
+ "TARGET_AVX"
+{
+ rtx tmp = ix86_expand_adjust_ufix_to_sfix_si (operands[1]);
+ emit_insn (gen_fix_trunc<mode><sseintvecmodelower>2 (operands[0], tmp));
+ DONE;
+})
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel double-precision floating point conversion operations
@@ -2492,7 +2505,7 @@
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "DI")])
-(define_insn "avx_cvtdq2pd256"
+(define_insn "floatv4siv4df2"
[(set (match_operand:V4DF 0 "register_operand" "=x")
(float:V4DF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))]
"TARGET_AVX"
@@ -2501,7 +2514,7 @@
(set_attr "prefix" "vex")
(set_attr "mode" "V4DF")])
-(define_insn "*avx_cvtdq2pd256_2"
+(define_insn "avx_cvtdq2pd256_2"
[(set (match_operand:V4DF 0 "register_operand" "=x")
(float:V4DF
(vec_select:V4SI
@@ -2521,7 +2534,7 @@
(match_operand:V4SI 1 "nonimmediate_operand" "xm")
(parallel [(const_int 0) (const_int 1)]))))]
"TARGET_SSE2"
- "%vcvtdq2pd\t{%1, %0|%0, %1}"
+ "%vcvtdq2pd\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssecvt")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V2DF")])
@@ -2536,6 +2549,27 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_expand "avx_cvtpd2dq256_2"
+ [(set (match_operand:V8SI 0 "register_operand" "")
+ (vec_concat:V8SI
+ (unspec:V4SI [(match_operand:V4DF 1 "nonimmediate_operand" "")]
+ UNSPEC_FIX_NOTRUNC)
+ (match_dup 2)))]
+ "TARGET_AVX"
+ "operands[2] = CONST0_RTX (V4SImode);")
+
+(define_insn "*avx_cvtpd2dq256_2"
+ [(set (match_operand:V8SI 0 "register_operand" "=x")
+ (vec_concat:V8SI
+ (unspec:V4SI [(match_operand:V4DF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX_NOTRUNC)
+ (match_operand:V4SI 2 "const0_operand" "")))]
+ "TARGET_AVX"
+ "vcvtpd2dq{y}\t{%1, %x0|%x0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "OI")])
+
(define_expand "sse2_cvtpd2dq"
[(set (match_operand:V4SI 0 "register_operand" "")
(vec_concat:V4SI
@@ -2567,7 +2601,7 @@
(set_attr "athlon_decode" "vector")
(set_attr "bdver1_decode" "double")])
-(define_insn "avx_cvttpd2dq256"
+(define_insn "fix_truncv4dfv4si2"
[(set (match_operand:V4SI 0 "register_operand" "=x")
(fix:V4SI (match_operand:V4DF 1 "nonimmediate_operand" "xm")))]
"TARGET_AVX"
@@ -2576,6 +2610,25 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
+(define_expand "avx_cvttpd2dq256_2"
+ [(set (match_operand:V8SI 0 "register_operand" "")
+ (vec_concat:V8SI
+ (fix:V4SI (match_operand:V4DF 1 "nonimmediate_operand" ""))
+ (match_dup 2)))]
+ "TARGET_AVX"
+ "operands[2] = CONST0_RTX (V4SImode);")
+
+(define_insn "*avx_cvttpd2dq256_2"
+ [(set (match_operand:V8SI 0 "register_operand" "=x")
+ (vec_concat:V8SI
+ (fix:V4SI (match_operand:V4DF 1 "nonimmediate_operand" "xm"))
+ (match_operand:V4SI 2 "const0_operand" "")))]
+ "TARGET_AVX"
+ "vcvttpd2dq{y}\t{%1, %x0|%x0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "prefix" "vex")
+ (set_attr "mode" "OI")])
+
(define_expand "sse2_cvttpd2dq"
[(set (match_operand:V4SI 0 "register_operand" "")
(vec_concat:V4SI
@@ -2716,7 +2769,7 @@
(match_operand:V4SF 1 "nonimmediate_operand" "xm")
(parallel [(const_int 0) (const_int 1)]))))]
"TARGET_SSE2"
- "%vcvtps2pd\t{%1, %0|%0, %1}"
+ "%vcvtps2pd\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssecvt")
(set_attr "amdfam10_decode" "direct")
(set_attr "athlon_decode" "double")
@@ -2770,51 +2823,58 @@
(const_int 2) (const_int 3)]))))]
"TARGET_AVX")
-(define_expand "vec_unpacks_float_hi_v8hi"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")]
+(define_mode_attr sseunpackfltmode
+ [(V8HI "V4SF") (V4SI "V2DF") (V16HI "V8SF") (V8SI "V4DF")])
+
+(define_expand "vec_unpacks_float_hi_<mode>"
+ [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
{
- rtx tmp = gen_reg_rtx (V4SImode);
+ rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
- emit_insn (gen_vec_unpacks_hi_v8hi (tmp, operands[1]));
- emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+ emit_insn (gen_vec_unpacks_hi_<mode> (tmp, operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
DONE;
})
-(define_expand "vec_unpacks_float_lo_v8hi"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacks_float_lo_<mode>"
+ [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
{
- rtx tmp = gen_reg_rtx (V4SImode);
+ rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
- emit_insn (gen_vec_unpacks_lo_v8hi (tmp, operands[1]));
- emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+ emit_insn (gen_vec_unpacks_lo_<mode> (tmp, operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
DONE;
})
-(define_expand "vec_unpacku_float_hi_v8hi"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacku_float_hi_<mode>"
+ [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
{
- rtx tmp = gen_reg_rtx (V4SImode);
+ rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
- emit_insn (gen_vec_unpacku_hi_v8hi (tmp, operands[1]));
- emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+ emit_insn (gen_vec_unpacku_hi_<mode> (tmp, operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
DONE;
})
-(define_expand "vec_unpacku_float_lo_v8hi"
- [(match_operand:V4SF 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")]
+(define_expand "vec_unpacku_float_lo_<mode>"
+ [(match_operand:<sseunpackfltmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
{
- rtx tmp = gen_reg_rtx (V4SImode);
+ rtx tmp = gen_reg_rtx (<sseunpackmode>mode);
- emit_insn (gen_vec_unpacku_lo_v8hi (tmp, operands[1]));
- emit_insn (gen_sse2_cvtdq2ps (operands[0], tmp));
+ emit_insn (gen_vec_unpacku_lo_<mode> (tmp, operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_FLOAT (<sseunpackfltmode>mode, tmp)));
DONE;
})
@@ -2926,6 +2986,58 @@
operands[i] = gen_reg_rtx (V2DFmode);
})
+(define_expand "vec_unpacku_float_hi_v8si"
+ [(match_operand:V4DF 0 "register_operand" "")
+ (match_operand:V8SI 1 "register_operand" "")]
+ "TARGET_AVX"
+{
+ REAL_VALUE_TYPE TWO32r;
+ rtx x, tmp[6];
+ int i;
+
+ real_ldexp (&TWO32r, &dconst1, 32);
+ x = const_double_from_real_value (TWO32r, DFmode);
+
+ tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
+ tmp[1] = force_reg (V4DFmode, ix86_build_const_vector (V4DFmode, 1, x));
+ tmp[5] = gen_reg_rtx (V4SImode);
+
+ for (i = 2; i < 5; i++)
+ tmp[i] = gen_reg_rtx (V4DFmode);
+ emit_insn (gen_vec_extract_hi_v8si (tmp[5], operands[1]));
+ emit_insn (gen_floatv4siv4df2 (tmp[2], tmp[5]));
+ emit_insn (gen_rtx_SET (VOIDmode, tmp[3],
+ gen_rtx_LT (V4DFmode, tmp[2], tmp[0])));
+ emit_insn (gen_andv4df3 (tmp[4], tmp[3], tmp[1]));
+ emit_insn (gen_addv4df3 (operands[0], tmp[2], tmp[4]));
+ DONE;
+})
+
+(define_expand "vec_unpacku_float_lo_v8si"
+ [(match_operand:V4DF 0 "register_operand" "")
+ (match_operand:V8SI 1 "nonimmediate_operand" "")]
+ "TARGET_AVX"
+{
+ REAL_VALUE_TYPE TWO32r;
+ rtx x, tmp[5];
+ int i;
+
+ real_ldexp (&TWO32r, &dconst1, 32);
+ x = const_double_from_real_value (TWO32r, DFmode);
+
+ tmp[0] = force_reg (V4DFmode, CONST0_RTX (V4DFmode));
+ tmp[1] = force_reg (V4DFmode, ix86_build_const_vector (V4DFmode, 1, x));
+
+ for (i = 2; i < 5; i++)
+ tmp[i] = gen_reg_rtx (V4DFmode);
+ emit_insn (gen_avx_cvtdq2pd256_2 (tmp[2], operands[1]));
+ emit_insn (gen_rtx_SET (VOIDmode, tmp[3],
+ gen_rtx_LT (V4DFmode, tmp[2], tmp[0])));
+ emit_insn (gen_andv4df3 (tmp[4], tmp[3], tmp[1]));
+ emit_insn (gen_addv4df3 (operands[0], tmp[2], tmp[4]));
+ DONE;
+})
+
(define_expand "vec_pack_trunc_v4df"
[(set (match_dup 3)
(float_truncate:V4SF
@@ -2960,6 +3072,23 @@
DONE;
})
+(define_expand "vec_pack_sfix_trunc_v4df"
+ [(match_operand:V8SI 0 "register_operand" "")
+ (match_operand:V4DF 1 "nonimmediate_operand" "")
+ (match_operand:V4DF 2 "nonimmediate_operand" "")]
+ "TARGET_AVX"
+{
+ rtx r1, r2;
+
+ r1 = gen_reg_rtx (V8SImode);
+ r2 = gen_reg_rtx (V8SImode);
+
+ emit_insn (gen_avx_cvttpd2dq256_2 (r1, operands[1]));
+ emit_insn (gen_avx_cvttpd2dq256_2 (r2, operands[2]));
+ emit_insn (gen_avx_vperm2f128v8si3 (operands[0], r1, r2, GEN_INT (0x20)));
+ DONE;
+})
+
(define_expand "vec_pack_sfix_trunc_v2df"
[(match_operand:V4SI 0 "register_operand" "")
(match_operand:V2DF 1 "nonimmediate_operand" "")
@@ -2979,6 +3108,39 @@
DONE;
})
+(define_mode_attr ssepackfltmode
+ [(V4DF "V8SI") (V2DF "V4SI")])
+
+(define_expand "vec_pack_ufix_trunc_<mode>"
+ [(match_operand:<ssepackfltmode> 0 "register_operand" "")
+ (match_operand:VF2 1 "register_operand" "")
+ (match_operand:VF2 2 "register_operand" "")]
+ "TARGET_AVX"
+{
+ rtx tmp[2];
+ tmp[0] = ix86_expand_adjust_ufix_to_sfix_si (operands[1]);
+ tmp[1] = ix86_expand_adjust_ufix_to_sfix_si (operands[2]);
+ emit_insn (gen_vec_pack_sfix_trunc_<mode> (operands[0], tmp[0], tmp[1]));
+ DONE;
+})
+
+(define_expand "vec_pack_sfix_v4df"
+ [(match_operand:V8SI 0 "register_operand" "")
+ (match_operand:V4DF 1 "nonimmediate_operand" "")
+ (match_operand:V4DF 2 "nonimmediate_operand" "")]
+ "TARGET_AVX"
+{
+ rtx r1, r2;
+
+ r1 = gen_reg_rtx (V8SImode);
+ r2 = gen_reg_rtx (V8SImode);
+
+ emit_insn (gen_avx_cvtpd2dq256_2 (r1, operands[1]));
+ emit_insn (gen_avx_cvtpd2dq256_2 (r2, operands[2]));
+ emit_insn (gen_avx_vperm2f128v8si3 (operands[0], r1, r2, GEN_INT (0x20)));
+ DONE;
+})
+
(define_expand "vec_pack_sfix_v2df"
[(match_operand:V4SI 0 "register_operand" "")
(match_operand:V2DF 1 "nonimmediate_operand" "")
@@ -3526,19 +3688,9 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "SF")])
-(define_expand "vec_dupv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (vec_duplicate:V4SF
- (match_operand:SF 1 "nonimmediate_operand" "")))]
- "TARGET_SSE"
-{
- if (!TARGET_AVX)
- operands[1] = force_reg (SFmode, operands[1]);
-})
-
-(define_insn "avx2_vec_dupv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_duplicate:V4SF
+(define_insn "avx2_vec_dup<mode>"
+ [(set (match_operand:VF1 0 "register_operand" "=x")
+ (vec_duplicate:VF1
(vec_select:SF
(match_operand:V4SF 1 "register_operand" "x")
(parallel [(const_int 0)]))))]
@@ -3546,42 +3698,22 @@
"vbroadcastss\t{%1, %0|%0, %1}"
[(set_attr "type" "sselog1")
(set_attr "prefix" "vex")
- (set_attr "mode" "V4SF")])
+ (set_attr "mode" "<MODE>")])
-(define_insn "*vec_dupv4sf_avx"
- [(set (match_operand:V4SF 0 "register_operand" "=x,x")
+(define_insn "vec_dupv4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=x,x,x")
(vec_duplicate:V4SF
- (match_operand:SF 1 "nonimmediate_operand" "x,m")))]
- "TARGET_AVX"
+ (match_operand:SF 1 "nonimmediate_operand" "x,m,0")))]
+ "TARGET_SSE"
"@
vshufps\t{$0, %1, %1, %0|%0, %1, %1, 0}
- vbroadcastss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sselog1,ssemov")
- (set_attr "length_immediate" "1,0")
- (set_attr "prefix_extra" "0,1")
- (set_attr "prefix" "vex")
- (set_attr "mode" "V4SF")])
-
-(define_insn "avx2_vec_dupv8sf"
- [(set (match_operand:V8SF 0 "register_operand" "=x")
- (vec_duplicate:V8SF
- (vec_select:SF
- (match_operand:V4SF 1 "register_operand" "x")
- (parallel [(const_int 0)]))))]
- "TARGET_AVX2"
- "vbroadcastss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sselog1")
- (set_attr "prefix" "vex")
- (set_attr "mode" "V8SF")])
-
-(define_insn "*vec_dupv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=x")
- (vec_duplicate:V4SF
- (match_operand:SF 1 "register_operand" "0")))]
- "TARGET_SSE"
- "shufps\t{$0, %0, %0|%0, %0, 0}"
- [(set_attr "type" "sselog1")
- (set_attr "length_immediate" "1")
+ vbroadcastss\t{%1, %0|%0, %1}
+ shufps\t{$0, %0, %0|%0, %0, 0}"
+ [(set_attr "isa" "avx,avx,noavx")
+ (set_attr "type" "sselog1,ssemov,sselog1")
+ (set_attr "length_immediate" "1,0,1")
+ (set_attr "prefix_extra" "0,1,*")
+ (set_attr "prefix" "vex,vex,orig")
(set_attr "mode" "V4SF")])
;; Although insertps takes register source, we prefer
@@ -3770,7 +3902,7 @@
})
(define_expand "vec_set<mode>"
- [(match_operand:V_128 0 "register_operand" "")
+ [(match_operand:V 0 "register_operand" "")
(match_operand:<ssescalarmode> 1 "register_operand" "")
(match_operand 2 "const_int_operand" "")]
"TARGET_SSE"
@@ -3799,6 +3931,62 @@
DONE;
})
+(define_insn_and_split "*sse4_1_extractps"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=rm,x,x")
+ (vec_select:SF
+ (match_operand:V4SF 1 "register_operand" "x,0,x")
+ (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n,n,n")])))]
+ "TARGET_SSE4_1"
+ "@
+ %vextractps\t{%2, %1, %0|%0, %1, %2}
+ #
+ #"
+ "&& reload_completed && SSE_REG_P (operands[0])"
+ [(const_int 0)]
+{
+ rtx dest = gen_rtx_REG (V4SFmode, REGNO (operands[0]));
+ switch (INTVAL (operands[2]))
+ {
+ case 1:
+ case 3:
+ emit_insn (gen_sse_shufps_v4sf (dest, operands[1], operands[1],
+ operands[2], operands[2],
+ GEN_INT (INTVAL (operands[2]) + 4),
+ GEN_INT (INTVAL (operands[2]) + 4)));
+ break;
+ case 2:
+ emit_insn (gen_vec_interleave_highv4sf (dest, operands[1], operands[1]));
+ break;
+ default:
+ /* 0 should be handled by the *vec_extractv4sf_0 pattern above. */
+ gcc_unreachable ();
+ }
+ DONE;
+}
+ [(set_attr "isa" "*,noavx,avx")
+ (set_attr "type" "sselog,*,*")
+ (set_attr "prefix_data16" "1,*,*")
+ (set_attr "prefix_extra" "1,*,*")
+ (set_attr "length_immediate" "1,*,*")
+ (set_attr "prefix" "maybe_vex,*,*")
+ (set_attr "mode" "V4SF,*,*")])
+
+(define_insn_and_split "*vec_extract_v4sf_mem"
+ [(set (match_operand:SF 0 "register_operand" "=x,*r,f")
+ (vec_select:SF
+ (match_operand:V4SF 1 "memory_operand" "o,o,o")
+ (parallel [(match_operand 2 "const_0_to_3_operand" "n,n,n")])))]
+ "TARGET_SSE"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ int i = INTVAL (operands[2]);
+
+ emit_move_insn (operands[0], adjust_address (operands[1], SFmode, i*4));
+ DONE;
+})
+
(define_expand "avx_vextractf128<mode>"
[(match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "")
(match_operand:V_256 1 "register_operand" "")
@@ -3977,62 +4165,6 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
-(define_insn_and_split "*sse4_1_extractps"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=rm,x,x")
- (vec_select:SF
- (match_operand:V4SF 1 "register_operand" "x,0,x")
- (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n,n,n")])))]
- "TARGET_SSE4_1"
- "@
- %vextractps\t{%2, %1, %0|%0, %1, %2}
- #
- #"
- "&& reload_completed && SSE_REG_P (operands[0])"
- [(const_int 0)]
-{
- rtx dest = gen_rtx_REG (V4SFmode, REGNO (operands[0]));
- switch (INTVAL (operands[2]))
- {
- case 1:
- case 3:
- emit_insn (gen_sse_shufps_v4sf (dest, operands[1], operands[1],
- operands[2], operands[2],
- GEN_INT (INTVAL (operands[2]) + 4),
- GEN_INT (INTVAL (operands[2]) + 4)));
- break;
- case 2:
- emit_insn (gen_vec_interleave_highv4sf (dest, operands[1], operands[1]));
- break;
- default:
- /* 0 should be handled by the *vec_extractv4sf_0 pattern above. */
- gcc_unreachable ();
- }
- DONE;
-}
- [(set_attr "isa" "*,noavx,avx")
- (set_attr "type" "sselog,*,*")
- (set_attr "prefix_data16" "1,*,*")
- (set_attr "prefix_extra" "1,*,*")
- (set_attr "length_immediate" "1,*,*")
- (set_attr "prefix" "maybe_vex,*,*")
- (set_attr "mode" "V4SF,*,*")])
-
-(define_insn_and_split "*vec_extract_v4sf_mem"
- [(set (match_operand:SF 0 "register_operand" "=x*rf")
- (vec_select:SF
- (match_operand:V4SF 1 "memory_operand" "o")
- (parallel [(match_operand 2 "const_0_to_3_operand" "n")])))]
- "TARGET_SSE"
- "#"
- "&& reload_completed"
- [(const_int 0)]
-{
- int i = INTVAL (operands[2]);
-
- emit_move_insn (operands[0], adjust_address (operands[1], SFmode, i*4));
- DONE;
-})
-
;; Modes handled by vec_extract patterns.
(define_mode_iterator VEC_EXTRACT_MODE
[(V32QI "TARGET_AVX") V16QI
@@ -4164,15 +4296,14 @@
[(set (match_operand:V4DF 0 "register_operand" "=x,x")
(vec_select:V4DF
(vec_concat:V8DF
- (match_operand:V4DF 1 "nonimmediate_operand" "xm,x")
- (match_operand:V4DF 2 "nonimmediate_operand" " 1,xm"))
+ (match_operand:V4DF 1 "nonimmediate_operand" " x,m")
+ (match_operand:V4DF 2 "nonimmediate_operand" "xm,1"))
(parallel [(const_int 0) (const_int 4)
(const_int 2) (const_int 6)])))]
- "TARGET_AVX
- && (!MEM_P (operands[1]) || rtx_equal_p (operands[1], operands[2]))"
+ "TARGET_AVX"
"@
- vmovddup\t{%1, %0|%0, %1}
- vunpcklpd\t{%2, %1, %0|%0, %1, %2}"
+ vunpcklpd\t{%2, %1, %0|%0, %1, %2}
+ vmovddup\t{%1, %0|%0, %1}"
[(set_attr "type" "sselog")
(set_attr "prefix" "vex")
(set_attr "mode" "V4DF")])
@@ -4328,35 +4459,6 @@
DONE;
})
-;; Modes handled by vec_extract_even/odd pattern.
-(define_mode_iterator VEC_EXTRACT_EVENODD_MODE
- [(V16QI "TARGET_SSE2")
- (V8HI "TARGET_SSE2")
- (V4SI "TARGET_SSE2")
- (V2DI "TARGET_SSE2")
- (V8SF "TARGET_AVX") V4SF
- (V4DF "TARGET_AVX") (V2DF "TARGET_SSE2")])
-
-(define_expand "vec_extract_even<mode>"
- [(match_operand:VEC_EXTRACT_EVENODD_MODE 0 "register_operand" "")
- (match_operand:VEC_EXTRACT_EVENODD_MODE 1 "register_operand" "")
- (match_operand:VEC_EXTRACT_EVENODD_MODE 2 "register_operand" "")]
- "TARGET_SSE"
-{
- ix86_expand_vec_extract_even_odd (operands[0], operands[1], operands[2], 0);
- DONE;
-})
-
-(define_expand "vec_extract_odd<mode>"
- [(match_operand:VEC_EXTRACT_EVENODD_MODE 0 "register_operand" "")
- (match_operand:VEC_EXTRACT_EVENODD_MODE 1 "register_operand" "")
- (match_operand:VEC_EXTRACT_EVENODD_MODE 2 "register_operand" "")]
- "TARGET_SSE"
-{
- ix86_expand_vec_extract_even_odd (operands[0], operands[1], operands[2], 1);
- DONE;
-})
-
;; punpcklqdq and punpckhqdq are shorter than shufpd.
(define_insn "avx2_interleave_highv4di"
[(set (match_operand:V4DI 0 "register_operand" "=x")
@@ -4714,69 +4816,43 @@
(set_attr "prefix" "orig,vex,orig,vex,maybe_vex,orig,orig,vex,maybe_vex")
(set_attr "mode" "DF,DF,V1DF,V1DF,V1DF,V2DF,V1DF,V1DF,V1DF")])
-(define_expand "vec_dupv2df"
- [(set (match_operand:V2DF 0 "register_operand" "")
- (vec_duplicate:V2DF
- (match_operand:DF 1 "nonimmediate_operand" "")))]
- "TARGET_SSE2"
-{
- if (!TARGET_SSE3)
- operands[1] = force_reg (DFmode, operands[1]);
-})
-
-(define_insn "*vec_dupv2df_sse3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_duplicate:V2DF
- (match_operand:DF 1 "nonimmediate_operand" "xm")))]
- "TARGET_SSE3"
- "%vmovddup\t{%1, %0|%0, %1}"
- [(set_attr "type" "sselog1")
- (set_attr "prefix" "maybe_vex")
- (set_attr "mode" "DF")])
-
-(define_insn "*vec_dupv2df"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
+(define_insn "vec_dupv2df"
+ [(set (match_operand:V2DF 0 "register_operand" "=x,x")
(vec_duplicate:V2DF
- (match_operand:DF 1 "register_operand" "0")))]
+ (match_operand:DF 1 "nonimmediate_operand" " 0,xm")))]
"TARGET_SSE2"
- "unpcklpd\t%0, %0"
- [(set_attr "type" "sselog1")
+ "@
+ unpcklpd\t%0, %0
+ %vmovddup\t{%1, %0|%0, %1}"
+ [(set_attr "isa" "noavx,sse3")
+ (set_attr "type" "sselog1")
+ (set_attr "prefix" "orig,maybe_vex")
(set_attr "mode" "V2DF")])
-(define_insn "*vec_concatv2df_sse3"
- [(set (match_operand:V2DF 0 "register_operand" "=x")
- (vec_concat:V2DF
- (match_operand:DF 1 "nonimmediate_operand" "xm")
- (match_dup 1)))]
- "TARGET_SSE3"
- "%vmovddup\t{%1, %0|%0, %1}"
- [(set_attr "type" "sselog1")
- (set_attr "prefix" "maybe_vex")
- (set_attr "mode" "DF")])
-
(define_insn "*vec_concatv2df"
- [(set (match_operand:V2DF 0 "register_operand" "=x,x,x,x,x,x,x")
+ [(set (match_operand:V2DF 0 "register_operand" "=x,x,x,x,x,x,x,x")
(vec_concat:V2DF
- (match_operand:DF 1 "nonimmediate_operand" " 0,x,0,x,m,0,0")
- (match_operand:DF 2 "vector_move_operand" " x,x,m,m,C,x,m")))]
+ (match_operand:DF 1 "nonimmediate_operand" " 0,x,m,0,x,m,0,0")
+ (match_operand:DF 2 "vector_move_operand" " x,x,1,m,m,C,x,m")))]
"TARGET_SSE"
"@
unpcklpd\t{%2, %0|%0, %2}
vunpcklpd\t{%2, %1, %0|%0, %1, %2}
+ %vmovddup\t{%1, %0|%0, %1}
movhpd\t{%2, %0|%0, %2}
vmovhpd\t{%2, %1, %0|%0, %1, %2}
%vmovsd\t{%1, %0|%0, %1}
movlhps\t{%2, %0|%0, %2}
movhps\t{%2, %0|%0, %2}"
- [(set_attr "isa" "sse2_noavx,avx,sse2_noavx,avx,sse2,noavx,noavx")
+ [(set_attr "isa" "sse2_noavx,avx,sse3,sse2_noavx,avx,sse2,noavx,noavx")
(set (attr "type")
(if_then_else
- (eq_attr "alternative" "0,1")
+ (eq_attr "alternative" "0,1,2")
(const_string "sselog")
(const_string "ssemov")))
- (set_attr "prefix_data16" "*,*,1,*,*,*,*")
- (set_attr "prefix" "orig,vex,orig,vex,maybe_vex,orig,orig")
- (set_attr "mode" "V2DF,V2DF,V1DF,V1DF,DF,V4SF,V2SF")])
+ (set_attr "prefix_data16" "*,*,*,1,*,*,*,*")
+ (set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex,orig,orig")
+ (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,DF,V4SF,V2SF")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
@@ -4785,10 +4861,10 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_expand "neg<mode>2"
- [(set (match_operand:VI_128 0 "register_operand" "")
- (minus:VI_128
+ [(set (match_operand:VI_AVX2 0 "register_operand" "")
+ (minus:VI_AVX2
(match_dup 2)
- (match_operand:VI_128 1 "nonimmediate_operand" "")))]
+ (match_operand:VI_AVX2 1 "nonimmediate_operand" "")))]
"TARGET_SSE2"
"operands[2] = force_reg (<MODE>mode, CONST0_RTX (<MODE>mode));")
@@ -4838,10 +4914,10 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
-(define_insn_and_split "mulv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "")
- (mult:V16QI (match_operand:V16QI 1 "register_operand" "")
- (match_operand:V16QI 2 "register_operand" "")))]
+(define_insn_and_split "mul<mode>3"
+ [(set (match_operand:VI1_AVX2 0 "register_operand" "")
+ (mult:VI1_AVX2 (match_operand:VI1_AVX2 1 "register_operand" "")
+ (match_operand:VI1_AVX2 2 "register_operand" "")))]
"TARGET_SSE2
&& can_create_pseudo_p ()"
"#"
@@ -4850,34 +4926,41 @@
{
rtx t[6];
int i;
+ enum machine_mode mulmode = <sseunpackmode>mode;
for (i = 0; i < 6; ++i)
- t[i] = gen_reg_rtx (V16QImode);
+ t[i] = gen_reg_rtx (<MODE>mode);
/* Unpack data such that we've got a source byte in each low byte of
each word. We don't care what goes into the high byte of each word.
Rather than trying to get zero in there, most convenient is to let
it be a copy of the low byte. */
- emit_insn (gen_vec_interleave_highv16qi (t[0], operands[1], operands[1]));
- emit_insn (gen_vec_interleave_highv16qi (t[1], operands[2], operands[2]));
- emit_insn (gen_vec_interleave_lowv16qi (t[2], operands[1], operands[1]));
- emit_insn (gen_vec_interleave_lowv16qi (t[3], operands[2], operands[2]));
+ emit_insn (gen_<vec_avx2>_interleave_high<mode> (t[0], operands[1],
+ operands[1]));
+ emit_insn (gen_<vec_avx2>_interleave_high<mode> (t[1], operands[2],
+ operands[2]));
+ emit_insn (gen_<vec_avx2>_interleave_low<mode> (t[2], operands[1],
+ operands[1]));
+ emit_insn (gen_<vec_avx2>_interleave_low<mode> (t[3], operands[2],
+ operands[2]));
/* Multiply words. The end-of-line annotations here give a picture of what
the output of that instruction looks like. Dot means don't care; the
letters are the bytes of the result with A being the most significant. */
- emit_insn (gen_mulv8hi3 (gen_lowpart (V8HImode, t[4]), /* .A.B.C.D.E.F.G.H */
- gen_lowpart (V8HImode, t[0]),
- gen_lowpart (V8HImode, t[1])));
- emit_insn (gen_mulv8hi3 (gen_lowpart (V8HImode, t[5]), /* .I.J.K.L.M.N.O.P */
- gen_lowpart (V8HImode, t[2]),
- gen_lowpart (V8HImode, t[3])));
+ emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (mulmode, t[4]),
+ gen_rtx_MULT (mulmode, /* .A.B.C.D.E.F.G.H */
+ gen_lowpart (mulmode, t[0]),
+ gen_lowpart (mulmode, t[1]))));
+ emit_insn (gen_rtx_SET (VOIDmode, gen_lowpart (mulmode, t[5]),
+ gen_rtx_MULT (mulmode, /* .I.J.K.L.M.N.O.P */
+ gen_lowpart (mulmode, t[2]),
+ gen_lowpart (mulmode, t[3]))));
/* Extract the even bytes and merge them back together. */
ix86_expand_vec_extract_even_odd (operands[0], t[5], t[4], 0);
set_unique_reg_note (get_last_insn (), REG_EQUAL,
- gen_rtx_MULT (V16QImode, operands[1], operands[2]));
+ gen_rtx_MULT (<MODE>mode, operands[1], operands[2]));
DONE;
})
@@ -5337,10 +5420,10 @@
DONE;
})
-(define_insn_and_split "mulv2di3"
- [(set (match_operand:V2DI 0 "register_operand" "")
- (mult:V2DI (match_operand:V2DI 1 "register_operand" "")
- (match_operand:V2DI 2 "register_operand" "")))]
+(define_insn_and_split "mul<mode>3"
+ [(set (match_operand:VI8_AVX2 0 "register_operand" "")
+ (mult:VI8_AVX2 (match_operand:VI8_AVX2 1 "register_operand" "")
+ (match_operand:VI8_AVX2 2 "register_operand" "")))]
"TARGET_SSE2
&& can_create_pseudo_p ()"
"#"
@@ -5354,7 +5437,7 @@
op1 = operands[1];
op2 = operands[2];
- if (TARGET_XOP)
+ if (TARGET_XOP && <MODE>mode == V2DImode)
{
/* op1: A,B,C,D, op2: E,F,G,H */
op1 = gen_lowpart (V4SImode, op1);
@@ -5386,119 +5469,136 @@
}
else
{
- t1 = gen_reg_rtx (V2DImode);
- t2 = gen_reg_rtx (V2DImode);
- t3 = gen_reg_rtx (V2DImode);
- t4 = gen_reg_rtx (V2DImode);
- t5 = gen_reg_rtx (V2DImode);
- t6 = gen_reg_rtx (V2DImode);
+ t1 = gen_reg_rtx (<MODE>mode);
+ t2 = gen_reg_rtx (<MODE>mode);
+ t3 = gen_reg_rtx (<MODE>mode);
+ t4 = gen_reg_rtx (<MODE>mode);
+ t5 = gen_reg_rtx (<MODE>mode);
+ t6 = gen_reg_rtx (<MODE>mode);
thirtytwo = GEN_INT (32);
/* Multiply low parts. */
- emit_insn (gen_sse2_umulv2siv2di3 (t1, gen_lowpart (V4SImode, op1),
- gen_lowpart (V4SImode, op2)));
+ emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+ (t1, gen_lowpart (<ssepackmode>mode, op1),
+ gen_lowpart (<ssepackmode>mode, op2)));
- /* Shift input vectors left 32 bits so we can multiply high parts. */
- emit_insn (gen_lshrv2di3 (t2, op1, thirtytwo));
- emit_insn (gen_lshrv2di3 (t3, op2, thirtytwo));
+ /* Shift input vectors right 32 bits so we can multiply high parts. */
+ emit_insn (gen_lshr<mode>3 (t2, op1, thirtytwo));
+ emit_insn (gen_lshr<mode>3 (t3, op2, thirtytwo));
/* Multiply high parts by low parts. */
- emit_insn (gen_sse2_umulv2siv2di3 (t4, gen_lowpart (V4SImode, op1),
- gen_lowpart (V4SImode, t3)));
- emit_insn (gen_sse2_umulv2siv2di3 (t5, gen_lowpart (V4SImode, op2),
- gen_lowpart (V4SImode, t2)));
+ emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+ (t4, gen_lowpart (<ssepackmode>mode, op1),
+ gen_lowpart (<ssepackmode>mode, t3)));
+ emit_insn (gen_<sse2_avx2>_umulv<ssescalarnum>si<mode>3
+ (t5, gen_lowpart (<ssepackmode>mode, op2),
+ gen_lowpart (<ssepackmode>mode, t2)));
/* Shift them back. */
- emit_insn (gen_ashlv2di3 (t4, t4, thirtytwo));
- emit_insn (gen_ashlv2di3 (t5, t5, thirtytwo));
+ emit_insn (gen_ashl<mode>3 (t4, t4, thirtytwo));
+ emit_insn (gen_ashl<mode>3 (t5, t5, thirtytwo));
/* Add the three parts together. */
- emit_insn (gen_addv2di3 (t6, t1, t4));
- emit_insn (gen_addv2di3 (op0, t6, t5));
+ emit_insn (gen_add<mode>3 (t6, t1, t4));
+ emit_insn (gen_add<mode>3 (op0, t6, t5));
}
set_unique_reg_note (get_last_insn (), REG_EQUAL,
- gen_rtx_MULT (V2DImode, operands[1], operands[2]));
+ gen_rtx_MULT (<MODE>mode, operands[1], operands[2]));
DONE;
})
-(define_expand "vec_widen_smult_hi_v8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
+(define_expand "vec_widen_<s>mult_hi_<mode>"
+ [(match_operand:<sseunpackmode> 0 "register_operand" "")
+ (any_extend:<sseunpackmode>
+ (match_operand:VI2_AVX2 1 "register_operand" ""))
+ (match_operand:VI2_AVX2 2 "register_operand" "")]
"TARGET_SSE2"
{
rtx op1, op2, t1, t2, dest;
op1 = operands[1];
op2 = operands[2];
- t1 = gen_reg_rtx (V8HImode);
- t2 = gen_reg_rtx (V8HImode);
- dest = gen_lowpart (V8HImode, operands[0]);
+ t1 = gen_reg_rtx (<MODE>mode);
+ t2 = gen_reg_rtx (<MODE>mode);
+ dest = gen_lowpart (<MODE>mode, operands[0]);
- emit_insn (gen_mulv8hi3 (t1, op1, op2));
- emit_insn (gen_smulv8hi3_highpart (t2, op1, op2));
- emit_insn (gen_vec_interleave_highv8hi (dest, t1, t2));
+ emit_insn (gen_mul<mode>3 (t1, op1, op2));
+ emit_insn (gen_<s>mul<mode>3_highpart (t2, op1, op2));
+ emit_insn (gen_vec_interleave_high<mode> (dest, t1, t2));
DONE;
})
-(define_expand "vec_widen_smult_lo_v8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
+(define_expand "vec_widen_<s>mult_lo_<mode>"
+ [(match_operand:<sseunpackmode> 0 "register_operand" "")
+ (any_extend:<sseunpackmode>
+ (match_operand:VI2_AVX2 1 "register_operand" ""))
+ (match_operand:VI2_AVX2 2 "register_operand" "")]
"TARGET_SSE2"
{
rtx op1, op2, t1, t2, dest;
op1 = operands[1];
op2 = operands[2];
- t1 = gen_reg_rtx (V8HImode);
- t2 = gen_reg_rtx (V8HImode);
- dest = gen_lowpart (V8HImode, operands[0]);
+ t1 = gen_reg_rtx (<MODE>mode);
+ t2 = gen_reg_rtx (<MODE>mode);
+ dest = gen_lowpart (<MODE>mode, operands[0]);
- emit_insn (gen_mulv8hi3 (t1, op1, op2));
- emit_insn (gen_smulv8hi3_highpart (t2, op1, op2));
- emit_insn (gen_vec_interleave_lowv8hi (dest, t1, t2));
+ emit_insn (gen_mul<mode>3 (t1, op1, op2));
+ emit_insn (gen_<s>mul<mode>3_highpart (t2, op1, op2));
+ emit_insn (gen_vec_interleave_low<mode> (dest, t1, t2));
DONE;
})
-(define_expand "vec_widen_umult_hi_v8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
- "TARGET_SSE2"
+(define_expand "vec_widen_<s>mult_hi_v8si"
+ [(match_operand:V4DI 0 "register_operand" "")
+ (any_extend:V4DI (match_operand:V8SI 1 "nonimmediate_operand" ""))
+ (match_operand:V8SI 2 "nonimmediate_operand" "")]
+ "TARGET_AVX2"
{
- rtx op1, op2, t1, t2, dest;
-
- op1 = operands[1];
- op2 = operands[2];
- t1 = gen_reg_rtx (V8HImode);
- t2 = gen_reg_rtx (V8HImode);
- dest = gen_lowpart (V8HImode, operands[0]);
+ rtx t1, t2, t3, t4;
- emit_insn (gen_mulv8hi3 (t1, op1, op2));
- emit_insn (gen_umulv8hi3_highpart (t2, op1, op2));
- emit_insn (gen_vec_interleave_highv8hi (dest, t1, t2));
+ t1 = gen_reg_rtx (V4DImode);
+ t2 = gen_reg_rtx (V4DImode);
+ t3 = gen_reg_rtx (V8SImode);
+ t4 = gen_reg_rtx (V8SImode);
+ emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, operands[1]),
+ const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+ emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, operands[2]),
+ const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+ emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1),
+ GEN_INT (2 + (2 << 2) + (3 << 4) + (3 << 6))));
+ emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2),
+ GEN_INT (2 + (2 << 2) + (3 << 4) + (3 << 6))));
+ emit_insn (gen_avx2_<u>mulv4siv4di3 (operands[0], t3, t4));
DONE;
})
-(define_expand "vec_widen_umult_lo_v8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
- "TARGET_SSE2"
+(define_expand "vec_widen_<s>mult_lo_v8si"
+ [(match_operand:V4DI 0 "register_operand" "")
+ (any_extend:V4DI (match_operand:V8SI 1 "nonimmediate_operand" ""))
+ (match_operand:V8SI 2 "nonimmediate_operand" "")]
+ "TARGET_AVX2"
{
- rtx op1, op2, t1, t2, dest;
-
- op1 = operands[1];
- op2 = operands[2];
- t1 = gen_reg_rtx (V8HImode);
- t2 = gen_reg_rtx (V8HImode);
- dest = gen_lowpart (V8HImode, operands[0]);
+ rtx t1, t2, t3, t4;
- emit_insn (gen_mulv8hi3 (t1, op1, op2));
- emit_insn (gen_umulv8hi3_highpart (t2, op1, op2));
- emit_insn (gen_vec_interleave_lowv8hi (dest, t1, t2));
+ t1 = gen_reg_rtx (V4DImode);
+ t2 = gen_reg_rtx (V4DImode);
+ t3 = gen_reg_rtx (V8SImode);
+ t4 = gen_reg_rtx (V8SImode);
+ emit_insn (gen_avx2_permv4di_1 (t1, gen_lowpart (V4DImode, operands[1]),
+ const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+ emit_insn (gen_avx2_permv4di_1 (t2, gen_lowpart (V4DImode, operands[2]),
+ const0_rtx, const2_rtx,
+ const1_rtx, GEN_INT (3)));
+ emit_insn (gen_avx2_pshufdv3 (t3, gen_lowpart (V8SImode, t1),
+ GEN_INT (0 + (0 << 2) + (1 << 4) + (1 << 6))));
+ emit_insn (gen_avx2_pshufdv3 (t4, gen_lowpart (V8SImode, t2),
+ GEN_INT (0 + (0 << 2) + (1 << 4) + (1 << 6))));
+ emit_insn (gen_avx2_<u>mulv4siv4di3 (operands[0], t3, t4));
DONE;
})
@@ -5506,24 +5606,28 @@
[(match_operand:V2DI 0 "register_operand" "")
(match_operand:V4SI 1 "register_operand" "")
(match_operand:V4SI 2 "register_operand" "")]
- "TARGET_XOP"
+ "TARGET_SSE4_1"
{
- rtx t1, t2;
+ rtx op1, op2, t1, t2;
+ op1 = operands[1];
+ op2 = operands[2];
t1 = gen_reg_rtx (V4SImode);
t2 = gen_reg_rtx (V4SImode);
- emit_insn (gen_sse2_pshufd_1 (t1, operands[1],
- GEN_INT (0),
- GEN_INT (2),
- GEN_INT (1),
- GEN_INT (3)));
- emit_insn (gen_sse2_pshufd_1 (t2, operands[2],
- GEN_INT (0),
- GEN_INT (2),
- GEN_INT (1),
- GEN_INT (3)));
- emit_insn (gen_xop_mulv2div2di3_high (operands[0], t1, t2));
+ if (TARGET_XOP)
+ {
+ emit_insn (gen_sse2_pshufd_1 (t1, op1, GEN_INT (0), GEN_INT (2),
+ GEN_INT (1), GEN_INT (3)));
+ emit_insn (gen_sse2_pshufd_1 (t2, op2, GEN_INT (0), GEN_INT (2),
+ GEN_INT (1), GEN_INT (3)));
+ emit_insn (gen_xop_mulv2div2di3_high (operands[0], t1, t2));
+ DONE;
+ }
+
+ emit_insn (gen_vec_interleave_highv4si (t1, op1, op1));
+ emit_insn (gen_vec_interleave_highv4si (t2, op2, op2));
+ emit_insn (gen_sse4_1_mulv2siv2di3 (operands[0], t1, t2));
DONE;
})
@@ -5531,24 +5635,28 @@
[(match_operand:V2DI 0 "register_operand" "")
(match_operand:V4SI 1 "register_operand" "")
(match_operand:V4SI 2 "register_operand" "")]
- "TARGET_XOP"
+ "TARGET_SSE4_1"
{
- rtx t1, t2;
+ rtx op1, op2, t1, t2;
+ op1 = operands[1];
+ op2 = operands[2];
t1 = gen_reg_rtx (V4SImode);
t2 = gen_reg_rtx (V4SImode);
- emit_insn (gen_sse2_pshufd_1 (t1, operands[1],
- GEN_INT (0),
- GEN_INT (2),
- GEN_INT (1),
- GEN_INT (3)));
- emit_insn (gen_sse2_pshufd_1 (t2, operands[2],
- GEN_INT (0),
- GEN_INT (2),
- GEN_INT (1),
- GEN_INT (3)));
- emit_insn (gen_xop_mulv2div2di3_low (operands[0], t1, t2));
+ if (TARGET_XOP)
+ {
+ emit_insn (gen_sse2_pshufd_1 (t1, op1, GEN_INT (0), GEN_INT (2),
+ GEN_INT (1), GEN_INT (3)));
+ emit_insn (gen_sse2_pshufd_1 (t2, op2, GEN_INT (0), GEN_INT (2),
+ GEN_INT (1), GEN_INT (3)));
+ emit_insn (gen_xop_mulv2div2di3_low (operands[0], t1, t2));
+ DONE;
+ }
+
+ emit_insn (gen_vec_interleave_lowv4si (t1, op1, op1));
+ emit_insn (gen_vec_interleave_lowv4si (t2, op2, op2));
+ emit_insn (gen_sse4_1_mulv2siv2di3 (operands[0], t1, t2));
DONE;
})
@@ -5590,30 +5698,35 @@
DONE;
})
-(define_expand "sdot_prodv8hi"
- [(match_operand:V4SI 0 "register_operand" "")
- (match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")
- (match_operand:V4SI 3 "register_operand" "")]
+(define_expand "sdot_prod<mode>"
+ [(match_operand:<sseunpackmode> 0 "register_operand" "")
+ (match_operand:VI2_AVX2 1 "register_operand" "")
+ (match_operand:VI2_AVX2 2 "register_operand" "")
+ (match_operand:<sseunpackmode> 3 "register_operand" "")]
"TARGET_SSE2"
{
- rtx t = gen_reg_rtx (V4SImode);
- emit_insn (gen_sse2_pmaddwd (t, operands[1], operands[2]));
- emit_insn (gen_addv4si3 (operands[0], operands[3], t));
+ rtx t = gen_reg_rtx (<sseunpackmode>mode);
+ emit_insn (gen_<sse2_avx2>_pmaddwd (t, operands[1], operands[2]));
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_PLUS (<sseunpackmode>mode,
+ operands[3], t)));
DONE;
})
-(define_expand "udot_prodv4si"
+(define_code_attr sse2_sse4_1
+ [(zero_extend "sse2") (sign_extend "sse4_1")])
+
+(define_expand "<s>dot_prodv4si"
[(match_operand:V2DI 0 "register_operand" "")
- (match_operand:V4SI 1 "register_operand" "")
+ (any_extend:V2DI (match_operand:V4SI 1 "register_operand" ""))
(match_operand:V4SI 2 "register_operand" "")
(match_operand:V2DI 3 "register_operand" "")]
- "TARGET_SSE2"
+ "<CODE> == ZERO_EXTEND ? TARGET_SSE2 : TARGET_SSE4_1"
{
rtx t1, t2, t3, t4;
t1 = gen_reg_rtx (V2DImode);
- emit_insn (gen_sse2_umulv2siv2di3 (t1, operands[1], operands[2]));
+ emit_insn (gen_<sse2_sse4_1>_<u>mulv2siv2di3 (t1, operands[1], operands[2]));
emit_insn (gen_addv2di3 (t1, t1, operands[3]));
t2 = gen_reg_rtx (V4SImode);
@@ -5626,12 +5739,41 @@
GEN_INT (32)));
t4 = gen_reg_rtx (V2DImode);
- emit_insn (gen_sse2_umulv2siv2di3 (t4, t2, t3));
+ emit_insn (gen_<sse2_sse4_1>_<u>mulv2siv2di3 (t4, t2, t3));
emit_insn (gen_addv2di3 (operands[0], t1, t4));
DONE;
})
+(define_expand "<s>dot_prodv8si"
+ [(match_operand:V4DI 0 "register_operand" "")
+ (any_extend:V4DI (match_operand:V8SI 1 "register_operand" ""))
+ (match_operand:V8SI 2 "register_operand" "")
+ (match_operand:V4DI 3 "register_operand" "")]
+ "TARGET_AVX2"
+{
+ rtx t1, t2, t3, t4;
+
+ t1 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_<u>mulv4siv4di3 (t1, operands[1], operands[2]));
+ emit_insn (gen_addv4di3 (t1, t1, operands[3]));
+
+ t2 = gen_reg_rtx (V8SImode);
+ t3 = gen_reg_rtx (V8SImode);
+ emit_insn (gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, t2),
+ gen_lowpart (V2TImode, operands[1]),
+ GEN_INT (32)));
+ emit_insn (gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, t3),
+ gen_lowpart (V2TImode, operands[2]),
+ GEN_INT (32)));
+
+ t4 = gen_reg_rtx (V4DImode);
+ emit_insn (gen_avx2_<u>mulv4siv4di3 (t4, t2, t3));
+
+ emit_insn (gen_addv4di3 (operands[0], t1, t4));
+ DONE;
+})
+
(define_insn "ashr<mode>3"
[(set (match_operand:VI24_AVX2 0 "register_operand" "=x,x")
(ashiftrt:VI24_AVX2
@@ -5651,15 +5793,15 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "lshr<mode>3"
+(define_insn "<shift_insn><mode>3"
[(set (match_operand:VI248_AVX2 0 "register_operand" "=x,x")
- (lshiftrt:VI248_AVX2
+ (any_lshift:VI248_AVX2
(match_operand:VI248_AVX2 1 "register_operand" "0,x")
(match_operand:SI 2 "nonmemory_operand" "xN,xN")))]
"TARGET_SSE2"
"@
- psrl<ssemodesuffix>\t{%2, %0|%0, %2}
- vpsrl<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ p<vshift><ssemodesuffix>\t{%2, %0|%0, %2}
+ vp<vshift><ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "isa" "noavx,avx")
(set_attr "type" "sseishft")
(set (attr "length_immediate")
@@ -5670,40 +5812,6 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "avx2_lshl<mode>3"
- [(set (match_operand:VI248_256 0 "register_operand" "=x")
- (ashift:VI248_256
- (match_operand:VI248_256 1 "register_operand" "x")
- (match_operand:SI 2 "nonmemory_operand" "xN")))]
- "TARGET_AVX2"
- "vpsll<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
- (set (attr "length_immediate")
- (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "1")
- (const_string "0")))
- (set_attr "mode" "OI")])
-
-(define_insn "ashl<mode>3"
- [(set (match_operand:VI248_128 0 "register_operand" "=x,x")
- (ashift:VI248_128
- (match_operand:VI248_128 1 "register_operand" "0,x")
- (match_operand:SI 2 "nonmemory_operand" "xN,xN")))]
- "TARGET_SSE2"
- "@
- psll<ssemodesuffix>\t{%2, %0|%0, %2}
- vpsll<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "isa" "noavx,avx")
- (set_attr "type" "sseishft")
- (set (attr "length_immediate")
- (if_then_else (match_operand 2 "const_int_operand" "")
- (const_string "1")
- (const_string "0")))
- (set_attr "prefix_data16" "1,*")
- (set_attr "prefix" "orig,vex")
- (set_attr "mode" "TI")])
-
(define_expand "vec_shl_<mode>"
[(set (match_operand:VI_128 0 "register_operand" "")
(ashift:V1TI
@@ -5802,8 +5910,9 @@
(define_expand "<code><mode>3"
[(set (match_operand:VI8_AVX2 0 "register_operand" "")
- (maxmin:VI8_AVX2 (match_operand:VI8_AVX2 1 "register_operand" "")
- (match_operand:VI8_AVX2 2 "register_operand" "")))]
+ (maxmin:VI8_AVX2
+ (match_operand:VI8_AVX2 1 "register_operand" "")
+ (match_operand:VI8_AVX2 2 "register_operand" "")))]
"TARGET_SSE4_2"
{
enum rtx_code code;
@@ -5836,8 +5945,9 @@
(define_expand "<code><mode>3"
[(set (match_operand:VI124_128 0 "register_operand" "")
- (smaxmin:VI124_128 (match_operand:VI124_128 1 "nonimmediate_operand" "")
- (match_operand:VI124_128 2 "nonimmediate_operand" "")))]
+ (smaxmin:VI124_128
+ (match_operand:VI124_128 1 "nonimmediate_operand" "")
+ (match_operand:VI124_128 2 "nonimmediate_operand" "")))]
"TARGET_SSE2"
{
if (TARGET_SSE4_1 || <MODE>mode == V8HImode)
@@ -5905,8 +6015,9 @@
(define_expand "<code><mode>3"
[(set (match_operand:VI124_128 0 "register_operand" "")
- (umaxmin:VI124_128 (match_operand:VI124_128 1 "nonimmediate_operand" "")
- (match_operand:VI124_128 2 "nonimmediate_operand" "")))]
+ (umaxmin:VI124_128
+ (match_operand:VI124_128 1 "nonimmediate_operand" "")
+ (match_operand:VI124_128 2 "nonimmediate_operand" "")))]
"TARGET_SSE2"
{
if (TARGET_SSE4_1 || <MODE>mode == V16QImode)
@@ -6196,11 +6307,9 @@
DONE;
})
-;; ??? Irritatingly, the 256-bit VPSHUFB only shuffles within the 128-bit
-;; lanes. For now, we don't try to support V32QI or V16HImode. So we
-;; don't want to use VI_AVX2.
(define_mode_iterator VEC_PERM_AVX2
[V16QI V8HI V4SI V2DI V4SF V2DF
+ (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")
(V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2")
(V8SF "TARGET_AVX2") (V4DF "TARGET_AVX2")])
@@ -6215,6 +6324,27 @@
DONE;
})
+(define_mode_iterator VEC_PERM_CONST
+ [(V4SF "TARGET_SSE") (V4SI "TARGET_SSE")
+ (V2DF "TARGET_SSE") (V2DI "TARGET_SSE")
+ (V16QI "TARGET_SSE2") (V8HI "TARGET_SSE2")
+ (V8SF "TARGET_AVX") (V4DF "TARGET_AVX")
+ (V8SI "TARGET_AVX") (V4DI "TARGET_AVX")
+ (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")])
+
+(define_expand "vec_perm_const<mode>"
+ [(match_operand:VEC_PERM_CONST 0 "register_operand" "")
+ (match_operand:VEC_PERM_CONST 1 "register_operand" "")
+ (match_operand:VEC_PERM_CONST 2 "register_operand" "")
+ (match_operand:<sseintvecmode> 3 "" "")]
+ ""
+{
+ if (ix86_expand_vec_perm_const (operands))
+ DONE;
+ else
+ FAIL;
+})
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Parallel bitwise logical operations
@@ -6431,8 +6561,8 @@
(define_expand "vec_pack_trunc_<mode>"
[(match_operand:<ssepackmode> 0 "register_operand" "")
- (match_operand:VI248_128 1 "register_operand" "")
- (match_operand:VI248_128 2 "register_operand" "")]
+ (match_operand:VI248_AVX2 1 "register_operand" "")
+ (match_operand:VI248_AVX2 2 "register_operand" "")]
"TARGET_SSE2"
{
rtx op1 = gen_lowpart (<ssepackmode>mode, operands[1]);
@@ -6513,8 +6643,7 @@
(const_int 28) (const_int 60)
(const_int 29) (const_int 61)
(const_int 30) (const_int 62)
- (const_int 31) (const_int 63)
- (const_int 32) (const_int 64)])))]
+ (const_int 31) (const_int 63)])))]
"TARGET_AVX2"
"vpunpckhbw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
@@ -6559,7 +6688,6 @@
(const_int 5) (const_int 37)
(const_int 6) (const_int 38)
(const_int 7) (const_int 39)
- (const_int 15) (const_int 47)
(const_int 16) (const_int 48)
(const_int 17) (const_int 49)
(const_int 18) (const_int 50)
@@ -6746,6 +6874,38 @@
(set_attr "prefix" "orig,vex")
(set_attr "mode" "TI")])
+(define_expand "vec_interleave_high<mode>"
+ [(match_operand:VI_256 0 "register_operand" "=x")
+ (match_operand:VI_256 1 "register_operand" "x")
+ (match_operand:VI_256 2 "nonimmediate_operand" "xm")]
+ "TARGET_AVX2"
+{
+ rtx t1 = gen_reg_rtx (<MODE>mode);
+ rtx t2 = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2]));
+ emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2]));
+ emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, operands[0]),
+ gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2), GEN_INT (1 + (3 << 4))));
+ DONE;
+})
+
+(define_expand "vec_interleave_low<mode>"
+ [(match_operand:VI_256 0 "register_operand" "=x")
+ (match_operand:VI_256 1 "register_operand" "x")
+ (match_operand:VI_256 2 "nonimmediate_operand" "xm")]
+ "TARGET_AVX2"
+{
+ rtx t1 = gen_reg_rtx (<MODE>mode);
+ rtx t2 = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2]));
+ emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2]));
+ emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, operands[0]),
+ gen_lowpart (V4DImode, t1),
+ gen_lowpart (V4DImode, t2), GEN_INT (0 + (2 << 4))));
+ DONE;
+})
+
;; Modes handled by pinsr patterns.
(define_mode_iterator PINSR_MODE
[(V16QI "TARGET_SSE4_1") V8HI
@@ -6919,7 +7079,11 @@
GEN_INT ((mask >> 0) & 3),
GEN_INT ((mask >> 2) & 3),
GEN_INT ((mask >> 4) & 3),
- GEN_INT ((mask >> 6) & 3)));
+ GEN_INT ((mask >> 6) & 3),
+ GEN_INT (((mask >> 0) & 3) + 4),
+ GEN_INT (((mask >> 2) & 3) + 4),
+ GEN_INT (((mask >> 4) & 3) + 4),
+ GEN_INT (((mask >> 6) & 3) + 4)));
DONE;
})
@@ -6931,11 +7095,15 @@
(match_operand 3 "const_0_to_3_operand" "")
(match_operand 4 "const_0_to_3_operand" "")
(match_operand 5 "const_0_to_3_operand" "")
- (match_dup 2)
- (match_dup 3)
- (match_dup 4)
- (match_dup 5)])))]
- "TARGET_AVX2"
+ (match_operand 6 "const_4_to_7_operand" "")
+ (match_operand 7 "const_4_to_7_operand" "")
+ (match_operand 8 "const_4_to_7_operand" "")
+ (match_operand 9 "const_4_to_7_operand" "")])))]
+ "TARGET_AVX2
+ && INTVAL (operands[2]) + 4 == INTVAL (operands[6])
+ && INTVAL (operands[3]) + 4 == INTVAL (operands[7])
+ && INTVAL (operands[4]) + 4 == INTVAL (operands[8])
+ && INTVAL (operands[5]) + 4 == INTVAL (operands[9])"
{
int mask = 0;
mask |= INTVAL (operands[2]) << 0;
@@ -7002,7 +7170,11 @@
GEN_INT ((mask >> 0) & 3),
GEN_INT ((mask >> 2) & 3),
GEN_INT ((mask >> 4) & 3),
- GEN_INT ((mask >> 6) & 3)));
+ GEN_INT ((mask >> 6) & 3),
+ GEN_INT (((mask >> 0) & 3) + 8),
+ GEN_INT (((mask >> 2) & 3) + 8),
+ GEN_INT (((mask >> 4) & 3) + 8),
+ GEN_INT (((mask >> 6) & 3) + 8)));
DONE;
})
@@ -7018,15 +7190,19 @@
(const_int 5)
(const_int 6)
(const_int 7)
- (match_dup 2)
- (match_dup 3)
- (match_dup 4)
- (match_dup 5)
+ (match_operand 6 "const_8_to_11_operand" "")
+ (match_operand 7 "const_8_to_11_operand" "")
+ (match_operand 8 "const_8_to_11_operand" "")
+ (match_operand 9 "const_8_to_11_operand" "")
(const_int 12)
(const_int 13)
(const_int 14)
(const_int 15)])))]
- "TARGET_AVX2"
+ "TARGET_AVX2
+ && INTVAL (operands[2]) + 8 == INTVAL (operands[6])
+ && INTVAL (operands[3]) + 8 == INTVAL (operands[7])
+ && INTVAL (operands[4]) + 8 == INTVAL (operands[8])
+ && INTVAL (operands[5]) + 8 == INTVAL (operands[9])"
{
int mask = 0;
mask |= INTVAL (operands[2]) << 0;
@@ -7098,7 +7274,11 @@
GEN_INT (((mask >> 0) & 3) + 4),
GEN_INT (((mask >> 2) & 3) + 4),
GEN_INT (((mask >> 4) & 3) + 4),
- GEN_INT (((mask >> 6) & 3) + 4)));
+ GEN_INT (((mask >> 6) & 3) + 4),
+ GEN_INT (((mask >> 0) & 3) + 12),
+ GEN_INT (((mask >> 2) & 3) + 12),
+ GEN_INT (((mask >> 4) & 3) + 12),
+ GEN_INT (((mask >> 6) & 3) + 12)));
DONE;
})
@@ -7118,11 +7298,15 @@
(const_int 9)
(const_int 10)
(const_int 11)
- (match_dup 2)
- (match_dup 3)
- (match_dup 4)
- (match_dup 5)])))]
- "TARGET_AVX2"
+ (match_operand 6 "const_12_to_15_operand" "")
+ (match_operand 7 "const_12_to_15_operand" "")
+ (match_operand 8 "const_12_to_15_operand" "")
+ (match_operand 9 "const_12_to_15_operand" "")])))]
+ "TARGET_AVX2
+ && INTVAL (operands[2]) + 8 == INTVAL (operands[6])
+ && INTVAL (operands[3]) + 8 == INTVAL (operands[7])
+ && INTVAL (operands[4]) + 8 == INTVAL (operands[8])
+ && INTVAL (operands[5]) + 8 == INTVAL (operands[9])"
{
int mask = 0;
mask |= (INTVAL (operands[2]) - 4) << 0;
@@ -7323,58 +7507,36 @@
(set_attr "prefix" "maybe_vex,orig,vex,maybe_vex,orig,orig")
(set_attr "mode" "V2SF,TI,TI,TI,V4SF,V2SF")])
-(define_insn "*vec_dupv4si_avx"
- [(set (match_operand:V4SI 0 "register_operand" "=x,x")
- (vec_duplicate:V4SI
- (match_operand:SI 1 "nonimmediate_operand" " x,m")))]
- "TARGET_AVX"
- "@
- vpshufd\t{$0, %1, %0|%0, %1, 0}
- vbroadcastss\t{%1, %0|%0, %1}"
- [(set_attr "type" "sselog1,ssemov")
- (set_attr "length_immediate" "1,0")
- (set_attr "prefix_extra" "0,1")
- (set_attr "prefix" "vex")
- (set_attr "mode" "TI,V4SF")])
-
(define_insn "*vec_dupv4si"
- [(set (match_operand:V4SI 0 "register_operand" "=x,x")
+ [(set (match_operand:V4SI 0 "register_operand" "=x,x,x")
(vec_duplicate:V4SI
- (match_operand:SI 1 "register_operand" " x,0")))]
+ (match_operand:SI 1 "nonimmediate_operand" " x,m,0")))]
"TARGET_SSE"
"@
- pshufd\t{$0, %1, %0|%0, %1, 0}
+ %vpshufd\t{$0, %1, %0|%0, %1, 0}
+ vbroadcastss\t{%1, %0|%0, %1}
shufps\t{$0, %0, %0|%0, %0, 0}"
- [(set_attr "isa" "sse2,*")
- (set_attr "type" "sselog1")
- (set_attr "length_immediate" "1")
- (set_attr "mode" "TI,V4SF")])
-
-(define_insn "*vec_dupv2di_sse3"
- [(set (match_operand:V2DI 0 "register_operand" "=x,x,x")
- (vec_duplicate:V2DI
- (match_operand:DI 1 "nonimmediate_operand" " 0,x,m")))]
- "TARGET_SSE3"
- "@
- punpcklqdq\t%0, %0
- vpunpcklqdq\t{%d1, %0|%0, %d1}
- %vmovddup\t{%1, %0|%0, %1}"
- [(set_attr "isa" "noavx,avx,*")
- (set_attr "type" "sselog1")
- (set_attr "prefix" "orig,vex,maybe_vex")
- (set_attr "mode" "TI,TI,DF")])
+ [(set_attr "isa" "sse2,avx,noavx")
+ (set_attr "type" "sselog1,ssemov,sselog1")
+ (set_attr "length_immediate" "1,0,1")
+ (set_attr "prefix_extra" "0,1,*")
+ (set_attr "prefix" "maybe_vex,vex,orig")
+ (set_attr "mode" "TI,V4SF,V4SF")])
(define_insn "*vec_dupv2di"
- [(set (match_operand:V2DI 0 "register_operand" "=x,x")
+ [(set (match_operand:V2DI 0 "register_operand" "=x,x,x,x")
(vec_duplicate:V2DI
- (match_operand:DI 1 "register_operand" " 0,0")))]
+ (match_operand:DI 1 "nonimmediate_operand" " 0,x,m,0")))]
"TARGET_SSE"
"@
punpcklqdq\t%0, %0
+ vpunpcklqdq\t{%d1, %0|%0, %d1}
+ %vmovddup\t{%1, %0|%0, %1}
movlhps\t%0, %0"
- [(set_attr "isa" "sse2,*")
- (set_attr "type" "sselog1,ssemov")
- (set_attr "mode" "TI,V4SF")])
+ [(set_attr "isa" "sse2_noavx,avx,sse3,noavx")
+ (set_attr "type" "sselog1,sselog1,sselog1,ssemov")
+ (set_attr "prefix" "orig,vex,maybe_vex,orig")
+ (set_attr "mode" "TI,TI,DF,V4SF")])
(define_insn "*vec_concatv2si_sse4_1"
[(set (match_operand:V2SI 0 "register_operand" "=x, x,x,x, x, *y,*y")
@@ -7503,25 +7665,25 @@
(define_expand "vec_unpacks_lo_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")]
+ (match_operand:VI124_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands, false, false); DONE;")
(define_expand "vec_unpacks_hi_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")]
+ (match_operand:VI124_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands, false, true); DONE;")
(define_expand "vec_unpacku_lo_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")]
+ (match_operand:VI124_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands, true, false); DONE;")
(define_expand "vec_unpacku_hi_<mode>"
[(match_operand:<sseunpackmode> 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")]
+ (match_operand:VI124_AVX2 1 "register_operand" "")]
"TARGET_SSE2"
"ix86_expand_sse_unpack (operands, true, true); DONE;")
@@ -9514,7 +9676,7 @@
(const_int 6)
(const_int 7)]))))]
"TARGET_SSE4_1"
- "%vpmov<extsuffix>bw\t{%1, %0|%0, %1}"
+ "%vpmov<extsuffix>bw\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
@@ -9534,7 +9696,7 @@
(const_int 6)
(const_int 7)]))))]
"TARGET_AVX2"
- "vpmov<extsuffix>bd\t{%1, %0|%0, %1}"
+ "vpmov<extsuffix>bd\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
@@ -9550,7 +9712,7 @@
(const_int 2)
(const_int 3)]))))]
"TARGET_SSE4_1"
- "%vpmov<extsuffix>bd\t{%1, %0|%0, %1}"
+ "%vpmov<extsuffix>bd\t{%1, %0|%0, %k1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
@@ -9577,7 +9739,7 @@
(const_int 2)
(const_int 3)]))))]
"TARGET_SSE4_1"
- "%vpmov<extsuffix>wd\t{%1, %0|%0, %1}"
+ "%vpmov<extsuffix>wd\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
@@ -9593,7 +9755,7 @@
(const_int 2)
(const_int 3)]))))]
"TARGET_AVX2"
- "vpmov<extsuffix>bq\t{%1, %0|%0, %1}"
+ "vpmov<extsuffix>bq\t{%1, %0|%0, %k1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
@@ -9607,7 +9769,7 @@
(parallel [(const_int 0)
(const_int 1)]))))]
"TARGET_SSE4_1"
- "%vpmov<extsuffix>bq\t{%1, %0|%0, %1}"
+ "%vpmov<extsuffix>bq\t{%1, %0|%0, %w1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
@@ -9623,7 +9785,7 @@
(const_int 2)
(const_int 3)]))))]
"TARGET_AVX2"
- "vpmov<extsuffix>wq\t{%1, %0|%0, %1}"
+ "vpmov<extsuffix>wq\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
@@ -9637,7 +9799,7 @@
(parallel [(const_int 0)
(const_int 1)]))))]
"TARGET_SSE4_1"
- "%vpmov<extsuffix>wq\t{%1, %0|%0, %1}"
+ "%vpmov<extsuffix>wq\t{%1, %0|%0, %k1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
@@ -9661,7 +9823,7 @@
(parallel [(const_int 0)
(const_int 1)]))))]
"TARGET_SSE4_1"
- "%vpmov<extsuffix>dq\t{%1, %0|%0, %1}"
+ "%vpmov<extsuffix>dq\t{%1, %0|%0, %q1}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
@@ -11030,42 +11192,110 @@
(set_attr "mode" "TI")])
;; XOP packed shift instructions.
-;; FIXME: add V2DI back in
(define_expand "vlshr<mode>3"
- [(match_operand:VI124_128 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")
- (match_operand:VI124_128 2 "register_operand" "")]
+ [(set (match_operand:VI12_128 0 "register_operand" "")
+ (lshiftrt:VI12_128
+ (match_operand:VI12_128 1 "register_operand" "")
+ (match_operand:VI12_128 2 "nonimmediate_operand" "")))]
"TARGET_XOP"
{
rtx neg = gen_reg_rtx (<MODE>mode);
emit_insn (gen_neg<mode>2 (neg, operands[2]));
- emit_insn (gen_xop_lshl<mode>3 (operands[0], operands[1], neg));
+ emit_insn (gen_xop_shl<mode>3 (operands[0], operands[1], neg));
DONE;
})
+(define_expand "vlshr<mode>3"
+ [(set (match_operand:VI48_128 0 "register_operand" "")
+ (lshiftrt:VI48_128
+ (match_operand:VI48_128 1 "register_operand" "")
+ (match_operand:VI48_128 2 "nonimmediate_operand" "")))]
+ "TARGET_AVX2 || TARGET_XOP"
+{
+ if (!TARGET_AVX2)
+ {
+ rtx neg = gen_reg_rtx (<MODE>mode);
+ emit_insn (gen_neg<mode>2 (neg, operands[2]));
+ emit_insn (gen_xop_shl<mode>3 (operands[0], operands[1], neg));
+ DONE;
+ }
+})
+
+(define_expand "vlshr<mode>3"
+ [(set (match_operand:VI48_256 0 "register_operand" "")
+ (lshiftrt:VI48_256
+ (match_operand:VI48_256 1 "register_operand" "")
+ (match_operand:VI48_256 2 "nonimmediate_operand" "")))]
+ "TARGET_AVX2")
+
(define_expand "vashr<mode>3"
- [(match_operand:VI124_128 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")
- (match_operand:VI124_128 2 "register_operand" "")]
+ [(set (match_operand:VI128_128 0 "register_operand" "")
+ (ashiftrt:VI128_128
+ (match_operand:VI128_128 1 "register_operand" "")
+ (match_operand:VI128_128 2 "nonimmediate_operand" "")))]
"TARGET_XOP"
{
rtx neg = gen_reg_rtx (<MODE>mode);
emit_insn (gen_neg<mode>2 (neg, operands[2]));
- emit_insn (gen_xop_ashl<mode>3 (operands[0], operands[1], neg));
+ emit_insn (gen_xop_sha<mode>3 (operands[0], operands[1], neg));
DONE;
})
+(define_expand "vashrv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "")
+ (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "")
+ (match_operand:V4SI 2 "nonimmediate_operand" "")))]
+ "TARGET_AVX2 || TARGET_XOP"
+{
+ if (!TARGET_AVX2)
+ {
+ rtx neg = gen_reg_rtx (V4SImode);
+ emit_insn (gen_negv4si2 (neg, operands[2]));
+ emit_insn (gen_xop_shav4si3 (operands[0], operands[1], neg));
+ DONE;
+ }
+})
+
+(define_expand "vashrv8si3"
+ [(set (match_operand:V8SI 0 "register_operand" "")
+ (ashiftrt:V8SI (match_operand:V8SI 1 "register_operand" "")
+ (match_operand:V8SI 2 "nonimmediate_operand" "")))]
+ "TARGET_AVX2")
+
(define_expand "vashl<mode>3"
- [(match_operand:VI124_128 0 "register_operand" "")
- (match_operand:VI124_128 1 "register_operand" "")
- (match_operand:VI124_128 2 "register_operand" "")]
+ [(set (match_operand:VI12_128 0 "register_operand" "")
+ (ashift:VI12_128
+ (match_operand:VI12_128 1 "register_operand" "")
+ (match_operand:VI12_128 2 "nonimmediate_operand" "")))]
"TARGET_XOP"
{
- emit_insn (gen_xop_ashl<mode>3 (operands[0], operands[1], operands[2]));
+ emit_insn (gen_xop_sha<mode>3 (operands[0], operands[1], operands[2]));
DONE;
})
-(define_insn "xop_ashl<mode>3"
+(define_expand "vashl<mode>3"
+ [(set (match_operand:VI48_128 0 "register_operand" "")
+ (ashift:VI48_128
+ (match_operand:VI48_128 1 "register_operand" "")
+ (match_operand:VI48_128 2 "nonimmediate_operand" "")))]
+ "TARGET_AVX2 || TARGET_XOP"
+{
+ if (!TARGET_AVX2)
+ {
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+ emit_insn (gen_xop_sha<mode>3 (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+})
+
+(define_expand "vashl<mode>3"
+ [(set (match_operand:VI48_256 0 "register_operand" "")
+ (ashift:VI48_256
+ (match_operand:VI48_256 1 "register_operand" "")
+ (match_operand:VI48_256 2 "nonimmediate_operand" "")))]
+ "TARGET_AVX2")
+
+(define_insn "xop_sha<mode>3"
[(set (match_operand:VI_128 0 "register_operand" "=x,x")
(if_then_else:VI_128
(ge:VI_128
@@ -11084,7 +11314,7 @@
(set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
-(define_insn "xop_lshl<mode>3"
+(define_insn "xop_shl<mode>3"
[(set (match_operand:VI_128 0 "register_operand" "=x,x")
(if_then_else:VI_128
(ge:VI_128
@@ -11103,104 +11333,90 @@
(set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
-;; SSE2 doesn't have some shift varients, so define versions for XOP
+;; SSE2 doesn't have some shift variants, so define versions for XOP
(define_expand "ashlv16qi3"
- [(match_operand:V16QI 0 "register_operand" "")
- (match_operand:V16QI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")]
+ [(set (match_operand:V16QI 0 "register_operand" "")
+ (ashift:V16QI
+ (match_operand:V16QI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
"TARGET_XOP"
{
- rtvec vs = rtvec_alloc (16);
- rtx par = gen_rtx_PARALLEL (V16QImode, vs);
rtx reg = gen_reg_rtx (V16QImode);
+ rtx par;
int i;
- for (i = 0; i < 16; i++)
- RTVEC_ELT (vs, i) = operands[2];
-
- emit_insn (gen_vec_initv16qi (reg, par));
- emit_insn (gen_xop_ashlv16qi3 (operands[0], operands[1], reg));
- DONE;
-})
-(define_expand "lshlv16qi3"
- [(match_operand:V16QI 0 "register_operand" "")
- (match_operand:V16QI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")]
- "TARGET_XOP"
-{
- rtvec vs = rtvec_alloc (16);
- rtx par = gen_rtx_PARALLEL (V16QImode, vs);
- rtx reg = gen_reg_rtx (V16QImode);
- int i;
+ par = gen_rtx_PARALLEL (V16QImode, rtvec_alloc (16));
for (i = 0; i < 16; i++)
- RTVEC_ELT (vs, i) = operands[2];
+ XVECEXP (par, 0, i) = operands[2];
emit_insn (gen_vec_initv16qi (reg, par));
- emit_insn (gen_xop_lshlv16qi3 (operands[0], operands[1], reg));
+ emit_insn (gen_xop_shav16qi3 (operands[0], operands[1], reg));
DONE;
})
-(define_expand "ashrv16qi3"
- [(match_operand:V16QI 0 "register_operand" "")
- (match_operand:V16QI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")]
+(define_expand "<shift_insn>v16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "")
+ (any_shiftrt:V16QI
+ (match_operand:V16QI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
"TARGET_XOP"
{
- rtvec vs = rtvec_alloc (16);
- rtx par = gen_rtx_PARALLEL (V16QImode, vs);
rtx reg = gen_reg_rtx (V16QImode);
+ rtx par;
+ bool negate = false;
+ rtx (*shift_insn)(rtx, rtx, rtx);
int i;
- rtx ele = ((CONST_INT_P (operands[2]))
- ? GEN_INT (- INTVAL (operands[2]))
- : operands[2]);
+ if (CONST_INT_P (operands[2]))
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
+ else
+ negate = true;
+
+ par = gen_rtx_PARALLEL (V16QImode, rtvec_alloc (16));
for (i = 0; i < 16; i++)
- RTVEC_ELT (vs, i) = ele;
+ XVECEXP (par, 0, i) = operands[2];
emit_insn (gen_vec_initv16qi (reg, par));
- if (!CONST_INT_P (operands[2]))
- {
- rtx neg = gen_reg_rtx (V16QImode);
- emit_insn (gen_negv16qi2 (neg, reg));
- emit_insn (gen_xop_ashlv16qi3 (operands[0], operands[1], neg));
- }
+ if (negate)
+ emit_insn (gen_negv16qi2 (reg, reg));
+
+ if (<CODE> == LSHIFTRT)
+ shift_insn = gen_xop_shlv16qi3;
else
- emit_insn (gen_xop_ashlv16qi3 (operands[0], operands[1], reg));
+ shift_insn = gen_xop_shav16qi3;
+ emit_insn (shift_insn (operands[0], operands[1], reg));
DONE;
})
(define_expand "ashrv2di3"
- [(match_operand:V2DI 0 "register_operand" "")
- (match_operand:V2DI 1 "register_operand" "")
- (match_operand:DI 2 "nonmemory_operand" "")]
+ [(set (match_operand:V2DI 0 "register_operand" "")
+ (ashiftrt:V2DI
+ (match_operand:V2DI 1 "register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
"TARGET_XOP"
{
- rtvec vs = rtvec_alloc (2);
- rtx par = gen_rtx_PARALLEL (V2DImode, vs);
rtx reg = gen_reg_rtx (V2DImode);
- rtx ele;
+ rtx par;
+ bool negate = false;
+ int i;
if (CONST_INT_P (operands[2]))
- ele = GEN_INT (- INTVAL (operands[2]));
- else if (GET_MODE (operands[2]) != DImode)
- {
- rtx move = gen_reg_rtx (DImode);
- ele = gen_reg_rtx (DImode);
- convert_move (move, operands[2], false);
- emit_insn (gen_negdi2 (ele, move));
- }
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
else
- {
- ele = gen_reg_rtx (DImode);
- emit_insn (gen_negdi2 (ele, operands[2]));
- }
+ negate = true;
+
+ par = gen_rtx_PARALLEL (V2DImode, rtvec_alloc (2));
+ for (i = 0; i < 2; i++)
+ XVECEXP (par, 0, i) = operands[2];
- RTVEC_ELT (vs, 0) = ele;
- RTVEC_ELT (vs, 1) = ele;
emit_insn (gen_vec_initv2di (reg, par));
- emit_insn (gen_xop_ashlv2di3 (operands[0], operands[1], reg));
+
+ if (negate)
+ emit_insn (gen_negv2di2 (reg, reg));
+
+ emit_insn (gen_xop_shav2di3 (operands[0], operands[1], reg));
DONE;
})
@@ -11526,14 +11742,39 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
-(define_insn "avx2_permv4di"
+(define_expand "avx2_permv4di"
+ [(match_operand:V4DI 0 "register_operand" "")
+ (match_operand:V4DI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_0_to_255_operand" "")]
+ "TARGET_AVX2"
+{
+ int mask = INTVAL (operands[2]);
+ emit_insn (gen_avx2_permv4di_1 (operands[0], operands[1],
+ GEN_INT ((mask >> 0) & 3),
+ GEN_INT ((mask >> 2) & 3),
+ GEN_INT ((mask >> 4) & 3),
+ GEN_INT ((mask >> 6) & 3)));
+ DONE;
+})
+
+(define_insn "avx2_permv4di_1"
[(set (match_operand:V4DI 0 "register_operand" "=x")
- (unspec:V4DI
- [(match_operand:V4DI 1 "register_operand" "xm")
- (match_operand:SI 2 "const_0_to_255_operand" "n")]
- UNSPEC_VPERMDI))]
+ (vec_select:V4DI
+ (match_operand:V4DI 1 "nonimmediate_operand" "xm")
+ (parallel [(match_operand 2 "const_0_to_3_operand" "")
+ (match_operand 3 "const_0_to_3_operand" "")
+ (match_operand 4 "const_0_to_3_operand" "")
+ (match_operand 5 "const_0_to_3_operand" "")])))]
"TARGET_AVX2"
- "vpermq\t{%2, %1, %0|%0, %1, %2}"
+{
+ int mask = 0;
+ mask |= INTVAL (operands[2]) << 0;
+ mask |= INTVAL (operands[3]) << 2;
+ mask |= INTVAL (operands[4]) << 4;
+ mask |= INTVAL (operands[5]) << 6;
+ operands[2] = GEN_INT (mask);
+ return "vpermq\t{%2, %1, %0|%0, %1, %2}";
+}
[(set_attr "type" "sselog")
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
@@ -11542,7 +11783,7 @@
[(set (match_operand:V4DI 0 "register_operand" "=x")
(unspec:V4DI
[(match_operand:V4DI 1 "register_operand" "x")
- (match_operand:V4DI 2 "register_operand" "xm")
+ (match_operand:V4DI 2 "nonimmediate_operand" "xm")
(match_operand:SI 3 "const_0_to_255_operand" "n")]
UNSPEC_VPERMTI))]
"TARGET_AVX2"
@@ -12036,53 +12277,32 @@
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
-(define_expand "<avx_avx2>_maskload<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:V48_AVX2 0 "register_operand" "")
- (unspec:V48_AVX2
- [(match_operand:<sseintvecmode> 2 "register_operand" "")
- (match_operand:V48_AVX2 1 "memory_operand" "")
- (match_dup 0)]
- UNSPEC_MASKMOV))]
- "TARGET_AVX")
-
-(define_expand "<avx_avx2>_maskstore<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:V48_AVX2 0 "memory_operand" "")
+(define_insn "<avx_avx2>_maskload<ssemodesuffix><avxsizesuffix>"
+ [(set (match_operand:V48_AVX2 0 "register_operand" "=x")
(unspec:V48_AVX2
- [(match_operand:<sseintvecmode> 1 "register_operand" "")
- (match_operand:V48_AVX2 2 "register_operand" "")
- (match_dup 0)]
+ [(match_operand:<sseintvecmode> 2 "register_operand" "x")
+ (match_operand:V48_AVX2 1 "memory_operand" "m")]
UNSPEC_MASKMOV))]
- "TARGET_AVX")
-
-(define_insn "*avx2_maskmov<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:VI48_AVX2 0 "nonimmediate_operand" "=x,m")
- (unspec:VI48_AVX2
- [(match_operand:<sseintvecmode> 1 "register_operand" "x,x")
- (match_operand:VI48_AVX2 2 "nonimmediate_operand" "m,x")
- (match_dup 0)]
- UNSPEC_MASKMOV))]
- "TARGET_AVX2
- && (REG_P (operands[0]) == MEM_P (operands[2]))"
- "vpmaskmov<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ "TARGET_AVX"
+ "v<sseintprefix>maskmov<ssemodesuffix>\t{%1, %2, %0|%0, %2, %1}"
[(set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "*avx_maskmov<ssemodesuffix><avxsizesuffix>"
- [(set (match_operand:VF 0 "nonimmediate_operand" "=x,m")
- (unspec:VF
- [(match_operand:<sseintvecmode> 1 "register_operand" "x,x")
- (match_operand:VF 2 "nonimmediate_operand" "m,x")
+(define_insn "<avx_avx2>_maskstore<ssemodesuffix><avxsizesuffix>"
+ [(set (match_operand:V48_AVX2 0 "memory_operand" "=m")
+ (unspec:V48_AVX2
+ [(match_operand:<sseintvecmode> 1 "register_operand" "x")
+ (match_operand:V48_AVX2 2 "register_operand" "x")
(match_dup 0)]
UNSPEC_MASKMOV))]
- "TARGET_AVX
- && (REG_P (operands[0]) == MEM_P (operands[2]))"
- "vmaskmov<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
+ "TARGET_AVX"
+ "v<sseintprefix>maskmov<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
- (set_attr "mode" "<MODE>")])
+ (set_attr "mode" "<sseinsnmode>")])
(define_insn_and_split "avx_<castmode><avxsizesuffix>_<castmode>"
[(set (match_operand:AVX256MODE2P 0 "nonimmediate_operand" "=x,m")
@@ -12162,248 +12382,27 @@
DONE;
})
-(define_insn "avx2_ashrvv8si"
- [(set (match_operand:V8SI 0 "register_operand" "=x")
- (vec_concat:V8SI
- (vec_concat:V4SI
- (vec_concat:V2SI
- (ashiftrt:SI
- (vec_select:SI
- (match_operand:V8SI 1 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:SI
- (match_operand:V8SI 2 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)])))
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 1)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 1)]))))
- (vec_concat:V2SI
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 2)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 2)])))
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 3)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 3)])))))
- (vec_concat:V4SI
- (vec_concat:V2SI
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 0)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 0)])))
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 1)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 1)]))))
- (vec_concat:V2SI
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 2)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 2)])))
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 3)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 3)])))))))]
- "TARGET_AVX2"
- "vpsravd\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
- (set_attr "mode" "OI")])
-
-(define_insn "avx2_ashrvv4si"
- [(set (match_operand:V4SI 0 "register_operand" "=x")
- (vec_concat:V4SI
- (vec_concat:V2SI
- (ashiftrt:SI
- (vec_select:SI
- (match_operand:V4SI 1 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:SI
- (match_operand:V4SI 2 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)])))
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 1)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 1)]))))
- (vec_concat:V2SI
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 2)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 2)])))
- (ashiftrt:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 3)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 3)]))))))]
+(define_insn "avx2_ashrv<mode>"
+ [(set (match_operand:VI4_AVX2 0 "register_operand" "=x")
+ (ashiftrt:VI4_AVX2
+ (match_operand:VI4_AVX2 1 "register_operand" "x")
+ (match_operand:VI4_AVX2 2 "nonimmediate_operand" "xm")))]
"TARGET_AVX2"
"vpsravd\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
(set_attr "prefix" "vex")
- (set_attr "mode" "TI")])
-
-(define_insn "avx2_<lshift>vv8si"
- [(set (match_operand:V8SI 0 "register_operand" "=x")
- (vec_concat:V8SI
- (vec_concat:V4SI
- (vec_concat:V2SI
- (lshift:SI
- (vec_select:SI
- (match_operand:V8SI 1 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:SI
- (match_operand:V8SI 2 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)])))
- (lshift:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 1)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 1)]))))
- (vec_concat:V2SI
- (lshift:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 2)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 2)])))
- (lshift:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 3)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 3)])))))
- (vec_concat:V4SI
- (vec_concat:V2SI
- (lshift:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 0)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 0)])))
- (lshift:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 1)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 1)]))))
- (vec_concat:V2SI
- (lshift:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 2)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 2)])))
- (lshift:SI
- (vec_select:SI
- (match_dup 1)
- (parallel [(const_int 3)]))
- (vec_select:SI
- (match_dup 2)
- (parallel [(const_int 3)])))))))]
- "TARGET_AVX2"
- "vp<lshift_insn>vd\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
- (set_attr "mode" "OI")])
-
-(define_insn "avx2_<lshift>v<mode>"
- [(set (match_operand:VI4SD_AVX2 0 "register_operand" "=x")
- (vec_concat:VI4SD_AVX2
- (vec_concat:<ssehalfvecmode>
- (lshift:<ssescalarmode>
- (vec_select:<ssescalarmode>
- (match_operand:VI4SD_AVX2 1 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:<ssescalarmode>
- (match_operand:VI4SD_AVX2 2 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)])))
- (lshift:<ssescalarmode>
- (vec_select:<ssescalarmode>
- (match_dup 1)
- (parallel [(const_int 1)]))
- (vec_select:<ssescalarmode>
- (match_dup 2)
- (parallel [(const_int 1)]))))
- (vec_concat:<ssehalfvecmode>
- (lshift:<ssescalarmode>
- (vec_select:<ssescalarmode>
- (match_dup 1)
- (parallel [(const_int 2)]))
- (vec_select:<ssescalarmode>
- (match_dup 2)
- (parallel [(const_int 2)])))
- (lshift:<ssescalarmode>
- (vec_select:<ssescalarmode>
- (match_dup 1)
- (parallel [(const_int 3)]))
- (vec_select:<ssescalarmode>
- (match_dup 2)
- (parallel [(const_int 3)]))))))]
- "TARGET_AVX2"
- "vp<lshift_insn>v<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
- [(set_attr "type" "sseishft")
- (set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
-(define_insn "avx2_<lshift>vv2di"
- [(set (match_operand:V2DI 0 "register_operand" "=x")
- (vec_concat:V2DI
- (lshift:DI
- (vec_select:DI
- (match_operand:V2DI 1 "register_operand" "x")
- (parallel [(const_int 0)]))
- (vec_select:DI
- (match_operand:V2DI 2 "nonimmediate_operand" "xm")
- (parallel [(const_int 0)])))
- (lshift:DI
- (vec_select:DI
- (match_dup 1)
- (parallel [(const_int 1)]))
- (vec_select:DI
- (match_dup 2)
- (parallel [(const_int 1)])))))]
+(define_insn "avx2_<shift_insn>v<mode>"
+ [(set (match_operand:VI48_AVX2 0 "register_operand" "=x")
+ (any_lshift:VI48_AVX2
+ (match_operand:VI48_AVX2 1 "register_operand" "x")
+ (match_operand:VI48_AVX2 2 "nonimmediate_operand" "xm")))]
"TARGET_AVX2"
- "vp<lshift_insn>vq\t{%2, %1, %0|%0, %1, %2}"
+ "vp<vshift>v<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
(set_attr "prefix" "vex")
- (set_attr "mode" "TI")])
+ (set_attr "mode" "<sseinsnmode>")])
(define_insn "avx_vec_concat<mode>"
[(set (match_operand:V_256 0 "register_operand" "=x,x")
@@ -12524,55 +12523,81 @@
(V8SI "V8SI") (V8SF "V8SI")])
(define_expand "avx2_gathersi<mode>"
- [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
- (unspec:VEC_GATHER_MODE
- [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
- (match_operand:<ssescalarmode> 2 "memory_operand" "")
- (match_operand:<VEC_GATHER_MODE> 3 "register_operand" "")
- (match_operand:VEC_GATHER_MODE 4 "register_operand" "")
- (match_operand:SI 5 "const1248_operand " "")]
- UNSPEC_GATHER))]
- "TARGET_AVX2")
+ [(parallel [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
+ (unspec:VEC_GATHER_MODE
+ [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
+ (mem:<ssescalarmode>
+ (match_par_dup 7
+ [(match_operand 2 "vsib_address_operand" "")
+ (match_operand:<VEC_GATHER_MODE> 3 "register_operand" "")
+ (match_operand:SI 5 "const1248_operand " "")]))
+ (mem:BLK (scratch))
+ (match_operand:VEC_GATHER_MODE 4 "register_operand" "")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VEC_GATHER_MODE 6 ""))])]
+ "TARGET_AVX2"
+{
+ operands[7]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[3],
+ operands[5]), UNSPEC_VSIBADDR);
+})
(define_insn "*avx2_gathersi<mode>"
- [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=x")
+ [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "=&x")
(unspec:VEC_GATHER_MODE
- [(match_operand:VEC_GATHER_MODE 1 "register_operand" "0")
- (mem:<ssescalarmode>
- (match_operand:P 2 "register_operand" "r"))
- (match_operand:<VEC_GATHER_MODE> 3 "register_operand" "x")
- (match_operand:VEC_GATHER_MODE 4 "register_operand" "x")
- (match_operand:SI 5 "const1248_operand" "n")]
- UNSPEC_GATHER))]
+ [(match_operand:VEC_GATHER_MODE 2 "register_operand" "0")
+ (match_operator:<ssescalarmode> 7 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 3 "vsib_address_operand" "p")
+ (match_operand:<VEC_GATHER_MODE> 4 "register_operand" "x")
+ (match_operand:SI 6 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (mem:BLK (scratch))
+ (match_operand:VEC_GATHER_MODE 5 "register_operand" "1")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VEC_GATHER_MODE 1 "=&x"))]
"TARGET_AVX2"
- "v<gthrfirstp>gatherd<gthrlastp>\t{%4, (%2, %3, %c5), %0|%0, (%2, %3, %c5), %4}"
+ "v<sseintprefix>gatherd<ssemodesuffix>\t{%1, %7, %0|%0, %7, %1}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
(define_expand "avx2_gatherdi<mode>"
- [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
- (unspec:VEC_GATHER_MODE
- [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
- (match_operand:<ssescalarmode> 2 "memory_operand" "")
- (match_operand:<AVXMODE48P_DI> 3 "register_operand" "")
- (match_operand:VEC_GATHER_MODE 4 "register_operand" "")
- (match_operand:SI 5 "const1248_operand " "")]
- UNSPEC_GATHER))]
- "TARGET_AVX2")
+ [(parallel [(set (match_operand:VEC_GATHER_MODE 0 "register_operand" "")
+ (unspec:VEC_GATHER_MODE
+ [(match_operand:VEC_GATHER_MODE 1 "register_operand" "")
+ (mem:<ssescalarmode>
+ (match_par_dup 7
+ [(match_operand 2 "vsib_address_operand" "")
+ (match_operand:<AVXMODE48P_DI> 3 "register_operand" "")
+ (match_operand:SI 5 "const1248_operand " "")]))
+ (mem:BLK (scratch))
+ (match_operand:VEC_GATHER_MODE 4 "register_operand" "")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VEC_GATHER_MODE 6 ""))])]
+ "TARGET_AVX2"
+{
+ operands[7]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[3],
+ operands[5]), UNSPEC_VSIBADDR);
+})
(define_insn "*avx2_gatherdi<mode>"
- [(set (match_operand:AVXMODE48P_DI 0 "register_operand" "=x")
+ [(set (match_operand:AVXMODE48P_DI 0 "register_operand" "=&x")
(unspec:AVXMODE48P_DI
- [(match_operand:AVXMODE48P_DI 1 "register_operand" "0")
- (mem:<ssescalarmode>
- (match_operand:P 2 "register_operand" "r"))
- (match_operand:<AVXMODE48P_DI> 3 "register_operand" "x")
- (match_operand:AVXMODE48P_DI 4 "register_operand" "x")
- (match_operand:SI 5 "const1248_operand" "n")]
- UNSPEC_GATHER))]
+ [(match_operand:AVXMODE48P_DI 2 "register_operand" "0")
+ (match_operator:<ssescalarmode> 7 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 3 "vsib_address_operand" "p")
+ (match_operand:<AVXMODE48P_DI> 4 "register_operand" "x")
+ (match_operand:SI 6 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (mem:BLK (scratch))
+ (match_operand:AVXMODE48P_DI 5 "register_operand" "1")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:AVXMODE48P_DI 1 "=&x"))]
"TARGET_AVX2"
- "v<gthrfirstp>gatherq<gthrlastp>\t{%4, (%2, %3, %c5), %0|%0, (%2, %3, %c5), %4}"
+ "v<sseintprefix>gatherq<ssemodesuffix>\t{%1, %7, %0|%0, %7, %1}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
@@ -12580,28 +12605,41 @@
;; Special handling for VEX.256 with float arguments
;; since there're still xmms as operands
(define_expand "avx2_gatherdi<mode>256"
- [(set (match_operand:VI4F_128 0 "register_operand" "")
- (unspec:VI4F_128
- [(match_operand:VI4F_128 1 "register_operand" "")
- (match_operand:<ssescalarmode> 2 "memory_operand" "")
- (match_operand:V4DI 3 "register_operand" "")
- (match_operand:VI4F_128 4 "register_operand" "")
- (match_operand:SI 5 "const1248_operand " "")]
- UNSPEC_GATHER))]
- "TARGET_AVX2")
+ [(parallel [(set (match_operand:VI4F_128 0 "register_operand" "")
+ (unspec:VI4F_128
+ [(match_operand:VI4F_128 1 "register_operand" "")
+ (mem:<ssescalarmode>
+ (match_par_dup 7
+ [(match_operand 2 "vsib_address_operand" "")
+ (match_operand:V4DI 3 "register_operand" "")
+ (match_operand:SI 5 "const1248_operand " "")]))
+ (mem:BLK (scratch))
+ (match_operand:VI4F_128 4 "register_operand" "")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VI4F_128 6 ""))])]
+ "TARGET_AVX2"
+{
+ operands[7]
+ = gen_rtx_UNSPEC (Pmode, gen_rtvec (3, operands[2], operands[3],
+ operands[5]), UNSPEC_VSIBADDR);
+})
(define_insn "*avx2_gatherdi<mode>256"
[(set (match_operand:VI4F_128 0 "register_operand" "=x")
(unspec:VI4F_128
- [(match_operand:VI4F_128 1 "register_operand" "0")
- (mem:<ssescalarmode>
- (match_operand:P 2 "register_operand" "r"))
- (match_operand:V4DI 3 "register_operand" "x")
- (match_operand:VI4F_128 4 "register_operand" "x")
- (match_operand:SI 5 "const1248_operand" "n")]
- UNSPEC_GATHER))]
+ [(match_operand:VI4F_128 2 "register_operand" "0")
+ (match_operator:<ssescalarmode> 7 "vsib_mem_operator"
+ [(unspec:P
+ [(match_operand:P 3 "vsib_address_operand" "p")
+ (match_operand:V4DI 4 "register_operand" "x")
+ (match_operand:SI 6 "const1248_operand" "n")]
+ UNSPEC_VSIBADDR)])
+ (mem:BLK (scratch))
+ (match_operand:VI4F_128 5 "register_operand" "1")]
+ UNSPEC_GATHER))
+ (clobber (match_scratch:VI4F_128 1 "=&x"))]
"TARGET_AVX2"
- "v<gthrfirstp>gatherq<gthrlastp>\t{%4, (%2, %3, %c5), %0|%0, (%2, %3, %c5), %4}"
+ "v<sseintprefix>gatherq<ssemodesuffix>\t{%1, %7, %0|%0, %7, %1}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "vex")
(set_attr "mode" "<sseinsnmode>")])
diff --git a/gcc/config/i386/t-crtstuff b/gcc/config/i386/t-crtstuff
deleted file mode 100644
index c14dd9411ae..00000000000
--- a/gcc/config/i386/t-crtstuff
+++ /dev/null
@@ -1,7 +0,0 @@
-# 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. -fno-asynchronous-unwind-tables is off by default for i386
-# and is on by default for x86-64. We turn it off for both i386 and
-# x86-64.
-CRTSTUFF_T_CFLAGS += -fno-omit-frame-pointer -fno-asynchronous-unwind-tables
diff --git a/gcc/config/i386/t-cygming b/gcc/config/i386/t-cygming
index af2c9e41c4d..18b57c4152a 100644
--- a/gcc/config/i386/t-cygming
+++ b/gcc/config/i386/t-cygming
@@ -1,4 +1,5 @@
-# Copyright (C) 2003, 2005, 2008, 2009, 2010 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2005, 2008, 2009, 2010, 2011
+# Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,18 +17,10 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = i386/cygwin.asm
-LIB1ASMFUNCS = _chkstk _chkstk_ms
-
# cygwin and mingw always have a limits.h, but, depending upon how we are
# doing the build, it may not be installed yet.
LIMITS_H_TEST = true
-# If we are building next to winsup, this will let us find the real
-# limits.h when building libgcc2. Otherwise, winsup must be installed
-# first.
-LIBGCC2_INCLUDES = -I$(srcdir)/../winsup/w32api/include
-
winnt.o: $(srcdir)/config/i386/winnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) $(HASHTAB_H) $(GGC_H) $(LTO_STREAMER_H)
@@ -54,63 +47,3 @@ msformat-c.o: $(srcdir)/config/i386/msformat-c.c $(CONFIG_H) $(SYSTEM_H) coretyp
$(srcdir)/config/i386/msformat-c.c
STMP_FIXINC=stmp-fixinc
-
-# Build a shared libgcc library for PECOFF with a DEF file
-# with the GNU linker.
-#
-# mkmap-flat.awk is used with the pe_dll option to produce a DEF instead
-# of an ELF map file.
-#
-# Warning: If SHLIB_SOVERSION or SHLIB_SONAME are updated, LIBGCC_SONAME
-# in mingw32.h and SHLIB_MKMAP_OPTS below must be updated also.
-
-SHLIB_EXT = .dll
-SHLIB_IMPLIB = @shlib_base_name@.a
-SHLIB_SOVERSION = 1
-SHLIB_SONAME = @shlib_base_name@_$(EH_MODEL)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
-SHLIB_MAP = @shlib_map_file@
-SHLIB_OBJS = @shlib_objs@
-SHLIB_DIR = @multilib_dir@/shlib
-SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
-# SHLIB_DLLDIR is defined by including one of either t-dlldir or t-dlldir-x
-# (native/cross build respectively) in the tmake_file list in gcc/config.gcc.
-ifndef SHLIB_DLLDIR
-$(error SHLIB_DLLDIR must be defined)
-endif
-ifndef SHLIB_PTHREAD_CFLAG
-SHLIB_PTHREAD_CFLAG =
-endif
-ifndef SHLIB_PTHREAD_LDFLAG
-SHLIB_PTHREAD_LDFLAG =
-endif
-
-SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
- if [ ! -d $(SHLIB_DIR) ]; then \
- mkdir $(SHLIB_DIR); \
- else true; fi && \
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(SHLIB_PTHREAD_CFLAG) \
- -shared -nodefaultlibs \
- $(SHLIB_MAP).def \
- -Wl,--out-implib,$(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \
- -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
- $(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) && \
- if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
- mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
- $(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
- else true; fi && \
- mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \
- mv $(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp $(SHLIB_DIR)/$(SHLIB_IMPLIB)
-# $(slibdir) double quoted to protect it from expansion while building
-# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = \
- $$(mkinstalldirs) $$(DESTDIR)$$(SHLIB_DLLDIR) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
- $(INSTALL) $(SHLIB_DIR)/$(SHLIB_SONAME) \
- $$(DESTDIR)$$(SHLIB_DLLDIR)/$(SHLIB_SONAME); \
- $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_IMPLIB) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_IMPLIB)
-SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
-# We'd like to use SHLIB_SONAME here too, but shlib_base_name
-# does not get substituted before mkmap-flat.awk is run.
-SHLIB_MKMAP_OPTS = -v pe_dll=libgcc_s_$(EH_MODEL)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
-SHLIB_MAPFILES = $$(libgcc_objdir)/libgcc-std.ver
diff --git a/gcc/config/i386/t-cygwin b/gcc/config/i386/t-cygwin
deleted file mode 100644
index f5eda91c0ef..00000000000
--- a/gcc/config/i386/t-cygwin
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010
-# 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# If we are building next to winsup, this will let us find the real
-# limits.h when building libgcc2. Otherwise, winsup must be installed
-# first.
-LIBGCC2_INCLUDES += -I$(srcdir)/../winsup/include \
- -I$(srcdir)/../winsup/cygwin/include
-
-# Cygwin-specific parts of LIB_SPEC
-SHLIB_LC = -lcygwin -ladvapi32 -lshell32 -luser32 -lkernel32
-
-# We have already included one of the t-{dw2,sjlj}-eh fragments for EH_MODEL
-SHLIB_EH_EXTENSION = $(subst -dw2,,-$(EH_MODEL))
-
-# Cygwin uses different conventions than MinGW; override generic SHLIB_ def'ns here.
-SHLIB_IMPLIB = @shlib_base_name@$(SHLIB_EXT).a
-SHLIB_SONAME = cyggcc_s$(SHLIB_EH_EXTENSION)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
-# This must match the definitions of SHLIB_SONAME/SHLIB_SOVERSION and LIBGCC_SONAME.
-# We'd like to use SHLIB_SONAME here too, and we can, since
-# we don't rely on shlib_base_name substitution for it.
-SHLIB_MKMAP_OPTS = -v pe_dll=$(SHLIB_SONAME)
-
diff --git a/gcc/config/i386/t-darwin b/gcc/config/i386/t-darwin
index 22323e4abee..bf44504d4fd 100644
--- a/gcc/config/i386/t-darwin
+++ b/gcc/config/i386/t-darwin
@@ -1,5 +1,2 @@
MULTILIB_OPTIONS = m64
MULTILIB_DIRNAMES = x86_64
-LIB2_SIDITI_CONV_FUNCS=yes
-LIB2FUNCS_EXTRA = $(srcdir)/config/darwin-64.c
-LIB2FUNCS_EXCLUDE = _fixtfdi _fixunstfdi _floatditf _floatunditf
diff --git a/gcc/config/i386/t-darwin64 b/gcc/config/i386/t-darwin64
index 81b4565ac72..6a6b22f1ee5 100644
--- a/gcc/config/i386/t-darwin64
+++ b/gcc/config/i386/t-darwin64
@@ -1,8 +1,2 @@
-LIB2_SIDITI_CONV_FUNCS=yes
-LIB2FUNCS_EXTRA = $(srcdir)/config/darwin-64.c
-
MULTILIB_OPTIONS = m32
MULTILIB_DIRNAMES = i386
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/i386/t-djgpp b/gcc/config/i386/t-djgpp
deleted file mode 100644
index 7b54b7ba7aa..00000000000
--- a/gcc/config/i386/t-djgpp
+++ /dev/null
@@ -1,2 +0,0 @@
-# Location of DJGPP's header directory.
-NATIVE_SYSTEM_HEADER_DIR=$(DJDIR)/include
diff --git a/gcc/config/i386/t-dlldir b/gcc/config/i386/t-dlldir
deleted file mode 100644
index a3e03317a04..00000000000
--- a/gcc/config/i386/t-dlldir
+++ /dev/null
@@ -1,6 +0,0 @@
-
-# In a native build, target DLLs go in bindir, where they can be executed.
-# Note double quoting to prevent variables from being evaluated until install
-# time; we don't want to expand them during libgcc.mvars generation.
-
-SHLIB_DLLDIR = $$(bindir)
diff --git a/gcc/config/i386/t-dlldir-x b/gcc/config/i386/t-dlldir-x
deleted file mode 100644
index 07dd845f0a6..00000000000
--- a/gcc/config/i386/t-dlldir-x
+++ /dev/null
@@ -1,9 +0,0 @@
-
-# In a cross build, bindir contains host not target binaries, so target DLLs
-# instead go in toolexeclibdir, alongside other target binaries and static libs.
-# Note double quoting to prevent variables from being evaluated until install
-# time; we don't want to expand them during libgcc.mvars generation, and in
-# any case, $toolexeclibdir is not defined in the gcc/ subdirectory, only in
-# target lib directories.
-
-SHLIB_DLLDIR = $$(toolexeclibdir)
diff --git a/gcc/config/i386/t-gthr-win32 b/gcc/config/i386/t-gthr-win32
deleted file mode 100644
index f67fa1e25a8..00000000000
--- a/gcc/config/i386/t-gthr-win32
+++ /dev/null
@@ -1,2 +0,0 @@
-# We hide calls to w32api needed for w32 thread support here:
-LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c
diff --git a/gcc/config/i386/t-i386elf b/gcc/config/i386/t-i386elf
deleted file mode 100644
index 9560d905521..00000000000
--- a/gcc/config/i386/t-i386elf
+++ /dev/null
@@ -1,4 +0,0 @@
-# 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
diff --git a/gcc/config/i386/t-interix b/gcc/config/i386/t-interix
index e7b016f1e7a..09c9127f6af 100644
--- a/gcc/config/i386/t-interix
+++ b/gcc/config/i386/t-interix
@@ -1,6 +1,3 @@
-LIB1ASMSRC = i386/cygwin.asm
-LIB1ASMFUNCS = _chkstk _chkstk_ms
-
winnt.o: $(srcdir)/config/i386/winnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) $(HASHTAB_H) $(GGC_H)
diff --git a/gcc/config/i386/t-linux b/gcc/config/i386/t-linux
deleted file mode 100644
index 500d932fec8..00000000000
--- a/gcc/config/i386/t-linux
+++ /dev/null
@@ -1,5 +0,0 @@
-# On 64bit we do not need any exports for glibc for 64-bit libgcc_s.
-# Need to support TImode for x86. Override the settings from
-# t-slibgcc-elf-ver and t-linux
-SHLIB_MAPFILES = $$(libgcc_objdir)/libgcc-std.ver \
- $(srcdir)/config/i386/libgcc-glibc.ver
diff --git a/gcc/config/i386/t-linux64 b/gcc/config/i386/t-linux64
index ea8f5e9d7ae..b5d39855a70 100644
--- a/gcc/config/i386/t-linux64
+++ b/gcc/config/i386/t-linux64
@@ -37,10 +37,3 @@ MULTILIB_DIRNAMES = $(patsubst m%, %, $(subst /, ,$(MULTILIB_OPTIONS)))
MULTILIB_OSDIRNAMES = m64=../lib64
MULTILIB_OSDIRNAMES+= m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)
MULTILIB_OSDIRNAMES+= mx32=../libx32
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o \
- crtbeginT.o crtprec32.o crtprec64.o crtprec80.o \
- crtfastmath.o
diff --git a/gcc/config/i386/t-mingw-w32 b/gcc/config/i386/t-mingw-w32
index a1421801664..4fc8582cf5e 100644
--- a/gcc/config/i386/t-mingw-w32
+++ b/gcc/config/i386/t-mingw-w32
@@ -1,12 +1,3 @@
-# Match SYSTEM_INCLUDE_DIR
-NATIVE_SYSTEM_HEADER_DIR = /mingw/include
-
MULTILIB_OPTIONS = m64/m32
MULTILIB_DIRNAMES = 64 32
MULTILIB_OSDIRNAMES = ../lib64 ../lib
-
-# MinGW-specific parts of LIB_SPEC
-SHLIB_LC = -lmingwthrd -lmingw32 -lmingwex -lmoldname -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/i386/t-mingw-w64 b/gcc/config/i386/t-mingw-w64
index dbe2d00a2e7..c809ebd7d1d 100644
--- a/gcc/config/i386/t-mingw-w64
+++ b/gcc/config/i386/t-mingw-w64
@@ -1,12 +1,3 @@
-# Match SYSTEM_INCLUDE_DIR
-NATIVE_SYSTEM_HEADER_DIR = /mingw/include
-
MULTILIB_OPTIONS = m64/m32
MULTILIB_DIRNAMES = 64 32
MULTILIB_OSDIRNAMES = ../lib ../lib32
-
-# MinGW-specific parts of LIB_SPEC
-SHLIB_LC = -lmingwthrd -lmingw32 -lmingwex -lmoldname -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/i386/t-mingw32 b/gcc/config/i386/t-mingw32
deleted file mode 100644
index a8235242a50..00000000000
--- a/gcc/config/i386/t-mingw32
+++ /dev/null
@@ -1,5 +0,0 @@
-# Match SYSTEM_INCLUDE_DIR
-NATIVE_SYSTEM_HEADER_DIR = /mingw/include
-
-# MinGW-specific parts of LIB_SPEC
-SHLIB_LC = -lmingwthrd -lmingw32 -lmingwex -lmoldname -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32
diff --git a/gcc/config/i386/t-nto b/gcc/config/i386/t-nto
deleted file mode 100644
index b80ff802927..00000000000
--- a/gcc/config/i386/t-nto
+++ /dev/null
@@ -1,4 +0,0 @@
-CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer -fPIC
-TARGET_LIBGCC2_CFLAGS = -fPIC -fexceptions
-
-EXTRA_PARTS = crtbegin.o
diff --git a/gcc/config/i386/t-openbsd b/gcc/config/i386/t-openbsd
index 18304634000..4f8ff657a93 100644
--- a/gcc/config/i386/t-openbsd
+++ b/gcc/config/i386/t-openbsd
@@ -2,5 +2,3 @@
# We cope by building variants of libgcc.
MULTILIB_OPTIONS = fpic
MULTILIB_MATCHES=fpic=fPIC
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/ia64/crti.asm b/gcc/config/ia64/crti.asm
deleted file mode 100644
index a9d51509782..00000000000
--- a/gcc/config/ia64/crti.asm
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright (C) 2000, 2001, 2008, 2009 Free Software Foundation, Inc.
-# Written By Timothy Wall
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file just make a stack frame for the contents of the .fini and
-# .init sections. Users may put any desired instructions in those
-# sections.
-
- .section ".init"
- .align 16
- .global _init
-_init:
- .prologue 14, 33
- .save ar.pfs, r34
- alloc r34 = ar.pfs, 0, 4, 0, 0
- .vframe r35
- mov r35 = r12
- .save rp, r33
- mov r33 = b0
- .body
-
- .section ".fini"
- .align 16
- .global _fini
-_fini:
- .prologue 14, 33
- .save ar.pfs, r34
- alloc r34 = ar.pfs, 0, 4, 0, 0
- .vframe r35
- mov r35 = r12
- .save rp, r33
- mov r33 = b0
- .body
-
-# end of crti.asm
diff --git a/gcc/config/ia64/crtn.asm b/gcc/config/ia64/crtn.asm
deleted file mode 100644
index e1a18795f79..00000000000
--- a/gcc/config/ia64/crtn.asm
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2000, 2001, 2008, 2009 Free Software Foundation, Inc.
-# Written By Timothy Wall
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file just makes sure that the .fini and .init sections do in
-# fact return. Users may put any desired instructions in those sections.
-# This file is the last thing linked into any executable.
-
- .section ".init"
- ;;
- mov ar.pfs = r34
- mov b0 = r33
- .restore sp
- mov r12 = r35
- br.ret.sptk.many b0
-
- .section ".fini"
- ;;
- mov ar.pfs = r34
- mov b0 = r33
- .restore sp
- mov r12 = r35
- br.ret.sptk.many b0
-
-# end of crtn.asm
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 6d3ac6d45ee..cad6d0f156c 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -10100,11 +10100,11 @@ ia64_init_builtins (void)
if (TARGET_HPUX)
{
- if ((decl = builtin_decl_explicit (BUILT_IN_FINITE))) != NULL_TREE)
+ if ((decl = builtin_decl_explicit (BUILT_IN_FINITE)) != NULL_TREE)
set_user_assembler_name (decl, "_Isfinite");
- if ((decl = builtin_decl_explicit (BUILT_IN_FINITEF))) != NULL_TREE)
+ if ((decl = builtin_decl_explicit (BUILT_IN_FINITEF)) != NULL_TREE)
set_user_assembler_name (decl, "_Isfinitef");
- if ((decl = builtin_decl_explicit (BUILT_IN_FINITEL))) != NULL_TREE)
+ if ((decl = builtin_decl_explicit (BUILT_IN_FINITEL)) != NULL_TREE)
set_user_assembler_name (decl, "_Isfinitef128");
}
}
@@ -10716,7 +10716,7 @@ ia64_profile_hook (int labelno)
char buf[30];
const char *label_name;
ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
- label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf));
+ label_name = ggc_strdup ((*targetm.strip_name_encoding) (buf));
label = gen_rtx_SYMBOL_REF (Pmode, label_name);
SYMBOL_REF_FLAGS (label) = SYMBOL_FLAG_LOCAL;
}
diff --git a/gcc/config/ia64/t-glibc b/gcc/config/ia64/t-glibc
deleted file mode 100644
index ce18a92e275..00000000000
--- a/gcc/config/ia64/t-glibc
+++ /dev/null
@@ -1 +0,0 @@
-SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-glibc.ver
diff --git a/gcc/config/ia64/t-hpux b/gcc/config/ia64/t-hpux
index 4aa661441b2..a1b681a3a25 100644
--- a/gcc/config/ia64/t-hpux
+++ b/gcc/config/ia64/t-hpux
@@ -19,55 +19,11 @@
# We need multilib support for HPUX's ILP32 & LP64 modes.
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
MULTILIB_OPTIONS = milp32/mlp64
MULTILIB_DIRNAMES = hpux32 hpux64
MULTILIB_MATCHES =
-# On HP-UX we do not want _fixtfdi, _fixunstfdi, or _floatditf from
-# LIB1ASMSRC. These functions map the 128 bit conversion function names
-# to 80 bit conversions and were done for Linux backwards compatibility.
-
-LIB1ASMFUNCS := $(filter-out _fixtfdi _fixunstfdi _floatditf,$(LIB1ASMFUNCS))
-
-# Support routines for HP-UX 128 bit floats.
-
-LIB2FUNCS_EXTRA=quadlib.c $(srcdir)/config/floatunsitf.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 =
-
# We do not want to include the EH stuff that linux uses, we want to use
# the HP-UX libunwind library.
T_CFLAGS += -DUSE_LIBUNWIND_EXCEPTIONS
-
-SHLIB_EXT = .so
-# Must include -lunwind in the link, so that libgcc_s.so has the necessary
-# DT_NEEDED entry for libunwind.
-SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,+h,@shlib_base_name@.so.0 \
- -o @multilib_dir@/@shlib_base_name@.so @multilib_flags@ \
- @shlib_objs@ -lunwind -lc && \
- rm -f @multilib_dir@/@shlib_base_name@.so.0 && \
- $(LN_S) @shlib_base_name@.so @multilib_dir@/@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 = \
- $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@; \
- $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.so \
- $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so.0; \
- rm -f $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so; \
- $(LN_S) @shlib_base_name@.so.0 \
- $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so; \
- chmod +x $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so
-
-SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
diff --git a/gcc/config/ia64/t-ia64 b/gcc/config/ia64/t-ia64
index f130f7c09d1..398aba1019f 100644
--- a/gcc/config/ia64/t-ia64
+++ b/gcc/config/ia64/t-ia64
@@ -18,31 +18,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = ia64/lib1funcs.asm
-
-# We use different names for the DImode div/mod files so that they won't
-# conflict with libgcc2.c files. We used to use __ia64 as a prefix, now
-# we use __ as the prefix. Note that L_divdi3 in libgcc2.c actually defines
-# a TImode divide function, so there is no actual overlap here between
-# libgcc2.c and lib1funcs.asm.
-LIB1ASMFUNCS = __divxf3 __divdf3 __divsf3 \
- __divdi3 __moddi3 __udivdi3 __umoddi3 \
- __divsi3 __modsi3 __udivsi3 __umodsi3 __save_stack_nonlocal \
- __nonlocal_goto __restore_stack_nonlocal __trampoline \
- _fixtfdi _fixunstfdi _floatditf
-
-# ??? Hack to get -P option used when compiling lib1funcs.asm, because Intel
-# assembler does not accept # line number as a comment.
-# ??? This breaks C++ pragma interface/implementation, which is used in the
-# C++ part of libgcc2, hence it had to be disabled. Must find some other way
-# to support the Intel assembler.
-#LIBGCC2_DEBUG_CFLAGS = -g1 -P
-
-SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-ia64.ver
-
-# Effectively disable the crtbegin/end rules using crtstuff.c
-T = disable
-
ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) $(CPPLIB_H) $(C_COMMON_H) $(C_PRAGMA_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
diff --git a/gcc/config/ia64/t-vms b/gcc/config/ia64/t-vms
deleted file mode 100644
index 094d53483ee..00000000000
--- a/gcc/config/ia64/t-vms
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2009, 2011
-# 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Enable the crtbegin/end rules disabled in t-ia64
-T =
-
-# VMS_EXTRA_PARTS is defined in x-vms and represent object files that
-# are only needed for VMS targets, but can only be compiled on a VMS host
-# (because they need DEC C).
-EXTRA_PARTS = $(VMS_EXTRA_PARTS) crtbegin.o crtbeginS.o crtend.o crtendS.o crtinitS.o
-
-CRTSTUFF_T_CFLAGS = -O0
-CRTSTUFF_T_CFLAGS_S = -O0
-
-$(T)crtinitS.o: $(srcdir)/config/ia64/vms-crtinit.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) -I. -c -o $(T)crtinitS.o -x assembler-with-cpp \
- $(srcdir)/config/ia64/vms-crtinit.asm
-
-# Shared library macros
-shlib_version:=$(shell echo $(BASEVER_c) | sed -e 's/\./,/' -e 's/\.//g')
-SHLIB_EXT = .exe
-SHLIB_OBJS = @shlib_objs@
-SHLIB_NAME = @shlib_base_name@.exe
-SHLIB_MULTILIB =
-SHLIB_INSTALL = $(INSTALL_DATA) $(SHLIB_NAME) $$(DESTDIR)$$(libsubdir)/$(SHLIB_ NAME)
-SHLIB_LINK = \
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -nodefaultlibs \
- -shared --for-linker=/noinform -o $(SHLIB_NAME) $(SHLIB_OBJS) \
- --for-linker=$(srcdir)/config/ia64/VMS_SYMVEC_@shlib_base_name@.opt \
- --for-linker=gsmatch=equal,$(shlib_version)
-
diff --git a/gcc/config/ia64/vms_symvec_libgcc_s.opt b/gcc/config/ia64/vms_symvec_libgcc_s.opt
deleted file mode 100644
index 88b46dfda6c..00000000000
--- a/gcc/config/ia64/vms_symvec_libgcc_s.opt
+++ /dev/null
@@ -1,89 +0,0 @@
-! Symbol vector listing all the universal symbols to be exported when
-! building libgcc_s.exe shareable image on IVMS for Gcc 3.4.5.
-! It would be better to auto-generate this file.
-
-case_sensitive=yes
-SYMBOL_VECTOR=(__divdf3=PROCEDURE)
-SYMBOL_VECTOR=(__divdi3=PROCEDURE)
-SYMBOL_VECTOR=(__divsf3=PROCEDURE)
-SYMBOL_VECTOR=(__divsi3=PROCEDURE)
-SYMBOL_VECTOR=(__divxf3=PROCEDURE)
-SYMBOL_VECTOR=(__moddi3=PROCEDURE)
-SYMBOL_VECTOR=(__modsi3=PROCEDURE)
-SYMBOL_VECTOR=(__ia64_nonlocal_goto=PROCEDURE)
-SYMBOL_VECTOR=(__ia64_restore_stack_nonlocal=PROCEDURE)
-SYMBOL_VECTOR=(__ia64_save_stack_nonlocal=PROCEDURE)
-SYMBOL_VECTOR=(__ia64_trampoline=PROCEDURE)
-SYMBOL_VECTOR=(__udivdi3=PROCEDURE)
-SYMBOL_VECTOR=(__udivsi3=PROCEDURE)
-SYMBOL_VECTOR=(__umoddi3=PROCEDURE)
-SYMBOL_VECTOR=(__umodsi3=PROCEDURE)
-SYMBOL_VECTOR=(__absvti2=PROCEDURE)
-SYMBOL_VECTOR=(__absvdi2=PROCEDURE)
-SYMBOL_VECTOR=(__absvsi2=PROCEDURE)
-SYMBOL_VECTOR=(__addvti3=PROCEDURE)
-SYMBOL_VECTOR=(__addvdi3=PROCEDURE)
-SYMBOL_VECTOR=(__addvsi3=PROCEDURE)
-SYMBOL_VECTOR=(__ashlti3=PROCEDURE)
-SYMBOL_VECTOR=(__ashrti3=PROCEDURE)
-SYMBOL_VECTOR=(__clear_cache=PROCEDURE)
-SYMBOL_VECTOR=(__clzti2=PROCEDURE)
-SYMBOL_VECTOR=(__clzdi2=PROCEDURE)
-SYMBOL_VECTOR=(__cmpti2=PROCEDURE)
-SYMBOL_VECTOR=(__ctzti2=PROCEDURE)
-SYMBOL_VECTOR=(__ctzdi2=PROCEDURE)
-SYMBOL_VECTOR=(__divti3=PROCEDURE)
-SYMBOL_VECTOR=(__enable_execute_stack=PROCEDURE)
-SYMBOL_VECTOR=(__ffsti2=PROCEDURE)
-SYMBOL_VECTOR=(__ffsdi2=PROCEDURE)
-SYMBOL_VECTOR=(__fixdfti=PROCEDURE)
-SYMBOL_VECTOR=(__fixsfti=PROCEDURE)
-SYMBOL_VECTOR=(__fixunsdfti=PROCEDURE)
-SYMBOL_VECTOR=(__fixunsdfdi=PROCEDURE)
-SYMBOL_VECTOR=(__fixunssfti=PROCEDURE)
-SYMBOL_VECTOR=(__fixunssfdi=PROCEDURE)
-SYMBOL_VECTOR=(__floattidf=PROCEDURE)
-SYMBOL_VECTOR=(__floattisf=PROCEDURE)
-SYMBOL_VECTOR=(__lshrti3=PROCEDURE)
-SYMBOL_VECTOR=(__modti3=PROCEDURE)
-SYMBOL_VECTOR=(__multi3=PROCEDURE)
-SYMBOL_VECTOR=(__mulvti3=PROCEDURE)
-SYMBOL_VECTOR=(__mulvdi3=PROCEDURE)
-SYMBOL_VECTOR=(__mulvsi3=PROCEDURE)
-SYMBOL_VECTOR=(__negti2=PROCEDURE)
-SYMBOL_VECTOR=(__negvti2=PROCEDURE)
-SYMBOL_VECTOR=(__negvdi2=PROCEDURE)
-SYMBOL_VECTOR=(__negvsi2=PROCEDURE)
-SYMBOL_VECTOR=(__parityti2=PROCEDURE)
-SYMBOL_VECTOR=(__paritydi2=PROCEDURE)
-SYMBOL_VECTOR=(__popcountti2=PROCEDURE)
-SYMBOL_VECTOR=(__popcountdi2=PROCEDURE)
-SYMBOL_VECTOR=(__subvti3=PROCEDURE)
-SYMBOL_VECTOR=(__subvdi3=PROCEDURE)
-SYMBOL_VECTOR=(__subvsi3=PROCEDURE)
-SYMBOL_VECTOR=(__ucmpti2=PROCEDURE)
-SYMBOL_VECTOR=(__udiv_w_sdiv=PROCEDURE)
-SYMBOL_VECTOR=(__udivti3=PROCEDURE)
-SYMBOL_VECTOR=(__udivmodti4=PROCEDURE)
-SYMBOL_VECTOR=(__umodti3=PROCEDURE)
-SYMBOL_VECTOR=(__gthread_active_p=PROCEDURE)
-SYMBOL_VECTOR=(__gthread_mutex_lock=PROCEDURE)
-SYMBOL_VECTOR=(__gthread_mutex_unlock=PROCEDURE)
-SYMBOL_VECTOR=(__gcc_personality_v0=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_GetGR=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_SetGR=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_GetIP=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_GetIPInfo=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_SetIP=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_GetLanguageSpecificData=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_GetRegionStart=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_FindEnclosingFunction=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_GetCFA=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_GetBSP=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_RaiseException=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_ForcedUnwind=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_Resume=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_Resume_or_Rethrow=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_DeleteException=PROCEDURE)
-SYMBOL_VECTOR=(_Unwind_Backtrace=PROCEDURE)
-case_sensitive=NO
diff --git a/gcc/config/iq2000/t-iq2000 b/gcc/config/iq2000/t-iq2000
deleted file mode 100644
index 03d8c703f86..00000000000
--- a/gcc/config/iq2000/t-iq2000
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2003, 2010, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Suppress building libgcc1.a, since the MIPS compiler port is complete
-# and does not need anything from libgcc1.a.
-LIBGCC1 =
-CROSS_LIBGCC1 =
-
-LIB2FUNCS_EXTRA = $(srcdir)/config/udivmod.c $(srcdir)/config/divmod.c $(srcdir)/config/udivmodsi4.c $(srcdir)/config/iq2000/lib2extra-funcs.c
-
-# 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 =
-# MULTILIB_DIRNAMES =
-# MULTILIB_MATCHES =
-# MULTILIB_EXCEPTIONS =
-# MULTILIB_EXTRA_OPTS =
-#
-# LIBGCC = stmp-multilib
-# INSTALL_LIBGCC = install-multilib
-
diff --git a/gcc/config/m32c/m32c-lib2-trapv.c b/gcc/config/m32c/m32c-lib2-trapv.c
deleted file mode 100644
index bb61ceaf0f4..00000000000
--- a/gcc/config/m32c/m32c-lib2-trapv.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* 16-bit trapping arithmetic routines for R8C/M16C/M32C
- Copyright (C) 2009
- Free Software Foundation, Inc.
- Contributed by Red Hat.
-
- 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 3, 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.
-
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
-
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
-
-/* See the comment by the definition of LIBGCC2_UNITS_PER_WORD in
- m32c.h for why we are creating extra versions of some of the
- functions defined in libgcc2.c.
-
- Note - this file is separate from m32c-lib2.c so that the following
- functions will appear in the their object file. This is necessary
- because they call abort() which is defined in the C library whereas
- the functions in m32c-lib2.c are completely self sufficieent. */
-
-#define LIBGCC2_UNITS_PER_WORD 2
-
-#define L_mulvsi3
-#define L_negvsi2
-#define L_addvsi3
-#define L_subvsi3
-
-#include "libgcc2.c"
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 7040df69fcf..04f69050609 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -391,7 +391,7 @@ class_can_hold_mode (reg_class_t rclass, enum machine_mode mode)
we allow the user to limit the number of memregs available, in
order to try to persuade gcc to try harder to use real registers.
- Memregs are provided by m32c-lib1.S.
+ Memregs are provided by lib1funcs.S.
*/
int ok_to_change_target_memregs = TRUE;
diff --git a/gcc/config/m32c/t-m32c b/gcc/config/m32c/t-m32c
index e39fdf3a0aa..1e4ed6b7113 100644
--- a/gcc/config/m32c/t-m32c
+++ b/gcc/config/m32c/t-m32c
@@ -19,18 +19,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = m32c/m32c-lib1.S
-
-LIB1ASMFUNCS = \
- __m32c_memregs \
- __m32c_eh_return \
- __m32c_mulsi3 \
- __m32c_cmpsi2 \
- __m32c_ucmpsi2 \
- __m32c_jsri16
-
-LIB2FUNCS_EXTRA = $(srcdir)/config/m32c/m32c-lib2.c $(srcdir)/config/m32c/m32c-lib2-trapv.c
-
# target-specific files
md_file = md
@@ -53,5 +41,3 @@ m32c-pragma.o: $(srcdir)/config/m32c/m32c-pragma.c $(RTL_H) $(TREE_H) $(CONFIG_H
MULTILIB_OPTIONS = mcpu=m32cm
MULTILIB_DIRNAMES = m32cm
MULTILIB_MATCHES = mcpu?m32cm=mcpu?m32c mcpu?r8c=mcpu?m16c
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
diff --git a/gcc/config/m32r/initfini.c b/gcc/config/m32r/initfini.c
deleted file mode 100644
index 6e7d58614c7..00000000000
--- a/gcc/config/m32r/initfini.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/* .init/.fini section handling + C++ global constructor/destructor handling.
- This file is based on crtstuff.c, sol2-crti.asm, sol2-crtn.asm.
-
- Copyright (C) 1996, 1997, 1998, 2006, 2009 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 3, 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.
-
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
-
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
-
-/* Declare a pointer to void function type. */
-typedef void (*func_ptr) (void);
-
-#ifdef CRT_INIT
-
-/* NOTE: In order to be able to support SVR4 shared libraries, we arrange
- to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
- __DTOR_END__ } per root executable and also one set of these symbols
- per shared library. So in any given whole process image, we may have
- multiple definitions of each of these symbols. In order to prevent
- these definitions from conflicting with one another, and in order to
- ensure that the proper lists are used for the initialization/finalization
- of each individual shared library (respectively), we give these symbols
- only internal (i.e. `static') linkage, and we also make it a point to
- refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__
- symbol in crtinit.o, where they are defined. */
-
-static func_ptr __CTOR_LIST__[1]
- __attribute__ ((used, section (".ctors")))
- = { (func_ptr) (-1) };
-
-static func_ptr __DTOR_LIST__[1]
- __attribute__ ((used, section (".dtors")))
- = { (func_ptr) (-1) };
-
-/* Run all the global destructors on exit from the program. */
-
-/* Some systems place the number of pointers in the first word of the
- table. On SVR4 however, that word is -1. In all cases, the table is
- null-terminated. On SVR4, we start from the beginning of the list and
- invoke each per-compilation-unit destructor routine in order
- until we find that null.
-
- Note that this function MUST be static. There will be one of these
- functions in each root executable and one in each shared library, but
- although they all have the same code, each one is unique in that it
- refers to one particular associated `__DTOR_LIST__' which belongs to the
- same particular root executable or shared library file. */
-
-static void __do_global_dtors (void)
-asm ("__do_global_dtors") __attribute__ ((used, section (".text")));
-
-static void
-__do_global_dtors (void)
-{
- func_ptr *p;
-
- for (p = __DTOR_LIST__ + 1; *p; p++)
- (*p) ();
-}
-
-/* .init section start.
- This must appear at the start of the .init section. */
-
-asm ("\n\
- .section .init,\"ax\",@progbits\n\
- .balign 4\n\
- .global __init\n\
-__init:\n\
- push fp\n\
- push lr\n\
- mv fp,sp\n\
- seth r0, #shigh(__fini)\n\
- add3 r0, r0, #low(__fini)\n\
- bl atexit\n\
- .fillinsn\n\
-");
-
-/* .fini section start.
- This must appear at the start of the .init section. */
-
-asm ("\n\
- .section .fini,\"ax\",@progbits\n\
- .balign 4\n\
- .global __fini\n\
-__fini:\n\
- push fp\n\
- push lr\n\
- mv fp,sp\n\
- bl __do_global_dtors\n\
- .fillinsn\n\
-");
-
-#endif /* CRT_INIT */
-
-#ifdef CRT_FINI
-
-/* Put a word containing zero at the end of each of our two lists of function
- addresses. Note that the words defined here go into the .ctors and .dtors
- sections of the crtend.o file, and since that file is always linked in
- last, these words naturally end up at the very ends of the two lists
- contained in these two sections. */
-
-static func_ptr __CTOR_END__[1]
- __attribute__ ((used, section (".ctors")))
- = { (func_ptr) 0 };
-
-static func_ptr __DTOR_END__[1]
- __attribute__ ((used, section (".dtors")))
- = { (func_ptr) 0 };
-
-/* Run all global constructors for the program.
- Note that they are run in reverse order. */
-
-static void __do_global_ctors (void)
-asm ("__do_global_ctors") __attribute__ ((used, section (".text")));
-
-static void
-__do_global_ctors (void)
-{
- func_ptr *p;
-
- for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
- (*p) ();
-}
-
-/* .init section end.
- This must live at the end of the .init section. */
-
-asm ("\n\
- .section .init,\"ax\",@progbits\n\
- bl __do_global_ctors\n\
- mv sp,fp\n\
- pop lr\n\
- pop fp\n\
- jmp lr\n\
- .fillinsn\n\
-");
-
-/* .fini section end.
- This must live at the end of the .fini section. */
-
-asm ("\n\
- .section .fini,\"ax\",@progbits\n\
- mv sp,fp\n\
- pop lr\n\
- pop fp\n\
- jmp lr\n\
- .fillinsn\n\
-");
-
-#endif /* CRT_FINI */
diff --git a/gcc/config/m32r/t-linux b/gcc/config/m32r/t-linux
index 6de9c781a67..c4f7dcc0bd6 100644
--- a/gcc/config/m32r/t-linux
+++ b/gcc/config/m32r/t-linux
@@ -16,30 +16,5 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# lib1funcs.asm is currently empty.
-CROSS_LIBGCC1 =
-
-# Turn off the SDA while compiling libgcc2. There are no headers for it
-# and we want maximal upward compatibility here.
-
-TARGET_LIBGCC2_CFLAGS = -G 0 -fPIC
-
-# We need to use -fpic when we are using gcc to compile the routines in
-# initfini.c. This is only really needed when we are going to use gcc/g++
-# to produce a shared library, but since we don't know ahead of time when
-# we will be doing that, we just always use -fpic when compiling the
-# routines in initfini.c.
-# -fpic currently isn't supported for the m32r.
-
-CRTSTUFF_T_CFLAGS_S = -fPIC
-
# Don't install "assert.h" in gcc. We use the one in glibc.
INSTALL_ASSERT_H =
-
-# Do not build libgcc1. Let gcc generate those functions. The GNU/Linux
-# C library can handle them.
-LIBGCC1 =
-CROSS_LIBGCC1 =
-LIBGCC1_TEST =
-
-SHLIB_MAPFILES += $(srcdir)/config/m32r/libgcc-glibc.ver
diff --git a/gcc/config/m32r/t-m32r b/gcc/config/m32r/t-m32r
index 44090658838..e048fbf04f2 100644
--- a/gcc/config/m32r/t-m32r
+++ b/gcc/config/m32r/t-m32r
@@ -17,40 +17,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Turn off the SDA while compiling libgcc2. There are no headers for it
-# and we want maximal upward compatibility here.
-
-TARGET_LIBGCC2_CFLAGS = -G 0
-
-# We need to use -fpic when we are using gcc to compile the routines in
-# initfini.c. This is only really needed when we are going to use gcc/g++
-# to produce a shared library, but since we don't know ahead of time when
-# we will be doing that, we just always use -fpic when compiling the
-# routines in initfini.c.
-# -fpic currently isn't supported for the m32r.
-
-CRTSTUFF_T_CFLAGS =
-
-# .init/.fini section routines
-
-$(T)crtinit.o: $(srcdir)/config/m32r/initfini.c $(GCC_PASSES) $(CONFIG_H)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) \
- $(CRTSTUFF_T_CFLAGS) $(INCLUDES) -DCRT_INIT \
- -finhibit-size-directive -fno-inline-functions -g0 \
- -mmodel=medium -c $(srcdir)/config/m32r/initfini.c \
- -o $(T)crtinit.o
-
-$(T)crtfini.o: $(srcdir)/config/m32r/initfini.c $(GCC_PASSES) $(CONFIG_H)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) \
- $(CRTSTUFF_T_CFLAGS) $(INCLUDES) -DCRT_FINI \
- -finhibit-size-directive -fno-inline-functions -g0 \
- -mmodel=medium -c $(srcdir)/config/m32r/initfini.c \
- -o $(T)crtfini.o
-m32rx:
- mkdir $@
-m32r2:
- mkdir $@
-
# -mmodel={small,medium} requires separate libraries.
# We don't build libraries for the large model, instead we use the medium
# libraries. The only difference is that the large model can handle jumps
@@ -64,8 +30,3 @@ MULTILIB_MATCHES = mmodel?medium=mmodel?large
# SHN_M32R_SCOMMON.
# This is important for objects referenced in system header files.
MULTILIB_EXTRA_OPTS = msdata=sdata
-
-EXTRA_MULTILIB_PARTS = crtinit.o crtfini.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/m68k/fpgnulib.c b/gcc/config/m68k/fpgnulib.c
deleted file mode 100644
index 2a7f6c75d11..00000000000
--- a/gcc/config/m68k/fpgnulib.c
+++ /dev/null
@@ -1,595 +0,0 @@
-/* This is a stripped down version of floatlib.c. It supplies only those
- functions which exist in libgcc, but for which there is not assembly
- language versions in m68k/lb1sf68.asm.
-
- It also includes simplistic support for extended floats (by working in
- double precision). You must compile this file again with -DEXTFLOAT
- to get this support. */
-
-/*
-** gnulib support for software floating point.
-** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved.
-** Permission is granted to do *anything* you want with this file,
-** commercial or otherwise, provided this message remains intact. So there!
-** I would appreciate receiving any updates/patches/changes that anyone
-** makes, and am willing to be the repository for said changes (am I
-** making a big mistake?).
-**
-** Pat Wood
-** Pipeline Associates, Inc.
-** pipeline!phw@motown.com or
-** sun!pipeline!phw or
-** uunet!motown!pipeline!phw
-**
-** 05/01/91 -- V1.0 -- first release to gcc mailing lists
-** 05/04/91 -- V1.1 -- added float and double prototypes and return values
-** -- fixed problems with adding and subtracting zero
-** -- fixed rounding in truncdfsf2
-** -- fixed SWAP define and tested on 386
-*/
-
-/*
-** The following are routines that replace the gnulib soft floating point
-** routines that are called automatically when -msoft-float is selected.
-** The support single and double precision IEEE format, with provisions
-** for byte-swapped machines (tested on 386). Some of the double-precision
-** routines work at full precision, but most of the hard ones simply punt
-** and call the single precision routines, producing a loss of accuracy.
-** long long support is not assumed or included.
-** Overall accuracy is close to IEEE (actually 68882) for single-precision
-** arithmetic. I think there may still be a 1 in 1000 chance of a bit
-** being rounded the wrong way during a multiply. I'm not fussy enough to
-** bother with it, but if anyone is, knock yourself out.
-**
-** Efficiency has only been addressed where it was obvious that something
-** would make a big difference. Anyone who wants to do this right for
-** best speed should go in and rewrite in assembler.
-**
-** I have tested this only on a 68030 workstation and 386/ix integrated
-** in with -msoft-float.
-*/
-
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126L
-#define SIGNBIT 0x80000000L
-#define HIDDEN (1L << 23L)
-#define SIGN(fp) ((fp) & SIGNBIT)
-#define EXP(fp) (((fp) >> 23L) & 0xFF)
-#define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23L) | (m))
-
-/* the following deal with IEEE double-precision numbers */
-#define EXCESSD 1022L
-#define HIDDEND (1L << 20L)
-#define EXPDBITS 11
-#define EXPDMASK 0x7FFL
-#define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL)
-#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
-#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
- (fp.l.lower >> 22))
-#define MANTDMASK 0xFFFFFL /* mask of upper part */
-
-/* the following deal with IEEE extended-precision numbers */
-#define EXCESSX 16382L
-#define HIDDENX (1L << 31L)
-#define EXPXBITS 15
-#define EXPXMASK 0x7FFF
-#define EXPX(fp) (((fp.l.upper) >> 16) & EXPXMASK)
-#define SIGNX(fp) ((fp.l.upper) & SIGNBIT)
-#define MANTXMASK 0x7FFFFFFFL /* mask of upper part */
-
-union double_long
-{
- double d;
- struct {
- long upper;
- unsigned long lower;
- } l;
-};
-
-union float_long {
- float f;
- long l;
-};
-
-union long_double_long
-{
- long double ld;
- struct
- {
- long upper;
- unsigned long middle;
- unsigned long lower;
- } l;
-};
-
-#ifndef EXTFLOAT
-
-int
-__unordsf2(float a, float b)
-{
- union float_long fl;
-
- fl.f = a;
- if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0)
- return 1;
- fl.f = b;
- if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0)
- return 1;
- return 0;
-}
-
-int
-__unorddf2(double a, double b)
-{
- union double_long dl;
-
- dl.d = a;
- if (EXPD(dl) == EXPDMASK
- && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0))
- return 1;
- dl.d = b;
- if (EXPD(dl) == EXPDMASK
- && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0))
- return 1;
- return 0;
-}
-
-/* convert unsigned int to double */
-double
-__floatunsidf (unsigned long a1)
-{
- long exp = 32 + EXCESSD;
- union double_long dl;
-
- if (!a1)
- {
- dl.l.upper = dl.l.lower = 0;
- return dl.d;
- }
-
- while (a1 < 0x2000000L)
- {
- a1 <<= 4;
- exp -= 4;
- }
-
- while (a1 < 0x80000000L)
- {
- a1 <<= 1;
- exp--;
- }
-
- /* pack up and go home */
- dl.l.upper = exp << 20L;
- dl.l.upper |= (a1 >> 11L) & ~HIDDEND;
- dl.l.lower = a1 << 21L;
-
- return dl.d;
-}
-
-/* convert int to double */
-double
-__floatsidf (long a1)
-{
- long sign = 0, exp = 31 + EXCESSD;
- union double_long dl;
-
- if (!a1)
- {
- dl.l.upper = dl.l.lower = 0;
- return dl.d;
- }
-
- if (a1 < 0)
- {
- sign = SIGNBIT;
- a1 = (long)-(unsigned long)a1;
- if (a1 < 0)
- {
- dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L);
- dl.l.lower = 0;
- return dl.d;
- }
- }
-
- while (a1 < 0x1000000L)
- {
- a1 <<= 4;
- exp -= 4;
- }
-
- while (a1 < 0x40000000L)
- {
- a1 <<= 1;
- exp--;
- }
-
- /* pack up and go home */
- dl.l.upper = sign;
- dl.l.upper |= exp << 20L;
- dl.l.upper |= (a1 >> 10L) & ~HIDDEND;
- dl.l.lower = a1 << 22L;
-
- return dl.d;
-}
-
-/* convert unsigned int to float */
-float
-__floatunsisf (unsigned long l)
-{
- double foo = __floatunsidf (l);
- return foo;
-}
-
-/* convert int to float */
-float
-__floatsisf (long l)
-{
- double foo = __floatsidf (l);
- return foo;
-}
-
-/* convert float to double */
-double
-__extendsfdf2 (float a1)
-{
- register union float_long fl1;
- register union double_long dl;
- register long exp;
- register long mant;
-
- fl1.f = a1;
-
- dl.l.upper = SIGN (fl1.l);
- if ((fl1.l & ~SIGNBIT) == 0)
- {
- dl.l.lower = 0;
- return dl.d;
- }
-
- exp = EXP(fl1.l);
- mant = MANT (fl1.l) & ~HIDDEN;
- if (exp == 0)
- {
- /* Denormal. */
- exp = 1;
- while (!(mant & HIDDEN))
- {
- mant <<= 1;
- exp--;
- }
- mant &= ~HIDDEN;
- }
- exp = exp - EXCESS + EXCESSD;
- dl.l.upper |= exp << 20;
- dl.l.upper |= mant >> 3;
- dl.l.lower = mant << 29;
-
- return dl.d;
-}
-
-/* convert double to float */
-float
-__truncdfsf2 (double a1)
-{
- register long exp;
- register long mant;
- register union float_long fl;
- register union double_long dl1;
- int sticky;
- int shift;
-
- dl1.d = a1;
-
- if ((dl1.l.upper & ~SIGNBIT) == 0 && !dl1.l.lower)
- {
- fl.l = SIGND(dl1);
- return fl.f;
- }
-
- exp = EXPD (dl1) - EXCESSD + EXCESS;
-
- sticky = dl1.l.lower & ((1 << 22) - 1);
- mant = MANTD (dl1);
- /* shift double mantissa 6 bits so we can round */
- sticky |= mant & ((1 << 6) - 1);
- mant >>= 6;
-
- /* Check for underflow and denormals. */
- if (exp <= 0)
- {
- if (exp < -24)
- {
- sticky |= mant;
- mant = 0;
- }
- else
- {
- sticky |= mant & ((1 << (1 - exp)) - 1);
- mant >>= 1 - exp;
- }
- exp = 0;
- }
-
- /* now round */
- shift = 1;
- if ((mant & 1) && (sticky || (mant & 2)))
- {
- int rounding = exp ? 2 : 1;
-
- mant += 1;
-
- /* did the round overflow? */
- if (mant >= (HIDDEN << rounding))
- {
- exp++;
- shift = rounding;
- }
- }
- /* shift down */
- mant >>= shift;
-
- mant &= ~HIDDEN;
-
- /* pack up and go home */
- fl.l = PACK (SIGND (dl1), exp, mant);
- return (fl.f);
-}
-
-/* convert double to int */
-long
-__fixdfsi (double a1)
-{
- register union double_long dl1;
- register long exp;
- register long l;
-
- dl1.d = a1;
-
- if (!dl1.l.upper && !dl1.l.lower)
- return 0;
-
- exp = EXPD (dl1) - EXCESSD - 31;
- l = MANTD (dl1);
-
- if (exp > 0)
- {
- /* Return largest integer. */
- return SIGND (dl1) ? 0x80000000L : 0x7fffffffL;
- }
-
- if (exp <= -32)
- return 0;
-
- /* shift down until exp = 0 */
- if (exp < 0)
- l >>= -exp;
-
- return (SIGND (dl1) ? -l : l);
-}
-
-/* convert float to int */
-long
-__fixsfsi (float a1)
-{
- double foo = a1;
- return __fixdfsi (foo);
-}
-
-#else /* EXTFLOAT */
-
-/* We do not need these routines for coldfire, as it has no extended
- float format. */
-#if !defined (__mcoldfire__)
-
-/* Primitive extended precision floating point support.
-
- We assume all numbers are normalized, don't do any rounding, etc. */
-
-/* Prototypes for the above in case we use them. */
-double __floatunsidf (unsigned long);
-double __floatsidf (long);
-float __floatsisf (long);
-double __extendsfdf2 (float);
-float __truncdfsf2 (double);
-long __fixdfsi (double);
-long __fixsfsi (float);
-
-int
-__unordxf2(long double a, long double b)
-{
- union long_double_long ldl;
-
- ldl.ld = a;
- if (EXPX(ldl) == EXPXMASK
- && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0))
- return 1;
- ldl.ld = b;
- if (EXPX(ldl) == EXPXMASK
- && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0))
- return 1;
- return 0;
-}
-
-/* convert double to long double */
-long double
-__extenddfxf2 (double d)
-{
- register union double_long dl;
- register union long_double_long ldl;
- register long exp;
-
- dl.d = d;
- /*printf ("dfxf in: %g\n", d);*/
-
- ldl.l.upper = SIGND (dl);
- if ((dl.l.upper & ~SIGNBIT) == 0 && !dl.l.lower)
- {
- ldl.l.middle = 0;
- ldl.l.lower = 0;
- return ldl.ld;
- }
-
- exp = EXPD (dl) - EXCESSD + EXCESSX;
- ldl.l.upper |= exp << 16;
- ldl.l.middle = HIDDENX;
- /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
- ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
- /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
- ldl.l.middle |= dl.l.lower >> (1 + 20);
- /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
- ldl.l.lower = dl.l.lower << (32 - 21);
-
- /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/
- return ldl.ld;
-}
-
-/* convert long double to double */
-double
-__truncxfdf2 (long double ld)
-{
- register long exp;
- register union double_long dl;
- register union long_double_long ldl;
-
- ldl.ld = ld;
- /*printf ("xfdf in: %s\n", dumpxf (ld));*/
-
- dl.l.upper = SIGNX (ldl);
- if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower)
- {
- dl.l.lower = 0;
- return dl.d;
- }
-
- exp = EXPX (ldl) - EXCESSX + EXCESSD;
- /* ??? quick and dirty: keep `exp' sane */
- if (exp >= EXPDMASK)
- exp = EXPDMASK - 1;
- dl.l.upper |= exp << (32 - (EXPDBITS + 1));
- /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
- dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
- dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
- dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
-
- /*printf ("xfdf out: %g\n", dl.d);*/
- return dl.d;
-}
-
-/* convert a float to a long double */
-long double
-__extendsfxf2 (float f)
-{
- long double foo = __extenddfxf2 (__extendsfdf2 (f));
- return foo;
-}
-
-/* convert a long double to a float */
-float
-__truncxfsf2 (long double ld)
-{
- float foo = __truncdfsf2 (__truncxfdf2 (ld));
- return foo;
-}
-
-/* convert an int to a long double */
-long double
-__floatsixf (long l)
-{
- double foo = __floatsidf (l);
- return foo;
-}
-
-/* convert an unsigned int to a long double */
-long double
-__floatunsixf (unsigned long l)
-{
- double foo = __floatunsidf (l);
- return foo;
-}
-
-/* convert a long double to an int */
-long
-__fixxfsi (long double ld)
-{
- long foo = __fixdfsi ((double) ld);
- return foo;
-}
-
-/* The remaining provide crude math support by working in double precision. */
-
-long double
-__addxf3 (long double x1, long double x2)
-{
- return (double) x1 + (double) x2;
-}
-
-long double
-__subxf3 (long double x1, long double x2)
-{
- return (double) x1 - (double) x2;
-}
-
-long double
-__mulxf3 (long double x1, long double x2)
-{
- return (double) x1 * (double) x2;
-}
-
-long double
-__divxf3 (long double x1, long double x2)
-{
- return (double) x1 / (double) x2;
-}
-
-long double
-__negxf2 (long double x1)
-{
- return - (double) x1;
-}
-
-long
-__cmpxf2 (long double x1, long double x2)
-{
- return __cmpdf2 ((double) x1, (double) x2);
-}
-
-long
-__eqxf2 (long double x1, long double x2)
-{
- return __cmpdf2 ((double) x1, (double) x2);
-}
-
-long
-__nexf2 (long double x1, long double x2)
-{
- return __cmpdf2 ((double) x1, (double) x2);
-}
-
-long
-__ltxf2 (long double x1, long double x2)
-{
- return __cmpdf2 ((double) x1, (double) x2);
-}
-
-long
-__lexf2 (long double x1, long double x2)
-{
- return __cmpdf2 ((double) x1, (double) x2);
-}
-
-long
-__gtxf2 (long double x1, long double x2)
-{
- return __cmpdf2 ((double) x1, (double) x2);
-}
-
-long
-__gexf2 (long double x1, long double x2)
-{
- return __cmpdf2 ((double) x1, (double) x2);
-}
-
-#endif /* !__mcoldfire__ */
-#endif /* EXTFLOAT */
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index e447708d239..51a04ed9c15 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -4206,7 +4206,8 @@ notice_update_cc (rtx exp, rtx insn)
&& GET_MODE_CLASS (GET_MODE (XEXP (cc_status.value2, 0))) == MODE_FLOAT)
{
cc_status.flags = CC_IN_68881;
- if (!FP_REG_P (XEXP (cc_status.value2, 0)))
+ if (!FP_REG_P (XEXP (cc_status.value2, 0))
+ && FP_REG_P (XEXP (cc_status.value2, 1)))
cc_status.flags |= CC_REVERSED;
}
}
diff --git a/gcc/config/m68k/t-crtstuff b/gcc/config/m68k/t-crtstuff
deleted file mode 100644
index a8bdb502d66..00000000000
--- a/gcc/config/m68k/t-crtstuff
+++ /dev/null
@@ -1,10 +0,0 @@
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crti.o crtn.o
-
-# Add flags here as required.
-CRTSTUFF_T_CFLAGS =
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/m68k/crti.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o $(srcdir)/config/m68k/crti.s
-$(T)crtn.o: $(srcdir)/config/m68k/crtn.s $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o $(srcdir)/config/m68k/crtn.s
diff --git a/gcc/config/m68k/t-floatlib b/gcc/config/m68k/t-floatlib
deleted file mode 100644
index 2039d1d0dc4..00000000000
--- a/gcc/config/m68k/t-floatlib
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2007 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMSRC = m68k/lb1sf68.asm
-LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
- _double _float _floatex \
- _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
- _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
-
-LIB2FUNCS_EXTRA = fpgnulib.c xfgnulib.c
-
-fpgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
- cp $(srcdir)/config/m68k/fpgnulib.c fpgnulib.c
-xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
- echo '#define EXTFLOAT' > xfgnulib.c
- cat $(srcdir)/config/m68k/fpgnulib.c >> xfgnulib.c
diff --git a/gcc/config/m68k/t-linux b/gcc/config/m68k/t-linux
index 17f0c6f5987..3fa29474693 100644
--- a/gcc/config/m68k/t-linux
+++ b/gcc/config/m68k/t-linux
@@ -1,4 +1,4 @@
-# Copyright (C) 2008, 2010 Free Software Foundation, Inc.
+# Copyright (C) 2008, 2010, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,10 +16,8 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
-
-# Only include multilibs for 680x0 CPUs with an MMU.
-M68K_MLIB_CPU += && (CPU ~ "^m680") && (FLAGS ~ "FL_MMU")
+# Only include multilibs for 680x0 and ColdFire CPUs with an MMU.
+M68K_MLIB_CPU += && ((CPU ~ "^m680") || (CPU ~ "^mcf")) && (FLAGS ~ "FL_MMU")
# This rule uses MULTILIB_MATCHES to generate a definition of
# SYSROOT_SUFFIX_SPEC.
diff --git a/gcc/config/m68k/t-m68kelf b/gcc/config/m68k/t-m68kelf
deleted file mode 100644
index bea01dc4f49..00000000000
--- a/gcc/config/m68k/t-m68kelf
+++ /dev/null
@@ -1,4 +0,0 @@
-# from ../t-svr4
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o
-# no pic for now
-#CRTSTUFF_T_CFLAGS=-fpic
diff --git a/gcc/config/m68k/t-mlibs b/gcc/config/m68k/t-mlibs
index 11df31f210e..7be0c9f4fd4 100644
--- a/gcc/config/m68k/t-mlibs
+++ b/gcc/config/m68k/t-mlibs
@@ -92,6 +92,3 @@ endif
# Remove the default CPU from the explicit exceptions.
MULTILIB_EXCEPTIONS := \
$(patsubst mcpu=$(M68K_MLIB_DEFAULT)/%,%,$(MULTILIB_EXCEPTIONS))
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/m68k/t-uclinux b/gcc/config/m68k/t-uclinux
index e1711a3443e..6994359dcce 100644
--- a/gcc/config/m68k/t-uclinux
+++ b/gcc/config/m68k/t-uclinux
@@ -1,4 +1,4 @@
-# Copyright (C) 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2005, 2007, 2008, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,9 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# crti and crtn are provided by uClibc.
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o
-
# Include multilibs for CPUs without an MMU or with FL_UCLINUX
M68K_MLIB_CPU += && (!match(FLAGS, "FL_MMU") || match(FLAGS, "FL_UCLINUX"))
diff --git a/gcc/config/mcore/crti.asm b/gcc/config/mcore/crti.asm
deleted file mode 100644
index 03f59292896..00000000000
--- a/gcc/config/mcore/crti.asm
+++ /dev/null
@@ -1,62 +0,0 @@
-# crti.asm for ELF based systems
-
-# Copyright (C) 1992, 1998, 1999, 2008, 2009 Free Software Foundation, Inc.
-# Written By David Vinayak Henkel-Wallace, June 1992
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-
-# This file just makes a stack frame for the contents of the .fini and
-# .init sections. Users may put any desired instructions in those
-# sections.
-
- .section ".init"
- .global _init
- .type _init,@function
- .align 4
-_init:
- subi r0, 16
- st.w r15, (r0, 12)
-
- # These nops are here to align the end of this code with a 16 byte
- # boundary. The linker will start inserting code into the .init
- # section at such a boundary.
-
- nop
- nop
- nop
- nop
- nop
- nop
-
-
- .section ".fini"
- .global _fini
- .type _fini,@function
- .align 4
-_fini:
- subi r0, 16
- st.w r15, (r0, 12)
- nop
- nop
- nop
- nop
- nop
- nop
diff --git a/gcc/config/mcore/crtn.asm b/gcc/config/mcore/crtn.asm
deleted file mode 100644
index b764441e721..00000000000
--- a/gcc/config/mcore/crtn.asm
+++ /dev/null
@@ -1,44 +0,0 @@
-# crtn.asm for ELF based systems
-
-# Copyright (C) 1992, 1999, 2000, 2008, 2009 Free Software Foundation, Inc.
-# Written By David Vinayak Henkel-Wallace, June 1992
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file just makes sure that the .fini and .init sections do in
-# fact return. Users may put any desired instructions in those sections.
-# This file is the last thing linked into any executable.
-
- .section ".init"
- .align 4
-
- ldw r15,(r0, 12)
- addi r0,16
- jmp r15
-
- .section ".fini"
- .align 4
-
- ldw r15, (r0, 12)
- addi r0,16
- jmp r15
-
-# Th-th-th-that is all folks!
-
diff --git a/gcc/config/mcore/t-mcore b/gcc/config/mcore/t-mcore
index 5533211a5d2..c848ceda3b3 100644
--- a/gcc/config/mcore/t-mcore
+++ b/gcc/config/mcore/t-mcore
@@ -16,42 +16,17 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = mcore/lib1.asm
-LIB1ASMFUNCS = _divsi3 _udivsi3 _modsi3 _umodsi3
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/mcore/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mcore/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/mcore/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mcore/crtn.asm
-
-# could use -msifilter to be safe from interrupt/jmp interactions and others.
-TARGET_LIBGCC2_CFLAGS=-O3 -DNO_FLOATLIB_FIXUNSDFSI #-msifilter
-
# We have values for float.h.
CROSS_FLOAT_H = $(srcdir)/config/mcore/gfloat.h
# If support for -m4align is ever re-enabled then comment out the
-# following line and uncomment the mutlilib lines below.
-
-EXTRA_PARTS = crtbegin.o crtend.o crti.o crtn.o
+# following line and uncomment the multilib lines below.
# MULTILIB_OPTIONS = m8align/m4align
# MULTILIB_DIRNAMES = align8 align4
# MULTILIB_MATCHES =
# MULTILIB_EXTRA_OPTS =
# MULTILIB_EXCEPTIONS =
-# EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-# LIBGCC = stmp-multilib
-# INSTALL_LIBGCC = install-multilib
MULTILIB_OPTIONS = mbig-endian/mlittle-endian m210/m340
MULTILIB_DIRNAMES = big little m210 m340
-
-EXTRA_PARTS =
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/mep/t-mep b/gcc/config/mep/t-mep
index 29c75457241..96542c4782c 100644
--- a/gcc/config/mep/t-mep
+++ b/gcc/config/mep/t-mep
@@ -24,12 +24,6 @@
GTM_H = tm.h $(tm_file_list) $(srcdir)/config/mep/mep-intrin.h insn-constants.h
-# Use -O0 instead of -O2 so we don't get complex relocations
-
-CRTSTUFF_CFLAGS = -O0 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
- -finhibit-size-directive -fno-inline-functions -fno-exceptions \
- -fno-zero-initialized-in-bss -fno-unit-at-a-time
-
TCFLAGS = -mlibrary
mep-pragma.o: $(srcdir)/config/mep/mep-pragma.c $(CONFIG_H) $(SYSTEM_H) \
@@ -38,27 +32,9 @@ mep-pragma.o: $(srcdir)/config/mep/mep-pragma.c $(CONFIG_H) $(SYSTEM_H) \
function.h insn-config.h reload.h $(TARGET_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-# profiling support
-
-LIB1ASMSRC = mep/mep-lib1.asm
-
-LIB1ASMFUNCS = _mep_profile \
- _mep_bb_init_trace \
- _mep_bb_init \
- _mep_bb_trace \
- _mep_bb_increment
-
-# multiply and divide routines
-
-LIB2FUNCS_EXTRA = \
- $(srcdir)/config/mep/mep-lib2.c \
- $(srcdir)/config/mep/mep-tramp.c
-
MULTILIB_OPTIONS = mel mall-opts mfar
MULTILIB_DIRNAMES = el allopt far
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-
MD_INCLUDES = \
$(srcdir)/config/mep/intrinsics.md \
$(srcdir)/config/mep/predicates.md \
diff --git a/gcc/config/microblaze/t-microblaze b/gcc/config/microblaze/t-microblaze
index 8c8767f9baa..cb49636b9ac 100644
--- a/gcc/config/microblaze/t-microblaze
+++ b/gcc/config/microblaze/t-microblaze
@@ -1,8 +1,3 @@
-# For C++ crtstuff
-EXTRA_MULTILIB_PARTS = crtbegin$(objext) crtend$(objext)
-
-EXTRA_PARTS += crti$(objext) crtn$(objext)
-
MULTILIB_OPTIONS = mxl-barrel-shift mno-xl-soft-mul mxl-multiply-high
MULTILIB_DIRNAMES = bs m mh
MULTILIB_EXCEPTIONS = *mxl-barrel-shift/mxl-multiply-high mxl-multiply-high
@@ -13,10 +8,3 @@ microblaze-c.o: $(srcdir)/config/microblaze/microblaze-c.c \
$(CONFIG_H) $(SYSTEM_H) $(CPPLIB_H) $(TM_P_H) $(TREE_H) errors.h $(TM_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/microblaze/microblaze-c.c
-
-# Assemble startup files
-$(T)crti$(objext): $(srcdir)/config/microblaze/crti.s
- $(GCC_FOR_TARGET) -c $(srcdir)/config/microblaze/crti.s -o $(T)crti$(objext)
-
-$(T)crtn$(objext): $(srcdir)/config/microblaze/crtn.s
- $(GCC_FOR_TARGET) -c $(srcdir)/config/microblaze/crtn.s -o $(T)crtn$(objext)
diff --git a/gcc/config/mips/t-elf b/gcc/config/mips/t-elf
index 4ed36da659b..b4535d28fc4 100644
--- a/gcc/config/mips/t-elf
+++ b/gcc/config/mips/t-elf
@@ -1,5 +1,5 @@
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006,
-# 2007 Free Software Foundation, Inc.
+# 2007, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -17,28 +17,8 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Don't let CTOR_LIST end up in sdata section.
-CRTSTUFF_T_CFLAGS = -G 0
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
-
-# We must build libgcc2.a with -G 0, in case the user wants to link
-# without the $gp register.
-TARGET_LIBGCC2_CFLAGS = -G 0
-
# Build the libraries for both hard and soft floating point
MULTILIB_OPTIONS = msoft-float EL/EB
MULTILIB_DIRNAMES = soft-float el eb
MULTILIB_MATCHES = EL=mel EB=meb msingle-float=m4650
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/mips/t-isa3264 b/gcc/config/mips/t-isa3264
index f6dce325562..7291193f8a6 100644
--- a/gcc/config/mips/t-isa3264
+++ b/gcc/config/mips/t-isa3264
@@ -1,5 +1,5 @@
# Copyright (C) 2001, 2002, 2003, 2004, 2007,
-# 2008 Free Software Foundation, Inc.
+# 2008, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -17,22 +17,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Don't let CTOR_LIST end up in sdata section.
-CRTSTUFF_T_CFLAGS = -G 0
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
-
-# We must build libgcc2.a with -G 0, in case the user wants to link
-# without the $gp register.
-TARGET_LIBGCC2_CFLAGS = -G 0
-
# Build the libraries for both hard and soft floating point
ifneq ($(filter MIPS_ABI_DEFAULT=ABI_EABI,$(tm_defines)),)
@@ -48,7 +32,3 @@ MULTILIB_EXCLUSIONS = !mips32r2/mfp64
endif
endif
MULTILIB_MATCHES = EL=mel EB=meb
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/mips/t-libgcc-mips16 b/gcc/config/mips/t-libgcc-mips16
deleted file mode 100644
index 772b05ac45e..00000000000
--- a/gcc/config/mips/t-libgcc-mips16
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright (C) 2007, 2008, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB1ASMSRC = mips/mips16.S
-LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \
- _m16eqsf2 _m16nesf2 _m16gtsf2 _m16gesf2 _m16lesf2 _m16ltsf2 \
- _m16unordsf2 \
- _m16fltsisf _m16fix_truncsfsi _m16fltunsisf \
- _m16adddf3 _m16subdf3 _m16muldf3 _m16divdf3 \
- _m16extsfdf2 _m16trdfsf2 \
- _m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \
- _m16unorddf2 \
- _m16fltsidf _m16fix_truncdfsi _m16fltunsidf \
- _m16retsf _m16retdf \
- _m16retsc _m16retdc \
- _m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \
- _m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \
- _m16stubsf9 _m16stubsf10 \
- _m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \
- _m16stubdf9 _m16stubdf10 \
- _m16stubsc0 _m16stubsc1 _m16stubsc2 _m16stubsc5 _m16stubsc6 \
- _m16stubsc9 _m16stubsc10 \
- _m16stubdc0 _m16stubdc1 _m16stubdc2 _m16stubdc5 _m16stubdc6 \
- _m16stubdc9 _m16stubdc10
-
-# Version these symbols if building libgcc.so.
-SHLIB_MAPFILES += $(srcdir)/config/mips/libgcc-mips16.ver
diff --git a/gcc/config/mips/t-linux64 b/gcc/config/mips/t-linux64
index 0e695172f55..5197e5ee209 100644
--- a/gcc/config/mips/t-linux64
+++ b/gcc/config/mips/t-linux64
@@ -19,5 +19,3 @@
MULTILIB_OPTIONS = mabi=n32/mabi=32/mabi=64
MULTILIB_DIRNAMES = n32 32 64
MULTILIB_OSDIRNAMES = ../lib32 ../lib ../lib64
-
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
diff --git a/gcc/config/mips/t-mips b/gcc/config/mips/t-mips
index 53993e9d3c0..46c5ebcb1e4 100644
--- a/gcc/config/mips/t-mips
+++ b/gcc/config/mips/t-mips
@@ -16,8 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB2_SIDITI_CONV_FUNCS=yes
-
$(srcdir)/config/mips/mips-tables.opt: $(srcdir)/config/mips/genopt.sh \
$(srcdir)/config/mips/mips-cpus.def
$(SHELL) $(srcdir)/config/mips/genopt.sh $(srcdir)/config/mips > \
diff --git a/gcc/config/mips/t-r3900 b/gcc/config/mips/t-r3900
index 2c4216399c5..d542df36ed6 100644
--- a/gcc/config/mips/t-r3900
+++ b/gcc/config/mips/t-r3900
@@ -1,5 +1,5 @@
# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2007 Free Software Foundation, Inc.
+# 2007, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -17,19 +17,8 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# We must build libgcc2.a with -G 0, in case the user wants to link
-# without the $gp register.
-TARGET_LIBGCC2_CFLAGS = -G 0
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-# Don't let CTOR_LIST end up in sdata section.
-CRTSTUFF_T_CFLAGS = -G 0
-
# Build the libraries for both hard and soft floating point
MULTILIB_OPTIONS = msoft-float EL/EB
MULTILIB_DIRNAMES = soft-float el eb
MULTILIB_MATCHES = EL=mel EB=meb
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/mips/t-sde b/gcc/config/mips/t-sde
index 0fa2277d573..d9c229ab4e0 100644
--- a/gcc/config/mips/t-sde
+++ b/gcc/config/mips/t-sde
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2007, 2008, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,18 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Don't let CTOR_LIST end up in sdata section.
-CRTSTUFF_T_CFLAGS = -G 0
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
-
MULTILIB_OPTIONS = EL/EB mips32/mips32r2/mips64/mips64r2 mips16 msoft-float/mfp64 mcode-readable=no
MULTILIB_DIRNAMES = el eb mips32 mips32r2 mips64 mips64r2 mips16 sof f64 spram
MULTILIB_MATCHES = EL=mel EB=meb
@@ -45,9 +33,3 @@ MULTILIB_EXCLUSIONS += !mips32/!mips32r2/mips16
else
MULTILIB_EXCLUSIONS += mips64/mips16 mips64r2/mips16
endif
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-# Build the multilibs.
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/mips/t-sr71k b/gcc/config/mips/t-sr71k
index 44b69402e62..309eec6a650 100644
--- a/gcc/config/mips/t-sr71k
+++ b/gcc/config/mips/t-sr71k
@@ -16,32 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Suppress building libgcc1.a, since the MIPS compiler port is complete
-# and does not need anything from libgcc1.a.
-LIBGCC1 =
-CROSS_LIBGCC1 =
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-# Don't let CTOR_LIST end up in sdata section.
-CRTSTUFF_T_CFLAGS = -G 0
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
-
-# We must build libgcc2.a with -G 0, in case the user wants to link
-# without the $gp register.
-TARGET_LIBGCC2_CFLAGS = -G 0
-
# Build the libraries for both hard and soft floating point
-
MULTILIB_OPTIONS = EL/EB msoft-float mips2
MULTILIB_DIRNAMES = el eb soft-float mips2
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/mips/t-st b/gcc/config/mips/t-st
index 83115f6fdd5..b0a8933c32b 100644
--- a/gcc/config/mips/t-st
+++ b/gcc/config/mips/t-st
@@ -1,4 +1,4 @@
-# Copyright (C) 2008 Free Software Foundation, Inc.
+# Copyright (C) 2008, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -28,5 +28,3 @@ MULTILIB_OSDIRNAMES += march.loongson2f/mabi.64=../lib64/2f
MULTILIB_OSDIRNAMES += mabi.n32=../lib32
MULTILIB_OSDIRNAMES += mabi.32=../lib
MULTILIB_OSDIRNAMES += mabi.64=../lib64
-
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
diff --git a/gcc/config/mips/t-vr b/gcc/config/mips/t-vr
index 81efef9b865..de5ca706faf 100644
--- a/gcc/config/mips/t-vr
+++ b/gcc/config/mips/t-vr
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2004, 2005, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,30 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# BEGIN boiler-plate MIPS stuff
-
-# Don't let CTOR_LIST end up in sdata section.
-CRTSTUFF_T_CFLAGS = -G 0
-
-# We must build libgcc2.a with -G 0, in case the user wants to link
-# without the $gp register.
-TARGET_LIBGCC2_CFLAGS = -G 0
-
-LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/mips16.S \
- $(srcdir)/config/mips/vr4120-div.S
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
-
-# END boiler-plate
-
# Main multilibs
# --------------
#
diff --git a/gcc/config/mmix/crti.asm b/gcc/config/mmix/crti.asm
deleted file mode 100644
index f5f4c5d68c4..00000000000
--- a/gcc/config/mmix/crti.asm
+++ /dev/null
@@ -1,116 +0,0 @@
-/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
- Contributed by Hans-Peter Nilsson <hp@bitrange.com>
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 3, or (at your option) any
-later version.
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-% This is the crt0 equivalent for mmix-knuth-mmixware, for setting up
-% things for compiler-generated assembly-code and for setting up things
-% between where the simulator calls and main, and shutting things down on
-% the way back. There's an actual crt0.o elsewhere, but that's a dummy.
-
-% This file and the GCC output are supposed to be *reasonably*
-% mmixal-compatible to enable people to re-use output with Knuth's mmixal.
-% However, forward references are used more freely: we are using the
-% binutils tools. Users of mmixal beware; you will sometimes have to
-% re-order things or use temporary variables.
-
-% Users of mmixal will want to set up 8H and 9H to be .text and .data
-% respectively, so the compiler can switch between them pretending they're
-% segments.
-
-% This little treasure is here so the 32 lowest address bits of user data
-% will not be zero. Because of truncation, that would cause testcase
-% gcc.c-torture/execute/980701-1.c to incorrectly fail.
-
- .data ! mmixal:= 8H LOC Data_Segment
- .p2align 3
- LOC @+(8-@)@7
- OCTA 2009
-
- .text ! mmixal:= 9H LOC 8B; LOC #100
- .global Main
-
-% The __Stack_start symbol is provided by the link script.
-stackpp OCTA __Stack_start
-
-% "Main" is the magic symbol the simulator jumps to. We want to go
-% on to "main".
-% We need to set rG explicitly to avoid hard-to-debug situations.
-Main SETL $255,32
- PUT rG,$255
-
-% Initialize the stack pointer. It is supposedly made a global
-% zero-initialized (allowed to change) register in crtn.asm; we use the
-% explicit number.
- GETA $255,stackpp
- LDOU $254,$255,0
-
-% Make sure we get more than one mem, to simplify counting cycles.
- LDBU $255,$1,0
- LDBU $255,$1,1
-
- PUSHJ $2,_init
-
-#ifdef __MMIX_ABI_GNU__
-% Copy argc and argv from their initial position to argument registers
-% where necessary.
- SET $231,$0
- SET $232,$1
-#else
-% For the mmixware ABI, we need to move arguments. The return value will
-% appear in $0.
- SET $2,$1
- SET $1,$0
-#endif
-
- PUSHJ $0,main
- JMP exit
-
-% Provide the first part of _init and _fini. Save the return address on the
-% register stack. We eventually ignore the return address of these
-% PUSHJ:s, so it doesn't matter that whether .init and .fini code calls
-% functions or where they store rJ. We shouldn't get there, so die
-% (TRAP Halt) if that happens.
-
- .section .init,"ax",@progbits
- .global _init
-_init:
- GET $0,:rJ
- PUSHJ $1,0F
- SETL $255,255
- TRAP 0,0,0
-0H IS @
-
-% Register _fini to be executed as the last atexit function.
-#ifdef __MMIX_ABI_GNU__
- GETA $231,_fini
-#else
- GETA $1,_fini
-#endif
- PUSHJ $0,atexit
-
- .section .fini,"ax",@progbits
- .global _fini
-_fini:
- GET $0,:rJ
- PUSHJ $1,0F
- SETL $255,255
- TRAP 0,0,0
-0H IS @
diff --git a/gcc/config/mmix/t-mmix b/gcc/config/mmix/t-mmix
index dc05c8e82f5..b25eebcd35a 100644
--- a/gcc/config/mmix/t-mmix
+++ b/gcc/config/mmix/t-mmix
@@ -1,4 +1,4 @@
-# Copyright (C) 2001, 2002, 2003, 2010 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003, 2010, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,16 +16,5 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# See "Target Fragment" in GCC info. That same order is used here.
-
-TARGET_LIBGCC2_CFLAGS = -mlibfuncs -O2
-
-# We need to turn off some assumptions on normality for code in crtstuff.c
-# and crt{i,n}.asm, specifically about execution not continuing past the
-# end of the section in the file being compiled. Thus we must stop the
-# assembler from generating stubbable PUSHJ relocs, because that will add
-# stubs at the end of the current section when necessary.
-CRTSTUFF_T_CFLAGS = -Wa,--no-stubs
-
MULTILIB_OPTIONS = mabi=gnu
MULTILIB_DIRNAMES = gnuabi
diff --git a/gcc/config/mn10300/t-mn10300 b/gcc/config/mn10300/t-mn10300
index c62c56f2013..af22d94cdc3 100644
--- a/gcc/config/mn10300/t-mn10300
+++ b/gcc/config/mn10300/t-mn10300
@@ -19,6 +19,3 @@
MULTILIB_OPTIONS = mam33/mam33-2/mam34
MULTILIB_DIRNAMES = am33 am33-2 am34
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/moxie/crti.asm b/gcc/config/moxie/crti.asm
deleted file mode 100644
index f44582799a3..00000000000
--- a/gcc/config/moxie/crti.asm
+++ /dev/null
@@ -1,40 +0,0 @@
-# crti.asm for moxie
-#
-# Copyright (C) 2009 Free Software Foundation
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file just make a stack frame for the contents of the .fini and
-# .init sections. Users may put any desired instructions in those
-# sections.
-
- .file "crti.asm"
-
- .section ".init"
- .global _init
- .type _init, @function
- .p2align 1
-_init:
-
- .section ".fini"
- .global _fini
- .type _fini,@function
- .p2align 1
-_fini:
diff --git a/gcc/config/moxie/crtn.asm b/gcc/config/moxie/crtn.asm
deleted file mode 100644
index 3ac9d31eed8..00000000000
--- a/gcc/config/moxie/crtn.asm
+++ /dev/null
@@ -1,34 +0,0 @@
-# crtn.asm for moxie
-#
-# Copyright (C) 2009 Free Software Foundation
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file just makes sure that the .fini and .init sections do in
-# fact return. Users may put any desired instructions in those sections.
-# This file is the last thing linked into any executable.
-
- .file "crtn.asm"
-
- .section ".init"
- ret
-
- .section ".fini"
- ret
diff --git a/gcc/config/openbsd.h b/gcc/config/openbsd.h
index aa279ed4738..fad29154cef 100644
--- a/gcc/config/openbsd.h
+++ b/gcc/config/openbsd.h
@@ -1,5 +1,5 @@
/* Base configuration file for all OpenBSD targets.
- Copyright (C) 1999, 2000, 2004, 2005, 2007, 2009, 2010
+ Copyright (C) 1999, 2000, 2004, 2005, 2007, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -59,7 +59,7 @@ along with GCC; see the file COPYING3. If not see
{ GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \
{ GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1 }, \
{ GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1 }, \
- { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 }, \
+ { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0 }, \
{ 0, 0, 0, 0 } \
}
diff --git a/gcc/config/pa/constraints.md b/gcc/config/pa/constraints.md
index c1f3d5cd3f3..ce5a5f7306a 100644
--- a/gcc/config/pa/constraints.md
+++ b/gcc/config/pa/constraints.md
@@ -55,7 +55,7 @@
(define_constraint "K"
"Integer constant that can be deposited with a zdepi instruction."
(and (match_code "const_int")
- (match_test "zdepi_cint_p (ival)")))
+ (match_test "pa_zdepi_cint_p (ival)")))
(define_constraint "L"
"Signed 5-bit integer constant."
@@ -70,7 +70,7 @@
(define_constraint "N"
"Integer constant that can be loaded with a ldil instruction."
(and (match_code "const_int")
- (match_test "ldil_cint_p (ival)")))
+ (match_test "pa_ldil_cint_p (ival)")))
(define_constraint "O"
"Integer constant such that ival+1 is a power of 2."
@@ -81,7 +81,7 @@
"Integer constant that can be used as an and mask in depi and
extru instructions."
(and (match_code "const_int")
- (match_test "and_mask_p (ival)")))
+ (match_test "pa_and_mask_p (ival)")))
(define_constraint "S"
"Integer constant 31."
diff --git a/gcc/config/pa/elf.h b/gcc/config/pa/elf.h
index 1028206fd4a..dc436a3fe96 100644
--- a/gcc/config/pa/elf.h
+++ b/gcc/config/pa/elf.h
@@ -80,7 +80,7 @@ do { \
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, RTL) \
do { fputs ("\t.IMPORT ", FILE); \
if (!function_label_operand (RTL, VOIDmode)) \
- hppa_encode_label (RTL); \
+ pa_encode_label (RTL); \
assemble_name (FILE, XSTR ((RTL), 0)); \
fputs (",ENTRY\n", FILE); \
} while (0)
diff --git a/gcc/config/pa/pa-linux.h b/gcc/config/pa/pa-linux.h
index 02a43eb316a..6c6cf210aa4 100644
--- a/gcc/config/pa/pa-linux.h
+++ b/gcc/config/pa/pa-linux.h
@@ -128,7 +128,7 @@ along with GCC; see the file COPYING3. If not see
do \
{ \
if (!FUNCTION_NAME_P (XSTR (FUN, 0))) \
- hppa_encode_label (FUN); \
+ pa_encode_label (FUN); \
(*targetm.asm_out.globalize_label) (FILE, XSTR (FUN, 0)); \
} \
while (0)
diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h
index 8c733e4f6f4..d28ee3cb862 100644
--- a/gcc/config/pa/pa-protos.h
+++ b/gcc/config/pa/pa-protos.h
@@ -24,89 +24,82 @@ along with GCC; see the file COPYING3. If not see
extern rtx pa_eh_return_handler_rtx (void);
/* Used in insn-*.c. */
-extern int following_call (rtx);
+extern int pa_following_call (rtx);
/* Define functions in pa.c and used in insn-output.c. */
-extern const char *output_and (rtx *);
-extern const char *output_ior (rtx *);
-extern const char *output_move_double (rtx *);
-extern const char *output_fp_move_double (rtx *);
-extern const char *output_block_move (rtx *, int);
-extern const char *output_block_clear (rtx *, int);
-extern const char *output_cbranch (rtx *, int, rtx);
-extern const char *output_lbranch (rtx, rtx, int);
-extern const char *output_bb (rtx *, int, rtx, int);
-extern const char *output_bvb (rtx *, int, rtx, int);
-extern const char *output_dbra (rtx *, rtx, int);
-extern const char *output_movb (rtx *, rtx, int, int);
-extern const char *output_parallel_movb (rtx *, rtx);
-extern const char *output_parallel_addb (rtx *, rtx);
-extern const char *output_call (rtx, rtx, int);
-extern const char *output_indirect_call (rtx, rtx);
-extern const char *output_millicode_call (rtx, rtx);
-extern const char *output_mul_insn (int, rtx);
-extern const char *output_div_insn (rtx *, int, rtx);
-extern const char *output_mod_insn (int, rtx);
-extern const char *singlemove_string (rtx *);
-extern void output_arg_descriptor (rtx);
-extern void output_global_address (FILE *, rtx, int);
-extern void print_operand (FILE *, rtx, int);
-extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
-extern void hppa_encode_label (rtx);
-extern int symbolic_expression_p (rtx);
+extern const char *pa_output_and (rtx *);
+extern const char *pa_output_64bit_and (rtx *);
+extern const char *pa_output_ior (rtx *);
+extern const char *pa_output_64bit_ior (rtx *);
+extern const char *pa_output_move_double (rtx *);
+extern const char *pa_output_fp_move_double (rtx *);
+extern const char *pa_output_block_move (rtx *, int);
+extern const char *pa_output_block_clear (rtx *, int);
+extern const char *pa_output_cbranch (rtx *, int, rtx);
+extern const char *pa_output_lbranch (rtx, rtx, int);
+extern const char *pa_output_bb (rtx *, int, rtx, int);
+extern const char *pa_output_bvb (rtx *, int, rtx, int);
+extern const char *pa_output_dbra (rtx *, rtx, int);
+extern const char *pa_output_movb (rtx *, rtx, int, int);
+extern const char *pa_output_parallel_movb (rtx *, rtx);
+extern const char *pa_output_parallel_addb (rtx *, rtx);
+extern const char *pa_output_call (rtx, rtx, int);
+extern const char *pa_output_indirect_call (rtx, rtx);
+extern const char *pa_output_millicode_call (rtx, rtx);
+extern const char *pa_output_mul_insn (int, rtx);
+extern const char *pa_output_div_insn (rtx *, int, rtx);
+extern const char *pa_output_mod_insn (int, rtx);
+extern const char *pa_singlemove_string (rtx *);
+extern void pa_output_arg_descriptor (rtx);
+extern void pa_output_global_address (FILE *, rtx, int);
+extern void pa_print_operand (FILE *, rtx, int);
+extern void pa_encode_label (rtx);
+extern int pa_symbolic_expression_p (rtx);
extern bool pa_tls_referenced_p (rtx);
extern int pa_adjust_insn_length (rtx, int);
-extern int fmpyaddoperands (rtx *);
-extern int fmpysuboperands (rtx *);
-extern void emit_bcond_fp (rtx[]);
-extern int emit_move_sequence (rtx *, enum machine_mode, rtx);
-extern int emit_hpdiv_const (rtx *, int);
-extern int is_function_label_plus_const (rtx);
-extern int jump_in_call_delay (rtx);
-extern int hppa_fpstore_bypass_p (rtx, rtx);
-extern int attr_length_millicode_call (rtx);
-extern int attr_length_call (rtx, int);
-extern int attr_length_indirect_call (rtx);
-extern int attr_length_save_restore_dltp (rtx);
+extern int pa_fmpyaddoperands (rtx *);
+extern int pa_fmpysuboperands (rtx *);
+extern void pa_emit_bcond_fp (rtx[]);
+extern int pa_emit_move_sequence (rtx *, enum machine_mode, rtx);
+extern int pa_emit_hpdiv_const (rtx *, int);
+extern int pa_is_function_label_plus_const (rtx);
+extern int pa_jump_in_call_delay (rtx);
+extern int pa_fpstore_bypass_p (rtx, rtx);
+extern int pa_attr_length_millicode_call (rtx);
+extern int pa_attr_length_call (rtx, int);
+extern int pa_attr_length_indirect_call (rtx);
/* Declare functions defined in pa.c and used in templates. */
-extern rtx return_addr_rtx (int, rtx);
+extern rtx pa_return_addr_rtx (int, rtx);
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
#ifdef TREE_CODE
-extern enum direction function_arg_padding (enum machine_mode, const_tree);
+extern enum direction pa_function_arg_padding (enum machine_mode, const_tree);
#endif
#endif /* ARGS_SIZE_RTX */
-extern int insn_refs_are_delayed (rtx);
-extern rtx get_deferred_plabel (rtx);
+extern int pa_insn_refs_are_delayed (rtx);
+extern rtx pa_get_deferred_plabel (rtx);
#endif /* RTX_CODE */
-extern int ldil_cint_p (HOST_WIDE_INT);
-extern int zdepi_cint_p (unsigned HOST_WIDE_INT);
-
-extern void output_ascii (FILE *, const char *, int);
-extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT, int *);
-extern int and_mask_p (unsigned HOST_WIDE_INT);
-extern int cint_ok_for_move (HOST_WIDE_INT);
-extern void hppa_expand_prologue (void);
-extern void hppa_expand_epilogue (void);
+extern int pa_and_mask_p (unsigned HOST_WIDE_INT);
+extern int pa_cint_ok_for_move (HOST_WIDE_INT);
+extern int pa_ior_mask_p (unsigned HOST_WIDE_INT);
+extern int pa_ldil_cint_p (HOST_WIDE_INT);
+extern int pa_shadd_constant_p (int);
+extern int pa_zdepi_cint_p (unsigned HOST_WIDE_INT);
+
+extern void pa_output_ascii (FILE *, const char *, int);
+extern HOST_WIDE_INT pa_compute_frame_size (HOST_WIDE_INT, int *);
+extern void pa_expand_prologue (void);
+extern void pa_expand_epilogue (void);
extern bool pa_can_use_return_insn (void);
-extern int ior_mask_p (unsigned HOST_WIDE_INT);
-extern void compute_zdepdi_operands (unsigned HOST_WIDE_INT,
- unsigned *);
-#ifdef RTX_CODE
-extern const char * output_64bit_and (rtx *);
-extern const char * output_64bit_ior (rtx *);
-extern int cmpib_comparison_operator (rtx, enum machine_mode);
-#endif
-
/* Miscellaneous functions in pa.c. */
#ifdef TREE_CODE
-extern int reloc_needed (tree);
+extern int pa_reloc_needed (tree);
extern bool pa_return_in_memory (const_tree, const_tree);
#endif /* TREE_CODE */
@@ -125,5 +118,4 @@ extern bool pa_cannot_change_mode_class (enum machine_mode, enum machine_mode,
extern bool pa_modes_tieable_p (enum machine_mode, enum machine_mode);
extern HOST_WIDE_INT pa_initial_elimination_offset (int, int);
-extern const int magic_milli[];
-extern int shadd_constant_p (int);
+extern const int pa_magic_milli[];
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 66e3fc700b4..6d2f67d00c3 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -54,7 +54,7 @@ along with GCC; see the file COPYING3. If not see
/* Return nonzero if there is a bypass for the output of
OUT_INSN and the fp store IN_INSN. */
int
-hppa_fpstore_bypass_p (rtx out_insn, rtx in_insn)
+pa_fpstore_bypass_p (rtx out_insn, rtx in_insn)
{
enum machine_mode store_mode;
enum machine_mode other_mode;
@@ -99,6 +99,7 @@ static void pa_combine_instructions (void);
static int pa_can_combine_p (rtx, rtx, rtx, int, rtx, rtx, rtx);
static bool forward_branch_p (rtx);
static void compute_zdepwi_operands (unsigned HOST_WIDE_INT, unsigned *);
+static void compute_zdepdi_operands (unsigned HOST_WIDE_INT, unsigned *);
static int compute_movmem_length (rtx);
static int compute_clrmem_length (rtx);
static bool pa_assemble_integer (rtx, unsigned int, int);
@@ -677,7 +678,7 @@ copy_reg_pointer (rtx to, rtx from)
expressions will have one of a few well defined forms, so
we need only check those forms. */
int
-symbolic_expression_p (rtx x)
+pa_symbolic_expression_p (rtx x)
{
/* Strip off any HIGH. */
@@ -690,19 +691,19 @@ symbolic_expression_p (rtx x)
/* Accept any constant that can be moved in one instruction into a
general register. */
int
-cint_ok_for_move (HOST_WIDE_INT ival)
+pa_cint_ok_for_move (HOST_WIDE_INT ival)
{
/* OK if ldo, ldil, or zdepi, can be used. */
return (VAL_14_BITS_P (ival)
- || ldil_cint_p (ival)
- || zdepi_cint_p (ival));
+ || pa_ldil_cint_p (ival)
+ || pa_zdepi_cint_p (ival));
}
/* True iff ldil can be used to load this CONST_INT. The least
significant 11 bits of the value must be zero and the value must
not change sign when extended from 32 to 64 bits. */
int
-ldil_cint_p (HOST_WIDE_INT ival)
+pa_ldil_cint_p (HOST_WIDE_INT ival)
{
HOST_WIDE_INT x = ival & (((HOST_WIDE_INT) -1 << 31) | 0x7ff);
@@ -713,7 +714,7 @@ ldil_cint_p (HOST_WIDE_INT ival)
zdepi first sign extends a 5-bit signed number to a given field
length, then places this field anywhere in a zero. */
int
-zdepi_cint_p (unsigned HOST_WIDE_INT x)
+pa_zdepi_cint_p (unsigned HOST_WIDE_INT x)
{
unsigned HOST_WIDE_INT lsb_mask, t;
@@ -731,7 +732,7 @@ zdepi_cint_p (unsigned HOST_WIDE_INT x)
1....10....0
1..10..01..1 */
int
-and_mask_p (unsigned HOST_WIDE_INT mask)
+pa_and_mask_p (unsigned HOST_WIDE_INT mask)
{
mask = ~mask;
mask += mask & -mask;
@@ -740,7 +741,7 @@ and_mask_p (unsigned HOST_WIDE_INT mask)
/* True iff depi can be used to compute (reg | MASK). */
int
-ior_mask_p (unsigned HOST_WIDE_INT mask)
+pa_ior_mask_p (unsigned HOST_WIDE_INT mask)
{
mask += mask & -mask;
return (mask & (mask - 1)) == 0;
@@ -751,7 +752,7 @@ ior_mask_p (unsigned HOST_WIDE_INT mask)
position-independent addresses go to REG. If we need more
than one register, we lose. */
-rtx
+static rtx
legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
{
rtx pic_ref = orig;
@@ -1102,7 +1103,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
+ && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
&& (OBJECT_P (XEXP (x, 1))
|| GET_CODE (XEXP (x, 1)) == SUBREG)
&& GET_CODE (XEXP (x, 1)) != CONST)
@@ -1133,7 +1134,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
&& GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
- && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
+ && pa_shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
&& (mode == SFmode || mode == DFmode))
{
@@ -1146,7 +1147,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
idx = NULL_RTX;
/* Make sure they're both regs. If one was a SYMBOL_REF [+ const],
- then emit_move_sequence will turn on REG_POINTER so we'll know
+ then pa_emit_move_sequence will turn on REG_POINTER so we'll know
it's a base register below. */
if (GET_CODE (reg1) != REG)
reg1 = force_reg (Pmode, force_operand (reg1, 0));
@@ -1259,7 +1260,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
do the optimization for floatint point modes. */
if (GET_CODE (x) == PLUS
- && symbolic_expression_p (XEXP (x, 1)))
+ && pa_symbolic_expression_p (XEXP (x, 1)))
{
/* Ugly. We modify things here so that the address offset specified
by the index expression is computed first, then added to x to form
@@ -1289,7 +1290,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& INTVAL (XEXP (y, 1)) >= -4096
&& INTVAL (XEXP (y, 1)) <= 4095
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+ && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
{
int val = INTVAL (XEXP (XEXP (x, 0), 1));
rtx reg1, reg2;
@@ -1315,7 +1316,7 @@ hppa_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& GET_CODE (XEXP (y, 1)) == CONST_INT
&& INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+ && pa_shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
{
regx1
= force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
@@ -1541,7 +1542,7 @@ pa_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
of SCRATCH_REG in the proper mode. */
int
-emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
+pa_emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
{
register rtx operand0 = operands[0];
register rtx operand1 = operands[1];
@@ -1722,7 +1723,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
const_mem = force_const_mem (mode, operand1);
xoperands[0] = scratch_reg;
xoperands[1] = XEXP (const_mem, 0);
- emit_move_sequence (xoperands, Pmode, 0);
+ pa_emit_move_sequence (xoperands, Pmode, 0);
/* Now load the destination register. */
emit_insn (gen_rtx_SET (mode, operand0,
@@ -1781,9 +1782,14 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
/* Handle the most common case: storing into a register. */
else if (register_operand (operand0, mode))
{
+ /* Legitimize TLS symbol references. This happens for references
+ that aren't a legitimate constant. */
+ if (PA_SYMBOL_REF_TLS_P (operand1))
+ operand1 = legitimize_tls_address (operand1);
+
if (register_operand (operand1, mode)
|| (GET_CODE (operand1) == CONST_INT
- && cint_ok_for_move (INTVAL (operand1)))
+ && pa_cint_ok_for_move (INTVAL (operand1)))
|| (operand1 == CONST0_RTX (mode))
|| (GET_CODE (operand1) == HIGH
&& !symbolic_operand (XEXP (operand1, 0), VOIDmode))
@@ -1941,12 +1947,12 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
/* Put the address of the memory location into our destination
register. */
operands[1] = temp;
- emit_move_sequence (operands, mode, scratch_reg);
+ pa_emit_move_sequence (operands, mode, scratch_reg);
/* Now load from the memory location into our destination
register. */
operands[1] = gen_rtx_MEM (Pmode, operands[0]);
- emit_move_sequence (operands, mode, scratch_reg);
+ pa_emit_move_sequence (operands, mode, scratch_reg);
/* And add back in the constant part. */
if (const_part != NULL_RTX)
@@ -1984,7 +1990,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
operands[1] = legitimize_pic_address (XEXP (const_mem, 0),
mode, temp);
operands[1] = replace_equiv_address (const_mem, operands[1]);
- emit_move_sequence (operands, mode, temp);
+ pa_emit_move_sequence (operands, mode, temp);
}
else
{
@@ -2058,7 +2064,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
operands[1] = tmp;
}
else if (GET_CODE (operand1) != CONST_INT
- || !cint_ok_for_move (INTVAL (operand1)))
+ || !pa_cint_ok_for_move (INTVAL (operand1)))
{
rtx insn, temp;
rtx op1 = operand1;
@@ -2201,7 +2207,7 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
it will need a link/runtime reloc). */
int
-reloc_needed (tree exp)
+pa_reloc_needed (tree exp)
{
int reloc = 0;
@@ -2213,13 +2219,13 @@ reloc_needed (tree exp)
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
- reloc = reloc_needed (TREE_OPERAND (exp, 0));
- reloc |= reloc_needed (TREE_OPERAND (exp, 1));
+ reloc = pa_reloc_needed (TREE_OPERAND (exp, 0));
+ reloc |= pa_reloc_needed (TREE_OPERAND (exp, 1));
break;
CASE_CONVERT:
case NON_LVALUE_EXPR:
- reloc = reloc_needed (TREE_OPERAND (exp, 0));
+ reloc = pa_reloc_needed (TREE_OPERAND (exp, 0));
break;
case CONSTRUCTOR:
@@ -2229,7 +2235,7 @@ reloc_needed (tree exp)
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), ix, value)
if (value)
- reloc |= reloc_needed (value);
+ reloc |= pa_reloc_needed (value);
}
break;
@@ -2246,7 +2252,7 @@ reloc_needed (tree exp)
/* Return the best assembler insn template
for moving operands[1] into operands[0] as a fullword. */
const char *
-singlemove_string (rtx *operands)
+pa_singlemove_string (rtx *operands)
{
HOST_WIDE_INT intval;
@@ -2277,7 +2283,7 @@ singlemove_string (rtx *operands)
return "ldi %1,%0";
else if ((intval & 0x7ff) == 0)
return "ldil L'%1,%0";
- else if (zdepi_cint_p (intval))
+ else if (pa_zdepi_cint_p (intval))
return "{zdepi %Z1,%0|depwi,z %Z1,%0}";
else
return "ldil L'%1,%0\n\tldo R'%1(%0),%0";
@@ -2326,7 +2332,8 @@ compute_zdepwi_operands (unsigned HOST_WIDE_INT imm, unsigned *op)
/* Compute position (in OP[1]) and width (in OP[2])
useful for copying IMM to a register using the depdi,z
instructions. Store the immediate value to insert in OP[0]. */
-void
+
+static void
compute_zdepdi_operands (unsigned HOST_WIDE_INT imm, unsigned *op)
{
int lsb, len, maxlen;
@@ -2370,7 +2377,7 @@ compute_zdepdi_operands (unsigned HOST_WIDE_INT imm, unsigned *op)
with operands OPERANDS. */
const char *
-output_move_double (rtx *operands)
+pa_output_move_double (rtx *operands)
{
enum { REGOP, OFFSOP, MEMOP, CNSTOP, RNDOP } optype0, optype1;
rtx latehalf[2];
@@ -2612,25 +2619,25 @@ output_move_double (rtx *operands)
/* Do the late half first. */
if (addreg1)
output_asm_insn ("ldo 4(%0),%0", &addreg1);
- output_asm_insn (singlemove_string (latehalf), latehalf);
+ output_asm_insn (pa_singlemove_string (latehalf), latehalf);
/* Then clobber. */
if (addreg1)
output_asm_insn ("ldo -4(%0),%0", &addreg1);
- return singlemove_string (operands);
+ return pa_singlemove_string (operands);
}
/* Now handle register -> register case. */
if (optype0 == REGOP && optype1 == REGOP
&& REGNO (operands[0]) == REGNO (operands[1]) + 1)
{
- output_asm_insn (singlemove_string (latehalf), latehalf);
- return singlemove_string (operands);
+ output_asm_insn (pa_singlemove_string (latehalf), latehalf);
+ return pa_singlemove_string (operands);
}
/* Normal case: do the two words, low-numbered first. */
- output_asm_insn (singlemove_string (operands), operands);
+ output_asm_insn (pa_singlemove_string (operands), operands);
/* Make any unoffsettable addresses point at high-numbered word. */
if (addreg0)
@@ -2639,7 +2646,7 @@ output_move_double (rtx *operands)
output_asm_insn ("ldo 4(%0),%0", &addreg1);
/* Do that word. */
- output_asm_insn (singlemove_string (latehalf), latehalf);
+ output_asm_insn (pa_singlemove_string (latehalf), latehalf);
/* Undo the adds we just did. */
if (addreg0)
@@ -2651,7 +2658,7 @@ output_move_double (rtx *operands)
}
const char *
-output_fp_move_double (rtx *operands)
+pa_output_fp_move_double (rtx *operands)
{
if (FP_REG_P (operands[0]))
{
@@ -2718,7 +2725,7 @@ find_addr_reg (rtx addr)
OPERANDS[6] is another temporary register. */
const char *
-output_block_move (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
+pa_output_block_move (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
{
int align = INTVAL (operands[5]);
unsigned long n_bytes = INTVAL (operands[4]);
@@ -2882,7 +2889,7 @@ compute_movmem_length (rtx insn)
OPERANDS[3] is the alignment safe to use, as a CONST_INT. */
const char *
-output_block_clear (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
+pa_output_block_clear (rtx *operands, int size_is_constant ATTRIBUTE_UNUSED)
{
int align = INTVAL (operands[3]);
unsigned long n_bytes = INTVAL (operands[2]);
@@ -3018,7 +3025,7 @@ compute_clrmem_length (rtx insn)
const char *
-output_and (rtx *operands)
+pa_output_and (rtx *operands)
{
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
{
@@ -3068,7 +3075,7 @@ output_and (rtx *operands)
/* Return a string to perform a bitwise-and of operands[1] with operands[2]
storing the result in operands[0]. */
const char *
-output_64bit_and (rtx *operands)
+pa_output_64bit_and (rtx *operands)
{
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0)
{
@@ -3116,7 +3123,7 @@ output_64bit_and (rtx *operands)
}
const char *
-output_ior (rtx *operands)
+pa_output_ior (rtx *operands)
{
unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
int bs0, bs1, p, len;
@@ -3145,7 +3152,7 @@ output_ior (rtx *operands)
/* Return a string to perform a bitwise-and of operands[1] with operands[2]
storing the result in operands[0]. */
const char *
-output_64bit_ior (rtx *operands)
+pa_output_64bit_ior (rtx *operands)
{
unsigned HOST_WIDE_INT mask = INTVAL (operands[2]);
int bs0, bs1, p, len;
@@ -3193,7 +3200,7 @@ pa_assemble_integer (rtx x, unsigned int size, int aligned_p)
/* Output an ascii string. */
void
-output_ascii (FILE *file, const char *p, int size)
+pa_output_ascii (FILE *file, const char *p, int size)
{
int i;
int chars_output;
@@ -3597,12 +3604,12 @@ set_reg_plus_d (int reg, int base, HOST_WIDE_INT disp, int note)
}
HOST_WIDE_INT
-compute_frame_size (HOST_WIDE_INT size, int *fregs_live)
+pa_compute_frame_size (HOST_WIDE_INT size, int *fregs_live)
{
int freg_saved = 0;
int i, j;
- /* The code in hppa_expand_prologue and hppa_expand_epilogue must
+ /* The code in pa_expand_prologue and pa_expand_epilogue must
be consistent with the rounding and size calculation done here.
Change them at the same time. */
@@ -3698,7 +3705,7 @@ pa_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
ASM_OUTPUT_LABEL (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
fputs ("\t.PROC\n", file);
- /* hppa_expand_prologue does the dirty work now. We just need
+ /* pa_expand_prologue does the dirty work now. We just need
to output the assembler directives which denote the start
of a function. */
fprintf (file, "\t.CALLINFO FRAME=" HOST_WIDE_INT_PRINT_DEC, actual_fsize);
@@ -3741,7 +3748,7 @@ pa_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
}
void
-hppa_expand_prologue (void)
+pa_expand_prologue (void)
{
int merge_sp_adjust_with_store = 0;
HOST_WIDE_INT size = get_frame_size ();
@@ -3754,13 +3761,13 @@ hppa_expand_prologue (void)
save_fregs = 0;
/* Compute total size for frame pointer, filler, locals and rounding to
- the next word boundary. Similar code appears in compute_frame_size
+ the next word boundary. Similar code appears in pa_compute_frame_size
and must be changed in tandem with this code. */
local_fsize = (size + UNITS_PER_WORD - 1) & ~(UNITS_PER_WORD - 1);
if (local_fsize || frame_pointer_needed)
local_fsize += STARTING_FRAME_OFFSET;
- actual_fsize = compute_frame_size (size, &save_fregs);
+ actual_fsize = pa_compute_frame_size (size, &save_fregs);
if (flag_stack_usage_info)
current_function_static_stack_size = actual_fsize;
@@ -4104,7 +4111,7 @@ pa_output_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
last_address = 0;
- /* hppa_expand_epilogue does the dirty work now. We just need
+ /* pa_expand_epilogue does the dirty work now. We just need
to output the assembler directives which denote the end
of a function.
@@ -4157,7 +4164,7 @@ pa_output_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
}
void
-hppa_expand_epilogue (void)
+pa_expand_epilogue (void)
{
rtx tmpreg;
HOST_WIDE_INT offset;
@@ -4349,7 +4356,7 @@ pa_can_use_return_insn (void)
if (crtl->profile)
return false;
- return compute_frame_size (get_frame_size (), 0) == 0;
+ return pa_compute_frame_size (get_frame_size (), 0) == 0;
}
rtx
@@ -4489,7 +4496,7 @@ hppa_profile_hook (int label_no)
return location is in a shared library. */
rtx
-return_addr_rtx (int count, rtx frameaddr)
+pa_return_addr_rtx (int count, rtx frameaddr)
{
rtx label;
rtx rp;
@@ -4558,7 +4565,7 @@ return_addr_rtx (int count, rtx frameaddr)
}
void
-emit_bcond_fp (rtx operands[])
+pa_emit_bcond_fp (rtx operands[])
{
enum rtx_code code = GET_CODE (operands[0]);
rtx operand0 = operands[1];
@@ -4914,7 +4921,7 @@ pa_print_operand_punct_valid_p (unsigned char code)
For `%' followed by punctuation, CODE is the punctuation and X is null. */
void
-print_operand (FILE *file, rtx x, int code)
+pa_print_operand (FILE *file, rtx x, int code)
{
switch (code)
{
@@ -4964,7 +4971,7 @@ print_operand (FILE *file, rtx x, int code)
xoperands[0] = XEXP (XEXP (x, 0), 0);
xoperands[1] = XVECEXP (XEXP (XEXP (x, 0), 1), 0, 0);
- output_global_address (file, xoperands[1], 0);
+ pa_output_global_address (file, xoperands[1], 0);
fprintf (file, "(%s)", reg_names [REGNO (xoperands[0])]);
return;
}
@@ -5189,10 +5196,10 @@ print_operand (FILE *file, rtx x, int code)
}
return;
case 'G':
- output_global_address (file, x, 0);
+ pa_output_global_address (file, x, 0);
return;
case 'H':
- output_global_address (file, x, 1);
+ pa_output_global_address (file, x, 1);
return;
case 0: /* Don't do anything special */
break;
@@ -5283,7 +5290,7 @@ print_operand (FILE *file, rtx x, int code)
/* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */
void
-output_global_address (FILE *file, rtx x, int round_constant)
+pa_output_global_address (FILE *file, rtx x, int round_constant)
{
/* Imagine (high (const (plus ...))). */
@@ -5472,7 +5479,7 @@ pa_hpux64_hpas_file_start (void)
label. If an entry for SYMBOL is not found, a new entry is created. */
rtx
-get_deferred_plabel (rtx symbol)
+pa_get_deferred_plabel (rtx symbol)
{
const char *fname = XSTR (symbol, 0);
size_t i;
@@ -5605,16 +5612,16 @@ import_milli (enum millicodes code)
the proper registers. */
const char *
-output_mul_insn (int unsignedp ATTRIBUTE_UNUSED, rtx insn)
+pa_output_mul_insn (int unsignedp ATTRIBUTE_UNUSED, rtx insn)
{
import_milli (mulI);
- return output_millicode_call (insn, gen_rtx_SYMBOL_REF (Pmode, "$$mulI"));
+ return pa_output_millicode_call (insn, gen_rtx_SYMBOL_REF (Pmode, "$$mulI"));
}
/* Emit the rtl for doing a division by a constant. */
/* Do magic division millicodes exist for this value? */
-const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1};
+const int pa_magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1};
/* We'll use an array to keep track of the magic millicodes and
whether or not we've used them already. [n][0] is signed, [n][1] is
@@ -5623,12 +5630,12 @@ const int magic_milli[]= {0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1};
static int div_milli[16][2];
int
-emit_hpdiv_const (rtx *operands, int unsignedp)
+pa_emit_hpdiv_const (rtx *operands, int unsignedp)
{
if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) < 16
- && magic_milli[INTVAL (operands[2])])
+ && pa_magic_milli[INTVAL (operands[2])])
{
rtx ret = gen_rtx_REG (SImode, TARGET_64BIT ? 2 : 31);
@@ -5653,7 +5660,7 @@ emit_hpdiv_const (rtx *operands, int unsignedp)
}
const char *
-output_div_insn (rtx *operands, int unsignedp, rtx insn)
+pa_output_div_insn (rtx *operands, int unsignedp, rtx insn)
{
int divisor;
@@ -5675,15 +5682,15 @@ output_div_insn (rtx *operands, int unsignedp, rtx insn)
{
sprintf (buf, "$$divU_" HOST_WIDE_INT_PRINT_DEC,
INTVAL (operands[0]));
- return output_millicode_call (insn,
- gen_rtx_SYMBOL_REF (SImode, buf));
+ return pa_output_millicode_call (insn,
+ gen_rtx_SYMBOL_REF (SImode, buf));
}
else
{
sprintf (buf, "$$divI_" HOST_WIDE_INT_PRINT_DEC,
INTVAL (operands[0]));
- return output_millicode_call (insn,
- gen_rtx_SYMBOL_REF (SImode, buf));
+ return pa_output_millicode_call (insn,
+ gen_rtx_SYMBOL_REF (SImode, buf));
}
}
/* Divisor isn't a special constant. */
@@ -5692,13 +5699,13 @@ output_div_insn (rtx *operands, int unsignedp, rtx insn)
if (unsignedp)
{
import_milli (divU);
- return output_millicode_call (insn,
+ return pa_output_millicode_call (insn,
gen_rtx_SYMBOL_REF (SImode, "$$divU"));
}
else
{
import_milli (divI);
- return output_millicode_call (insn,
+ return pa_output_millicode_call (insn,
gen_rtx_SYMBOL_REF (SImode, "$$divI"));
}
}
@@ -5707,24 +5714,24 @@ output_div_insn (rtx *operands, int unsignedp, rtx insn)
/* Output a $$rem millicode to do mod. */
const char *
-output_mod_insn (int unsignedp, rtx insn)
+pa_output_mod_insn (int unsignedp, rtx insn)
{
if (unsignedp)
{
import_milli (remU);
- return output_millicode_call (insn,
- gen_rtx_SYMBOL_REF (SImode, "$$remU"));
+ return pa_output_millicode_call (insn,
+ gen_rtx_SYMBOL_REF (SImode, "$$remU"));
}
else
{
import_milli (remI);
- return output_millicode_call (insn,
- gen_rtx_SYMBOL_REF (SImode, "$$remI"));
+ return pa_output_millicode_call (insn,
+ gen_rtx_SYMBOL_REF (SImode, "$$remI"));
}
}
void
-output_arg_descriptor (rtx call_insn)
+pa_output_arg_descriptor (rtx call_insn)
{
const char *arg_regs[4];
enum machine_mode arg_mode;
@@ -5842,7 +5849,7 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
/* Secondary reloads of symbolic operands require %r1 as a scratch
register when we're generating PIC code and when the operand isn't
readonly. */
- if (symbolic_expression_p (x))
+ if (pa_symbolic_expression_p (x))
{
if (GET_CODE (x) == HIGH)
x = XEXP (x, 0);
@@ -5864,7 +5871,7 @@ pa_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
/* In order to allow 14-bit displacements in integer loads and stores,
we need to prevent reload from generating out of range integer mode
loads and stores to the floating point registers. Previously, we
- used to call for a secondary reload and have emit_move_sequence()
+ used to call for a secondary reload and have pa_emit_move_sequence()
fix the instruction sequence. However, reload occasionally wouldn't
generate the reload and we would end up with an invalid REG+D memory
address. So, now we use an intermediate general register for most
@@ -5989,7 +5996,7 @@ pa_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
}
enum direction
-function_arg_padding (enum machine_mode mode, const_tree type)
+pa_function_arg_padding (enum machine_mode mode, const_tree type)
{
if (mode == BLKmode
|| (TARGET_64BIT
@@ -6303,7 +6310,7 @@ use_skip_p (rtx insn)
parameters. */
const char *
-output_cbranch (rtx *operands, int negated, rtx insn)
+pa_output_cbranch (rtx *operands, int negated, rtx insn)
{
static char buf[100];
bool useskip;
@@ -6429,7 +6436,7 @@ output_cbranch (rtx *operands, int negated, rtx insn)
default:
/* The reversed conditional branch must branch over one additional
instruction if the delay slot is filled and needs to be extracted
- by output_lbranch. If the delay slot is empty or this is a
+ by pa_output_lbranch. If the delay slot is empty or this is a
nullified forward branch, the instruction after the reversed
condition branch must be nullified. */
if (dbr_sequence_length () == 0
@@ -6491,7 +6498,7 @@ output_cbranch (rtx *operands, int negated, rtx insn)
}
output_asm_insn (buf, operands);
- return output_lbranch (operands[0], insn, xdelay);
+ return pa_output_lbranch (operands[0], insn, xdelay);
}
return buf;
}
@@ -6514,7 +6521,7 @@ output_cbranch (rtx *operands, int negated, rtx insn)
bytes for the portable runtime, non-PIC and PIC cases, respectively. */
const char *
-output_lbranch (rtx dest, rtx insn, int xdelay)
+pa_output_lbranch (rtx dest, rtx insn, int xdelay)
{
rtx xoperands[2];
@@ -6629,7 +6636,7 @@ output_lbranch (rtx dest, rtx insn, int xdelay)
above. it returns the appropriate output template to emit the branch. */
const char *
-output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
+pa_output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
{
static char buf[100];
bool useskip;
@@ -6771,7 +6778,7 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
default:
/* The reversed conditional branch must branch over one additional
instruction if the delay slot is filled and needs to be extracted
- by output_lbranch. If the delay slot is empty or this is a
+ by pa_output_lbranch. If the delay slot is empty or this is a
nullified forward branch, the instruction after the reversed
condition branch must be nullified. */
if (dbr_sequence_length () == 0
@@ -6801,8 +6808,8 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
else
strcat (buf, " %0,%1,.+%4");
output_asm_insn (buf, operands);
- return output_lbranch (negated ? operands[3] : operands[2],
- insn, xdelay);
+ return pa_output_lbranch (negated ? operands[3] : operands[2],
+ insn, xdelay);
}
return buf;
}
@@ -6814,7 +6821,8 @@ output_bb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
branch. */
const char *
-output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
+pa_output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn,
+ int which)
{
static char buf[100];
bool useskip;
@@ -6955,7 +6963,7 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
default:
/* The reversed conditional branch must branch over one additional
instruction if the delay slot is filled and needs to be extracted
- by output_lbranch. If the delay slot is empty or this is a
+ by pa_output_lbranch. If the delay slot is empty or this is a
nullified forward branch, the instruction after the reversed
condition branch must be nullified. */
if (dbr_sequence_length () == 0
@@ -6985,8 +6993,8 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
else
strcat (buf, " {%0,.+%4|%0,%%sar,.+%4}");
output_asm_insn (buf, operands);
- return output_lbranch (negated ? operands[3] : operands[2],
- insn, xdelay);
+ return pa_output_lbranch (negated ? operands[3] : operands[2],
+ insn, xdelay);
}
return buf;
}
@@ -6996,7 +7004,7 @@ output_bvb (rtx *operands ATTRIBUTE_UNUSED, int negated, rtx insn, int which)
Note it may perform some output operations on its own before
returning the final output string. */
const char *
-output_dbra (rtx *operands, rtx insn, int which_alternative)
+pa_output_dbra (rtx *operands, rtx insn, int which_alternative)
{
int length = get_attr_length (insn);
@@ -7075,7 +7083,7 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
default:
/* The reversed conditional branch must branch over one additional
instruction if the delay slot is filled and needs to be extracted
- by output_lbranch. If the delay slot is empty or this is a
+ by pa_output_lbranch. If the delay slot is empty or this is a
nullified forward branch, the instruction after the reversed
condition branch must be nullified. */
if (dbr_sequence_length () == 0
@@ -7096,7 +7104,7 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
else
output_asm_insn ("addib,%N2 %1,%0,.+%4", operands);
- return output_lbranch (operands[3], insn, xdelay);
+ return pa_output_lbranch (operands[3], insn, xdelay);
}
}
@@ -7118,7 +7126,7 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
operands[5] = GEN_INT (length - 16);
output_asm_insn ("{comb|cmpb},%B2 %%r0,%4,.+%5", operands);
output_asm_insn ("{fldws|fldw} -16(%%r30),%0", operands);
- return output_lbranch (operands[3], insn, 0);
+ return pa_output_lbranch (operands[3], insn, 0);
}
}
/* Deal with gross reload from memory case. */
@@ -7135,7 +7143,7 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
{
operands[5] = GEN_INT (length - 4);
output_asm_insn ("addib,%N2 %1,%4,.+%5\n\tstw %4,%0", operands);
- return output_lbranch (operands[3], insn, 0);
+ return pa_output_lbranch (operands[3], insn, 0);
}
}
}
@@ -7145,7 +7153,7 @@ output_dbra (rtx *operands, rtx insn, int which_alternative)
Note it may perform some output operations on its own before
returning the final output string. */
const char *
-output_movb (rtx *operands, rtx insn, int which_alternative,
+pa_output_movb (rtx *operands, rtx insn, int which_alternative,
int reverse_comparison)
{
int length = get_attr_length (insn);
@@ -7226,7 +7234,7 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
default:
/* The reversed conditional branch must branch over one additional
instruction if the delay slot is filled and needs to be extracted
- by output_lbranch. If the delay slot is empty or this is a
+ by pa_output_lbranch. If the delay slot is empty or this is a
nullified forward branch, the instruction after the reversed
condition branch must be nullified. */
if (dbr_sequence_length () == 0
@@ -7247,7 +7255,7 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
else
output_asm_insn ("movb,%N2 %1,%0,.+%4", operands);
- return output_lbranch (operands[3], insn, xdelay);
+ return pa_output_lbranch (operands[3], insn, xdelay);
}
}
/* Deal with gross reload for FP destination register case. */
@@ -7266,7 +7274,7 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
operands[4] = GEN_INT (length - 4);
output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4", operands);
output_asm_insn ("{fldws|fldw} -16(%%r30),%0", operands);
- return output_lbranch (operands[3], insn, 0);
+ return pa_output_lbranch (operands[3], insn, 0);
}
}
/* Deal with gross reload from memory case. */
@@ -7283,7 +7291,7 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
operands[4] = GEN_INT (length);
output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4\n\tstw %1,%0",
operands);
- return output_lbranch (operands[3], insn, 0);
+ return pa_output_lbranch (operands[3], insn, 0);
}
}
/* Handle SAR as a destination. */
@@ -7298,7 +7306,7 @@ output_movb (rtx *operands, rtx insn, int which_alternative,
operands[4] = GEN_INT (length);
output_asm_insn ("{comb|cmpb},%B2 %%r0,%1,.+%4\n\tmtsar %r1",
operands);
- return output_lbranch (operands[3], insn, 0);
+ return pa_output_lbranch (operands[3], insn, 0);
}
}
}
@@ -7380,12 +7388,12 @@ length_fp_args (rtx insn)
}
/* Return the attribute length for the millicode call instruction INSN.
- The length must match the code generated by output_millicode_call.
+ The length must match the code generated by pa_output_millicode_call.
We include the delay slot in the returned length as it is better to
over estimate the length than to under estimate it. */
int
-attr_length_millicode_call (rtx insn)
+pa_attr_length_millicode_call (rtx insn)
{
unsigned long distance = -1;
unsigned long total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
@@ -7424,7 +7432,7 @@ attr_length_millicode_call (rtx insn)
CALL_DEST is the routine we are calling. */
const char *
-output_millicode_call (rtx insn, rtx call_dest)
+pa_output_millicode_call (rtx insn, rtx call_dest)
{
int attr_length = get_attr_length (insn);
int seq_length = dbr_sequence_length ();
@@ -7572,7 +7580,7 @@ output_millicode_call (rtx insn, rtx call_dest)
/* Return the attribute length of the call instruction INSN. The SIBCALL
flag indicates whether INSN is a regular call or a sibling call. The
length returned must be longer than the code actually generated by
- output_call. Since branch shortening is done before delay branch
+ pa_output_call. Since branch shortening is done before delay branch
sequencing, there is no way to determine whether or not the delay
slot will be filled during branch shortening. Even when the delay
slot is filled, we may have to add a nop if the delay slot contains
@@ -7583,7 +7591,7 @@ output_millicode_call (rtx insn, rtx call_dest)
these sequences. */
int
-attr_length_call (rtx insn, int sibcall)
+pa_attr_length_call (rtx insn, int sibcall)
{
int local_call;
rtx call, call_dest;
@@ -7673,7 +7681,7 @@ attr_length_call (rtx insn, int sibcall)
CALL_DEST is the routine we are calling. */
const char *
-output_call (rtx insn, rtx call_dest, int sibcall)
+pa_output_call (rtx insn, rtx call_dest, int sibcall)
{
int delay_insn_deleted = 0;
int delay_slot_filled = 0;
@@ -7687,7 +7695,7 @@ output_call (rtx insn, rtx call_dest, int sibcall)
/* Handle the common case where we're sure that the branch will reach
the beginning of the "$CODE$" subspace. This is the beginning of
the current function if we are in a named section. */
- if (!TARGET_LONG_CALLS && attr_length_call (insn, sibcall) == 8)
+ if (!TARGET_LONG_CALLS && pa_attr_length_call (insn, sibcall) == 8)
{
xoperands[1] = gen_rtx_REG (word_mode, sibcall ? 0 : 2);
output_asm_insn ("{bl|b,l} %0,%1", xoperands);
@@ -7699,7 +7707,7 @@ output_call (rtx insn, rtx call_dest, int sibcall)
/* ??? As far as I can tell, the HP linker doesn't support the
long pc-relative sequence described in the 64-bit runtime
architecture. So, we use a slightly longer indirect call. */
- xoperands[0] = get_deferred_plabel (call_dest);
+ xoperands[0] = pa_get_deferred_plabel (call_dest);
xoperands[1] = gen_label_rtx ();
/* If this isn't a sibcall, we put the load of %r27 into the
@@ -7825,7 +7833,7 @@ output_call (rtx insn, rtx call_dest, int sibcall)
essentially an inline implementation of $$dyncall.
We don't actually try to call $$dyncall as this is
as difficult as calling the function itself. */
- xoperands[0] = get_deferred_plabel (call_dest);
+ xoperands[0] = pa_get_deferred_plabel (call_dest);
xoperands[1] = gen_label_rtx ();
/* Since the call is indirect, FP arguments in registers
@@ -7962,7 +7970,7 @@ output_call (rtx insn, rtx call_dest, int sibcall)
the sequence itself. */
int
-attr_length_indirect_call (rtx insn)
+pa_attr_length_indirect_call (rtx insn)
{
unsigned long distance = -1;
unsigned long total = IN_NAMED_SECTION_P (cfun->decl) ? 0 : total_code_bytes;
@@ -7994,7 +8002,7 @@ attr_length_indirect_call (rtx insn)
}
const char *
-output_indirect_call (rtx insn, rtx call_dest)
+pa_output_indirect_call (rtx insn, rtx call_dest)
{
rtx xoperands[1];
@@ -8015,7 +8023,7 @@ output_indirect_call (rtx insn, rtx call_dest)
No need to check target flags as the length uniquely identifies
the remaining cases. */
- if (attr_length_indirect_call (insn) == 8)
+ if (pa_attr_length_indirect_call (insn) == 8)
{
/* The HP linker sometimes substitutes a BLE for BL/B,L calls to
$$dyncall. Since BLE uses %r31 as the link register, the 22-bit
@@ -8028,11 +8036,11 @@ output_indirect_call (rtx insn, rtx call_dest)
/* Long millicode call, but we are not generating PIC or portable runtime
code. */
- if (attr_length_indirect_call (insn) == 12)
+ if (pa_attr_length_indirect_call (insn) == 12)
return ".CALL\tARGW0=GR\n\tldil L'$$dyncall,%%r2\n\tble R'$$dyncall(%%sr4,%%r2)\n\tcopy %%r31,%%r2";
/* Long millicode call for portable runtime. */
- if (attr_length_indirect_call (insn) == 20)
+ if (pa_attr_length_indirect_call (insn) == 20)
return "ldil L'$$dyncall,%%r31\n\tldo R'$$dyncall(%%r31),%%r31\n\tblr %%r0,%%r2\n\tbv,n %%r0(%%r31)\n\tnop";
/* We need a long PIC call to $$dyncall. */
@@ -8057,28 +8065,13 @@ output_indirect_call (rtx insn, rtx call_dest)
return "";
}
-/* Return the total length of the save and restore instructions needed for
- the data linkage table pointer (i.e., the PIC register) across the call
- instruction INSN. No-return calls do not require a save and restore.
- In addition, we may be able to avoid the save and restore for calls
- within the same translation unit. */
-
-int
-attr_length_save_restore_dltp (rtx insn)
-{
- if (find_reg_note (insn, REG_NORETURN, NULL_RTX))
- return 0;
-
- return 8;
-}
-
/* In HPUX 8.0's shared library scheme, special relocations are needed
for function labels if they might be passed to a function
in a shared library (because shared libraries don't live in code
space), and special magic is needed to construct their address. */
void
-hppa_encode_label (rtx sym)
+pa_encode_label (rtx sym)
{
const char *str = XSTR (sym, 0);
int len = strlen (str) + 1;
@@ -8106,7 +8099,7 @@ pa_encode_section_info (tree decl, rtx rtl, int first)
{
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
if (TREE_CODE (decl) == FUNCTION_DECL)
- hppa_encode_label (XEXP (rtl, 0));
+ pa_encode_label (XEXP (rtl, 0));
}
else if (old_referenced)
SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= old_referenced;
@@ -8126,7 +8119,7 @@ pa_strip_name_encoding (const char *str)
with a constant. Used to keep certain patterns from matching
during instruction combination. */
int
-is_function_label_plus_const (rtx op)
+pa_is_function_label_plus_const (rtx op)
{
/* Strip off any CONST. */
if (GET_CODE (op) == CONST)
@@ -8422,7 +8415,7 @@ pa_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
single subspace mode and the call is not indirect. As far as I know,
there is no operating system support for the multiple subspace mode.
It might be possible to support indirect calls if we didn't use
- $$dyncall (see the indirect sequence generated in output_call). */
+ $$dyncall (see the indirect sequence generated in pa_output_call). */
if (TARGET_ELF32)
return (decl != NULL_TREE);
@@ -8454,7 +8447,7 @@ pa_commutative_p (const_rtx x, int outer_code)
/* Returns 1 if the 6 operands specified in OPERANDS are suitable for
use in fmpyadd instructions. */
int
-fmpyaddoperands (rtx *operands)
+pa_fmpyaddoperands (rtx *operands)
{
enum machine_mode mode = GET_MODE (operands[0]);
@@ -8514,7 +8507,7 @@ static void
pa_asm_out_constructor (rtx symbol, int priority)
{
if (!function_label_operand (symbol, VOIDmode))
- hppa_encode_label (symbol);
+ pa_encode_label (symbol);
#ifdef CTORS_SECTION_ASM_OP
default_ctor_section_asm_out_constructor (symbol, priority);
@@ -8531,7 +8524,7 @@ static void
pa_asm_out_destructor (rtx symbol, int priority)
{
if (!function_label_operand (symbol, VOIDmode))
- hppa_encode_label (symbol);
+ pa_encode_label (symbol);
#ifdef DTORS_SECTION_ASM_OP
default_dtor_section_asm_out_destructor (symbol, priority);
@@ -8632,7 +8625,7 @@ pa_asm_output_aligned_local (FILE *stream,
/* Returns 1 if the 6 operands specified in OPERANDS are suitable for
use in fmpysub instructions. */
int
-fmpysuboperands (rtx *operands)
+pa_fmpysuboperands (rtx *operands)
{
enum machine_mode mode = GET_MODE (operands[0]);
@@ -8688,7 +8681,7 @@ fmpysuboperands (rtx *operands)
/* Return 1 if the given constant is 2, 4, or 8. These are the valid
constants for shadd instructions. */
int
-shadd_constant_p (int val)
+pa_shadd_constant_p (int val)
{
if (val == 2 || val == 4 || val == 8)
return 1;
@@ -8722,7 +8715,7 @@ forward_branch_p (rtx insn)
/* Return 1 if INSN is in the delay slot of a call instruction. */
int
-jump_in_call_delay (rtx insn)
+pa_jump_in_call_delay (rtx insn)
{
if (GET_CODE (insn) != JUMP_INSN)
@@ -8745,7 +8738,7 @@ jump_in_call_delay (rtx insn)
/* Output an unconditional move and branch insn. */
const char *
-output_parallel_movb (rtx *operands, rtx insn)
+pa_output_parallel_movb (rtx *operands, rtx insn)
{
int length = get_attr_length (insn);
@@ -8779,13 +8772,13 @@ output_parallel_movb (rtx *operands, rtx insn)
output_asm_insn ("ldi %1,%0", operands);
else
output_asm_insn ("copy %1,%0", operands);
- return output_lbranch (operands[2], insn, 1);
+ return pa_output_lbranch (operands[2], insn, 1);
}
/* Output an unconditional add and branch insn. */
const char *
-output_parallel_addb (rtx *operands, rtx insn)
+pa_output_parallel_addb (rtx *operands, rtx insn)
{
int length = get_attr_length (insn);
@@ -8811,7 +8804,7 @@ output_parallel_addb (rtx *operands, rtx insn)
}
output_asm_insn ("add%I1 %1,%0,%0", operands);
- return output_lbranch (operands[3], insn, 1);
+ return pa_output_lbranch (operands[3], insn, 1);
}
/* Return nonzero if INSN (a jump insn) immediately follows a call
@@ -8820,7 +8813,7 @@ output_parallel_addb (rtx *operands, rtx insn)
the delay slot of the call. */
int
-following_call (rtx insn)
+pa_following_call (rtx insn)
{
if (! TARGET_JUMP_IN_DELAY)
return 0;
@@ -9283,7 +9276,7 @@ pa_can_combine_p (rtx new_rtx, rtx anchor, rtx floater, int reversed, rtx dest,
filter out things it will not accept -- SEQUENCE, USE and CLOBBER insns
in particular. */
int
-insn_refs_are_delayed (rtx insn)
+pa_insn_refs_are_delayed (rtx insn)
{
return ((GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) != SEQUENCE
@@ -10186,7 +10179,7 @@ pa_initial_elimination_offset (int from, int to)
if ((from == HARD_FRAME_POINTER_REGNUM || from == FRAME_POINTER_REGNUM)
&& to == STACK_POINTER_REGNUM)
- offset = -compute_frame_size (get_frame_size (), 0);
+ offset = -pa_compute_frame_size (get_frame_size (), 0);
else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
offset = 0;
else
@@ -10271,6 +10264,16 @@ pa_legitimate_constant_p (enum machine_mode mode, rtx x)
if (!NEW_HP_ASSEMBLER && !TARGET_GAS && GET_CODE (x) == LABEL_REF)
return false;
+ /* TLS_MODEL_GLOBAL_DYNAMIC and TLS_MODEL_LOCAL_DYNAMIC are not
+ legitimate constants. */
+ if (PA_SYMBOL_REF_TLS_P (x))
+ {
+ enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
+
+ if (model == TLS_MODEL_GLOBAL_DYNAMIC || model == TLS_MODEL_LOCAL_DYNAMIC)
+ return false;
+ }
+
if (TARGET_64BIT && GET_CODE (x) == CONST_DOUBLE)
return false;
@@ -10280,7 +10283,7 @@ pa_legitimate_constant_p (enum machine_mode mode, rtx x)
&& !reload_in_progress
&& !reload_completed
&& !LEGITIMATE_64BIT_CONST_INT_P (INTVAL (x))
- && !cint_ok_for_move (INTVAL (x)))
+ && !pa_cint_ok_for_move (INTVAL (x)))
return false;
if (function_label_operand (x, mode))
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index dc2dab1ee16..2f1295b0fbf 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -162,11 +162,11 @@ extern unsigned long total_code_bytes;
the stack pointer at the function's entry. Yuk! */
#define DEBUGGER_AUTO_OFFSET(X) \
((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) \
- + (frame_pointer_needed ? 0 : compute_frame_size (get_frame_size (), 0)))
+ + (frame_pointer_needed ? 0 : pa_compute_frame_size (get_frame_size (), 0)))
#define DEBUGGER_ARG_OFFSET(OFFSET, X) \
((GET_CODE (X) == PLUS ? OFFSET : 0) \
- + (frame_pointer_needed ? 0 : compute_frame_size (get_frame_size (), 0)))
+ + (frame_pointer_needed ? 0 : pa_compute_frame_size (get_frame_size (), 0)))
#define TARGET_CPU_CPP_BUILTINS() \
do { \
@@ -457,7 +457,7 @@ extern rtx hppa_pic_save_rtx (void);
{ \
fputs (integer_asm_op (SIZE, FALSE), FILE); \
if ((ENCODING) & DW_EH_PE_indirect) \
- output_addr_const (FILE, get_deferred_plabel (ADDR)); \
+ output_addr_const (FILE, pa_get_deferred_plabel (ADDR)); \
else \
assemble_name (FILE, XSTR ((ADDR), 0)); \
fputs ("+8-$PIC_pcrel$0", FILE); \
@@ -661,7 +661,8 @@ struct hppa_args {int words, nargs_prototype, incoming, indirect; };
/* If defined, a C expression which determines whether, and in which
direction, to pad out an argument with extra space. */
-#define FUNCTION_ARG_PADDING(MODE, TYPE) function_arg_padding ((MODE), (TYPE))
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+ pa_function_arg_padding ((MODE), (TYPE))
/* Specify padding for the last element of a block move between registers
and memory.
@@ -673,7 +674,7 @@ struct hppa_args {int words, nargs_prototype, incoming, indirect; };
so that there is only one element. This allows the object to be
correctly padded. */
#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- function_arg_padding ((MODE), (TYPE))
+ pa_function_arg_padding ((MODE), (TYPE))
/* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than
@@ -793,7 +794,8 @@ extern int may_call_alloca;
|| (GET_CODE (X) == SYMBOL_REF && !SYMBOL_REF_TLS_MODEL (X)) \
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
|| GET_CODE (X) == HIGH) \
- && (reload_in_progress || reload_completed || ! symbolic_expression_p (X)))
+ && (reload_in_progress || reload_completed \
+ || ! pa_symbolic_expression_p (X)))
/* A C expression that is nonzero if we are using the new HP assembler. */
@@ -926,7 +928,7 @@ extern int may_call_alloca;
the REG_POINTER lossage can be fixed, it seems better canonicalize.
We initially break out scaled indexed addresses in canonical order
- in emit_move_sequence. LEGITIMIZE_ADDRESS also canonicalizes
+ in pa_emit_move_sequence. LEGITIMIZE_ADDRESS also canonicalizes
scaled indexed addresses during RTL generation. However, fold_rtx
has its own opinion on how the operands of a PLUS should be ordered.
If one of the operands is equivalent to a constant, it will make
@@ -1183,7 +1185,7 @@ do { \
(TREE_CODE (DECL) == FUNCTION_DECL \
|| (TREE_CODE (DECL) == VAR_DECL \
&& TREE_READONLY (DECL) && ! TREE_SIDE_EFFECTS (DECL) \
- && (! DECL_INITIAL (DECL) || ! reloc_needed (DECL_INITIAL (DECL))) \
+ && (! DECL_INITIAL (DECL) || ! pa_reloc_needed (DECL_INITIAL (DECL))) \
&& !flag_pic) \
|| CONSTANT_CLASS_P (DECL))
@@ -1290,7 +1292,7 @@ do { \
get_attr_type will try to recognize the given insn, so make sure to
filter out things it will not accept -- SEQUENCE, USE and CLOBBER insns
in particular. */
-#define INSN_REFERENCES_ARE_DELAYED(X) (insn_refs_are_delayed (X))
+#define INSN_REFERENCES_ARE_DELAYED(X) (pa_insn_refs_are_delayed (X))
/* Control the assembler format that we output. */
@@ -1368,7 +1370,7 @@ do { \
#define TARGET_ASM_GLOBALIZE_LABEL pa_globalize_label
#define ASM_OUTPUT_ASCII(FILE, P, SIZE) \
- output_ascii ((FILE), (P), (SIZE))
+ pa_output_ascii ((FILE), (P), (SIZE))
/* Jump tables are always placed in the text section. Technically, it
is possible to put them in the readonly data section when -mbig-switch
@@ -1452,7 +1454,7 @@ do { \
M modifier to handle preincrement addressing for memory refs.
F modifier to handle preincrement addressing for fp memory refs */
-#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
+#define PRINT_OPERAND(FILE, X, CODE) pa_print_operand (FILE, X, CODE)
/* Print a memory address as an operand to reference that memory location. */
@@ -1476,7 +1478,7 @@ do { \
fputs ("RR'", FILE); \
else \
fputs ("RT'", FILE); \
- output_global_address (FILE, XEXP (addr, 1), 0); \
+ pa_output_global_address (FILE, XEXP (addr, 1), 0); \
fputs ("(", FILE); \
output_operand (XEXP (addr, 0), 0); \
fputs (")", FILE); \
@@ -1492,7 +1494,7 @@ do { \
/* Find the return address associated with the frame given by
FRAMEADDR. */
#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) \
- (return_addr_rtx (COUNT, FRAMEADDR))
+ (pa_return_addr_rtx (COUNT, FRAMEADDR))
/* Used to mask out junk bits from the return address, such as
processor state, interrupt status, condition codes and the like. */
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index 8a170b97a08..1be614c3241 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -180,7 +180,7 @@
(attr_flag "backward"))])
(define_delay (and (eq_attr "type" "uncond_branch")
- (not (match_test "following_call (insn)")))
+ (not (match_test "pa_following_call (insn)")))
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
;; Memory. Disregarding Cache misses, the Mustang memory times are:
@@ -286,14 +286,14 @@
;; We have a bypass for all computations in the FP unit which feed an
;; FP store as long as the sizes are the same.
-(define_bypass 2 "W1,W2" "W10,W11" "hppa_fpstore_bypass_p")
-(define_bypass 9 "W3" "W10,W11" "hppa_fpstore_bypass_p")
-(define_bypass 11 "W4" "W10,W11" "hppa_fpstore_bypass_p")
-(define_bypass 13 "W5" "W10,W11" "hppa_fpstore_bypass_p")
-(define_bypass 17 "W6" "W10,W11" "hppa_fpstore_bypass_p")
+(define_bypass 2 "W1,W2" "W10,W11" "pa_fpstore_bypass_p")
+(define_bypass 9 "W3" "W10,W11" "pa_fpstore_bypass_p")
+(define_bypass 11 "W4" "W10,W11" "pa_fpstore_bypass_p")
+(define_bypass 13 "W5" "W10,W11" "pa_fpstore_bypass_p")
+(define_bypass 17 "W6" "W10,W11" "pa_fpstore_bypass_p")
;; We have an "anti-bypass" for FP loads which feed an FP store.
-(define_bypass 4 "W8,W12" "W10,W11" "hppa_fpstore_bypass_p")
+(define_bypass 4 "W8,W12" "W10,W11" "pa_fpstore_bypass_p")
;; Function units for the 7100 and 7150. The 7100/7150 can dual-issue
;; floating point computations with non-floating point computations (fp loads
@@ -382,12 +382,12 @@
;; We have a bypass for all computations in the FP unit which feed an
;; FP store as long as the sizes are the same.
-(define_bypass 1 "X0" "X6,X7" "hppa_fpstore_bypass_p")
-(define_bypass 7 "X1" "X6,X7" "hppa_fpstore_bypass_p")
-(define_bypass 14 "X2" "X6,X7" "hppa_fpstore_bypass_p")
+(define_bypass 1 "X0" "X6,X7" "pa_fpstore_bypass_p")
+(define_bypass 7 "X1" "X6,X7" "pa_fpstore_bypass_p")
+(define_bypass 14 "X2" "X6,X7" "pa_fpstore_bypass_p")
;; We have an "anti-bypass" for FP loads which feed an FP store.
-(define_bypass 3 "X4,X8" "X6,X7" "hppa_fpstore_bypass_p")
+(define_bypass 3 "X4,X8" "X6,X7" "pa_fpstore_bypass_p")
;; The 7100LC has three floating-point units: ALU, MUL, and DIV.
;; There's no value in modeling the ALU and MUL separately though
@@ -543,7 +543,7 @@
"i1_7100lc,i1_7100lc+mem_7100lc")
;; We have an "anti-bypass" for FP loads which feed an FP store.
-(define_bypass 3 "Y3,Y7,Y13,Y17" "Y5,Y6,Y11,Y12,Y15,Y16" "hppa_fpstore_bypass_p")
+(define_bypass 3 "Y3,Y7,Y13,Y17" "Y5,Y6,Y11,Y12,Y15,Y16" "pa_fpstore_bypass_p")
;; Scheduling for the PA8000 is somewhat different than scheduling for a
;; traditional architecture.
@@ -1301,7 +1301,7 @@
""
"
{
- emit_bcond_fp (operands);
+ pa_emit_bcond_fp (operands);
DONE;
}")
@@ -1316,7 +1316,7 @@
""
"
{
- emit_bcond_fp (operands);
+ pa_emit_bcond_fp (operands);
DONE;
}")
@@ -1336,7 +1336,7 @@
""
"*
{
- return output_cbranch (operands, 0, insn);
+ return pa_output_cbranch (operands, 0, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1365,7 +1365,7 @@
""
"*
{
- return output_cbranch (operands, 1, insn);
+ return pa_output_cbranch (operands, 1, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1392,7 +1392,7 @@
"TARGET_64BIT"
"*
{
- return output_cbranch (operands, 0, insn);
+ return pa_output_cbranch (operands, 0, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1421,7 +1421,7 @@
"TARGET_64BIT"
"*
{
- return output_cbranch (operands, 1, insn);
+ return pa_output_cbranch (operands, 1, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1447,7 +1447,7 @@
"TARGET_64BIT"
"*
{
- return output_cbranch (operands, 0, insn);
+ return pa_output_cbranch (operands, 0, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1476,7 +1476,7 @@
"TARGET_64BIT"
"*
{
- return output_cbranch (operands, 1, insn);
+ return pa_output_cbranch (operands, 1, insn);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1505,7 +1505,7 @@
""
"*
{
- return output_bb (operands, 0, insn, 0);
+ return pa_output_bb (operands, 0, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1533,7 +1533,7 @@
"TARGET_64BIT"
"*
{
- return output_bb (operands, 0, insn, 0);
+ return pa_output_bb (operands, 0, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1561,7 +1561,7 @@
""
"*
{
- return output_bb (operands, 1, insn, 0);
+ return pa_output_bb (operands, 1, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1589,7 +1589,7 @@
"TARGET_64BIT"
"*
{
- return output_bb (operands, 1, insn, 0);
+ return pa_output_bb (operands, 1, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1617,7 +1617,7 @@
""
"*
{
- return output_bb (operands, 0, insn, 1);
+ return pa_output_bb (operands, 0, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1645,7 +1645,7 @@
"TARGET_64BIT"
"*
{
- return output_bb (operands, 0, insn, 1);
+ return pa_output_bb (operands, 0, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1673,7 +1673,7 @@
""
"*
{
- return output_bb (operands, 1, insn, 1);
+ return pa_output_bb (operands, 1, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1701,7 +1701,7 @@
"TARGET_64BIT"
"*
{
- return output_bb (operands, 1, insn, 1);
+ return pa_output_bb (operands, 1, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1730,7 +1730,7 @@
""
"*
{
- return output_bvb (operands, 0, insn, 0);
+ return pa_output_bvb (operands, 0, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1758,7 +1758,7 @@
"TARGET_64BIT"
"*
{
- return output_bvb (operands, 0, insn, 0);
+ return pa_output_bvb (operands, 0, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1786,7 +1786,7 @@
""
"*
{
- return output_bvb (operands, 1, insn, 0);
+ return pa_output_bvb (operands, 1, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1814,7 +1814,7 @@
"TARGET_64BIT"
"*
{
- return output_bvb (operands, 1, insn, 0);
+ return pa_output_bvb (operands, 1, insn, 0);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1842,7 +1842,7 @@
""
"*
{
- return output_bvb (operands, 0, insn, 1);
+ return pa_output_bvb (operands, 0, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1870,7 +1870,7 @@
"TARGET_64BIT"
"*
{
- return output_bvb (operands, 0, insn, 1);
+ return pa_output_bvb (operands, 0, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1898,7 +1898,7 @@
""
"*
{
- return output_bvb (operands, 1, insn, 1);
+ return pa_output_bvb (operands, 1, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1926,7 +1926,7 @@
"TARGET_64BIT"
"*
{
- return output_bvb (operands, 1, insn, 1);
+ return pa_output_bvb (operands, 1, insn, 1);
}"
[(set_attr "type" "cbranch")
(set (attr "length")
@@ -1978,7 +1978,7 @@
output_asm_insn (\"ftest\;add,tr %%r0,%%r0,%%r0\;b,n .+%0\", xoperands);
else
output_asm_insn (\"ftest\;add,tr %%r0,%%r0,%%r0\;b .+%0\", xoperands);
- return output_lbranch (operands[0], insn, xdelay);
+ return pa_output_lbranch (operands[0], insn, xdelay);
}"
[(set_attr "type" "fbranch")
(set (attr "length")
@@ -2022,7 +2022,7 @@
output_asm_insn (\"ftest\;b,n .+%0\", xoperands);
else
output_asm_insn (\"ftest\;b .+%0\", xoperands);
- return output_lbranch (operands[0], insn, xdelay);
+ return pa_output_lbranch (operands[0], insn, xdelay);
}"
[(set_attr "type" "fbranch")
(set (attr "length")
@@ -2043,7 +2043,7 @@
""
"
{
- if (emit_move_sequence (operands, SImode, 0))
+ if (pa_emit_move_sequence (operands, SImode, 0))
DONE;
}")
@@ -2055,7 +2055,7 @@
""
"
{
- if (emit_move_sequence (operands, SImode, operands[2]))
+ if (pa_emit_move_sequence (operands, SImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -2072,7 +2072,7 @@
""
"
{
- if (emit_move_sequence (operands, SImode, operands[2]))
+ if (pa_emit_move_sequence (operands, SImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -2089,7 +2089,7 @@
""
"
{
- if (emit_move_sequence (operands, SImode, operands[2]))
+ if (pa_emit_move_sequence (operands, SImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -2624,7 +2624,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (match_operand 1 "" "")))]
"(!flag_pic || !symbolic_operand (operands[1], Pmode))
- && !is_function_label_plus_const (operands[1])"
+ && !pa_is_function_label_plus_const (operands[1])"
"*
{
if (symbolic_operand (operands[1], Pmode))
@@ -2656,7 +2656,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "i")))]
- "!is_function_label_plus_const (operands[2])"
+ "!pa_is_function_label_plus_const (operands[2])"
"*
{
gcc_assert (!flag_pic || !symbolic_operand (operands[2], Pmode));
@@ -2735,7 +2735,7 @@
""
"
{
- if (emit_move_sequence (operands, HImode, 0))
+ if (pa_emit_move_sequence (operands, HImode, 0))
DONE;
}")
@@ -2748,7 +2748,7 @@
""
"
{
- if (emit_move_sequence (operands, HImode, operands[2]))
+ if (pa_emit_move_sequence (operands, HImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -2765,7 +2765,7 @@
""
"
{
- if (emit_move_sequence (operands, HImode, operands[2]))
+ if (pa_emit_move_sequence (operands, HImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -2893,7 +2893,7 @@
""
"
{
- if (emit_move_sequence (operands, QImode, 0))
+ if (pa_emit_move_sequence (operands, QImode, 0))
DONE;
}")
@@ -2906,7 +2906,7 @@
""
"
{
- if (emit_move_sequence (operands, QImode, operands[2]))
+ if (pa_emit_move_sequence (operands, QImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -2923,7 +2923,7 @@
""
"
{
- if (emit_move_sequence (operands, QImode, operands[2]))
+ if (pa_emit_move_sequence (operands, QImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -3121,7 +3121,7 @@
}")
;; The operand constraints are written like this to support both compile-time
-;; and run-time determined byte counts. The expander and output_block_move
+;; and run-time determined byte counts. The expander and pa_output_block_move
;; only support compile-time determined counts at this time.
;;
;; If the count is run-time determined, the register with the byte count
@@ -3238,7 +3238,7 @@
(use (match_operand:SI 5 "const_int_operand" "n,n")) ;alignment
(const_int 0)]
"!TARGET_64BIT && reload_completed"
- "* return output_block_move (operands, !which_alternative);"
+ "* return pa_output_block_move (operands, !which_alternative);"
[(set_attr "type" "multi,multi")])
(define_expand "movmemdi"
@@ -3309,7 +3309,7 @@
}")
;; The operand constraints are written like this to support both compile-time
-;; and run-time determined byte counts. The expander and output_block_move
+;; and run-time determined byte counts. The expander and pa_output_block_move
;; only support compile-time determined counts at this time.
;;
;; If the count is run-time determined, the register with the byte count
@@ -3426,7 +3426,7 @@
(use (match_operand:DI 5 "const_int_operand" "n,n")) ;alignment
(const_int 0)]
"TARGET_64BIT && reload_completed"
- "* return output_block_move (operands, !which_alternative);"
+ "* return pa_output_block_move (operands, !which_alternative);"
[(set_attr "type" "multi,multi")])
(define_expand "setmemsi"
@@ -3540,7 +3540,7 @@
(use (match_operand:SI 3 "const_int_operand" "n,n")) ;alignment
(const_int 0)]
"!TARGET_64BIT && reload_completed"
- "* return output_block_clear (operands, !which_alternative);"
+ "* return pa_output_block_clear (operands, !which_alternative);"
[(set_attr "type" "multi,multi")])
(define_expand "setmemdi"
@@ -3654,7 +3654,7 @@
(use (match_operand:DI 3 "const_int_operand" "n,n")) ;alignment
(const_int 0)]
"TARGET_64BIT && reload_completed"
- "* return output_block_clear (operands, !which_alternative);"
+ "* return pa_output_block_clear (operands, !which_alternative);"
[(set_attr "type" "multi,multi")])
;; Floating point move insns
@@ -3675,7 +3675,7 @@
&& operands[1] != CONST0_RTX (DFmode)
&& !TARGET_64BIT
&& !TARGET_SOFT_FLOAT"
- "* return (which_alternative == 0 ? output_move_double (operands)
+ "* return (which_alternative == 0 ? pa_output_move_double (operands)
: \"fldd%F1 %1,%0\");"
[(set_attr "type" "move,fpload")
(set_attr "length" "16,4")])
@@ -3701,7 +3701,7 @@
operands[1] = force_const_mem (DFmode, operands[1]);
}
- if (emit_move_sequence (operands, DFmode, 0))
+ if (pa_emit_move_sequence (operands, DFmode, 0))
DONE;
}")
@@ -3714,7 +3714,7 @@
""
"
{
- if (emit_move_sequence (operands, DFmode, operands[2]))
+ if (pa_emit_move_sequence (operands, DFmode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -3731,7 +3731,7 @@
""
"
{
- if (emit_move_sequence (operands, DFmode, operands[2]))
+ if (pa_emit_move_sequence (operands, DFmode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -3756,8 +3756,8 @@
|| operands[1] == CONST0_RTX (DFmode))
&& !(REG_P (operands[0]) && REG_P (operands[1])
&& FP_REG_P (operands[0]) ^ FP_REG_P (operands[1])))
- return output_fp_move_double (operands);
- return output_move_double (operands);
+ return pa_output_fp_move_double (operands);
+ return pa_output_move_double (operands);
}"
[(set_attr "type" "fpalu,move,fpstore,store,store,fpload,load,load,fpstore_load,store_fpload")
(set_attr "length" "4,8,4,8,16,4,8,16,12,12")])
@@ -3924,7 +3924,7 @@
&& TARGET_SOFT_FLOAT"
"*
{
- return output_move_double (operands);
+ return pa_output_move_double (operands);
}"
[(set_attr "type" "move,store,store,load,load")
(set_attr "length" "8,8,16,8,16")])
@@ -3970,7 +3970,7 @@
&& REGNO (operands[0]) >= 32)
FAIL;
- if (emit_move_sequence (operands, DImode, 0))
+ if (pa_emit_move_sequence (operands, DImode, 0))
DONE;
}")
@@ -3982,7 +3982,7 @@
""
"
{
- if (emit_move_sequence (operands, DImode, operands[2]))
+ if (pa_emit_move_sequence (operands, DImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -3999,7 +3999,7 @@
""
"
{
- if (emit_move_sequence (operands, DImode, operands[2]))
+ if (pa_emit_move_sequence (operands, DImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -4016,7 +4016,7 @@
""
"
{
- if (emit_move_sequence (operands, DImode, operands[2]))
+ if (pa_emit_move_sequence (operands, DImode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -4052,7 +4052,7 @@
operands[0] = operand_subword (op0, 0, 0, DImode);
operands[1] = GEN_INT (INTVAL (op1) >> 32);
- output_asm_insn (singlemove_string (operands), operands);
+ output_asm_insn (pa_singlemove_string (operands), operands);
#endif
break;
@@ -4063,7 +4063,7 @@
operands[0] = operand_subword (op0, 0, 0, DImode);
operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
- output_asm_insn (singlemove_string (operands), operands);
+ output_asm_insn (pa_singlemove_string (operands), operands);
break;
default:
@@ -4089,8 +4089,8 @@
|| operands[1] == CONST0_RTX (DFmode))
&& !(REG_P (operands[0]) && REG_P (operands[1])
&& FP_REG_P (operands[0]) ^ FP_REG_P (operands[1])))
- return output_fp_move_double (operands);
- return output_move_double (operands);
+ return pa_output_fp_move_double (operands);
+ return pa_output_move_double (operands);
}"
[(set_attr "type"
"move,store,store,load,load,multi,fpalu,fpload,fpstore,fpstore_load,store_fpload")
@@ -4216,7 +4216,7 @@
&& TARGET_SOFT_FLOAT"
"*
{
- return output_move_double (operands);
+ return pa_output_move_double (operands);
}"
[(set_attr "type" "move,store,store,load,load,multi")
(set_attr "length" "8,8,16,8,16,16")])
@@ -4257,7 +4257,7 @@
"GET_CODE (operands[1]) == CONST_DOUBLE
&& operands[1] != CONST0_RTX (SFmode)
&& ! TARGET_SOFT_FLOAT"
- "* return (which_alternative == 0 ? singlemove_string (operands)
+ "* return (which_alternative == 0 ? pa_singlemove_string (operands)
: \" fldw%F1 %1,%0\");"
[(set_attr "type" "move,fpload")
(set_attr "length" "8,4")])
@@ -4276,7 +4276,7 @@
&& REGNO (operands[0]) >= 32)
FAIL;
- if (emit_move_sequence (operands, SFmode, 0))
+ if (pa_emit_move_sequence (operands, SFmode, 0))
DONE;
}")
@@ -4289,7 +4289,7 @@
""
"
{
- if (emit_move_sequence (operands, SFmode, operands[2]))
+ if (pa_emit_move_sequence (operands, SFmode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -4306,7 +4306,7 @@
""
"
{
- if (emit_move_sequence (operands, SFmode, operands[2]))
+ if (pa_emit_move_sequence (operands, SFmode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
@@ -5026,7 +5026,7 @@
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
(clobber (match_operand:SI 4 "register_operand" ""))]
- "! cint_ok_for_move (INTVAL (operands[2]))
+ "! pa_cint_ok_for_move (INTVAL (operands[2]))
&& VAL_14_BITS_P (INTVAL (operands[2]) >> 1)"
[(set (match_dup 4) (plus:SI (match_dup 1) (match_dup 2)))
(set (match_dup 0) (plus:SI (match_dup 4) (match_dup 3)))]
@@ -5045,7 +5045,7 @@
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))
(clobber (match_operand:SI 4 "register_operand" ""))]
- "! cint_ok_for_move (INTVAL (operands[2]))"
+ "! pa_cint_ok_for_move (INTVAL (operands[2]))"
[(set (match_dup 4) (match_dup 2))
(set (match_dup 0) (plus:SI (mult:SI (match_dup 4) (match_dup 3))
(match_dup 1)))]
@@ -5055,26 +5055,26 @@
/* Try dividing the constant by 2, then 4, and finally 8 to see
if we can get a constant which can be loaded into a register
- in a single instruction (cint_ok_for_move).
+ in a single instruction (pa_cint_ok_for_move).
If that fails, try to negate the constant and subtract it
from our input operand. */
- if (intval % 2 == 0 && cint_ok_for_move (intval / 2))
+ if (intval % 2 == 0 && pa_cint_ok_for_move (intval / 2))
{
operands[2] = GEN_INT (intval / 2);
operands[3] = const2_rtx;
}
- else if (intval % 4 == 0 && cint_ok_for_move (intval / 4))
+ else if (intval % 4 == 0 && pa_cint_ok_for_move (intval / 4))
{
operands[2] = GEN_INT (intval / 4);
operands[3] = GEN_INT (4);
}
- else if (intval % 8 == 0 && cint_ok_for_move (intval / 8))
+ else if (intval % 8 == 0 && pa_cint_ok_for_move (intval / 8))
{
operands[2] = GEN_INT (intval / 8);
operands[3] = GEN_INT (8);
}
- else if (cint_ok_for_move (-intval))
+ else if (pa_cint_ok_for_move (-intval))
{
emit_insn (gen_rtx_SET (VOIDmode, operands[4], GEN_INT (-intval)));
emit_insn (gen_subsi3 (operands[0], operands[1], operands[4]));
@@ -5328,9 +5328,9 @@
(clobber (reg:SI 25))
(clobber (reg:SI 31))]
"!TARGET_64BIT"
- "* return output_mul_insn (0, insn);"
+ "* return pa_output_mul_insn (0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_insn ""
[(set (reg:SI 29) (mult:SI (reg:SI 26) (reg:SI 25)))
@@ -5339,9 +5339,9 @@
(clobber (reg:SI 25))
(clobber (reg:SI 2))]
"TARGET_64BIT"
- "* return output_mul_insn (0, insn);"
+ "* return pa_output_mul_insn (0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_expand "muldi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -5416,7 +5416,7 @@
operands[5] = gen_rtx_REG (SImode, 31);
operands[4] = gen_reg_rtx (SImode);
}
- if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 0))
+ if (GET_CODE (operands[2]) == CONST_INT && pa_emit_hpdiv_const (operands, 0))
DONE;
}")
@@ -5430,9 +5430,9 @@
(clobber (reg:SI 31))]
"!TARGET_64BIT"
"*
- return output_div_insn (operands, 0, insn);"
+ return pa_output_div_insn (operands, 0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_insn ""
[(set (reg:SI 29)
@@ -5444,9 +5444,9 @@
(clobber (reg:SI 2))]
"TARGET_64BIT"
"*
- return output_div_insn (operands, 0, insn);"
+ return pa_output_div_insn (operands, 0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_expand "udivsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
@@ -5473,7 +5473,7 @@
operands[5] = gen_rtx_REG (SImode, 31);
operands[4] = gen_reg_rtx (SImode);
}
- if (GET_CODE (operands[2]) == CONST_INT && emit_hpdiv_const (operands, 1))
+ if (GET_CODE (operands[2]) == CONST_INT && pa_emit_hpdiv_const (operands, 1))
DONE;
}")
@@ -5487,9 +5487,9 @@
(clobber (reg:SI 31))]
"!TARGET_64BIT"
"*
- return output_div_insn (operands, 1, insn);"
+ return pa_output_div_insn (operands, 1, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_insn ""
[(set (reg:SI 29)
@@ -5501,9 +5501,9 @@
(clobber (reg:SI 2))]
"TARGET_64BIT"
"*
- return output_div_insn (operands, 1, insn);"
+ return pa_output_div_insn (operands, 1, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_expand "modsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
@@ -5540,9 +5540,9 @@
(clobber (reg:SI 31))]
"!TARGET_64BIT"
"*
- return output_mod_insn (0, insn);"
+ return pa_output_mod_insn (0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_insn ""
[(set (reg:SI 29) (mod:SI (reg:SI 26) (reg:SI 25)))
@@ -5553,9 +5553,9 @@
(clobber (reg:SI 2))]
"TARGET_64BIT"
"*
- return output_mod_insn (0, insn);"
+ return pa_output_mod_insn (0, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_expand "umodsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_src_operand" ""))
@@ -5592,9 +5592,9 @@
(clobber (reg:SI 31))]
"!TARGET_64BIT"
"*
- return output_mod_insn (1, insn);"
+ return pa_output_mod_insn (1, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
(define_insn ""
[(set (reg:SI 29) (umod:SI (reg:SI 26) (reg:SI 25)))
@@ -5605,9 +5605,9 @@
(clobber (reg:SI 2))]
"TARGET_64BIT"
"*
- return output_mod_insn (1, insn);"
+ return pa_output_mod_insn (1, insn);"
[(set_attr "type" "milli")
- (set (attr "length") (symbol_ref "attr_length_millicode_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_millicode_call (insn)"))])
;;- and instructions
;; We define DImode `and` so with DImode `not` we can get
@@ -5639,7 +5639,7 @@
(and:DI (match_operand:DI 1 "register_operand" "%?r,0")
(match_operand:DI 2 "and_operand" "rO,P")))]
"TARGET_64BIT"
- "* return output_64bit_and (operands); "
+ "* return pa_output_64bit_and (operands); "
[(set_attr "type" "binary")
(set_attr "length" "4")])
@@ -5650,7 +5650,7 @@
(and:SI (match_operand:SI 1 "register_operand" "%?r,0")
(match_operand:SI 2 "and_operand" "rO,P")))]
""
- "* return output_and (operands); "
+ "* return pa_output_and (operands); "
[(set_attr "type" "binary,shift")
(set_attr "length" "4,4")])
@@ -5707,7 +5707,7 @@
(ior:DI (match_operand:DI 1 "register_operand" "0,0")
(match_operand:DI 2 "cint_ior_operand" "M,i")))]
"TARGET_64BIT"
- "* return output_64bit_ior (operands); "
+ "* return pa_output_64bit_ior (operands); "
[(set_attr "type" "binary,shift")
(set_attr "length" "4,4")])
@@ -5733,7 +5733,7 @@
(ior:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "cint_ior_operand" "M,i")))]
""
- "* return output_ior (operands); "
+ "* return pa_output_ior (operands); "
[(set_attr "type" "binary,shift")
(set_attr "length" "4,4")])
@@ -6711,14 +6711,14 @@
(define_expand "prologue"
[(const_int 0)]
""
- "hppa_expand_prologue ();DONE;")
+ "pa_expand_prologue ();DONE;")
(define_expand "sibcall_epilogue"
[(return)]
""
"
{
- hppa_expand_epilogue ();
+ pa_expand_epilogue ();
DONE;
}")
@@ -6734,7 +6734,7 @@
x = gen_return ();
else
{
- hppa_expand_epilogue ();
+ pa_expand_epilogue ();
/* EH returns bypass the normal return stub. Thus, we must do an
interspace branch to return from functions that call eh_return.
@@ -6808,12 +6808,12 @@
if (get_attr_length (insn) < 16)
return \"b%* %l0\";
- return output_lbranch (operands[0], insn, 1);
+ return pa_output_lbranch (operands[0], insn, 1);
}"
[(set_attr "type" "uncond_branch")
(set_attr "pa_combine_type" "uncond_branch")
(set (attr "length")
- (cond [(match_test "jump_in_call_delay (insn)")
+ (cond [(match_test "pa_jump_in_call_delay (insn)")
(if_then_else (lt (abs (minus (match_dup 0)
(plus (pc) (const_int 8))))
(const_int MAX_12BIT_OFFSET))
@@ -7179,11 +7179,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[0], 0);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[0], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
(define_insn "call_symref_pic"
[(set (match_operand:SI 2 "register_operand" "=&r") (reg:SI 19))
@@ -7256,11 +7256,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[0], 0);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[0], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
@@ -7341,11 +7341,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[0], 0);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[0], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
(define_insn "call_reg"
[(call (mem:SI (reg:SI 22))
@@ -7356,10 +7356,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_64BIT"
"*
{
- return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+ return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
@@ -7434,10 +7434,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_64BIT"
"*
{
- return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+ return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
@@ -7518,10 +7518,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"TARGET_64BIT"
"*
{
- return output_indirect_call (insn, operands[0]);
+ return pa_output_indirect_call (insn, operands[0]);
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
@@ -7643,11 +7643,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[1], 0);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[1], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
(define_insn "call_val_symref_pic"
[(set (match_operand:SI 3 "register_operand" "=&r") (reg:SI 19))
@@ -7726,11 +7726,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[1], 0);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[1], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
@@ -7817,11 +7817,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[1], 0);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[1], 0);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 0)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 0)"))])
(define_insn "call_val_reg"
[(set (match_operand 0 "" "")
@@ -7833,10 +7833,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_64BIT"
"*
{
- return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+ return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
@@ -7917,10 +7917,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_64BIT"
"*
{
- return output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
+ return pa_output_indirect_call (insn, gen_rtx_REG (word_mode, 22));
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
;; This pattern is split if it is necessary to save and restore the
;; PIC register.
@@ -8007,10 +8007,10 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"TARGET_64BIT"
"*
{
- return output_indirect_call (insn, operands[1]);
+ return pa_output_indirect_call (insn, operands[1]);
}"
[(set_attr "type" "dyncall")
- (set (attr "length") (symbol_ref "attr_length_indirect_call (insn)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_indirect_call (insn)"))])
;; Call subroutine returning any type.
@@ -8100,11 +8100,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[0], 1);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[0], 1);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 1)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 1)"))])
(define_insn "sibcall_internal_symref_64bit"
[(call (mem:SI (match_operand 0 "call_operand_address" ""))
@@ -8115,11 +8115,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[0], 1);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[0], 1);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 1)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 1)"))])
(define_expand "sibcall_value"
[(set (match_operand 0 "" "")
@@ -8184,11 +8184,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"!TARGET_PORTABLE_RUNTIME && !TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[1], 1);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[1], 1);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 1)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 1)"))])
(define_insn "sibcall_value_internal_symref_64bit"
[(set (match_operand 0 "" "")
@@ -8200,11 +8200,11 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"TARGET_64BIT"
"*
{
- output_arg_descriptor (insn);
- return output_call (insn, operands[1], 1);
+ pa_output_arg_descriptor (insn);
+ return pa_output_call (insn, operands[1], 1);
}"
[(set_attr "type" "call")
- (set (attr "length") (symbol_ref "attr_length_call (insn, 1)"))])
+ (set (attr "length") (symbol_ref "pa_attr_length_call (insn, 1)"))])
(define_insn "nop"
[(const_int 0)]
@@ -8593,7 +8593,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(plus:SI (match_dup 0) (match_dup 1)))
(clobber (match_scratch:SI 4 "=X,r,r"))]
""
- "* return output_dbra (operands, insn, which_alternative); "
+ "* return pa_output_dbra (operands, insn, which_alternative); "
;; Do not expect to understand this the first time through.
[(set_attr "type" "cbranch,multi,multi")
(set (attr "length")
@@ -8676,7 +8676,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*m,!*q")
(match_dup 1))]
""
-"* return output_movb (operands, insn, which_alternative, 0); "
+"* return pa_output_movb (operands, insn, which_alternative, 0); "
;; Do not expect to understand this the first time through.
[(set_attr "type" "cbranch,multi,multi,multi")
(set (attr "length")
@@ -8748,7 +8748,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*m,!*q")
(match_dup 1))]
""
-"* return output_movb (operands, insn, which_alternative, 1); "
+"* return pa_output_movb (operands, insn, which_alternative, 1); "
;; Do not expect to understand this the first time through.
[(set_attr "type" "cbranch,multi,multi,multi")
(set (attr "length")
@@ -8817,7 +8817,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"(reload_completed && operands[0] == operands[1]) || operands[0] == operands[2]"
"*
{
- return output_parallel_addb (operands, insn);
+ return pa_output_parallel_addb (operands, insn);
}"
[(set_attr "type" "parallel_branch")
(set (attr "length")
@@ -8840,7 +8840,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"reload_completed"
"*
{
- return output_parallel_movb (operands, insn);
+ return pa_output_parallel_movb (operands, insn);
}"
[(set_attr "type" "parallel_branch")
(set (attr "length")
@@ -8863,7 +8863,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"reload_completed"
"*
{
- return output_parallel_movb (operands, insn);
+ return pa_output_parallel_movb (operands, insn);
}"
[(set_attr "type" "parallel_branch")
(set (attr "length")
@@ -8886,7 +8886,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"reload_completed"
"*
{
- return output_parallel_movb (operands, insn);
+ return pa_output_parallel_movb (operands, insn);
}"
[(set_attr "type" "parallel_branch")
(set (attr "length")
@@ -8909,7 +8909,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
"reload_completed"
"*
{
- return output_parallel_movb (operands, insn);
+ return pa_output_parallel_movb (operands, insn);
}"
[(set_attr "type" "parallel_branch")
(set (attr "length")
@@ -8933,7 +8933,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(plus (match_operand 4 "register_operand" "f")
(match_operand 5 "register_operand" "f")))]
"TARGET_PA_11 && ! TARGET_SOFT_FLOAT
- && reload_completed && fmpyaddoperands (operands)"
+ && reload_completed && pa_fmpyaddoperands (operands)"
"*
{
if (GET_MODE (operands[0]) == DFmode)
@@ -8962,7 +8962,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(mult (match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")))]
"TARGET_PA_11 && ! TARGET_SOFT_FLOAT
- && reload_completed && fmpyaddoperands (operands)"
+ && reload_completed && pa_fmpyaddoperands (operands)"
"*
{
if (GET_MODE (operands[0]) == DFmode)
@@ -8991,7 +8991,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(minus (match_operand 4 "register_operand" "f")
(match_operand 5 "register_operand" "f")))]
"TARGET_PA_11 && ! TARGET_SOFT_FLOAT
- && reload_completed && fmpysuboperands (operands)"
+ && reload_completed && pa_fmpysuboperands (operands)"
"*
{
if (GET_MODE (operands[0]) == DFmode)
@@ -9010,7 +9010,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(mult (match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")))]
"TARGET_PA_11 && ! TARGET_SOFT_FLOAT
- && reload_completed && fmpysuboperands (operands)"
+ && reload_completed && pa_fmpysuboperands (operands)"
"*
{
if (GET_MODE (operands[0]) == DFmode)
@@ -9236,13 +9236,13 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
output_asm_insn (\"{comb|cmpb},<<,n %%r26,%%r31,.+%1\", xoperands);
/* Finally, call $$sh_func_adrs to extract the function's real add24. */
- return output_millicode_call (insn,
- gen_rtx_SYMBOL_REF (SImode,
- \"$$sh_func_adrs\"));
+ return pa_output_millicode_call (insn,
+ gen_rtx_SYMBOL_REF (SImode,
+ \"$$sh_func_adrs\"));
}"
[(set_attr "type" "multi")
(set (attr "length")
- (plus (symbol_ref "attr_length_millicode_call (insn)")
+ (plus (symbol_ref "pa_attr_length_millicode_call (insn)")
(const_int 20)))])
;; On the PA, the PIC register is call clobbered, so it must
diff --git a/gcc/config/pa/pa64-hpux.h b/gcc/config/pa/pa64-hpux.h
index 37c4cb2ccfa..66eeecb35dd 100644
--- a/gcc/config/pa/pa64-hpux.h
+++ b/gcc/config/pa/pa64-hpux.h
@@ -236,7 +236,7 @@ do { \
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
do { \
if (!FUNCTION_NAME_P (XSTR (FUN, 0))) \
- hppa_encode_label (FUN); \
+ pa_encode_label (FUN); \
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, XSTR (FUN, 0), "function"); \
} while (0)
diff --git a/gcc/config/pa/pa64-linux.h b/gcc/config/pa/pa64-linux.h
index 174d7c54dec..1d5fa93b5a9 100644
--- a/gcc/config/pa/pa64-linux.h
+++ b/gcc/config/pa/pa64-linux.h
@@ -37,7 +37,7 @@ along with GCC; see the file COPYING3. If not see
{ \
int fsize; \
\
- fsize = compute_frame_size (get_frame_size (), 0); \
+ fsize = pa_compute_frame_size (get_frame_size (), 0); \
if ((TO) == FRAME_POINTER_REGNUM \
&& (FROM) == ARG_POINTER_REGNUM) \
{ \
diff --git a/gcc/config/pa/predicates.md b/gcc/config/pa/predicates.md
index d6f45d513de..962e2f6e817 100644
--- a/gcc/config/pa/predicates.md
+++ b/gcc/config/pa/predicates.md
@@ -59,14 +59,14 @@
(define_predicate "cint_ior_operand"
(and (match_code "const_int")
- (match_test "ior_mask_p (INTVAL (op))")))
+ (match_test "pa_ior_mask_p (INTVAL (op))")))
;; True iff OP is CONST_INT that can be moved in one instruction
;; into a general register.
(define_predicate "cint_move_operand"
(and (match_code "const_int")
- (match_test "cint_ok_for_move (INTVAL (op))")))
+ (match_test "pa_cint_ok_for_move (INTVAL (op))")))
;; True iff OP is a CONST0_RTX for MODE.
@@ -91,7 +91,7 @@
(define_predicate "and_operand"
(ior (match_operand 0 "register_operand")
(and (match_code "const_int")
- (match_test "and_mask_p (INTVAL (op))"))))
+ (match_test "pa_and_mask_p (INTVAL (op))"))))
;; Return truth value of whether OP can be used as an operand in a
;; three operand arithmetic insn that accepts registers of mode MODE
@@ -179,7 +179,7 @@
&& ((REG_P (op) && REGNO (op) == 25)
|| (CONST_INT_P (op)
&& INTVAL (op) > 0 && INTVAL (op) < 16
- && magic_milli[INTVAL (op)])));
+ && pa_magic_milli[INTVAL (op)])));
})
;; True iff OP is a reloading floating point register
@@ -304,7 +304,7 @@
return true;
if (CONST_INT_P (op))
- return cint_ok_for_move (INTVAL (op));
+ return pa_cint_ok_for_move (INTVAL (op));
if (GET_MODE (op) != mode)
return false;
@@ -452,7 +452,7 @@
(define_predicate "shadd_operand"
(and (match_code "const_int")
- (match_test "shadd_constant_p (INTVAL (op))")))
+ (match_test "pa_shadd_constant_p (INTVAL (op))")))
;; Return truth value of statement that OP is a symbolic memory operand.
@@ -463,7 +463,7 @@
op = SUBREG_REG (op);
if (!MEM_P (op))
return false;
- return symbolic_expression_p (XEXP (op, 0));
+ return pa_symbolic_expression_p (XEXP (op, 0));
})
;; True iff OP is a symbolic operand.
diff --git a/gcc/config/pa/som.h b/gcc/config/pa/som.h
index f9f56484421..51476157fca 100644
--- a/gcc/config/pa/som.h
+++ b/gcc/config/pa/som.h
@@ -227,7 +227,7 @@ do { \
tree id; \
\
if (!function_label_operand (RTL, VOIDmode)) \
- hppa_encode_label (RTL); \
+ pa_encode_label (RTL); \
\
name = targetm.strip_name_encoding (XSTR ((RTL), 0)); \
id = maybe_get_identifier (name); \
diff --git a/gcc/config/pa/t-dce-thr b/gcc/config/pa/t-dce-thr
index 8d86a418186..51b3abcf607 100644
--- a/gcc/config/pa/t-dce-thr
+++ b/gcc/config/pa/t-dce-thr
@@ -1,5 +1,2 @@
MULTILIB_OPTIONS = threads
MULTILIB_DIRNAMES = threads
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/pa/t-hpux-shlib b/gcc/config/pa/t-hpux-shlib
deleted file mode 100644
index d5a5b6c8609..00000000000
--- a/gcc/config/pa/t-hpux-shlib
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright (C) 2001, 2003, 2004, 2005, 2006 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Build a shared libgcc library.
-SHLIB_EXT = .sl
-SHLIB_NAME = @shlib_base_name@$(SHLIB_EXT)
-SHLIB_SOVERSION = 1
-SHLIB_SONAME = @shlib_base_name@.$(SHLIB_SOVERSION)
-SHLIB_OBJS = @shlib_objs@
-SHLIB_DIR = @multilib_dir@
-SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
-
-SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,+h -Wl,$(SHLIB_SONAME) \
- -o $(SHLIB_DIR)/$(SHLIB_NAME).tmp @multilib_flags@ $(SHLIB_OBJS) && \
- rm -f $(SHLIB_DIR)/$(SHLIB_SONAME) && \
- if [ -f $(SHLIB_DIR)/$(SHLIB_NAME) ]; then \
- mv -f $(SHLIB_DIR)/$(SHLIB_NAME) $(SHLIB_DIR)/$(SHLIB_NAME).backup; \
- else true; fi && \
- mv $(SHLIB_DIR)/$(SHLIB_NAME).tmp $(SHLIB_DIR)/$(SHLIB_NAME) && \
- $(LN_S) $(SHLIB_NAME) $(SHLIB_DIR)/$(SHLIB_SONAME)
-
-# $(slibdir) double quoted to protect it from expansion while building
-# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = \
- $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
- $(INSTALL_DATA) -m 555 $(SHLIB_DIR)/$(SHLIB_NAME) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SONAME); \
- rm -f $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_NAME); \
- $(LN_S) $(SHLIB_SONAME) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_NAME)
diff --git a/gcc/config/pa/t-linux b/gcc/config/pa/t-linux
deleted file mode 100644
index fbbcfe29fd7..00000000000
--- a/gcc/config/pa/t-linux
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 1999, 2001, 2002, 2008 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-#Plug millicode routines into libgcc.a We want these on both native and
-#cross compiles. We use the "64-bit" routines because the "32-bit" code
-#is broken for certain corner cases.
-
-LIB1ASMFUNCS = _divI _divU _remI _remU _div_const _mulI _dyncall
-LIB1ASMSRC = pa/milli64.S
-
-# Compile libgcc2.a as PIC.
-TARGET_LIBGCC2_CFLAGS = -fPIC -DELF=1 -DLINUX=1
-
-LIB2FUNCS_EXTRA=fptr.c
-LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/pa/linux-atomic.c
-
-fptr.c: $(srcdir)/config/pa/fptr.c
- rm -f fptr.c
- cp $(srcdir)/config/pa/fptr.c .
-
-# Compile crtbeginS.o and crtendS.o as PIC.
-CRTSTUFF_T_CFLAGS_S = -fPIC
diff --git a/gcc/config/pa/t-linux64 b/gcc/config/pa/t-linux64
deleted file mode 100644
index 1658f6d8aae..00000000000
--- a/gcc/config/pa/t-linux64
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2001, 2008 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-#Plug millicode routines into libgcc.a We want these on both native and
-#cross compiles.
-
-LIB1ASMFUNCS = _divI _divU _remI _remU _div_const _mulI
-LIB1ASMSRC = pa/milli64.S
-
-# Compile crtbeginS.o and crtendS.o as PIC.
-# Actually, hppa64 is always PIC but adding -fPIC does no harm.
-CRTSTUFF_T_CFLAGS_S = -fPIC
-
-LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/pa/linux-atomic.c
-
-# Compile libgcc2.a as PIC.
-TARGET_LIBGCC2_CFLAGS = -fPIC -Dpa64=1 -DELF=1
diff --git a/gcc/config/pa/t-pa-hpux b/gcc/config/pa/t-pa-hpux
deleted file mode 100644
index 63eab636200..00000000000
--- a/gcc/config/pa/t-pa-hpux
+++ /dev/null
@@ -1,7 +0,0 @@
-lib2funcs.asm: $(srcdir)/config/pa/lib2funcs.asm
- rm -f lib2funcs.asm
- cp $(srcdir)/config/pa/lib2funcs.asm .
-
-quadlib.c: $(srcdir)/config/pa/quadlib.c
- rm -f quadlib.c
- cp $(srcdir)/config/pa/quadlib.c .
diff --git a/gcc/config/pa/t-pa-hpux10 b/gcc/config/pa/t-pa-hpux10
deleted file mode 100644
index fd7ff484257..00000000000
--- a/gcc/config/pa/t-pa-hpux10
+++ /dev/null
@@ -1,2 +0,0 @@
-TARGET_LIBGCC2_CFLAGS = -fPIC -frandom-seed=fixed-seed -D_T_HPUX10
-LIB2FUNCS_EXTRA=lib2funcs.asm quadlib.c
diff --git a/gcc/config/pa/t-pa-hpux11 b/gcc/config/pa/t-pa-hpux11
deleted file mode 100644
index 4436b4ca640..00000000000
--- a/gcc/config/pa/t-pa-hpux11
+++ /dev/null
@@ -1,31 +0,0 @@
-TARGET_LIBGCC2_CFLAGS = -fPIC -frandom-seed=fixed-seed
-LIB2FUNCS_EXTRA=lib2funcs.asm quadlib.c
-LIBGCCSTUB_OBJS = pthread_default_stacksize_np-stub.o \
- pthread_mutex_lock-stub.o \
- pthread_mutex_unlock-stub.o \
- pthread_once-stub.o
-
-stublib.c: $(srcdir)/config/pa/stublib.c
- rm -f stublib.c
- cp $(srcdir)/config/pa/stublib.c .
-
-pthread_default_stacksize_np-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_pthread_default_stacksize_np stublib.c \
- -o pthread_default_stacksize_np-stub.o
-
-pthread_mutex_lock-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_pthread_mutex_lock stublib.c \
- -o pthread_mutex_lock-stub.o
-
-pthread_mutex_unlock-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_pthread_mutex_unlock stublib.c \
- -o pthread_mutex_unlock-stub.o
-
-pthread_once-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_pthread_once stublib.c \
- -o pthread_once-stub.o
-
-$(T)libgcc_stub.a: $(LIBGCCSTUB_OBJS)
- -rm -rf $(T)libgcc_stub.a
- $(AR) rc $(T)libgcc_stub.a $(LIBGCCSTUB_OBJS)
- $(RANLIB) $(T)libgcc_stub.a
diff --git a/gcc/config/pa/t-pa64 b/gcc/config/pa/t-pa64
deleted file mode 100644
index e6ac7a5bb7d..00000000000
--- a/gcc/config/pa/t-pa64
+++ /dev/null
@@ -1,67 +0,0 @@
-# Copyright (C) 2000, 2001, 2002, 2004, 2006,
-# 2007, 2010 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-TARGET_LIBGCC2_CFLAGS = -fPIC -Dpa64=1 -DELF=1 -mlong-calls
-LIB2FUNCS_EXTRA = quadlib.c
-LIBGCCSTUB_OBJS = rfi-stub.o dfi-stub.o jvrc-stub.o cxaf-stub.o \
- pthread_default_stacksize_np-stub.o \
- pthread_mutex_lock-stub.o \
- pthread_mutex_unlock-stub.o \
- pthread_once-stub.o
-
-stublib.c: $(srcdir)/config/pa/stublib.c
- rm -f stublib.c
- cp $(srcdir)/config/pa/stublib.c .
-
-rfi-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_register_frame_info stublib.c \
- -o rfi-stub.o
-
-dfi-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_deregister_frame_info stublib.c \
- -o dfi-stub.o
-
-cxaf-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_cxa_finalize stublib.c \
- -o cxaf-stub.o
-
-jvrc-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_Jv_RegisterClasses stublib.c \
- -o jvrc-stub.o
-
-pthread_default_stacksize_np-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_pthread_default_stacksize_np stublib.c \
- -o pthread_default_stacksize_np-stub.o
-
-pthread_mutex_lock-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_pthread_mutex_lock stublib.c \
- -o pthread_mutex_lock-stub.o
-
-pthread_mutex_unlock-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_pthread_mutex_unlock stublib.c \
- -o pthread_mutex_unlock-stub.o
-
-pthread_once-stub.o: stublib.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) -c -O2 -DL_pthread_once stublib.c \
- -o pthread_once-stub.o
-
-$(T)libgcc_stub.a: $(LIBGCCSTUB_OBJS)
- -rm -rf $(T)libgcc_stub.a
- $(AR) rc $(T)libgcc_stub.a $(LIBGCCSTUB_OBJS)
- $(RANLIB) $(T)libgcc_stub.a
diff --git a/gcc/config/pdp11/t-pdp11 b/gcc/config/pdp11/t-pdp11
index 032084b381b..c0287d50da2 100644
--- a/gcc/config/pdp11/t-pdp11
+++ b/gcc/config/pdp11/t-pdp11
@@ -17,11 +17,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-TARGET_LIBGCC2_CFLAGS = -O2 -mfloat32
-LIB2FUNCS_EXTRA = $(srcdir)/config/udivmod.c $(srcdir)/config/udivmodsi4.c \
- $(srcdir)/config/memcmp.c $(srcdir)/config/memcpy.c \
- $(srcdir)/config/memmove.c $(srcdir)/config/memset.c
-
MULTILIB_OPTIONS = msoft-float
# Because the pdp11 POINTER_SIZE is only 16, in dwarf2out.c,
diff --git a/gcc/config/picochip/libgccExtras/clzsi2.asm b/gcc/config/picochip/libgccExtras/clzsi2.asm
deleted file mode 100644
index 835d4694167..00000000000
--- a/gcc/config/picochip/libgccExtras/clzsi2.asm
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright (C) 2008 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 3, 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.
-//
-// Under Section 7 of GPL version 3, you are granted additional
-// permissions described in the GCC Runtime Library Exception, version
-// 3.1, as published by the Free Software Foundation.
-//
-// You should have received a copy of the GNU General Public License and
-// a copy of the GCC Runtime Library Exception along with this program;
-// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-// <http://www.gnu.org/licenses/>.
-
-// picoChip ASM file
-//.file "clzsi2.asm"
-
-.section .text
-
-.global __clzsi2
-__clzsi2:
-_picoMark_FUNCTION_BEGIN=
-
-// picoChip Function Prologue : &__clzsi2 = 0 bytes
-
- // What value should be operated on? If the top word is empty
- // then count the bits in the bottom word, and add 16. If the
- // top word is not empty, then count the bits in the top word.
-
- // R4 stores the constant 0
-
- sub.0 R1,0,r15 \ copy.1 16,r2
- copyeq r0,r1
- copyne 0,r2
-
- // R1 now stores value to count, and R2 stores current bit offset.
- sbc r1,r0
- asr.0 r1,15,r15 \ add.1 r0,1,r0
- jr (lr) \ copyne 0,r0
-=-> add.0 r0,r2,r0
-
-_picoMark_FUNCTION_END=
-
-// picoChip Function Epilogue : __clzsi2
-
-//============================================================================
-// All DWARF information between this marker, and the END OF DWARF
-// marker should be included in the source file. Search for
-// FUNCTION_STACK_SIZE_GOES_HERE and FUNCTION NAME GOES HERE, and
-// provide the relevent information. Add markers called
-// _picoMark_FUNCTION_BEGIN and _picoMark_FUNCTION_END around the
-// function in question.
-//============================================================================
-
-//============================================================================
-// Frame information.
-//============================================================================
-
-.section .debug_frame
-_picoMark_DebugFrame=
-
-// Common CIE header.
-.unalignedInitLong _picoMark_CieEnd-_picoMark_CieBegin
-_picoMark_CieBegin=
-.unalignedInitLong 0xffffffff
-.initByte 0x1 // CIE Version
-.ascii 16#0# // CIE Augmentation
-.uleb128 0x1 // CIE Code Alignment Factor
-.sleb128 2 // CIE Data Alignment Factor
-.initByte 0xc // CIE RA Column
-.initByte 0xc // DW_CFA_def_cfa
-.uleb128 0xd
-.uleb128 0x0
-.align 2
-_picoMark_CieEnd=
-
-// FDE
-_picoMark_LSFDE0I900821033007563=
-.unalignedInitLong _picoMark_FdeEnd-_picoMark_FdeBegin
-_picoMark_FdeBegin=
-.unalignedInitLong _picoMark_DebugFrame // FDE CIE offset
-.unalignedInitWord _picoMark_FUNCTION_BEGIN // FDE initial location
-.unalignedInitWord _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN
-.initByte 0xe // DW_CFA_def_cfa_offset
-.uleb128 0x0 // <-- FUNCTION_STACK_SIZE_GOES_HERE
-.initByte 0x4 // DW_CFA_advance_loc4
-.unalignedInitLong _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN
-.initByte 0xe // DW_CFA_def_cfa_offset
-.uleb128 0x0
-.align 2
-_picoMark_FdeEnd=
-
-//============================================================================
-// Abbrevation information.
-//============================================================================
-
-.section .debug_abbrev
-_picoMark_ABBREVIATIONS=
-
-.section .debug_abbrev
- .uleb128 0x1 // (abbrev code)
- .uleb128 0x11 // (TAG: DW_TAG_compile_unit)
- .initByte 0x1 // DW_children_yes
- .uleb128 0x10 // (DW_AT_stmt_list)
- .uleb128 0x6 // (DW_FORM_data4)
- .uleb128 0x12 // (DW_AT_high_pc)
- .uleb128 0x1 // (DW_FORM_addr)
- .uleb128 0x11 // (DW_AT_low_pc)
- .uleb128 0x1 // (DW_FORM_addr)
- .uleb128 0x25 // (DW_AT_producer)
- .uleb128 0x8 // (DW_FORM_string)
- .uleb128 0x13 // (DW_AT_language)
- .uleb128 0x5 // (DW_FORM_data2)
- .uleb128 0x3 // (DW_AT_name)
- .uleb128 0x8 // (DW_FORM_string)
-.initByte 0x0
-.initByte 0x0
-
- .uleb128 0x2 ;# (abbrev code)
- .uleb128 0x2e ;# (TAG: DW_TAG_subprogram)
-.initByte 0x0 ;# DW_children_no
- .uleb128 0x3 ;# (DW_AT_name)
- .uleb128 0x8 ;# (DW_FORM_string)
- .uleb128 0x11 ;# (DW_AT_low_pc)
- .uleb128 0x1 ;# (DW_FORM_addr)
- .uleb128 0x12 ;# (DW_AT_high_pc)
- .uleb128 0x1 ;# (DW_FORM_addr)
-.initByte 0x0
-.initByte 0x0
-
-.initByte 0x0
-
-//============================================================================
-// Line information. DwarfLib requires this to be present, but it can
-// be empty.
-//============================================================================
-
-.section .debug_line
-_picoMark_LINES=
-
-//============================================================================
-// Debug Information
-//============================================================================
-.section .debug_info
-
-//Fixed header.
-.unalignedInitLong _picoMark_DEBUG_INFO_END-_picoMark_DEBUG_INFO_BEGIN
-_picoMark_DEBUG_INFO_BEGIN=
-.unalignedInitWord 0x2
-.unalignedInitLong _picoMark_ABBREVIATIONS
-.initByte 0x2
-
-// Compile unit information.
-.uleb128 0x1 // (DIE 0xb) DW_TAG_compile_unit)
-.unalignedInitLong _picoMark_LINES
-.unalignedInitWord _picoMark_FUNCTION_END
-.unalignedInitWord _picoMark_FUNCTION_BEGIN
-// Producer is `picoChip'
-.ascii 16#70# 16#69# 16#63# 16#6f# 16#43# 16#68# 16#69# 16#70# 16#00#
-.unalignedInitWord 0xcafe // ASM language
-.ascii 16#0# // Name. DwarfLib expects this to be present.
-
-.uleb128 0x2 ;# (DIE DW_TAG_subprogram)
-
-// FUNCTION NAME GOES HERE. Use `echo name | od -t x1' to get the hex. Each hex
-// digit is specified using the format 16#XX#
-.ascii 16#5F# 16#63# 16#6C# 16#7A# 16#73# 16#69# 16#32# 16#0# // Function name `_clzsi2'
-.unalignedInitWord _picoMark_FUNCTION_BEGIN // DW_AT_low_pc
-.unalignedInitWord _picoMark_FUNCTION_END // DW_AT_high_pc
-
-.initByte 0x0 // end of compile unit children.
-
-_picoMark_DEBUG_INFO_END=
-
-//============================================================================
-// END OF DWARF
-//============================================================================
-
-.section .endFile
-// End of picoChip ASM file
diff --git a/gcc/config/picochip/libgccExtras/fake_libgcc.asm b/gcc/config/picochip/libgccExtras/fake_libgcc.asm
deleted file mode 100644
index e4b78f1e1f1..00000000000
--- a/gcc/config/picochip/libgccExtras/fake_libgcc.asm
+++ /dev/null
@@ -1,6 +0,0 @@
-// picoChip ASM file
-// Fake libgcc asm file. This contains nothing, but is used to prevent gcc
-// getting upset about the lack of a libgcc.S file when LIB1ASMFUNCS is defined
-// to switch off the compilation of parts of libgcc.
-
-
diff --git a/gcc/config/picochip/t-picochip b/gcc/config/picochip/t-picochip
index 222d7a646b9..269a0551407 100644
--- a/gcc/config/picochip/t-picochip
+++ b/gcc/config/picochip/t-picochip
@@ -16,45 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Compile the extra library functions.
-
-LIB2FUNCS_EXTRA = \
- $(srcdir)/config/picochip/libgccExtras/ashrsi3.asm \
- $(srcdir)/config/picochip/libgccExtras/ashlsi3.asm \
- $(srcdir)/config/picochip/libgccExtras/divmodhi4.asm \
- $(srcdir)/config/picochip/libgccExtras/udivmodhi4.asm \
- $(srcdir)/config/picochip/libgccExtras/divmodsi4.asm \
- $(srcdir)/config/picochip/libgccExtras/udivmodsi4.asm \
- $(srcdir)/config/picochip/libgccExtras/divmod15.asm \
- $(srcdir)/config/picochip/libgccExtras/ucmpsi2.asm \
- $(srcdir)/config/picochip/libgccExtras/cmpsi2.asm \
- $(srcdir)/config/picochip/libgccExtras/clzsi2.asm \
- $(srcdir)/config/picochip/libgccExtras/adddi3.asm \
- $(srcdir)/config/picochip/libgccExtras/subdi3.asm \
- $(srcdir)/config/picochip/libgccExtras/lshrsi3.asm \
- $(srcdir)/config/picochip/libgccExtras/parityhi2.asm \
- $(srcdir)/config/picochip/libgccExtras/popcounthi2.asm
-
-# Prevent some of the more complicated libgcc functions from being
-# compiled. This is because they are generally too big to fit into an
-# AE anyway, so there is no point in having them. Also, some don't
-# compile properly so we'll ignore them for the moment.
-
-LIB1ASMFUNCS = _mulsc3 _divsc3
-LIB1ASMSRC = picochip/libgccExtras/fake_libgcc.asm
-
-# Turn off ranlib on target libraries.
-RANLIB_FOR_TARGET = cat
-
-# Special libgcc setup. Make single/double floating point the same,
-# and use our own include files.
-TARGET_LIBGCC2_CFLAGS = -DDF=SF -I../../includes/
-
-# Switch off all debugging for the embedded libraries.
-# (embedded processors need small libraries by default).
-# NOTE: If the debug level is increased, turn off instruction scheduling.
-LIBGCC2_DEBUG_CFLAGS = -g0
-
# Build all combinations of library for different multiply units, and
# presence/absence of byte access.
MULTILIB_OPTIONS = mmul-type=none/mmul-type=mac/mmul-type=mul mno-byte-access/mbyte-access
diff --git a/gcc/config/rs6000/476.h b/gcc/config/rs6000/476.h
new file mode 100644
index 00000000000..70ee7bd7406
--- /dev/null
+++ b/gcc/config/rs6000/476.h
@@ -0,0 +1,32 @@
+/* Enable IBM PowerPC 476 support.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Peter Bergner (bergner@vnet.ibm.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 3, 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#undef TARGET_LINK_STACK
+#define TARGET_LINK_STACK (rs6000_link_stack)
+
+#undef SET_TARGET_LINK_STACK
+#define SET_TARGET_LINK_STACK(X) do { TARGET_LINK_STACK = (X); } while (0)
+
+#undef TARGET_ASM_CODE_END
+#define TARGET_ASM_CODE_END rs6000_code_end
diff --git a/gcc/config/rs6000/476.opt b/gcc/config/rs6000/476.opt
new file mode 100644
index 00000000000..c987fc6c662
--- /dev/null
+++ b/gcc/config/rs6000/476.opt
@@ -0,0 +1,24 @@
+; IBM PowerPC 476 options.
+;
+; Copyright (C) 2011 Free Software Foundation, Inc.
+; Contributed by Peter Bergner (bergner@vnet.ibm.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 3, 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 COPYING3. If not see
+; <http://www.gnu.org/licenses/>.
+
+mpreserve-link-stack
+Target Var(rs6000_link_stack) Init(-1) Save
+Preserve the PowerPC 476's link stack by matching up a blr with the bcl/bl insns used for GOT accesses
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 9e7437ed0fe..a3a8d77bc2e 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -1357,6 +1357,15 @@
"vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
+(define_expand "vec_permv16qi"
+ [(set (match_operand:V16QI 0 "register_operand" "")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "")
+ (match_operand:V16QI 2 "register_operand" "")
+ (match_operand:V16QI 3 "register_operand" "")]
+ UNSPEC_VPERM))]
+ "TARGET_ALTIVEC"
+ "")
+
(define_insn "altivec_vrfip" ; ceil
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
@@ -2420,6 +2429,7 @@
"stvrxl %1,%y0"
[(set_attr "type" "vecstore")])
+;; ??? This is still used directly by vector.md
(define_expand "vec_extract_evenv4si"
[(set (match_operand:V4SI 0 "register_operand" "")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "")
@@ -2453,6 +2463,7 @@
DONE;
}")
+;; ??? This is still used directly by vector.md
(define_expand "vec_extract_evenv4sf"
[(set (match_operand:V4SF 0 "register_operand" "")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
@@ -2486,138 +2497,6 @@
DONE;
}")
-(define_expand "vec_extract_evenv8hi"
- [(set (match_operand:V8HI 0 "register_operand" "")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "")
- (match_operand:V8HI 2 "register_operand" "")]
- UNSPEC_EXTEVEN_V8HI))]
- "TARGET_ALTIVEC"
- "
-{
- rtx mask = gen_reg_rtx (V16QImode);
- rtvec v = rtvec_alloc (16);
-
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 0);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 1);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 4);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 5);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 8);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 9);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 12);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 13);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 17);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 20);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 21);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 24);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 25);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 28);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 29);
- emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
- emit_insn (gen_altivec_vperm_v8hi (operands[0], operands[1], operands[2], mask));
-
- DONE;
-}")
-
-(define_expand "vec_extract_evenv16qi"
- [(set (match_operand:V16QI 0 "register_operand" "")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "")
- (match_operand:V16QI 2 "register_operand" "")]
- UNSPEC_EXTEVEN_V16QI))]
- "TARGET_ALTIVEC"
- "
-{
- rtx mask = gen_reg_rtx (V16QImode);
- rtvec v = rtvec_alloc (16);
-
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 0);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 2);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 4);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 6);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 8);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 10);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 12);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 14);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 16);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 18);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 20);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 22);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 24);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 26);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 28);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 30);
- emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
- emit_insn (gen_altivec_vperm_v16qi (operands[0], operands[1], operands[2], mask));
-
- DONE;
-}")
-
-(define_expand "vec_extract_oddv4si"
- [(set (match_operand:V4SI 0 "register_operand" "")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "")
- (match_operand:V4SI 2 "register_operand" "")]
- UNSPEC_EXTODD_V4SI))]
- "TARGET_ALTIVEC"
- "
-{
- rtx mask = gen_reg_rtx (V16QImode);
- rtvec v = rtvec_alloc (16);
-
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 4);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 5);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 6);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 7);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 12);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 13);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 14);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 15);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 20);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 21);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 22);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 23);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 28);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 29);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 30);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 31);
- emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
- emit_insn (gen_altivec_vperm_v4si (operands[0], operands[1], operands[2], mask));
-
- DONE;
-}")
-
-(define_expand "vec_extract_oddv4sf"
- [(set (match_operand:V4SF 0 "register_operand" "")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "")
- (match_operand:V4SF 2 "register_operand" "")]
- UNSPEC_EXTODD_V4SF))]
- "TARGET_ALTIVEC"
- "
-{
- rtx mask = gen_reg_rtx (V16QImode);
- rtvec v = rtvec_alloc (16);
-
- RTVEC_ELT (v, 0) = gen_rtx_CONST_INT (QImode, 4);
- RTVEC_ELT (v, 1) = gen_rtx_CONST_INT (QImode, 5);
- RTVEC_ELT (v, 2) = gen_rtx_CONST_INT (QImode, 6);
- RTVEC_ELT (v, 3) = gen_rtx_CONST_INT (QImode, 7);
- RTVEC_ELT (v, 4) = gen_rtx_CONST_INT (QImode, 12);
- RTVEC_ELT (v, 5) = gen_rtx_CONST_INT (QImode, 13);
- RTVEC_ELT (v, 6) = gen_rtx_CONST_INT (QImode, 14);
- RTVEC_ELT (v, 7) = gen_rtx_CONST_INT (QImode, 15);
- RTVEC_ELT (v, 8) = gen_rtx_CONST_INT (QImode, 20);
- RTVEC_ELT (v, 9) = gen_rtx_CONST_INT (QImode, 21);
- RTVEC_ELT (v, 10) = gen_rtx_CONST_INT (QImode, 22);
- RTVEC_ELT (v, 11) = gen_rtx_CONST_INT (QImode, 23);
- RTVEC_ELT (v, 12) = gen_rtx_CONST_INT (QImode, 28);
- RTVEC_ELT (v, 13) = gen_rtx_CONST_INT (QImode, 29);
- RTVEC_ELT (v, 14) = gen_rtx_CONST_INT (QImode, 30);
- RTVEC_ELT (v, 15) = gen_rtx_CONST_INT (QImode, 31);
- emit_insn (gen_vec_initv16qi (mask, gen_rtx_PARALLEL (V16QImode, v)));
- emit_insn (gen_altivec_vperm_v4sf (operands[0], operands[1], operands[2], mask));
-
- DONE;
-}")
-
(define_insn "vpkuhum_nomode"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand 1 "register_operand" "v")
diff --git a/gcc/config/rs6000/darwin.h b/gcc/config/rs6000/darwin.h
index 82971ae0e32..425111e7561 100644
--- a/gcc/config/rs6000/darwin.h
+++ b/gcc/config/rs6000/darwin.h
@@ -173,18 +173,27 @@ extern int darwin_emit_branch_islands;
(RS6000_ALIGN (crtl->outgoing_args_size, 16) \
+ (STACK_POINTER_OFFSET))
-/* Define cutoff for using external functions to save floating point.
- Currently on Darwin, always use inline stores. */
+/* Define cutoff for using out-of-line functions to save registers.
+ Currently on Darwin, we implement FP and GPR out-of-line-saves plus the
+ special routine for 'save everything'. */
+
+#undef FP_SAVE_INLINE
+#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) > 60 && (FIRST_REG) < 64)
-#undef FP_SAVE_INLINE
-#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 64)
#undef GP_SAVE_INLINE
-#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32)
+#define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) > 29 && (FIRST_REG) < 32)
/* Darwin uses a function call if everything needs to be saved/restored. */
+
#undef WORLD_SAVE_P
#define WORLD_SAVE_P(INFO) ((INFO)->world_save_p)
+/* We don't use these on Darwin, they are just place-holders. */
+#define SAVE_FP_PREFIX ""
+#define SAVE_FP_SUFFIX ""
+#define RESTORE_FP_PREFIX ""
+#define RESTORE_FP_SUFFIX ""
+
/* The assembler wants the alternate register names, but without
leading percent sign. */
#undef REGISTER_NAMES
@@ -234,12 +243,6 @@ extern int darwin_emit_branch_islands;
#undef ASM_COMMENT_START
#define ASM_COMMENT_START ";"
-/* FP save and restore routines. */
-#define SAVE_FP_PREFIX "._savef"
-#define SAVE_FP_SUFFIX ""
-#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. */
diff --git a/gcc/config/rs6000/power7.md b/gcc/config/rs6000/power7.md
index 148a7a52a8a..9071bd5e8e0 100644
--- a/gcc/config/rs6000/power7.md
+++ b/gcc/config/rs6000/power7.md
@@ -139,7 +139,7 @@
(define_insn_reservation "power7-vecstore" 6
(and (eq_attr "type" "vecstore")
(eq_attr "cpu" "power7"))
- "DU_power7,LSU_power7+VSU_power7")
+ "DU_power7,LSU_power7+vsu2_power7")
(define_insn_reservation "power7-sync" 11
(and (eq_attr "type" "sync")
@@ -265,54 +265,69 @@
(define_bypass 8 "power7-fp" "power7-branch")
-(define_insn_reservation "power7-fpcompare" 4
+(define_insn_reservation "power7-fpcompare" 8
(and (eq_attr "type" "fpcompare")
(eq_attr "cpu" "power7"))
"DU_power7,VSU_power7")
-(define_insn_reservation "power7-sdiv" 26
+(define_insn_reservation "power7-sdiv" 27
(and (eq_attr "type" "sdiv")
(eq_attr "cpu" "power7"))
"DU_power7,VSU_power7")
-(define_insn_reservation "power7-ddiv" 32
+(define_insn_reservation "power7-ddiv" 33
(and (eq_attr "type" "ddiv")
(eq_attr "cpu" "power7"))
"DU_power7,VSU_power7")
-(define_insn_reservation "power7-sqrt" 31
+(define_insn_reservation "power7-sqrt" 32
(and (eq_attr "type" "ssqrt")
(eq_attr "cpu" "power7"))
"DU_power7,VSU_power7")
-(define_insn_reservation "power7-dsqrt" 43
+(define_insn_reservation "power7-dsqrt" 44
(and (eq_attr "type" "dsqrt")
(eq_attr "cpu" "power7"))
"DU_power7,VSU_power7")
(define_insn_reservation "power7-vecsimple" 2
- (and (eq_attr "type" "vecsimple")
- (eq_attr "cpu" "power7"))
- "du1_power7,VSU_power7")
-
-(define_insn_reservation "power7-veccmp" 7
- (and (eq_attr "type" "veccmp")
+ (and (eq_attr "type" "vecsimple,veccmp")
(eq_attr "cpu" "power7"))
- "du1_power7,VSU_power7")
+ "DU_power7,vsu1_power7")
-(define_insn_reservation "power7-vecfloat" 7
+(define_insn_reservation "power7-vecfloat" 6
(and (eq_attr "type" "vecfloat")
(eq_attr "cpu" "power7"))
- "du1_power7,VSU_power7")
+ "DU_power7,vsu1_power7")
-(define_bypass 6 "power7-vecfloat" "power7-vecfloat")
+(define_bypass 7 "power7-vecfloat" "power7-vecsimple,power7-veccomplex,\
+ power7-vecperm")
(define_insn_reservation "power7-veccomplex" 7
(and (eq_attr "type" "veccomplex")
(eq_attr "cpu" "power7"))
- "du1_power7,VSU_power7")
+ "DU_power7,vsu1_power7")
(define_insn_reservation "power7-vecperm" 3
(and (eq_attr "type" "vecperm")
(eq_attr "cpu" "power7"))
- "du2_power7,VSU_power7")
+ "DU_power7,vsu2_power7")
+
+(define_insn_reservation "power7-vecdouble" 6
+ (and (eq_attr "type" "vecdouble")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
+(define_bypass 7 "power7-vecdouble" "power7-vecsimple,power7-veccomplex,\
+ power7-vecperm")
+
+(define_insn_reservation "power7-vecfdiv" 26
+ (and (eq_attr "type" "vecfdiv")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
+(define_insn_reservation "power7-vecdiv" 32
+ (and (eq_attr "type" "vecdiv")
+ (eq_attr "cpu" "power7"))
+ "DU_power7,VSU_power7")
+
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 73da0f69f47..23d2d2aa389 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -173,6 +173,7 @@ extern void rs6000_emit_eh_reg_restore (rtx, rtx);
extern const char * output_isel (rtx *);
extern void rs6000_call_indirect_aix (rtx, rtx, rtx);
extern void rs6000_aix_asm_output_dwarf_table_ref (char *);
+extern void get_ppc476_thunk_name (char name[32]);
/* Declare functions in rs6000-c.c */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 4fd2192d380..2430cdf9e65 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -899,8 +899,6 @@ static const char *rs6000_mangle_type (const_tree);
static void rs6000_set_default_type_attributes (tree);
static rtx rs6000_savres_routine_sym (rs6000_stack_t *, bool, bool, bool);
static rtx rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool);
-static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int,
- enum machine_mode, bool, bool, bool);
static bool rs6000_reg_live_or_pic_offset_p (int);
static tree rs6000_builtin_vectorized_libmass (tree, tree, tree);
static tree rs6000_builtin_vectorized_function (tree, tree, tree);
@@ -988,7 +986,6 @@ static tree rs6000_builtin_mask_for_load (void);
static tree rs6000_builtin_mul_widen_even (tree);
static tree rs6000_builtin_mul_widen_odd (tree);
static tree rs6000_builtin_conversion (unsigned int, tree, tree);
-static tree rs6000_builtin_vec_perm (tree, tree *);
static bool rs6000_builtin_support_vector_misalignment (enum
machine_mode,
const_tree,
@@ -1179,6 +1176,7 @@ static void rs6000_trampoline_init (rtx, tree, rtx);
static bool rs6000_cannot_force_const_mem (enum machine_mode, rtx);
static bool rs6000_legitimate_constant_p (enum machine_mode, rtx);
static bool rs6000_save_toc_in_prologue_p (void);
+static void rs6000_code_end (void) ATTRIBUTE_UNUSED;
/* Hash table stuff for keeping track of TOC entries. */
@@ -1407,8 +1405,6 @@ static const struct attribute_spec rs6000_attribute_table[] =
#define TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD rs6000_builtin_mul_widen_odd
#undef TARGET_VECTORIZE_BUILTIN_CONVERSION
#define TARGET_VECTORIZE_BUILTIN_CONVERSION rs6000_builtin_conversion
-#undef TARGET_VECTORIZE_BUILTIN_VEC_PERM
-#define TARGET_VECTORIZE_BUILTIN_VEC_PERM rs6000_builtin_vec_perm
#undef TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT
#define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \
rs6000_builtin_support_vector_misalignment
@@ -1618,7 +1614,6 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P rs6000_legitimate_constant_p
-struct gcc_target targetm = TARGET_INITIALIZER;
/* Simplifications for entries below. */
@@ -3244,6 +3239,11 @@ rs6000_option_override_internal (bool global_init_p)
target_option_default_node = target_option_current_node
= build_target_option_node ();
+ /* If not explicitly specified via option, decide whether to generate the
+ extra blr's required to preserve the link stack on some cpus (eg, 476). */
+ if (TARGET_LINK_STACK == -1)
+ SET_TARGET_LINK_STACK (rs6000_cpu == PROCESSOR_PPC476 && flag_pic);
+
return ret;
}
@@ -3475,65 +3475,6 @@ rs6000_builtin_support_vector_misalignment (enum machine_mode mode,
return false;
}
-/* Implement targetm.vectorize.builtin_vec_perm. */
-tree
-rs6000_builtin_vec_perm (tree type, tree *mask_element_type)
-{
- tree inner_type = TREE_TYPE (type);
- bool uns_p = TYPE_UNSIGNED (inner_type);
- tree d;
-
- *mask_element_type = unsigned_char_type_node;
-
- switch (TYPE_MODE (type))
- {
- case V16QImode:
- d = (uns_p
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI_UNS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_16QI]);
- break;
-
- case V8HImode:
- d = (uns_p
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI_UNS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_8HI]);
- break;
-
- case V4SImode:
- d = (uns_p
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI_UNS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SI]);
- break;
-
- case V4SFmode:
- d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SF];
- break;
-
- case V2DFmode:
- if (!TARGET_ALLOW_DF_PERMUTE)
- return NULL_TREE;
-
- d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DF];
- break;
-
- case V2DImode:
- if (!TARGET_ALLOW_DF_PERMUTE)
- return NULL_TREE;
-
- d = (uns_p
- ? rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI_UNS]
- : rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_2DI]);
- break;
-
- default:
- return NULL_TREE;
- }
-
- gcc_assert (d);
- return d;
-}
-
-
/* Implement targetm.vectorize.builtin_vectorization_cost. */
static int
rs6000_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
@@ -4758,7 +4699,7 @@ rs6000_expand_vector_init (rtx target, rtx vals)
/* Store value to stack temp. Load vector element. Splat. However, splat
of 64-bit items is not supported on Altivec. */
- if (all_same && GET_MODE_SIZE (mode) <= 4)
+ if (all_same && GET_MODE_SIZE (inner_mode) <= 4)
{
mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
emit_move_insn (adjust_address_nv (mem, inner_mode, 0),
@@ -5932,6 +5873,8 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
lab = gen_label_rtx ();
emit_insn (gen_load_toc_v4_PIC_1b (gsym, lab));
emit_move_insn (tmp1, gen_rtx_REG (Pmode, LR_REGNO));
+ if (TARGET_LINK_STACK)
+ emit_insn (gen_addsi3 (tmp1, tmp1, GEN_INT (4)));
emit_move_insn (tmp2, mem);
last = emit_insn (gen_addsi3 (got, tmp1, tmp2));
set_unique_reg_note (last, REG_EQUAL, gsym);
@@ -12213,7 +12156,7 @@ rs6000_init_builtins (void)
#if TARGET_XCOFF
/* AIX libm provides clog as __clog. */
- if ((tdecl = builtin_decl_explicit ([BUILT_IN_CLOG))) != NULL_TREE)
+ if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
set_user_assembler_name (tdecl, "__clog");
#endif
@@ -18047,9 +17990,11 @@ rs6000_savres_strategy (rs6000_stack_t *info,
/* Don't bother to try to save things out-of-line if r11 is occupied
by the static chain. It would require too much fiddling and the
- static chain is rarely used anyway. */
+ static chain is rarely used anyway. FPRs are saved w.r.t the stack
+ pointer on Darwin. */
if (using_static_chain_p)
- strategy |= SAVE_INLINE_FPRS | SAVE_INLINE_GPRS;
+ strategy |= (DEFAULT_ABI == ABI_DARWIN ? 0 : SAVE_INLINE_FPRS)
+ | SAVE_INLINE_GPRS;
/* If we are going to use store multiple, then don't even bother
with the out-of-line routines, since the store-multiple
@@ -18097,6 +18042,9 @@ rs6000_savres_strategy (rs6000_stack_t *info,
if (TARGET_AIX && !(strategy & REST_INLINE_FPRS))
strategy |= REST_NOINLINE_FPRS_DOESNT_RESTORE_LR;
#endif
+ if (TARGET_MACHO && !(strategy & SAVE_INLINE_FPRS))
+ strategy |= SAVE_NOINLINE_FPRS_SAVES_LR;
+
return strategy;
}
@@ -18692,6 +18640,8 @@ debug_stack_info (rs6000_stack_t *info)
if (info->reg_size != 4)
fprintf (stderr, "\treg_size = %5d\n", info->reg_size);
+ fprintf (stderr, "\tsave-strategy = %04x\n", info->savres_strategy);
+
fprintf (stderr, "\n");
}
@@ -18923,6 +18873,8 @@ rs6000_emit_load_toc_table (int fromprolog)
lab = gen_label_rtx ();
emit_insn (gen_load_toc_v4_PIC_1b (tocsym, lab));
emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO));
+ if (TARGET_LINK_STACK)
+ emit_insn (gen_addsi3 (dest, dest, GEN_INT (4)));
emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest));
}
emit_insn (gen_addsi3 (dest, temp0, dest));
@@ -19637,10 +19589,25 @@ rs6000_savres_routine_name (rs6000_stack_t *info, int regno,
suffix = savep ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX;
}
}
- else if (DEFAULT_ABI == ABI_DARWIN)
- sorry ("out-of-line save/restore routines not supported on Darwin");
- sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix);
+ if (DEFAULT_ABI == ABI_DARWIN)
+ {
+ /* The Darwin approach is (slightly) different, in order to be
+ compatible with code generated by the system toolchain. There is a
+ single symbol for the start of save sequence, and the code here
+ embeds an offset into that code on the basis of the first register
+ to be saved. */
+ prefix = savep ? "save" : "rest" ;
+ if (gpr)
+ sprintf (savres_routine_name, "*%sGPR%s%s%.0d ; %s r%d-r31",
+ prefix, (lr ? "x" : ""), (regno == 13 ? "" : "+"),
+ (regno-13) * 4, prefix, regno);
+ else
+ sprintf (savres_routine_name, "*%sFP%s%.0d ; %s f%d-f31",
+ prefix, (regno == 14 ? "" : "+"), (regno-14) * 4, prefix, regno);
+ }
+ else
+ sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix);
return savres_routine_name;
}
@@ -19705,8 +19672,10 @@ rs6000_emit_stack_reset (rs6000_stack_t *info,
if (sp_offset != 0)
{
rtx dest_reg = savres ? gen_rtx_REG (Pmode, 11) : sp_reg_rtx;
- return emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx,
- GEN_INT (sp_offset)));
+ rtx insn = emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx,
+ GEN_INT (sp_offset)));
+ if (!savres)
+ return insn;
}
else if (!savres)
return emit_move_insn (sp_reg_rtx, frame_reg_rtx);
@@ -19730,19 +19699,21 @@ rs6000_emit_stack_reset (rs6000_stack_t *info,
}
/* Construct a parallel rtx describing the effect of a call to an
- out-of-line register save/restore routine. */
+ out-of-line register save/restore routine, and emit the insn
+ or jump_insn as appropriate. */
static rtx
-rs6000_make_savres_rtx (rs6000_stack_t *info,
+rs6000_emit_savres_rtx (rs6000_stack_t *info,
rtx frame_reg_rtx, int save_area_offset,
enum machine_mode reg_mode,
bool savep, bool gpr, bool lr)
{
int i;
- int offset, start_reg, end_reg, n_regs;
+ int offset, start_reg, end_reg, n_regs, use_reg;
int reg_size = GET_MODE_SIZE (reg_mode);
rtx sym;
rtvec p;
+ rtx par, insn;
offset = 0;
start_reg = (gpr
@@ -19756,15 +19727,16 @@ rs6000_make_savres_rtx (rs6000_stack_t *info,
RTVEC_ELT (p, offset++) = ret_rtx;
RTVEC_ELT (p, offset++)
- = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65));
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNO));
sym = rs6000_savres_routine_sym (info, savep, gpr, lr);
RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym);
+ use_reg = DEFAULT_ABI == ABI_AIX ? (gpr && !lr ? 12 : 1)
+ : DEFAULT_ABI == ABI_DARWIN && !gpr ? 1
+ : 11;
RTVEC_ELT (p, offset++)
= gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode, DEFAULT_ABI != ABI_AIX ? 11
- : gpr && !lr ? 12
- : 1));
+ gen_rtx_REG (Pmode, use_reg));
for (i = 0; i < end_reg - start_reg; i++)
{
@@ -19789,7 +19761,16 @@ rs6000_make_savres_rtx (rs6000_stack_t *info,
RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg);
}
- return gen_rtx_PARALLEL (VOIDmode, p);
+ par = gen_rtx_PARALLEL (VOIDmode, p);
+
+ if (!savep && lr)
+ {
+ insn = emit_jump_insn (par);
+ JUMP_LABEL (insn) = ret_rtx;
+ }
+ else
+ insn = emit_insn (par);
+ return insn;
}
/* Determine whether the gp REG is really used. */
@@ -20088,16 +20069,13 @@ rs6000_emit_prologue (void)
}
else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
{
- rtx par;
-
- par = rs6000_make_savres_rtx (info, frame_reg_rtx,
- info->fp_save_offset + sp_offset,
- DFmode,
- /*savep=*/true, /*gpr=*/false,
- /*lr=*/(strategy
- & SAVE_NOINLINE_FPRS_SAVES_LR)
- != 0);
- insn = emit_insn (par);
+ insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
+ info->fp_save_offset + sp_offset,
+ DFmode,
+ /*savep=*/true, /*gpr=*/false,
+ /*lr=*/((strategy
+ & SAVE_NOINLINE_FPRS_SAVES_LR)
+ != 0));
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
@@ -20187,13 +20165,10 @@ rs6000_emit_prologue (void)
}
else
{
- rtx par;
-
- par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
- 0, reg_mode,
- /*savep=*/true, /*gpr=*/true,
- /*lr=*/false);
- insn = emit_insn (par);
+ insn = rs6000_emit_savres_rtx (info, gen_rtx_REG (Pmode, 11),
+ 0, reg_mode,
+ /*savep=*/true, /*gpr=*/true,
+ /*lr=*/false);
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
@@ -20205,10 +20180,21 @@ rs6000_emit_prologue (void)
}
else if (!WORLD_SAVE_P (info) && !saving_GPRs_inline)
{
- rtx par;
-
+ if (DEFAULT_ABI == ABI_DARWIN)
+ {
+ rtx dest_reg = gen_rtx_REG (reg_mode, 11);
+ if (info->first_fp_reg_save == 64)
+ /* we only need a copy, no fprs were saved. */
+ emit_move_insn (dest_reg, frame_reg_rtx);
+ else
+ {
+ rtx offset = GEN_INT (sp_offset
+ + (-8 * (64-info->first_fp_reg_save)));
+ emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
+ }
+ }
/* Need to adjust r11 (r12) if we saved any FPRs. */
- if (info->first_fp_reg_save != 64)
+ else if (info->first_fp_reg_save != 64)
{
rtx dest_reg = gen_rtx_REG (reg_mode, DEFAULT_ABI == ABI_AIX
? 12 : 11);
@@ -20217,14 +20203,13 @@ rs6000_emit_prologue (void)
emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset));
}
- par = rs6000_make_savres_rtx (info, frame_reg_rtx,
- info->gp_save_offset + sp_offset,
- reg_mode,
- /*savep=*/true, /*gpr=*/true,
- /*lr=*/(strategy
- & SAVE_NOINLINE_GPRS_SAVES_LR)
- != 0);
- insn = emit_insn (par);
+ insn = rs6000_emit_savres_rtx (info, frame_reg_rtx,
+ info->gp_save_offset + sp_offset,
+ reg_mode,
+ /*savep=*/true, /*gpr=*/true,
+ /*lr=*/((strategy
+ & SAVE_NOINLINE_GPRS_SAVES_LR)
+ != 0));
rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
@@ -20575,7 +20560,8 @@ rs6000_output_function_prologue (FILE *file,
/* Write .extern for any function we will call to save and restore
fp values. */
- if (info->first_fp_reg_save < 64)
+ if (info->first_fp_reg_save < 64
+ && !TARGET_MACHO)
{
char *name;
int regno = info->first_fp_reg_save - 32;
@@ -20673,6 +20659,20 @@ offset_below_red_zone_p (HOST_WIDE_INT offset)
: TARGET_32BIT ? -220 : -288);
}
+/* Append CFA_RESTORES to any existing REG_NOTES on the last insn. */
+
+static void
+emit_cfa_restores (rtx cfa_restores)
+{
+ rtx insn = get_last_insn ();
+ rtx *loc = &REG_NOTES (insn);
+
+ while (*loc)
+ loc = &XEXP (*loc, 1);
+ *loc = cfa_restores;
+ RTX_FRAME_RELATED_P (insn) = 1;
+}
+
/* Emit function epilogue as insns. */
void
@@ -20770,6 +20770,14 @@ rs6000_emit_epilogue (int sibcall)
rtx mem = gen_frame_mem (reg_mode, addr);
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+
+ if (flag_shrink_wrap)
+ {
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (Pmode, LR_REGNO),
+ cfa_restores);
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
}
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
@@ -20781,6 +20789,8 @@ rs6000_emit_epilogue (int sibcall)
rtx mem = gen_frame_mem (reg_mode, addr);
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ if (flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
{
@@ -20791,6 +20801,8 @@ rs6000_emit_epilogue (int sibcall)
rtx mem = gen_frame_mem (V4SImode, addr);
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ if (flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
for (i = 0; info->first_fp_reg_save + i <= 63; i++)
{
@@ -20804,6 +20816,8 @@ rs6000_emit_epilogue (int sibcall)
? DFmode : SFmode), addr);
RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ if (flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
RTVEC_ELT (p, j++)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 0));
@@ -20815,8 +20829,14 @@ rs6000_emit_epilogue (int sibcall)
= gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 8));
RTVEC_ELT (p, j++)
= gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 10));
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ insn = emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ if (flag_shrink_wrap)
+ {
+ REG_NOTES (insn) = cfa_restores;
+ add_reg_note (insn, REG_CFA_DEF_CFA, sp_reg_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
return;
}
@@ -20861,9 +20881,10 @@ rs6000_emit_epilogue (int sibcall)
reg = gen_rtx_REG (V4SImode, i);
emit_move_insn (reg, mem);
- if (offset_below_red_zone_p (info->altivec_save_offset
- + (i - info->first_altivec_reg_save)
- * 16))
+ if (flag_shrink_wrap
+ || offset_below_red_zone_p (info->altivec_save_offset
+ + (i - info->first_altivec_reg_save)
+ * 16))
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
cfa_restores);
}
@@ -21002,7 +21023,7 @@ rs6000_emit_epilogue (int sibcall)
reg = gen_rtx_REG (V4SImode, i);
emit_move_insn (reg, mem);
- if (DEFAULT_ABI == ABI_V4)
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
cfa_restores);
}
@@ -21052,8 +21073,7 @@ rs6000_emit_epilogue (int sibcall)
emit_move_insn (cr_save_reg, mem);
}
- /* Set LR here to try to overlap restores below. LR is always saved
- above incoming stack, so it never needs REG_CFA_RESTORE. */
+ /* Set LR here to try to overlap restores below. */
if (restore_lr && restoring_GPRs_inline)
emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO),
gen_rtx_REG (Pmode, 0));
@@ -21091,7 +21111,7 @@ rs6000_emit_epilogue (int sibcall)
/* Restore GPRs. This is done as a PARALLEL if we are using
the load-multiple instructions. */
if (TARGET_SPE_ABI
- && info->spe_64bit_regs_used != 0
+ && info->spe_64bit_regs_used
&& info->first_gp_reg_save != 32)
{
/* Determine whether we can address all of the registers that need
@@ -21115,7 +21135,7 @@ rs6000_emit_epilogue (int sibcall)
int ool_adjust = (restoring_GPRs_inline
? 0
: (info->first_gp_reg_save
- - (FIRST_SAVRES_REGISTER+1))*8);
+ - (FIRST_SAVRES_REGISTER + 1)) * 8);
if (frame_reg_rtx == sp_reg_rtx)
frame_reg_rtx = gen_rtx_REG (Pmode, 11);
@@ -21146,48 +21166,32 @@ rs6000_emit_epilogue (int sibcall)
mem = gen_rtx_MEM (V2SImode, addr);
reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
- insn = emit_move_insn (reg, mem);
- if (DEFAULT_ABI == ABI_V4)
- {
- if (frame_pointer_needed
- && info->first_gp_reg_save + i
- == HARD_FRAME_POINTER_REGNUM)
- {
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (frame_reg_rtx,
- sp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
+ emit_move_insn (reg, mem);
}
}
else
- {
- rtx par;
-
- par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11),
- 0, reg_mode,
- /*savep=*/false, /*gpr=*/true,
- /*lr=*/true);
- emit_jump_insn (par);
- /* We don't want anybody else emitting things after we jumped
- back. */
- return;
- }
+ rs6000_emit_savres_rtx (info, gen_rtx_REG (Pmode, 11),
+ 0, reg_mode,
+ /*savep=*/false, /*gpr=*/true,
+ /*lr=*/true);
}
else if (!restoring_GPRs_inline)
{
/* We are jumping to an out-of-line function. */
bool can_use_exit = info->first_fp_reg_save == 64;
- rtx par;
/* Emit stack reset code if we need it. */
if (can_use_exit)
- rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
+ {
+ rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx,
sp_offset, can_use_exit);
+ if (DEFAULT_ABI == ABI_DARWIN)
+ /* we only need a copy, no fprs were saved. */
+ emit_move_insn (gen_rtx_REG (reg_mode, 11), frame_reg_rtx);
+
+ if (info->cr_save_p)
+ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
+ }
else
{
emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX
@@ -21198,45 +21202,10 @@ rs6000_emit_epilogue (int sibcall)
sp_offset += info->fp_size;
}
- par = rs6000_make_savres_rtx (info, frame_reg_rtx,
- info->gp_save_offset, reg_mode,
- /*savep=*/false, /*gpr=*/true,
- /*lr=*/can_use_exit);
-
- if (can_use_exit)
- {
- if (info->cr_save_p)
- {
- rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
- if (DEFAULT_ABI == ABI_V4)
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (SImode, CR2_REGNO),
- cfa_restores);
- }
-
- emit_jump_insn (par);
-
- /* We don't want anybody else emitting things after we jumped
- back. */
- return;
- }
-
- insn = emit_insn (par);
- if (DEFAULT_ABI == ABI_V4)
- {
- if (frame_pointer_needed)
- {
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (frame_reg_rtx, sp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- for (i = info->first_gp_reg_save; i < 32; i++)
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (reg_mode, i), cfa_restores);
- }
+ rs6000_emit_savres_rtx (info, frame_reg_rtx,
+ info->gp_save_offset, reg_mode,
+ /*savep=*/false, /*gpr=*/true,
+ /*lr=*/can_use_exit);
}
else if (using_load_multiple)
{
@@ -21252,17 +21221,8 @@ rs6000_emit_epilogue (int sibcall)
rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, reg, mem);
- if (DEFAULT_ABI == ABI_V4)
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
- insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- if (DEFAULT_ABI == ABI_V4 && frame_pointer_needed)
- {
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (frame_reg_rtx, sp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
}
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
}
else
{
@@ -21276,24 +21236,70 @@ rs6000_emit_epilogue (int sibcall)
rtx mem = gen_frame_mem (reg_mode, addr);
rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
- insn = emit_move_insn (reg, mem);
- if (DEFAULT_ABI == ABI_V4)
- {
- if (frame_pointer_needed
- && info->first_gp_reg_save + i
- == HARD_FRAME_POINTER_REGNUM)
- {
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (frame_reg_rtx, sp_offset));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
- }
+ emit_move_insn (reg, mem);
}
}
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ {
+ /* If the frame pointer was used then we can't delay emitting
+ a REG_CFA_DEF_CFA note. This must happen on the insn that
+ restores the frame pointer, r31. We may have already emitted
+ a REG_CFA_DEF_CFA note, but that's OK; A duplicate is
+ discarded by dwarf2cfi.c/dwarf2out.c, and in any case would
+ be harmless if emitted. */
+ if (frame_pointer_needed)
+ {
+ insn = get_last_insn ();
+ add_reg_note (insn, REG_CFA_DEF_CFA,
+ plus_constant (frame_reg_rtx, sp_offset));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* Set up cfa_restores. We always need these when
+ shrink-wrapping. If not shrink-wrapping then we only need
+ the cfa_restore when the stack location is no longer valid.
+ The cfa_restores must be emitted on or before the insn that
+ invalidates the stack, and of course must not be emitted
+ before the insn that actually does the restore. The latter
+ is why the LR cfa_restore condition below is a little
+ complicated. It's also why it is a bad idea to emit the
+ cfa_restores as a group on the last instruction here that
+ actually does a restore: That insn may be reordered with
+ respect to others doing restores. */
+ if (info->cr_save_p)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (SImode, CR2_REGNO),
+ cfa_restores);
+ if (flag_shrink_wrap
+ && (restore_lr
+ || (info->lr_save_p
+ && !restoring_GPRs_inline
+ && info->first_fp_reg_save == 64)))
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (Pmode, LR_REGNO),
+ cfa_restores);
+
+ for (i = info->first_gp_reg_save; i < 32; i++)
+ if (!restoring_GPRs_inline
+ || using_load_multiple
+ || rs6000_reg_live_or_pic_offset_p (i))
+ {
+ rtx reg = gen_rtx_REG (reg_mode, i);
+
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
+ }
+ }
+
+ if (!restoring_GPRs_inline
+ && info->first_fp_reg_save == 64)
+ {
+ /* We are jumping to an out-of-line function. */
+ if (cfa_restores)
+ emit_cfa_restores (cfa_restores);
+ return;
+ }
+
if (restore_lr && !restoring_GPRs_inline)
{
rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
@@ -21307,8 +21313,8 @@ rs6000_emit_epilogue (int sibcall)
/* Restore fpr's if we need to do it without calling a function. */
if (restoring_FPRs_inline)
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
- if ((df_regs_ever_live_p (info->first_fp_reg_save+i)
- && ! call_used_regs[info->first_fp_reg_save+i]))
+ if ((df_regs_ever_live_p (info->first_fp_reg_save + i)
+ && !call_used_regs[info->first_fp_reg_save + i]))
{
rtx addr, mem, reg;
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
@@ -21322,20 +21328,13 @@ rs6000_emit_epilogue (int sibcall)
info->first_fp_reg_save + i);
emit_move_insn (reg, mem);
- if (DEFAULT_ABI == ABI_V4)
- cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
- cfa_restores);
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg, cfa_restores);
}
/* If we saved cr, restore it here. Just those that were used. */
if (info->cr_save_p)
- {
- rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
- if (DEFAULT_ABI == ABI_V4)
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE, gen_rtx_REG (SImode, CR2_REGNO),
- cfa_restores);
- }
+ rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple);
/* If this is V.4, unwind the stack pointer after all of the loads
have been done. */
@@ -21363,15 +21362,40 @@ rs6000_emit_epilogue (int sibcall)
rtvec p;
bool lr = (strategy & REST_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0;
if (! restoring_FPRs_inline)
- p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
+ {
+ p = rtvec_alloc (4 + 64 - info->first_fp_reg_save);
+ RTVEC_ELT (p, 0) = ret_rtx;
+ }
else
- p = rtvec_alloc (2);
+ {
+ if (cfa_restores)
+ {
+ /* We can't hang the cfa_restores off a simple return,
+ since the shrink-wrap code sometimes uses an existing
+ return. This means there might be a path from
+ pre-prologue code to this return, and dwarf2cfi code
+ wants the eh_frame unwinder state to be the same on
+ all paths to any point. So we need to emit the
+ cfa_restores before the return. For -m64 we really
+ don't need epilogue cfa_restores at all, except for
+ this irritating dwarf2cfi with shrink-wrap
+ requirement; The stack red-zone means eh_frame info
+ from the prologue telling the unwinder to restore
+ from the stack is perfectly good right to the end of
+ the function. */
+ emit_insn (gen_blockage ());
+ emit_cfa_restores (cfa_restores);
+ cfa_restores = NULL_RTX;
+ }
+ p = rtvec_alloc (2);
+ RTVEC_ELT (p, 0) = simple_return_rtx;
+ }
- RTVEC_ELT (p, 0) = ret_rtx;
RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr)
- ? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65))
+ ? gen_rtx_USE (VOIDmode,
+ gen_rtx_REG (Pmode, LR_REGNO))
: gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (Pmode, 65)));
+ gen_rtx_REG (Pmode, LR_REGNO)));
/* If we have to restore more than two FP registers, branch to the
restore function. It will return to our caller. */
@@ -21380,6 +21404,12 @@ rs6000_emit_epilogue (int sibcall)
int i;
rtx sym;
+ if ((DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ && lr)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE,
+ gen_rtx_REG (Pmode, LR_REGNO),
+ cfa_restores);
+
sym = rs6000_savres_routine_sym (info,
/*savep=*/false,
/*gpr=*/false,
@@ -21391,20 +21421,32 @@ rs6000_emit_epilogue (int sibcall)
? 1 : 11));
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
{
- rtx addr, mem;
+ rtx addr, mem, reg;
+
addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
- GEN_INT (info->fp_save_offset + 8*i));
+ GEN_INT (info->fp_save_offset + 8 * i));
mem = gen_frame_mem (DFmode, addr);
+ reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
- RTVEC_ELT (p, i+4) =
- gen_rtx_SET (VOIDmode,
- gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
- mem);
+ RTVEC_ELT (p, i + 4) = gen_rtx_SET (VOIDmode, reg, mem);
+ if (DEFAULT_ABI == ABI_V4 || flag_shrink_wrap)
+ cfa_restores = alloc_reg_note (REG_CFA_RESTORE, reg,
+ cfa_restores);
}
}
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
}
+
+ if (cfa_restores)
+ {
+ if (sibcall)
+ /* Ensure the cfa_restores are hung off an insn that won't
+ be reordered above other restores. */
+ emit_insn (gen_blockage ());
+
+ emit_cfa_restores (cfa_restores);
+ }
}
/* Write function epilogue. */
@@ -21769,7 +21811,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
gen_rtx_USE (VOIDmode,
gen_rtx_REG (SImode,
LR_REGNO)),
- ret_rtx)));
+ simple_return_rtx)));
SIBLING_CALL_P (insn) = 1;
emit_barrier ();
@@ -22493,7 +22535,15 @@ output_function_profiler (FILE *file, int labelno)
}
else if (TARGET_SECURE_PLT && flag_pic)
{
- asm_fprintf (file, "\tbcl 20,31,1f\n1:\n\t{st|stw} %s,4(%s)\n",
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc476_thunk_name (name);
+ asm_fprintf (file, "\tbl %s\n", name);
+ }
+ else
+ asm_fprintf (file, "\tbcl 20,31,1f\n1:\n");
+ asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
reg_names[0], reg_names[1]);
asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
asm_fprintf (file, "\t{cau|addis} %s,%s,",
@@ -22518,10 +22568,24 @@ output_function_profiler (FILE *file, int labelno)
asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
reg_names[0], reg_names[1]);
/* Now, we need to get the address of the label. */
- fputs ("\tbcl 20,31,1f\n\t.long ", file);
- assemble_name (file, buf);
- fputs ("-.\n1:", file);
- asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc476_thunk_name (name);
+ asm_fprintf (file, "\tbl %s\n\tb 1f\n\t.long ", name);
+ assemble_name (file, buf);
+ fputs ("-.\n1:", file);
+ asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
+ asm_fprintf (file, "\taddi %s,%s,4\n",
+ reg_names[11], reg_names[11]);
+ }
+ else
+ {
+ fputs ("\tbcl 20,31,1f\n\t.long ", file);
+ assemble_name (file, buf);
+ fputs ("-.\n1:", file);
+ asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
+ }
asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
reg_names[0], reg_names[11]);
asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
@@ -25004,11 +25068,24 @@ macho_branch_islands (void)
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
if (flag_pic)
{
- strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic\n");
- strcat (tmp_buf, label);
- strcat (tmp_buf, "_pic:\n\tmflr r11\n");
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc64_thunk_name (name);
+ strcat (tmp_buf, ":\n\tmflr r0\n\tbl ");
+ strcat (tmp_buf, name);
+ strcat (tmp_buf, "\n");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic:\n\tmflr r11\n");
+ }
+ else
+ {
+ strcat (tmp_buf, ":\n\tmflr r0\n\tbcl 20,31,");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic\n");
+ strcat (tmp_buf, label);
+ strcat (tmp_buf, "_pic:\n\tmflr r11\n");
+ }
strcat (tmp_buf, "\taddis r11,r11,ha16(");
strcat (tmp_buf, name_buf);
@@ -25154,8 +25231,18 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub)
sprintf (local_label_0, "\"L%011d$spb\"", label);
fprintf (file, "\tmflr r0\n");
- fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
- fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
+ if (TARGET_LINK_STACK)
+ {
+ char name[32];
+ get_ppc476_thunk_name (name);
+ fprintf (file, "\tbl %s\n", name);
+ fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
+ }
+ else
+ {
+ fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
+ fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
+ }
fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n",
lazy_ptr_name, local_label_0);
fprintf (file, "\tmtlr r0\n");
@@ -27862,4 +27949,73 @@ rs6000_save_toc_in_prologue_p (void)
return (cfun && cfun->machine && cfun->machine->save_toc_in_prologue);
}
+/* Fills in the label name that should be used for a 476 link stack thunk. */
+
+void
+get_ppc476_thunk_name (char name[32])
+{
+ gcc_assert (TARGET_LINK_STACK);
+
+ if (HAVE_GAS_HIDDEN)
+ sprintf (name, "__ppc476.get_thunk");
+ else
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPPC476_", 0);
+}
+
+/* This function emits the simple thunk routine that is used to preserve
+ the link stack on the 476 cpu. */
+
+static void
+rs6000_code_end (void)
+{
+ char name[32];
+ tree decl;
+
+ if (!TARGET_LINK_STACK)
+ return;
+
+ get_ppc476_thunk_name (name);
+
+ decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, get_identifier (name),
+ build_function_type_list (void_type_node, NULL_TREE));
+ DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL,
+ NULL_TREE, void_type_node);
+ TREE_PUBLIC (decl) = 1;
+ TREE_STATIC (decl) = 1;
+
+ if (HAVE_GAS_HIDDEN)
+ {
+ DECL_COMDAT_GROUP (decl) = DECL_ASSEMBLER_NAME (decl);
+ targetm.asm_out.unique_section (decl, 0);
+ switch_to_section (get_named_section (decl, NULL, 0));
+ DECL_WEAK (decl) = 1;
+ ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
+ targetm.asm_out.globalize_label (asm_out_file, name);
+ targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN);
+ ASM_DECLARE_FUNCTION_NAME (asm_out_file, name, decl);
+ }
+ else
+ {
+ switch_to_section (text_section);
+ ASM_OUTPUT_LABEL (asm_out_file, name);
+ }
+
+ DECL_INITIAL (decl) = make_node (BLOCK);
+ current_function_decl = decl;
+ init_function_start (decl);
+ first_function_block_is_cold = false;
+ /* Make sure unwind info is emitted for the thunk if needed. */
+ final_start_function (emit_barrier (), asm_out_file, 1);
+
+ fputs ("\tblr\n", asm_out_file);
+
+ final_end_function ();
+ init_insn_lengths ();
+ free_after_compilation (cfun);
+ set_cfun (NULL);
+ current_function_decl = NULL;
+}
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
#include "gt-rs6000.h"
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 2c21fb7ea47..d0cfabb8449 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -313,6 +313,14 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
#define HAVE_AS_TLS 0
#endif
+#ifndef TARGET_LINK_STACK
+#define TARGET_LINK_STACK 0
+#endif
+
+#ifndef SET_TARGET_LINK_STACK
+#define SET_TARGET_LINK_STACK(X) do { } while (0)
+#endif
+
/* Return 1 for a symbol ref for a thread-local storage symbol. */
#define RS6000_SYMBOL_REF_TLS_P(RTX) \
(GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
@@ -894,10 +902,11 @@ extern unsigned rs6000_pointer_size;
cr1 (not saved, but used for FP operations)
cr0 (not saved, but used for arithmetic operations)
cr4, cr3, cr2 (saved)
- r0 (not saved; cannot be base reg)
r9 (not saved; best for TImode)
- r11, r10, r8-r4 (not saved; highest used first to make less conflict)
+ r10, r8-r4 (not saved; highest first for less conflict with params)
r3 (not saved; return value register)
+ r11 (not saved; later alloc to help shrink-wrap)
+ r0 (not saved; cannot be base reg)
r31 - r13 (saved; order given to save least number)
r12 (not saved; if used for DImode or DFmode would use r13)
mq (not saved; best to use it if we can)
@@ -922,6 +931,14 @@ extern unsigned rs6000_pointer_size;
#define MAYBE_R2_FIXED
#endif
+#if FIXED_R13 == 1
+#define EARLY_R12 12,
+#define LATE_R12
+#else
+#define EARLY_R12
+#define LATE_R12 12,
+#endif
+
#define REG_ALLOC_ORDER \
{32, \
45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \
@@ -929,11 +946,11 @@ extern unsigned rs6000_pointer_size;
63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \
50, 49, 48, 47, 46, \
75, 74, 69, 68, 72, 71, 70, \
- 0, MAYBE_R2_AVAILABLE \
- 9, 11, 10, 8, 7, 6, 5, 4, \
- 3, \
+ MAYBE_R2_AVAILABLE \
+ 9, 10, 8, 7, 6, 5, 4, \
+ 3, EARLY_R12 11, 0, \
31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
- 18, 17, 16, 15, 14, 13, 12, \
+ 18, 17, 16, 15, 14, 13, LATE_R12 \
64, 66, 65, \
73, 1, MAYBE_R2_FIXED 67, 76, \
/* AltiVec registers. */ \
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index a2e6fdc2b20..331aa79aac0 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -144,7 +144,7 @@
;; Define an insn type attribute. This is used in function unit delay
;; computations.
-(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel"
+(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,var_delayed_compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,vecdouble,isync,sync,load_l,store_c,shift,trap,insert_dword,var_shift_rotate,cntlz,exts,mffgpr,mftgpr,isel"
(const_string "integer"))
;; Define floating point instruction sub-types for use with Xfpu.md
@@ -264,6 +264,12 @@
; Iterator for just SF/DF
(define_mode_iterator SFDF [SF DF])
+; Conditional returns.
+(define_code_iterator any_return [return simple_return])
+(define_code_attr return_pred [(return "direct_return ()")
+ (simple_return "")])
+(define_code_attr return_str [(return "") (simple_return "simple_")])
+
; Various instructions that come in SI and DI forms.
; A generic w/d attribute, for things like cmpw/cmpd.
(define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")])
@@ -12081,27 +12087,81 @@
[(set_attr "type" "branch")
(set_attr "length" "4")])
-(define_insn "load_toc_v4_PIC_1"
+(define_expand "load_toc_v4_PIC_1"
+ [(parallel [(set (reg:SI LR_REGNO)
+ (match_operand:SI 0 "immediate_operand" "s"))
+ (use (unspec [(match_dup 0)] UNSPEC_TOC))])]
+ "TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
+ "")
+
+(define_insn "load_toc_v4_PIC_1_normal"
[(set (reg:SI LR_REGNO)
(match_operand:SI 0 "immediate_operand" "s"))
(use (unspec [(match_dup 0)] UNSPEC_TOC))]
- "TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX
&& (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"bcl 20,31,%0\\n%0:"
[(set_attr "type" "branch")
(set_attr "length" "4")])
-(define_insn "load_toc_v4_PIC_1b"
+(define_insn "load_toc_v4_PIC_1_476"
+ [(set (reg:SI LR_REGNO)
+ (match_operand:SI 0 "immediate_operand" "s"))
+ (use (unspec [(match_dup 0)] UNSPEC_TOC))]
+ "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
+ "*
+{
+ char name[32];
+ static char templ[32];
+
+ get_ppc476_thunk_name (name);
+ sprintf (templ, \"bl %s\\n%%0:\", name);
+ return templ;
+}"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_expand "load_toc_v4_PIC_1b"
+ [(parallel [(set (reg:SI LR_REGNO)
+ (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
+ (label_ref (match_operand 1 "" ""))]
+ UNSPEC_TOCPTR))
+ (match_dup 1)])]
+ "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "")
+
+(define_insn "load_toc_v4_PIC_1b_normal"
[(set (reg:SI LR_REGNO)
(unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
(label_ref (match_operand 1 "" ""))]
UNSPEC_TOCPTR))
(match_dup 1)]
- "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "!TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
"bcl 20,31,$+8\;.long %0-$"
[(set_attr "type" "branch")
(set_attr "length" "8")])
+(define_insn "load_toc_v4_PIC_1b_476"
+ [(set (reg:SI LR_REGNO)
+ (unspec:SI [(match_operand:SI 0 "immediate_operand" "s")
+ (label_ref (match_operand 1 "" ""))]
+ UNSPEC_TOCPTR))
+ (match_dup 1)]
+ "TARGET_LINK_STACK && TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "*
+{
+ char name[32];
+ static char templ[32];
+
+ get_ppc476_thunk_name (name);
+ sprintf (templ, \"bl %s\\n\\tb $+8\\n\\t.long %%0-$\", name);
+ return templ;
+}"
+ [(set_attr "type" "branch")
+ (set_attr "length" "16")])
+
(define_insn "load_toc_v4_PIC_2"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mem:SI (plus:SI (match_operand:SI 1 "gpc_reg_operand" "b")
@@ -12718,7 +12778,7 @@
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(use (reg:SI LR_REGNO))
- (return)])]
+ (simple_return)])]
""
"
{
@@ -12742,7 +12802,7 @@
(match_operand 1 "" "g,g"))
(use (match_operand:SI 2 "immediate_operand" "O,n"))
(use (reg:SI LR_REGNO))
- (return)]
+ (simple_return)]
"(INTVAL (operands[2]) & CALL_LONG) == 0"
"*
{
@@ -12762,7 +12822,7 @@
(match_operand 1 "" "g,g"))
(use (match_operand:SI 2 "immediate_operand" "O,n"))
(use (reg:SI LR_REGNO))
- (return)]
+ (simple_return)]
"TARGET_64BIT && (INTVAL (operands[2]) & CALL_LONG) == 0"
"*
{
@@ -12783,7 +12843,7 @@
(match_operand 2 "" "g,g")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(use (reg:SI LR_REGNO))
- (return)]
+ (simple_return)]
"(INTVAL (operands[3]) & CALL_LONG) == 0"
"*
{
@@ -12805,7 +12865,7 @@
(match_operand 2 "" "g,g")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(use (reg:SI LR_REGNO))
- (return)]
+ (simple_return)]
"TARGET_64BIT && (INTVAL (operands[3]) & CALL_LONG) == 0"
"*
{
@@ -12825,7 +12885,7 @@
(match_operand 1 "" "g,g"))
(use (match_operand:SI 2 "immediate_operand" "O,O"))
(use (reg:SI LR_REGNO))
- (return)]
+ (simple_return)]
"DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
"@
@@ -12840,7 +12900,7 @@
(match_operand 2 "" "g,g")))
(use (match_operand:SI 3 "immediate_operand" "O,O"))
(use (reg:SI LR_REGNO))
- (return)]
+ (simple_return)]
"DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
"@
@@ -12854,7 +12914,7 @@
(match_operand 1 "" ""))
(use (match_operand 2 "immediate_operand" "O,n,O,n"))
(use (reg:SI LR_REGNO))
- (return)]
+ (simple_return)]
"(DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_V4)
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
@@ -12885,7 +12945,7 @@
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(use (reg:SI LR_REGNO))
- (return)])]
+ (simple_return)])]
""
"
{
@@ -12906,7 +12966,7 @@
(match_operand 2 "" "")))
(use (match_operand:SI 3 "immediate_operand" "O,n,O,n"))
(use (reg:SI LR_REGNO))
- (return)]
+ (simple_return)]
"(DEFAULT_ABI == ABI_DARWIN
|| DEFAULT_ABI == ABI_V4)
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
@@ -15236,9 +15296,9 @@
[(match_operand 1
"cc_reg_operand" "y")
(const_int 0)])
- (return)
+ (any_return)
(pc)))]
- "direct_return ()"
+ "<return_pred>"
"*
{
return output_cbranch (operands[0], NULL, 0, insn);
@@ -15268,8 +15328,8 @@
"cc_reg_operand" "y")
(const_int 0)])
(pc)
- (return)))]
- "direct_return ()"
+ (any_return)))]
+ "<return_pred>"
"*
{
return output_cbranch (operands[0], NULL, 1, insn);
@@ -15399,9 +15459,9 @@
"b %l0"
[(set_attr "type" "branch")])
-(define_insn "return"
- [(return)]
- "direct_return ()"
+(define_insn "<return_str>return"
+ [(any_return)]
+ "<return_pred>"
"{br|blr}"
[(set_attr "type" "jmpreg")])
@@ -15923,7 +15983,7 @@
(set_attr "cell_micro" "always")])
(define_insn "*return_internal_<mode>"
- [(return)
+ [(simple_return)
(use (match_operand:P 0 "register_operand" "lc"))]
""
"b%T0"
diff --git a/gcc/config/rs6000/t-aix43 b/gcc/config/rs6000/t-aix43
index 374b98dfa93..97ce70ecca3 100644
--- a/gcc/config/rs6000/t-aix43
+++ b/gcc/config/rs6000/t-aix43
@@ -44,35 +44,3 @@ MULTILIB_MATCHES = mcpu?power=mcpu?power \
mcpu?powerpc=mcpu?604e \
mcpu?powerpc=mcpu?620 \
mcpu?powerpc=mcpu?630
-
-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 @multilib_dir@ in \
- *pthread*) echo -L/usr/lib/threads -lpthreads -lc_r /usr/lib/libc.a ;; \
- *) echo -lc ;; esac` ; \
- rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
- $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
- @multilib_dir@/shr.o ; \
- mv @multilib_dir@/tmp-@shlib_base_name@.a \
- @multilib_dir@/@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 = \
- $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@; \
- $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \
- $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/
-SHLIB_LIBS = -lc `case @multilib_dir@ in *pthread*) echo -lpthread ;; esac`
-SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
-SHLIB_MAPFILES = $$(libgcc_objdir)/libgcc-std.ver
-SHLIB_NM_FLAGS = -Bpg -X32_64
-
-# Either 32-bit and 64-bit objects in archives.
-AR_FLAGS_FOR_TARGET = -X32_64
-
diff --git a/gcc/config/rs6000/t-aix52 b/gcc/config/rs6000/t-aix52
index 79ef16fd84e..f3bf78d3630 100644
--- a/gcc/config/rs6000/t-aix52
+++ b/gcc/config/rs6000/t-aix52
@@ -25,34 +25,3 @@ 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 @multilib_dir@ in \
- *pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
- *) echo -lc ;; esac` ; \
- rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
- $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
- @multilib_dir@/shr.o ; \
- mv @multilib_dir@/tmp-@shlib_base_name@.a \
- @multilib_dir@/@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 = \
- $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@; \
- $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \
- $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/
-SHLIB_LIBS = -lc `case @multilib_dir@ in *pthread*) echo -lpthread ;; esac`
-SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
-SHLIB_MAPFILES = $$(libgcc_objdir)/libgcc-std.ver
-SHLIB_NM_FLAGS = -Bpg -X32_64
-
-# Either 32-bit and 64-bit objects in archives.
-AR_FLAGS_FOR_TARGET = -X32_64
diff --git a/gcc/config/rs6000/t-darwin b/gcc/config/rs6000/t-darwin
deleted file mode 100644
index 93d6f884999..00000000000
--- a/gcc/config/rs6000/t-darwin
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006,
-# 2007, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/darwin-tramp.asm \
- $(srcdir)/config/darwin-64.c \
- $(srcdir)/config/rs6000/darwin-world.asm
-
-LIB2FUNCS_STATIC_EXTRA = \
- $(srcdir)/config/rs6000/darwin-fpsave.asm \
- $(srcdir)/config/rs6000/darwin-vecsave.asm
-
-# The .asm files above are designed to run on all processors,
-# even though they use AltiVec instructions. -Wa is used because
-# -force_cpusubtype_ALL doesn't work with -dynamiclib.
-#
-# -pipe because there's an assembler bug, 4077127, which causes
-# it to not properly process the first # directive, causing temporary
-# file names to appear in stabs, causing the bootstrap to fail. Using -pipe
-# works around this by not having any temporary file names.
-TARGET_LIBGCC2_CFLAGS = -Wa,-force_cpusubtype_ALL -pipe -mmacosx-version-min=10.4
-
-darwin-fpsave.o: $(srcdir)/config/rs6000/darwin-asm.h
-darwin-tramp.o: $(srcdir)/config/rs6000/darwin-asm.h
diff --git a/gcc/config/rs6000/t-darwin64 b/gcc/config/rs6000/t-darwin64
index 4c50b243873..b0a04c7d89d 100644
--- a/gcc/config/rs6000/t-darwin64
+++ b/gcc/config/rs6000/t-darwin64
@@ -1,11 +1,2 @@
-LIB2_SIDITI_CONV_FUNCS=yes
-
-LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/darwin-tramp.asm \
- $(srcdir)/config/darwin-64.c \
- $(srcdir)/config/rs6000/darwin-world.asm
-
MULTILIB_OPTIONS = m32
MULTILIB_DIRNAMES = ppc
-
-#LIBGCC = stmp-multilib
-#INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/rs6000/t-fprules b/gcc/config/rs6000/t-fprules
index 42d8fd77b5b..913bbbdae69 100644
--- a/gcc/config/rs6000/t-fprules
+++ b/gcc/config/rs6000/t-fprules
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2005, 2006, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2005, 2006, 2008, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -33,6 +33,3 @@ MULTILIB_MATCHES_FLOAT = msoft-float=mcpu?401 \
MULTILIB_OPTIONS = msoft-float
MULTILIB_DIRNAMES = soft-float
MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT}
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/rs6000/t-linux64 b/gcc/config/rs6000/t-linux64
index bd01d319212..6420431214d 100644
--- a/gcc/config/rs6000/t-linux64
+++ b/gcc/config/rs6000/t-linux64
@@ -19,8 +19,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-TARGET_LIBGCC2_CFLAGS += -mno-minimal-toc
-
# On Debian, Ubuntu and other derivative distributions, the 32bit libraries
# are found in /lib32 and /usr/lib32, /lib64 and /usr/lib64 are symlinks to
# /lib and /usr/lib, while other distributions install libraries into /lib64
diff --git a/gcc/config/rs6000/t-lynx b/gcc/config/rs6000/t-lynx
index 768856e06eb..fdc5b56daed 100644
--- a/gcc/config/rs6000/t-lynx
+++ b/gcc/config/rs6000/t-lynx
@@ -16,14 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB2FUNCS_EXTRA = tramp.S
-
-tramp.S: $(srcdir)/config/rs6000/tramp.asm
- cat $(srcdir)/config/rs6000/tramp.asm > tramp.S
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
MULTILIB_OPTIONS += msoft-float
MULTILIB_DIRNAMES += soft-float
@@ -32,15 +24,6 @@ MULTILIB_DIRNAMES += altivec
MULTILIB_EXCEPTIONS = *msoft-float/*maltivec*
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
-
-# If .sdata is enabled __CTOR_{LIST,END}__ go into .sdata instead of
-# .ctors.
-CRTSTUFF_T_CFLAGS = -mno-sdata
-
-# Compile crtbeginS.o and crtendS.o with pic.
-CRTSTUFF_T_CFLAGS_S = -fPIC -mno-sdata
-
Local Variables:
mode: makefile
End:
diff --git a/gcc/config/rs6000/t-netbsd b/gcc/config/rs6000/t-netbsd
index bad21beaac6..462f0ce7536 100644
--- a/gcc/config/rs6000/t-netbsd
+++ b/gcc/config/rs6000/t-netbsd
@@ -1,6 +1,6 @@
# Support for NetBSD PowerPC ELF targets (SVR4 ABI).
#
-# Copyright (C) 2002, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2008, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -18,37 +18,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB2FUNCS_EXTRA = tramp.S
-
-LIB2FUNCS_STATIC_EXTRA = crtsavfpr.S crtresfpr.S \
- crtsavgpr.S crtresgpr.S \
- crtresxfpr.S crtresxgpr.S
-
-tramp.S: $(srcdir)/config/rs6000/tramp.asm
- cat $(srcdir)/config/rs6000/tramp.asm > tramp.S
-
-crtsavfpr.S: $(srcdir)/config/rs6000/crtsavfpr.asm
- cat $(srcdir)/config/rs6000/crtsavfpr.asm >crtsavfpr.S
-
-crtresfpr.S: $(srcdir)/config/rs6000/crtresfpr.asm
- cat $(srcdir)/config/rs6000/crtresfpr.asm >crtresfpr.S
-
-crtsavgpr.S: $(srcdir)/config/rs6000/crtsavgpr.asm
- cat $(srcdir)/config/rs6000/crtsavgpr.asm >crtsavgpr.S
-
-crtresgpr.S: $(srcdir)/config/rs6000/crtresgpr.asm
- cat $(srcdir)/config/rs6000/crtresgpr.asm >crtresgpr.S
-
-crtresxfpr.S: $(srcdir)/config/rs6000/crtresxfpr.asm
- cat $(srcdir)/config/rs6000/crtresxfpr.asm >crtresxfpr.S
-
-crtresxgpr.S: $(srcdir)/config/rs6000/crtresxgpr.asm
- cat $(srcdir)/config/rs6000/crtresxgpr.asm >crtresxgpr.S
-
-# 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 \
@@ -65,26 +34,3 @@ 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)
-
-$(T)crtsavfpr$(objext): crtsavfpr.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtsavfpr.S -o $(T)crtsavfpr$(objext)
-
-$(T)crtresfpr$(objext): crtresfpr.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtresfpr.S -o $(T)crtresfpr$(objext)
-
-$(T)crtsavgpr$(objext): crtsavgpr.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtsavgpr.S -o $(T)crtsavgpr$(objext)
-
-$(T)crtresgpr$(objext): crtresgpr.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtresgpr.S -o $(T)crtresgpr$(objext)
-
-$(T)crtresxfpr$(objext): crtresxfpr.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtresxfpr.S -o $(T)crtresxfpr$(objext)
-
-$(T)crtresxgpr$(objext): crtresxgpr.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c crtresxgpr.S -o $(T)crtresxgpr$(objext)
diff --git a/gcc/config/rs6000/t-ppccomm b/gcc/config/rs6000/t-ppccomm
index b7e07a9b4c9..81ab7effa42 100644
--- a/gcc/config/rs6000/t-ppccomm
+++ b/gcc/config/rs6000/t-ppccomm
@@ -19,57 +19,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB2FUNCS_EXTRA += tramp.S
-
-# These can't end up in shared libgcc
-LIB2FUNCS_STATIC_EXTRA = eabi.S
-
-eabi.S: $(srcdir)/config/rs6000/eabi.asm
- cat $(srcdir)/config/rs6000/eabi.asm > eabi.S
-
-tramp.S: $(srcdir)/config/rs6000/tramp.asm
- cat $(srcdir)/config/rs6000/tramp.asm > tramp.S
-
# Switch synonyms
MULTILIB_MATCHES_ENDIAN = mlittle=mlittle-endian mbig=mbig-endian
MULTILIB_MATCHES_SYSV = mcall-sysv=mcall-sysv-eabi mcall-sysv=mcall-sysv-noeabi mcall-sysv=mcall-linux mcall-sysv=mcall-netbsd
-
-EXTRA_MULTILIB_PARTS = crtbegin$(objext) crtend$(objext) \
- crtbeginS$(objext) crtendS$(objext) crtbeginT$(objext) \
- ecrti$(objext) ecrtn$(objext) \
- ncrti$(objext) ncrtn$(objext)
-
-# We build {e,n}crti.o and {e,n}crtn.o, which serve to add begin and
-# end labels to all of the special sections used when we link using gcc.
-
-# Assemble startup files.
-ecrti.S: $(srcdir)/config/rs6000/eabi-ci.asm
- cat $(srcdir)/config/rs6000/eabi-ci.asm >ecrti.S
-
-ecrtn.S: $(srcdir)/config/rs6000/eabi-cn.asm
- cat $(srcdir)/config/rs6000/eabi-cn.asm >ecrtn.S
-
-ncrti.S: $(srcdir)/config/rs6000/sol-ci.asm
- cat $(srcdir)/config/rs6000/sol-ci.asm >ncrti.S
-
-ncrtn.S: $(srcdir)/config/rs6000/sol-cn.asm
- cat $(srcdir)/config/rs6000/sol-cn.asm >ncrtn.S
-
-# Build multiple copies of ?crt{i,n}.o, one for each target switch.
-$(T)ecrti$(objext): ecrti.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c ecrti.S -o $(T)ecrti$(objext)
-
-$(T)ecrtn$(objext): ecrtn.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c ecrtn.S -o $(T)ecrtn$(objext)
-
-$(T)ncrti$(objext): ncrti.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c ncrti.S -o $(T)ncrti$(objext)
-
-$(T)ncrtn$(objext): ncrtn.S
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -c ncrtn.S -o $(T)ncrtn$(objext)
-
-# It is important that crtbegin.o, etc., aren't surprised by stuff in .sdata.
-CRTSTUFF_T_CFLAGS = -msdata=none
-# Make sure crt*.o are built with -fPIC even if configured with
-# --enable-shared --disable-multilib
-CRTSTUFF_T_CFLAGS_S = -fPIC -msdata=none
diff --git a/gcc/config/rs6000/t-spe b/gcc/config/rs6000/t-spe
index cbbac79f661..1bed1e32b0e 100644
--- a/gcc/config/rs6000/t-spe
+++ b/gcc/config/rs6000/t-spe
@@ -18,9 +18,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
# What we really want are these variants:
# -mcpu=7400
# -mcpu=7400 -maltivec -mabi=altivec
diff --git a/gcc/config/rs6000/t-vxworks b/gcc/config/rs6000/t-vxworks
index 8a3d394ed77..c0128ed845f 100644
--- a/gcc/config/rs6000/t-vxworks
+++ b/gcc/config/rs6000/t-vxworks
@@ -1,6 +1,6 @@
# Multilibs for VxWorks.
#
-# Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2005, 2006, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -23,12 +23,3 @@ MULTILIB_OPTIONS = mrtp fPIC msoft-float
MULTILIB_DIRNAMES =
MULTILIB_MATCHES = fPIC=fpic
MULTILIB_EXCEPTIONS = fPIC*
-
-# This is set from the common config/t-vxworks but clobbered by t-ppccomm
-# on this target.
-EXTRA_MULTILIB_PARTS =
-
-# Similarily, LIB2FUNCS_EXTRA is set from config/t-vxworks and
-# t-ppccomm *adds* to it, but the common contents are useful to us.
-# In particular the base trampoline_setup bits are expected to be
-# provided there.
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index e859af36e11..fb860342304 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -120,7 +120,7 @@
(DF "s")])
;; Appropriate type for add ops (and other simple FP ops)
-(define_mode_attr VStype_simple [(V2DF "vecfloat")
+(define_mode_attr VStype_simple [(V2DF "vecdouble")
(V4SF "vecfloat")
(DF "fp")])
@@ -129,7 +129,7 @@
(DF "fp_addsub_d")])
;; Appropriate type for multiply ops
-(define_mode_attr VStype_mul [(V2DF "vecfloat")
+(define_mode_attr VStype_mul [(V2DF "vecdouble")
(V4SF "vecfloat")
(DF "dmul")])
@@ -137,10 +137,9 @@
(V4SF "fp_mul_s")
(DF "fp_mul_d")])
-;; Appropriate type for divide ops. For now, just lump the vector divide with
-;; the scalar divides
-(define_mode_attr VStype_div [(V2DF "ddiv")
- (V4SF "sdiv")
+;; Appropriate type for divide ops.
+(define_mode_attr VStype_div [(V2DF "vecdiv")
+ (V4SF "vecfdiv")
(DF "ddiv")])
(define_mode_attr VSfptype_div [(V2DF "fp_div_d")
@@ -150,8 +149,8 @@
;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with
;; the scalar sqrt
(define_mode_attr VStype_sqrt [(V2DF "dsqrt")
- (V4SF "sdiv")
- (DF "ddiv")])
+ (V4SF "ssqrt")
+ (DF "dsqrt")])
(define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d")
(V4SF "fp_sqrt_s")
@@ -171,8 +170,8 @@
(V2DF "xvcvdpsp")])
(define_mode_attr VS_spdp_type [(DF "fp")
- (V4SF "vecfloat")
- (V2DF "vecfloat")])
+ (V4SF "vecdouble")
+ (V2DF "vecdouble")])
;; Map the scalar mode for a vector type
(define_mode_attr VS_scalar [(V2DF "DF")
@@ -572,7 +571,7 @@
xvmaddmdp %x0,%x1,%x3
xvmaddadp %x0,%x1,%x2
xvmaddmdp %x0,%x1,%x3"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
(define_insn "*vsx_fmsdf4"
[(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
@@ -604,7 +603,7 @@
x<VSv>msubm<VSs> %x0,%x1,%x3
x<VSv>msuba<VSs> %x0,%x1,%x2
x<VSv>msubm<VSs> %x0,%x1,%x3"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "<VStype_mul>")])
(define_insn "*vsx_nfmadf4"
[(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,d")
@@ -688,7 +687,7 @@
xvnmsubmdp %x0,%x1,%x3
xvnmsubadp %x0,%x1,%x2
xvnmsubmdp %x0,%x1,%x3"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
;; Vector conditional expressions (no scalar version for these instructions)
(define_insn "vsx_eq<mode>"
@@ -741,7 +740,7 @@
(match_dup 2)))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"xvcmpeq<VSs>. %x0,%x1,%x2"
- [(set_attr "type" "veccmp")])
+ [(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_gt_<mode>_p"
[(set (reg:CC 74)
@@ -754,7 +753,7 @@
(match_dup 2)))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"xvcmpgt<VSs>. %x0,%x1,%x2"
- [(set_attr "type" "veccmp")])
+ [(set_attr "type" "<VStype_simple>")])
(define_insn "*vsx_ge_<mode>_p"
[(set (reg:CC 74)
@@ -767,7 +766,7 @@
(match_dup 2)))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
"xvcmpge<VSs>. %x0,%x1,%x2"
- [(set_attr "type" "veccmp")])
+ [(set_attr "type" "<VStype_simple>")])
;; Vector select
(define_insn "*vsx_xxsel<mode>"
@@ -948,7 +947,7 @@
UNSPEC_VSX_CVDPSXWS))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvdpsxws %x0,%x1"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvdpuxws"
[(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
@@ -956,7 +955,7 @@
UNSPEC_VSX_CVDPUXWS))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvdpuxws %x0,%x1"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvsxdsp"
[(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa")
@@ -972,7 +971,7 @@
UNSPEC_VSX_CVUXDSP))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvuxwdp %x0,%x1"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
;; Convert from 32-bit to 64-bit types
(define_insn "vsx_xvcvsxwdp"
@@ -981,7 +980,7 @@
UNSPEC_VSX_CVSXWDP))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvsxwdp %x0,%x1"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvuxwdp"
[(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
@@ -989,7 +988,7 @@
UNSPEC_VSX_CVUXWDP))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvuxwdp %x0,%x1"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvspsxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
@@ -997,7 +996,7 @@
UNSPEC_VSX_CVSPSXDS))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvspsxds %x0,%x1"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
(define_insn "vsx_xvcvspuxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
@@ -1005,7 +1004,7 @@
UNSPEC_VSX_CVSPUXDS))]
"VECTOR_UNIT_VSX_P (V2DFmode)"
"xvcvspuxds %x0,%x1"
- [(set_attr "type" "vecfloat")])
+ [(set_attr "type" "vecdouble")])
;; Only optimize (float (fix x)) -> frz if we are in fast-math mode, since
;; since the xsrdpiz instruction does not truncate the value if the floating
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c
index 6ff9418c9d8..c9720eb3e15 100644
--- a/gcc/config/rx/rx.c
+++ b/gcc/config/rx/rx.c
@@ -637,7 +637,7 @@ rx_print_operand (FILE * file, rtx op, int letter)
case 0xb: fprintf (file, "fintv"); break;
case 0xc: fprintf (file, "intb"); break;
default:
- warning (0, "unreocgnized control register number: %d - using 'psw'",
+ warning (0, "unrecognized control register number: %d - using 'psw'",
(int) INTVAL (op));
fprintf (file, "psw");
break;
diff --git a/gcc/config/rx/t-rx b/gcc/config/rx/t-rx
index ad667bcc5c9..9a5dca9056a 100644
--- a/gcc/config/rx/t-rx
+++ b/gcc/config/rx/t-rx
@@ -27,8 +27,3 @@ MULTILIB_MATCHES = nofpu=mnofpu nofpu=mcpu?rx200
MULTILIB_EXCEPTIONS =
MULTILIB_EXTRA_OPTS =
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
diff --git a/gcc/config/score/crti.asm b/gcc/config/score/crti.asm
deleted file mode 100644
index 4cd00cf9914..00000000000
--- a/gcc/config/score/crti.asm
+++ /dev/null
@@ -1,131 +0,0 @@
-# crti.asm for Sunplus S+CORE
-#
-# Copyright (C) 2005, 2009, 2010 Free Software Foundation, Inc.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file makes a stack frame for the contents of the .init and
-# .fini sections.
-.extern _stack
-
-#ifndef __pic__
-.section .init, "ax", @progbits
- .weak _start
- .ent _start
- .frame r0, 0, r3, 0
- .mask 0x00000000, 0
-_start:
- la r28, _gp
- la r8, __bss_start
- la r9, __bss_end__
- sub! r9, r8
- srli! r9, 2
- addi r9, -1
- mtsr r9, sr0
- li r9, 0
-1:
- sw r9, [r8]+, 4
- bcnz 1b
- la r0, _stack
- jl _init
- la r4, _end
- jl _init_argv
- jl exit
- .end _start
-
- .weak _init_argv
- .ent
- .frame r0, 0, r3, 0
- .mask 0x00000000, 0
-_init_argv:
- ldiu! r4, 0
- ldiu! r5, 0
- j main
- .end _init_argv
-
- .globl _init
- .type _init, %function
-_init:
- addi r0, -32
- sw r3, [r0, 20]
-
- .section .fini, "ax", @progbits
- .globl _fini
- .type _fini, %function
-_fini:
- addi r0, -32
- sw r3, [r0, 20]
-#else
-.section .init, "ax", @progbits
- .set pic
- .weak _start
- .ent _start
- .frame r0, 0, r3, 0
- .mask 0x00000000, 0
-_start:
- mv r29, r3
- bl 0f
-0:
- .cpload r3
- mv r3, r29
- la r8, __bss_start
- la r9, __bss_end__
- sub! r9, r8
- srli! r9, 2
- addi r9, -1
- mtsr r9, sr0
- li r9, 0
-1:
- sw r9, [r8]+, 4
- bcnz 1b
- la r0, _stack
- bl _init
- la r4, _end
- la r29, _init_argv
- brl r29
- la r29, exit
- brl r29
- .end _start
-
- .weak _init_argv
- .ent _init_argv
- .frame r0, 0, r3, 0
- .mask 0x00000000, 0
-_init_argv:
- ldiu! r4, 0
- ldiu! r5, 0
- la r29, main
- brl r29
- .end _init_argv
-
- .globl _init
- .type _init, %function
-_init:
- addi r0, -32
- sw r3, [r0, 20]
-
- .section .fini, "ax", @progbits
- .globl _fini
- .type _fini, %function
-_fini:
- addi r0, -32
- sw r3, [r0, 20]
-
-#endif
diff --git a/gcc/config/score/crtn.asm b/gcc/config/score/crtn.asm
deleted file mode 100644
index 8132388a0c7..00000000000
--- a/gcc/config/score/crtn.asm
+++ /dev/null
@@ -1,50 +0,0 @@
-# crtn.asm for Sunplus S+CORE
-
-# Copyright (C) 2005, 2009, 2010 Free Software Foundation, Inc.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file makes sure that the .init and .fini sections do in
-# fact return.
-
-#ifndef __pic__
-.section .init, "ax", @progbits
- lw r3, [r0, 20]
- addi r0, 32
- br r3
-
-.section .fini, "ax", @progbits
- lw r3, [r0, 20]
- addi r0, 32
- br r3
-#else
- .set pic
-.section .init, "ax", @progbits
- lw r3, [r0, 20]
- addi r0, 32
- br r3
-
- .set pic
-.section .fini, "ax", @progbits
- lw r3, [r0, 20]
- addi r0, 32
- br r3
-#endif
-
diff --git a/gcc/config/score/t-score-elf b/gcc/config/score/t-score-elf
deleted file mode 100644
index fd080c1b1fe..00000000000
--- a/gcc/config/score/t-score-elf
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2006, 2007, 2008, 2009, 2010 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Assemble startup files.
-$(T)crti.o: $(srcdir)/config/score/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/score/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/score/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/score/crtn.asm
diff --git a/gcc/config/sh/crt1.asm b/gcc/config/sh/crt1.asm
deleted file mode 100644
index e2857904f86..00000000000
--- a/gcc/config/sh/crt1.asm
+++ /dev/null
@@ -1,1369 +0,0 @@
-/* Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2009
- Free Software Foundation, Inc.
- This file was pretty much copied from newlib.
-
-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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-#ifdef MMU_SUPPORT
- /* Section used for exception/timer interrupt stack area */
- .section .data.vbr.stack,"aw"
- .align 4
- .global __ST_VBR
-__ST_VBR:
- .zero 1024 * 2 /* ; 2k for VBR handlers */
-/* Label at the highest stack address where the stack grows from */
-__timer_stack:
-#endif /* MMU_SUPPORT */
-
- /* ;----------------------------------------
- Normal newlib crt1.asm */
-
-#ifdef __SH5__
- .section .data,"aw"
- .global ___data
-___data:
-
- .section .rodata,"a"
- .global ___rodata
-___rodata:
-
-#define ICCR_BASE 0x01600000
-#define OCCR_BASE 0x01e00000
-#define MMUIR_BASE 0x00000000
-#define MMUDR_BASE 0x00800000
-
-#define PTE_ENABLED 1
-#define PTE_DISABLED 0
-
-#define PTE_SHARED (1 << 1)
-#define PTE_NOT_SHARED 0
-
-#define PTE_CB_UNCACHEABLE 0
-#define PTE_CB_DEVICE 1
-#define PTE_CB_CACHEABLE_WB 2
-#define PTE_CB_CACHEABLE_WT 3
-
-#define PTE_SZ_4KB (0 << 3)
-#define PTE_SZ_64KB (1 << 3)
-#define PTE_SZ_1MB (2 << 3)
-#define PTE_SZ_512MB (3 << 3)
-
-#define PTE_PRR (1 << 6)
-#define PTE_PRX (1 << 7)
-#define PTE_PRW (1 << 8)
-#define PTE_PRU (1 << 9)
-
-#define SR_MMU_BIT 31
-#define SR_BL_BIT 28
-
-#define ALIGN_4KB (0xfff)
-#define ALIGN_1MB (0xfffff)
-#define ALIGN_512MB (0x1fffffff)
-
-#define DYNACON_BASE 0x0f000000
-#define DM_CB_DLINK_BASE 0x0c000000
-#define DM_DB_DLINK_BASE 0x0b000000
-
-#define FEMI_AREA_0 0x00000000
-#define FEMI_AREA_1 0x04000000
-#define FEMI_AREA_2 0x05000000
-#define FEMI_AREA_3 0x06000000
-#define FEMI_AREA_4 0x07000000
-#define FEMI_CB 0x08000000
-
-#define EMI_BASE 0X80000000
-
-#define DMA_BASE 0X0e000000
-
-#define CPU_BASE 0X0d000000
-
-#define PERIPH_BASE 0X09000000
-#define DMAC_BASE 0x0e000000
-#define INTC_BASE 0x0a000000
-#define CPRC_BASE 0x0a010000
-#define TMU_BASE 0x0a020000
-#define SCIF_BASE 0x0a030000
-#define RTC_BASE 0x0a040000
-
-
-
-#define LOAD_CONST32(val, reg) \
- movi ((val) >> 16) & 65535, reg; \
- shori (val) & 65535, reg
-
-#define LOAD_PTEH_VAL(sym, align, bits, scratch_reg, reg) \
- LOAD_ADDR (sym, reg); \
- LOAD_CONST32 ((align), scratch_reg); \
- andc reg, scratch_reg, reg; \
- LOAD_CONST32 ((bits), scratch_reg); \
- or reg, scratch_reg, reg
-
-#define LOAD_PTEL_VAL(sym, align, bits, scratch_reg, reg) \
- LOAD_ADDR (sym, reg); \
- LOAD_CONST32 ((align), scratch_reg); \
- andc reg, scratch_reg, reg; \
- LOAD_CONST32 ((bits), scratch_reg); \
- or reg, scratch_reg, reg
-
-#define SET_PTE(pte_addr_reg, pteh_val_reg, ptel_val_reg) \
- putcfg pte_addr_reg, 0, r63; \
- putcfg pte_addr_reg, 1, ptel_val_reg; \
- putcfg pte_addr_reg, 0, pteh_val_reg
-
-#if __SH5__ == 64
- .section .text,"ax"
-#define LOAD_ADDR(sym, reg) \
- movi (sym >> 48) & 65535, reg; \
- shori (sym >> 32) & 65535, reg; \
- shori (sym >> 16) & 65535, reg; \
- shori sym & 65535, reg
-#else
- .mode SHmedia
- .section .text..SHmedia32,"ax"
-#define LOAD_ADDR(sym, reg) \
- movi (sym >> 16) & 65535, reg; \
- shori sym & 65535, reg
-#endif
- .global start
-start:
- LOAD_ADDR (_stack, r15)
-
-#ifdef MMU_SUPPORT
- ! Set up the VM using the MMU and caches
-
- ! .vm_ep is first instruction to execute
- ! after VM initialization
- pt/l .vm_ep, tr1
-
- ! Configure instruction cache (ICCR)
- movi 3, r2
- movi 0, r3
- LOAD_ADDR (ICCR_BASE, r1)
- putcfg r1, 0, r2
- putcfg r1, 1, r3
-
- ! movi 7, r2 ! write through
- ! Configure operand cache (OCCR)
- LOAD_ADDR (OCCR_BASE, r1)
- putcfg r1, 0, r2
- putcfg r1, 1, r3
-
- ! Disable all PTE translations
- LOAD_ADDR (MMUIR_BASE, r1)
- LOAD_ADDR (MMUDR_BASE, r2)
- movi 64, r3
- pt/l .disable_ptes_loop, tr0
-.disable_ptes_loop:
- putcfg r1, 0, r63
- putcfg r2, 0, r63
- addi r1, 16, r1
- addi r2, 16, r2
- addi r3, -1, r3
- bgt r3, r63, tr0
-
- LOAD_ADDR (MMUIR_BASE, r1)
-
- ! FEMI instruction mappings
- ! Area 0 - 1Mb cacheable at 0x00000000
- ! Area 1 - None
- ! Area 2 - 1Mb cacheable at 0x05000000
- ! - 1Mb cacheable at 0x05100000
- ! Area 3 - None
- ! Area 4 - None
-
- ! Map a 1Mb page for instructions at 0x00000000
- LOAD_PTEH_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1Mb page for instructions at 0x05000000
- addi r1, 16, r1
- LOAD_PTEH_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1Mb page for instructions at 0x05100000
- addi r1, 16, r1
- LOAD_PTEH_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 512M page for instructions at EMI base
- addi r1, 16, r1
- LOAD_PTEH_VAL (EMI_BASE, ALIGN_512MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (EMI_BASE, ALIGN_512MB, PTE_CB_CACHEABLE_WB | PTE_SZ_512MB | PTE_PRX | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 4K page for instructions at DM_DB_DLINK_BASE
- addi r1, 16, r1
- LOAD_PTEH_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRX | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- LOAD_ADDR (MMUDR_BASE, r1)
-
- ! FEMI data mappings
- ! Area 0 - 1Mb cacheable at 0x00000000
- ! Area 1 - 1Mb device at 0x04000000
- ! Area 2 - 1Mb cacheable at 0x05000000
- ! - 1Mb cacheable at 0x05100000
- ! Area 3 - None
- ! Area 4 - None
- ! CB - 1Mb device at 0x08000000
-
- ! Map a 1Mb page for data at 0x00000000
- LOAD_PTEH_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1Mb page for data at 0x04000000
- addi r1, 16, r1
- LOAD_PTEH_VAL (FEMI_AREA_1, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (FEMI_AREA_1, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1Mb page for data at 0x05000000
- addi r1, 16, r1
- LOAD_PTEH_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1Mb page for data at 0x05100000
- addi r1, 16, r1
- LOAD_PTEH_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 4K page for registers at 0x08000000
- addi r1, 16, r1
- LOAD_PTEH_VAL (FEMI_CB, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (FEMI_CB, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 512M page for data at EMI
- addi r1, 16, r1
- LOAD_PTEH_VAL (EMI_BASE, ALIGN_512MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (EMI_BASE, ALIGN_512MB, PTE_CB_CACHEABLE_WB | PTE_SZ_512MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 4K page for DYNACON at DYNACON_BASE
- addi r1, 16, r1
- LOAD_PTEH_VAL (DYNACON_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (DYNACON_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 4K page for instructions at DM_DB_DLINK_BASE
- addi r1, 16, r1
- LOAD_PTEH_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 4K page for data at DM_DB_DLINK_BASE+0x1000
- addi r1, 16, r1
- LOAD_PTEH_VAL ((DM_DB_DLINK_BASE+0x1000), ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((DM_DB_DLINK_BASE+0x1000), ALIGN_4KB, PTE_CB_UNCACHEABLE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 4K page for stack DM_DB_DLINK_BASE+0x2000
- addi r1, 16, r1
- LOAD_PTEH_VAL ((DM_DB_DLINK_BASE+0x2000), ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((DM_DB_DLINK_BASE+0x2000), ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
- ! 0x0c000000 - 0x0c0fffff
- addi r1, 16, r1
- LOAD_PTEH_VAL (DM_CB_DLINK_BASE, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (DM_CB_DLINK_BASE, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
- ! 0x0c100000 - 0x0c1fffff
- addi r1, 16, r1
- LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x100000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
- ! 0x0c200000 - 0x0c2fffff
- addi r1, 16, r1
- LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x200000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x200000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
- ! 0x0c400000 - 0x0c4fffff
- addi r1, 16, r1
- LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x400000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x400000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
- ! 0x0c800000 - 0x0c8fffff
- addi r1, 16, r1
- LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x800000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x800000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map a 4K page for DMA control registers
- addi r1, 16, r1
- LOAD_PTEH_VAL (DMA_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (DMA_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map lots of 4K pages for peripherals
-
- ! /* peripheral */
- addi r1, 16, r1
- LOAD_PTEH_VAL (PERIPH_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (PERIPH_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
- ! /* dmac */
- addi r1, 16, r1
- LOAD_PTEH_VAL (DMAC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (DMAC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
- ! /* intc */
- addi r1, 16, r1
- LOAD_PTEH_VAL (INTC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (INTC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
- ! /* rtc */
- addi r1, 16, r1
- LOAD_PTEH_VAL (RTC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (RTC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
- ! /* dmac */
- addi r1, 16, r1
- LOAD_PTEH_VAL (TMU_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (TMU_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
- ! /* scif */
- addi r1, 16, r1
- LOAD_PTEH_VAL (SCIF_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (SCIF_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
- ! /* cprc */
- addi r1, 16, r1
- LOAD_PTEH_VAL (CPRC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (CPRC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Map CPU WPC registers
- addi r1, 16, r1
- LOAD_PTEH_VAL (CPU_BASE, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL (CPU_BASE, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
- addi r1, 16, r1
-
- LOAD_PTEH_VAL ((CPU_BASE+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((CPU_BASE+0x100000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- addi r1, 16, r1
- LOAD_PTEH_VAL ((CPU_BASE+0x200000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((CPU_BASE+0x200000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- addi r1, 16, r1
- LOAD_PTEH_VAL ((CPU_BASE+0x400000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
- LOAD_PTEL_VAL ((CPU_BASE+0x400000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
- SET_PTE (r1, r2, r3)
-
- ! Switch over to virtual addressing and enabled cache
- getcon sr, r1
- movi 1, r2
- shlli r2, SR_BL_BIT, r2
- or r1, r2, r1
- putcon r1, ssr
- getcon sr, r1
- movi 1, r2
- shlli r2, SR_MMU_BIT, r2
- or r1, r2, r1
- putcon r1, ssr
- gettr tr1, r1
- putcon r1, spc
- synco
- rte
-
- ! VM entry point. From now on, we are in VM mode.
-.vm_ep:
-
- ! Install the trap handler, by seeding vbr with the
- ! correct value, and by assigning sr.bl = 0.
-
- LOAD_ADDR (vbr_start, r1)
- putcon r1, vbr
- movi ~(1<<28), r1
- getcon sr, r2
- and r1, r2, r2
- putcon r2, sr
-#endif /* MMU_SUPPORT */
-
- pt/l .Lzero_bss_loop, tr0
- pt/l _init, tr5
- pt/l ___setup_argv_and_call_main, tr6
- pt/l _exit, tr7
-
- ! zero out bss
- LOAD_ADDR (_edata, r0)
- LOAD_ADDR (_end, r1)
-.Lzero_bss_loop:
- stx.q r0, r63, r63
- addi r0, 8, r0
- bgt/l r1, r0, tr0
-
- LOAD_ADDR (___data, r26)
- LOAD_ADDR (___rodata, r27)
-
-#ifdef __SH_FPU_ANY__
- getcon sr, r0
- ! enable the FP unit, by resetting SR.FD
- ! also zero out SR.FR, SR.SZ and SR.PR, as mandated by the ABI
- movi 0, r1
- shori 0xf000, r1
- andc r0, r1, r0
- putcon r0, sr
-#if __SH5__ == 32
- pt/l ___set_fpscr, tr0
- movi 0, r4
- blink tr0, r18
-#endif
-#endif
-
- ! arrange for exit to call fini
- pt/l _atexit, tr1
- LOAD_ADDR (_fini, r2)
- blink tr1, r18
-
- ! call init
- blink tr5, r18
-
- ! call the mainline
- blink tr6, r18
-
- ! call exit
- blink tr7, r18
- ! We should never return from _exit but in case we do we would enter the
- ! the following tight loop. This avoids executing any data that might follow.
-limbo:
- pt/l limbo, tr0
- blink tr0, r63
-
-#ifdef MMU_SUPPORT
- ! All these traps are handled in the same place.
- .balign 256
-vbr_start:
- pt/l handler, tr0 ! tr0 trashed.
- blink tr0, r63
- .balign 256
-vbr_100:
- pt/l handler, tr0 ! tr0 trashed.
- blink tr0, r63
-vbr_100_end:
- .balign 256
-vbr_200:
- pt/l handler, tr0 ! tr0 trashed.
- blink tr0, r63
- .balign 256
-vbr_300:
- pt/l handler, tr0 ! tr0 trashed.
- blink tr0, r63
- .balign 256
-vbr_400: ! Should be at vbr+0x400
-handler:
- /* If the trap handler is there call it */
- LOAD_ADDR (__superh_trap_handler, r2)
- pta chandler,tr2
- beq r2, r63, tr2 /* If zero, ie not present branch around to chandler */
- /* Now call the trap handler with as much of the context unchanged as possible.
- Move trapping address into R18 to make it look like the trap point */
- getcon spc, r18
- pt/l __superh_trap_handler, tr0
- blink tr0, r7
-chandler:
- getcon spc, r62
- getcon expevt, r2
- pt/l _exit, tr0
- blink tr0, r63
-
- /* Simulated trap handler */
- .section .text..SHmedia32,"ax"
-gcc2_compiled.:
- .section .debug_abbrev
-.Ldebug_abbrev0:
- .section .text..SHmedia32
-.Ltext0:
- .section .debug_info
-.Ldebug_info0:
- .section .debug_line
-.Ldebug_line0:
- .section .text..SHmedia32,"ax"
- .align 5
- .global __superh_trap_handler
- .type __superh_trap_handler,@function
-__superh_trap_handler:
-.LFB1:
- ptabs r18, tr0
- addi.l r15, -8, r15
- st.l r15, 4, r14
- addi.l r15, -8, r15
- add.l r15, r63, r14
- st.l r14, 0, r2
- ptabs r7, tr0
- addi.l r14, 8, r14
- add.l r14, r63, r15
- ld.l r15, 4, r14
- addi.l r15, 8, r15
- blink tr0, r63
-.LFE1:
-.Lfe1:
- .size __superh_trap_handler,.Lfe1-__superh_trap_handler
-
- .section .text..SHmedia32
-.Letext0:
-
- .section .debug_info
- .ualong 0xa7
- .uaword 0x2
- .ualong .Ldebug_abbrev0
- .byte 0x4
- .byte 0x1
- .ualong .Ldebug_line0
- .ualong .Letext0
- .ualong .Ltext0
- .string "trap_handler.c"
-
- .string "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
-
- .string "GNU C 2.97-sh5-010522"
-
- .byte 0x1
- .byte 0x2
- .ualong 0x9a
- .byte 0x1
- .string "_superh_trap_handler"
-
- .byte 0x1
- .byte 0x2
- .byte 0x1
- .ualong .LFB1
- .ualong .LFE1
- .byte 0x1
- .byte 0x5e
- .byte 0x3
- .string "trap_reason"
-
- .byte 0x1
- .byte 0x1
- .ualong 0x9a
- .byte 0x2
- .byte 0x91
- .byte 0x0
- .byte 0x0
- .byte 0x4
- .string "unsigned int"
-
- .byte 0x4
- .byte 0x7
- .byte 0x0
-
- .section .debug_abbrev
- .byte 0x1
- .byte 0x11
- .byte 0x1
- .byte 0x10
- .byte 0x6
- .byte 0x12
- .byte 0x1
- .byte 0x11
- .byte 0x1
- .byte 0x3
- .byte 0x8
- .byte 0x1b
- .byte 0x8
- .byte 0x25
- .byte 0x8
- .byte 0x13
- .byte 0xb
- .byte 0,0
- .byte 0x2
- .byte 0x2e
- .byte 0x1
- .byte 0x1
- .byte 0x13
- .byte 0x3f
- .byte 0xc
- .byte 0x3
- .byte 0x8
- .byte 0x3a
- .byte 0xb
- .byte 0x3b
- .byte 0xb
- .byte 0x27
- .byte 0xc
- .byte 0x11
- .byte 0x1
- .byte 0x12
- .byte 0x1
- .byte 0x40
- .byte 0xa
- .byte 0,0
- .byte 0x3
- .byte 0x5
- .byte 0x0
- .byte 0x3
- .byte 0x8
- .byte 0x3a
- .byte 0xb
- .byte 0x3b
- .byte 0xb
- .byte 0x49
- .byte 0x13
- .byte 0x2
- .byte 0xa
- .byte 0,0
- .byte 0x4
- .byte 0x24
- .byte 0x0
- .byte 0x3
- .byte 0x8
- .byte 0xb
- .byte 0xb
- .byte 0x3e
- .byte 0xb
- .byte 0,0
- .byte 0
-
- .section .debug_pubnames
- .ualong 0x27
- .uaword 0x2
- .ualong .Ldebug_info0
- .ualong 0xab
- .ualong 0x5b
- .string "_superh_trap_handler"
-
- .ualong 0x0
-
- .section .debug_aranges
- .ualong 0x1c
- .uaword 0x2
- .ualong .Ldebug_info0
- .byte 0x4
- .byte 0x0
- .uaword 0x0,0
- .ualong .Ltext0
- .ualong .Letext0-.Ltext0
- .ualong 0x0
- .ualong 0x0
- .ident "GCC: (GNU) 2.97-sh5-010522"
-#endif /* MMU_SUPPORT */
-#else /* ! __SH5__ */
-
- ! make a place to keep any previous value of the vbr register
- ! this will only have a value if it has been set by redboot (for example)
- .section .bss
-old_vbr:
- .long 0
-#ifdef PROFILE
-profiling_enabled:
- .long 0
-#endif
-
-
- .section .text
- .global start
- .import ___rtos_profiler_start_timer
- .weak ___rtos_profiler_start_timer
-start:
- mov.l stack_k,r15
-
-#if defined (__SH3__) || (defined (__SH_FPU_ANY__) && ! defined (__SH2A__)) || defined (__SH4_NOFPU__)
-#define VBR_SETUP
- ! before zeroing the bss ...
- ! if the vbr is already set to vbr_start then the program has been restarted
- ! (i.e. it is not the first time the program has been run since reset)
- ! reset the vbr to its old value before old_vbr (in bss) is wiped
- ! this ensures that the later code does not create a circular vbr chain
- stc vbr, r1
- mov.l vbr_start_k, r2
- cmp/eq r1, r2
- bf 0f
- ! reset the old vbr value
- mov.l old_vbr_k, r1
- mov.l @r1, r2
- ldc r2, vbr
-0:
-#endif /* VBR_SETUP */
-
- ! zero out bss
- mov.l edata_k,r0
- mov.l end_k,r1
- mov #0,r2
-start_l:
- mov.l r2,@r0
- add #4,r0
- cmp/ge r0,r1
- bt start_l
-
-#if defined (__SH_FPU_ANY__)
- mov.l set_fpscr_k, r1
- mov #4,r4
- jsr @r1
- shll16 r4 ! Set DN bit (flush denormal inputs to zero)
- lds r3,fpscr ! Switch to default precision
-#endif /* defined (__SH_FPU_ANY__) */
-
-#ifdef VBR_SETUP
- ! save the existing contents of the vbr
- ! there will only be a prior value when using something like redboot
- ! otherwise it will be zero
- stc vbr, r1
- mov.l old_vbr_k, r2
- mov.l r1, @r2
- ! setup vbr
- mov.l vbr_start_k, r1
- ldc r1,vbr
-#endif /* VBR_SETUP */
-
- ! if an rtos is exporting a timer start fn,
- ! then pick up an SR which does not enable ints
- ! (the rtos will take care of this)
- mov.l rtos_start_fn, r0
- mov.l sr_initial_bare, r1
- tst r0, r0
- bt set_sr
-
- mov.l sr_initial_rtos, r1
-
-set_sr:
- ! Set status register (sr)
- ldc r1, sr
-
- ! arrange for exit to call fini
- mov.l atexit_k,r0
- mov.l fini_k,r4
- jsr @r0
- nop
-
-#ifdef PROFILE
- ! arrange for exit to call _mcleanup (via stop_profiling)
- mova stop_profiling,r0
- mov.l atexit_k,r1
- jsr @r1
- mov r0, r4
-
- ! Call profiler startup code
- mov.l monstartup_k, r0
- mov.l start_k, r4
- mov.l etext_k, r5
- jsr @r0
- nop
-
- ! enable profiling trap
- ! until now any trap 33s will have been ignored
- ! This means that all library functions called before this point
- ! (directly or indirectly) may have the profiling trap at the start.
- ! Therefore, only mcount itself may not have the extra header.
- mov.l profiling_enabled_k2, r0
- mov #1, r1
- mov.l r1, @r0
-#endif /* PROFILE */
-
- ! call init
- mov.l init_k,r0
- jsr @r0
- nop
-
- ! call the mainline
- mov.l main_k,r0
- jsr @r0
- nop
-
- ! call exit
- mov r0,r4
- mov.l exit_k,r0
- jsr @r0
- nop
-
- .balign 4
-#ifdef PROFILE
-stop_profiling:
- # stop mcount counting
- mov.l profiling_enabled_k2, r0
- mov #0, r1
- mov.l r1, @r0
-
- # call mcleanup
- mov.l mcleanup_k, r0
- jmp @r0
- nop
-
- .balign 4
-mcleanup_k:
- .long __mcleanup
-monstartup_k:
- .long ___monstartup
-profiling_enabled_k2:
- .long profiling_enabled
-start_k:
- .long _start
-etext_k:
- .long __etext
-#endif /* PROFILE */
-
- .align 2
-#if defined (__SH_FPU_ANY__)
-set_fpscr_k:
- .long ___set_fpscr
-#endif /* defined (__SH_FPU_ANY__) */
-
-stack_k:
- .long _stack
-edata_k:
- .long _edata
-end_k:
- .long _end
-main_k:
- .long ___setup_argv_and_call_main
-exit_k:
- .long _exit
-atexit_k:
- .long _atexit
-init_k:
- .long _init
-fini_k:
- .long _fini
-#ifdef VBR_SETUP
-old_vbr_k:
- .long old_vbr
-vbr_start_k:
- .long vbr_start
-#endif /* VBR_SETUP */
-
-sr_initial_rtos:
- ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
- ! Whether profiling or not, keep interrupts masked,
- ! the RTOS will enable these if required.
- .long 0x600000f1
-
-rtos_start_fn:
- .long ___rtos_profiler_start_timer
-
-#ifdef PROFILE
-sr_initial_bare:
- ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
- ! For bare machine, we need to enable interrupts to get profiling working
- .long 0x60000001
-#else
-
-sr_initial_bare:
- ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
- ! Keep interrupts disabled - the application will enable as required.
- .long 0x600000f1
-#endif
-
- ! supplied for backward compatibility only, in case of linking
- ! code whose main() was compiled with an older version of GCC.
- .global ___main
-___main:
- rts
- nop
-#ifdef VBR_SETUP
-! Exception handlers
- .section .text.vbr, "ax"
-vbr_start:
-
- .org 0x100
-vbr_100:
-#ifdef PROFILE
- ! Note on register usage.
- ! we use r0..r3 as scratch in this code. If we are here due to a trapa for profiling
- ! then this is OK as we are just before executing any function code.
- ! The other r4..r7 we save explicityl on the stack
- ! Remaining registers are saved by normal ABI conventions and we assert we do not
- ! use floating point registers.
- mov.l expevt_k1, r1
- mov.l @r1, r1
- mov.l event_mask, r0
- and r0,r1
- mov.l trapcode_k, r2
- cmp/eq r1,r2
- bt 1f
- bra handler_100 ! if not a trapa, go to default handler
- nop
-1:
- mov.l trapa_k, r0
- mov.l @r0, r0
- shlr2 r0 ! trapa code is shifted by 2.
- cmp/eq #33, r0
- bt 2f
- bra handler_100
- nop
-2:
-
- ! If here then it looks like we have trap #33
- ! Now we need to call mcount with the following convention
- ! Save and restore r4..r7
- mov.l r4,@-r15
- mov.l r5,@-r15
- mov.l r6,@-r15
- mov.l r7,@-r15
- sts.l pr,@-r15
-
- ! r4 is frompc.
- ! r5 is selfpc
- ! r0 is the branch back address.
- ! The code sequence emitted by gcc for the profiling trap is
- ! .align 2
- ! trapa #33
- ! .align 2
- ! .long lab Where lab is planted by the compiler. This is the address
- ! of a datum that needs to be incremented.
- sts pr, r4 ! frompc
- stc spc, r5 ! selfpc
- mov #2, r2
- not r2, r2 ! pattern to align to 4
- and r2, r5 ! r5 now has aligned address
-! add #4, r5 ! r5 now has address of address
- mov r5, r2 ! Remember it.
-! mov.l @r5, r5 ! r5 has value of lable (lab in above example)
- add #8, r2
- ldc r2, spc ! our return address avoiding address word
-
- ! only call mcount if profiling is enabled
- mov.l profiling_enabled_k, r0
- mov.l @r0, r0
- cmp/eq #0, r0
- bt 3f
- ! call mcount
- mov.l mcount_k, r2
- jsr @r2
- nop
-3:
- lds.l @r15+,pr
- mov.l @r15+,r7
- mov.l @r15+,r6
- mov.l @r15+,r5
- mov.l @r15+,r4
- rte
- nop
- .balign 4
-event_mask:
- .long 0xfff
-trapcode_k:
- .long 0x160
-expevt_k1:
- .long 0xff000024 ! Address of expevt
-trapa_k:
- .long 0xff000020
-mcount_k:
- .long __call_mcount
-profiling_enabled_k:
- .long profiling_enabled
-#endif
- ! Non profiling case.
-handler_100:
- mov.l 2f, r0 ! load the old vbr setting (if any)
- mov.l @r0, r0
- cmp/eq #0, r0
- bf 1f
- ! no previous vbr - jump to own generic handler
- bra handler
- nop
-1: ! there was a previous handler - chain them
- add #0x7f, r0 ! 0x7f
- add #0x7f, r0 ! 0xfe
- add #0x2, r0 ! add 0x100 without corrupting another register
- jmp @r0
- nop
- .balign 4
-2:
- .long old_vbr
-
- .org 0x400
-vbr_400: ! Should be at vbr+0x400
- mov.l 2f, r0 ! load the old vbr setting (if any)
- mov.l @r0, r0
- cmp/eq #0, r0
- ! no previous vbr - jump to own generic handler
- bt handler
- ! there was a previous handler - chain them
- rotcr r0
- rotcr r0
- add #0x7f, r0 ! 0x1fc
- add #0x7f, r0 ! 0x3f8
- add #0x02, r0 ! 0x400
- rotcl r0
- rotcl r0 ! Add 0x400 without corrupting another register
- jmp @r0
- nop
- .balign 4
-2:
- .long old_vbr
-handler:
- /* If the trap handler is there call it */
- mov.l superh_trap_handler_k, r0
- cmp/eq #0, r0 ! True if zero.
- bf 3f
- bra chandler
- nop
-3:
- ! Here handler available, call it.
- /* Now call the trap handler with as much of the context unchanged as possible.
- Move trapping address into PR to make it look like the trap point */
- stc spc, r1
- lds r1, pr
- mov.l expevt_k, r4
- mov.l @r4, r4 ! r4 is value of expevt, first parameter.
- mov r1, r5 ! Remember trapping pc.
- mov r1, r6 ! Remember trapping pc.
- mov.l chandler_k, r1
- mov.l superh_trap_handler_k, r2
- ! jmp to trap handler to avoid disturbing pr.
- jmp @r2
- nop
-
- .org 0x600
-vbr_600:
-#ifdef PROFILE
- ! Should be at vbr+0x600
- ! Now we are in the land of interrupts so need to save more state.
- ! Save register state
- mov.l interrupt_stack_k, r15 ! r15 has been saved to sgr.
- mov.l r0,@-r15
- mov.l r1,@-r15
- mov.l r2,@-r15
- mov.l r3,@-r15
- mov.l r4,@-r15
- mov.l r5,@-r15
- mov.l r6,@-r15
- mov.l r7,@-r15
- sts.l pr,@-r15
- sts.l mach,@-r15
- sts.l macl,@-r15
-#if defined(__SH_FPU_ANY__)
- ! Save fpul and fpscr, save fr0-fr7 in 64 bit mode
- ! and set the pervading precision for the timer_handler
- mov #0,r0
- sts.l fpul,@-r15
- sts.l fpscr,@-r15
- lds r0,fpscr ! Clear fpscr
- fmov fr0,@-r15
- fmov fr1,@-r15
- fmov fr2,@-r15
- fmov fr3,@-r15
- mov.l pervading_precision_k,r0
- fmov fr4,@-r15
- fmov fr5,@-r15
- mov.l @r0,r0
- fmov fr6,@-r15
- fmov fr7,@-r15
- lds r0,fpscr
-#endif /* __SH_FPU_ANY__ */
- ! Pass interrupted pc to timer_handler as first parameter (r4).
- stc spc, r4
- mov.l timer_handler_k, r0
- jsr @r0
- nop
-#if defined(__SH_FPU_ANY__)
- mov #0,r0
- lds r0,fpscr ! Clear the fpscr
- fmov @r15+,fr7
- fmov @r15+,fr6
- fmov @r15+,fr5
- fmov @r15+,fr4
- fmov @r15+,fr3
- fmov @r15+,fr2
- fmov @r15+,fr1
- fmov @r15+,fr0
- lds.l @r15+,fpscr
- lds.l @r15+,fpul
-#endif /* __SH_FPU_ANY__ */
- lds.l @r15+,macl
- lds.l @r15+,mach
- lds.l @r15+,pr
- mov.l @r15+,r7
- mov.l @r15+,r6
- mov.l @r15+,r5
- mov.l @r15+,r4
- mov.l @r15+,r3
- mov.l @r15+,r2
- mov.l @r15+,r1
- mov.l @r15+,r0
- stc sgr, r15 ! Restore r15, destroyed by this sequence.
- rte
- nop
-#if defined(__SH_FPU_ANY__)
- .balign 4
-pervading_precision_k:
-#define CONCAT1(A,B) A##B
-#define CONCAT(A,B) CONCAT1(A,B)
- .long CONCAT(__USER_LABEL_PREFIX__,__fpscr_values)+4
-#endif
-#else
- mov.l 2f, r0 ! Load the old vbr setting (if any).
- mov.l @r0, r0
- cmp/eq #0, r0
- ! no previous vbr - jump to own handler
- bt chandler
- ! there was a previous handler - chain them
- rotcr r0
- rotcr r0
- add #0x7f, r0 ! 0x1fc
- add #0x7f, r0 ! 0x3f8
- add #0x7f, r0 ! 0x5f4
- add #0x03, r0 ! 0x600
- rotcl r0
- rotcl r0 ! Add 0x600 without corrupting another register
- jmp @r0
- nop
- .balign 4
-2:
- .long old_vbr
-#endif /* PROFILE code */
-chandler:
- mov.l expevt_k, r4
- mov.l @r4, r4 ! r4 is value of expevt hence making this the return code
- mov.l handler_exit_k,r0
- jsr @r0
- nop
- ! We should never return from _exit but in case we do we would enter the
- ! the following tight loop
-limbo:
- bra limbo
- nop
- .balign 4
-#ifdef PROFILE
-interrupt_stack_k:
- .long __timer_stack ! The high end of the stack
-timer_handler_k:
- .long __profil_counter
-#endif
-expevt_k:
- .long 0xff000024 ! Address of expevt
-chandler_k:
- .long chandler
-superh_trap_handler_k:
- .long __superh_trap_handler
-handler_exit_k:
- .long _exit
- .align 2
-! Simulated compile of trap handler.
- .section .debug_abbrev,"",@progbits
-.Ldebug_abbrev0:
- .section .debug_info,"",@progbits
-.Ldebug_info0:
- .section .debug_line,"",@progbits
-.Ldebug_line0:
- .text
-.Ltext0:
- .align 5
- .type __superh_trap_handler,@function
-__superh_trap_handler:
-.LFB1:
- mov.l r14,@-r15
-.LCFI0:
- add #-4,r15
-.LCFI1:
- mov r15,r14
-.LCFI2:
- mov.l r4,@r14
- lds r1, pr
- add #4,r14
- mov r14,r15
- mov.l @r15+,r14
- rts
- nop
-.LFE1:
-.Lfe1:
- .size __superh_trap_handler,.Lfe1-__superh_trap_handler
- .section .debug_frame,"",@progbits
-.Lframe0:
- .ualong .LECIE0-.LSCIE0
-.LSCIE0:
- .ualong 0xffffffff
- .byte 0x1
- .string ""
- .uleb128 0x1
- .sleb128 -4
- .byte 0x11
- .byte 0xc
- .uleb128 0xf
- .uleb128 0x0
- .align 2
-.LECIE0:
-.LSFDE0:
- .ualong .LEFDE0-.LASFDE0
-.LASFDE0:
- .ualong .Lframe0
- .ualong .LFB1
- .ualong .LFE1-.LFB1
- .byte 0x4
- .ualong .LCFI0-.LFB1
- .byte 0xe
- .uleb128 0x4
- .byte 0x4
- .ualong .LCFI1-.LCFI0
- .byte 0xe
- .uleb128 0x8
- .byte 0x8e
- .uleb128 0x1
- .byte 0x4
- .ualong .LCFI2-.LCFI1
- .byte 0xd
- .uleb128 0xe
- .align 2
-.LEFDE0:
- .text
-.Letext0:
- .section .debug_info
- .ualong 0xb3
- .uaword 0x2
- .ualong .Ldebug_abbrev0
- .byte 0x4
- .uleb128 0x1
- .ualong .Ldebug_line0
- .ualong .Letext0
- .ualong .Ltext0
- .string "trap_handler.c"
- .string "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
- .string "GNU C 3.2 20020529 (experimental)"
- .byte 0x1
- .uleb128 0x2
- .ualong 0xa6
- .byte 0x1
- .string "_superh_trap_handler"
- .byte 0x1
- .byte 0x2
- .byte 0x1
- .ualong .LFB1
- .ualong .LFE1
- .byte 0x1
- .byte 0x5e
- .uleb128 0x3
- .string "trap_reason"
- .byte 0x1
- .byte 0x1
- .ualong 0xa6
- .byte 0x2
- .byte 0x91
- .sleb128 0
- .byte 0x0
- .uleb128 0x4
- .string "unsigned int"
- .byte 0x4
- .byte 0x7
- .byte 0x0
- .section .debug_abbrev
- .uleb128 0x1
- .uleb128 0x11
- .byte 0x1
- .uleb128 0x10
- .uleb128 0x6
- .uleb128 0x12
- .uleb128 0x1
- .uleb128 0x11
- .uleb128 0x1
- .uleb128 0x3
- .uleb128 0x8
- .uleb128 0x1b
- .uleb128 0x8
- .uleb128 0x25
- .uleb128 0x8
- .uleb128 0x13
- .uleb128 0xb
- .byte 0x0
- .byte 0x0
- .uleb128 0x2
- .uleb128 0x2e
- .byte 0x1
- .uleb128 0x1
- .uleb128 0x13
- .uleb128 0x3f
- .uleb128 0xc
- .uleb128 0x3
- .uleb128 0x8
- .uleb128 0x3a
- .uleb128 0xb
- .uleb128 0x3b
- .uleb128 0xb
- .uleb128 0x27
- .uleb128 0xc
- .uleb128 0x11
- .uleb128 0x1
- .uleb128 0x12
- .uleb128 0x1
- .uleb128 0x40
- .uleb128 0xa
- .byte 0x0
- .byte 0x0
- .uleb128 0x3
- .uleb128 0x5
- .byte 0x0
- .uleb128 0x3
- .uleb128 0x8
- .uleb128 0x3a
- .uleb128 0xb
- .uleb128 0x3b
- .uleb128 0xb
- .uleb128 0x49
- .uleb128 0x13
- .uleb128 0x2
- .uleb128 0xa
- .byte 0x0
- .byte 0x0
- .uleb128 0x4
- .uleb128 0x24
- .byte 0x0
- .uleb128 0x3
- .uleb128 0x8
- .uleb128 0xb
- .uleb128 0xb
- .uleb128 0x3e
- .uleb128 0xb
- .byte 0x0
- .byte 0x0
- .byte 0x0
- .section .debug_pubnames,"",@progbits
- .ualong 0x27
- .uaword 0x2
- .ualong .Ldebug_info0
- .ualong 0xb7
- .ualong 0x67
- .string "_superh_trap_handler"
- .ualong 0x0
- .section .debug_aranges,"",@progbits
- .ualong 0x1c
- .uaword 0x2
- .ualong .Ldebug_info0
- .byte 0x4
- .byte 0x0
- .uaword 0x0
- .uaword 0x0
- .ualong .Ltext0
- .ualong .Letext0-.Ltext0
- .ualong 0x0
- .ualong 0x0
-#endif /* VBR_SETUP */
-#endif /* ! __SH5__ */
diff --git a/gcc/config/sh/crti.asm b/gcc/config/sh/crti.asm
deleted file mode 100644
index ef5cd719d82..00000000000
--- a/gcc/config/sh/crti.asm
+++ /dev/null
@@ -1,125 +0,0 @@
-/* Copyright (C) 2000, 2001, 2009 Free Software Foundation, Inc.
- This file was adapted from glibc sources.
-
-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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-
-/* The code in sections .init and .fini is supposed to be a single
- regular function. The function in .init is called directly from
- start in crt1.asm. The function in .fini is atexit()ed in crt1.asm
- too.
-
- crti.asm contributes the prologue of a function to these sections,
- and crtn.asm comes up the epilogue. STARTFILE_SPEC should list
- crti.o before any other object files that might add code to .init
- or .fini sections, and ENDFILE_SPEC should list crtn.o after any
- such object files. */
-
- .section .init
-/* The alignment below can't be smaller, otherwise the mova below
- breaks. Yes, we might align just the label, but then we'd be
- exchanging an alignment here for one there, since the code fragment
- below ensures 4-byte alignment on __ELF__. */
-#ifdef __ELF__
- .p2align 2
-#else
- .p2align 1
-#endif
- .global _init
-_init:
-#if __SHMEDIA__
- addi r15, -16, r15
- st.q r15, 8, r14
- st.q r15, 0, r18
- add r15, r63, r14
-#elif __SH5__ && ! __SHMEDIA__
- mov r15,r0
- add #-8,r15
- mov.l r14,@-r0
- sts.l pr,@-r0
- mov r15,r14
- nop
-#else
-#ifdef __ELF__
- mov.l r12,@-r15
- mova 0f,r0
- mov.l 0f,r12
-#endif
- mov.l r14,@-r15
-#ifdef __ELF__
- add r0,r12
-#endif
- sts.l pr,@-r15
-#ifdef __ELF__
- bra 1f
-#endif
- mov r15,r14
-#ifdef __ELF__
-0: .long _GLOBAL_OFFSET_TABLE_
-1:
-#endif
-#endif /* __SHMEDIA__ */
-
- .section .fini
-/* The alignment below can't be smaller, otherwise the mova below
- breaks. Yes, we might align just the label, but then we'd be
- exchanging an alignment here for one there, since the code fragment
- below ensures 4-byte alignment on __ELF__. */
-#ifdef __ELF__
- .p2align 2
-#else
- .p2align 1
-#endif
- .global _fini
-_fini:
-#if __SHMEDIA__
- addi r15, -16, r15
- st.q r15, 8, r14
- st.q r15, 0, r18
- add r15, r63, r14
-#elif __SH5__ && ! __SHMEDIA__
- mov r15,r0
- add #-8,r15
- mov.l r14,@-r0
- sts.l pr,@-r0
- mov r15,r14
- nop
-#else
-#ifdef __ELF__
- mov.l r12,@-r15
- mova 0f,r0
- mov.l 0f,r12
-#endif
- mov.l r14,@-r15
-#ifdef __ELF__
- add r0,r12
-#endif
- sts.l pr,@-r15
-#ifdef __ELF__
- bra 1f
-#endif
- mov r15,r14
-#ifdef __ELF__
-0: .long _GLOBAL_OFFSET_TABLE_
-1:
-#endif
-#endif /* __SHMEDIA__ */
diff --git a/gcc/config/sh/crtn.asm b/gcc/config/sh/crtn.asm
deleted file mode 100644
index 670d90f7b6a..00000000000
--- a/gcc/config/sh/crtn.asm
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Copyright (C) 2000, 2001, 2009 Free Software Foundation, Inc.
- This file was adapted from glibc sources.
-
-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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* See an explanation about .init and .fini in crti.asm. */
-
- .section .init
-#if __SHMEDIA__
- add r14, r63, r15
- ld.q r15, 0, r18
- ptabs r18, tr0
- ld.q r15, 8, r14
- addi r15, 16, r15
- blink tr0, r63
-#elif __SH5__ && ! __SHMEDIA__
- mov r14,r15
- lds.l @r14+,pr
- mov.l @r14,r14
- rts
- add #8,r15
-#else
- mov r14,r15
- lds.l @r15+,pr
- mov.l @r15+,r14
- rts
-#ifdef __ELF__
- mov.l @r15+,r12
-#else
- nop
-#endif
-#endif /* __SHMEDIA__ */
-
- .section .fini
-#if __SHMEDIA__
- add r14, r63, r15
- ld.q r15, 0, r18
- ptabs r18, tr0
- ld.q r15, 8, r14
- addi r15, 16, r15
- blink tr0, r63
-#elif __SH5__ && ! __SHMEDIA__
- mov r14,r15
- lds.l @r14+,pr
- mov.l @r14,r14
- rts
- add #8,r15
-#else
- mov r14,r15
- lds.l @r15+,pr
- mov.l @r15+,r14
- rts
-#ifdef __ELF__
- mov.l @r15+,r12
-#else
- nop
-#endif
-#endif /* __SHMEDIA__ */
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index c0bfdd3af49..03c3c48c0e4 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -242,7 +242,7 @@ static void sh_file_start (void);
static int flow_dependent_p (rtx, rtx);
static void flow_dependent_p_1 (rtx, const_rtx, void *);
static int shiftcosts (rtx);
-static int and_xor_ior_costs (rtx, int code);
+static int and_xor_ior_costs (rtx, int);
static int addsubcosts (rtx);
static int multcosts (rtx);
static bool unspec_caller_rtx_p (rtx);
@@ -2995,6 +2995,20 @@ sh_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
*total = 8;
return true;
+ case EQ:
+ /* An and with a constant compared against zero is
+ most likely going to be a TST #imm, R0 instruction.
+ Notice that this does not catch the zero_extract variants from
+ the md file. */
+ if (GET_CODE (XEXP (x, 0)) == AND
+ && CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 0)
+ {
+ *total = 1;
+ return true;
+ }
+ else
+ return false;
+
case CONST:
case LABEL_REF:
case SYMBOL_REF:
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index ef42a1bfc9d..cc26e05a764 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -1195,6 +1195,9 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
#define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \
&& ((HOST_WIDE_INT)(VALUE)) <= 255)
+#define ZERO_EXTRACT_ANDMASK(EXTRACT_SZ_RTX, EXTRACT_POS_RTX)\
+ (((1 << INTVAL (EXTRACT_SZ_RTX)) - 1) << INTVAL (EXTRACT_POS_RTX))
+
#if 0
#define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \
((((REGCLASS_HAS_FP_REG (CLASS) \
@@ -1980,7 +1983,7 @@ struct sh_args {
that the native compiler puts too large (> 32) immediate shift counts
into a register and shifts by the register, letting the SH decide what
to do instead of doing that itself. */
-/* ??? The library routines in lib1funcs.asm truncate the shift count.
+/* ??? The library routines in lib1funcs.S truncate the shift count.
However, the SH3 has hardware shifts that do not truncate exactly as gcc
expects - the sign bit is significant - so it appears that we need to
leave this zero for correct SH3 code. */
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 63cb9393653..ce660185dd3 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -585,15 +585,164 @@
;; SImode signed integer comparisons
;; -------------------------------------------------------------------------
-(define_insn ""
+;; Various patterns to generate the TST #imm, R0 instruction.
+;; Although this adds some pressure on the R0 register, it can potentially
+;; result in faster code, even if the operand has to be moved to R0 first.
+;; This is because on SH4 TST #imm, R0 and MOV Rm, Rn are both MT group
+;; instructions and thus will be executed in parallel. On SH4A TST #imm, R0
+;; is an EX group instruction but still can be executed in parallel with the
+;; MT group MOV Rm, Rn instruction.
+
+;; Usual TST #imm, R0 patterns for SI, HI and QI
+;; This is usually used for bit patterns other than contiguous bits
+;; and single bits.
+
+(define_insn "tstsi_t"
[(set (reg:SI T_REG)
- (eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
+ (eq:SI (and:SI (match_operand:SI 0 "logical_operand" "%z,r")
(match_operand:SI 1 "logical_operand" "K08,r"))
(const_int 0)))]
"TARGET_SH1"
"tst %1,%0"
[(set_attr "type" "mt_group")])
+(define_insn "tsthi_t"
+ [(set (reg:SI T_REG)
+ (eq:SI (subreg:SI (and:HI (match_operand:HI 0 "logical_operand" "%z")
+ (match_operand 1 "const_int_operand")) 0)
+ (const_int 0)))]
+ "TARGET_SH1
+ && CONST_OK_FOR_K08 (INTVAL (operands[1]))"
+ "tst %1,%0"
+ [(set_attr "type" "mt_group")])
+
+(define_insn "tstqi_t"
+ [(set (reg:SI T_REG)
+ (eq:SI (subreg:SI (and:QI (match_operand:QI 0 "logical_operand" "%z")
+ (match_operand 1 "const_int_operand")) 0)
+ (const_int 0)))]
+ "TARGET_SH1
+ && (CONST_OK_FOR_K08 (INTVAL (operands[1]))
+ || CONST_OK_FOR_I08 (INTVAL (operands[1])))"
+{
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 255);
+ return "tst %1,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; Test low QI subreg against zero.
+;; This avoids unecessary zero extension before the test.
+
+(define_insn "tstqi_t_zero"
+ [(set (reg:SI T_REG)
+ (eq:SI (match_operand:QI 0 "logical_operand" "z") (const_int 0)))]
+ "TARGET_SH1"
+ "tst #255,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract LSB, negate and store in T bit.
+
+(define_insn "tstsi_t_and_not"
+ [(set (reg:SI T_REG)
+ (and:SI (not:SI (match_operand:SI 0 "logical_operand" "z"))
+ (const_int 1)))]
+ "TARGET_SH1"
+ "tst #1,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract contiguous bits and compare them against zero.
+
+(define_insn "tstsi_t_zero_extract_eq"
+ [(set (reg:SI T_REG)
+ (eq:SI (zero_extract:SI (match_operand 0 "logical_operand" "z")
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand"))
+ (const_int 0)))]
+ "TARGET_SH1
+ && CONST_OK_FOR_K08 (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]))"
+{
+ operands[1] = GEN_INT (ZERO_EXTRACT_ANDMASK (operands[1], operands[2]));
+ return "tst %1,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; This split is required when testing bits in a QI subreg.
+
+(define_split
+ [(set (reg:SI T_REG)
+ (eq:SI (if_then_else:SI (zero_extract:SI
+ (match_operand 0 "logical_operand" "")
+ (match_operand 1 "const_int_operand")
+ (match_operand 2 "const_int_operand"))
+ (match_operand 3 "const_int_operand")
+ (const_int 0))
+ (const_int 0)))]
+ "TARGET_SH1
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
+ [(set (reg:SI T_REG) (eq:SI (and:SI (match_dup 0) (match_dup 3))
+ (const_int 0)))]
+ "
+{
+ if (GET_MODE (operands[0]) == QImode)
+ operands[0] = simplify_gen_subreg (SImode, operands[0], QImode, 0);
+}")
+
+;; Extract single bit, negate and store it in the T bit.
+;; Not used for SH4A.
+
+(define_insn "tstsi_t_zero_extract_xor"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand"))
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == INTVAL (operands[3])
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]))"
+ "tst %3,%0"
+ [(set_attr "type" "mt_group")])
+
+;; Extract single bit, negate and store it in the T bit.
+;; Used for SH4A little endian.
+
+(define_insn "tstsi_t_zero_extract_subreg_xor_little"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI
+ (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand")) 0)
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1 && TARGET_LITTLE_ENDIAN
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
+ == (INTVAL (operands[3]) & 255)
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
+{
+ operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
+ return "tst %3,%0";
+}
+ [(set_attr "type" "mt_group")])
+
+;; Extract single bit, negate and store it in the T bit.
+;; Used for SH4A big endian.
+
+(define_insn "tstsi_t_zero_extract_subreg_xor_big"
+ [(set (reg:SI T_REG)
+ (zero_extract:SI
+ (subreg:QI (xor:SI (match_operand:SI 0 "logical_operand" "z")
+ (match_operand:SI 3 "const_int_operand")) 3)
+ (match_operand:SI 1 "const_int_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN
+ && ZERO_EXTRACT_ANDMASK (operands[1], operands[2])
+ == (INTVAL (operands[3]) & 255)
+ && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)"
+{
+ operands[3] = GEN_INT (INTVAL (operands[3]) & 255);
+ return "tst %3,%0";
+}
+ [(set_attr "type" "mt_group")])
+
;; ??? Perhaps should only accept reg/constant if the register is reg 0.
;; That would still allow reload to create cmpi instructions, but would
;; perhaps allow forcing the constant into a register when that is better.
@@ -1157,7 +1306,7 @@
&& (arith_reg_operand (operands[1], SImode)
|| (immediate_operand (operands[1], SImode)
&& satisfies_constraint_I08 (operands[1])))"
- "bt 0f\;mov %1,%0\\n0:"
+ "bt 0f\;mov %1,%0\\n0:"
[(set_attr "type" "mt_group,arith") ;; poor approximation
(set_attr "length" "4")])
@@ -1170,7 +1319,7 @@
&& (arith_reg_operand (operands[1], SImode)
|| (immediate_operand (operands[1], SImode)
&& satisfies_constraint_I08 (operands[1])))"
- "bf 0f\;mov %1,%0\\n0:"
+ "bf 0f\;mov %1,%0\\n0:"
[(set_attr "type" "mt_group,arith") ;; poor approximation
(set_attr "length" "4")])
@@ -3015,9 +3164,9 @@ label:
;; -------------------------------------------------------------------------
(define_insn "*andsi3_compact"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r,z")
+ [(set (match_operand:SI 0 "arith_reg_dest" "=z,r")
(and:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
- (match_operand:SI 2 "logical_operand" "r,K08")))]
+ (match_operand:SI 2 "logical_operand" "K08,r")))]
"TARGET_SH1"
"and %2,%0"
[(set_attr "type" "arith")])
diff --git a/gcc/config/sh/t-elf b/gcc/config/sh/t-elf
deleted file mode 100644
index 333efb54e09..00000000000
--- a/gcc/config/sh/t-elf
+++ /dev/null
@@ -1,10 +0,0 @@
-EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o \
- crtbegin.o crtend.o crtbeginS.o crtendS.o $(IC_EXTRA_PARTS) $(OPT_EXTRA_PARTS)
-
-# Compile crtbeginS.o and crtendS.o with pic.
-CRTSTUFF_T_CFLAGS_S = -fPIC
-
-# Don't compile libgcc with -fpic for now. It's unlikely that we'll
-# build shared libraries for embedded SH.
-# Linux / Netbsd will already have set TARGET_LIBGCC2_CFLAGS.
-# TARGET_LIBGCC2_CFLAGS = -fpic
diff --git a/gcc/config/sh/t-linux b/gcc/config/sh/t-linux
index 13ff848dd7c..d33c6383915 100644
--- a/gcc/config/sh/t-linux
+++ b/gcc/config/sh/t-linux
@@ -1,8 +1,2 @@
-LIB1ASMFUNCS_CACHE = _ic_invalidate _ic_invalidate_array
-
-LIB2FUNCS_EXTRA= $(srcdir)/config/sh/linux-atomic.asm
-
MULTILIB_DIRNAMES=
MULTILIB_MATCHES =
-
-EXTRA_MULTILIB_PARTS= crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
diff --git a/gcc/config/sh/t-linux64 b/gcc/config/sh/t-linux64
deleted file mode 100644
index 126b0163754..00000000000
--- a/gcc/config/sh/t-linux64
+++ /dev/null
@@ -1 +0,0 @@
-EXTRA_MULTILIB_PARTS= crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
diff --git a/gcc/config/sh/t-netbsd b/gcc/config/sh/t-netbsd
deleted file mode 100644
index 11bfe31458e..00000000000
--- a/gcc/config/sh/t-netbsd
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright (C) 2002, 2004, 2009, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-TARGET_LIBGCC2_CFLAGS = -fpic -mieee
-LIB1ASMFUNCS_CACHE = _ic_invalidate
-
-LIB2FUNCS_EXTRA=
-
-EXTRA_MULTILIB_PARTS=
diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh
index e63131a5348..1d305ee5193 100644
--- a/gcc/config/sh/t-sh
+++ b/gcc/config/sh/t-sh
@@ -22,15 +22,6 @@ sh-c.o: $(srcdir)/config/sh/sh-c.c \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/sh/sh-c.c
-LIB1ASMSRC = sh/lib1funcs.asm
-LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movmem \
- _movmem_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
- _div_table _udiv_qrnnd_16 \
- $(LIB1ASMFUNCS_CACHE)
-LIB1ASMFUNCS_CACHE = _ic_invalidate _ic_invalidate_array
-
-TARGET_LIBGCC2_CFLAGS = -mieee
-
DEFAULT_ENDIAN = $(word 1,$(TM_ENDIAN_CONFIG))
OTHER_ENDIAN = $(word 2,$(TM_ENDIAN_CONFIG))
@@ -91,58 +82,9 @@ MULTILIB_OSDIRNAMES = \
m5-64media=!m5-64media $(OTHER_ENDIAN)/m5-64media=!$(OTHER_ENDIAN)/m5-64media \
m5-64media-nofpu=!m5-64media-nofpu $(OTHER_ENDIAN)/m5-64media-nofpu=!$(OTHER_ENDIAN)/m5-64media-nofpu
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-$(T)crt1.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
-$(T)crti.o: $(srcdir)/config/sh/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/sh/crti.asm
-$(T)crtn.o: $(srcdir)/config/sh/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/sh/crtn.asm
-
$(out_object_file): gt-sh.h
gt-sh.h : s-gtype ; @true
-# These are not suitable for COFF.
-# EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o crtbegin.o crtend.o
-
-IC_EXTRA_PARTS= libic_invalidate_array_4-100.a libic_invalidate_array_4-200.a \
-libic_invalidate_array_4a.a
-OPT_EXTRA_PARTS= libgcc-Os-4-200.a libgcc-4-300.a
-EXTRA_MULTILIB_PARTS= $(IC_EXTRA_PARTS) $(OPT_EXTRA_PARTS)
-
-$(T)ic_invalidate_array_4-100.o: $(srcdir)/config/sh/lib1funcs.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)ic_invalidate_array_4-100.o -DL_ic_invalidate_array -DWAYS=1 -DWAY_SIZE=0x2000 -x assembler-with-cpp $(srcdir)/config/sh/lib1funcs.asm
-$(T)libic_invalidate_array_4-100.a: $(T)ic_invalidate_array_4-100.o $(GCC_PASSES)
- $(AR_CREATE_FOR_TARGET) $(T)libic_invalidate_array_4-100.a $(T)ic_invalidate_array_4-100.o
-
-$(T)ic_invalidate_array_4-200.o: $(srcdir)/config/sh/lib1funcs.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)ic_invalidate_array_4-200.o -DL_ic_invalidate_array -DWAYS=2 -DWAY_SIZE=0x2000 -x assembler-with-cpp $(srcdir)/config/sh/lib1funcs.asm
-$(T)libic_invalidate_array_4-200.a: $(T)ic_invalidate_array_4-200.o $(GCC_PASSES)
- $(AR_CREATE_FOR_TARGET) $(T)libic_invalidate_array_4-200.a $(T)ic_invalidate_array_4-200.o
-
-$(T)ic_invalidate_array_4a.o: $(srcdir)/config/sh/lib1funcs.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)ic_invalidate_array_4a.o -DL_ic_invalidate_array -D__FORCE_SH4A__ -x assembler-with-cpp $(srcdir)/config/sh/lib1funcs.asm
-$(T)libic_invalidate_array_4a.a: $(T)ic_invalidate_array_4a.o $(GCC_PASSES)
- $(AR_CREATE_FOR_TARGET) $(T)libic_invalidate_array_4a.a $(T)ic_invalidate_array_4a.o
-
-$(T)sdivsi3_i4i-Os-4-200.o: $(srcdir)/config/sh/lib1funcs-Os-4-200.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $@ -DL_sdivsi3_i4i -x assembler-with-cpp $<
-$(T)udivsi3_i4i-Os-4-200.o: $(srcdir)/config/sh/lib1funcs-Os-4-200.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $@ -DL_udivsi3_i4i -x assembler-with-cpp $<
-$(T)unwind-dw2-Os-4-200.o: $(srcdir)/../libgcc/unwind-dw2.c $(srcdir)/../libgcc/unwind-generic.h $(srcdir)/../libgcc/unwind-pe.h $(srcdir)/../libgcc/unwind.inc $(srcdir)/../libgcc/unwind-dw2-fde.h $(srcdir)/../libgcc/unwind-dw2.h $(CONFIG_H) coretypes.h $(TM_H) $(MACHMODE_H) longlong.h config.status stmp-int-hdrs tsystem.h $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) $(LIBGCC2_CFLAGS) $(INCLUDES) $(vis_hide) -fexceptions -Os -c -o $@ $<
-OBJS_Os_4_200=$(T)sdivsi3_i4i-Os-4-200.o $(T)udivsi3_i4i-Os-4-200.o $(T)unwind-dw2-Os-4-200.o
-$(T)libgcc-Os-4-200.a: $(OBJS_Os_4_200) $(GCC_PASSES)
- $(AR_CREATE_FOR_TARGET) $@ $(OBJS_Os_4_200)
-
-$(T)div_table-4-300.o: $(srcdir)/config/sh/lib1funcs-4-300.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $@ -DL_div_table -x assembler-with-cpp $<
-
-$(T)libgcc-4-300.a: $(T)div_table-4-300.o $(GCC_PASSES)
- $(AR_CREATE_FOR_TARGET) $@ $(T)div_table-4-300.o
-
# Local Variables:
# mode: Makefile
# End:
diff --git a/gcc/config/sh/t-sh64 b/gcc/config/sh/t-sh64
index d88f929fd7a..3bd9205079b 100644
--- a/gcc/config/sh/t-sh64
+++ b/gcc/config/sh/t-sh64
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2004, 2005, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,13 +16,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMFUNCS = \
- _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
- _shcompact_call_trampoline _shcompact_return_trampoline \
- _shcompact_incoming_args _ic_invalidate _nested_trampoline \
- _push_pop_shmedia_regs \
- _udivdi3 _divdi3 _umoddi3 _moddi3 _div_table
-
MULTILIB_CPU_DIRS= $(ML_sh1) $(ML_sh2e) $(ML_sh2) $(ML_sh3e) $(ML_sh3) $(ML_sh4_nofpu) $(ML_sh4_single_only) $(ML_sh4_single) $(ML_sh4) $(ML_sh5_32media:m5-32media/=media32) $(ML_sh5_32media_nofpu:m5-32media-nofpu/=nofpu/media32) $(ML_sh5_compact:m5-compact/=compact) $(ML_sh5_compact_nofpu:m5-compact-nofpu/=nofpu/compact) $(ML_sh5_64media:m5-64media/=media64) $(ML_sh5_64media_nofpu:m5-64media-nofpu/=nofpu/media64)
MULTILIB_RAW_DIRNAMES= $(MULTILIB_ENDIAN:/mb= mb) $(MULTILIB_CPU_DIRS:/=)
diff --git a/gcc/config/sh/t-superh b/gcc/config/sh/t-superh
deleted file mode 100644
index 4e2d83dcba0..00000000000
--- a/gcc/config/sh/t-superh
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2005, 2006 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-EXTRA_MULTILIB_PARTS= crt1.o crti.o crtn.o \
- crtbegin.o crtend.o crtbeginS.o crtendS.o \
- crt1-mmu.o gcrt1-mmu.o gcrt1.o $(IC_EXTRA_PARTS) $(OPT_EXTRA_PARTS)
-
-# Compile crt1-mmu.o as crt1.o with -DMMU_SUPPORT
-$(T)crt1-mmu.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1-mmu.o -DMMU_SUPPORT -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
-
-# Compile gcrt1-mmu.o as crt1-mmu.o with -DPROFILE
-$(T)gcrt1-mmu.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)gcrt1-mmu.o -DPROFILE -DMMU_SUPPORT -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
-
-# For sh4-400: Compile gcrt1.o as crt1.o with -DPROFILE
-$(T)gcrt1.o: $(srcdir)/config/sh/crt1.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)gcrt1.o -DPROFILE -x assembler-with-cpp $(srcdir)/config/sh/crt1.asm
diff --git a/gcc/config/sh/t-vxworks b/gcc/config/sh/t-vxworks
index 66aa7091ab1..d7ccc9b7f59 100644
--- a/gcc/config/sh/t-vxworks
+++ b/gcc/config/sh/t-vxworks
@@ -4,6 +4,3 @@ MULTILIB_OPTIONS = mrtp fPIC m2/m3/m4/m4a ml
# Don't build -fPIC without -mrtp, or -ml without -m3/-m4.
MULTILIB_EXCEPTIONS = fPIC* ml* mrtp/ml* mrtp/fPIC/ml* *m2/ml*
MULTILIB_MATCHES = m2=m4-nofpu fPIC=fpic
-
-# Restore a variable from t-vxworks clobbered by t-elf.
-EXTRA_MULTILIB_PARTS =
diff --git a/gcc/config/sparc/lb1spl.asm b/gcc/config/sparc/lb1spl.asm
deleted file mode 100644
index 973401f8018..00000000000
--- a/gcc/config/sparc/lb1spl.asm
+++ /dev/null
@@ -1,246 +0,0 @@
-/* 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
- to match the desired calling convention, and also to optimize them. */
-
-#ifdef L_udivsi3
-.text
- .align 4
- .global .udiv
- .proc 04
-.udiv:
- wr %g0,%g0,%y ! Not a delayed write for sparclite
- tst %g0
- divscc %o0,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- retl
- divscc %g1,%o1,%o0
-#endif
-
-#ifdef L_umodsi3
-.text
- .align 4
- .global .urem
- .proc 04
-.urem:
- wr %g0,%g0,%y ! Not a delayed write for sparclite
- tst %g0
- divscc %o0,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- divscc %g1,%o1,%g1
- bl 1f
- rd %y,%o0
- retl
- nop
-1: retl
- add %o0,%o1,%o0
-#endif
-
-#ifdef L_divsi3
-.text
- .align 4
- .global .div
- .proc 04
-! ??? This routine could be made faster if was optimized, and if it was
-! rewritten to only calculate the quotient.
-.div:
- wr %g0,%g0,%y ! Not a delayed write for sparclite
- mov %o1,%o4
- tst %o1
- bl,a 1f
- sub %g0,%o4,%o4
-1: tst %o0
- bl,a 2f
- mov -1,%y
-2: divscc %o0,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- be 6f
- mov %y,%o3
- bg 4f
- addcc %o3,%o4,%g0
- be,a 6f
- mov %g0,%o3
- tst %o0
- bl 5f
- tst %g1
- ba 5f
- add %o3,%o4,%o3
-4: subcc %o3,%o4,%g0
- be,a 6f
- mov %g0,%o3
- tst %o0
- bge 5f
- tst %g1
- sub %o3,%o4,%o3
-5: bl,a 6f
- add %g1,1,%g1
-6: tst %o1
- bl,a 7f
- sub %g0,%g1,%g1
-7: retl
- mov %g1,%o0 ! Quotient is in %g1.
-#endif
-
-#ifdef L_modsi3
-.text
- .align 4
- .global .rem
- .proc 04
-! ??? This routine could be made faster if was optimized, and if it was
-! rewritten to only calculate the remainder.
-.rem:
- wr %g0,%g0,%y ! Not a delayed write for sparclite
- mov %o1,%o4
- tst %o1
- bl,a 1f
- sub %g0,%o4,%o4
-1: tst %o0
- bl,a 2f
- mov -1,%y
-2: divscc %o0,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- divscc %g1,%o4,%g1
- be 6f
- mov %y,%o3
- bg 4f
- addcc %o3,%o4,%g0
- be,a 6f
- mov %g0,%o3
- tst %o0
- bl 5f
- tst %g1
- ba 5f
- add %o3,%o4,%o3
-4: subcc %o3,%o4,%g0
- be,a 6f
- mov %g0,%o3
- tst %o0
- bge 5f
- tst %g1
- sub %o3,%o4,%o3
-5: bl,a 6f
- add %g1,1,%g1
-6: tst %o1
- bl,a 7f
- sub %g0,%g1,%g1
-7: retl
- mov %o3,%o0 ! Remainder is in %o3.
-#endif
diff --git a/gcc/config/sparc/linux.h b/gcc/config/sparc/linux.h
index 0ad4b3482f1..443c7966405 100644
--- a/gcc/config/sparc/linux.h
+++ b/gcc/config/sparc/linux.h
@@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see
/* -mcpu=native handling only makes sense with compiler running on
a SPARC chip. */
-#if defined(__sparc__)
+#if defined(__sparc__) && defined(__linux__)
extern const char *host_detect_local_cpu (int argc, const char **argv);
# define EXTRA_SPEC_FUNCTIONS \
{ "local_cpu_detect", host_detect_local_cpu },
diff --git a/gcc/config/sparc/linux64.h b/gcc/config/sparc/linux64.h
index 3c83d2d0a6e..bec279de8c9 100644
--- a/gcc/config/sparc/linux64.h
+++ b/gcc/config/sparc/linux64.h
@@ -31,7 +31,9 @@ along with GCC; see the file COPYING3. If not see
} \
while (0)
-#ifdef TARGET_64BIT_DEFAULT
+/* On Linux, the combination sparc64-* --with-cpu=v8 is supported and
+ selects a 32-bit compiler. */
+#if defined(TARGET_64BIT_DEFAULT) && TARGET_CPU_DEFAULT >= TARGET_CPU_v9
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_STACK_BIAS + \
@@ -131,13 +133,12 @@ along with GCC; see the file COPYING3. If not see
#undef LINK_SPEC
#define LINK_SPEC "\
%(link_arch) \
-%{mlittle-endian:-EL} \
%{!mno-relax:%{!r:-relax}} \
"
/* -mcpu=native handling only makes sense with compiler running on
a SPARC chip. */
-#if defined(__sparc__)
+#if defined(__sparc__) && defined(__linux__)
extern const char *host_detect_local_cpu (int argc, const char **argv);
# define EXTRA_SPEC_FUNCTIONS \
{ "local_cpu_detect", host_detect_local_cpu },
@@ -164,6 +165,8 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
%{m32:%{m64:%emay not use both -m32 and -m64}} \
%{m32:-mptr32 -mno-stack-bias %{!mlong-double-128:-mlong-double-64} \
%{!mcpu*:-mcpu=cypress}} \
+%{mv8plus:-mptr32 -mno-stack-bias %{!mlong-double-128:-mlong-double-64} \
+ %{!mcpu*:-mcpu=v9}} \
%{!m32:%{!mcpu*:-mcpu=ultrasparc}} \
%{!mno-vis:%{!m32:%{!mcpu=v9:-mvis}}} \
"
@@ -205,7 +208,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
%{rdynamic:-export-dynamic} \
-dynamic-linker " GNU_USER_DYNAMIC_LINKER64 "} \
%{static:-static}} \
-%{mlittle-endian:-EL} \
%{!mno-relax:%{!r:-relax}} \
"
@@ -217,7 +219,6 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
-s \
%{fpic|fPIC|fpie|fPIE:-K PIC} \
%{!.c:%{findirect-dispatch:-K PIC}} \
-%{mlittle-endian:-EL} \
%(asm_cpu) %(asm_arch) %(asm_relax)"
#undef ASM_OUTPUT_ALIGNED_LOCAL
diff --git a/gcc/config/sparc/little-endian.opt b/gcc/config/sparc/little-endian.opt
deleted file mode 100644
index 52db029c06b..00000000000
--- a/gcc/config/sparc/little-endian.opt
+++ /dev/null
@@ -1,27 +0,0 @@
-; Options for the SPARC port of the compiler
-;
-; Copyright (C) 2005, 2007 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 3, 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 COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-mlittle-endian
-Target Report RejectNegative Mask(LITTLE_ENDIAN) MaskExists
-Generate code for little-endian
-
-mbig-endian
-Target Report RejectNegative InverseMask(LITTLE_ENDIAN)
-Generate code for big-endian
diff --git a/gcc/config/sparc/netbsd-elf.h b/gcc/config/sparc/netbsd-elf.h
index d19615bc4f1..505a29e1420 100644
--- a/gcc/config/sparc/netbsd-elf.h
+++ b/gcc/config/sparc/netbsd-elf.h
@@ -69,7 +69,6 @@ along with GCC; see the file COPYING3. If not see
#undef ASM_SPEC
#define ASM_SPEC "%{fpic|fPIC|fpie|fPIE:-K PIC} \
-%{mlittle-endian:-EL} \
%(asm_cpu) %(asm_arch) %(asm_relax)"
#undef STDC_0_IN_SYSTEM_HEADERS
diff --git a/gcc/config/sparc/openbsd64.h b/gcc/config/sparc/openbsd64.h
index da479db144a..a38b68e8932 100644
--- a/gcc/config/sparc/openbsd64.h
+++ b/gcc/config/sparc/openbsd64.h
@@ -50,7 +50,6 @@ along with GCC; see the file COPYING3. If not see
#undef ASM_SPEC
#define ASM_SPEC "\
-s %{fpic|fPIC|fpie|fPIE:-K PIC} \
-%{mlittle-endian:-EL} \
%(asm_cpu) %(asm_arch) \
"
diff --git a/gcc/config/sparc/predicates.md b/gcc/config/sparc/predicates.md
index f0be14997af..4dd734f047e 100644
--- a/gcc/config/sparc/predicates.md
+++ b/gcc/config/sparc/predicates.md
@@ -427,8 +427,12 @@
&& (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
return true;
- if ((mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE)
- || (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR))
+ if (mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE)
+ return true;
+
+ if (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR
+ && (const_zero_operand (op, mode)
+ || const_all_ones_operand (op, mode)))
return true;
if (register_operand (op, mode))
diff --git a/gcc/config/sparc/sol2.h b/gcc/config/sparc/sol2.h
index fea60d0543b..ba2ec35e20a 100644
--- a/gcc/config/sparc/sol2.h
+++ b/gcc/config/sparc/sol2.h
@@ -181,7 +181,7 @@ along with GCC; see the file COPYING3. If not see
/* -mcpu=native handling only makes sense with compiler running on
a SPARC chip. */
-#if defined(__sparc__)
+#if defined(__sparc__) && defined(__SVR4)
extern const char *host_detect_local_cpu (int argc, const char **argv);
# define EXTRA_SPEC_FUNCTIONS \
{ "local_cpu_detect", host_detect_local_cpu },
diff --git a/gcc/config/sparc/sp64-elf.h b/gcc/config/sparc/sp64-elf.h
index 492f90fd490..17463b4c68d 100644
--- a/gcc/config/sparc/sp64-elf.h
+++ b/gcc/config/sparc/sp64-elf.h
@@ -39,7 +39,6 @@ along with GCC; see the file COPYING3. If not see
#undef ASM_SPEC
#define ASM_SPEC "\
-s %{fpic|fPIC|fpie|fPIE:-K PIC} \
-%{mlittle-endian:-EL} \
%(asm_cpu) %(asm_arch) \
"
@@ -47,7 +46,6 @@ along with GCC; see the file COPYING3. If not see
#undef LINK_SPEC
#define LINK_SPEC "\
%{v:-V} \
-%{mlittle-endian:-EL} \
"
#undef STARTFILE_SPEC
@@ -60,12 +58,6 @@ along with GCC; see the file COPYING3. If not see
/* Use the default (for now). */
#undef LIB_SPEC
-
-#undef BYTES_BIG_ENDIAN
-#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
-
-#undef WORDS_BIG_ENDIAN
-#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
diff --git a/gcc/config/sparc/sparc-modes.def b/gcc/config/sparc/sparc-modes.def
index ed135ccc1b7..a5849c984b1 100644
--- a/gcc/config/sparc/sparc-modes.def
+++ b/gcc/config/sparc/sparc-modes.def
@@ -45,4 +45,6 @@ CC_MODE (CCFPE);
/* Vector modes. */
VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
-VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODE (INT, DI, 1); /* V1DI */
+VECTOR_MODE (INT, SI, 1); /* V1SI */
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index f7b563eda9d..b9a094e160a 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -43,7 +43,6 @@ extern void sparc_expand_epilogue (bool);
extern void sparc_flat_expand_epilogue (bool);
extern bool sparc_can_use_return_insn_p (void);
extern int check_pic (int);
-extern int short_branch (int, int);
extern void sparc_profile_hook (int);
extern void sparc_override_options (void);
extern void sparc_output_scratch_registers (FILE *);
@@ -69,6 +68,7 @@ extern void sparc_defer_case_vector (rtx, rtx, int);
extern bool sparc_expand_move (enum machine_mode, rtx *);
extern void sparc_emit_set_symbolic_const64 (rtx, rtx, rtx);
extern int sparc_splitdi_legitimate (rtx, rtx);
+extern int sparc_split_regreg_legitimate (rtx, rtx);
extern int sparc_absnegfloat_split_legitimate (rtx, rtx);
extern const char *output_ubranch (rtx, int, rtx);
extern const char *output_cbranch (rtx, rtx, int, int, int, rtx);
@@ -95,7 +95,6 @@ extern int fp_mov_p (rtx);
extern int fp_high_losum_p (rtx);
extern int mem_min_alignment (rtx, int);
extern int pic_address_needs_scratch (rtx);
-extern int reg_unused_after (rtx, rtx);
extern int register_ok_for_ldd (rtx);
extern int memory_ok_for_ldd (rtx);
extern int registers_ok_for_ldd_peep (rtx, rtx);
@@ -106,6 +105,10 @@ extern int sparc_check_64 (rtx, rtx);
extern rtx gen_df_reg (rtx, int);
extern void sparc_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
extern const char *output_v8plus_mult (rtx, rtx *, const char *);
+extern void sparc_expand_vector_init (rtx, rtx);
+extern void sparc_expand_vec_perm_bmask(enum machine_mode, rtx);
+extern bool sparc_expand_conditional_move (enum machine_mode, rtx *);
+extern void sparc_expand_vcond (enum machine_mode, rtx *, int, int);
#endif /* RTX_CODE */
#endif /* __SPARC_PROTOS_H__ */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 9c7cc56b43e..649612e92ef 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -59,6 +59,81 @@ along with GCC; see the file COPYING3. If not see
#include "opts.h"
/* Processor costs */
+
+struct processor_costs {
+ /* Integer load */
+ const int int_load;
+
+ /* Integer signed load */
+ const int int_sload;
+
+ /* Integer zeroed load */
+ const int int_zload;
+
+ /* Float load */
+ const int float_load;
+
+ /* fmov, fneg, fabs */
+ const int float_move;
+
+ /* fadd, fsub */
+ const int float_plusminus;
+
+ /* fcmp */
+ const int float_cmp;
+
+ /* fmov, fmovr */
+ const int float_cmove;
+
+ /* fmul */
+ const int float_mul;
+
+ /* fdivs */
+ const int float_div_sf;
+
+ /* fdivd */
+ const int float_div_df;
+
+ /* fsqrts */
+ const int float_sqrt_sf;
+
+ /* fsqrtd */
+ const int float_sqrt_df;
+
+ /* umul/smul */
+ const int int_mul;
+
+ /* mulX */
+ const int int_mulX;
+
+ /* integer multiply cost for each bit set past the most
+ significant 3, so the formula for multiply cost becomes:
+
+ if (rs1 < 0)
+ highest_bit = highest_clear_bit(rs1);
+ else
+ highest_bit = highest_set_bit(rs1);
+ if (highest_bit < 3)
+ highest_bit = 3;
+ cost = int_mul{,X} + ((highest_bit - 3) / int_mul_bit_factor);
+
+ A value of zero indicates that the multiply costs is fixed,
+ and not variable. */
+ const int int_mul_bit_factor;
+
+ /* udiv/sdiv */
+ const int int_div;
+
+ /* divX */
+ const int int_divX;
+
+ /* movcc, movr */
+ const int int_cmove;
+
+ /* penalty for shifts, due to scheduling rules etc. */
+ const int shift_penalty;
+};
+
static const
struct processor_costs cypress_costs = {
COSTS_N_INSNS (2), /* int load */
@@ -299,7 +374,7 @@ struct processor_costs niagara3_costs = {
0, /* shift penalty */
};
-const struct processor_costs *sparc_costs = &cypress_costs;
+static const struct processor_costs *sparc_costs = &cypress_costs;
#ifdef HAVE_AS_RELAX_OPTION
/* If 'as' and 'ld' are relaxing tail call insns into branch always, use
@@ -444,6 +519,7 @@ static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
HOST_WIDE_INT, const_tree);
+static void sparc_reorg (void);
static struct machine_function * sparc_init_machine_status (void);
static bool sparc_cannot_force_const_mem (enum machine_mode, rtx);
static rtx sparc_tls_get_addr (void);
@@ -499,6 +575,8 @@ static reg_class_t sparc_preferred_reload_class (rtx x, reg_class_t rclass);
static bool sparc_print_operand_punct_valid_p (unsigned char);
static void sparc_print_operand (FILE *, rtx, int);
static void sparc_print_operand_address (FILE *, rtx);
+static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
+ enum machine_mode, secondary_reload_info *);
#ifdef SUBTARGET_ATTRIBUTE_TABLE
/* Table of valid machine attributes. */
@@ -582,6 +660,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG sparc_reorg
+
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs
#undef TARGET_ADDRESS_COST
@@ -670,6 +751,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_PREFERRED_RELOAD_CLASS
#define TARGET_PREFERRED_RELOAD_CLASS sparc_preferred_reload_class
+#undef TARGET_SECONDARY_RELOAD
+#define TARGET_SECONDARY_RELOAD sparc_secondary_reload
+
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE sparc_conditional_register_usage
@@ -696,6 +780,59 @@ char sparc_hard_reg_printed[8];
struct gcc_target targetm = TARGET_INITIALIZER;
+static void
+dump_target_flag_bits (const int flags)
+{
+ if (flags & MASK_64BIT)
+ fprintf (stderr, "64BIT ");
+ if (flags & MASK_APP_REGS)
+ fprintf (stderr, "APP_REGS ");
+ if (flags & MASK_FASTER_STRUCTS)
+ fprintf (stderr, "FASTER_STRUCTS ");
+ if (flags & MASK_FLAT)
+ fprintf (stderr, "FLAT ");
+ if (flags & MASK_FMAF)
+ fprintf (stderr, "FMAF ");
+ if (flags & MASK_FPU)
+ fprintf (stderr, "FPU ");
+ if (flags & MASK_HARD_QUAD)
+ fprintf (stderr, "HARD_QUAD ");
+ if (flags & MASK_POPC)
+ fprintf (stderr, "POPC ");
+ if (flags & MASK_PTR64)
+ fprintf (stderr, "PTR64 ");
+ if (flags & MASK_STACK_BIAS)
+ fprintf (stderr, "STACK_BIAS ");
+ if (flags & MASK_UNALIGNED_DOUBLES)
+ fprintf (stderr, "UNALIGNED_DOUBLES ");
+ if (flags & MASK_V8PLUS)
+ fprintf (stderr, "V8PLUS ");
+ if (flags & MASK_VIS)
+ fprintf (stderr, "VIS ");
+ if (flags & MASK_VIS2)
+ fprintf (stderr, "VIS2 ");
+ if (flags & MASK_VIS3)
+ fprintf (stderr, "VIS3 ");
+ if (flags & MASK_DEPRECATED_V8_INSNS)
+ fprintf (stderr, "DEPRECATED_V8_INSNS ");
+ if (flags & MASK_SPARCLET)
+ fprintf (stderr, "SPARCLET ");
+ if (flags & MASK_SPARCLITE)
+ fprintf (stderr, "SPARCLITE ");
+ if (flags & MASK_V8)
+ fprintf (stderr, "V8 ");
+ if (flags & MASK_V9)
+ fprintf (stderr, "V9 ");
+}
+
+static void
+dump_target_flags (const char *prefix, const int flags)
+{
+ fprintf (stderr, "%s: (%08x) [ ", prefix, flags);
+ dump_target_flag_bits (flags);
+ fprintf(stderr, "]\n");
+}
+
/* Validate and override various options, and do some machine dependent
initialization. */
@@ -741,49 +878,93 @@ sparc_option_override (void)
/* Table of values for -m{cpu,tune}=. This must match the order of
the PROCESSOR_* enumeration. */
static struct cpu_table {
+ const char *const name;
const int disable;
const int enable;
} const cpu_table[] = {
- { MASK_ISA, 0 },
- { MASK_ISA, 0 },
- { MASK_ISA, MASK_V8 },
+ { "v7", MASK_ISA, 0 },
+ { "cypress", MASK_ISA, 0 },
+ { "v8", MASK_ISA, MASK_V8 },
/* TI TMS390Z55 supersparc */
- { MASK_ISA, MASK_V8 },
- { MASK_ISA, MASK_V8|MASK_FPU },
+ { "supersparc", MASK_ISA, MASK_V8 },
+ { "hypersparc", MASK_ISA, MASK_V8|MASK_FPU },
/* LEON */
- { MASK_ISA, MASK_V8|MASK_FPU },
- { MASK_ISA, MASK_SPARCLITE },
+ { "leon", MASK_ISA, MASK_V8|MASK_FPU },
+ { "sparclite", MASK_ISA, MASK_SPARCLITE },
/* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */
- { MASK_ISA|MASK_FPU, MASK_SPARCLITE },
+ { "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
/* The Fujitsu MB86934 is the recent sparclite chip, with an FPU. */
- { MASK_ISA, MASK_SPARCLITE|MASK_FPU },
- { MASK_ISA|MASK_FPU, MASK_SPARCLITE },
- { MASK_ISA, MASK_SPARCLET },
+ { "f934", MASK_ISA, MASK_SPARCLITE|MASK_FPU },
+ { "sparclite86x", MASK_ISA|MASK_FPU, MASK_SPARCLITE },
+ { "sparclet", MASK_ISA, MASK_SPARCLET },
/* TEMIC sparclet */
- { MASK_ISA, MASK_SPARCLET },
- { MASK_ISA, MASK_V9 },
+ { "tsc701", MASK_ISA, MASK_SPARCLET },
+ { "v9", MASK_ISA, MASK_V9 },
/* UltraSPARC I, II, IIi */
- { MASK_ISA,
+ { "ultrasparc", MASK_ISA,
/* Although insns using %y are deprecated, it is a clear win. */
- MASK_V9|MASK_DEPRECATED_V8_INSNS},
+ MASK_V9|MASK_DEPRECATED_V8_INSNS },
/* UltraSPARC III */
/* ??? Check if %y issue still holds true. */
- { MASK_ISA,
- MASK_V9|MASK_DEPRECATED_V8_INSNS|MASK_VIS2},
+ { "ultrasparc3", MASK_ISA,
+ MASK_V9|MASK_DEPRECATED_V8_INSNS|MASK_VIS2 },
/* UltraSPARC T1 */
- { MASK_ISA,
- MASK_V9|MASK_DEPRECATED_V8_INSNS},
+ { "niagara", MASK_ISA,
+ MASK_V9|MASK_DEPRECATED_V8_INSNS },
/* UltraSPARC T2 */
- { MASK_ISA, MASK_V9|MASK_POPC|MASK_VIS2},
+ { "niagara2", MASK_ISA,
+ MASK_V9|MASK_POPC|MASK_VIS2 },
/* UltraSPARC T3 */
- { MASK_ISA, MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF},
+ { "niagara3", MASK_ISA,
+ MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF },
/* UltraSPARC T4 */
- { MASK_ISA, MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF},
+ { "niagara4", MASK_ISA,
+ MASK_V9|MASK_POPC|MASK_VIS2|MASK_VIS3|MASK_FMAF },
};
const struct cpu_table *cpu;
unsigned int i;
int fpu;
+ if (sparc_debug_string != NULL)
+ {
+ const char *q;
+ char *p;
+
+ p = ASTRDUP (sparc_debug_string);
+ while ((q = strtok (p, ",")) != NULL)
+ {
+ bool invert;
+ int mask;
+
+ p = NULL;
+ if (*q == '!')
+ {
+ invert = true;
+ q++;
+ }
+ else
+ invert = false;
+
+ if (! strcmp (q, "all"))
+ mask = MASK_DEBUG_ALL;
+ else if (! strcmp (q, "options"))
+ mask = MASK_DEBUG_OPTIONS;
+ else
+ error ("unknown -mdebug-%s switch", q);
+
+ if (invert)
+ sparc_debug &= ~mask;
+ else
+ sparc_debug |= mask;
+ }
+ }
+
+ if (TARGET_DEBUG_OPTIONS)
+ {
+ dump_target_flags("Initial target_flags", target_flags);
+ dump_target_flags("target_flags_explicit", target_flags_explicit);
+ }
+
#ifdef SUBTARGET_OVERRIDE_OPTIONS
SUBTARGET_OVERRIDE_OPTIONS;
#endif
@@ -845,12 +1026,27 @@ sparc_option_override (void)
gcc_assert (def->cpu != -1);
sparc_cpu_and_features = def->processor;
}
+
if (!global_options_set.x_sparc_cpu)
sparc_cpu = sparc_cpu_and_features;
cpu = &cpu_table[(int) sparc_cpu_and_features];
+
+ if (TARGET_DEBUG_OPTIONS)
+ {
+ fprintf (stderr, "sparc_cpu_and_features: %s\n", cpu->name);
+ fprintf (stderr, "sparc_cpu: %s\n",
+ cpu_table[(int) sparc_cpu].name);
+ dump_target_flags ("cpu->disable", cpu->disable);
+ dump_target_flags ("cpu->enable", cpu->enable);
+ }
+
target_flags &= ~cpu->disable;
- target_flags |= cpu->enable;
+ target_flags |= (cpu->enable
+#ifndef HAVE_AS_FMAF_HPC_VIS3
+ & ~(MASK_FMAF | MASK_VIS3)
+#endif
+ );
/* If -mfpu or -mno-fpu was explicitly used, don't override with
the processor default. */
@@ -968,6 +1164,9 @@ sparc_option_override (void)
target_flags |= MASK_LONG_DOUBLE_128;
#endif
+ if (TARGET_DEBUG_OPTIONS)
+ dump_target_flags ("Final target_flags", target_flags);
+
maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES,
((sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_NIAGARA
@@ -1191,7 +1390,7 @@ sparc_expand_move (enum machine_mode mode, rtx *operands)
&& (mode == SFmode
/* And any DF constant in integer registers. */
|| (mode == DFmode
- && (reload_completed || reload_in_progress))))
+ && ! can_create_pseudo_p ())))
return false;
operands[1] = force_const_mem (mode, operands[1]);
@@ -1237,11 +1436,9 @@ static void
sparc_emit_set_const32 (rtx op0, rtx op1)
{
enum machine_mode mode = GET_MODE (op0);
- rtx temp;
+ rtx temp = op0;
- if (reload_in_progress || reload_completed)
- temp = op0;
- else
+ if (can_create_pseudo_p ())
temp = gen_reg_rtx (mode);
if (GET_CODE (op1) == CONST_INT)
@@ -1614,11 +1811,9 @@ sparc_emit_set_const64_longway (rtx op0, rtx temp,
unsigned HOST_WIDE_INT high_bits,
unsigned HOST_WIDE_INT low_bits)
{
- rtx sub_temp;
+ rtx sub_temp = op0;
- if (reload_in_progress || reload_completed)
- sub_temp = op0;
- else
+ if (can_create_pseudo_p ())
sub_temp = gen_reg_rtx (DImode);
if ((high_bits & 0xfffffc00) != 0)
@@ -1637,7 +1832,7 @@ sparc_emit_set_const64_longway (rtx op0, rtx temp,
sub_temp = temp;
}
- if (!reload_in_progress && !reload_completed)
+ if (can_create_pseudo_p ())
{
rtx temp2 = gen_reg_rtx (DImode);
rtx temp3 = gen_reg_rtx (DImode);
@@ -1845,7 +2040,7 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
&& (GET_CODE (op0) == SUBREG
|| (REG_P (op0) && ! SPARC_FP_REG_P (REGNO (op0)))));
- if (reload_in_progress || reload_completed)
+ if (! can_create_pseudo_p ())
temp = op0;
if (GET_CODE (op1) != CONST_INT)
@@ -2324,7 +2519,7 @@ emit_scc_insn (rtx operands[])
}
else if (GET_MODE (x) == DImode)
{
- rtx pat = gen_seqdi_special (operands[0], x, y);
+ rtx pat = gen_seqdi_special (operands[0], x, y);
emit_insn (pat);
return true;
}
@@ -2340,19 +2535,23 @@ emit_scc_insn (rtx operands[])
}
else if (GET_MODE (x) == DImode)
{
- rtx pat = gen_snedi_special (operands[0], x, y);
+ rtx pat;
+ if (TARGET_VIS3)
+ pat = gen_snedi_special_vis3 (operands[0], x, y);
+ else
+ pat = gen_snedi_special (operands[0], x, y);
emit_insn (pat);
return true;
}
}
- /* For the rest, on v9 we can use conditional moves. */
-
- if (TARGET_V9)
- {
- if (gen_v9_scc (operands[0], code, x, y))
- return true;
- }
+ if (TARGET_V9
+ && TARGET_ARCH64
+ && GET_MODE (x) == DImode
+ && !(TARGET_VIS3
+ && (code == GTU || code == LTU))
+ && gen_v9_scc (operands[0], code, x, y))
+ return true;
/* We can do LTU and GEU using the addx/subx instructions too. And
for GTU/LEU, if both operands are registers swap them and fall
@@ -2369,7 +2568,8 @@ emit_scc_insn (rtx operands[])
}
}
- if (code == LTU || code == GEU)
+ if (code == LTU
+ || (!TARGET_VIS3 && code == GEU))
{
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_fmt_ee (code, SImode,
@@ -2378,6 +2578,12 @@ emit_scc_insn (rtx operands[])
return true;
}
+ /* All the posibilities to use addx/subx based sequences has been
+ exhausted, try for a 3 instruction sequence using v9 conditional
+ moves. */
+ if (TARGET_V9 && gen_v9_scc (operands[0], code, x, y))
+ return true;
+
/* Nope, do branches. */
return false;
}
@@ -2439,7 +2645,7 @@ gen_df_reg (rtx reg, int low)
int regno = REGNO (reg);
if ((WORDS_BIG_ENDIAN == 0) ^ (low != 0))
- regno += (TARGET_ARCH64 && regno < 32) ? 1 : 2;
+ regno += (TARGET_ARCH64 && SPARC_INT_REG_P (regno)) ? 1 : 2;
return gen_rtx_REG (DFmode, regno);
}
@@ -2795,10 +3001,23 @@ eligible_for_restore_insn (rtx trial, bool return_p)
{
rtx pat = PATTERN (trial);
rtx src = SET_SRC (pat);
+ bool src_is_freg = false;
+ rtx src_reg;
+
+ /* Since we now can do moves between float and integer registers when
+ VIS3 is enabled, we have to catch this case. We can allow such
+ moves when doing a 'return' however. */
+ src_reg = src;
+ if (GET_CODE (src_reg) == SUBREG)
+ src_reg = SUBREG_REG (src_reg);
+ if (GET_CODE (src_reg) == REG
+ && SPARC_FP_REG_P (REGNO (src_reg)))
+ src_is_freg = true;
/* The 'restore src,%g0,dest' pattern for word mode and below. */
if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
- && arith_operand (src, GET_MODE (src)))
+ && arith_operand (src, GET_MODE (src))
+ && ! src_is_freg)
{
if (TARGET_ARCH64)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
@@ -2808,7 +3027,8 @@ eligible_for_restore_insn (rtx trial, bool return_p)
/* The 'restore src,%g0,dest' pattern for double-word mode. */
else if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
- && arith_double_operand (src, GET_MODE (src)))
+ && arith_double_operand (src, GET_MODE (src))
+ && ! src_is_freg)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
/* The 'restore src,%g0,dest' pattern for float if no FPU. */
@@ -2923,7 +3143,7 @@ eligible_for_return_delay (rtx trial)
/* If this instruction sets up floating point register and we have a return
instruction, it can probably go in. But restore will not work
with FP_REGS. */
- if (regno >= 32)
+ if (! SPARC_INT_REG_P (regno))
return (TARGET_V9
&& !epilogue_renumber (&pat, 1)
&& get_attr_in_uncond_branch_delay (trial)
@@ -2965,7 +3185,7 @@ eligible_for_sibcall_delay (rtx trial)
a `restore' insn can go into the delay slot. */
if (GET_CODE (SET_DEST (pat)) != REG
|| (REGNO (SET_DEST (pat)) >= 8 && REGNO (SET_DEST (pat)) < 24)
- || REGNO (SET_DEST (pat)) >= 32)
+ || ! SPARC_INT_REG_P (REGNO (SET_DEST (pat))))
return 0;
/* If it mentions %o7, it can't go in, because sibcall will clobber it
@@ -2975,51 +3195,6 @@ eligible_for_sibcall_delay (rtx trial)
return eligible_for_restore_insn (trial, false);
}
-
-int
-short_branch (int uid1, int uid2)
-{
- int delta = INSN_ADDRESSES (uid1) - INSN_ADDRESSES (uid2);
-
- /* Leave a few words of "slop". */
- if (delta >= -1023 && delta <= 1022)
- return 1;
-
- return 0;
-}
-
-/* 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
-reg_unused_after (rtx reg, rtx insn)
-{
- enum rtx_code code, prev_code = UNKNOWN;
-
- while ((insn = NEXT_INSN (insn)))
- {
- if (prev_code == CALL_INSN && call_used_regs[REGNO (reg)])
- return 1;
-
- code = GET_CODE (insn);
- if (GET_CODE (insn) == CODE_LABEL)
- return 1;
-
- if (INSN_P (insn))
- {
- rtx set = single_set (insn);
- int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
- if (set && in_src)
- return 0;
- if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
- return 1;
- if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
- return 0;
- }
- prev_code = code;
- }
- return 1;
-}
/* 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
@@ -3330,11 +3505,11 @@ sparc_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
}
else
{
- if ((REGNO (rs1) >= 32
+ if ((! SPARC_INT_REG_P (REGNO (rs1))
&& REGNO (rs1) != FRAME_POINTER_REGNUM
&& REGNO (rs1) < FIRST_PSEUDO_REGISTER)
|| (rs2
- && (REGNO (rs2) >= 32
+ && (! SPARC_INT_REG_P (REGNO (rs2))
&& REGNO (rs2) != FRAME_POINTER_REGNUM
&& REGNO (rs2) < FIRST_PSEUDO_REGISTER)))
return 0;
@@ -3560,7 +3735,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
if (reg == 0)
{
- gcc_assert (! reload_in_progress && ! reload_completed);
+ gcc_assert (can_create_pseudo_p ());
reg = gen_reg_rtx (Pmode);
}
@@ -3569,7 +3744,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
/* If not during reload, allocate another temp reg here for loading
in the address, so that these instructions can be optimized
properly. */
- rtx temp_reg = ((reload_in_progress || reload_completed)
+ rtx temp_reg = (! can_create_pseudo_p ()
? reg : gen_reg_rtx (Pmode));
/* Must put the SYMBOL_REF inside an UNSPEC here so that cse
@@ -3628,7 +3803,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
if (reg == 0)
{
- gcc_assert (! reload_in_progress && ! reload_completed);
+ gcc_assert (can_create_pseudo_p ());
reg = gen_reg_rtx (Pmode);
}
@@ -3641,7 +3816,7 @@ sparc_legitimize_pic_address (rtx orig, rtx reg)
{
if (SMALL_INT (offset))
return plus_constant (base, INTVAL (offset));
- else if (! reload_in_progress && ! reload_completed)
+ else if (can_create_pseudo_p ())
offset = force_reg (Pmode, offset);
else
/* If we reach here, then something is seriously wrong. */
@@ -4573,17 +4748,17 @@ emit_save_or_restore_regs (unsigned int low, unsigned int high, rtx base,
if (reg0 && reg1)
{
- mode = i < 32 ? DImode : DFmode;
+ mode = SPARC_INT_REG_P (i) ? DImode : DFmode;
regno = i;
}
else if (reg0)
{
- mode = i < 32 ? SImode : SFmode;
+ mode = SPARC_INT_REG_P (i) ? SImode : SFmode;
regno = i;
}
else if (reg1)
{
- mode = i < 32 ? SImode : SFmode;
+ mode = SPARC_INT_REG_P (i) ? SImode : SFmode;
regno = i + 1;
offset += 4;
}
@@ -7606,6 +7781,38 @@ sparc_splitdi_legitimate (rtx reg, rtx mem)
return 1;
}
+/* Like sparc_splitdi_legitimate but for REG <--> REG moves. */
+
+int
+sparc_split_regreg_legitimate (rtx reg1, rtx reg2)
+{
+ int regno1, regno2;
+
+ if (GET_CODE (reg1) == SUBREG)
+ reg1 = SUBREG_REG (reg1);
+ if (GET_CODE (reg1) != REG)
+ return 0;
+ regno1 = REGNO (reg1);
+
+ if (GET_CODE (reg2) == SUBREG)
+ reg2 = SUBREG_REG (reg2);
+ if (GET_CODE (reg2) != REG)
+ return 0;
+ regno2 = REGNO (reg2);
+
+ if (SPARC_INT_REG_P (regno1) && SPARC_INT_REG_P (regno2))
+ return 1;
+
+ if (TARGET_VIS3)
+ {
+ if ((SPARC_INT_REG_P (regno1) && SPARC_FP_REG_P (regno2))
+ || (SPARC_FP_REG_P (regno1) && SPARC_INT_REG_P (regno2)))
+ return 1;
+ }
+
+ return 0;
+}
+
/* Return 1 if x and y are some kind of REG and they refer to
different hard registers. This test is guaranteed to be
run after reload. */
@@ -7638,7 +7845,7 @@ registers_ok_for_ldd_peep (rtx reg1, rtx reg2)
return 0;
/* Integer ldd is deprecated in SPARC V9 */
- if (TARGET_V9 && REGNO (reg1) < 32)
+ if (TARGET_V9 && SPARC_INT_REG_P (REGNO (reg1)))
return 0;
return (REGNO (reg1) == REGNO (reg2) - 1);
@@ -7775,7 +7982,7 @@ memory_ok_for_ldd (rtx op)
if (TARGET_ARCH32 && !mem_min_alignment (op, 8))
return 0;
- if ((reload_in_progress || reload_completed)
+ if (! can_create_pseudo_p ()
&& !strict_memory_address_p (Pmode, XEXP (op, 0)))
return 0;
}
@@ -7966,20 +8173,11 @@ sparc_print_operand (FILE *file, rtx x, int code)
}
return;
- /* These are used by the conditional move instructions. */
- case 'c' :
+ /* This is used by the conditional move instructions. */
case 'C':
{
enum rtx_code rc = GET_CODE (x);
- if (code == 'c')
- {
- enum machine_mode mode = GET_MODE (XEXP (x, 0));
- if (mode == CCFPmode || mode == CCFPEmode)
- rc = reverse_condition_maybe_unordered (GET_CODE (x));
- else
- rc = reverse_condition (GET_CODE (x));
- }
switch (rc)
{
case NE: fputs ("ne", file); break;
@@ -8000,20 +8198,15 @@ sparc_print_operand (FILE *file, rtx x, int code)
case UNGT: fputs ("ug", file); break;
case UNGE: fputs ("uge", file); break;
case UNEQ: fputs ("ue", file); break;
- default: output_operand_lossage (code == 'c'
- ? "invalid %%c operand"
- : "invalid %%C operand");
+ default: output_operand_lossage ("invalid %%C operand");
}
return;
}
- /* These are used by the movr instruction pattern. */
- case 'd':
+ /* This are used by the movr instruction pattern. */
case 'D':
{
- enum rtx_code rc = (code == 'd'
- ? reverse_condition (GET_CODE (x))
- : GET_CODE (x));
+ enum rtx_code rc = GET_CODE (x);
switch (rc)
{
case NE: fputs ("ne", file); break;
@@ -8022,9 +8215,7 @@ sparc_print_operand (FILE *file, rtx x, int code)
case LT: fputs ("lz", file); break;
case LE: fputs ("lez", file); break;
case GT: fputs ("gz", file); break;
- default: output_operand_lossage (code == 'd'
- ? "invalid %%d operand"
- : "invalid %%D operand");
+ default: output_operand_lossage ("invalid %%D operand");
}
return;
}
@@ -9278,7 +9469,7 @@ sparc_vis_init_builtins (void)
v8qi_ftype_v8qi_v8qi);
def_builtin ("__builtin_vis_faligndatav2si", CODE_FOR_faligndatav2si_vis,
v2si_ftype_v2si_v2si);
- def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatadi_vis,
+ def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatav1di_vis,
di_ftype_di_di);
def_builtin ("__builtin_vis_write_gsr", CODE_FOR_wrgsr_vis,
@@ -9414,7 +9605,7 @@ sparc_vis_init_builtins (void)
v2hi_ftype_v2hi_v2hi);
def_builtin_const ("__builtin_vis_fpadd32", CODE_FOR_addv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fpadd32s", CODE_FOR_addsi3,
+ def_builtin_const ("__builtin_vis_fpadd32s", CODE_FOR_addv1si3,
v1si_ftype_v1si_v1si);
def_builtin_const ("__builtin_vis_fpsub16", CODE_FOR_subv4hi3,
v4hi_ftype_v4hi_v4hi);
@@ -9422,7 +9613,7 @@ sparc_vis_init_builtins (void)
v2hi_ftype_v2hi_v2hi);
def_builtin_const ("__builtin_vis_fpsub32", CODE_FOR_subv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fpsub32s", CODE_FOR_subsi3,
+ def_builtin_const ("__builtin_vis_fpsub32s", CODE_FOR_subv1si3,
v1si_ftype_v1si_v1si);
/* Three-dimensional array addressing. */
@@ -9460,7 +9651,7 @@ sparc_vis_init_builtins (void)
v8qi_ftype_v8qi_v8qi);
def_builtin ("__builtin_vis_bshufflev2si", CODE_FOR_bshufflev2si_vis,
v2si_ftype_v2si_v2si);
- def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshuffledi_vis,
+ def_builtin ("__builtin_vis_bshuffledi", CODE_FOR_bshufflev1di_vis,
di_ftype_di_di);
}
@@ -9488,21 +9679,21 @@ sparc_vis_init_builtins (void)
def_builtin_const ("__builtin_vis_fchksm16", CODE_FOR_fchksm16_vis,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fsll16", CODE_FOR_fsll16_vis,
+ def_builtin_const ("__builtin_vis_fsll16", CODE_FOR_vashlv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fslas16", CODE_FOR_fslas16_vis,
+ def_builtin_const ("__builtin_vis_fslas16", CODE_FOR_vssashlv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fsrl16", CODE_FOR_fsrl16_vis,
+ def_builtin_const ("__builtin_vis_fsrl16", CODE_FOR_vlshrv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fsra16", CODE_FOR_fsra16_vis,
+ def_builtin_const ("__builtin_vis_fsra16", CODE_FOR_vashrv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fsll32", CODE_FOR_fsll32_vis,
+ def_builtin_const ("__builtin_vis_fsll32", CODE_FOR_vashlv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fslas32", CODE_FOR_fslas32_vis,
+ def_builtin_const ("__builtin_vis_fslas32", CODE_FOR_vssashlv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fsrl32", CODE_FOR_fsrl32_vis,
+ def_builtin_const ("__builtin_vis_fsrl32", CODE_FOR_vlshrv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fsra32", CODE_FOR_fsra32_vis,
+ def_builtin_const ("__builtin_vis_fsra32", CODE_FOR_vashrv2si3,
v2si_ftype_v2si_v2si);
if (TARGET_ARCH64)
@@ -9519,21 +9710,21 @@ sparc_vis_init_builtins (void)
def_builtin_const ("__builtin_vis_fpsub64", CODE_FOR_fpsub64_vis,
di_ftype_di_di);
- def_builtin_const ("__builtin_vis_fpadds16", CODE_FOR_fpadds16_vis,
+ def_builtin_const ("__builtin_vis_fpadds16", CODE_FOR_ssaddv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fpadds16s", CODE_FOR_fpadds16s_vis,
+ def_builtin_const ("__builtin_vis_fpadds16s", CODE_FOR_ssaddv2hi3,
v2hi_ftype_v2hi_v2hi);
- def_builtin_const ("__builtin_vis_fpsubs16", CODE_FOR_fpsubs16_vis,
+ def_builtin_const ("__builtin_vis_fpsubs16", CODE_FOR_sssubv4hi3,
v4hi_ftype_v4hi_v4hi);
- def_builtin_const ("__builtin_vis_fpsubs16s", CODE_FOR_fpsubs16s_vis,
+ def_builtin_const ("__builtin_vis_fpsubs16s", CODE_FOR_sssubv2hi3,
v2hi_ftype_v2hi_v2hi);
- def_builtin_const ("__builtin_vis_fpadds32", CODE_FOR_fpadds32_vis,
+ def_builtin_const ("__builtin_vis_fpadds32", CODE_FOR_ssaddv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fpadds32s", CODE_FOR_fpadds32s_vis,
+ def_builtin_const ("__builtin_vis_fpadds32s", CODE_FOR_ssaddv1si3,
v1si_ftype_v1si_v1si);
- def_builtin_const ("__builtin_vis_fpsubs32", CODE_FOR_fpsubs32_vis,
+ def_builtin_const ("__builtin_vis_fpsubs32", CODE_FOR_sssubv2si3,
v2si_ftype_v2si_v2si);
- def_builtin_const ("__builtin_vis_fpsubs32s", CODE_FOR_fpsubs32s_vis,
+ def_builtin_const ("__builtin_vis_fpsubs32s", CODE_FOR_sssubv1si3,
v1si_ftype_v1si_v1si);
if (TARGET_ARCH64)
@@ -9623,6 +9814,13 @@ sparc_expand_builtin (tree exp, rtx target,
insn_op = &insn_data[icode].operand[idx];
op[arg_count] = expand_normal (arg);
+ if (insn_op->mode == V1DImode
+ && GET_MODE (op[arg_count]) == DImode)
+ op[arg_count] = gen_lowpart (V1DImode, op[arg_count]);
+ else if (insn_op->mode == V1SImode
+ && GET_MODE (op[arg_count]) == SImode)
+ op[arg_count] = gen_lowpart (V1SImode, op[arg_count]);
+
if (! (*insn_data[icode].operand[idx].predicate) (op[arg_count],
insn_op->mode))
op[arg_count] = copy_to_mode_reg (insn_op->mode, op[arg_count]);
@@ -10114,10 +10312,28 @@ static int
sparc_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
reg_class_t from, reg_class_t to)
{
- if ((FP_REG_CLASS_P (from) && general_or_i64_p (to))
- || (general_or_i64_p (from) && FP_REG_CLASS_P (to))
- || from == FPCC_REGS
- || to == FPCC_REGS)
+ bool need_memory = false;
+
+ if (from == FPCC_REGS || to == FPCC_REGS)
+ need_memory = true;
+ else if ((FP_REG_CLASS_P (from) && general_or_i64_p (to))
+ || (general_or_i64_p (from) && FP_REG_CLASS_P (to)))
+ {
+ if (TARGET_VIS3)
+ {
+ int size = GET_MODE_SIZE (mode);
+ if (size == 8 || size == 4)
+ {
+ if (! TARGET_ARCH32 || size == 4)
+ return 4;
+ else
+ return 6;
+ }
+ }
+ need_memory = true;
+ }
+
+ if (need_memory)
{
if (sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_ULTRASPARC3
@@ -10385,6 +10601,104 @@ sparc_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
return (vcall_offset >= -32768 || ! fixed_regs[5]);
}
+/* We use the machine specific reorg pass to enable workarounds for errata. */
+
+static void
+sparc_reorg (void)
+{
+ rtx insn, next;
+
+ /* The only erratum we handle for now is that of the AT697F processor. */
+ if (!sparc_fix_at697f)
+ return;
+
+ /* We need to have the (essentially) final form of the insn stream in order
+ to properly detect the various hazards. Run delay slot scheduling. */
+ if (optimize > 0 && flag_delayed_branch)
+ dbr_schedule (get_insns ());
+
+ /* Now look for specific patterns in the insn stream. */
+ for (insn = get_insns (); insn; insn = next)
+ {
+ bool insert_nop = false;
+ rtx set;
+
+ /* Look for a single-word load into an odd-numbered FP register. */
+ if (NONJUMP_INSN_P (insn)
+ && (set = single_set (insn)) != NULL_RTX
+ && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
+ && MEM_P (SET_SRC (set))
+ && REG_P (SET_DEST (set))
+ && REGNO (SET_DEST (set)) > 31
+ && REGNO (SET_DEST (set)) % 2 != 0)
+ {
+ /* The wrong dependency is on the enclosing double register. */
+ unsigned int x = REGNO (SET_DEST (set)) - 1;
+ unsigned int src1, src2, dest;
+ int code;
+
+ /* If the insn has a delay slot, then it cannot be problematic. */
+ next = next_active_insn (insn);
+ if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+ code = -1;
+ else
+ {
+ extract_insn (next);
+ code = INSN_CODE (next);
+ }
+
+ switch (code)
+ {
+ case CODE_FOR_adddf3:
+ case CODE_FOR_subdf3:
+ case CODE_FOR_muldf3:
+ case CODE_FOR_divdf3:
+ dest = REGNO (recog_data.operand[0]);
+ src1 = REGNO (recog_data.operand[1]);
+ src2 = REGNO (recog_data.operand[2]);
+ if (src1 != src2)
+ {
+ /* Case [1-4]:
+ ld [address], %fx+1
+ FPOPd %f{x,y}, %f{y,x}, %f{x,y} */
+ if ((src1 == x || src2 == x)
+ && (dest == src1 || dest == src2))
+ insert_nop = true;
+ }
+ else
+ {
+ /* Case 5:
+ ld [address], %fx+1
+ FPOPd %fx, %fx, %fx */
+ if (src1 == x
+ && dest == src1
+ && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
+ insert_nop = true;
+ }
+ break;
+
+ case CODE_FOR_sqrtdf2:
+ dest = REGNO (recog_data.operand[0]);
+ src1 = REGNO (recog_data.operand[1]);
+ /* Case 6:
+ ld [address], %fx+1
+ fsqrtd %fx, %fx */
+ if (src1 == x && dest == src1)
+ insert_nop = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ next = NEXT_INSN (insn);
+
+ if (insert_nop)
+ emit_insn_after (gen_nop (), insn);
+ }
+}
+
/* How to allocate a 'struct machine_function'. */
static struct machine_function *
@@ -10633,6 +10947,113 @@ sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
emit_move_insn (result, gen_lowpart (GET_MODE (result), res));
}
+void
+sparc_expand_vec_perm_bmask (enum machine_mode vmode, rtx sel)
+{
+ rtx t_1, t_2, t_3;
+
+ sel = gen_lowpart (DImode, sel);
+ switch (vmode)
+ {
+ case V2SImode:
+ /* inp = xxxxxxxAxxxxxxxB */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ....xxxxxxxAxxx. */
+ sel = expand_simple_binop (SImode, AND, gen_lowpart (SImode, sel),
+ GEN_INT (3), NULL_RTX, 1, OPTAB_DIRECT);
+ t_1 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_1),
+ GEN_INT (0x30000), NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = .......B */
+ /* t_1 = ...A.... */
+ sel = expand_simple_binop (SImode, IOR, sel, t_1, sel, 1, OPTAB_DIRECT);
+ /* sel = ...A...B */
+ sel = expand_mult (SImode, sel, GEN_INT (0x4444), sel, 1);
+ /* sel = AAAABBBB * 4 */
+ t_1 = force_reg (SImode, GEN_INT (0x01230123));
+ /* sel = { A*4, A*4+1, A*4+2, ... } */
+ break;
+
+ case V4HImode:
+ /* inp = xxxAxxxBxxxCxxxD */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (8),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_2 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_3 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (24),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ..xxxAxxxBxxxCxx */
+ /* t_2 = ....xxxAxxxBxxxC */
+ /* t_3 = ......xxxAxxxBxx */
+ sel = expand_simple_binop (SImode, AND, gen_lowpart (SImode, sel),
+ GEN_INT (0x07),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_1 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_1),
+ GEN_INT (0x0700),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_2 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_2),
+ GEN_INT (0x070000),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ t_3 = expand_simple_binop (SImode, AND, gen_lowpart (SImode, t_3),
+ GEN_INT (0x07000000),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = .......D */
+ /* t_1 = .....C.. */
+ /* t_2 = ...B.... */
+ /* t_3 = .A...... */
+ sel = expand_simple_binop (SImode, IOR, sel, t_1, sel, 1, OPTAB_DIRECT);
+ t_2 = expand_simple_binop (SImode, IOR, t_2, t_3, t_2, 1, OPTAB_DIRECT);
+ sel = expand_simple_binop (SImode, IOR, sel, t_2, sel, 1, OPTAB_DIRECT);
+ /* sel = .A.B.C.D */
+ sel = expand_mult (SImode, sel, GEN_INT (0x22), sel, 1);
+ /* sel = AABBCCDD * 2 */
+ t_1 = force_reg (SImode, GEN_INT (0x01010101));
+ /* sel = { A*2, A*2+1, B*2, B*2+1, ... } */
+ break;
+
+ case V8QImode:
+ /* input = xAxBxCxDxExFxGxH */
+ sel = expand_simple_binop (DImode, AND, sel,
+ GEN_INT ((HOST_WIDE_INT)0x0f0f0f0f << 32
+ | 0x0f0f0f0f),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = .A.B.C.D.E.F.G.H */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (4),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ..A.B.C.D.E.F.G. */
+ sel = expand_simple_binop (DImode, IOR, sel, t_1,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = .AABBCCDDEEFFGGH */
+ sel = expand_simple_binop (DImode, AND, sel,
+ GEN_INT ((HOST_WIDE_INT)0xff00ff << 32
+ | 0xff00ff),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = ..AB..CD..EF..GH */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (8),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ....AB..CD..EF.. */
+ sel = expand_simple_binop (DImode, IOR, sel, t_1,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = ..ABABCDCDEFEFGH */
+ sel = expand_simple_binop (DImode, AND, sel,
+ GEN_INT ((HOST_WIDE_INT)0xffff << 32 | 0xffff),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* sel = ....ABCD....EFGH */
+ t_1 = expand_simple_binop (DImode, LSHIFTRT, sel, GEN_INT (16),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* t_1 = ........ABCD.... */
+ sel = gen_lowpart (SImode, sel);
+ t_1 = gen_lowpart (SImode, t_1);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Always perform the final addition/merge within the bmask insn. */
+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, t_1));
+}
+
/* Implement TARGET_FRAME_POINTER_REQUIRED. */
static bool
@@ -10748,17 +11169,38 @@ sparc_conditional_register_usage (void)
static reg_class_t
sparc_preferred_reload_class (rtx x, reg_class_t rclass)
{
+ enum machine_mode mode = GET_MODE (x);
if (CONSTANT_P (x))
{
if (FP_REG_CLASS_P (rclass)
|| rclass == GENERAL_OR_FP_REGS
|| rclass == GENERAL_OR_EXTRA_FP_REGS
- || (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT && ! TARGET_FPU)
- || (GET_MODE (x) == TFmode && ! const_zero_operand (x, TFmode)))
+ || (GET_MODE_CLASS (mode) == MODE_FLOAT && ! TARGET_FPU)
+ || (mode == TFmode && ! const_zero_operand (x, mode)))
return NO_REGS;
- if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT)
+ if (GET_MODE_CLASS (mode) == MODE_INT)
return GENERAL_REGS;
+
+ if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
+ {
+ if (! FP_REG_CLASS_P (rclass)
+ || !(const_zero_operand (x, mode)
+ || const_all_ones_operand (x, mode)))
+ return NO_REGS;
+ }
+ }
+
+ if (TARGET_VIS3
+ && ! TARGET_ARCH64
+ && (rclass == EXTRA_FP_REGS
+ || rclass == GENERAL_OR_EXTRA_FP_REGS))
+ {
+ int regno = true_regnum (x);
+
+ if (SPARC_INT_REG_P (regno))
+ return (rclass == EXTRA_FP_REGS
+ ? FP_REGS : GENERAL_OR_FP_REGS);
}
return rclass;
@@ -10837,4 +11279,317 @@ output_v8plus_mult (rtx insn, rtx *operands, const char *name)
}
}
+static void
+vector_init_bshuffle (rtx target, rtx elt, enum machine_mode mode,
+ enum machine_mode inner_mode)
+{
+ rtx t1, final_insn;
+ int bmask;
+
+ t1 = gen_reg_rtx (mode);
+
+ elt = convert_modes (SImode, inner_mode, elt, true);
+ emit_move_insn (gen_lowpart(SImode, t1), elt);
+
+ switch (mode)
+ {
+ case V2SImode:
+ final_insn = gen_bshufflev2si_vis (target, t1, t1);
+ bmask = 0x45674567;
+ break;
+ case V4HImode:
+ final_insn = gen_bshufflev4hi_vis (target, t1, t1);
+ bmask = 0x67676767;
+ break;
+ case V8QImode:
+ final_insn = gen_bshufflev8qi_vis (target, t1, t1);
+ bmask = 0x77777777;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), CONST0_RTX (SImode),
+ force_reg (SImode, GEN_INT (bmask))));
+ emit_insn (final_insn);
+}
+
+static void
+vector_init_fpmerge (rtx target, rtx elt, enum machine_mode inner_mode)
+{
+ rtx t1, t2, t3, t3_low;
+
+ t1 = gen_reg_rtx (V4QImode);
+ elt = convert_modes (SImode, inner_mode, elt, true);
+ emit_move_insn (gen_lowpart (SImode, t1), elt);
+
+ t2 = gen_reg_rtx (V4QImode);
+ emit_move_insn (t2, t1);
+
+ t3 = gen_reg_rtx (V8QImode);
+ t3_low = gen_lowpart (V4QImode, t3);
+
+ emit_insn (gen_fpmerge_vis (t3, t1, t2));
+ emit_move_insn (t1, t3_low);
+ emit_move_insn (t2, t3_low);
+
+ emit_insn (gen_fpmerge_vis (t3, t1, t2));
+ emit_move_insn (t1, t3_low);
+ emit_move_insn (t2, t3_low);
+
+ emit_insn (gen_fpmerge_vis (gen_lowpart (V8QImode, target), t1, t2));
+}
+
+static void
+vector_init_faligndata (rtx target, rtx elt, enum machine_mode inner_mode)
+{
+ rtx t1 = gen_reg_rtx (V4HImode);
+
+ elt = convert_modes (SImode, inner_mode, elt, true);
+
+ emit_move_insn (gen_lowpart (SImode, t1), elt);
+
+ emit_insn (gen_alignaddrsi_vis (gen_reg_rtx (SImode),
+ force_reg (SImode, GEN_INT (6)),
+ CONST0_RTX (SImode)));
+
+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
+ emit_insn (gen_faligndatav4hi_vis (target, t1, target));
+}
+
+void
+sparc_expand_vector_init (rtx target, rtx vals)
+{
+ enum machine_mode mode = GET_MODE (target);
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ int n_elts = GET_MODE_NUNITS (mode);
+ int i, n_var = 0;
+ bool all_same;
+ rtx mem;
+
+ all_same = true;
+ for (i = 0; i < n_elts; i++)
+ {
+ rtx x = XVECEXP (vals, 0, i);
+ if (!CONSTANT_P (x))
+ n_var++;
+
+ if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
+ all_same = false;
+ }
+
+ if (n_var == 0)
+ {
+ emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
+ return;
+ }
+
+ if (GET_MODE_SIZE (inner_mode) == GET_MODE_SIZE (mode))
+ {
+ if (GET_MODE_SIZE (inner_mode) == 4)
+ {
+ emit_move_insn (gen_lowpart (SImode, target),
+ gen_lowpart (SImode, XVECEXP (vals, 0, 0)));
+ return;
+ }
+ else if (GET_MODE_SIZE (inner_mode) == 8)
+ {
+ emit_move_insn (gen_lowpart (DImode, target),
+ gen_lowpart (DImode, XVECEXP (vals, 0, 0)));
+ return;
+ }
+ }
+ else if (GET_MODE_SIZE (inner_mode) == GET_MODE_SIZE (word_mode)
+ && GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode))
+ {
+ emit_move_insn (gen_highpart (word_mode, target),
+ gen_lowpart (word_mode, XVECEXP (vals, 0, 0)));
+ emit_move_insn (gen_lowpart (word_mode, target),
+ gen_lowpart (word_mode, XVECEXP (vals, 0, 1)));
+ return;
+ }
+
+ if (all_same && GET_MODE_SIZE (mode) == 8)
+ {
+ if (TARGET_VIS2)
+ {
+ vector_init_bshuffle (target, XVECEXP (vals, 0, 0), mode, inner_mode);
+ return;
+ }
+ if (mode == V8QImode)
+ {
+ vector_init_fpmerge (target, XVECEXP (vals, 0, 0), inner_mode);
+ return;
+ }
+ if (mode == V4HImode)
+ {
+ vector_init_faligndata (target, XVECEXP (vals, 0, 0), inner_mode);
+ return;
+ }
+ }
+
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
+ for (i = 0; i < n_elts; i++)
+ emit_move_insn (adjust_address_nv (mem, inner_mode,
+ i * GET_MODE_SIZE (inner_mode)),
+ XVECEXP (vals, 0, i));
+ emit_move_insn (target, mem);
+}
+
+static reg_class_t
+sparc_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
+ enum machine_mode mode, secondary_reload_info *sri)
+{
+ enum reg_class rclass = (enum reg_class) rclass_i;
+
+ sri->icode = CODE_FOR_nothing;
+ sri->extra_cost = 0;
+
+ /* We need a temporary when loading/storing a HImode/QImode value
+ between memory and the FPU registers. This can happen when combine puts
+ a paradoxical subreg in a float/fix conversion insn. */
+ if (FP_REG_CLASS_P (rclass)
+ && (mode == HImode || mode == QImode)
+ && (GET_CODE (x) == MEM
+ || ((GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
+ && true_regnum (x) == -1)))
+ return GENERAL_REGS;
+
+ /* On 32-bit we need a temporary when loading/storing a DFmode value
+ between unaligned memory and the upper FPU registers. */
+ if (TARGET_ARCH32
+ && rclass == EXTRA_FP_REGS
+ && mode == DFmode
+ && GET_CODE (x) == MEM
+ && ! mem_min_alignment (x, 8))
+ return FP_REGS;
+
+ if (((TARGET_CM_MEDANY
+ && symbolic_operand (x, mode))
+ || (TARGET_CM_EMBMEDANY
+ && text_segment_operand (x, mode)))
+ && ! flag_pic)
+ {
+ if (in_p)
+ sri->icode = direct_optab_handler (reload_in_optab, mode);
+ else
+ sri->icode = direct_optab_handler (reload_out_optab, mode);
+ return NO_REGS;
+ }
+
+ if (TARGET_VIS3 && TARGET_ARCH32)
+ {
+ int regno = true_regnum (x);
+
+ /* When using VIS3 fp<-->int register moves, on 32-bit we have
+ to move 8-byte values in 4-byte pieces. This only works via
+ FP_REGS, and not via EXTRA_FP_REGS. Therefore if we try to
+ move between EXTRA_FP_REGS and GENERAL_REGS, we will need
+ an FP_REGS intermediate move. */
+ if ((rclass == EXTRA_FP_REGS && SPARC_INT_REG_P (regno))
+ || ((general_or_i64_p (rclass)
+ || rclass == GENERAL_OR_FP_REGS)
+ && SPARC_FP_REG_P (regno)))
+ {
+ sri->extra_cost = 2;
+ return FP_REGS;
+ }
+ }
+
+ return NO_REGS;
+}
+
+bool
+sparc_expand_conditional_move (enum machine_mode mode, rtx *operands)
+{
+ enum rtx_code rc = GET_CODE (operands[1]);
+ enum machine_mode cmp_mode;
+ rtx cc_reg, dst, cmp;
+
+ cmp = operands[1];
+ cmp_mode = GET_MODE (XEXP (cmp, 0));
+ if (cmp_mode == DImode && !TARGET_ARCH64)
+ return false;
+
+ dst = operands[0];
+
+ if (! rtx_equal_p (operands[2], dst)
+ && ! rtx_equal_p (operands[3], dst))
+ {
+ if (reg_overlap_mentioned_p (dst, cmp))
+ dst = gen_reg_rtx (mode);
+
+ emit_move_insn (dst, operands[3]);
+ }
+ else if (operands[2] == dst)
+ {
+ operands[2] = operands[3];
+
+ if (GET_MODE_CLASS (cmp_mode) == MODE_FLOAT)
+ rc = reverse_condition_maybe_unordered (rc);
+ else
+ rc = reverse_condition (rc);
+ }
+
+ if (cmp_mode == TFmode && !TARGET_HARD_QUAD)
+ cmp = sparc_emit_float_lib_cmp (XEXP (cmp, 0), XEXP (cmp, 1), rc);
+
+ if (XEXP (cmp, 1) == const0_rtx
+ && GET_CODE (XEXP (cmp, 0)) == REG
+ && cmp_mode == DImode
+ && v9_regcmp_p (rc))
+ cc_reg = XEXP (cmp, 0);
+ else
+ cc_reg = gen_compare_reg_1 (rc, XEXP (cmp, 0), XEXP (cmp, 1));
+
+ cmp = gen_rtx_fmt_ee (rc, GET_MODE (cc_reg), cc_reg, const0_rtx);
+
+ emit_insn (gen_rtx_SET (VOIDmode, dst,
+ gen_rtx_IF_THEN_ELSE (mode, cmp, operands[2], dst)));
+
+ if (dst != operands[0])
+ emit_move_insn (operands[0], dst);
+
+ return true;
+}
+
+void
+sparc_expand_vcond (enum machine_mode mode, rtx *operands, int ccode, int fcode)
+{
+ rtx mask, cop0, cop1, fcmp, cmask, bshuf, gsr;
+ enum rtx_code code = GET_CODE (operands[3]);
+
+ mask = gen_reg_rtx (Pmode);
+ cop0 = operands[4];
+ cop1 = operands[5];
+ if (code == LT || code == GE)
+ {
+ rtx t;
+
+ code = swap_condition (code);
+ t = cop0; cop0 = cop1; cop1 = t;
+ }
+
+ gsr = gen_rtx_REG (DImode, SPARC_GSR_REG);
+
+ fcmp = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, gen_rtx_fmt_ee (code, mode, cop0, cop1)),
+ fcode);
+
+ cmask = gen_rtx_UNSPEC (DImode,
+ gen_rtvec (2, mask, gsr),
+ ccode);
+
+ bshuf = gen_rtx_UNSPEC (mode,
+ gen_rtvec (3, operands[1], operands[2], gsr),
+ UNSPEC_BSHUFFLE);
+
+ emit_insn (gen_rtx_SET (VOIDmode, mask, fcmp));
+ emit_insn (gen_rtx_SET (VOIDmode, gsr, cmask));
+
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], bshuf));
+}
+
#include "gt-sparc.h"
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index 0642ff2f9e8..65b45271890 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -27,84 +27,6 @@ along with GCC; see the file COPYING3. If not see
/* Note that some other tm.h files include this one and then override
whatever definitions are necessary. */
-/* Define the specific costs for a given cpu */
-
-struct processor_costs {
- /* Integer load */
- const int int_load;
-
- /* Integer signed load */
- const int int_sload;
-
- /* Integer zeroed load */
- const int int_zload;
-
- /* Float load */
- const int float_load;
-
- /* fmov, fneg, fabs */
- const int float_move;
-
- /* fadd, fsub */
- const int float_plusminus;
-
- /* fcmp */
- const int float_cmp;
-
- /* fmov, fmovr */
- const int float_cmove;
-
- /* fmul */
- const int float_mul;
-
- /* fdivs */
- const int float_div_sf;
-
- /* fdivd */
- const int float_div_df;
-
- /* fsqrts */
- const int float_sqrt_sf;
-
- /* fsqrtd */
- const int float_sqrt_df;
-
- /* umul/smul */
- const int int_mul;
-
- /* mulX */
- const int int_mulX;
-
- /* integer multiply cost for each bit set past the most
- significant 3, so the formula for multiply cost becomes:
-
- if (rs1 < 0)
- highest_bit = highest_clear_bit(rs1);
- else
- highest_bit = highest_set_bit(rs1);
- if (highest_bit < 3)
- highest_bit = 3;
- cost = int_mul{,X} + ((highest_bit - 3) / int_mul_bit_factor);
-
- A value of zero indicates that the multiply costs is fixed,
- and not variable. */
- const int int_mul_bit_factor;
-
- /* udiv/sdiv */
- const int int_div;
-
- /* divX */
- const int int_divX;
-
- /* movcc, movr */
- const int int_cmove;
-
- /* penalty for shifts, due to scheduling rules etc. */
- const int shift_penalty;
-};
-
-extern const struct processor_costs *sparc_costs;
-
#define TARGET_CPU_CPP_BUILTINS() sparc_target_macros ()
/* Specify this in a cover file to provide bi-architecture (32/64) support. */
@@ -385,7 +307,6 @@ extern enum cmodel sparc_cmodel;
/* Macros to distinguish the endianness, window model and FP support. */
#define CPP_OTHER_SPEC "\
-%{mlittle-endian:-D__LITTLE_ENDIAN__} \
%{mflat:-D_FLAT} \
%{msoft-float:-D_SOFT_FLOAT} \
"
@@ -675,6 +596,8 @@ extern enum cmodel sparc_cmodel;
#define FIRST_PSEUDO_REGISTER 103
+#define SPARC_FIRST_INT_REG 0
+#define SPARC_LAST_INT_REG 31
#define SPARC_FIRST_FP_REG 32
/* Additional V9 fp regs. */
#define SPARC_FIRST_V9_FP_REG 64
@@ -692,6 +615,10 @@ extern enum cmodel sparc_cmodel;
#define SPARC_FP_REG_P(REGNO) \
((REGNO) >= SPARC_FIRST_FP_REG && (REGNO) <= SPARC_LAST_V9_FP_REG)
+/* Nonzero if REGNO is an int reg. */
+#define SPARC_INT_REG_P(REGNO) \
+(((unsigned) (REGNO)) <= SPARC_LAST_INT_REG)
+
/* Argument passing regs. */
#define SPARC_OUTGOING_INT_ARG_FIRST 8
#define SPARC_INCOMING_INT_ARG_FIRST (TARGET_FLAT ? 8 : 24)
@@ -781,7 +708,7 @@ extern enum cmodel sparc_cmodel;
#define HARD_REGNO_NREGS(REGNO, MODE) \
((REGNO) == SPARC_GSR_REG ? 1 : \
(TARGET_ARCH64 \
- ? ((REGNO) < 32 || (REGNO) == FRAME_POINTER_REGNUM \
+ ? (SPARC_INT_REG_P (REGNO) || (REGNO) == FRAME_POINTER_REGNUM \
? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD \
: (GET_MODE_SIZE (MODE) + 3) / 4) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
@@ -1112,58 +1039,13 @@ extern char leaf_reg_remap[];
#define SPARC_SETHI32_P(X) \
(SPARC_SETHI_P ((unsigned HOST_WIDE_INT) (X) & GET_MODE_MASK (SImode)))
-/* Return the register class of a scratch register needed to load IN into
- a register of class CLASS in MODE.
-
- We need a temporary when loading/storing a HImode/QImode value
- between memory and the FPU registers. This can happen when combine puts
- a paradoxical subreg in a float/fix conversion insn.
-
- We need a temporary when loading/storing a DFmode value between
- unaligned memory and the upper FPU registers. */
-
-#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \
- ((FP_REG_CLASS_P (CLASS) \
- && ((MODE) == HImode || (MODE) == QImode) \
- && (GET_CODE (IN) == MEM \
- || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
- && true_regnum (IN) == -1))) \
- ? GENERAL_REGS \
- : ((CLASS) == EXTRA_FP_REGS && (MODE) == DFmode \
- && GET_CODE (IN) == MEM && TARGET_ARCH32 \
- && ! mem_min_alignment ((IN), 8)) \
- ? FP_REGS \
- : (((TARGET_CM_MEDANY \
- && symbolic_operand ((IN), (MODE))) \
- || (TARGET_CM_EMBMEDANY \
- && text_segment_operand ((IN), (MODE)))) \
- && !flag_pic) \
- ? GENERAL_REGS \
- : NO_REGS)
-
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, IN) \
- ((FP_REG_CLASS_P (CLASS) \
- && ((MODE) == HImode || (MODE) == QImode) \
- && (GET_CODE (IN) == MEM \
- || ((GET_CODE (IN) == REG || GET_CODE (IN) == SUBREG) \
- && true_regnum (IN) == -1))) \
- ? GENERAL_REGS \
- : ((CLASS) == EXTRA_FP_REGS && (MODE) == DFmode \
- && GET_CODE (IN) == MEM && TARGET_ARCH32 \
- && ! mem_min_alignment ((IN), 8)) \
- ? FP_REGS \
- : (((TARGET_CM_MEDANY \
- && symbolic_operand ((IN), (MODE))) \
- || (TARGET_CM_EMBMEDANY \
- && text_segment_operand ((IN), (MODE)))) \
- && !flag_pic) \
- ? GENERAL_REGS \
- : NO_REGS)
-
-/* On SPARC it is not possible to directly move data between
- GENERAL_REGS and FP_REGS. */
+/* On SPARC when not VIS3 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))
+ ((FP_REG_CLASS_P (CLASS1) != FP_REG_CLASS_P (CLASS2)) \
+ && (! TARGET_VIS3 \
+ || GET_MODE_SIZE (MODE) > 8 \
+ || GET_MODE_SIZE (MODE) < 4))
/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on v9
because the movsi and movsf patterns don't handle r/f moves.
@@ -1508,8 +1390,8 @@ do { \
has been allocated, which happens in local-alloc.c. */
#define REGNO_OK_FOR_INDEX_P(REGNO) \
-((REGNO) < 32 || (unsigned) reg_renumber[REGNO] < (unsigned)32 \
- || (REGNO) == FRAME_POINTER_REGNUM \
+(SPARC_INT_REG_P (REGNO) || SPARC_INT_REG_P (reg_renumber[REGNO]) \
+ || (REGNO) == FRAME_POINTER_REGNUM \
|| reg_renumber[REGNO] == FRAME_POINTER_REGNUM)
#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
@@ -1871,10 +1753,6 @@ extern int sparc_indent_opcode;
#ifndef HAVE_AS_FMAF_HPC_VIS3
#define AS_NIAGARA3_FLAG "b"
-#undef TARGET_FMAF
-#define TARGET_FMAF 0
-#undef TARGET_VIS3
-#define TARGET_VIS3 0
#else
#define AS_NIAGARA3_FLAG "d"
#endif
@@ -1884,3 +1762,9 @@ extern int sparc_indent_opcode;
/* We use gcc _mcount for profiling. */
#define NO_PROFILE_COUNTERS 0
+
+/* Debug support */
+#define MASK_DEBUG_OPTIONS 0x01 /* debug option handling */
+#define MASK_DEBUG_ALL MASK_DEBUG_OPTIONS
+
+#define TARGET_DEBUG_OPTIONS (sparc_debug & MASK_DEBUG_OPTIONS)
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 24993fb1821..76be31af3f4 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -53,7 +53,7 @@
(UNSPEC_FPACK32 41)
(UNSPEC_FPACKFIX 42)
(UNSPEC_FEXPAND 43)
- (UNSPEC_FPMERGE 44)
+ (UNSPEC_MUL16AU 44)
(UNSPEC_MUL16AL 45)
(UNSPEC_MUL8UL 46)
(UNSPEC_MULDUL 47)
@@ -89,6 +89,9 @@
(UNSPEC_FHADD 83)
(UNSPEC_FHSUB 84)
(UNSPEC_XMUL 85)
+ (UNSPEC_MUL8 86)
+ (UNSPEC_MUL8SU 87)
+ (UNSPEC_MULDSU 88)
])
(define_constants
@@ -197,24 +200,12 @@
(define_mode_iterator I [QI HI SI DI])
(define_mode_iterator F [SF DF TF])
-;; We don't define V1SI because SI should work just fine.
-(define_mode_iterator V32 [SF V2HI V4QI])
-(define_mode_iterator V32I [SI V2HI V4QI])
-
-(define_mode_iterator V64 [DF V2SI V4HI V8QI])
-(define_mode_iterator V64I [DI V2SI V4HI V8QI])
-
-(define_mode_iterator V64N8 [V2SI V4HI])
-
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
;; a second register class, EXTRA_FP_REGS, exists for the v9 chip. The name
;; is a bit of a misnomer as it covers all 64 fp regs. The corresponding
;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
;; 'f' for all DF/TFmode values, including those that are specific to the v8.
-(define_mode_attr vbits [(V2SI "32") (V4HI "16") (SI "32s") (V2HI "16s")])
-(define_mode_attr vconstr [(V2SI "e") (V4HI "e") (SI "f") (V2HI "f")])
-
;; Attribute for cpu type.
;; These must match the values for enum processor_type in sparc.h.
(define_attr "cpu"
@@ -249,6 +240,17 @@
(symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
(const_string "v7"))))
+(define_attr "cpu_feature" "none,fpu,fpunotv9,v9,vis,vis3" (const_string "none"))
+
+(define_attr "enabled" ""
+ (cond [(eq_attr "cpu_feature" "none") (const_int 1)
+ (eq_attr "cpu_feature" "fpu") (symbol_ref "TARGET_FPU")
+ (eq_attr "cpu_feature" "fpunotv9") (symbol_ref "TARGET_FPU && ! TARGET_V9")
+ (eq_attr "cpu_feature" "v9") (symbol_ref "TARGET_V9")
+ (eq_attr "cpu_feature" "vis") (symbol_ref "TARGET_VIS")
+ (eq_attr "cpu_feature" "vis3") (symbol_ref "TARGET_VIS3")]
+ (const_int 0)))
+
;; Insn type.
(define_attr "type"
"ialu,compare,shift,
@@ -395,15 +397,15 @@
(define_attr "in_call_delay" "false,true"
(cond [(eq_attr "type" "uncond_branch,branch,call,sibcall,call_no_delay_slot,multi")
- (const_string "false")
+ (const_string "false")
(eq_attr "type" "load,fpload,store,fpstore")
- (if_then_else (eq_attr "length" "1")
+ (if_then_else (eq_attr "length" "1")
(const_string "true")
(const_string "false"))]
- (if_then_else (and (eq_attr "length" "1")
- (eq_attr "tls_call_delay" "true"))
- (const_string "true")
- (const_string "false"))))
+ (if_then_else (and (eq_attr "length" "1")
+ (eq_attr "tls_call_delay" "true"))
+ (const_string "true")
+ (const_string "false"))))
(define_attr "eligible_for_sibcall_delay" "false,true"
(symbol_ref "(eligible_for_sibcall_delay (insn)
@@ -654,7 +656,17 @@
(match_operand:DI 2 "register_operand" "")))
(set (match_operand:SI 0 "register_operand" "")
(ne:SI (match_dup 3) (const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64 && ! TARGET_VIS3"
+ { operands[3] = gen_reg_rtx (DImode); })
+
+(define_expand "snedi_special_vis3"
+ [(set (match_dup 3)
+ (xor:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "register_operand" "")))
+ (parallel [(set (match_operand:SI 0 "register_operand" "")
+ (ne:SI (match_dup 3) (const_int 0)))
+ (clobber (reg:CCX CC_REG))])]
+ "TARGET_ARCH64 && TARGET_VIS3"
{ operands[3] = gen_reg_rtx (DImode); })
@@ -711,11 +723,27 @@
""
[(set_attr "length" "2")])
+(define_insn_and_split "*neg_snesi_sign_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (neg:DI (ne:DI (match_operand:SI 1 "register_operand" "r")
+ (const_int 0))))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_ARCH64"
+ "#"
+ "&& 1"
+ [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (minus:SI (const_int 0)
+ (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG)
+ (const_int 0)))))]
+ ""
+ [(set_attr "length" "2")])
+
(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)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64 && ! TARGET_VIS3"
"#"
"&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
@@ -726,6 +754,20 @@
""
[(set_attr "length" "2")])
+(define_insn_and_split "*snedi_zero_vis3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ne:DI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0)))
+ (clobber (reg:CCX CC_REG))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "#"
+ ""
+ [(set (reg:CCX_NOOV CC_REG) (compare:CCX_NOOV (neg:DI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (ltu:DI (reg:CCX CC_REG) (const_int 0)))]
+ ""
+ [(set_attr "length" "2")])
+
(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")
@@ -745,7 +787,7 @@
[(set (match_operand:SI 0 "register_operand" "=&r")
(ne:SI (match_operand:DI 1 "register_operand" "r")
(const_int 0)))]
- "TARGET_ARCH64"
+ "TARGET_ARCH64 && ! TARGET_VIS3"
"#"
"&& ! reg_overlap_mentioned_p (operands[1], operands[0])"
[(set (match_dup 0) (const_int 0))
@@ -756,6 +798,20 @@
""
[(set_attr "length" "2")])
+(define_insn_and_split "*snedi_zero_trunc_vis3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ne:SI (match_operand:DI 1 "register_operand" "r")
+ (const_int 0)))
+ (clobber (reg:CCX CC_REG))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "#"
+ ""
+ [(set (reg:CCX_NOOV CC_REG) (compare:CCX_NOOV (neg:DI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (ltu:SI (reg:CCX CC_REG) (const_int 0)))]
+ ""
+ [(set_attr "length" "2")])
+
(define_insn_and_split "*seqsi_zero"
[(set (match_operand:SI 0 "register_operand" "=r")
(eq:SI (match_operand:SI 1 "register_operand" "r")
@@ -802,6 +858,21 @@
""
[(set_attr "length" "2")])
+(define_insn_and_split "*neg_seqsi_sign_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (neg:DI (eq:DI (match_operand:SI 1 "register_operand" "r")
+ (const_int 0))))
+ (clobber (reg:CC CC_REG))]
+ "TARGET_ARCH64"
+ "#"
+ "&& 1"
+ [(set (reg:CC_NOOV CC_REG) (compare:CC_NOOV (neg:SI (match_dup 1))
+ (const_int 0)))
+ (set (match_dup 0) (sign_extend:DI (neg:SI (geu:SI (reg:CC CC_REG)
+ (const_int 0)))))]
+ ""
+ [(set_attr "length" "2")])
+
(define_insn_and_split "*seqdi_zero"
[(set (match_operand:DI 0 "register_operand" "=&r")
(eq:DI (match_operand:DI 1 "register_operand" "r")
@@ -926,6 +997,27 @@
"addx\t%%g0, 0, %0"
[(set_attr "type" "ialuX")])
+(define_insn "*sltu_insn_vis3"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ltu:DI (reg:CCX CC_REG) (const_int 0)))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "addxc\t%%g0, %%g0, %0"
+ [(set_attr "type" "ialuX")])
+
+(define_insn "*sltu_insn_vis3_trunc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ltu:SI (reg:CCX CC_REG) (const_int 0)))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "addxc\t%%g0, %%g0, %0"
+ [(set_attr "type" "ialuX")])
+
+(define_insn "*sltu_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ltu:DI (reg:CC CC_REG) (const_int 0)))]
+ "TARGET_ARCH64"
+ "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 CC_REG) (const_int 0))))]
@@ -933,6 +1025,13 @@
"subx\t%%g0, 0, %0"
[(set_attr "type" "ialuX")])
+(define_insn "*neg_sltu_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (neg:SI (ltu:SI (reg:CC CC_REG) (const_int 0)))))]
+ "TARGET_ARCH64"
+ "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"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -957,6 +1056,13 @@
"subx\t%%g0, -1, %0"
[(set_attr "type" "ialuX")])
+(define_insn "*sgeu_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (geu:DI (reg:CC CC_REG) (const_int 0)))]
+ "TARGET_ARCH64"
+ "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 CC_REG) (const_int 0))))]
@@ -964,6 +1070,13 @@
"addx\t%%g0, -1, %0"
[(set_attr "type" "ialuX")])
+(define_insn "*neg_sgeu_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (neg:SI (geu:SI (reg:CC CC_REG) (const_int 0)))))]
+ "TARGET_ARCH64"
+ "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
;; versions for v9.
@@ -1322,21 +1435,24 @@
})
(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,!f,!f,!m,d,d")
- (match_operand:SI 1 "input_operand" "rI,K,m,rJ,f,m,f,J,P"))]
- "(register_operand (operands[0], SImode)
- || register_or_zero_or_all_ones_operand (operands[1], SImode))"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m, r,*f,*f,*f, m,d,d")
+ (match_operand:SI 1 "input_operand" "rI,K,m,rJ,*f, r, f, m,*f,J,P"))]
+ "register_operand (operands[0], SImode)
+ || register_or_zero_or_all_ones_operand (operands[1], SImode)"
"@
mov\t%1, %0
sethi\t%%hi(%a1), %0
ld\t%1, %0
st\t%r1, %0
+ movstouw\t%1, %0
+ movwtos\t%1, %0
fmovs\t%1, %0
ld\t%1, %0
st\t%1, %0
fzeros\t%0
fones\t%0"
- [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga,fga")])
+ [(set_attr "type" "*,*,load,store,*,*,fpmove,fpload,fpstore,fga,fga")
+ (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")])
(define_insn "*movsi_lo_sum"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1473,13 +1589,14 @@
(define_insn "*movdi_insn_sp32"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ "=T,o,T,U,o,r,r,r,?T,?*f,?*f,?o,?*e,?*e, r,?*f,?*e,?W,b,b")
(match_operand:DI 1 "input_operand"
- " J,U,T,r,o,i,r, f, T, o, f, f"))]
- "! TARGET_V9
+ " J,J,U,T,r,o,i,r,*f, T, o,*f, *e, *e,?*f, r, W,*e,J,P"))]
+ "! TARGET_ARCH64
&& (register_operand (operands[0], DImode)
|| register_or_zero_operand (operands[1], DImode))"
"@
+ stx\t%%g0, %0
#
std\t%1, %0
ldd\t%1, %0
@@ -1491,42 +1608,22 @@
ldd\t%1, %0
#
#
- #"
- [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
-
-(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,?e,?e,?W")
- (match_operand:DI 1 "input_operand"
- " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
- "! TARGET_ARCH64
- && TARGET_V9
- && (register_operand (operands[0], DImode)
- || register_or_zero_operand (operands[1], DImode))"
- "@
- stx\t%%g0, %0
- #
- std\t%1, %0
- ldd\t%1, %0
- #
+ fmovd\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,*,*,*")
- (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
+ std\t%1, %0
+ fzero\t%0
+ fone\t%0"
+ [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,*,*,*,fpload,fpstore,fga,fga")
+ (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,2,2,2,*,*,*,*")
+ (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*,*,*,*,double,double")
+ (set_attr "cpu_feature" "v9,*,*,*,*,*,*,*,fpu,fpu,fpu,fpu,v9,fpunotv9,vis3,vis3,fpu,fpu,vis,vis")])
(define_insn "*movdi_insn_sp64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,?e,?e,?W,b,b")
- (match_operand:DI 1 "input_operand" "rI,N,m,rJ,e,W,e,J,P"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r, m, r,*e,?*e,?*e,?W,b,b")
+ (match_operand:DI 1 "input_operand" "rI,N,m,rJ,*e, r, *e, W,*e,J,P"))]
"TARGET_ARCH64
&& (register_operand (operands[0], DImode)
|| register_or_zero_or_all_ones_operand (operands[1], DImode))"
@@ -1535,13 +1632,16 @@
sethi\t%%hi(%a1), %0
ldx\t%1, %0
stx\t%r1, %0
+ movdtox\t%1, %0
+ movxtod\t%1, %0
fmovd\t%1, %0
ldd\t%1, %0
std\t%1, %0
fzero\t%0
fone\t%0"
- [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga,fga")
- (set_attr "fptype" "*,*,*,*,double,*,*,double,double")])
+ [(set_attr "type" "*,*,load,store,*,*,fpmove,fpload,fpstore,fga,fga")
+ (set_attr "fptype" "*,*,*,*,*,*,double,*,*,double,double")
+ (set_attr "cpu_feature" "*,*,*,*,vis3,vis3,*,*,*,vis,vis")])
(define_expand "movdi_pic_label_ref"
[(set (match_dup 3) (high:DI
@@ -1766,7 +1866,13 @@
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "const_int_operand" ""))]
- "! TARGET_ARCH64 && reload_completed"
+ "! TARGET_ARCH64
+ && ((GET_CODE (operands[0]) == REG
+ && SPARC_INT_REG_P (REGNO (operands[0])))
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))
+ && reload_completed"
[(clobber (const_int 0))]
{
#if HOST_BITS_PER_WIDE_INT == 32
@@ -1803,10 +1909,10 @@
&& (! TARGET_V9
|| (! TARGET_ARCH64
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))))"
[(clobber (const_int 0))]
{
emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
@@ -1835,11 +1941,8 @@
"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))))"
+ && sparc_split_regreg_legitimate (operands[0],
+ operands[1])))"
[(clobber (const_int 0))]
{
rtx set_dest = operands[0];
@@ -1926,24 +2029,22 @@
})
-;; Floating point and vector move instructions
+;; Floating point move instructions
-;; Yes, you guessed it right, the former movsf expander.
-(define_expand "mov<V32:mode>"
- [(set (match_operand:V32 0 "nonimmediate_operand" "")
- (match_operand:V32 1 "general_operand" ""))]
- "<V32:MODE>mode == SFmode || TARGET_VIS"
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
{
- if (sparc_expand_move (<V32:MODE>mode, operands))
+ if (sparc_expand_move (SFmode, operands))
DONE;
})
(define_insn "*movsf_insn"
- [(set (match_operand:V32 0 "nonimmediate_operand" "=d,d,f,*r,*r,*r,f,*r,m,m")
- (match_operand:V32 1 "input_operand" "GY,ZC,f,*rRY,Q,S,m,m,f,*rGY"))]
- "TARGET_FPU
- && (register_operand (operands[0], <V32:MODE>mode)
- || register_or_zero_or_all_ones_operand (operands[1], <V32:MODE>mode))"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,f, *r,*r,*r,*r, f,f,*r,m, m")
+ (match_operand:SF 1 "input_operand" "G,C,f,*rR, Q, S, f,*r,m, m,f,*rG"))]
+ "(register_operand (operands[0], SFmode)
+ || register_or_zero_or_all_ones_operand (operands[1], SFmode))"
{
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& (which_alternative == 3
@@ -1973,58 +2074,21 @@
case 5:
return "#";
case 6:
+ return "movstouw\t%1, %0";
case 7:
- return "ld\t%1, %0";
+ return "movwtos\t%1, %0";
case 8:
case 9:
- return "st\t%r1, %0";
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "fga,fga,fpmove,*,*,*,fpload,load,fpstore,store")])
-
-;; Exactly the same as above, except that all `f' cases are deleted.
-;; This is necessary to prevent reload from ever trying to use a `f' reg
-;; when -mno-fpu.
-
-(define_insn "*movsf_insn_no_fpu"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,m")
- (match_operand:SF 1 "input_operand" "rR,Q,S,m,rG"))]
- "! TARGET_FPU
- && (register_operand (operands[0], SFmode)
- || register_or_zero_operand (operands[1], SFmode))"
-{
- if (GET_CODE (operands[1]) == CONST_DOUBLE
- && (which_alternative == 0
- || which_alternative == 1
- || which_alternative == 2))
- {
- REAL_VALUE_TYPE r;
- long i;
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_SINGLE (r, i);
- operands[1] = GEN_INT (i);
- }
-
- switch (which_alternative)
- {
- case 0:
- return "mov\t%1, %0";
- case 1:
- return "sethi\t%%hi(%a1), %0";
- case 2:
- return "#";
- case 3:
return "ld\t%1, %0";
- case 4:
+ case 10:
+ case 11:
return "st\t%r1, %0";
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "*,*,*,load,store")])
+ [(set_attr "type" "fga,fga,fpmove,*,*,*,*,*,fpload,load,fpstore,store")
+ (set_attr "cpu_feature" "vis,vis,fpu,*,*,*,vis3,vis3,fpu,*,fpu,*")])
;; The following 3 patterns build SFmode constants in integer registers.
@@ -2060,71 +2124,32 @@
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "fp_const_high_losum_operand" ""))]
- "REG_P (operands[0]) && REGNO (operands[0]) < 32"
+ "REG_P (operands[0]) && SPARC_INT_REG_P (REGNO (operands[0]))"
[(set (match_dup 0) (high:SF (match_dup 1)))
(set (match_dup 0) (lo_sum:SF (match_dup 0) (match_dup 1)))])
-;; Yes, you again guessed it right, the former movdf expander.
-(define_expand "mov<V64:mode>"
- [(set (match_operand:V64 0 "nonimmediate_operand" "")
- (match_operand:V64 1 "general_operand" ""))]
- "<V64:MODE>mode == DFmode || TARGET_VIS"
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
{
- if (sparc_expand_move (<V64:MODE>mode, operands))
+ if (sparc_expand_move (DFmode, operands))
DONE;
})
-;; Be careful, fmovd does not exist when !v9.
(define_insn "*movdf_insn_sp32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,W,U,T,o,e,*r,o,e,o")
- (match_operand:DF 1 "input_operand" "W#F,e,T,U,G,e,*rFo,*r,o#F,e"))]
- "TARGET_FPU
- && ! TARGET_V9
- && (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- ldd\t%1, %0
- std\t%1, %0
- ldd\t%1, %0
- std\t%1, %0
- #
- #
- #
- #
- #
- #"
- [(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
- (set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
-
-(define_insn "*movdf_insn_sp32_no_fpu"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
- (match_operand:DF 1 "input_operand" "T,U,G,ro,r"))]
- "! TARGET_FPU
- && ! TARGET_V9
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=b,b,e,e,*r, f, e,T,W,U,T, f, *r, o,o")
+ (match_operand:DF 1 "input_operand" "G,C,e,e, f,*r,W#F,G,e,T,U,o#F,*roF,*rG,f"))]
+ "! TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- ldd\t%1, %0
- std\t%1, %0
- #
- #
- #"
- [(set_attr "type" "load,store,*,*,*")
- (set_attr "length" "*,*,2,2,2")])
-
-;; We have available v9 double floats but not 64-bit integer registers.
-(define_insn "*movdf_insn_sp32_v9"
- [(set (match_operand:V64 0 "nonimmediate_operand" "=b,b,e,e,T,W,U,T,f,*r,o")
- (match_operand:V64 1 "input_operand" "GY,ZC,e,W#F,GY,e,T,U,o#F,*roGYDF,*rGYf"))]
- "TARGET_FPU
- && TARGET_V9
- && ! TARGET_ARCH64
- && (register_operand (operands[0], <V64:MODE>mode)
- || register_or_zero_or_all_ones_operand (operands[1], <V64:MODE>mode))"
+ || register_or_zero_or_all_ones_operand (operands[1], DFmode))"
"@
fzero\t%0
fone\t%0
fmovd\t%1, %0
+ #
+ #
+ #
ldd\t%1, %0
stx\t%r1, %0
std\t%1, %0
@@ -2132,70 +2157,42 @@
std\t%1, %0
#
#
- #"
- [(set_attr "type" "fga,fga,fpmove,load,store,store,load,store,*,*,*")
- (set_attr "length" "*,*,*,*,*,*,*,*,2,2,2")
- (set_attr "fptype" "double,double,double,*,*,*,*,*,*,*,*")])
-
-(define_insn "*movdf_insn_sp32_v9_no_fpu"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
- (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
- "! TARGET_FPU
- && TARGET_V9
- && ! TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- ldd\t%1, %0
- std\t%1, %0
- stx\t%r1, %0
#
#"
- [(set_attr "type" "load,store,store,*,*")
- (set_attr "length" "*,*,*,2,2")])
+ [(set_attr "type" "fga,fga,fpmove,*,*,*,fpload,store,fpstore,load,store,*,*,*,*")
+ (set_attr "length" "*,*,*,2,2,2,*,*,*,*,*,2,2,2,2")
+ (set_attr "fptype" "double,double,double,*,*,*,*,*,*,*,*,*,*,*,*")
+ (set_attr "cpu_feature" "vis,vis,v9,fpunotv9,vis3,vis3,fpu,v9,fpu,*,*,fpu,*,*,fpu")])
-;; We have available both v9 double floats and 64-bit integer registers.
(define_insn "*movdf_insn_sp64"
- [(set (match_operand:V64 0 "nonimmediate_operand" "=b,b,e,e,W,*r,*r,m,*r")
- (match_operand:V64 1 "input_operand" "GY,ZC,e,W#F,e,*rGY,m,*rGY,DF"))]
- "TARGET_FPU
- && TARGET_ARCH64
- && (register_operand (operands[0], <V64:MODE>mode)
- || register_or_zero_or_all_ones_operand (operands[1], <V64:MODE>mode))"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=b,b,e,*r, e, e,W, *r,*r, m,*r")
+ (match_operand:DF 1 "input_operand" "G,C,e, e,*r,W#F,e,*rG, m,*rG, F"))]
+ "TARGET_ARCH64
+ && (register_operand (operands[0], DFmode)
+ || register_or_zero_or_all_ones_operand (operands[1], DFmode))"
"@
fzero\t%0
fone\t%0
fmovd\t%1, %0
+ movdtox\t%1, %0
+ movxtod\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" "fga,fga,fpmove,load,store,*,load,store,*")
- (set_attr "length" "*,*,*,*,*,*,*,*,2")
- (set_attr "fptype" "double,double,double,*,*,*,*,*,*")])
+ [(set_attr "type" "fga,fga,fpmove,*,*,load,store,*,load,store,*")
+ (set_attr "length" "*,*,*,*,*,*,*,*,*,*,2")
+ (set_attr "fptype" "double,double,double,double,double,*,*,*,*,*,*")
+ (set_attr "cpu_feature" "vis,vis,fpu,vis3,vis3,fpu,fpu,*,*,*,*")])
-(define_insn "*movdf_insn_sp64_no_fpu"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:DF 1 "input_operand" "r,m,rG"))]
- "! TARGET_FPU
- && TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_or_zero_operand (operands[1], DFmode))"
- "@
- mov\t%1, %0
- ldx\t%1, %0
- stx\t%r1, %0"
- [(set_attr "type" "*,load,store")])
-
-;; This pattern builds V64mode constants in integer registers.
+;; This pattern builds DFmode constants in integer registers.
(define_split
- [(set (match_operand:V64 0 "register_operand" "")
- (match_operand:V64 1 "const_double_or_vector_operand" ""))]
- "TARGET_FPU
- && (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "const_double_operand" ""))]
+ "REG_P (operands[0])
+ && SPARC_INT_REG_P (REGNO (operands[0]))
&& ! const_zero_operand (operands[1], GET_MODE (operands[0]))
&& reload_completed"
[(clobber (const_int 0))]
@@ -2246,15 +2243,12 @@
;; careful when V9 but not ARCH64 because the integer
;; register DFmode cases must be handled.
(define_split
- [(set (match_operand:V64 0 "register_operand" "")
- (match_operand:V64 1 "register_operand" ""))]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "register_operand" ""))]
"(! TARGET_V9
|| (! TARGET_ARCH64
- && ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))))
+ && sparc_split_regreg_legitimate (operands[0],
+ operands[1])))
&& reload_completed"
[(clobber (const_int 0))]
{
@@ -2262,18 +2256,11 @@
rtx set_src = operands[1];
rtx dest1, dest2;
rtx src1, src2;
- enum machine_mode half_mode;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- dest1 = gen_highpart (half_mode, set_dest);
- dest2 = gen_lowpart (half_mode, set_dest);
- src1 = gen_highpart (half_mode, set_src);
- src2 = gen_lowpart (half_mode, set_src);
+ dest1 = gen_highpart (SFmode, set_dest);
+ dest2 = gen_lowpart (SFmode, set_dest);
+ src1 = gen_highpart (SFmode, set_src);
+ src2 = gen_lowpart (SFmode, set_src);
/* Now emit using the real source and destination we found, swapping
the order if we detect overlap. */
@@ -2291,8 +2278,8 @@
})
(define_split
- [(set (match_operand:V64 0 "register_operand" "")
- (match_operand:V64 1 "memory_operand" ""))]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "memory_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& (((REGNO (operands[0]) % 2) != 0)
@@ -2300,34 +2287,27 @@
&& offsettable_memref_p (operands[1])"
[(clobber (const_int 0))]
{
- enum machine_mode half_mode;
rtx word0, word1;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- word0 = adjust_address (operands[1], half_mode, 0);
- word1 = adjust_address (operands[1], half_mode, 4);
+ word0 = adjust_address (operands[1], SFmode, 0);
+ word1 = adjust_address (operands[1], SFmode, 4);
- if (reg_overlap_mentioned_p (gen_highpart (half_mode, operands[0]), word1))
+ if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
{
- emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
- emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
+ emit_move_insn_1 (gen_lowpart (SFmode, operands[0]), word1);
+ emit_move_insn_1 (gen_highpart (SFmode, operands[0]), word0);
}
else
{
- emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
- emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
+ emit_move_insn_1 (gen_highpart (SFmode, operands[0]), word0);
+ emit_move_insn_1 (gen_lowpart (SFmode, operands[0]), word1);
}
DONE;
})
(define_split
- [(set (match_operand:V64 0 "memory_operand" "")
- (match_operand:V64 1 "register_operand" ""))]
+ [(set (match_operand:DF 0 "memory_operand" "")
+ (match_operand:DF 1 "register_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& (((REGNO (operands[1]) % 2) != 0)
@@ -2335,26 +2315,19 @@
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
{
- enum machine_mode half_mode;
rtx word0, word1;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- word0 = adjust_address (operands[0], half_mode, 0);
- word1 = adjust_address (operands[0], half_mode, 4);
+ word0 = adjust_address (operands[0], SFmode, 0);
+ word1 = adjust_address (operands[0], SFmode, 4);
- emit_move_insn_1 (word0, gen_highpart (half_mode, operands[1]));
- emit_move_insn_1 (word1, gen_lowpart (half_mode, operands[1]));
+ emit_move_insn_1 (word0, gen_highpart (SFmode, operands[1]));
+ emit_move_insn_1 (word1, gen_lowpart (SFmode, operands[1]));
DONE;
})
(define_split
- [(set (match_operand:V64 0 "memory_operand" "")
- (match_operand:V64 1 "const_zero_operand" ""))]
+ [(set (match_operand:DF 0 "memory_operand" "")
+ (match_operand:DF 1 "const_zero_operand" ""))]
"reload_completed
&& (! TARGET_V9
|| (! TARGET_ARCH64
@@ -2362,49 +2335,35 @@
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
{
- enum machine_mode half_mode;
rtx dest1, dest2;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- dest1 = adjust_address (operands[0], half_mode, 0);
- dest2 = adjust_address (operands[0], half_mode, 4);
+ dest1 = adjust_address (operands[0], SFmode, 0);
+ dest2 = adjust_address (operands[0], SFmode, 4);
- emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
- emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
+ emit_move_insn_1 (dest1, CONST0_RTX (SFmode));
+ emit_move_insn_1 (dest2, CONST0_RTX (SFmode));
DONE;
})
(define_split
- [(set (match_operand:V64 0 "register_operand" "")
- (match_operand:V64 1 "const_zero_operand" ""))]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "const_zero_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(clobber (const_int 0))]
{
- enum machine_mode half_mode;
rtx set_dest = operands[0];
rtx dest1, dest2;
- /* We can be expanded for DFmode or integral vector modes. */
- if (<V64:MODE>mode == DFmode)
- half_mode = SFmode;
- else
- half_mode = SImode;
-
- dest1 = gen_highpart (half_mode, set_dest);
- dest2 = gen_lowpart (half_mode, set_dest);
- emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
- emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
+ dest1 = gen_highpart (SFmode, set_dest);
+ dest2 = gen_lowpart (SFmode, set_dest);
+ emit_move_insn_1 (dest1, CONST0_RTX (SFmode));
+ emit_move_insn_1 (dest2, CONST0_RTX (SFmode));
DONE;
})
@@ -2418,8 +2377,8 @@
})
(define_insn "*movtf_insn_sp32"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,U,r")
- (match_operand:TF 1 "input_operand" "G,oe,GeUr,o,roG"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b, e, o,U, r")
+ (match_operand:TF 1 "input_operand" " G,oe,GeUr,o,roG"))]
"TARGET_FPU
&& ! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
@@ -2432,8 +2391,8 @@
;; when -mno-fpu.
(define_insn "*movtf_insn_sp32_no_fpu"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
- (match_operand:TF 1 "input_operand" "G,o,U,roG,r"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o, r,o")
+ (match_operand:TF 1 "input_operand" " G,o,U,roG,r"))]
"! TARGET_FPU
&& ! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
@@ -2442,8 +2401,8 @@
[(set_attr "length" "4")])
(define_insn "*movtf_insn_sp64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,r")
- (match_operand:TF 1 "input_operand" "G,oe,Ger,roG"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b, e, o, r")
+ (match_operand:TF 1 "input_operand" "G,oe,Ger,roG"))]
"TARGET_FPU
&& TARGET_ARCH64
&& ! TARGET_HARD_QUAD
@@ -2453,8 +2412,8 @@
[(set_attr "length" "2")])
(define_insn "*movtf_insn_sp64_hq"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m,o,r")
- (match_operand:TF 1 "input_operand" "G,e,m,e,rG,roG"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m, o, r")
+ (match_operand:TF 1 "input_operand" "G,e,m,e,rG,roG"))]
"TARGET_FPU
&& TARGET_ARCH64
&& TARGET_HARD_QUAD
@@ -2471,8 +2430,8 @@
(set_attr "length" "2,*,*,*,2,2")])
(define_insn "*movtf_insn_sp64_no_fpu"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
- (match_operand:TF 1 "input_operand" "orG,rG"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "= r, o")
+ (match_operand:TF 1 "input_operand" "orG,rG"))]
"! TARGET_FPU
&& TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
@@ -2488,7 +2447,8 @@
&& (! TARGET_ARCH64
|| (TARGET_FPU
&& ! TARGET_HARD_QUAD)
- || ! fp_register_operand (operands[0], TFmode))"
+ || (! fp_register_operand (operands[0], TFmode)
+ && ! fp_register_operand (operands[1], TFmode)))"
[(clobber (const_int 0))]
{
rtx set_dest = operands[0];
@@ -2606,6 +2566,9 @@
;; 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).
+;;
+;; Our instruction patterns, on the other hand, canonicalize such that
+;; operand 3 must be the set destination.
(define_expand "mov<I:mode>cc"
[(set (match_operand:I 0 "register_operand" "")
@@ -2614,27 +2577,9 @@
(match_operand:I 3 "arith10_operand" "")))]
"TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
{
- rtx cc_reg;
-
- if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
+ if (! sparc_expand_conditional_move (<I:MODE>mode, operands))
FAIL;
-
- if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
- operands[1]
- = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
- GET_CODE (operands[1]));
-
- if (XEXP (operands[1], 1) == const0_rtx
- && GET_CODE (XEXP (operands[1], 0)) == REG
- && GET_MODE (XEXP (operands[1], 0)) == DImode
- && v9_regcmp_p (GET_CODE (operands[1])))
- cc_reg = XEXP (operands[1], 0);
- else
- cc_reg = gen_compare_reg (operands[1]);
-
- operands[1]
- = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
- const0_rtx);
+ DONE;
})
(define_expand "mov<F:mode>cc"
@@ -2644,146 +2589,112 @@
(match_operand:F 3 "register_operand" "")))]
"TARGET_V9 && TARGET_FPU"
{
- rtx cc_reg;
-
- if (GET_MODE (XEXP (operands[1], 0)) == DImode && !TARGET_ARCH64)
+ if (! sparc_expand_conditional_move (<F:MODE>mode, operands))
FAIL;
-
- if (GET_MODE (XEXP (operands[1], 0)) == TFmode && !TARGET_HARD_QUAD)
- operands[1]
- = sparc_emit_float_lib_cmp (XEXP (operands[1], 0), XEXP (operands[1], 1),
- GET_CODE (operands[1]));
-
- if (XEXP (operands[1], 1) == const0_rtx
- && GET_CODE (XEXP (operands[1], 0)) == REG
- && GET_MODE (XEXP (operands[1], 0)) == DImode
- && v9_regcmp_p (GET_CODE (operands[1])))
- cc_reg = XEXP (operands[1], 0);
- else
- cc_reg = gen_compare_reg (operands[1]);
-
- operands[1]
- = gen_rtx_fmt_ee (GET_CODE (operands[1]), GET_MODE (cc_reg), cc_reg,
- const0_rtx);
+ DONE;
})
;; Conditional move define_insns
(define_insn "*mov<I:mode>_cc_v9"
- [(set (match_operand:I 0 "register_operand" "=r,r")
+ [(set (match_operand:I 0 "register_operand" "=r")
(if_then_else:I (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:I 3 "arith11_operand" "rL,0")
- (match_operand:I 4 "arith11_operand" "0,rL")))]
+ (match_operand:I 3 "arith11_operand" "rL")
+ (match_operand:I 4 "register_operand" "0")))]
"TARGET_V9 && !(<I:MODE>mode == DImode && TARGET_ARCH32)"
- "@
- mov%C1\t%x2, %3, %0
- mov%c1\t%x2, %4, %0"
+ "mov%C1\t%x2, %3, %0"
[(set_attr "type" "cmove")])
(define_insn "*mov<I:mode>_cc_reg_sp64"
- [(set (match_operand:I 0 "register_operand" "=r,r")
+ [(set (match_operand:I 0 "register_operand" "=r")
(if_then_else:I (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:I 3 "arith10_operand" "rM,0")
- (match_operand:I 4 "arith10_operand" "0,rM")))]
+ (match_operand:I 3 "arith10_operand" "rM")
+ (match_operand:I 4 "register_operand" "0")))]
"TARGET_ARCH64"
- "@
- movr%D1\t%2, %r3, %0
- movr%d1\t%2, %r4, %0"
+ "movr%D1\t%2, %r3, %0"
[(set_attr "type" "cmove")])
(define_insn "*movsf_cc_v9"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
+ [(set (match_operand:SF 0 "register_operand" "=f")
(if_then_else:SF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
+ (match_operand:SF 3 "register_operand" "f")
+ (match_operand:SF 4 "register_operand" "0")))]
"TARGET_V9 && TARGET_FPU"
- "@
- fmovs%C1\t%x2, %3, %0
- fmovs%c1\t%x2, %4, %0"
+ "fmovs%C1\t%x2, %3, %0"
[(set_attr "type" "fpcmove")])
(define_insn "*movsf_cc_reg_sp64"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
+ [(set (match_operand:SF 0 "register_operand" "=f")
(if_then_else:SF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:SF 3 "register_operand" "f,0")
- (match_operand:SF 4 "register_operand" "0,f")))]
+ (match_operand:SF 3 "register_operand" "f")
+ (match_operand:SF 4 "register_operand" "0")))]
"TARGET_ARCH64 && TARGET_FPU"
- "@
- fmovrs%D1\t%2, %3, %0
- fmovrs%d1\t%2, %4, %0"
+ "fmovrs%D1\t%2, %3, %0"
[(set_attr "type" "fpcrmove")])
;; Named because invoked by movtf_cc_v9
(define_insn "movdf_cc_v9"
- [(set (match_operand:DF 0 "register_operand" "=e,e")
+ [(set (match_operand:DF 0 "register_operand" "=e")
(if_then_else:DF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:DF 3 "register_operand" "e,0")
- (match_operand:DF 4 "register_operand" "0,e")))]
+ (match_operand:DF 3 "register_operand" "e")
+ (match_operand:DF 4 "register_operand" "0")))]
"TARGET_V9 && TARGET_FPU"
- "@
- fmovd%C1\t%x2, %3, %0
- fmovd%c1\t%x2, %4, %0"
+ "fmovd%C1\t%x2, %3, %0"
[(set_attr "type" "fpcmove")
(set_attr "fptype" "double")])
;; Named because invoked by movtf_cc_reg_sp64
(define_insn "movdf_cc_reg_sp64"
- [(set (match_operand:DF 0 "register_operand" "=e,e")
+ [(set (match_operand:DF 0 "register_operand" "=e")
(if_then_else:DF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:DF 3 "register_operand" "e,0")
- (match_operand:DF 4 "register_operand" "0,e")))]
+ (match_operand:DF 3 "register_operand" "e")
+ (match_operand:DF 4 "register_operand" "0")))]
"TARGET_ARCH64 && TARGET_FPU"
- "@
- fmovrd%D1\t%2, %3, %0
- fmovrd%d1\t%2, %4, %0"
+ "fmovrd%D1\t%2, %3, %0"
[(set_attr "type" "fpcrmove")
(set_attr "fptype" "double")])
(define_insn "*movtf_cc_hq_v9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
+ [(set (match_operand:TF 0 "register_operand" "=e")
(if_then_else:TF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e")
+ (match_operand:TF 4 "register_operand" "0")))]
"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"
[(set_attr "type" "fpcmove")])
(define_insn "*movtf_cc_reg_hq_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
+ [(set (match_operand:TF 0 "register_operand" "=e")
(if_then_else:TF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e")
+ (match_operand:TF 4 "register_operand" "0")))]
"TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
- "@
- fmovrq%D1\t%2, %3, %0
- fmovrq%d1\t%2, %4, %0"
+ "fmovrq%D1\t%2, %3, %0"
[(set_attr "type" "fpcrmove")])
(define_insn_and_split "*movtf_cc_v9"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
+ [(set (match_operand:TF 0 "register_operand" "=e")
(if_then_else:TF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e")
+ (match_operand:TF 4 "register_operand" "0")))]
"TARGET_V9 && TARGET_FPU && !TARGET_HARD_QUAD"
"#"
"&& reload_completed"
@@ -2791,42 +2702,35 @@
{
rtx set_dest = operands[0];
rtx set_srca = operands[3];
- rtx set_srcb = operands[4];
- int third = rtx_equal_p (set_dest, set_srca);
rtx dest1, dest2;
- rtx srca1, srca2, srcb1, srcb2;
+ rtx srca1, srca2;
dest1 = gen_df_reg (set_dest, 0);
dest2 = gen_df_reg (set_dest, 1);
srca1 = gen_df_reg (set_srca, 0);
srca2 = gen_df_reg (set_srca, 1);
- srcb1 = gen_df_reg (set_srcb, 0);
- srcb2 = gen_df_reg (set_srcb, 1);
- /* Now emit using the real source and destination we found, swapping
- the order if we detect overlap. */
- if ((third && reg_overlap_mentioned_p (dest1, srcb2))
- || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+ if (reg_overlap_mentioned_p (dest1, srca2))
{
- emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
- emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, dest2));
+ emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, dest1));
}
else
{
- emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, srcb1));
- emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_v9 (dest1, operands[1], operands[2], srca1, dest1));
+ emit_insn (gen_movdf_cc_v9 (dest2, operands[1], operands[2], srca2, dest2));
}
DONE;
}
[(set_attr "length" "2")])
(define_insn_and_split "*movtf_cc_reg_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e,e")
+ [(set (match_operand:TF 0 "register_operand" "=e")
(if_then_else:TF (match_operator 1 "v9_register_compare_operator"
- [(match_operand:DI 2 "register_operand" "r,r")
+ [(match_operand:DI 2 "register_operand" "r")
(const_int 0)])
- (match_operand:TF 3 "register_operand" "e,0")
- (match_operand:TF 4 "register_operand" "0,e")))]
+ (match_operand:TF 3 "register_operand" "e")
+ (match_operand:TF 4 "register_operand" "0")))]
"TARGET_ARCH64 && TARGET_FPU && ! TARGET_HARD_QUAD"
"#"
"&& reload_completed"
@@ -2834,30 +2738,23 @@
{
rtx set_dest = operands[0];
rtx set_srca = operands[3];
- rtx set_srcb = operands[4];
- int third = rtx_equal_p (set_dest, set_srca);
rtx dest1, dest2;
- rtx srca1, srca2, srcb1, srcb2;
+ rtx srca1, srca2;
dest1 = gen_df_reg (set_dest, 0);
dest2 = gen_df_reg (set_dest, 1);
srca1 = gen_df_reg (set_srca, 0);
srca2 = gen_df_reg (set_srca, 1);
- srcb1 = gen_df_reg (set_srcb, 0);
- srcb2 = gen_df_reg (set_srcb, 1);
- /* Now emit using the real source and destination we found, swapping
- the order if we detect overlap. */
- if ((third && reg_overlap_mentioned_p (dest1, srcb2))
- || (!third && reg_overlap_mentioned_p (dest1, srca2)))
+ if (reg_overlap_mentioned_p (dest1, srca2))
{
- emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
- emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, dest2));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, dest1));
}
else
{
- emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, srcb1));
- emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, srcb2));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest1, operands[1], operands[2], srca1, dest1));
+ emit_insn (gen_movdf_cc_reg_sp64 (dest2, operands[1], operands[2], srca2, dest2));
}
DONE;
}
@@ -2989,13 +2886,16 @@
"")
(define_insn "*zero_extendsidi2_insn_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
- "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+ (zero_extend:DI (match_operand:SI 1 "input_operand" "r,m,*f")))]
+ "TARGET_ARCH64
+ && GET_CODE (operands[1]) != CONST_INT"
"@
srl\t%1, 0, %0
- lduw\t%1, %0"
- [(set_attr "type" "shift,load")])
+ lduw\t%1, %0
+ movstouw\t%1, %0"
+ [(set_attr "type" "shift,load,*")
+ (set_attr "cpu_feature" "*,*,vis3")])
(define_insn_and_split "*zero_extendsidi2_insn_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -3321,14 +3221,16 @@
"")
(define_insn "*sign_extendsidi2_insn"
- [(set (match_operand:DI 0 "register_operand" "=r,r")
- (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m")))]
+ [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+ (sign_extend:DI (match_operand:SI 1 "input_operand" "r,m,*f")))]
"TARGET_ARCH64"
"@
sra\t%1, 0, %0
- ldsw\t%1, %0"
- [(set_attr "type" "shift,sload")
- (set_attr "us3load_type" "*,3cycle")])
+ ldsw\t%1, %0
+ movstosw\t%1, %0"
+ [(set_attr "type" "shift,sload,*")
+ (set_attr "us3load_type" "*,3cycle,*")
+ (set_attr "cpu_feature" "*,*,vis3")])
;; Special pattern for optimizing bit-field compares. This is needed
@@ -3692,6 +3594,15 @@
"addx\t%1, %2, %0"
[(set_attr "type" "ialuX")])
+(define_insn "addxc"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (plus:DI (match_operand:DI 1 "register_or_zero_operand" "%rJ")
+ (match_operand:DI 2 "register_or_zero_operand" "rJ"))
+ (ltu:DI (reg:CCX_NOOV CC_REG) (const_int 0))))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "addxc\t%r1, %r2, %0"
+ [(set_attr "type" "ialuX")])
+
(define_insn_and_split "*addx_extend_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (plus:SI
@@ -3711,10 +3622,19 @@
(define_insn "*addx_extend_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
- (match_operand:SI 2 "arith_operand" "rI"))
+ (match_operand:SI 2 "register_or_zero_operand" "rJ"))
(ltu:SI (reg:CC_NOOV CC_REG) (const_int 0)))))]
"TARGET_ARCH64"
- "addx\t%r1, %2, %0"
+ "addx\t%r1, %r2, %0"
+ [(set_attr "type" "ialuX")])
+
+(define_insn "*addxc_trunc_sp64_vis3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
+ (match_operand:SI 2 "register_or_zero_operand" "rJ"))
+ (ltu:SI (reg:CCX_NOOV CC_REG) (const_int 0))))]
+ "TARGET_ARCH64 && TARGET_VIS3"
+ "addxc\t%r1, %r2, %0"
[(set_attr "type" "ialuX")])
(define_insn_and_split "*adddi3_extend_sp32"
@@ -3748,16 +3668,15 @@
sub\t%1, -%2, %0")
(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")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
+ (match_operand:SI 2 "arith_add_operand" "rI,O")))]
""
"@
add\t%1, %2, %0
- sub\t%1, -%2, %0
- fpadd32s\t%1, %2, %0"
- [(set_attr "type" "*,*,fga")
- (set_attr "fptype" "*,*,single")])
+ sub\t%1, -%2, %0"
+ [(set_attr "type" "*,*")
+ (set_attr "fptype" "*,*")])
(define_insn "*cmp_cc_plus"
[(set (reg:CC_NOOV CC_REG)
@@ -3920,16 +3839,15 @@
add\t%1, -%2, %0")
(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")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r,r")
+ (match_operand:SI 2 "arith_add_operand" "rI,O")))]
""
"@
sub\t%1, %2, %0
- add\t%1, -%2, %0
- fpsub32s\t%1, %2, %0"
- [(set_attr "type" "*,*,fga")
- (set_attr "fptype" "*,*,single")])
+ add\t%1, -%2, %0"
+ [(set_attr "type" "*,*")
+ (set_attr "fptype" "*,*")])
(define_insn "*cmp_minus_cc"
[(set (reg:CC_NOOV CC_REG)
@@ -4654,46 +4572,33 @@
;; We define DImode `and' so with DImode `not' we can get
;; DImode `andn'. Other combinations are possible.
-(define_expand "and<V64I:mode>3"
- [(set (match_operand:V64I 0 "register_operand" "")
- (and:V64I (match_operand:V64I 1 "arith_double_operand" "")
- (match_operand:V64I 2 "arith_double_operand" "")))]
+(define_expand "anddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (match_operand:DI 1 "arith_double_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*and<V64I:mode>3_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (and:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
- (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*anddi3_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (match_operand:DI 1 "arith_double_operand" "%r")
+ (match_operand:DI 2 "arith_double_operand" "rHI")))]
"! TARGET_ARCH64"
- "@
- #
- fand\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*and<V64I:mode>3_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (and:V64I (match_operand:V64I 1 "arith_operand" "%r,b")
- (match_operand:V64I 2 "arith_operand" "rI,b")))]
+ "#")
+
+(define_insn "*anddi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (match_operand:DI 1 "arith_operand" "%r")
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "@
- and\t%1, %2, %0
- fand\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "and\t%1, %2, %0")
-(define_insn "and<V32I:mode>3"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (and:V32I (match_operand:V32I 1 "arith_operand" "%r,d")
- (match_operand:V32I 2 "arith_operand" "rI,d")))]
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
""
- "@
- and\t%1, %2, %0
- fands\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "and\t%1, %2, %0")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4707,20 +4612,18 @@
operands[4] = GEN_INT (~INTVAL (operands[2]));
})
-(define_insn_and_split "*and_not_<V64I:mode>_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (and:V64I (not:V64I (match_operand:V64I 1 "register_operand" "%r,b"))
- (match_operand:V64I 2 "register_operand" "r,b")))]
+(define_insn_and_split "*and_not_di_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "%r"))
+ (match_operand:DI 2 "register_operand" "r")))]
"! TARGET_ARCH64"
- "@
- #
- fandnot1\t%1, %2, %0"
+ "#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))
(set (match_dup 6) (and:SI (not:SI (match_dup 7)) (match_dup 8)))]
"operands[3] = gen_highpart (SImode, operands[0]);
@@ -4729,72 +4632,50 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*and_not_<V64I:mode>_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (and:V64I (not:V64I (match_operand:V64I 1 "register_operand" "%r,b"))
- (match_operand:V64I 2 "register_operand" "r,b")))]
+ [(set_attr "length" "2")])
+
+(define_insn "*and_not_di_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" "%r"))
+ (match_operand:DI 2 "register_operand" "r")))]
"TARGET_ARCH64"
- "@
- andn\t%2, %1, %0
- fandnot1\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "andn\t%2, %1, %0")
-(define_insn "*and_not_<V32I:mode>"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (and:V32I (not:V32I (match_operand:V32I 1 "register_operand" "%r,d"))
- (match_operand:V32I 2 "register_operand" "r,d")))]
+(define_insn "*and_not_si"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
+ (match_operand:SI 2 "register_operand" "r")))]
""
- "@
- andn\t%2, %1, %0
- fandnot1s\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "andn\t%2, %1, %0")
-(define_expand "ior<V64I:mode>3"
- [(set (match_operand:V64I 0 "register_operand" "")
- (ior:V64I (match_operand:V64I 1 "arith_double_operand" "")
- (match_operand:V64I 2 "arith_double_operand" "")))]
+(define_expand "iordi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (ior:DI (match_operand:DI 1 "arith_double_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*ior<V64I:mode>3_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (ior:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
- (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*iordi3_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (match_operand:DI 1 "arith_double_operand" "%r")
+ (match_operand:DI 2 "arith_double_operand" "rHI")))]
"! TARGET_ARCH64"
- "@
- #
- for\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*ior<V64I:mode>3_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (ior:V64I (match_operand:V64I 1 "arith_operand" "%r,b")
- (match_operand:V64I 2 "arith_operand" "rI,b")))]
+ "#"
+ [(set_attr "length" "2")])
+
+(define_insn "*iordi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (match_operand:DI 1 "arith_operand" "%r")
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "@
- or\t%1, %2, %0
- for\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "or\t%1, %2, %0")
-(define_insn "ior<V32I:mode>3"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (ior:V32I (match_operand:V32I 1 "arith_operand" "%r,d")
- (match_operand:V32I 2 "arith_operand" "rI,d")))]
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
""
- "@
- or\t%1, %2, %0
- fors\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "or\t%1, %2, %0")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4808,20 +4689,18 @@
operands[4] = GEN_INT (~INTVAL (operands[2]));
})
-(define_insn_and_split "*or_not_<V64I:mode>_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (ior:V64I (not:V64I (match_operand:V64I 1 "register_operand" "r,b"))
- (match_operand:V64I 2 "register_operand" "r,b")))]
+(define_insn_and_split "*or_not_di_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
+ (match_operand:DI 2 "register_operand" "r")))]
"! TARGET_ARCH64"
- "@
- #
- fornot1\t%1, %2, %0"
+ "#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 3) (ior:SI (not:SI (match_dup 4)) (match_dup 5)))
(set (match_dup 6) (ior:SI (not:SI (match_dup 7)) (match_dup 8)))]
"operands[3] = gen_highpart (SImode, operands[0]);
@@ -4830,72 +4709,50 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*or_not_<V64I:mode>_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (ior:V64I (not:V64I (match_operand:V64I 1 "register_operand" "r,b"))
- (match_operand:V64I 2 "register_operand" "r,b")))]
+ [(set_attr "length" "2")])
+
+(define_insn "*or_not_di_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r"))
+ (match_operand:DI 2 "register_operand" "r")))]
"TARGET_ARCH64"
- "@
- orn\t%2, %1, %0
- fornot1\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "orn\t%2, %1, %0")
-(define_insn "*or_not_<V32I:mode>"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (ior:V32I (not:V32I (match_operand:V32I 1 "register_operand" "r,d"))
- (match_operand:V32I 2 "register_operand" "r,d")))]
+(define_insn "*or_not_si"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r")))]
""
- "@
- orn\t%2, %1, %0
- fornot1s\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "orn\t%2, %1, %0")
-(define_expand "xor<V64I:mode>3"
- [(set (match_operand:V64I 0 "register_operand" "")
- (xor:V64I (match_operand:V64I 1 "arith_double_operand" "")
- (match_operand:V64I 2 "arith_double_operand" "")))]
+(define_expand "xordi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (xor:DI (match_operand:DI 1 "arith_double_operand" "")
+ (match_operand:DI 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*xor<V64I:mode>3_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (xor:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
- (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*xordi3_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
+ (match_operand:DI 2 "arith_double_operand" "rHI")))]
"! TARGET_ARCH64"
- "@
- #
- fxor\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*xor<V64I:mode>3_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (xor:V64I (match_operand:V64I 1 "arith_operand" "%rJ,b")
- (match_operand:V64I 2 "arith_operand" "rI,b")))]
+ "#"
+ [(set_attr "length" "2")])
+
+(define_insn "*xordi3_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (xor:DI (match_operand:DI 1 "arith_operand" "%rJ")
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "@
- xor\t%r1, %2, %0
- fxor\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "xor\t%r1, %2, %0")
-(define_insn "xor<V32I:mode>3"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (xor:V32I (match_operand:V32I 1 "arith_operand" "%rJ,d")
- (match_operand:V32I 2 "arith_operand" "rI,d")))]
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "arith_operand" "%rJ")
+ (match_operand:SI 2 "arith_operand" "rI")))]
""
- "@
- xor\t%r1, %2, %0
- fxors\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "xor\t%r1, %2, %0")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
@@ -4923,17 +4780,17 @@
;; Split DImode logical operations requiring two instructions.
(define_split
- [(set (match_operand:V64I 0 "register_operand" "")
- (match_operator:V64I 1 "cc_arith_operator" ; AND, IOR, XOR
- [(match_operand:V64I 2 "register_operand" "")
- (match_operand:V64I 3 "arith_double_operand" "")]))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operator:DI 1 "cc_arith_operator" ; AND, IOR, XOR
+ [(match_operand:DI 2 "register_operand" "")
+ (match_operand:DI 3 "arith_double_operand" "")]))]
"! TARGET_ARCH64
&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(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)]))]
{
@@ -4942,7 +4799,7 @@
operands[6] = gen_highpart (SImode, operands[2]);
operands[7] = gen_lowpart (SImode, operands[2]);
#if HOST_BITS_PER_WIDE_INT == 32
- if (GET_CODE (operands[3]) == CONST_INT && <V64I:MODE>mode == DImode)
+ if (GET_CODE (operands[3]) == CONST_INT)
{
if (INTVAL (operands[3]) < 0)
operands[8] = constm1_rtx;
@@ -4951,26 +4808,24 @@
}
else
#endif
- operands[8] = gen_highpart_mode (SImode, <V64I:MODE>mode, operands[3]);
+ operands[8] = gen_highpart_mode (SImode, DImode, operands[3]);
operands[9] = gen_lowpart (SImode, operands[3]);
})
;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
;; Combine now canonicalizes to the rightmost expression.
-(define_insn_and_split "*xor_not_<V64I:mode>_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (not:V64I (xor:V64I (match_operand:V64I 1 "register_operand" "r,b")
- (match_operand:V64I 2 "register_operand" "r,b"))))]
+(define_insn_and_split "*xor_not_di_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r"))))]
"! TARGET_ARCH64"
- "@
- #
- fxnor\t%1, %2, %0"
+ "#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 3) (not:SI (xor:SI (match_dup 4) (match_dup 5))))
(set (match_dup 6) (not:SI (xor:SI (match_dup 7) (match_dup 8))))]
"operands[3] = gen_highpart (SImode, operands[0]);
@@ -4979,31 +4834,21 @@
operands[6] = gen_lowpart (SImode, operands[0]);
operands[7] = gen_lowpart (SImode, operands[1]);
operands[8] = gen_lowpart (SImode, operands[2]);"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
-
-(define_insn "*xor_not_<V64I:mode>_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (not:V64I (xor:V64I (match_operand:V64I 1 "register_or_zero_operand" "rJ,b")
- (match_operand:V64I 2 "arith_operand" "rI,b"))))]
+ [(set_attr "length" "2")])
+
+(define_insn "*xor_not_di_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (xor:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
+ (match_operand:DI 2 "arith_operand" "rI"))))]
"TARGET_ARCH64"
- "@
- xnor\t%r1, %2, %0
- fxnor\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "xnor\t%r1, %2, %0")
-(define_insn "*xor_not_<V32I:mode>"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (not:V32I (xor:V32I (match_operand:V32I 1 "register_or_zero_operand" "rJ,d")
- (match_operand:V32I 2 "arith_operand" "rI,d"))))]
+(define_insn "*xor_not_si"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))))]
""
- "@
- xnor\t%r1, %2, %0
- fxnors\t%1, %2, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "xnor\t%r1, %2, %0")
;; These correspond to the above in the case where we also (or only)
;; want to set the condition code.
@@ -5241,54 +5086,42 @@
;; We cannot use the "not" pseudo insn because the Sun assembler
;; does not know how to make it work for constants.
-(define_expand "one_cmpl<V64I:mode>2"
- [(set (match_operand:V64I 0 "register_operand" "")
- (not:V64I (match_operand:V64I 1 "register_operand" "")))]
+(define_expand "one_cmpldi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (not:DI (match_operand:DI 1 "register_operand" "")))]
""
"")
-(define_insn_and_split "*one_cmpl<V64I:mode>2_sp32"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (not:V64I (match_operand:V64I 1 "register_operand" "r,b")))]
+(define_insn_and_split "*one_cmpldi2_sp32"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (match_operand:DI 1 "register_operand" "r")))]
"! TARGET_ARCH64"
- "@
- #
- fnot1\t%1, %0"
+ "#"
"&& reload_completed
&& ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
+ && SPARC_INT_REG_P (REGNO (operands[0])))
|| (GET_CODE (operands[0]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
+ && SPARC_INT_REG_P (REGNO (SUBREG_REG (operands[0])))))"
[(set (match_dup 2) (not:SI (xor:SI (match_dup 3) (const_int 0))))
(set (match_dup 4) (not:SI (xor:SI (match_dup 5) (const_int 0))))]
"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]);"
- [(set_attr "type" "*,fga")
- (set_attr "length" "2,*")
- (set_attr "fptype" "*,double")])
+ [(set_attr "length" "2")])
-(define_insn "*one_cmpl<V64I:mode>2_sp64"
- [(set (match_operand:V64I 0 "register_operand" "=r,b")
- (not:V64I (match_operand:V64I 1 "arith_operand" "rI,b")))]
+(define_insn "*one_cmpldi2_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (match_operand:DI 1 "arith_operand" "rI")))]
"TARGET_ARCH64"
- "@
- xnor\t%%g0, %1, %0
- fnot1\t%1, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,double")])
+ "xnor\t%%g0, %1, %0")
-(define_insn "one_cmpl<V32I:mode>2"
- [(set (match_operand:V32I 0 "register_operand" "=r,d")
- (not:V32I (match_operand:V32I 1 "arith_operand" "rI,d")))]
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
""
- "@
- xnor\t%%g0, %1, %0
- fnot1s\t%1, %0"
- [(set_attr "type" "*,fga")
- (set_attr "fptype" "*,single")])
+ "xnor\t%%g0, %1, %0")
(define_insn "*cmp_cc_not"
[(set (reg:CC CC_REG)
@@ -7878,89 +7711,235 @@
[(set_attr "type" "multi")
(set_attr "length" "4")])
-
;; Vector instructions.
-(define_insn "addv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=e")
- (plus:V2SI (match_operand:V2SI 1 "register_operand" "e")
- (match_operand:V2SI 2 "register_operand" "e")))]
+(define_mode_iterator VM32 [V1SI V2HI V4QI])
+(define_mode_iterator VM64 [V1DI V2SI V4HI V8QI])
+(define_mode_iterator VMALL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
+
+(define_mode_attr vbits [(V2SI "32") (V4HI "16") (V1SI "32s") (V2HI "16s")])
+(define_mode_attr vconstr [(V1SI "f") (V2HI "f") (V4QI "f")
+ (V1DI "e") (V2SI "e") (V4HI "e") (V8QI "e")])
+(define_mode_attr vfptype [(V1SI "single") (V2HI "single") (V4QI "single")
+ (V1DI "double") (V2SI "double") (V4HI "double")
+ (V8QI "double")])
+
+(define_expand "mov<VMALL:mode>"
+ [(set (match_operand:VMALL 0 "nonimmediate_operand" "")
+ (match_operand:VMALL 1 "general_operand" ""))]
"TARGET_VIS"
- "fpadd32\t%1, %2, %0"
- [(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+{
+ if (sparc_expand_move (<VMALL:MODE>mode, operands))
+ DONE;
+})
-(define_insn "addv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=e")
- (plus:V4HI (match_operand:V4HI 1 "register_operand" "e")
- (match_operand:V4HI 2 "register_operand" "e")))]
+(define_insn "*mov<VM32:mode>_insn"
+ [(set (match_operand:VM32 0 "nonimmediate_operand" "=f,f,f,f,m,m,*r, m,*r,*r, f")
+ (match_operand:VM32 1 "input_operand" "Y,Z,f,m,f,Y, m,*r,*r, f,*r"))]
+ "TARGET_VIS
+ && (register_operand (operands[0], <VM32:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM32:MODE>mode))"
+ "@
+ fzeros\t%0
+ fones\t%0
+ fsrc1s\t%1, %0
+ ld\t%1, %0
+ st\t%1, %0
+ st\t%r1, %0
+ ld\t%1, %0
+ st\t%1, %0
+ mov\t%1, %0
+ movstouw\t%1, %0
+ movwtos\t%1, %0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*,*")
+ (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,*,vis3,vis3")])
+
+(define_insn "*mov<VM64:mode>_insn_sp64"
+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,e,m,m,*r, m,*r, e,*r")
+ (match_operand:VM64 1 "input_operand" "Y,C,e,m,e,Y, m,*r, e,*r,*r"))]
+ "TARGET_VIS
+ && TARGET_ARCH64
+ && (register_operand (operands[0], <VM64:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM64:MODE>mode))"
+ "@
+ fzero\t%0
+ fone\t%0
+ fsrc1\t%1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ stx\t%r1, %0
+ ldx\t%1, %0
+ stx\t%1, %0
+ movdtox\t%1, %0
+ movxtod\t%1, %0
+ mov\t%1, %0"
+ [(set_attr "type" "fga,fga,fga,fpload,fpstore,store,load,store,*,*,*")
+ (set_attr "cpu_feature" "vis,vis,vis,*,*,*,*,*,vis3,vis3,*")])
+
+(define_insn "*mov<VM64:mode>_insn_sp32"
+ [(set (match_operand:VM64 0 "nonimmediate_operand" "=e,e,e,*r, f,e,m,m,U,T, o,*r")
+ (match_operand:VM64 1 "input_operand" "Y,C,e, f,*r,m,e,Y,T,U,*r,*r"))]
+ "TARGET_VIS
+ && ! TARGET_ARCH64
+ && (register_operand (operands[0], <VM64:MODE>mode)
+ || register_or_zero_or_all_ones_operand (operands[1], <VM64:MODE>mode))"
+ "@
+ fzero\t%0
+ fone\t%0
+ fsrc1\t%1, %0
+ #
+ #
+ ldd\t%1, %0
+ std\t%1, %0
+ stx\t%r1, %0
+ ldd\t%1, %0
+ std\t%1, %0
+ #
+ #"
+ [(set_attr "type" "fga,fga,fga,*,*,fpload,fpstore,store,load,store,*,*")
+ (set_attr "length" "*,*,*,2,2,*,*,*,*,*,2,2")
+ (set_attr "cpu_feature" "vis,vis,vis,vis3,vis3,*,*,*,*,*,*,*")])
+
+(define_split
+ [(set (match_operand:VM64 0 "memory_operand" "")
+ (match_operand:VM64 1 "register_operand" ""))]
+ "reload_completed
+ && TARGET_VIS
+ && ! TARGET_ARCH64
+ && (((REGNO (operands[1]) % 2) != 0)
+ || ! mem_min_alignment (operands[0], 8))
+ && offsettable_memref_p (operands[0])"
+ [(clobber (const_int 0))]
+{
+ rtx word0, word1;
+
+ word0 = adjust_address (operands[0], SImode, 0);
+ word1 = adjust_address (operands[0], SImode, 4);
+
+ emit_move_insn_1 (word0, gen_highpart (SImode, operands[1]));
+ emit_move_insn_1 (word1, gen_lowpart (SImode, operands[1]));
+ DONE;
+})
+
+(define_split
+ [(set (match_operand:VM64 0 "register_operand" "")
+ (match_operand:VM64 1 "register_operand" ""))]
+ "reload_completed
+ && TARGET_VIS
+ && ! TARGET_ARCH64
+ && sparc_split_regreg_legitimate (operands[0], operands[1])"
+ [(clobber (const_int 0))]
+{
+ rtx set_dest = operands[0];
+ rtx set_src = operands[1];
+ rtx dest1, dest2;
+ rtx src1, src2;
+
+ dest1 = gen_highpart (SImode, set_dest);
+ dest2 = gen_lowpart (SImode, set_dest);
+ src1 = gen_highpart (SImode, set_src);
+ src2 = gen_lowpart (SImode, set_src);
+
+ /* Now emit using the real source and destination we found, swapping
+ the order if we detect overlap. */
+ if (reg_overlap_mentioned_p (dest1, src2))
+ {
+ emit_insn (gen_movsi (dest2, src2));
+ emit_insn (gen_movsi (dest1, src1));
+ }
+ else
+ {
+ emit_insn (gen_movsi (dest1, src1));
+ emit_insn (gen_movsi (dest2, src2));
+ }
+ DONE;
+})
+
+(define_expand "vec_init<mode>"
+ [(match_operand:VMALL 0 "register_operand" "")
+ (match_operand:VMALL 1 "" "")]
"TARGET_VIS"
- "fpadd16\t%1, %2, %0"
- [(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+{
+ sparc_expand_vector_init (operands[0], operands[1]);
+ DONE;
+})
-;; fpadd32s is emitted by the addsi3 pattern.
+(define_code_iterator plusminus [plus minus])
+(define_code_attr plusminus_insn [(plus "add") (minus "sub")])
-(define_insn "addv2hi3"
- [(set (match_operand:V2HI 0 "register_operand" "=f")
- (plus:V2HI (match_operand:V2HI 1 "register_operand" "f")
- (match_operand:V2HI 2 "register_operand" "f")))]
+(define_mode_iterator VADDSUB [V1SI V2SI V2HI V4HI])
+
+(define_insn "<plusminus_insn><mode>3"
+ [(set (match_operand:VADDSUB 0 "register_operand" "=<vconstr>")
+ (plusminus:VADDSUB (match_operand:VADDSUB 1 "register_operand" "<vconstr>")
+ (match_operand:VADDSUB 2 "register_operand" "<vconstr>")))]
"TARGET_VIS"
- "fpadd16s\t%1, %2, %0"
+ "fp<plusminus_insn><vbits>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "single")])
-
-(define_insn "subv2si3"
- [(set (match_operand:V2SI 0 "register_operand" "=e")
- (minus:V2SI (match_operand:V2SI 1 "register_operand" "e")
- (match_operand:V2SI 2 "register_operand" "e")))]
+ (set_attr "fptype" "<vfptype>")])
+
+(define_mode_iterator VL [V1SI V2HI V4QI V1DI V2SI V4HI V8QI])
+(define_mode_attr vlsuf [(V1SI "s") (V2HI "s") (V4QI "s")
+ (V1DI "") (V2SI "") (V4HI "") (V8QI "")])
+(define_code_iterator vlop [ior and xor])
+(define_code_attr vlinsn [(ior "or") (and "and") (xor "xor")])
+(define_code_attr vlninsn [(ior "nor") (and "nand") (xor "xnor")])
+
+(define_insn "<code><mode>3"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (match_operand:VL 2 "register_operand" "<vconstr>")))]
"TARGET_VIS"
- "fpsub32\t%1, %2, %0"
+ "f<vlinsn><vlsuf>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "<vfptype>")])
-(define_insn "subv4hi3"
- [(set (match_operand:V4HI 0 "register_operand" "=e")
- (minus:V4HI (match_operand:V4HI 1 "register_operand" "e")
- (match_operand:V4HI 2 "register_operand" "e")))]
+(define_insn "*not_<code><mode>3"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (not:VL (vlop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (match_operand:VL 2 "register_operand" "<vconstr>"))))]
"TARGET_VIS"
- "fpsub16\t%1, %2, %0"
+ "f<vlninsn><vlsuf>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "<vfptype>")])
-;; fpsub32s is emitted by the subsi3 pattern.
-
-(define_insn "subv2hi3"
- [(set (match_operand:V2HI 0 "register_operand" "=f")
- (minus:V2HI (match_operand:V2HI 1 "register_operand" "f")
- (match_operand:V2HI 2 "register_operand" "f")))]
+;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
+(define_insn "*nand<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (ior:VL (not:VL (match_operand:VL 1 "register_operand" "<vconstr>"))
+ (not:VL (match_operand:VL 2 "register_operand" "<vconstr>"))))]
"TARGET_VIS"
- "fpsub16s\t%1, %2, %0"
+ "fnand<vlsuf>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "single")])
+ (set_attr "fptype" "<vfptype>")])
-;; All other logical instructions have integer equivalents so they
-;; are defined together.
+(define_code_iterator vlnotop [ior and])
-;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
+(define_insn "*<code>_not1<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlnotop:VL (not:VL (match_operand:VL 1 "register_operand" "<vconstr>"))
+ (match_operand:VL 2 "register_operand" "<vconstr>")))]
+ "TARGET_VIS"
+ "f<vlinsn>not1<vlsuf>\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "<vfptype>")])
-(define_insn "*nand<V64:mode>_vis"
- [(set (match_operand:V64 0 "register_operand" "=e")
- (ior:V64 (not:V64 (match_operand:V64 1 "register_operand" "e"))
- (not:V64 (match_operand:V64 2 "register_operand" "e"))))]
+(define_insn "*<code>_not2<mode>_vis"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (vlnotop:VL (match_operand:VL 1 "register_operand" "<vconstr>")
+ (not:VL (match_operand:VL 2 "register_operand" "<vconstr>"))))]
"TARGET_VIS"
- "fnand\t%1, %2, %0"
+ "f<vlinsn>not2<vlsuf>\t%1, %2, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "<vfptype>")])
-(define_insn "*nand<V32:mode>_vis"
- [(set (match_operand:V32 0 "register_operand" "=f")
- (ior:V32 (not:V32 (match_operand:V32 1 "register_operand" "f"))
- (not:V32 (match_operand:V32 2 "register_operand" "f"))))]
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:VL 0 "register_operand" "=<vconstr>")
+ (not:VL (match_operand:VL 1 "register_operand" "<vconstr>")))]
"TARGET_VIS"
- "fnands\t%1, %2, %0"
+ "fnot1<vlsuf>\t%1, %0"
[(set_attr "type" "fga")
- (set_attr "fptype" "single")])
+ (set_attr "fptype" "<vfptype>")])
;; Hard to generate VIS instructions. We have builtins for these.
@@ -8004,36 +7983,64 @@
[(set_attr "type" "fga")
(set_attr "fptype" "double")])
-;; It may be possible to describe this operation as (1 indexed):
-;; (vec_select (vec_duplicate (vec_duplicate (vec_concat 1 2)))
-;; 1,5,10,14,19,23,28,32)
-;; Note that (vec_merge:V8QI [(V4QI) (V4QI)] (10101010 = 170) doesn't work
-;; because vec_merge expects all the operands to be of the same type.
(define_insn "fpmerge_vis"
[(set (match_operand:V8QI 0 "register_operand" "=e")
- (unspec:V8QI [(match_operand:V4QI 1 "register_operand" "f")
- (match_operand:V4QI 2 "register_operand" "f")]
- UNSPEC_FPMERGE))]
+ (vec_select:V8QI
+ (vec_concat:V8QI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4QI 2 "register_operand" "f"))
+ (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)])))]
"TARGET_VIS"
"fpmerge\t%1, %2, %0"
[(set_attr "type" "fga")
(set_attr "fptype" "double")])
+(define_insn "vec_interleave_lowv8qi"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (vec_select:V8QI
+ (vec_concat:V16QI (match_operand:V8QI 1 "register_operand" "f")
+ (match_operand:V8QI 2 "register_operand" "f"))
+ (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)])))]
+ "TARGET_VIS"
+ "fpmerge\t%L1, %L2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "vec_interleave_highv8qi"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (vec_select:V8QI
+ (vec_concat:V16QI (match_operand:V8QI 1 "register_operand" "f")
+ (match_operand:V8QI 2 "register_operand" "f"))
+ (parallel [(const_int 4) (const_int 12)
+ (const_int 5) (const_int 13)
+ (const_int 6) (const_int 14)
+ (const_int 7) (const_int 15)])))]
+ "TARGET_VIS"
+ "fpmerge\t%H1, %H2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
;; Partitioned multiply instructions
(define_insn "fmul8x16_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
- (mult:V4HI (match_operand:V4QI 1 "register_operand" "f")
- (match_operand:V4HI 2 "register_operand" "e")))]
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8))]
"TARGET_VIS"
"fmul8x16\t%1, %2, %0"
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
-;; Only one of the following two insns can be a multiply.
(define_insn "fmul8x16au_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
- (mult:V4HI (match_operand:V4QI 1 "register_operand" "f")
- (match_operand:V2HI 2 "register_operand" "f")))]
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MUL16AU))]
"TARGET_VIS"
"fmul8x16au\t%1, %2, %0"
[(set_attr "type" "fpmul")
@@ -8049,11 +8056,11 @@
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
-;; Only one of the following two insns can be a multiply.
(define_insn "fmul8sux16_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
- (mult:V4HI (match_operand:V8QI 1 "register_operand" "e")
- (match_operand:V4HI 2 "register_operand" "e")))]
+ (unspec:V4HI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8SU))]
"TARGET_VIS"
"fmul8sux16\t%1, %2, %0"
[(set_attr "type" "fpmul")
@@ -8069,11 +8076,11 @@
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
-;; Only one of the following two insns can be a multiply.
(define_insn "fmuld8sux16_vis"
[(set (match_operand:V2SI 0 "register_operand" "=e")
- (mult:V2SI (match_operand:V4QI 1 "register_operand" "f")
- (match_operand:V2HI 2 "register_operand" "f")))]
+ (unspec:V2SI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MULDSU))]
"TARGET_VIS"
"fmuld8sux16\t%1, %2, %0"
[(set_attr "type" "fpmul")
@@ -8149,10 +8156,10 @@
;; Using faligndata only makes sense after an alignaddr since the choice of
;; bytes to take out of each operand is dependent on the results of the last
;; alignaddr.
-(define_insn "faligndata<V64I:mode>_vis"
- [(set (match_operand:V64I 0 "register_operand" "=e")
- (unspec:V64I [(match_operand:V64I 1 "register_operand" "e")
- (match_operand:V64I 2 "register_operand" "e")
+(define_insn "faligndata<VM64:mode>_vis"
+ [(set (match_operand:VM64 0 "register_operand" "=e")
+ (unspec:VM64 [(match_operand:VM64 1 "register_operand" "e")
+ (match_operand:VM64 2 "register_operand" "e")
(reg:DI GSR_REG)]
UNSPEC_ALIGNDATA))]
"TARGET_VIS"
@@ -8213,8 +8220,8 @@
;; with the same operands.
(define_insn "edge8<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE8))]
@@ -8224,8 +8231,8 @@
(define_insn "edge8l<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE8L))]
@@ -8235,8 +8242,8 @@
(define_insn "edge16<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE16))]
@@ -8246,8 +8253,8 @@
(define_insn "edge16l<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE16L))]
@@ -8257,8 +8264,8 @@
(define_insn "edge32<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE32))]
@@ -8268,8 +8275,8 @@
(define_insn "edge32l<P:mode>_vis"
[(set (reg:CC_NOOV CC_REG)
- (compare:CC_NOOV (minus:P (match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ"))
+ (compare:CC_NOOV (minus:P (match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ"))
(const_int 0)))
(set (match_operand:P 0 "register_operand" "=r")
(unspec:P [(match_dup 1) (match_dup 2)] UNSPEC_EDGE32L))]
@@ -8291,10 +8298,40 @@
[(set_attr "type" "fpmul")
(set_attr "fptype" "double")])
+(define_expand "vcond<mode><mode>"
+ [(match_operand:GCM 0 "register_operand" "")
+ (match_operand:GCM 1 "register_operand" "")
+ (match_operand:GCM 2 "register_operand" "")
+ (match_operator 3 ""
+ [(match_operand:GCM 4 "register_operand" "")
+ (match_operand:GCM 5 "register_operand" "")])]
+ "TARGET_VIS3"
+{
+ sparc_expand_vcond (<MODE>mode, operands,
+ UNSPEC_CMASK<gcm_name>,
+ UNSPEC_FCMP);
+ DONE;
+})
+
+(define_expand "vconduv8qiv8qi"
+ [(match_operand:V8QI 0 "register_operand" "")
+ (match_operand:V8QI 1 "register_operand" "")
+ (match_operand:V8QI 2 "register_operand" "")
+ (match_operator 3 ""
+ [(match_operand:V8QI 4 "register_operand" "")
+ (match_operand:V8QI 5 "register_operand" "")])]
+ "TARGET_VIS3"
+{
+ sparc_expand_vcond (V8QImode, operands,
+ UNSPEC_CMASK8,
+ UNSPEC_FUCMP);
+ DONE;
+})
+
(define_insn "array8<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_ARRAY8))]
"TARGET_VIS"
"array8\t%r1, %r2, %0"
@@ -8302,8 +8339,8 @@
(define_insn "array16<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_ARRAY16))]
"TARGET_VIS"
"array16\t%r1, %r2, %0"
@@ -8311,8 +8348,8 @@
(define_insn "array32<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_ARRAY32))]
"TARGET_VIS"
"array32\t%r1, %r2, %0"
@@ -8320,8 +8357,8 @@
(define_insn "bmaskdi_vis"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "register_operand" "rJ")
- (match_operand:DI 2 "register_operand" "rJ")))
+ (plus:DI (match_operand:DI 1 "register_or_zero_operand" "rJ")
+ (match_operand:DI 2 "register_or_zero_operand" "rJ")))
(set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
(plus:DI (match_dup 1) (match_dup 2)))]
"TARGET_VIS2"
@@ -8330,18 +8367,18 @@
(define_insn "bmasksi_vis"
[(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_operand:SI 1 "register_operand" "rJ")
- (match_operand:SI 2 "register_operand" "rJ")))
+ (plus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "register_or_zero_operand" "rJ")))
(set (zero_extract:DI (reg:DI GSR_REG) (const_int 32) (const_int 32))
(zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
"TARGET_VIS2"
"bmask\t%r1, %r2, %0"
[(set_attr "type" "array")])
-(define_insn "bshuffle<V64I:mode>_vis"
- [(set (match_operand:V64I 0 "register_operand" "=e")
- (unspec:V64I [(match_operand:V64I 1 "register_operand" "e")
- (match_operand:V64I 2 "register_operand" "e")
+(define_insn "bshuffle<VM64:mode>_vis"
+ [(set (match_operand:VM64 0 "register_operand" "=e")
+ (unspec:VM64 [(match_operand:VM64 1 "register_operand" "e")
+ (match_operand:VM64 2 "register_operand" "e")
(reg:DI GSR_REG)]
UNSPEC_BSHUFFLE))]
"TARGET_VIS2"
@@ -8349,11 +8386,48 @@
[(set_attr "type" "fga")
(set_attr "fptype" "double")])
+;; The rtl expanders will happily convert constant permutations on other
+;; modes down to V8QI. Rely on this to avoid the complexity of the byte
+;; order of the permutation.
+(define_expand "vec_perm_constv8qi"
+ [(match_operand:V8QI 0 "register_operand" "")
+ (match_operand:V8QI 1 "register_operand" "")
+ (match_operand:V8QI 2 "register_operand" "")
+ (match_operand:V8QI 3 "" "")]
+ "TARGET_VIS2"
+{
+ unsigned int i, mask;
+ rtx sel = operands[3];
+
+ for (i = mask = 0; i < 8; ++i)
+ mask |= (INTVAL (XVECEXP (sel, 0, i)) & 0xf) << (28 - i*4);
+ sel = force_reg (SImode, gen_int_mode (mask, SImode));
+
+ emit_insn (gen_bmasksi_vis (gen_reg_rtx (SImode), sel, const0_rtx));
+ emit_insn (gen_bshufflev8qi_vis (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+;; Unlike constant permutation, we can vastly simplify the compression of
+;; the 64-bit selector input to the 32-bit %gsr value by knowing what the
+;; width of the input is.
+(define_expand "vec_perm<mode>"
+ [(match_operand:VM64 0 "register_operand" "")
+ (match_operand:VM64 1 "register_operand" "")
+ (match_operand:VM64 2 "register_operand" "")
+ (match_operand:VM64 3 "register_operand" "")]
+ "TARGET_VIS2"
+{
+ sparc_expand_vec_perm_bmask (<MODE>mode, operands[3]);
+ emit_insn (gen_bshuffle<mode>_vis (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
;; VIS 2.0 adds edge variants which do not set the condition codes
(define_insn "edge8n<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE8N))]
"TARGET_VIS2"
"edge8n\t%r1, %r2, %0"
@@ -8361,8 +8435,8 @@
(define_insn "edge8ln<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE8LN))]
"TARGET_VIS2"
"edge8ln\t%r1, %r2, %0"
@@ -8370,8 +8444,8 @@
(define_insn "edge16n<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE16N))]
"TARGET_VIS2"
"edge16n\t%r1, %r2, %0"
@@ -8379,8 +8453,8 @@
(define_insn "edge16ln<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE16LN))]
"TARGET_VIS2"
"edge16ln\t%r1, %r2, %0"
@@ -8388,8 +8462,8 @@
(define_insn "edge32n<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE32N))]
"TARGET_VIS2"
"edge32n\t%r1, %r2, %0"
@@ -8397,8 +8471,8 @@
(define_insn "edge32ln<P:mode>_vis"
[(set (match_operand:P 0 "register_operand" "=r")
- (unspec:P [(match_operand:P 1 "register_operand" "rJ")
- (match_operand:P 2 "register_operand" "rJ")]
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
UNSPEC_EDGE32LN))]
"TARGET_VIS2"
"edge32ln\t%r1, %r2, %0"
@@ -8407,7 +8481,7 @@
;; Conditional moves are possible via fcmpX --> cmaskX -> bshuffle
(define_insn "cmask8<P:mode>_vis"
[(set (reg:DI GSR_REG)
- (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
(reg:DI GSR_REG)]
UNSPEC_CMASK8))]
"TARGET_VIS3"
@@ -8415,7 +8489,7 @@
(define_insn "cmask16<P:mode>_vis"
[(set (reg:DI GSR_REG)
- (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
(reg:DI GSR_REG)]
UNSPEC_CMASK16))]
"TARGET_VIS3"
@@ -8423,7 +8497,7 @@
(define_insn "cmask32<P:mode>_vis"
[(set (reg:DI GSR_REG)
- (unspec:DI [(match_operand:P 0 "register_operand" "r")
+ (unspec:DI [(match_operand:P 0 "register_or_zero_operand" "rJ")
(reg:DI GSR_REG)]
UNSPEC_CMASK32))]
"TARGET_VIS3"
@@ -8440,11 +8514,13 @@
(define_code_iterator vis3_shift [ashift ss_ashift lshiftrt ashiftrt])
(define_code_attr vis3_shift_insn
[(ashift "fsll") (ss_ashift "fslas") (lshiftrt "fsrl") (ashiftrt "fsra")])
+(define_code_attr vis3_shift_patname
+ [(ashift "ashl") (ss_ashift "ssashl") (lshiftrt "lshr") (ashiftrt "ashr")])
-(define_insn "<vis3_shift_insn><vbits>_vis"
- [(set (match_operand:V64N8 0 "register_operand" "=<vconstr>")
- (vis3_shift:V64N8 (match_operand:V64N8 1 "register_operand" "<vconstr>")
- (match_operand:V64N8 2 "register_operand" "<vconstr>")))]
+(define_insn "v<vis3_shift_patname><mode>3"
+ [(set (match_operand:GCM 0 "register_operand" "=<vconstr>")
+ (vis3_shift:GCM (match_operand:GCM 1 "register_operand" "<vconstr>")
+ (match_operand:GCM 2 "register_operand" "<vconstr>")))]
"TARGET_VIS3"
"<vis3_shift_insn><vbits>\t%1, %2, %0")
@@ -8472,26 +8548,21 @@
"TARGET_VIS3"
"fmean16\t%1, %2, %0")
-(define_insn "fpadd64_vis"
- [(set (match_operand:DI 0 "register_operand" "=e")
- (plus:DI (match_operand:DI 1 "register_operand" "e")
- (match_operand:DI 2 "register_operand" "e")))]
- "TARGET_VIS3"
- "fpadd64\t%1, %2, %0")
-
-(define_insn "fpsub64_vis"
- [(set (match_operand:DI 0 "register_operand" "=e")
- (minus:DI (match_operand:DI 1 "register_operand" "e")
- (match_operand:DI 2 "register_operand" "e")))]
+(define_insn "fp<plusminus_insn>64_vis"
+ [(set (match_operand:V1DI 0 "register_operand" "=e")
+ (plusminus:V1DI (match_operand:V1DI 1 "register_operand" "e")
+ (match_operand:V1DI 2 "register_operand" "e")))]
"TARGET_VIS3"
- "fpsub64\t%1, %2, %0")
+ "fp<plusminus_insn>64\t%1, %2, %0")
-(define_mode_iterator VASS [V4HI V2SI V2HI SI])
+(define_mode_iterator VASS [V4HI V2SI V2HI V1SI])
(define_code_iterator vis3_addsub_ss [ss_plus ss_minus])
(define_code_attr vis3_addsub_ss_insn
[(ss_plus "fpadds") (ss_minus "fpsubs")])
+(define_code_attr vis3_addsub_ss_patname
+ [(ss_plus "ssadd") (ss_minus "sssub")])
-(define_insn "<vis3_addsub_ss_insn><vbits>_vis"
+(define_insn "<vis3_addsub_ss_patname><mode>3"
[(set (match_operand:VASS 0 "register_operand" "=<vconstr>")
(vis3_addsub_ss:VASS (match_operand:VASS 1 "register_operand" "<vconstr>")
(match_operand:VASS 2 "register_operand" "<vconstr>")))]
diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt
index 131db4277d9..cb807fdad65 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -21,6 +21,10 @@
HeaderInclude
config/sparc/sparc-opts.h
+;; Debug flags
+TargetVariable
+unsigned int sparc_debug
+
mfpu
Target Report Mask(FPU)
Use hardware FP
@@ -180,12 +184,18 @@ mcmodel=
Target RejectNegative Joined Var(sparc_cmodel_string)
Use given SPARC-V9 code model
+mdebug=
+Target RejectNegative Joined Var(sparc_debug_string)
+Enable debug output
+
mstd-struct-return
Target Report RejectNegative Var(sparc_std_struct_return)
Enable strict 32-bit psABI struct return checking.
-Mask(LITTLE_ENDIAN)
-;; Generate code for little-endian
+mfix-at697f
+Target Report RejectNegative Var(sparc_fix_at697f)
+Enable workaround for single erratum of AT697F processor
+(corresponding to erratum #13 of AT697E processor)
Mask(LONG_DOUBLE_128)
;; Use 128-bit long double
diff --git a/gcc/config/sparc/t-elf b/gcc/config/sparc/t-elf
index 7073bcb7721..e9acfe3693e 100644
--- a/gcc/config/sparc/t-elf
+++ b/gcc/config/sparc/t-elf
@@ -17,12 +17,6 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = sparc/lb1spc.asm
-LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
-
MULTILIB_OPTIONS = msoft-float mcpu=v8 mflat
MULTILIB_DIRNAMES = soft v8 flat
MULTILIB_MATCHES = msoft-float=mno-fpu
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/sparc/t-leon b/gcc/config/sparc/t-leon
index 4f9d0a9e797..25fc61136a9 100644
--- a/gcc/config/sparc/t-leon
+++ b/gcc/config/sparc/t-leon
@@ -16,15 +16,9 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = sparc/lb1spc.asm
-LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
-
# Multilibs for LEON
# LEON is a SPARC-V8, but the AT697 implementation has a bug in the
# V8-specific instructions.
MULTILIB_OPTIONS = mcpu=v7 msoft-float mflat
MULTILIB_DIRNAMES = v7 soft flat
MULTILIB_MATCHES = mcpu?v7=mv7 msoft-float=mno-fpu
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/sparc/t-leon3 b/gcc/config/sparc/t-leon3
index 0e7e45cc594..acdd1f2c67b 100644
--- a/gcc/config/sparc/t-leon3
+++ b/gcc/config/sparc/t-leon3
@@ -20,6 +20,3 @@
MULTILIB_OPTIONS = msoft-float
MULTILIB_DIRNAMES = soft
MULTILIB_MATCHES = msoft-float=mno-fpu
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/sparc/t-linux b/gcc/config/sparc/t-linux
deleted file mode 100644
index 30daa376614..00000000000
--- a/gcc/config/sparc/t-linux
+++ /dev/null
@@ -1,5 +0,0 @@
-# Override t-slibgcc-elf-ver to export some libgcc symbols with
-# the symbol versions that glibc used.
-# Avoid the t-linux version file.
-SHLIB_MAPFILES = $$(libgcc_objdir)/libgcc-std.ver \
- $(srcdir)/config/sparc/libgcc-sparc-glibc.ver
diff --git a/gcc/config/sparc/t-linux64 b/gcc/config/sparc/t-linux64
index 74d04898d9f..d9dfad66ce7 100644
--- a/gcc/config/sparc/t-linux64
+++ b/gcc/config/sparc/t-linux64
@@ -1,5 +1,5 @@
# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004,
-# 2006, 2010 Free Software Foundation, Inc.
+# 2006, 2010, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -27,10 +27,3 @@
MULTILIB_OPTIONS = m64/m32
MULTILIB_DIRNAMES = 64 32
MULTILIB_OSDIRNAMES = ../lib64 $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-CRTSTUFF_T_CFLAGS = `if test x$$($(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) \
- -print-multi-os-directory) \
- = x../lib64; then echo -mcmodel=medany; fi`
diff --git a/gcc/config/sparc/t-netbsd64 b/gcc/config/sparc/t-netbsd64
index 0fddb0ffe87..bc783c19366 100644
--- a/gcc/config/sparc/t-netbsd64
+++ b/gcc/config/sparc/t-netbsd64
@@ -1,8 +1,5 @@
-# Disable multilib fow now, as NetBSD/sparc64 does not ship with
+# Disable multilib for now, as NetBSD/sparc64 does not ship with
# a 32-bit environment.
#MULTILIB_OPTIONS = m32/m64
#MULTILIB_DIRNAMES = 32 64
#MULTILIB_MATCHES =
-
-#LIBGCC = stmp-multilib
-#INSTALL_LIBGCC = install-multilib
diff --git a/gcc/config/spu/divmodti4.c b/gcc/config/spu/divmodti4.c
deleted file mode 100644
index 57c975c6b3c..00000000000
--- a/gcc/config/spu/divmodti4.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/* Copyright (C) 2008, 2009 Free Software Foundation, Inc.
-
- This file is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3 of the License, or (at your option)
- any later version.
-
- This file is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
-
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
-
-#include <spu_intrinsics.h>
-
-typedef unsigned int UTItype __attribute__ ((mode (TI)));
-typedef int TItype __attribute__ ((mode (TI)));
-TItype __divti3 (TItype u, TItype v);
-TItype __modti3 (TItype u, TItype v);
-UTItype __udivti3 (UTItype u, UTItype v);
-UTItype __umodti3 (UTItype u, UTItype v);
-UTItype __udivmodti4 (UTItype u, UTItype v, UTItype *w);
-
-union qword_UTItype
- {
- qword q;
- UTItype t;
- };
-
-inline static qword
-si_from_UTItype (UTItype t)
-{
- union qword_UTItype u;
- u.t = t;
- return u.q;
-}
-
-inline static UTItype
-si_to_UTItype (qword q)
-{
- union qword_UTItype u;
- u.q = q;
- return u.t;
-}
-
-inline static unsigned int
-count_leading_zeros (UTItype x)
-{
- qword c = si_clz (*(qword *) & x);
- qword cmp0 = si_cgti (c, 31);
- qword cmp1 = si_and (cmp0, si_shlqbyi (cmp0, 4));
- qword cmp2 = si_and (cmp1, si_shlqbyi (cmp0, 8));
- qword s = si_a (c, si_and (cmp0, si_shlqbyi (c, 4)));
- s = si_a (s, si_and (cmp1, si_shlqbyi (c, 8)));
- s = si_a (s, si_and (cmp2, si_shlqbyi (c, 12)));
- return si_to_uint (s);
-}
-
-/* Based on implementation of udivmodsi4, which is essentially
- * an optimized version of gcc/config/udivmodsi4.c
- clz %7,%2
- clz %4,%1
- il %5,1
- fsmbi %0,0
- sf %7,%4,%7
- ori %3,%1,0
- shl %5,%5,%7
- shl %4,%2,%7
-1: or %8,%0,%5
- rotmi %5,%5,-1
- clgt %6,%4,%3
- sf %7,%4,%3
- rotmi %4,%4,-1
- selb %0,%8,%0,%6
- selb %3,%7,%3,%6
-3: brnz %5,1b
- */
-
-UTItype
-__udivmodti4 (UTItype num, UTItype den, UTItype * rp)
-{
- qword shift =
- si_from_uint (count_leading_zeros (den) - count_leading_zeros (num));
- qword n0 = si_from_UTItype (num);
- qword d0 = si_from_UTItype (den);
- qword bit = si_andi (si_fsmbi (1), 1);
- qword r0 = si_il (0);
- qword m1 = si_fsmbi (0x000f);
- qword mask, r1, n1;
-
- d0 = si_shlqbybi (si_shlqbi (d0, shift), shift);
- bit = si_shlqbybi (si_shlqbi (bit, shift), shift);
-
- do
- {
- r1 = si_or (r0, bit);
-
- // n1 = n0 - d0 in TImode
- n1 = si_bg (d0, n0);
- n1 = si_shlqbyi (n1, 4);
- n1 = si_sf (m1, n1);
- n1 = si_bgx (d0, n0, n1);
- n1 = si_shlqbyi (n1, 4);
- n1 = si_sf (m1, n1);
- n1 = si_bgx (d0, n0, n1);
- n1 = si_shlqbyi (n1, 4);
- n1 = si_sf (m1, n1);
- n1 = si_sfx (d0, n0, n1);
-
- mask = si_fsm (si_cgti (n1, -1));
- r0 = si_selb (r0, r1, mask);
- n0 = si_selb (n0, n1, mask);
- bit = si_rotqmbii (bit, -1);
- d0 = si_rotqmbii (d0, -1);
- }
- while (si_to_uint (si_orx (bit)));
- if (rp)
- *rp = si_to_UTItype (n0);
- return si_to_UTItype (r0);
-}
-
-UTItype
-__udivti3 (UTItype n, UTItype d)
-{
- return __udivmodti4 (n, d, (UTItype *)0);
-}
-
-UTItype
-__umodti3 (UTItype n, UTItype d)
-{
- UTItype w;
- __udivmodti4 (n, d, &w);
- return w;
-}
-
-TItype
-__divti3 (TItype n, TItype d)
-{
- int c = 0;
- TItype w;
-
- if (n < 0)
- {
- c = ~c;
- n = -n;
- }
- if (d < 0)
- {
- c = ~c;
- d = -d;
- }
-
- w = __udivmodti4 (n, d, (UTItype *)0);
- if (c)
- w = -w;
- return w;
-}
-
-TItype
-__modti3 (TItype n, TItype d)
-{
- int c = 0;
- TItype w;
-
- if (n < 0)
- {
- c = ~c;
- n = -n;
- }
- if (d < 0)
- {
- c = ~c;
- d = -d;
- }
-
- __udivmodti4 (n, d, (UTItype *) &w);
- if (c)
- w = -w;
- return w;
-}
diff --git a/gcc/config/spu/spu-elf.h b/gcc/config/spu/spu-elf.h
index 818c391f994..146bcb21052 100644
--- a/gcc/config/spu/spu-elf.h
+++ b/gcc/config/spu/spu-elf.h
@@ -35,10 +35,6 @@
#undef STANDARD_STARTFILE_PREFIX_2
#define STANDARD_STARTFILE_PREFIX_2 ""
-/* Use "/include" instead of "/usr/include". */
-#undef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/include"
-
/* We do not provide any "/usr/local/include" directory on SPU. */
#undef LOCAL_INCLUDE_DIR
@@ -77,4 +73,3 @@
mcache-size=16 :-lgcc_cache16k; \
mcache-size=8 :-lgcc_cache8k; \
:-lgcc_cache64k}"
-
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 952aea50444..0bab5cfb692 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -218,7 +218,6 @@ static tree spu_builtin_mul_widen_odd (tree);
static tree spu_builtin_mask_for_load (void);
static int spu_builtin_vectorization_cost (enum vect_cost_for_stmt, tree, int);
static bool spu_vector_alignment_reachable (const_tree, bool);
-static tree spu_builtin_vec_perm (tree, tree *);
static enum machine_mode spu_addr_space_pointer_mode (addr_space_t);
static enum machine_mode spu_addr_space_address_mode (addr_space_t);
static bool spu_addr_space_subset_p (addr_space_t, addr_space_t);
@@ -449,9 +448,6 @@ static void spu_setup_incoming_varargs (cumulative_args_t cum,
#undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE
#define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE spu_vector_alignment_reachable
-#undef TARGET_VECTORIZE_BUILTIN_VEC_PERM
-#define TARGET_VECTORIZE_BUILTIN_VEC_PERM spu_builtin_vec_perm
-
#undef TARGET_LIBGCC_CMP_RETURN_MODE
#define TARGET_LIBGCC_CMP_RETURN_MODE spu_libgcc_cmp_return_mode
@@ -500,10 +496,27 @@ static void spu_setup_incoming_varargs (cumulative_args_t cum,
struct gcc_target targetm = TARGET_INITIALIZER;
+/* Define the structure for the machine field in struct function. */
+struct GTY(()) machine_function
+{
+ /* Register to use for PIC accesses. */
+ rtx pic_reg;
+};
+
+/* How to allocate a 'struct machine_function'. */
+static struct machine_function *
+spu_init_machine_status (void)
+{
+ return ggc_alloc_cleared_machine_function ();
+}
+
/* Implement TARGET_OPTION_OVERRIDE. */
static void
spu_option_override (void)
{
+ /* Set up function hooks. */
+ init_machine_status = spu_init_machine_status;
+
/* Small loops will be unpeeled at -O3. For SPU it is more important
to keep code small by default. */
if (!flag_unroll_loops && !flag_peel_loops)
@@ -1741,12 +1754,22 @@ print_operand (FILE * file, rtx x, int code)
static rtx
get_pic_reg (void)
{
- rtx pic_reg = pic_offset_table_rtx;
if (!reload_completed && !reload_in_progress)
abort ();
- if (current_function_is_leaf && !df_regs_ever_live_p (LAST_ARG_REGNUM))
- pic_reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM);
- return pic_reg;
+
+ /* If we've already made the decision, we need to keep with it. Once we've
+ decided to use LAST_ARG_REGNUM, future calls to df_regs_ever_live_p may
+ return true since the register is now live; this should not cause us to
+ "switch back" to using pic_offset_table_rtx. */
+ if (!cfun->machine->pic_reg)
+ {
+ if (current_function_is_leaf && !df_regs_ever_live_p (LAST_ARG_REGNUM))
+ cfun->machine->pic_reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM);
+ else
+ cfun->machine->pic_reg = pic_offset_table_rtx;
+ }
+
+ return cfun->machine->pic_reg;
}
/* Split constant addresses to handle cases that are too large.
@@ -1849,7 +1872,6 @@ spu_split_immediate (rtx * ops)
{
rtx pic_reg = get_pic_reg ();
emit_insn (gen_addsi3 (ops[0], ops[0], pic_reg));
- crtl->uses_pic_offset_table = 1;
}
return flag_pic || c == IC_IL2s;
}
@@ -1875,9 +1897,7 @@ need_to_save_reg (int regno, int saving)
return 1;
if (flag_pic
&& regno == PIC_OFFSET_TABLE_REGNUM
- && (!saving || crtl->uses_pic_offset_table)
- && (!saving
- || !current_function_is_leaf || df_regs_ever_live_p (LAST_ARG_REGNUM)))
+ && (!saving || cfun->machine->pic_reg == pic_offset_table_rtx))
return 1;
return 0;
}
@@ -1991,8 +2011,8 @@ spu_expand_prologue (void)
rtx scratch_reg_0, scratch_reg_1;
rtx insn, real;
- if (flag_pic && optimize == 0)
- crtl->uses_pic_offset_table = 1;
+ if (flag_pic && optimize == 0 && !cfun->machine->pic_reg)
+ cfun->machine->pic_reg = pic_offset_table_rtx;
if (spu_naked_function_p (current_function_decl))
return;
@@ -2029,9 +2049,9 @@ spu_expand_prologue (void)
}
}
- if (flag_pic && crtl->uses_pic_offset_table)
+ if (flag_pic && cfun->machine->pic_reg)
{
- rtx pic_reg = get_pic_reg ();
+ rtx pic_reg = cfun->machine->pic_reg;
insn = emit_insn (gen_load_pic_offset (pic_reg, scratch_reg_0));
insn = emit_insn (gen_subsi3 (pic_reg, pic_reg, scratch_reg_0));
}
@@ -6391,13 +6411,24 @@ spu_emit_vector_compare (enum rtx_code rcode,
try_again = true;
break;
case NE:
+ case UNEQ:
+ case UNLE:
+ case UNLT:
+ case UNGE:
+ case UNGT:
+ case UNORDERED:
/* Treat A != B as ~(A==B). */
{
+ enum rtx_code rev_code;
enum insn_code nor_code;
- rtx eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode);
+ rtx rev_mask;
+
+ rev_code = reverse_condition_maybe_unordered (rcode);
+ rev_mask = spu_emit_vector_compare (rev_code, op0, op1, dest_mode);
+
nor_code = optab_handler (one_cmpl_optab, dest_mode);
gcc_assert (nor_code != CODE_FOR_nothing);
- emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
+ emit_insn (GEN_FCN (nor_code) (mask, rev_mask));
if (dmode != dest_mode)
{
rtx temp = gen_reg_rtx (dest_mode);
@@ -6442,6 +6473,48 @@ spu_emit_vector_compare (enum rtx_code rcode,
return mask;
}
break;
+ case LTGT:
+ /* Try LT OR GT */
+ {
+ rtx lt_rtx, gt_rtx;
+ enum insn_code ior_code;
+
+ lt_rtx = spu_emit_vector_compare (LT, op0, op1, dest_mode);
+ gt_rtx = spu_emit_vector_compare (GT, op0, op1, dest_mode);
+
+ ior_code = optab_handler (ior_optab, dest_mode);
+ gcc_assert (ior_code != CODE_FOR_nothing);
+ emit_insn (GEN_FCN (ior_code) (mask, lt_rtx, gt_rtx));
+ if (dmode != dest_mode)
+ {
+ rtx temp = gen_reg_rtx (dest_mode);
+ convert_move (temp, mask, 0);
+ return temp;
+ }
+ return mask;
+ }
+ break;
+ case ORDERED:
+ /* Implement as (A==A) & (B==B) */
+ {
+ rtx a_rtx, b_rtx;
+ enum insn_code and_code;
+
+ a_rtx = spu_emit_vector_compare (EQ, op0, op0, dest_mode);
+ b_rtx = spu_emit_vector_compare (EQ, op1, op1, dest_mode);
+
+ and_code = optab_handler (and_optab, dest_mode);
+ gcc_assert (and_code != CODE_FOR_nothing);
+ emit_insn (GEN_FCN (and_code) (mask, a_rtx, b_rtx));
+ if (dmode != dest_mode)
+ {
+ rtx temp = gen_reg_rtx (dest_mode);
+ convert_move (temp, mask, 0);
+ return temp;
+ }
+ return mask;
+ }
+ break;
default:
gcc_unreachable ();
}
@@ -6881,49 +6954,6 @@ spu_vector_alignment_reachable (const_tree type ATTRIBUTE_UNUSED, bool is_packed
return true;
}
-/* Implement targetm.vectorize.builtin_vec_perm. */
-tree
-spu_builtin_vec_perm (tree type, tree *mask_element_type)
-{
- *mask_element_type = unsigned_char_type_node;
-
- switch (TYPE_MODE (type))
- {
- case V16QImode:
- if (TYPE_UNSIGNED (type))
- return spu_builtin_decls[SPU_SHUFFLE_0];
- else
- return spu_builtin_decls[SPU_SHUFFLE_1];
-
- case V8HImode:
- if (TYPE_UNSIGNED (type))
- return spu_builtin_decls[SPU_SHUFFLE_2];
- else
- return spu_builtin_decls[SPU_SHUFFLE_3];
-
- case V4SImode:
- if (TYPE_UNSIGNED (type))
- return spu_builtin_decls[SPU_SHUFFLE_4];
- else
- return spu_builtin_decls[SPU_SHUFFLE_5];
-
- case V2DImode:
- if (TYPE_UNSIGNED (type))
- return spu_builtin_decls[SPU_SHUFFLE_6];
- else
- return spu_builtin_decls[SPU_SHUFFLE_7];
-
- case V4SFmode:
- return spu_builtin_decls[SPU_SHUFFLE_8];
-
- case V2DFmode:
- return spu_builtin_decls[SPU_SHUFFLE_9];
-
- default:
- return NULL_TREE;
- }
-}
-
/* Return the appropriate mode for a named address pointer. */
static enum machine_mode
spu_addr_space_pointer_mode (addr_space_t addrspace)
diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md
index 676d54e8de0..3178a6df593 100644
--- a/gcc/config/spu/spu.md
+++ b/gcc/config/spu/spu.md
@@ -4395,6 +4395,24 @@ selb\t%0,%4,%0,%3"
"shufb\t%0,%1,%2,%3"
[(set_attr "type" "shuf")])
+; The semantics of vec_permv16qi are nearly identical to those of the SPU
+; shufb instruction, except that we need to reduce the selector modulo 32.
+(define_expand "vec_permv16qi"
+ [(set (match_dup 4) (and:V16QI (match_operand:V16QI 3 "spu_reg_operand" "")
+ (match_dup 6)))
+ (set (match_operand:V16QI 0 "spu_reg_operand" "")
+ (unspec:V16QI
+ [(match_operand:V16QI 1 "spu_reg_operand" "")
+ (match_operand:V16QI 2 "spu_reg_operand" "")
+ (match_dup 5)]
+ UNSPEC_SHUFB))]
+ ""
+ {
+ operands[4] = gen_reg_rtx (V16QImode);
+ operands[5] = gen_lowpart (TImode, operands[4]);
+ operands[6] = spu_const (V16QImode, 31);
+ })
+
(define_insn "nop"
[(unspec_volatile [(const_int 0)] UNSPECV_NOP)]
""
@@ -4929,439 +4947,6 @@ DONE;
})
-(define_expand "vec_extract_evenv4si"
- [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
- (vec_concat:V4SI
- (vec_select:V2SI
- (match_operand:V4SI 1 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 2)]))
- (vec_select:V2SI
- (match_operand:V4SI 2 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 2)]))))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x00, 0x01, 0x02, 0x03,
- 0x08, 0x09, 0x0A, 0x0B,
- 0x10, 0x11, 0x12, 0x13,
- 0x18, 0x19, 0x1A, 0x1B};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-
-(define_expand "vec_extract_evenv4sf"
- [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
- (vec_concat:V4SF
- (vec_select:V2SF
- (match_operand:V4SF 1 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 2)]))
- (vec_select:V2SF
- (match_operand:V4SF 2 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 2)]))))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x00, 0x01, 0x02, 0x03,
- 0x08, 0x09, 0x0A, 0x0B,
- 0x10, 0x11, 0x12, 0x13,
- 0x18, 0x19, 0x1A, 0x1B};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_extract_evenv8hi"
- [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
- (vec_concat:V8HI
- (vec_select:V4HI
- (match_operand:V8HI 1 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))
- (vec_select:V4HI
- (match_operand:V8HI 2 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)]))))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x00, 0x01, 0x04, 0x05,
- 0x08, 0x09, 0x0C, 0x0D,
- 0x10, 0x11, 0x14, 0x15,
- 0x18, 0x19, 0x1C, 0x1D};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_extract_evenv16qi"
- [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
- (vec_concat:V16QI
- (vec_select:V8QI
- (match_operand:V16QI 1 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)
- (const_int 8)(const_int 10)(const_int 12)(const_int 14)]))
- (vec_select:V8QI
- (match_operand:V16QI 2 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 2)(const_int 4)(const_int 6)
- (const_int 8)(const_int 10)(const_int 12)(const_int 14)]))))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x00, 0x02, 0x04, 0x06,
- 0x08, 0x0A, 0x0C, 0x0E,
- 0x10, 0x12, 0x14, 0x16,
- 0x18, 0x1A, 0x1C, 0x1E};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_extract_oddv4si"
- [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
- (vec_concat:V4SI
- (vec_select:V2SI
- (match_operand:V4SI 1 "spu_reg_operand" "r")
- (parallel [(const_int 1)(const_int 3)]))
- (vec_select:V2SI
- (match_operand:V4SI 2 "spu_reg_operand" "r")
- (parallel [(const_int 1)(const_int 3)]))))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x04, 0x05, 0x06, 0x07,
- 0x0C, 0x0D, 0x0E, 0x0F,
- 0x14, 0x15, 0x16, 0x17,
- 0x1C, 0x1D, 0x1E, 0x1F};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_extract_oddv4sf"
- [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
- (vec_concat:V4SF
- (vec_select:V2SF
- (match_operand:V4SF 1 "spu_reg_operand" "r")
- (parallel [(const_int 1)(const_int 3)]))
- (vec_select:V2SF
- (match_operand:V4SF 2 "spu_reg_operand" "r")
- (parallel [(const_int 1)(const_int 3)]))))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x04, 0x05, 0x06, 0x07,
- 0x0C, 0x0D, 0x0E, 0x0F,
- 0x14, 0x15, 0x16, 0x17,
- 0x1C, 0x1D, 0x1E, 0x1F};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_extract_oddv8hi"
- [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
- (vec_concat:V8HI
- (vec_select:V4HI
- (match_operand:V8HI 1 "spu_reg_operand" "r")
- (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))
- (vec_select:V4HI
- (match_operand:V8HI 2 "spu_reg_operand" "r")
- (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)]))))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x02, 0x03, 0x06, 0x07,
- 0x0A, 0x0B, 0x0E, 0x0F,
- 0x12, 0x13, 0x16, 0x17,
- 0x1A, 0x1B, 0x1E, 0x1F};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_extract_oddv16qi"
- [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
- (vec_concat:V16QI
- (vec_select:V8QI
- (match_operand:V16QI 1 "spu_reg_operand" "r")
- (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)
- (const_int 9)(const_int 11)(const_int 13)(const_int 15)]))
- (vec_select:V8QI
- (match_operand:V16QI 2 "spu_reg_operand" "r")
- (parallel [(const_int 1)(const_int 3)(const_int 5)(const_int 7)
- (const_int 9)(const_int 11)(const_int 13)(const_int 15)]))))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x01, 0x03, 0x05, 0x07,
- 0x09, 0x0B, 0x0D, 0x0F,
- 0x11, 0x13, 0x15, 0x17,
- 0x19, 0x1B, 0x1D, 0x1F};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_interleave_highv4sf"
- [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
- (vec_select:V4SF
- (vec_concat:V4SF
- (vec_select:V2SF
- (match_operand:V4SF 1 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 1)]))
- (vec_select:V2SF
- (match_operand:V4SF 2 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 1)])))
- (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x00, 0x01, 0x02, 0x03,
- 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07,
- 0x14, 0x15, 0x16, 0x17};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_interleave_lowv4sf"
- [(set (match_operand:V4SF 0 "spu_reg_operand" "=r")
- (vec_select:V4SF
- (vec_concat:V4SF
- (vec_select:V2SF
- (match_operand:V4SF 1 "spu_reg_operand" "r")
- (parallel [(const_int 2)(const_int 3)]))
- (vec_select:V2SF
- (match_operand:V4SF 2 "spu_reg_operand" "r")
- (parallel [(const_int 2)(const_int 3)])))
- (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x08, 0x09, 0x0A, 0x0B,
- 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F,
- 0x1C, 0x1D, 0x1E, 0x1F};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_interleave_highv4si"
- [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
- (vec_select:V4SI
- (vec_concat:V4SI
- (vec_select:V2SI
- (match_operand:V4SI 1 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 1)]))
- (vec_select:V2SI
- (match_operand:V4SI 2 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 1)])))
- (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x00, 0x01, 0x02, 0x03,
- 0x10, 0x11, 0x12, 0x13,
- 0x04, 0x05, 0x06, 0x07,
- 0x14, 0x15, 0x16, 0x17};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_interleave_lowv4si"
- [(set (match_operand:V4SI 0 "spu_reg_operand" "=r")
- (vec_select:V4SI
- (vec_concat:V4SI
- (vec_select:V2SI
- (match_operand:V4SI 1 "spu_reg_operand" "r")
- (parallel [(const_int 2)(const_int 3)]))
- (vec_select:V2SI
- (match_operand:V4SI 2 "spu_reg_operand" "r")
- (parallel [(const_int 2)(const_int 3)])))
- (parallel [(const_int 0)(const_int 2)(const_int 1)(const_int 3)])))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x08, 0x09, 0x0A, 0x0B,
- 0x18, 0x19, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x0E, 0x0F,
- 0x1C, 0x1D, 0x1E, 0x1F};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_interleave_highv8hi"
- [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
- (vec_select:V8HI
- (vec_concat:V8HI
- (vec_select:V4HI
- (match_operand:V8HI 1 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)]))
- (vec_select:V4HI
- (match_operand:V8HI 2 "spu_reg_operand" "r")
- (parallel [(const_int 0)(const_int 1)(const_int 2)(const_int 3)])))
- (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)])))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x00, 0x01, 0x10, 0x11,
- 0x02, 0x03, 0x12, 0x13,
- 0x04, 0x05, 0x14, 0x15,
- 0x06, 0x07, 0x16, 0x17};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
- }")
-
-(define_expand "vec_interleave_lowv8hi"
- [(set (match_operand:V8HI 0 "spu_reg_operand" "=r")
- (vec_select:V8HI
- (vec_concat:V8HI
- (vec_select:V4HI
- (match_operand:V8HI 1 "spu_reg_operand" "r")
- (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)]))
- (vec_select:V4HI
- (match_operand:V8HI 2 "spu_reg_operand" "r")
- (parallel [(const_int 4)(const_int 5)(const_int 6)(const_int 7)])))
- (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)])))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x08, 0x09, 0x18, 0x19,
- 0x0A, 0x0B, 0x1A, 0x1B,
- 0x0C, 0x0D, 0x1C, 0x1D,
- 0x0E, 0x0F, 0x1E, 0x1F};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_interleave_highv16qi"
- [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
- (vec_select:V16QI
- (vec_concat:V16QI
- (vec_select:V8QI
- (match_operand:V16QI 1 "spu_reg_operand" "r")
- (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)]))
- (vec_select:V8QI
- (match_operand:V16QI 2 "spu_reg_operand" "r")
- (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)])))
- (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)])))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x00, 0x10, 0x01, 0x11,
- 0x02, 0x12, 0x03, 0x13,
- 0x04, 0x14, 0x05, 0x15,
- 0x06, 0x16, 0x07, 0x17};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
-(define_expand "vec_interleave_lowv16qi"
- [(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
- (vec_select:V16QI
- (vec_concat:V16QI
- (vec_select:V8QI
- (match_operand:V16QI 1 "spu_reg_operand" "r")
- (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)]))
- (vec_select:V8QI
- (match_operand:V16QI 2 "spu_reg_operand" "r")
- (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)])))
- (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)])))]
-
- ""
- "
-{
- rtx mask = gen_reg_rtx (TImode);
- unsigned char arr[16] = {
- 0x08, 0x18, 0x09, 0x19,
- 0x0A, 0x1A, 0x0B, 0x1B,
- 0x0C, 0x1C, 0x0D, 0x1D,
- 0x0E, 0x1E, 0x0F, 0x1F};
-
- emit_move_insn (mask, array_to_constant (TImode, arr));
- emit_insn (gen_shufb (operands[0], operands[1], operands[2], mask));
- DONE;
-}")
-
(define_expand "vec_pack_trunc_v8hi"
[(set (match_operand:V16QI 0 "spu_reg_operand" "=r")
(vec_concat:V16QI
diff --git a/gcc/config/spu/t-spu-elf b/gcc/config/spu/t-spu-elf
index 3f9510112f7..50c8d0353f5 100644
--- a/gcc/config/spu/t-spu-elf
+++ b/gcc/config/spu/t-spu-elf
@@ -15,78 +15,9 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Define system directory to match STANDARD_INCLUDE_DIR in spu-elf.h,
-# allowing combined SPU/PPU sysroot builds.
-NATIVE_SYSTEM_HEADER_DIR = /include
-
-# Suppress building libgcc1.a
-LIBGCC1 =
-CROSS_LIBGCC1 =
-
-TARGET_LIBGCC2_CFLAGS = -fPIC -mwarn-reloc -D__IN_LIBGCC2
-
-# We exclude those because the libgcc2.c default versions do not support
-# the SPU single-precision format (round towards zero). We provide our
-# own versions below and/or via direct expansion.
-LIB2FUNCS_EXCLUDE = _floatdisf _floatundisf _floattisf _floatunstisf
-
-LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/spu/float_unssidf.c \
- $(srcdir)/config/spu/float_unsdidf.c \
- $(srcdir)/config/spu/float_unsdisf.c \
- $(srcdir)/config/spu/float_disf.c \
- $(srcdir)/config/spu/mfc_tag_table.c \
- $(srcdir)/config/spu/mfc_tag_reserve.c \
- $(srcdir)/config/spu/mfc_tag_release.c \
- $(srcdir)/config/spu/mfc_multi_tag_reserve.c \
- $(srcdir)/config/spu/mfc_multi_tag_release.c \
- $(srcdir)/config/spu/multi3.c \
- $(srcdir)/config/spu/divmodti4.c \
- $(srcdir)/config/spu/divv2df3.c
-
-# Build TImode conversion routines to support Fortran 128-bit
-# integer data types.
-LIB2_SIDITI_CONV_FUNCS=yes
-
-# Don't let CTOR_LIST end up in sdata section.
-CRTSTUFF_T_CFLAGS =
-
# Multi-lib support.
MULTILIB_OPTIONS=mea64
-# Neither gcc or newlib seem to have a standard way to generate multiple
-# crt*.o files. So we don't use the standard crt0.o name anymore.
-
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o libgcc_cachemgr.a libgcc_cachemgr_nonatomic.a \
- libgcc_cache8k.a libgcc_cache16k.a libgcc_cache32k.a libgcc_cache64k.a libgcc_cache128k.a
-
-$(T)cachemgr.o: $(srcdir)/config/spu/cachemgr.c
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(MULTILIB_CFLAGS) -c $< -o $@
-
-# Specialised rule to add a -D flag.
-$(T)cachemgr_nonatomic.o: $(srcdir)/config/spu/cachemgr.c
- $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(MULTILIB_CFLAGS) -DNONATOMIC -c $< -o $@
-
-$(T)libgcc_%.a: $(T)%.o
- $(AR_FOR_TARGET) -rcs $@ $<
-
-$(T)cache8k.o: $(srcdir)/config/spu/cache.S
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -D__CACHE_SIZE__=8 -o $@ -c $<
-
-$(T)cache16k.o: $(srcdir)/config/spu/cache.S
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -D__CACHE_SIZE__=16 -o $@ -c $<
-
-$(T)cache32k.o: $(srcdir)/config/spu/cache.S
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -D__CACHE_SIZE__=32 -o $@ -c $<
-
-$(T)cache64k.o: $(srcdir)/config/spu/cache.S
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -D__CACHE_SIZE__=64 -o $@ -c $<
-
-$(T)cache128k.o: $(srcdir)/config/spu/cache.S
- $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -D__CACHE_SIZE__=128 -o $@ -c $<
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
spu.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(REGS_H) hard-reg-set.h \
real.h insn-config.h conditions.h insn-attr.h flags.h $(RECOG_H) \
diff --git a/gcc/config/stormy16/stormy16-lib2-ashlsi3.c b/gcc/config/stormy16/stormy16-lib2-ashlsi3.c
deleted file mode 100644
index d6cabc6691c..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-ashlsi3.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_ASHLSI3
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-ashrsi3.c b/gcc/config/stormy16/stormy16-lib2-ashrsi3.c
deleted file mode 100644
index 151e3d01cab..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-ashrsi3.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_ASHRSI3
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-clzhi2.c b/gcc/config/stormy16/stormy16-lib2-clzhi2.c
deleted file mode 100644
index 066fdf13112..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-clzhi2.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_CLZHI2
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-cmpsi2.c b/gcc/config/stormy16/stormy16-lib2-cmpsi2.c
deleted file mode 100644
index 7563c36b569..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-cmpsi2.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_CMPSI2
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-ctzhi2.c b/gcc/config/stormy16/stormy16-lib2-ctzhi2.c
deleted file mode 100644
index c1497db952f..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-ctzhi2.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_CTZHI2
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-divsi3.c b/gcc/config/stormy16/stormy16-lib2-divsi3.c
deleted file mode 100644
index 33c370d1c1f..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-divsi3.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_DIVSI3
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-ffshi2.c b/gcc/config/stormy16/stormy16-lib2-ffshi2.c
deleted file mode 100644
index 4b629ddece8..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-ffshi2.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_FFSHI2
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-lshrsi3.c b/gcc/config/stormy16/stormy16-lib2-lshrsi3.c
deleted file mode 100644
index cd769ee6647..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-lshrsi3.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_LSHRSI3
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-modsi3.c b/gcc/config/stormy16/stormy16-lib2-modsi3.c
deleted file mode 100644
index 587d0070d23..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-modsi3.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_MODSI3
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-parityhi2.c b/gcc/config/stormy16/stormy16-lib2-parityhi2.c
deleted file mode 100644
index 1d128171a8b..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-parityhi2.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_PARITYHI2
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-popcounthi2.c b/gcc/config/stormy16/stormy16-lib2-popcounthi2.c
deleted file mode 100644
index f07d66873e6..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-popcounthi2.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_POPCOUNTHI2
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-ucmpsi2.c b/gcc/config/stormy16/stormy16-lib2-ucmpsi2.c
deleted file mode 100644
index da1a3e70753..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-ucmpsi2.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_UCMPSI2
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-udivmodsi4.c b/gcc/config/stormy16/stormy16-lib2-udivmodsi4.c
deleted file mode 100644
index d555e64c6d8..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-udivmodsi4.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_UDIVMODSI4
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-udivsi3.c b/gcc/config/stormy16/stormy16-lib2-udivsi3.c
deleted file mode 100644
index fdcd64a0ae0..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-udivsi3.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_UDIVSI3
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2-umodsi3.c b/gcc/config/stormy16/stormy16-lib2-umodsi3.c
deleted file mode 100644
index 87921f2a196..00000000000
--- a/gcc/config/stormy16/stormy16-lib2-umodsi3.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define XSTORMY16_UMODSI3
-#include "stormy16-lib2.c"
diff --git a/gcc/config/stormy16/stormy16-lib2.c b/gcc/config/stormy16/stormy16-lib2.c
deleted file mode 100644
index e3c16435471..00000000000
--- a/gcc/config/stormy16/stormy16-lib2.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/* This file contains 16-bit versions of some of the functions found in
- libgcc2.c. Really libgcc ought to be moved out of the gcc directory
- and into its own top level directory, and then split up into multiple
- files. On this glorious day maybe this code can be integrated into
- it too. */
-
-/* Copyright (C) 2005, 2008, 2009, 2010 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 3, 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.
-
- Under Section 7 of GPL version 3, you are granted additional
- permissions described in the GCC Runtime Library Exception, version
- 3.1, as published by the Free Software Foundation.
-
- You should have received a copy of the GNU General Public License and
- a copy of the GCC Runtime Library Exception along with this program;
- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
- <http://www.gnu.org/licenses/>. */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-
-#ifdef HAVE_GAS_HIDDEN
-#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
-#else
-#define ATTRIBUTE_HIDDEN
-#endif
-
-#ifndef MIN_UNITS_PER_WORD
-#define MIN_UNITS_PER_WORD UNITS_PER_WORD
-#endif
-
-#ifndef LIBGCC2_UNITS_PER_WORD
-# if MIN_UNITS_PER_WORD > 4
-# define LIBGCC2_UNITS_PER_WORD 8
-# elif (MIN_UNITS_PER_WORD > 2 \
- || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32))
-# define LIBGCC2_UNITS_PER_WORD 4
-# else
-# define LIBGCC2_UNITS_PER_WORD MIN_UNITS_PER_WORD
-# endif
-#endif
-
-#define word_type Wtype
-
-#include "libgcc2.h"
-#undef int
-
-/* These prototypes would normally live in libgcc2.h, but this can
- only happen once the code below is integrated into libgcc2.c. */
-
-extern USItype udivmodsi4 (USItype, USItype, word_type);
-extern SItype __divsi3 (SItype, SItype);
-extern SItype __modsi3 (SItype, SItype);
-extern SItype __udivsi3 (SItype, SItype);
-extern SItype __umodsi3 (SItype, SItype);
-extern SItype __ashlsi3 (SItype, SItype);
-extern SItype __ashrsi3 (SItype, SItype);
-extern USItype __lshrsi3 (USItype, USItype);
-extern int __popcounthi2 (UHWtype);
-extern int __parityhi2 (UHWtype);
-extern int __clzhi2 (UHWtype);
-extern int __ctzhi2 (UHWtype);
-
-
-#ifdef XSTORMY16_UDIVMODSI4
-USItype
-udivmodsi4 (USItype num, USItype den, word_type modwanted)
-{
- USItype bit = 1;
- USItype res = 0;
-
- while (den < num && bit && !(den & (1L << 31)))
- {
- den <<= 1;
- bit <<= 1;
- }
- while (bit)
- {
- if (num >= den)
- {
- num -= den;
- res |= bit;
- }
- bit >>= 1;
- den >>= 1;
- }
-
- if (modwanted)
- return num;
- return res;
-}
-#endif
-
-#ifdef XSTORMY16_DIVSI3
-SItype
-__divsi3 (SItype a, SItype b)
-{
- word_type neg = 0;
- SItype res;
-
- if (a < 0)
- {
- a = -a;
- neg = !neg;
- }
-
- if (b < 0)
- {
- b = -b;
- neg = !neg;
- }
-
- res = udivmodsi4 (a, b, 0);
-
- if (neg)
- res = -res;
-
- return res;
-}
-#endif
-
-#ifdef XSTORMY16_MODSI3
-SItype
-__modsi3 (SItype a, SItype b)
-{
- word_type neg = 0;
- SItype res;
-
- if (a < 0)
- {
- a = -a;
- neg = 1;
- }
-
- if (b < 0)
- b = -b;
-
- res = udivmodsi4 (a, b, 1);
-
- if (neg)
- res = -res;
-
- return res;
-}
-#endif
-
-#ifdef XSTORMY16_UDIVSI3
-SItype
-__udivsi3 (SItype a, SItype b)
-{
- return udivmodsi4 (a, b, 0);
-}
-#endif
-
-#ifdef XSTORMY16_UMODSI3
-SItype
-__umodsi3 (SItype a, SItype b)
-{
- return udivmodsi4 (a, b, 1);
-}
-#endif
-
-#ifdef XSTORMY16_ASHLSI3
-SItype
-__ashlsi3 (SItype a, SItype b)
-{
- word_type i;
-
- if (b & 16)
- a <<= 16;
- if (b & 8)
- a <<= 8;
- for (i = (b & 0x7); i > 0; --i)
- a <<= 1;
- return a;
-}
-#endif
-
-#ifdef XSTORMY16_ASHRSI3
-SItype
-__ashrsi3 (SItype a, SItype b)
-{
- word_type i;
-
- if (b & 16)
- a >>= 16;
- if (b & 8)
- a >>= 8;
- for (i = (b & 0x7); i > 0; --i)
- a >>= 1;
- return a;
-}
-#endif
-
-#ifdef XSTORMY16_LSHRSI3
-USItype
-__lshrsi3 (USItype a, USItype b)
-{
- word_type i;
-
- if (b & 16)
- a >>= 16;
- if (b & 8)
- a >>= 8;
- for (i = (b & 0x7); i > 0; --i)
- a >>= 1;
- return a;
-}
-#endif
-
-#ifdef XSTORMY16_POPCOUNTHI2
-/* Returns the number of set bits in X.
- FIXME: The return type really should be "unsigned int"
- but this is not how the builtin is prototyped. */
-int
-__popcounthi2 (UHWtype x)
-{
- int ret;
-
- ret = __popcount_tab [x & 0xff];
- ret += __popcount_tab [(x >> 8) & 0xff];
-
- return ret;
-}
-#endif
-
-#ifdef XSTORMY16_PARITYHI2
-/* Returns the number of set bits in X, modulo 2.
- FIXME: The return type really should be "unsigned int"
- but this is not how the builtin is prototyped. */
-
-int
-__parityhi2 (UHWtype x)
-{
- x ^= x >> 8;
- x ^= x >> 4;
- x &= 0xf;
- return (0x6996 >> x) & 1;
-}
-#endif
-
-#ifdef XSTORMY16_CLZHI2
-/* Returns the number of zero-bits from the most significant bit to the
- first nonzero bit in X. Returns 16 for X == 0. Implemented as a
- simple for loop in order to save space by removing the need for
- the __clz_tab array.
- FIXME: The return type really should be "unsigned int" but this is
- not how the builtin is prototyped. */
-#undef unsigned
-int
-__clzhi2 (UHWtype x)
-{
- unsigned int i;
- unsigned int c;
- unsigned int value = x;
-
- for (c = 0, i = 1 << 15; i; i >>= 1, c++)
- if (i & value)
- break;
- return c;
-}
-#endif
-
-#ifdef XSTORMY16_CTZHI2
-/* Returns the number of trailing zero bits in X.
- FIXME: The return type really should be "signed int" since
- ctz(0) returns -1, but this is not how the builtin is prototyped. */
-
-int
-__ctzhi2 (UHWtype x)
-{
- /* This is cunning. It converts X into a number with only the one bit
- set, the bit that was the least significant bit in X. From this we
- can use the count_leading_zeros to compute the number of trailing
- bits. */
- x &= - x;
-
- return 15 - __builtin_clz (x);
-}
-#endif
-
-#ifdef XSTORMY16_FFSHI2
-/* Returns one plus the index of the least significant 1-bit of X,
- or if X is zero, returns zero. FIXME: The return type really
- should be "unsigned int" but this is not how the builtin is
- prototyped. */
-
-int
-__ffshi2 (UHWtype u)
-{
- UHWtype count;
-
- if (u == 0)
- return 0;
-
- return 16 - __builtin_clz (u & - u);
-}
-#endif
-
-#ifdef XSTORMY16_UCMPSI2
-/* Performs an unsigned comparison of two 32-bit values: A and B.
- If A is less than B, then 0 is returned. If A is greater than B,
- then 2 is returned. Otherwise A and B are equal and 1 is returned. */
-
-word_type
-__ucmpsi2 (USItype a, USItype b)
-{
- word_type hi_a = (a >> 16);
- word_type hi_b = (b >> 16);
-
- if (hi_a == hi_b)
- {
- word_type low_a = (a & 0xffff);
- word_type low_b = (b & 0xffff);
-
- return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1);
- }
-
- return hi_a < hi_b ? 0 : 2;
-}
-#endif
-
-#ifdef XSTORMY16_CMPSI2
-/* Performs an signed comparison of two 32-bit values: A and B.
- If A is less than B, then 0 is returned. If A is greater than B,
- then 2 is returned. Otherwise A and B are equal and 1 is returned. */
-
-word_type
-__cmpsi2 (SItype a, SItype b)
-{
- word_type hi_a = (a >> 16);
- word_type hi_b = (b >> 16);
-
- if (hi_a == hi_b)
- {
- word_type low_a = (a & 0xffff);
- word_type low_b = (b & 0xffff);
-
- return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1);
- }
-
- return hi_a < hi_b ? 0 : 2;
-}
-#endif
diff --git a/gcc/config/stormy16/t-stormy16 b/gcc/config/stormy16/t-stormy16
deleted file mode 100644
index c2b6c2a5573..00000000000
--- a/gcc/config/stormy16/t-stormy16
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- makefile -*-
-#
-# Copyright (C) 2001, 2004, 2010, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# SImode arithmetic and logical routines, HImode bit counting routines.
-LIB2FUNCS_EXTRA = \
- $(srcdir)/config/stormy16/stormy16-lib2-udivmodsi4.c \
- $(srcdir)/config/stormy16/stormy16-lib2-divsi3.c \
- $(srcdir)/config/stormy16/stormy16-lib2-modsi3.c \
- $(srcdir)/config/stormy16/stormy16-lib2-udivsi3.c \
- $(srcdir)/config/stormy16/stormy16-lib2-umodsi3.c \
- $(srcdir)/config/stormy16/stormy16-lib2-ashlsi3.c \
- $(srcdir)/config/stormy16/stormy16-lib2-ashrsi3.c \
- $(srcdir)/config/stormy16/stormy16-lib2-lshrsi3.c \
- $(srcdir)/config/stormy16/stormy16-lib2-popcounthi2.c \
- $(srcdir)/config/stormy16/stormy16-lib2-parityhi2.c \
- $(srcdir)/config/stormy16/stormy16-lib2-clzhi2.c \
- $(srcdir)/config/stormy16/stormy16-lib2-ctzhi2.c \
- $(srcdir)/config/stormy16/stormy16-lib2-ffshi2.c \
- $(srcdir)/config/stormy16/stormy16-lib2-cmpsi2.c \
- $(srcdir)/config/stormy16/stormy16-lib2-ucmpsi2.c
-
-TARGET_LIBGCC2_CFLAGS = -O2
diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin
index d952bd39273..e2bd74d61b0 100644
--- a/gcc/config/t-darwin
+++ b/gcc/config/t-darwin
@@ -41,9 +41,3 @@ darwin-driver.o: $(srcdir)/config/darwin-driver.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) opts.h
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/darwin-driver.c
-
-# -pipe because there's an assembler bug, 4077127, which causes
-# it to not properly process the first # directive, causing temporary
-# file names to appear in stabs, causing the bootstrap to fail. Using -pipe
-# works around this by not having any temporary file names.
-TARGET_LIBGCC2_CFLAGS = -fPIC -pipe
diff --git a/gcc/config/t-freebsd b/gcc/config/t-freebsd
deleted file mode 100644
index 0680618a6ec..00000000000
--- a/gcc/config/t-freebsd
+++ /dev/null
@@ -1,5 +0,0 @@
-# Compile crtbeginS.o and crtendS.o with pic.
-CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
-
-# Compile libgcc.a with pic.
-TARGET_LIBGCC2_CFLAGS += -fPIC
diff --git a/gcc/config/t-freebsd-thread b/gcc/config/t-freebsd-thread
deleted file mode 100644
index 6e5c64f78cf..00000000000
--- a/gcc/config/t-freebsd-thread
+++ /dev/null
@@ -1,2 +0,0 @@
-# This is currently needed to compile libgcc2 for threads support
-TARGET_LIBGCC2_CFLAGS += -pthread
diff --git a/gcc/config/t-gnu b/gcc/config/t-gnu
deleted file mode 100644
index 7be5d00a718..00000000000
--- a/gcc/config/t-gnu
+++ /dev/null
@@ -1,2 +0,0 @@
-# In GNU, "/usr" is a four-letter word.
-NATIVE_SYSTEM_HEADER_DIR = /include
diff --git a/gcc/config/t-libc-ok b/gcc/config/t-libc-ok
deleted file mode 100644
index 561ee0b31d1..00000000000
--- a/gcc/config/t-libc-ok
+++ /dev/null
@@ -1 +0,0 @@
-CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
diff --git a/gcc/config/t-libgcc-pic b/gcc/config/t-libgcc-pic
deleted file mode 100644
index ff935fe1e05..00000000000
--- a/gcc/config/t-libgcc-pic
+++ /dev/null
@@ -1,2 +0,0 @@
-# Compile libgcc2.a with pic.
-TARGET_LIBGCC2_CFLAGS = -fPIC
diff --git a/gcc/config/t-libunwind b/gcc/config/t-libunwind
index 6b8d2dd1292..6ebef7cc837 100644
--- a/gcc/config/t-libunwind
+++ b/gcc/config/t-libunwind
@@ -17,11 +17,5 @@
# <http://www.gnu.org/licenses/>.
# Use the system libunwind library.
-#
-# Override the default value from t-slibgcc-elf-ver and mention -lunwind
-# so that the resulting libgcc_s.so has the necessary DT_NEEDED entry for
-# libunwind.
-SHLIB_LC = -lunwind -lc
T_CFLAGS += -DUSE_LIBUNWIND_EXCEPTIONS
-TARGET_LIBGCC2_CFLAGS += -DUSE_GAS_SYMVER
diff --git a/gcc/config/t-linux b/gcc/config/t-linux
deleted file mode 100644
index 64d19ca8dd7..00000000000
--- a/gcc/config/t-linux
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003,
-# 2004, 2011 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Compile crtbeginS.o and crtendS.o with pic.
-CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
-# Compile libgcc2.a with pic.
-TARGET_LIBGCC2_CFLAGS = -fPIC
-
-# Override t-slibgcc-elf-ver to export some libgcc symbols with
-# the symbol versions that glibc used.
-SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
diff --git a/gcc/config/t-lynx b/gcc/config/t-lynx
index ab6d2675c4f..860f61281d0 100644
--- a/gcc/config/t-lynx
+++ b/gcc/config/t-lynx
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2007 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2007, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -16,18 +16,9 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Compile crtbeginS.o and crtendS.o with pic.
-CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
-
-# Compile libgcc2.a with pic.
-TARGET_LIBGCC2_CFLAGS = -fPIC
-
MULTILIB_OPTIONS = mthreads
MULTILIB_DIRNAMES = thread
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
Local Variables:
mode: makefile
End:
diff --git a/gcc/config/t-netbsd b/gcc/config/t-netbsd
deleted file mode 100644
index 34949e12858..00000000000
--- a/gcc/config/t-netbsd
+++ /dev/null
@@ -1,2 +0,0 @@
-# Always build crtstuff with PIC.
-CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
diff --git a/gcc/config/t-openbsd-thread b/gcc/config/t-openbsd-thread
deleted file mode 100644
index 5f4edf567c5..00000000000
--- a/gcc/config/t-openbsd-thread
+++ /dev/null
@@ -1,3 +0,0 @@
-# This is currently needed to compile libgcc2 for threads support
-TARGET_LIBGCC2_CFLAGS=-pthread
-
diff --git a/gcc/config/t-rtems b/gcc/config/t-rtems
index dfbd3afe9ee..baa00d83176 100644
--- a/gcc/config/t-rtems
+++ b/gcc/config/t-rtems
@@ -1,7 +1,2 @@
# RTEMS always has limits.h.
LIMITS_H_TEST = true
-
-# If we are building next to newlib, this will let us find the RTEMS
-# limits.h when building libgcc2. Otherwise, newlib must be installed
-# first.
-LIBGCC2_INCLUDES = -I$(srcdir)/../newlib/libc/sys/rtems/include
diff --git a/gcc/config/t-slibgcc b/gcc/config/t-slibgcc
new file mode 100644
index 00000000000..91f2d92e822
--- /dev/null
+++ b/gcc/config/t-slibgcc
@@ -0,0 +1,2 @@
+# Cause ENABLE_SHARED_LIBGCC to be defined in gcc/Makefile.in (DRIVER_DEFINES).
+SHLIB = true
diff --git a/gcc/config/t-slibgcc-dummy b/gcc/config/t-slibgcc-dummy
deleted file mode 100644
index e68ce5eb24a..00000000000
--- a/gcc/config/t-slibgcc-dummy
+++ /dev/null
@@ -1,3 +0,0 @@
-# SHLIB_LINK must be non-empty so ENABLE_SHARED_LIBGCC is defined correctly
-# in DRIVER_DEFINES if libgcc configuration has been moved to toplevel.
-SHLIB_LINK = dummy
diff --git a/gcc/config/t-slibgcc-elf-ver b/gcc/config/t-slibgcc-elf-ver
deleted file mode 100644
index b90f4fcf3a3..00000000000
--- a/gcc/config/t-slibgcc-elf-ver
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright (C) 2001, 2002, 2003, 2004, 2005 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Build a shared libgcc library for ELF with symbol versioning
-# with the GNU linker.
-
-SHLIB_EXT = .so
-SHLIB_SOLINK = @shlib_base_name@.so
-SHLIB_SOVERSION = 1
-SHLIB_SONAME = @shlib_base_name@.so.$(SHLIB_SOVERSION)
-SHLIB_MAP = @shlib_map_file@
-SHLIB_OBJS = @shlib_objs@
-SHLIB_DIR = @multilib_dir@
-SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
-SHLIB_LC = -lc
-SHLIB_MAKE_SOLINK = $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
-SHLIB_INSTALL_SOLINK = $(LN_S) $(SHLIB_SONAME) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
-
-SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,--soname=$(SHLIB_SONAME) \
- -Wl,--version-script=$(SHLIB_MAP) \
- -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
- $(SHLIB_OBJS) $(SHLIB_LC) && \
- rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
- if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
- mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
- $(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
- else true; fi && \
- mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \
- $(SHLIB_MAKE_SOLINK)
-# $(slibdir) double quoted to protect it from expansion while building
-# libgcc.mk. We want this delayed until actual install time.
-SHLIB_INSTALL = \
- $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
- $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_SONAME) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SONAME); \
- rm -f $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
- $(SHLIB_INSTALL_SOLINK)
-SHLIB_MKMAP = $(srcdir)/mkmap-symver.awk
-SHLIB_MAPFILES = $$(libgcc_objdir)/libgcc-std.ver
diff --git a/gcc/config/t-slibgcc-libgcc b/gcc/config/t-slibgcc-libgcc
deleted file mode 100644
index df004a5e964..00000000000
--- a/gcc/config/t-slibgcc-libgcc
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (C) 2009 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 3, 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 COPYING3. If not see
-# <http://www.gnu.org/licenses/>.
-
-# Instead of creating $(SHLIB_SOLINK) symlink create a GNU ld
-# linker script which sources in both $(SHLIB_SONAME) and libgcc.a.
-# This is needed on targets where libgcc.a contains routines that aren't in
-# $(SHLIB_SONAME) and are needed for shared libraries.
-
-SHLIB_MAKE_SOLINK = \
- (echo "/* GNU ld script"; \
- echo " Use the shared library, but some functions are only in"; \
- echo " the static library. */"; \
- echo "GROUP ( $(SHLIB_SONAME) libgcc.a )" \
- ) > $(SHLIB_DIR)/$(SHLIB_SOLINK)
-SHLIB_INSTALL_SOLINK = \
- $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_SOLINK) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
diff --git a/gcc/config/t-sol2 b/gcc/config/t-sol2
index f9156223593..8646e3625e8 100644
--- a/gcc/config/t-sol2
+++ b/gcc/config/t-sol2
@@ -36,6 +36,3 @@ sol2-stubs.o: $(srcdir)/config/sol2-stubs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h
sol2.o: $(srcdir)/config/sol2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
tree.h output.h $(TM_H) $(TARGET_H) $(TM_P_H) $(GGC_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
-
-# This is required by gcc/ada/gcc-interface/Makefile.in.
-TARGET_LIBGCC2_CFLAGS = -fPIC
diff --git a/gcc/config/t-svr4 b/gcc/config/t-svr4
deleted file mode 100644
index 6e75eea1f6e..00000000000
--- a/gcc/config/t-svr4
+++ /dev/null
@@ -1,8 +0,0 @@
-# We need to use -fPIC when we are using gcc to compile the routines in
-# crtstuff.c. This is only really needed when we are going to use gcc/g++
-# to produce a shared library, but since we don't know ahead of time when
-# we will be doing that, we just always use -fPIC when compiling the
-# routines in crtstuff.c. Likewise for libgcc2.c.
-
-CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
-TARGET_LIBGCC2_CFLAGS = -fPIC
diff --git a/gcc/config/t-vxworks b/gcc/config/t-vxworks
index e200d932095..61d6e710aca 100644
--- a/gcc/config/t-vxworks
+++ b/gcc/config/t-vxworks
@@ -1,5 +1,5 @@
# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008,
-# 2009, 2010 Free Software Foundation, Inc.
+# 2009, 2010, 2011 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -17,37 +17,9 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# Build libgcc using the multilib mechanism
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
-
-# No special flags needed for libgcc.a
-TARGET_LIBGCC2_CFLAGS =
-
-# Don't build libgcc.a with debug info
-LIBGCC2_DEBUG_CFLAGS =
-
-# Extra libgcc2 modules used by gthr-vxworks.h functions
-LIB2FUNCS_EXTRA = $(srcdir)/config/vxlib.c $(srcdir)/config/vxlib-tls.c
-
-# Some runtime modules need these. Can't set extra_headers in config.gcc
-# because the paths are always made absolute to the cpu config dir.
-EXTRA_HEADERS += $(srcdir)/gthr-vxworks.h gthr-default.h
-
-# This ensures that the correct target headers are used; some
-# VxWorks system headers have names that collide with GCC's
-# internal (host) headers, e.g. regs.h.
-LIBGCC2_INCLUDES = -nostdinc -I \
- `case "/$$(MULTIDIR)" in \
- */mrtp*) echo $(WIND_USR)/h ;; \
- *) echo $(WIND_BASE)/target/h ;; \
- esac`
-
# Both the kernel and RTP headers provide limits.h.
LIMITS_H_TEST = true
-EXTRA_MULTILIB_PARTS =
-
vxworks.o: $(srcdir)/config/vxworks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TARGET_H) output.h $(TM_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/v850/t-v850 b/gcc/config/v850/t-v850
index fcd3b841e30..ca7f7ff73aa 100644
--- a/gcc/config/v850/t-v850
+++ b/gcc/config/v850/t-v850
@@ -17,71 +17,9 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = v850/lib1funcs.asm
-LIB1ASMFUNCS = _mulsi3 \
- _divsi3 \
- _udivsi3 \
- _modsi3 \
- _umodsi3 \
- _save_2 \
- _save_20 \
- _save_21 \
- _save_22 \
- _save_23 \
- _save_24 \
- _save_25 \
- _save_26 \
- _save_27 \
- _save_28 \
- _save_29 \
- _save_2c \
- _save_20c \
- _save_21c \
- _save_22c \
- _save_23c \
- _save_24c \
- _save_25c \
- _save_26c \
- _save_27c \
- _save_28c \
- _save_29c \
- _save_31c \
- _save_interrupt \
- _save_all_interrupt \
- _callt_save_20 \
- _callt_save_21 \
- _callt_save_22 \
- _callt_save_23 \
- _callt_save_24 \
- _callt_save_25 \
- _callt_save_26 \
- _callt_save_27 \
- _callt_save_28 \
- _callt_save_29 \
- _callt_save_20c \
- _callt_save_21c \
- _callt_save_22c \
- _callt_save_23c \
- _callt_save_24c \
- _callt_save_25c \
- _callt_save_26c \
- _callt_save_27c \
- _callt_save_28c \
- _callt_save_29c \
- _callt_save_31c \
- _callt_save_interrupt \
- _callt_save_all_interrupt \
- _callt_save_r2_r29 \
- _callt_save_r2_r31 \
- _negdi2 \
- _cmpdi2 \
- _ucmpdi2 \
- _muldi3
-
# Create target-specific versions of the libraries
MULTILIB_OPTIONS = mv850/mv850e/mv850e2/mv850e2v3
MULTILIB_DIRNAMES = v850 v850e v850e2 v850e2v3
-INSTALL_LIBGCC = install-multilib
MULTILIB_MATCHES = mv850e=mv850e1
TCFLAGS = -mno-app-regs -msmall-sld -Wa,-mwarn-signed-overflow -Wa,-mwarn-unsigned-overflow
diff --git a/gcc/config/vax/t-linux b/gcc/config/vax/t-linux
deleted file mode 100644
index 9af1edb0fab..00000000000
--- a/gcc/config/vax/t-linux
+++ /dev/null
@@ -1,2 +0,0 @@
-LIB1ASMSRC = vax/lib1funcs.asm
-LIB1ASMFUNCS = _udivsi3 _umodsi3
diff --git a/gcc/config/vms/t-vms b/gcc/config/vms/t-vms
index 516435df1f9..2ebcfd713c9 100644
--- a/gcc/config/vms/t-vms
+++ b/gcc/config/vms/t-vms
@@ -1,4 +1,4 @@
-# Copyright (C) 2009, 2010
+# Copyright (C) 2009, 2010, 2011
# Free Software Foundation, Inc.
#
# This file is part of GCC.
@@ -24,17 +24,6 @@ LIMITS_H_TEST = false
# Under VMS, directory names cannot contain dots.
version:=$(shell echo $(BASEVER_c) | sed -e 's/\./_/g')
-VMS_EXTRA_PARTS=vcrt0.o pcrt0.o
-
-# Assemble startup files.
-$(T)vcrt0.o: $(srcdir)/config/vms/vms-ucrt0.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)vcrt0.o $(srcdir)/config/vms/vms-ucrt0.c
-
-$(T)pcrt0.o: $(srcdir)/config/vms/vms-ucrt0.c $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)pcrt0.o -DCRT0_POSIX_EXIT $(srcdir)/config/vms/vms-ucrt0.c
-
vms-crtlmap.h: $(srcdir)/config/vms/vms-crtlmap.map \
$(srcdir)/config/vms/make-crtlmap.awk
$(AWK) -f $(srcdir)/config/vms/make-crtlmap.awk \
diff --git a/gcc/config/vms/xm-vms.h b/gcc/config/vms/xm-vms.h
index 7907f9263cf..816935b5062 100644
--- a/gcc/config/vms/xm-vms.h
+++ b/gcc/config/vms/xm-vms.h
@@ -1,6 +1,6 @@
/* Configuration for GCC for hosting on VMS
using a Unix style C library.
- Copyright (C) 1996, 1997, 2001, 2004, 2007, 2009
+ Copyright (C) 1996, 1997, 2001, 2004, 2007, 2009, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -55,4 +55,3 @@ do \
#define STANDARD_EXEC_PREFIX "/gnu/libexec/gcc/"
#define STANDARD_STARTFILE_PREFIX "/gnu/lib/"
-#define STANDARD_INCLUDE_DIR "/gnu/include"
diff --git a/gcc/config/xtensa/t-elf b/gcc/config/xtensa/t-elf
deleted file mode 100644
index 7d6cd1a3a9b..00000000000
--- a/gcc/config/xtensa/t-elf
+++ /dev/null
@@ -1,6 +0,0 @@
-# Build CRT files and libgcc with the "longcalls" option
-CRTSTUFF_T_CFLAGS += -mlongcalls
-CRTSTUFF_T_CFLAGS_S += -mlongcalls
-TARGET_LIBGCC2_CFLAGS += -mlongcalls
-
-EXTRA_MULTILIB_PARTS = crti.o crtn.o crtbegin.o crtend.o
diff --git a/gcc/config/xtensa/t-linux b/gcc/config/xtensa/t-linux
deleted file mode 100644
index 7d535e155b4..00000000000
--- a/gcc/config/xtensa/t-linux
+++ /dev/null
@@ -1,3 +0,0 @@
-EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
-
-SHLIB_MAPFILES += $(srcdir)/config/xtensa/libgcc-xtensa.ver
diff --git a/gcc/config/xtensa/t-xtensa b/gcc/config/xtensa/t-xtensa
index 641e6fe7620..6ec56969fe4 100644
--- a/gcc/config/xtensa/t-xtensa
+++ b/gcc/config/xtensa/t-xtensa
@@ -17,25 +17,4 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-LIB1ASMSRC = xtensa/lib1funcs.asm
-LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 _udivsi3 _umodsi3 \
- _umulsidi3 _clz _clzsi2 _ctzsi2 _ffssi2 \
- _ashldi3 _ashrdi3 _lshrdi3 \
- _negsf2 _addsubsf3 _mulsf3 _divsf3 _cmpsf2 _fixsfsi _fixsfdi \
- _fixunssfsi _fixunssfdi _floatsisf _floatunsisf \
- _floatdisf _floatundisf \
- _negdf2 _addsubdf3 _muldf3 _divdf3 _cmpdf2 _fixdfsi _fixdfdi \
- _fixunsdfsi _fixunsdfdi _floatsidf _floatunsidf \
- _floatdidf _floatundidf \
- _truncdfsf2 _extendsfdf2
-
-LIB2FUNCS_EXTRA = $(srcdir)/config/xtensa/lib2funcs.S
-
-$(T)crti.o: $(srcdir)/config/xtensa/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/xtensa/crti.asm
-$(T)crtn.o: $(srcdir)/config/xtensa/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/xtensa/crtn.asm
-
$(out_object_file): gt-xtensa.h
diff --git a/gcc/configure b/gcc/configure
index cb55ddaa2a4..3b0b39b484a 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -618,12 +618,9 @@ xm_include_list
xm_file_list
tm_p_include_list
tm_p_file_list
-libgcc_tm_include_list
-libgcc_tm_file_list
tm_defines
tm_include_list
tm_file_list
-thread_file
common_out_object_file
common_out_file
out_object_file
@@ -645,7 +642,6 @@ gcc_config_arguments
float_h_file
extra_programs
extra_passes
-extra_parts
extra_objs
extra_headers_list
user_headers_inc_next_post
@@ -671,7 +667,6 @@ all_gtfiles
all_compilers
srcdir
subdirs
-slibdir
dollar
gcc_tooldir
enable_lto
@@ -728,7 +723,7 @@ LIBINTL
USE_NLS
extra_opt_files
extra_modes_file
-gthread_flags
+NATIVE_SYSTEM_HEADER_DIR
objext
manext
LIBICONV_DEP
@@ -886,6 +881,7 @@ enable_tls
enable_objc_gc
with_dwarf2
enable_shared
+with_native_system_header_dir
with_build_sysroot
with_sysroot
with_specs
@@ -916,7 +912,6 @@ with_gc
with_system_zlib
enable_maintainer_mode
enable_version_specific_runtime_libs
-with_slibdir
enable_plugin
enable_libquadmath_support
with_linker_hash_style
@@ -1651,6 +1646,9 @@ Optional Packages:
--with-as arrange to use the specified as (full pathname)
--with-stabs arrange to use stabs instead of host debug format
--with-dwarf2 force the default debug format to be DWARF 2
+ --with-native-system-header-dir=dir
+ use dir as the directory to look for standard
+ system header files in. Defaults to /usr/include.
--with-build-sysroot=sysroot
use sysroot as the system root during the build
--with-sysroot[=DIR] search for usr/lib, usr/include, et al, within DIR
@@ -1669,7 +1667,6 @@ Optional Packages:
--with-gc={page,zone} choose the garbage collection mechanism to use with
the compiler
--with-system-zlib use installed libz
- --with-slibdir=DIR shared libraries in DIR [LIBDIR]
--with-linker-hash-style={sysv,gnu,both}
specify the linker hash style
@@ -7152,6 +7149,22 @@ fi
+# Check whether --with-native-system-header-dir was given.
+if test "${with_native_system_header_dir+set}" = set; then :
+ withval=$with_native_system_header_dir;
+ case ${with_native_system_header_dir} in
+ yes|no) as_fn_error "bad value ${withval} given for --with-native-system-header-dir" "$LINENO" 5 ;;
+ /* | [A-Za-z]:[\\/]*) ;;
+ *) as_fn_error "--with-native-system-header-dir argument ${withval} must be an absolute directory" "$LINENO" 5 ;;
+ esac
+ configured_native_system_header_dir="${withval}"
+
+else
+ configured_native_system_header_dir=
+fi
+
+
+
# Check whether --with-build-sysroot was given.
if test "${with_build_sysroot+set}" = set; then :
withval=$with_build_sysroot; if test x"$withval" != x ; then
@@ -9001,7 +9014,7 @@ fi
for ac_func in times clock kill getrlimit setrlimit atoll atoq \
sysconf strsignal getrusage nl_langinfo \
gettimeofday mbstowcs wcswidth mmap setlocale \
- clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked
+ clearerr_unlocked feof_unlocked ferror_unlocked fflush_unlocked fgetc_unlocked fgets_unlocked fileno_unlocked fprintf_unlocked fputc_unlocked fputs_unlocked fread_unlocked fwrite_unlocked getchar_unlocked getc_unlocked putchar_unlocked putc_unlocked madvise
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -10394,6 +10407,8 @@ $as_echo "#define HAVE_LANGINFO_CODESET 1" >>confdefs.h
# We will need to find libiberty.h and ansidecl.h
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
+saved_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -I${srcdir} -I${srcdir}/../include"
for ac_func in getenv atol asprintf sbrk abort atof getcwd getwd \
strsignal strstr strverscmp \
errno snprintf vsnprintf vasprintf malloc realloc calloc \
@@ -10698,6 +10713,127 @@ fi
done
+# g++ on Solaris 10+ defines _XOPEN_SOURCE=600, which hides the madvise()
+# prototype.
+if test "$ENABLE_BUILD_WITH_CXX" = "yes"; then :
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ for ac_func in madvise
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if { as_var=gcc_cv_have_decl_$ac_func; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+ #include "ansidecl.h"
+ #include "system.h"
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+else
+ for ac_func in madvise
+do
+ ac_tr_decl=`$as_echo "HAVE_DECL_$ac_func" | $as_tr_cpp`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $ac_func is declared" >&5
+$as_echo_n "checking whether $ac_func is declared... " >&6; }
+if { as_var=gcc_cv_have_decl_$ac_func; eval "test \"\${$as_var+set}\" = set"; }; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#undef $ac_tr_decl
+#define $ac_tr_decl 1
+
+ #include "ansidecl.h"
+ #include "system.h"
+
+
+int
+main ()
+{
+#ifndef $ac_func
+char *(*pfn) = (char *(*)) $ac_func ;
+#endif
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "gcc_cv_have_decl_$ac_func=yes"
+else
+ eval "gcc_cv_have_decl_$ac_func=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+if eval "test \"`echo '$gcc_cv_have_decl_'$ac_func`\" = yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 1
+_ACEOF
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; } ; cat >>confdefs.h <<_ACEOF
+#define $ac_tr_decl 0
+_ACEOF
+
+fi
+
+done
+
+
+fi
+
# More time-related stuff.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct tms" >&5
$as_echo_n "checking for struct tms... " >&6; }
@@ -10774,8 +10910,9 @@ $as_echo "#define HAVE_CLOCK_T 1" >>confdefs.h
fi
-# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
+# Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
+CXXFLAGS="$saved_CXXFLAGS"
# Check whether --enable-initfini-array was given.
if test "${enable_initfini_array+set}" = set; then :
@@ -11145,6 +11282,12 @@ if test "$host_xm_file" != "$build_xm_file"; then
fi
fi
+if test -n "$configured_native_system_header_dir"; then
+ native_system_header_dir=$configured_native_system_header_dir
+fi
+NATIVE_SYSTEM_HEADER_DIR="$native_system_header_dir"
+
+
case ${host} in
powerpc*-*-darwin*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mcontext_t fields have underscores" >&5
@@ -11208,19 +11351,6 @@ if test x${thread_file} = x; then
thread_file=${target_thread_file}
fi
-# Make gthr-default.h if we have a thread file.
-gthread_flags=
-if test $thread_file != single; then
- echo "#include \"gthr-${thread_file}.h\"" > gthr-default.h-t
- if diff gthr-default.h-t gthr-default.h 2>/dev/null; then
- rm -f gthr-default.h-t
- else
- mv -f gthr-default.h-t gthr-default.h
- fi
- gthread_flags=-DHAVE_GTHR_DEFAULT
-fi
-
-
# --------
# UNSORTED
# --------
@@ -11642,13 +11772,6 @@ for f in $tm_file; do
esac
done
-libgcc_tm_file_list=
-libgcc_tm_include_list=
-for f in $libgcc_tm_file; do
- libgcc_tm_file_list="${libgcc_tm_file_list} \$(srcdir)/../libgcc/config/$f"
- libgcc_tm_include_list="${libgcc_tm_include_list} ../libgcc/config/$f"
-done
-
tm_p_file_list=
tm_p_include_list=
for f in $tm_p_file; do
@@ -17921,7 +18044,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 17924 "configure"
+#line 18047 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -18027,7 +18150,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 18030 "configure"
+#line 18153 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -26409,14 +26532,14 @@ if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x; then
elif test "x$with_sysroot" = x; then
target_header_dir="${exec_prefix}/${target_noncanonical}/sys-include"
elif test "x$with_build_sysroot" != "x"; then
- target_header_dir="${with_build_sysroot}/usr/include"
+ target_header_dir="${with_build_sysroot}${native_system_header_dir}"
elif test "x$with_sysroot" = xyes; then
- target_header_dir="${exec_prefix}/${target_noncanonical}/sys-root/usr/include"
+ target_header_dir="${exec_prefix}/${target_noncanonical}/sys-root${native_system_header_dir}"
else
- target_header_dir="${with_sysroot}/usr/include"
+ target_header_dir="${with_sysroot}${native_system_header_dir}"
fi
else
- target_header_dir=/usr/include
+ target_header_dir=${native_system_header_dir}
fi
# Test for stack protector support in target C library.
@@ -26483,6 +26606,7 @@ fi
$as_echo_n "checking sys/sdt.h in the target C library... " >&6; }
have_sys_sdt_h=no
if test -f $target_header_dir/sys/sdt.h; then
+ have_sys_sdt_h=yes
$as_echo "#define HAVE_SYS_SDT_H 1" >>confdefs.h
@@ -26805,22 +26929,6 @@ if test "${enable_version_specific_runtime_libs+set}" = set; then :
fi
-
-# Check whether --with-slibdir was given.
-if test "${with_slibdir+set}" = set; then :
- withval=$with_slibdir; slibdir="$with_slibdir"
-else
- if test "${enable_version_specific_runtime_libs+set}" = set; then
- slibdir='$(libsubdir)'
-elif test "$host" != "$target"; then
- slibdir='$(build_tooldir)/lib'
-else
- slibdir='$(libdir)'
-fi
-fi
-
-
-
# Substitute configuration variables
@@ -26884,10 +26992,6 @@ fi
-
-
-
-
# Echo link setup.
if test x${build} = x${host} ; then
if test x${host} = x${target} ; then
diff --git a/gcc/configure.ac b/gcc/configure.ac
index a7b94e64451..dd6cf2f17f3 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -725,6 +725,19 @@ AC_ARG_ENABLE(shared,
], [enable_shared=yes])
AC_SUBST(enable_shared)
+AC_ARG_WITH([native-system-header-dir],
+ [ --with-native-system-header-dir=dir
+ use dir as the directory to look for standard
+ system header files in. Defaults to /usr/include.],
+[
+ case ${with_native_system_header_dir} in
+ yes|no) AC_MSG_ERROR([bad value ${withval} given for --with-native-system-header-dir]) ;;
+ /* | [[A-Za-z]]:[[\\/]]*) ;;
+ *) AC_MSG_ERROR([--with-native-system-header-dir argument ${withval} must be an absolute directory]) ;;
+ esac
+ configured_native_system_header_dir="${withval}"
+], [configured_native_system_header_dir=])
+
AC_ARG_WITH(build-sysroot,
[AS_HELP_STRING([--with-build-sysroot=sysroot],
[use sysroot as the system root during the build])],
@@ -1027,7 +1040,7 @@ define(gcc_UNLOCKED_FUNCS, clearerr_unlocked feof_unlocked dnl
AC_CHECK_FUNCS(times clock kill getrlimit setrlimit atoll atoq \
sysconf strsignal getrusage nl_langinfo \
gettimeofday mbstowcs wcswidth mmap setlocale \
- gcc_UNLOCKED_FUNCS)
+ gcc_UNLOCKED_FUNCS madvise)
if test x$ac_cv_func_mbstowcs = xyes; then
AC_CACHE_CHECK(whether mbstowcs works, gcc_cv_func_mbstowcs_works,
@@ -1081,6 +1094,8 @@ AM_LANGINFO_CODESET
# We will need to find libiberty.h and ansidecl.h
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -I${srcdir} -I${srcdir}/../include"
+saved_CXXFLAGS="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -I${srcdir} -I${srcdir}/../include"
gcc_AC_CHECK_DECLS(getenv atol asprintf sbrk abort atof getcwd getwd \
strsignal strstr strverscmp \
errno snprintf vsnprintf vasprintf malloc realloc calloc \
@@ -1133,6 +1148,21 @@ gcc_AC_CHECK_DECLS(sigaltstack, , ,[
#include <signal.h>
])
+# g++ on Solaris 10+ defines _XOPEN_SOURCE=600, which hides the madvise()
+# prototype.
+AS_IF([test "$ENABLE_BUILD_WITH_CXX" = "yes"],
+ [AC_LANG_PUSH([C++])
+ gcc_AC_CHECK_DECLS(madvise, , ,[
+ #include "ansidecl.h"
+ #include "system.h"
+ ])
+ AC_LANG_POP([C++])],
+ [gcc_AC_CHECK_DECLS(madvise, , ,[
+ #include "ansidecl.h"
+ #include "system.h"
+ ])
+])
+
# More time-related stuff.
AC_CACHE_CHECK(for struct tms, ac_cv_struct_tms, [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@@ -1159,8 +1189,9 @@ if test $gcc_cv_type_clock_t = yes; then
[Define if <time.h> defines clock_t.])
fi
-# Restore CFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
+# Restore CFLAGS, CXXFLAGS from before the gcc_AC_NEED_DECLARATIONS tests.
CFLAGS="$saved_CFLAGS"
+CXXFLAGS="$saved_CXXFLAGS"
gcc_AC_INITFINI_ARRAY
@@ -1331,6 +1362,12 @@ if test "$host_xm_file" != "$build_xm_file"; then
fi
fi
+if test -n "$configured_native_system_header_dir"; then
+ native_system_header_dir=$configured_native_system_header_dir
+fi
+NATIVE_SYSTEM_HEADER_DIR="$native_system_header_dir"
+AC_SUBST(NATIVE_SYSTEM_HEADER_DIR)
+
case ${host} in
powerpc*-*-darwin*)
AC_CACHE_CHECK([whether mcontext_t fields have underscores],
@@ -1379,19 +1416,6 @@ if test x${thread_file} = x; then
thread_file=${target_thread_file}
fi
-# Make gthr-default.h if we have a thread file.
-gthread_flags=
-if test $thread_file != single; then
- echo "#include \"gthr-${thread_file}.h\"" > gthr-default.h-t
- if diff gthr-default.h-t gthr-default.h 2>/dev/null; then
- rm -f gthr-default.h-t
- else
- mv -f gthr-default.h-t gthr-default.h
- fi
- gthread_flags=-DHAVE_GTHR_DEFAULT
-fi
-AC_SUBST(gthread_flags)
-
# --------
# UNSORTED
# --------
@@ -1678,13 +1702,6 @@ for f in $tm_file; do
esac
done
-libgcc_tm_file_list=
-libgcc_tm_include_list=
-for f in $libgcc_tm_file; do
- libgcc_tm_file_list="${libgcc_tm_file_list} \$(srcdir)/../libgcc/config/$f"
- libgcc_tm_include_list="${libgcc_tm_include_list} ../libgcc/config/$f"
-done
-
tm_p_file_list=
tm_p_include_list=
for f in $tm_p_file; do
@@ -4517,14 +4534,14 @@ if test x$host != x$target || test "x$TARGET_SYSTEM_ROOT" != x; then
elif test "x$with_sysroot" = x; then
target_header_dir="${exec_prefix}/${target_noncanonical}/sys-include"
elif test "x$with_build_sysroot" != "x"; then
- target_header_dir="${with_build_sysroot}/usr/include"
+ target_header_dir="${with_build_sysroot}${native_system_header_dir}"
elif test "x$with_sysroot" = xyes; then
- target_header_dir="${exec_prefix}/${target_noncanonical}/sys-root/usr/include"
+ target_header_dir="${exec_prefix}/${target_noncanonical}/sys-root${native_system_header_dir}"
else
- target_header_dir="${with_sysroot}/usr/include"
+ target_header_dir="${with_sysroot}${native_system_header_dir}"
fi
else
- target_header_dir=/usr/include
+ target_header_dir=${native_system_header_dir}
fi
# Test for stack protector support in target C library.
@@ -4578,6 +4595,7 @@ GCC_TARGET_TEMPLATE([HAVE_SYS_SDT_H])
AC_MSG_CHECKING(sys/sdt.h in the target C library)
have_sys_sdt_h=no
if test -f $target_header_dir/sys/sdt.h; then
+ have_sys_sdt_h=yes
AC_DEFINE(HAVE_SYS_SDT_H, 1,
[Define if your target C library provides sys/sdt.h])
fi
@@ -4883,18 +4901,6 @@ AC_ARG_ENABLE(version-specific-runtime-libs,
[specify that runtime libraries should be
installed in a compiler-specific directory])])
-AC_ARG_WITH(slibdir,
-[AS_HELP_STRING([--with-slibdir=DIR], [shared libraries in DIR @<:@LIBDIR@:>@])],
-slibdir="$with_slibdir",
-if test "${enable_version_specific_runtime_libs+set}" = set; then
- slibdir='$(libsubdir)'
-elif test "$host" != "$target"; then
- slibdir='$(build_tooldir)/lib'
-else
- slibdir='$(libdir)'
-fi)
-AC_SUBST(slibdir)
-
# Substitute configuration variables
AC_SUBST(subdirs)
AC_SUBST(srcdir)
@@ -4921,7 +4927,6 @@ AC_SUBST(user_headers_inc_next_pre)
AC_SUBST(user_headers_inc_next_post)
AC_SUBST(extra_headers_list)
AC_SUBST(extra_objs)
-AC_SUBST(extra_parts)
AC_SUBST(extra_passes)
AC_SUBST(extra_programs)
AC_SUBST(float_h_file)
@@ -4943,12 +4948,9 @@ AC_SUBST(out_file)
AC_SUBST(out_object_file)
AC_SUBST(common_out_file)
AC_SUBST(common_out_object_file)
-AC_SUBST(thread_file)
AC_SUBST(tm_file_list)
AC_SUBST(tm_include_list)
AC_SUBST(tm_defines)
-AC_SUBST(libgcc_tm_file_list)
-AC_SUBST(libgcc_tm_include_list)
AC_SUBST(tm_p_file_list)
AC_SUBST(tm_p_include_list)
AC_SUBST(xm_file_list)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ca8566f0f5c..90651e6e540 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,391 @@
+2011-11-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50956
+ * typeck.c (build_const_cast_1): Fix -Wcast-qual for false
+ comp_ptr_ttypes_const.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Make-lang.in (g++spec.o): Pass SHLIB instead of SHLIB_LINK.
+
+2011-11-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/44277
+ * cvt.c (cp_convert_to_pointer): Warn for zero as null pointer
+ constant.
+ * typeck.c (cp_truthvalue_conversion): Handle pointers and member
+ function pointers under c_inhibit_evaluation_warnings; use
+ nullptr_node for data member pointers.
+ (cp_build_binary_op): Tweak, just forward to cp_convert op1,
+ either a nullptr_node or an integer_zero_node.
+ (build_ptrmemfunc): Use nullptr_node.
+ * init.c (build_zero_init_1): Likewise.
+
+2011-11-01 Jason Merrill <jason@redhat.com>
+
+ PR c++/50500
+ DR 1082
+ * search.c (lookup_fnfields_idx_nolazy): Split out from...
+ (lookup_fnfields_1): ...here.
+ (lookup_fnfields_slot_nolazy): Use it.
+ * cp-tree.h: Declare it.
+ * class.c (type_has_move_assign): Use it.
+ (type_has_user_declared_move_assign): Likewise.
+
+2011-10-31 Jason Merrill <jason@redhat.com>
+
+ PR c++/50920
+ * class.c (check_field_decl): Change c++0x in diags to c++11.
+ * error.c (maybe_warn_cpp0x): Likewise.
+ * parser.c (cp_parser_diagnose_invalid_type_name): Likewise.
+ * pt.c (check_default_tmpl_args): Likewise.
+
+2011-10-31 Diego Novillo <dnovillo@google.com>
+
+ * mangle.c (get_mangled_id): Factor from ...
+ (mangle_decl): ... here.
+ Call get_mangled_id.
+
+2011-10-25 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * NEWS (GCC 2.95): Refer to GNU/Linux instead of Linux.
+ (EGCS 1.0): Ditto.
+
+2011-10-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50901
+ * call.c (build_new_op_1): Handle ABS_EXPR together with the
+ other unary EXPR.
+
+2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ Revert:
+ 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50864
+ * pt.c (tsubst_copy_and_build): Fix qualified_name_lookup_error
+ call in case COMPONENT_REF.
+
+2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * pt.c (unify_pack_expansion): Initialize bad_old_arg and bad_new_arg.
+
+2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50864
+ * pt.c (tsubst_copy_and_build): Fix qualified_name_lookup_error
+ call in case COMPONENT_REF.
+
+2011-10-27 Jason Merrill <jason@redhat.com>
+
+ * semantics.c (cxx_eval_outermost_constant_expr): Check
+ cp_has_mutable_p.
+ (cxx_eval_component_reference): Check DECL_MUTABLE_P.
+
+2011-10-27 Roberto Agostino Vitillo <ravitillo@lbl.gov>
+
+ PR c++/30066
+ * decl2.c (determine_hidden_inline): New function.
+ (determine_visibility): fvisibility-inlines-hidden affects inline
+ functions.
+
+2011-10-27 Dodji Seketeli <dodji@redhat.com>
+
+ * cp-tree.h (DECL_DECLARES_TYPE_P): Fix comment.
+
+2011-10-26 Jason Merrill <jason@redhat.com>
+
+ * typeck.c (check_literal_operator_args): Avoid building types.
+
+2011-10-26 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++11 user-defined literals.
+ * cp-objcp-common.c: (cp_tree_size) Return size of USERDEF_LITERAL tree.
+ * cp-tree.h: (UDLIT_OP_*, UDLIT_OPER_P): Literal operator
+ name tools. New tree code for user-defined literals.
+ * cxx-pretty-print.h: (pp_cxx_userdef_literal) New.
+ * cxx-pretty-print.c: (pp_cxx_userdef_literal) New.
+ (pp_cxx_primary_expression, pp_cxx_expression): Use it.
+ * decl.c: (cp_tree_node_structure): Return new tree code.
+ (duplicate_decls): Check for raw vs. template operator conflicts.
+ (grokfndecl, grokdeclarator): New checks for literal operators.
+ * error.c: (dump_expr): Warn about user-defined literals
+ in C++98 mode. (dump_function_name): Pretty printing.
+ * mangle.c: (write_literal_operator_name): New.
+ (write_unqualified_id, write_unqualified_name): Use it.
+ * parser.c: (cp_parser_operator): Handle operator"".
+ (cp_parser_userdef_char_literal, cp_parser_userdef_numeric_literal,
+ cp_parser_userdef_string_literal): New.
+ (cp_parser_primary_expression): Handle new user-defined literal tokens
+ with new functions.
+ * semantics.c: (potential_constant_expression_1): Add
+ user-defined literals.
+ * typeck.c (check_raw_literal_operator,
+ check_literal_operator_args): New.
+
+2011-10-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * typeck.c (cp_build_addr_expr_1): Use BASELINK_P.
+ * class.c (instantiate_type): Likewise.
+ * pt.c (convert_nontype_argument_function, uses_template_parms,
+ tsubst_copy, resolve_nondeduced_context, type_dependent_expression_p):
+ Likewise.
+ * semantics.c (finish_decltype_type): Likewise.
+ * decl2.c (mark_used): Likewise.
+ * name-lookup.c (arg_assoc): Likewise.
+
+2011-10-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50870
+ * typeck.c (non_reference): Pass NULL_TREE through.
+
+2011-10-25 Jason Merrill <jason@redhat.com>
+
+ PR c++/50866
+ PR c++/41449
+ * semantics.c (maybe_cleanup_point_expr_void): No longer static.
+ * typeck2.c (split_nonconstant_init_1): Use it.
+ * cp-tree.h: Declare it.
+ * decl.c (wrap_cleanups_r): Stop at CLEANUP_POINT_EXPR.
+
+ PR c++/49996
+ * tree.c (stabilize_init): Stabilize scalar elements of a
+ CONSTRUCTOR, too.
+
+2011-10-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50858
+ * typeck.c (composite_pointer_type_r): Check return value of
+ composite_pointer_type_r for error_mark_node.
+
+2011-10-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50861
+ * pt.c (tsubst_copy_and_build): Check return value of
+ tsubst_copy_and_build for error_mark_node.
+
+2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50841
+ Revert:
+ 2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50810
+ * typeck2.c (check_narrowing): Adjust OPT_Wnarrowing diagnostics.
+ (digest_init_r): Call check_narrowing irrespective of the C++ dialect.
+ * decl.c (check_initializer): Likewise.
+ * semantics.c (finish_compound_literal): Likewise.
+
+2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50810
+ * typeck2.c (check_narrowing): Adjust OPT_Wnarrowing diagnostics.
+ (digest_init_r): Call check_narrowing irrespective of the C++ dialect.
+ * decl.c (check_initializer): Likewise.
+ * semantics.c (finish_compound_literal): Likewise.
+
+2011-10-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/45385
+ * init.c (build_vec_init): Early return error_mark_node if
+ maxindex is -1.
+
+2011-10-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/31423
+ * typeck2.c (cxx_incomplete_type_diagnostic): Improve error message
+ for invalid use of member function.
+
+2011-10-21 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR c++/50811
+ * parser.c (cp_parser_class_head): Parse virt-specifiers
+ regardless of whether an id is present
+
+2011-10-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/41449
+ * typeck2.c (split_nonconstant_init_1): Handle EH cleanup of
+ initialized subobjects.
+
+2011-10-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/13657
+ * class.c (instantiate_type): Fix error message.
+
+2011-10-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/50793
+ * tree.c (bot_manip): Propagate AGGR_INIT_ZERO_FIRST.
+
+2011-10-19 Roland Stigge <stigge@antcom.de>
+
+ PR translation/49704
+ * semantics.c (potential_constant_expression_1): Use "AST" instead of
+ "ast" in sorry message.
+
+2011-10-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38761
+ PR c++/40872
+ * decl.c (duplicate_decls, make_typename_type, grokdeclarator): Use
+ G_() in error message strings to facilitate translation.
+ * semantics.c (finish_id_expression): Likewise.
+ * parser.c (cp_parser_nested_name_specifier_opt,
+ cp_parser_parameter_declaration): Likewise.
+
+2011-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/50531
+ * pt.c (instantiate_decl): Recognize when a function defaulted
+ outside the class is already instantiated.
+
+ PR c++/50742
+ * decl.c (check_previous_goto_1): Handle using-decl.
+
+2011-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/50500
+ DR 1082
+ * class.c (type_has_user_declared_move_constructor): New.
+ (type_has_user_declared_move_assign): New.
+ (add_implicitly_declared_members): Add lazy copy ops
+ even if there's a move.
+ * method.c (lazily_declare_fn): Delete implicit copies
+ if there's a move.
+ (maybe_explain_implicit_delete): Explain this. Use inform rather
+ than error.
+ * cp-tree.h: Declare new fns.
+
+2011-10-18 Diego Novillo <dnovillo@google.com>
+
+ * parser.c: Remove ENABLE_CHECKING markers around debugging
+ routines.
+ (cp_lexer_dump_tokens): Add arguments START_TOKEN and CURR_TOKEN.
+ Make static
+ When printing CURR_TOKEN surround it in [[ ]].
+ Start printing at START_TOKEN.
+ Update all users.
+ (cp_debug_print_tree_if_set): New.
+ (cp_debug_print_context): New.
+ (cp_debug_print_context_stack): New.
+ (cp_debug_print_flag): New.
+ (cp_debug_print_unparsed_function): New.
+ (cp_debug_print_unparsed_queues): New.
+ (cp_debug_parser_tokens): New.
+ (cp_debug_parser): New.
+ (cp_lexer_start_debugging): Set cp_lexer_debug_stream to stderr.
+ (cp_lexer_stop_debugging): Set cp_lexer_debug_stream to NULL.
+ * parser.h (cp_lexer_dump_tokens): Remove declaration.
+ (cp_debug_parser): Declare.
+
+2011-10-17 Michael Spertus <mike_spertus@symantec.com>
+
+ * cp-tree.def: Add BASES as a new tree code.
+ * cp-tree.h (enum cp_trait_kind): Add CPTK_BASES, CPTK_DIRECT_BASES.
+ (BASES_TYPE, BASES_DIRECT): Define.
+ (calculate_bases, finish_bases, calculate_direct_bases): Declare.
+ * parser.c (cp_parser_trait_expr, cp_parser_template_argument_list,
+ (cp_parser_simple_type_specifier, cp_parser_save_nsdmi): Use them.
+ * pt.c (find_parameter_packs_r, tsubst_pack_expansion): Likewise.
+ * semantics.c (calculate_bases, finish_bases, calculate_direct_bases,
+ dfs_calculate_bases_pre, dfs_calculate_bases_post,
+ calculate_bases_helper): Define.
+
+2011-10-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/50736
+ * parser.c (cp_parser_lambda_introducer): Check for more
+ invalid captures.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/44524
+ * typeck.c (build_class_member_access_expr): Provide a better error
+ message for X.Y where X is a pointer to class type.
+ (finish_class_member_access_expr): Likewise.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * error.c (cp_diagnostic_starter): Pass the relevant location to
+ diagnostic_report_current_module.
+ (cp_diagnostic_finalizer): Call virt_loc_aware_diagnostic_finalizer.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/48489
+ * typeck.c (finish_class_member_access_expr): Fix error call
+ for TREE_CODE (access_path) == TREE_BINFO.
+
+2011-10-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50732
+ * semantics.c (finish_trait_expr): Do not try to instantiate the
+ the base type of an __is_base_of trait.
+ (check_trait_type): Return a tree; use complete_type_or_else.
+
+2011-10-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/50563
+ * parser.c (cp_parser_cache_group): Handle end==CPP_COMMA.
+ (cp_parser_save_nsdmi): Pass it.
+
+ PR c++/50707
+ * method.c (walk_field_subobs): Check for NSDMI before
+ complaining about uninitialized fields.
+
+ * pt.c (tsubst_decl) [FIELD_DECL]: Use void_zero_node
+ instead of error_mark_node as a placeholder.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38174
+ * call.c (add_builtin_candidate): If two pointers have a composite
+ pointer type, generate a single candidate with that type.
+
+2011-10-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/50614
+ * cp-tree.h (VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK): New.
+ (DECL_TEMPLATE_INFO): Use it.
+ * pt.c (tsubst_decl) [FIELD_DECL]: Set DECL_TEMPLATE_INFO
+ if the decl has an NSDMI.
+ * init.c (perform_member_init): Use it.
+
+ PR c++/50437
+ * cp-tree.h (struct tree_lambda_expr): Add closure field.
+ (LAMBDA_EXPR_CLOSURE): New.
+ * pt.c (tsubst_copy_and_build) [LAMBDA_EXPR]: Likewise.
+ * semantics.c (build_lambda_object): Use it instead of TREE_TYPE.
+ (begin_lambda_type, lambda_function, add_capture): Likewise.
+ (add_default_capture, lambda_expr_this_capture): Likewise.
+
+2011-10-13 Diego Novillo <dnovillo@google.com>
+
+ * cp-tree.h (struct language_function): Rename in_function_try_handler
+ to x_in_function_try_handler.
+ Rename in_base_initializer to x_in_base_initializer.
+ Update all users.
+
+2011-10-13 Diego Novillo <dnovillo@google.com>
+
+ * class.c (sorted_fields_type_new): Factor out of ...
+ (finish_struct_1): ... here.
+
+2011-10-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/50618
+ * init.c (expand_aggr_init_1): Don't zero-initialize virtual
+ bases of a base subobject.
+
+2011-10-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50594
+ * decl.c (cxx_init_decl_processing): Add
+ __attribute__((externally_visible)) to operator new and
+ operator delete library fn.
+
2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
* decl.c (duplicate_decls): Delete old interface with two parallel
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 6944ce972a8..650fc385096 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -55,7 +55,7 @@ c++: cc1plus$(exeext)
g++spec.o: $(srcdir)/cp/g++spec.c $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
$(CONFIG_H) $(OPTS_H)
- (SHLIB_LINK='$(SHLIB_LINK)'; \
+ (SHLIB='$(SHLIB)'; \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
$(INCLUDES) $(srcdir)/cp/g++spec.c)
diff --git a/gcc/cp/NEWS b/gcc/cp/NEWS
index 79a1a421b19..ed316d5a89b 100644
--- a/gcc/cp/NEWS
+++ b/gcc/cp/NEWS
@@ -168,7 +168,7 @@
* Unused virtual functions can be discarded on some targets by specifying
-ffunction-sections -fvtable-gc to the compiler and --gc-sections to the
- linker. Unfortunately, this only works on Linux if you're linking
+ linker. Unfortunately, this only works on GNU/Linux if you're linking
statically.
* Lots of bugs stomped.
@@ -343,7 +343,7 @@
translation units.
* -fvtable-thunks is supported for all targets, and is the default for
- Linux with glibc 2.x (also called libc 6.x).
+ GNU/Linux with glibc 2.x (also called libc 6.x).
* bool is now always the same size as another built-in type. Previously,
a 64-bit RISC target using a 32-bit ABI would have 32-bit pointers and a
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 7219afe8f59..439a1fe7c4f 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2582,6 +2582,21 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
|| MAYBE_CLASS_TYPE_P (type1)
|| TREE_CODE (type1) == ENUMERAL_TYPE))
{
+ if (TYPE_PTR_P (type1) || TYPE_PTR_TO_MEMBER_P (type1))
+ {
+ tree cptype = composite_pointer_type (type1, type2,
+ error_mark_node,
+ error_mark_node,
+ CPO_CONVERSION,
+ tf_none);
+ if (cptype != error_mark_node)
+ {
+ build_builtin_candidate
+ (candidates, fnname, cptype, cptype, args, argtypes, flags);
+ return;
+ }
+ }
+
build_builtin_candidate
(candidates, fnname, type1, type1, args, argtypes, flags);
build_builtin_candidate
@@ -5208,6 +5223,7 @@ build_new_op_1 (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
case POSTDECREMENT_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
+ case ABS_EXPR:
return cp_build_unary_op (code, arg1, candidates != 0, complain);
case ARRAY_REF:
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 2df9177e47e..41d182a4ca8 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2736,13 +2736,12 @@ add_implicitly_declared_members (tree t,
If a class definition does not explicitly declare a copy
constructor, one is declared implicitly. */
- if (! TYPE_HAS_COPY_CTOR (t) && ! TYPE_FOR_JAVA (t)
- && !type_has_move_constructor (t))
+ if (! TYPE_HAS_COPY_CTOR (t) && ! TYPE_FOR_JAVA (t))
{
TYPE_HAS_COPY_CTOR (t) = 1;
TYPE_HAS_CONST_COPY_CTOR (t) = !cant_have_const_cctor;
CLASSTYPE_LAZY_COPY_CTOR (t) = 1;
- if (cxx_dialect >= cxx0x)
+ if (cxx_dialect >= cxx0x && !type_has_move_constructor (t))
CLASSTYPE_LAZY_MOVE_CTOR (t) = 1;
}
@@ -2750,13 +2749,12 @@ add_implicitly_declared_members (tree t,
when it is needed. For now, just record whether or not the type
of the parameter to the assignment operator will be a const or
non-const reference. */
- if (!TYPE_HAS_COPY_ASSIGN (t) && !TYPE_FOR_JAVA (t)
- && !type_has_move_assign (t))
+ if (!TYPE_HAS_COPY_ASSIGN (t) && !TYPE_FOR_JAVA (t))
{
TYPE_HAS_COPY_ASSIGN (t) = 1;
TYPE_HAS_CONST_COPY_ASSIGN (t) = !cant_have_const_assignment;
CLASSTYPE_LAZY_COPY_ASSIGN (t) = 1;
- if (cxx_dialect >= cxx0x)
+ if (cxx_dialect >= cxx0x && !type_has_move_assign (t))
CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 1;
}
@@ -2926,7 +2924,7 @@ check_field_decl (tree field,
if (!warned && errorcount > oldcount)
{
inform (DECL_SOURCE_LOCATION (field), "unrestricted unions "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
warned = true;
}
}
@@ -4487,7 +4485,7 @@ type_has_move_assign (tree t)
lazily_declare_fn (sfk_move_assignment, t);
}
- for (fns = lookup_fnfields_slot (t, ansi_assopname (NOP_EXPR));
+ for (fns = lookup_fnfields_slot_nolazy (t, ansi_assopname (NOP_EXPR));
fns; fns = OVL_NEXT (fns))
if (move_fn_p (OVL_CURRENT (fns)))
return true;
@@ -4495,6 +4493,54 @@ type_has_move_assign (tree t)
return false;
}
+/* Returns true iff class T has a move constructor that was explicitly
+ declared in the class body. Note that this is different from
+ "user-provided", which doesn't include functions that are defaulted in
+ the class. */
+
+bool
+type_has_user_declared_move_constructor (tree t)
+{
+ tree fns;
+
+ if (CLASSTYPE_LAZY_MOVE_CTOR (t))
+ return false;
+
+ if (!CLASSTYPE_METHOD_VEC (t))
+ return false;
+
+ for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (move_fn_p (fn) && !DECL_ARTIFICIAL (fn))
+ return true;
+ }
+
+ return false;
+}
+
+/* Returns true iff class T has a move assignment operator that was
+ explicitly declared in the class body. */
+
+bool
+type_has_user_declared_move_assign (tree t)
+{
+ tree fns;
+
+ if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
+ return false;
+
+ for (fns = lookup_fnfields_slot_nolazy (t, ansi_assopname (NOP_EXPR));
+ fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ if (move_fn_p (fn) && !DECL_ARTIFICIAL (fn))
+ return true;
+ }
+
+ return false;
+}
+
/* Nonzero if we need to build up a constructor call when initializing an
object of this class, either because it has a user-provided constructor
or because it doesn't have a default constructor (so we need to give an
@@ -5663,6 +5709,22 @@ determine_key_method (tree type)
return;
}
+
+/* Allocate and return an instance of struct sorted_fields_type with
+ N fields. */
+
+static struct sorted_fields_type *
+sorted_fields_type_new (int n)
+{
+ struct sorted_fields_type *sft;
+ sft = ggc_alloc_sorted_fields_type (sizeof (struct sorted_fields_type)
+ + n * sizeof (tree));
+ sft->len = n;
+
+ return sft;
+}
+
+
/* Perform processing required when the definition of T (a class type)
is complete. */
@@ -5792,9 +5854,7 @@ finish_struct_1 (tree t)
n_fields = count_fields (TYPE_FIELDS (t));
if (n_fields > 7)
{
- struct sorted_fields_type *field_vec = ggc_alloc_sorted_fields_type
- (sizeof (struct sorted_fields_type) + n_fields * sizeof (tree));
- field_vec->len = n_fields;
+ struct sorted_fields_type *field_vec = sorted_fields_type_new (n_fields);
add_fields_to_record_type (TYPE_FIELDS (t), field_vec, 0);
qsort (field_vec->elts, n_fields, sizeof (tree),
field_decl_cmp);
@@ -6807,13 +6867,13 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
else
{
if (flags & tf_error)
- error ("argument of type %qT does not match %qT",
- TREE_TYPE (rhs), lhstype);
+ error ("cannot convert %qE from type %qT to type %qT",
+ rhs, TREE_TYPE (rhs), lhstype);
return error_mark_node;
}
}
- if (TREE_CODE (rhs) == BASELINK)
+ if (BASELINK_P (rhs))
{
access_path = BASELINK_ACCESS_BINFO (rhs);
rhs = BASELINK_FUNCTIONS (rhs);
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 035fdcd2f4e..a957a0303ac 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -100,6 +100,8 @@ cp_tree_size (enum tree_code code)
case TEMPLATE_INFO: return sizeof (struct tree_template_info);
+ case USERDEF_LITERAL: return sizeof (struct tree_userdef_literal);
+
default:
gcc_unreachable ();
}
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index be29870d93e..4eec9f97c7d 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -462,6 +462,10 @@ DEFTREECODE (DECLTYPE_TYPE, "decltype_type", tcc_type, 0)
UNDERLYING_TYPE_TYPE is the type in question. */
DEFTREECODE (UNDERLYING_TYPE, "underlying_type", tcc_type, 0)
+/* A type designated by one of the bases type traits.
+ BASES_TYPE is the type in question. */
+DEFTREECODE (BASES, "bases", tcc_type, 0)
+
/* Used to represent the template information stored by template
specializations.
The accessors are:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index b53accfed65..ac42e0e1572 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -201,6 +201,9 @@ c-common.h, not after.
#define VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK(NODE) \
TREE_CHECK4(NODE,VAR_DECL,FUNCTION_DECL,TYPE_DECL,TEMPLATE_DECL)
+#define VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK(NODE) \
+ TREE_CHECK5(NODE,VAR_DECL,FIELD_DECL,FUNCTION_DECL,TYPE_DECL,TEMPLATE_DECL)
+
#define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
@@ -397,7 +400,9 @@ typedef enum cpp0x_warn_str
/* override controls, override/final */
CPP0X_OVERRIDE_CONTROLS,
/* non-static data member initializers */
- CPP0X_NSDMI
+ CPP0X_NSDMI,
+ /* user defined literals */
+ CPP0X_USER_DEFINED_LITERALS
} cpp0x_warn_str;
/* The various kinds of operation used by composite_pointer_type. */
@@ -561,6 +566,8 @@ struct GTY (()) tree_argument_pack_select {
typedef enum cp_trait_kind
{
+ CPTK_BASES,
+ CPTK_DIRECT_BASES,
CPTK_HAS_NOTHROW_ASSIGN,
CPTK_HAS_NOTHROW_CONSTRUCTOR,
CPTK_HAS_NOTHROW_COPY,
@@ -671,6 +678,12 @@ enum cp_lambda_default_capture_mode_type {
#define LAMBDA_EXPR_PENDING_PROXIES(NODE) \
(((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->pending_proxies)
+/* The closure type of the lambda. Note that the TREE_TYPE of a
+ LAMBDA_EXPR is always NULL_TREE, because we need to instantiate the
+ LAMBDA_EXPR in order to instantiate the type. */
+#define LAMBDA_EXPR_CLOSURE(NODE) \
+ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->closure)
+
struct GTY (()) tree_lambda_expr
{
struct tree_typed typed;
@@ -678,6 +691,7 @@ struct GTY (()) tree_lambda_expr
tree this_capture;
tree return_type;
tree extra_scope;
+ tree closure;
VEC(tree,gc)* pending_proxies;
location_t locus;
enum cp_lambda_default_capture_mode_type default_capture_mode;
@@ -728,6 +742,7 @@ enum cp_tree_node_structure_enum {
TS_CP_TRAIT_EXPR,
TS_CP_LAMBDA_EXPR,
TS_CP_TEMPLATE_INFO,
+ TS_CP_USERDEF_LITERAL,
LAST_TS_CP_ENUM
};
@@ -753,6 +768,8 @@ union GTY((desc ("cp_tree_node_structure (&%h)"),
lambda_expression;
struct tree_template_info GTY ((tag ("TS_CP_TEMPLATE_INFO")))
template_info;
+ struct tree_userdef_literal GTY ((tag ("TS_CP_USERDEF_LITERAL")))
+ userdef_literal;
};
@@ -1053,8 +1070,8 @@ struct GTY(()) language_function {
BOOL_BITFIELD returns_value : 1;
BOOL_BITFIELD returns_null : 1;
BOOL_BITFIELD returns_abnormally : 1;
- BOOL_BITFIELD in_function_try_handler : 1;
- BOOL_BITFIELD in_base_initializer : 1;
+ BOOL_BITFIELD x_in_function_try_handler : 1;
+ BOOL_BITFIELD x_in_base_initializer : 1;
/* True if this function can throw an exception. */
BOOL_BITFIELD can_throw : 1;
@@ -1121,9 +1138,9 @@ struct GTY(()) language_function {
cp_function_chain->returns_abnormally
/* Nonzero if we are processing a base initializer. Zero elsewhere. */
-#define in_base_initializer cp_function_chain->in_base_initializer
+#define in_base_initializer cp_function_chain->x_in_base_initializer
-#define in_function_try_handler cp_function_chain->in_function_try_handler
+#define in_function_try_handler cp_function_chain->x_in_function_try_handler
/* Expression always returned from function, or error_mark_node
otherwise, for use by the automatic named return value optimization. */
@@ -2549,7 +2566,7 @@ extern void decl_shadowed_for_var_insert (tree, tree);
global function f. In this case, DECL_TEMPLATE_INFO for S<int>::f
will be non-NULL, but DECL_USE_TEMPLATE will be zero. */
#define DECL_TEMPLATE_INFO(NODE) \
- (DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_OR_FUNCTION_DECL_CHECK (NODE)) \
+ (DECL_LANG_SPECIFIC (VAR_TEMPL_TYPE_FIELD_OR_FUNCTION_DECL_CHECK (NODE)) \
->u.min.template_info)
/* For a VAR_DECL, indicates that the variable is actually a
@@ -2694,7 +2711,10 @@ extern void decl_shadowed_for_var_insert (tree, tree);
template <class T> struct S { friend void f<int>(int, double); }
the DECL_TI_TEMPLATE will be an IDENTIFIER_NODE for `f' and the
- DECL_TI_ARGS will be {int}. */
+ DECL_TI_ARGS will be {int}.
+
+ For a FIELD_DECL with a non-static data member initializer, this value
+ is the FIELD_DECL it was instantiated from. */
#define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE))
/* The template arguments used to obtain this decl from the most
@@ -3420,6 +3440,13 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define UNDERLYING_TYPE_TYPE(NODE) \
(TYPE_VALUES_RAW (UNDERLYING_TYPE_CHECK (NODE)))
+/* The type in question for BASES. */
+#define BASES_TYPE(NODE) \
+ (TYPE_VALUES_RAW (BASES_CHECK (NODE)))
+
+#define BASES_DIRECT(NODE) \
+ TREE_LANG_FLAG_0 (BASES_CHECK (NODE))
+
/* The expression in question for a DECLTYPE_TYPE. */
#define DECLTYPE_TYPE_EXPR(NODE) (TYPE_VALUES_RAW (DECLTYPE_TYPE_CHECK (NODE)))
@@ -3598,7 +3625,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
&& DECL_TEMPLATE_RESULT (NODE) != NULL_TREE \
&& DECL_IMPLICIT_TYPEDEF_P (DECL_TEMPLATE_RESULT (NODE)))
-/* Nonzero if NODE which declares a type. */
+/* Nonzero for a NODE which declares a type. */
#define DECL_DECLARES_TYPE_P(NODE) \
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
@@ -4206,6 +4233,17 @@ extern GTY(()) VEC(tree,gc) *local_classes;
LAMBDANAME_PREFIX, \
sizeof (LAMBDANAME_PREFIX) - 1))
+#define UDLIT_OP_ANSI_PREFIX "operator\"\" "
+#define UDLIT_OP_ANSI_FORMAT UDLIT_OP_ANSI_PREFIX "%s"
+#define UDLIT_OP_MANGLED_PREFIX "li"
+#define UDLIT_OP_MANGLED_FORMAT UDLIT_OP_MANGLED_PREFIX "%s"
+#define UDLIT_OPER_P(ID_NODE) \
+ (!strncmp (IDENTIFIER_POINTER (ID_NODE), \
+ UDLIT_OP_ANSI_PREFIX, \
+ sizeof (UDLIT_OP_ANSI_PREFIX) - 1))
+#define UDLIT_OP_SUFFIX(ID_NODE) \
+ (IDENTIFIER_POINTER (ID_NODE) + sizeof (UDLIT_OP_ANSI_PREFIX) - 1)
+
#if !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL)
#define VTABLE_NAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[1] == 'v' \
@@ -4848,6 +4886,8 @@ extern bool type_has_constexpr_default_constructor (tree);
extern bool type_has_virtual_destructor (tree);
extern bool type_has_move_constructor (tree);
extern bool type_has_move_assign (tree);
+extern bool type_has_user_declared_move_constructor (tree);
+extern bool type_has_user_declared_move_assign(tree);
extern bool type_build_ctor_call (tree);
extern void explain_non_literal_class (tree);
extern void defaulted_late_check (tree);
@@ -5288,6 +5328,7 @@ extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_field (tree, tree, int, bool);
extern int lookup_fnfields_1 (tree, tree);
extern tree lookup_fnfields_slot (tree, tree);
+extern tree lookup_fnfields_slot_nolazy (tree, tree);
extern int class_method_index_for_fn (tree, tree);
extern tree lookup_fnfields (tree, tree, int);
extern tree lookup_member (tree, tree, int, bool);
@@ -5348,6 +5389,7 @@ extern int stmts_are_full_exprs_p (void);
extern void init_cp_semantics (void);
extern tree do_poplevel (tree);
extern void add_decl_expr (tree);
+extern tree maybe_cleanup_point_expr_void (tree);
extern tree finish_expr_stmt (tree);
extern tree begin_if_stmt (void);
extern void finish_if_stmt_cond (tree, tree);
@@ -5449,6 +5491,9 @@ extern tree finish_id_expression (tree, tree, tree,
location_t);
extern tree finish_typeof (tree);
extern tree finish_underlying_type (tree);
+extern tree calculate_bases (tree);
+extern tree finish_bases (tree, bool);
+extern tree calculate_direct_bases (tree);
extern tree finish_offsetof (tree);
extern void finish_decl_cleanup (tree, tree);
extern void finish_eh_cleanup (tree);
@@ -5731,6 +5776,8 @@ extern tree convert_ptrmem (tree, tree, bool, bool,
extern int lvalue_or_else (tree, enum lvalue_use,
tsubst_flags_t);
extern void check_template_keyword (tree);
+extern bool check_raw_literal_operator (const_tree decl);
+extern bool check_literal_operator_args (const_tree, bool *, bool *);
/* in typeck2.c */
extern void require_complete_eh_spec_types (tree, tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 3e618d320ad..8570e3d4502 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -198,6 +198,11 @@ cp_convert_to_pointer (tree type, tree expr)
if (null_ptr_cst_p (expr))
{
+ if (c_inhibit_evaluation_warnings == 0
+ && !NULLPTR_TYPE_P (TREE_TYPE (expr)))
+ warning (OPT_Wzero_as_null_pointer_constant,
+ "zero as null pointer constant");
+
if (TYPE_PTRMEMFUNC_P (type))
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
/*c_cast_p=*/false, tf_warning_or_error);
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 708afc8cdc2..55cb64b21e4 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -367,6 +367,17 @@ pp_cxx_id_expression (cxx_pretty_printer *pp, tree t)
pp_cxx_unqualified_id (pp, t);
}
+/* user-defined literal:
+ literal ud-suffix */
+
+void
+pp_cxx_userdef_literal (cxx_pretty_printer *pp, tree t)
+{
+ pp_cxx_constant (pp, USERDEF_LITERAL_VALUE (t));
+ pp_cxx_id_expression (pp, USERDEF_LITERAL_SUFFIX_ID (t));
+}
+
+
/* primary-expression:
literal
this
@@ -413,6 +424,10 @@ pp_cxx_primary_expression (cxx_pretty_printer *pp, tree t)
pp_cxx_constant (pp, t);
break;
+ case USERDEF_LITERAL:
+ pp_cxx_userdef_literal (pp, t);
+ break;
+
case BASELINK:
t = BASELINK_FUNCTIONS (t);
case VAR_DECL:
@@ -1024,6 +1039,10 @@ pp_cxx_expression (cxx_pretty_printer *pp, tree t)
pp_cxx_constant (pp, t);
break;
+ case USERDEF_LITERAL:
+ pp_cxx_userdef_literal (pp, t);
+ break;
+
case RESULT_DECL:
pp_cxx_unqualified_id (pp, t);
break;
diff --git a/gcc/cp/cxx-pretty-print.h b/gcc/cp/cxx-pretty-print.h
index d12506e62fe..bb9fec1c1bd 100644
--- a/gcc/cp/cxx-pretty-print.h
+++ b/gcc/cp/cxx-pretty-print.h
@@ -74,5 +74,7 @@ void pp_cxx_canonical_template_parameter (cxx_pretty_printer *, tree);
void pp_cxx_trait_expression (cxx_pretty_printer *, tree);
void pp_cxx_va_arg_expression (cxx_pretty_printer *, tree);
void pp_cxx_offsetof_expression (cxx_pretty_printer *, tree);
+void pp_cxx_userdef_literal (cxx_pretty_printer *, tree);
+
#endif /* GCC_CXX_PRETTY_PRINT_H */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c8f325548cb..860556c21a9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1203,6 +1203,21 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|| TREE_TYPE (olddecl) == error_mark_node)
return error_mark_node;
+ if (UDLIT_OPER_P (DECL_NAME (newdecl))
+ && UDLIT_OPER_P (DECL_NAME (olddecl)))
+ {
+ if (TREE_CODE (newdecl) == TEMPLATE_DECL
+ && TREE_CODE (olddecl) != TEMPLATE_DECL
+ && check_raw_literal_operator (olddecl))
+ error ("literal operator template %q+D conflicts with"
+ " raw literal operator %qD", newdecl, olddecl);
+ else if (TREE_CODE (newdecl) != TEMPLATE_DECL
+ && TREE_CODE (olddecl) == TEMPLATE_DECL
+ && check_raw_literal_operator (newdecl))
+ error ("raw literal operator %q+D conflicts with"
+ " literal operator template %qD", newdecl, olddecl);
+ }
+
if (DECL_P (olddecl)
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1542,8 +1557,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
error_at (DECL_SOURCE_LOCATION (newdecl), errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
error ((DECL_INITIAL (olddecl) && namespace_bindings_p ())
- ? "%q+#D previously defined here"
- : "%q+#D previously declared here", olddecl);
+ ? G_("%q+#D previously defined here")
+ : G_("%q+#D previously declared here"), olddecl);
return error_mark_node;
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -2683,7 +2698,8 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
tree new_decls, old_decls = (b == level ? names : NULL_TREE);
for (new_decls = b->names; new_decls != old_decls;
- new_decls = DECL_CHAIN (new_decls))
+ new_decls = (DECL_P (new_decls) ? DECL_CHAIN (new_decls)
+ : TREE_CHAIN (new_decls)))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
@@ -3235,8 +3251,8 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
if (!t)
{
if (complain & tf_error)
- error (want_template ? "no class template named %q#T in %q#T"
- : "no type named %q#T in %q#T", name, context);
+ error (want_template ? G_("no class template named %q#T in %q#T")
+ : G_("no type named %q#T in %q#T"), name, context);
return error_mark_node;
}
@@ -3654,7 +3670,7 @@ cxx_init_decl_processing (void)
current_lang_name = lang_name_cplusplus;
{
- tree newattrs;
+ tree newattrs, extvisattr;
tree newtype, deltype;
tree ptr_ftype_sizetype;
tree new_eh_spec;
@@ -3684,12 +3700,15 @@ cxx_init_decl_processing (void)
/* Ensure attribs.c is initialized. */
init_attributes ();
- newattrs
- = build_tree_list (get_identifier ("alloc_size"),
- build_tree_list (NULL_TREE, integer_one_node));
+ extvisattr = build_tree_list (get_identifier ("externally_visible"),
+ NULL_TREE);
+ newattrs = tree_cons (get_identifier ("alloc_size"),
+ build_tree_list (NULL_TREE, integer_one_node),
+ extvisattr);
newtype = cp_build_type_attribute_variant (ptr_ftype_sizetype, newattrs);
newtype = build_exception_variant (newtype, new_eh_spec);
- deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
+ deltype = cp_build_type_attribute_variant (void_ftype_ptr, extvisattr);
+ deltype = build_exception_variant (deltype, empty_except_spec);
push_cp_library_fn (NEW_EXPR, newtype);
push_cp_library_fn (VEC_NEW_EXPR, newtype);
global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
@@ -5714,7 +5733,9 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
static tree
wrap_cleanups_r (tree *stmt_p, int *walk_subtrees, void *data)
{
- if (TYPE_P (*stmt_p))
+ /* Stop at types or full-expression boundaries. */
+ if (TYPE_P (*stmt_p)
+ || TREE_CODE (*stmt_p) == CLEANUP_POINT_EXPR)
{
*walk_subtrees = 0;
return NULL_TREE;
@@ -7339,6 +7360,47 @@ grokfndecl (tree ctype,
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))
&& !grok_op_properties (decl, /*complain=*/true))
return NULL_TREE;
+ else if (UDLIT_OPER_P (DECL_NAME (decl)))
+ {
+ bool long_long_unsigned_p;
+ bool long_double_p;
+ const char *suffix = NULL;
+ /* [over.literal]/6: Literal operators shall not have C linkage. */
+ if (DECL_LANGUAGE (decl) == lang_c)
+ {
+ error ("literal operator with C linkage");
+ return NULL_TREE;
+ }
+
+ if (DECL_NAMESPACE_SCOPE_P (decl))
+ {
+ if (!check_literal_operator_args (decl, &long_long_unsigned_p,
+ &long_double_p))
+ {
+ error ("%qD has invalid argument list", decl);
+ return NULL_TREE;
+ }
+
+ suffix = UDLIT_OP_SUFFIX (DECL_NAME (decl));
+ if (long_long_unsigned_p)
+ {
+ if (cpp_interpret_int_suffix (suffix, strlen (suffix)))
+ warning (0, "integer suffix %<%s%>"
+ " shadowed by implementation", suffix);
+ }
+ else if (long_double_p)
+ {
+ if (cpp_interpret_float_suffix (suffix, strlen (suffix)))
+ warning (0, "floating point suffix %<%s%>"
+ " shadowed by implementation", suffix);
+ }
+ }
+ else
+ {
+ error ("%qD must be a non-member function", decl);
+ return NULL_TREE;
+ }
+ }
if (funcdef_flag)
/* Make the init_value nonzero so pushdecl knows this is not
@@ -8531,6 +8593,15 @@ grokdeclarator (const cp_declarator *declarator,
return error_mark_node;
}
+ if (dname
+ && TREE_CODE (dname) == IDENTIFIER_NODE
+ && UDLIT_OPER_P (dname)
+ && innermost_code != cdk_function)
+ {
+ error ("declaration of %qD as non-function", dname);
+ return error_mark_node;
+ }
+
if (dname && IDENTIFIER_OPNAME_P (dname))
{
if (declspecs->specs[(int)ds_typedef])
@@ -9139,13 +9210,13 @@ grokdeclarator (const cp_declarator *declarator,
virtual. A constructor may not be static. */
if (staticp == 2)
error ((flags == DTOR_FLAG)
- ? "destructor cannot be static member function"
- : "constructor cannot be static member function");
+ ? G_("destructor cannot be static member function")
+ : G_("constructor cannot be static member function"));
if (memfn_quals)
{
error ((flags == DTOR_FLAG)
- ? "destructors may not be cv-qualified"
- : "constructors may not be cv-qualified");
+ ? G_("destructors may not be cv-qualified")
+ : G_("constructors may not be cv-qualified"));
memfn_quals = TYPE_UNQUALIFIED;
}
@@ -9498,8 +9569,10 @@ grokdeclarator (const cp_declarator *declarator,
&& (!friendp || funcdef_flag))
{
error (funcdef_flag
- ? "cannot define member function %<%T::%s%> within %<%T%>"
- : "cannot declare member function %<%T::%s%> within %<%T%>",
+ ? G_("cannot define member function %<%T::%s%> "
+ "within %<%T%>")
+ : G_("cannot declare member function %<%T::%s%> "
+ "within %<%T%>"),
ctype, name, current_class_type);
return error_mark_node;
}
@@ -10219,8 +10292,8 @@ grokdeclarator (const cp_declarator *declarator,
|| sfk == sfk_destructor)
{
error (funcdef_flag
- ? "%qs defined in a non-class scope"
- : "%qs declared in a non-class scope", name);
+ ? G_("%qs defined in a non-class scope")
+ : G_("%qs declared in a non-class scope"), name);
sfk = sfk_none;
}
}
@@ -13746,6 +13819,7 @@ cp_tree_node_structure (union lang_tree_node * t)
case TRAIT_EXPR: return TS_CP_TRAIT_EXPR;
case LAMBDA_EXPR: return TS_CP_LAMBDA_EXPR;
case TEMPLATE_INFO: return TS_CP_TEMPLATE_INFO;
+ case USERDEF_LITERAL: return TS_CP_USERDEF_LITERAL;
default: return TS_CP_GENERIC;
}
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 6e5f7cc7d75..be9044b9e67 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -86,6 +86,7 @@ static void write_out_vars (tree);
static void import_export_class (tree);
static tree get_guard_bits (tree);
static void determine_visibility_from_class (tree, tree);
+static bool determine_hidden_inline (tree);
static bool decl_defined_p (tree);
/* A list of static class variables. This is needed, because a
@@ -2088,14 +2089,29 @@ determine_visibility (tree decl)
containing function by default, except that
-fvisibility-inlines-hidden doesn't affect them. */
tree fn = DECL_CONTEXT (decl);
- if (DECL_VISIBILITY_SPECIFIED (fn) || ! DECL_CLASS_SCOPE_P (fn))
+ if (DECL_VISIBILITY_SPECIFIED (fn))
{
DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
DECL_VISIBILITY_SPECIFIED (decl) =
DECL_VISIBILITY_SPECIFIED (fn);
}
else
- determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+ {
+ if (DECL_CLASS_SCOPE_P (fn))
+ determine_visibility_from_class (decl, DECL_CONTEXT (fn));
+ else if (determine_hidden_inline (fn))
+ {
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) =
+ visibility_options.inpragma;
+ }
+ else
+ {
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn);
+ DECL_VISIBILITY_SPECIFIED (decl) =
+ DECL_VISIBILITY_SPECIFIED (fn);
+ }
+ }
/* Local classes in templates have CLASSTYPE_USE_TEMPLATE set,
but have no TEMPLATE_INFO, so don't try to check it. */
@@ -2134,10 +2150,15 @@ determine_visibility (tree decl)
on their template unless they override it with an attribute. */;
else if (! DECL_VISIBILITY_SPECIFIED (decl))
{
- /* Set default visibility to whatever the user supplied with
- #pragma GCC visibility or a namespace visibility attribute. */
- DECL_VISIBILITY (decl) = default_visibility;
- DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ if (determine_hidden_inline (decl))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else
+ {
+ /* Set default visibility to whatever the user supplied with
+ #pragma GCC visibility or a namespace visibility attribute. */
+ DECL_VISIBILITY (decl) = default_visibility;
+ DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+ }
}
}
@@ -2157,9 +2178,15 @@ determine_visibility (tree decl)
if (!DECL_VISIBILITY_SPECIFIED (decl))
{
- DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
- DECL_VISIBILITY_SPECIFIED (decl)
- = DECL_VISIBILITY_SPECIFIED (pattern);
+ if (!DECL_VISIBILITY_SPECIFIED (pattern)
+ && determine_hidden_inline (decl))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else
+ {
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (pattern);
+ DECL_VISIBILITY_SPECIFIED (decl)
+ = DECL_VISIBILITY_SPECIFIED (pattern);
+ }
}
/* FIXME should TMPL_ARGS_DEPTH really return 1 for null input? */
@@ -2214,15 +2241,7 @@ determine_visibility_from_class (tree decl, tree class_type)
if (DECL_VISIBILITY_SPECIFIED (decl))
return;
- if (visibility_options.inlines_hidden
- /* Don't do this for inline templates; specializations might not be
- inline, and we don't want them to inherit the hidden
- visibility. We'll set it here for all inline instantiations. */
- && !processing_template_decl
- && TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (decl)
- && (! DECL_LANG_SPECIFIC (decl)
- || ! DECL_EXPLICIT_INSTANTIATION (decl)))
+ if (determine_hidden_inline (decl))
DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
else
{
@@ -2247,6 +2266,23 @@ determine_visibility_from_class (tree decl, tree class_type)
targetm.cxx.determine_class_data_visibility (decl);
}
+/* Returns true iff DECL is an inline that should get hidden visibility
+ because of -fvisibility-inlines-hidden. */
+
+static bool
+determine_hidden_inline (tree decl)
+{
+ return (visibility_options.inlines_hidden
+ /* Don't do this for inline templates; specializations might not be
+ inline, and we don't want them to inherit the hidden
+ visibility. We'll set it here for all inline instantiations. */
+ && !processing_template_decl
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl)
+ && (! DECL_LANG_SPECIFIC (decl)
+ || ! DECL_EXPLICIT_INSTANTIATION (decl)));
+}
+
/* Constrain the visibility of a class TYPE based on the visibility of its
field types. Warn if any fields require lesser visibility. */
@@ -4174,7 +4210,7 @@ mark_used (tree decl)
like the DECL for the function. Otherwise, if the BASELINK is
for an overloaded function, we don't know which function was
actually used until after overload resolution. */
- if (TREE_CODE (decl) == BASELINK)
+ if (BASELINK_P (decl))
{
decl = BASELINK_FUNCTIONS (decl);
if (really_overloaded_fn (decl))
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 7d345c98922..0bee6b4105c 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1534,6 +1534,8 @@ dump_function_name (tree t, int flags)
}
else if (name && IDENTIFIER_OPNAME_P (name))
pp_cxx_tree_identifier (cxx_pp, name);
+ else if (name && UDLIT_OPER_P (name))
+ pp_cxx_tree_identifier (cxx_pp, name);
else
dump_decl (name, flags);
@@ -1756,6 +1758,10 @@ dump_expr (tree t, int flags)
pp_constant (cxx_pp, t);
break;
+ case USERDEF_LITERAL:
+ pp_cxx_userdef_literal (cxx_pp, t);
+ break;
+
case THROW_EXPR:
/* While waiting for caret diagnostics, avoid printing
__cxa_allocate_exception, __cxa_throw, and the like. */
@@ -2769,7 +2775,7 @@ static void
cp_diagnostic_starter (diagnostic_context *context,
diagnostic_info *diagnostic)
{
- diagnostic_report_current_module (context);
+ diagnostic_report_current_module (context, diagnostic->location);
cp_print_error_function (context, diagnostic);
maybe_print_instantiation_context (context);
maybe_print_constexpr_context (context);
@@ -2779,8 +2785,9 @@ cp_diagnostic_starter (diagnostic_context *context,
static void
cp_diagnostic_finalizer (diagnostic_context *context,
- diagnostic_info *diagnostic ATTRIBUTE_UNUSED)
+ diagnostic_info *diagnostic)
{
+ virt_loc_aware_diagnostic_finalizer (context, diagnostic);
pp_base_destroy_prefix (context->printer);
}
@@ -3198,53 +3205,58 @@ maybe_warn_cpp0x (cpp0x_warn_str str)
case CPP0X_INITIALIZER_LISTS:
pedwarn (input_location, 0,
"extended initializer lists "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_EXPLICIT_CONVERSION:
pedwarn (input_location, 0,
"explicit conversion operators "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_VARIADIC_TEMPLATES:
pedwarn (input_location, 0,
"variadic templates "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_LAMBDA_EXPR:
pedwarn (input_location, 0,
"lambda expressions "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_AUTO:
pedwarn (input_location, 0,
- "C++0x auto only available with -std=c++0x or -std=gnu++0x");
+ "C++0x auto only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_SCOPED_ENUMS:
pedwarn (input_location, 0,
- "scoped enums only available with -std=c++0x or -std=gnu++0x");
+ "scoped enums only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_DEFAULTED_DELETED:
pedwarn (input_location, 0,
"defaulted and deleted functions "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_INLINE_NAMESPACES:
pedwarn (input_location, OPT_pedantic,
"inline namespaces "
- "only available with -std=c++0x or -std=gnu++0x");
- break;
+ "only available with -std=c++11 or -std=gnu++11");
+ break;
case CPP0X_OVERRIDE_CONTROLS:
pedwarn (input_location, 0,
"override controls (override/final) "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
case CPP0X_NSDMI:
pedwarn (input_location, 0,
"non-static data member initializers "
- "only available with -std=c++0x or -std=gnu++0x");
+ "only available with -std=c++11 or -std=gnu++11");
break;
+ case CPP0X_USER_DEFINED_LITERALS:
+ pedwarn (input_location, 0,
+ "user-defined literals "
+ "only available with -std=c++11 or -std=gnu++11");
+ break;
default:
- gcc_unreachable();
+ gcc_unreachable ();
}
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 7897fffb684..6b57eb60a65 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -176,6 +176,8 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
items with static storage duration that are not otherwise
initialized are initialized to zero. */
;
+ else if (TYPE_PTR_P (type) || TYPE_PTR_TO_MEMBER_P (type))
+ init = convert (type, nullptr_node);
else if (SCALAR_TYPE_P (type))
init = convert (type, integer_zero_node);
else if (CLASS_TYPE_P (type))
@@ -497,11 +499,11 @@ perform_member_init (tree member, tree init)
mem-initializer for this field. */
if (init == NULL_TREE)
{
- if (CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (member)))
+ if (DECL_LANG_SPECIFIC (member) && DECL_TEMPLATE_INFO (member))
/* Do deferred instantiation of the NSDMI. */
init = (tsubst_copy_and_build
- (DECL_INITIAL (member),
- CLASSTYPE_TI_ARGS (DECL_CONTEXT (member)),
+ (DECL_INITIAL (DECL_TI_TEMPLATE (member)),
+ DECL_TI_ARGS (member),
tf_warning_or_error, member, /*function_p=*/false,
/*integral_constant_expression_p=*/false));
else
@@ -1588,27 +1590,25 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
that's value-initialization. */
if (init == void_type_node)
{
- /* If there's a user-provided constructor, we just call that. */
- if (type_has_user_provided_constructor (type))
- /* Fall through. */;
- /* If there isn't, but we still need to call the constructor,
- zero out the object first. */
- else if (type_build_ctor_call (type))
+ /* If no user-provided ctor, we need to zero out the object. */
+ if (!type_has_user_provided_constructor (type))
{
- init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
+ tree field_size = NULL_TREE;
+ if (exp != true_exp && CLASSTYPE_AS_BASE (type) != type)
+ /* Don't clobber already initialized virtual bases. */
+ field_size = TYPE_SIZE (CLASSTYPE_AS_BASE (type));
+ init = build_zero_init_1 (type, NULL_TREE, /*static_storage_p=*/false,
+ field_size);
init = build2 (INIT_EXPR, type, exp, init);
finish_expr_stmt (init);
- /* And then call the constructor. */
}
+
/* If we don't need to mess with the constructor at all,
- then just zero out the object and we're done. */
- else
- {
- init = build2 (INIT_EXPR, type, exp,
- build_value_init_noctor (type, complain));
- finish_expr_stmt (init);
- return;
- }
+ then we're done. */
+ if (! type_build_ctor_call (type))
+ return;
+
+ /* Otherwise fall through and call the constructor. */
init = NULL_TREE;
}
@@ -3000,7 +3000,8 @@ build_vec_init (tree base, tree maxindex, tree init,
if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
maxindex = array_type_nelts (atype);
- if (maxindex == NULL_TREE || maxindex == error_mark_node)
+ if (maxindex == NULL_TREE || maxindex == error_mark_node
+ || integer_all_onesp (maxindex))
return error_mark_node;
if (explicit_value_init_p)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 55851e646b2..69fe147f480 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -181,6 +181,7 @@ static void write_template_prefix (const tree);
static void write_unqualified_name (const tree);
static void write_conversion_operator_name (const tree);
static void write_source_name (tree);
+static void write_literal_operator_name (tree);
static void write_unnamed_type_name (const tree);
static void write_closure_type_name (const tree);
static int hwint_to_ascii (unsigned HOST_WIDE_INT, const unsigned int, char *,
@@ -1174,6 +1175,8 @@ write_unqualified_id (tree identifier)
}
write_string (mangled_name);
}
+ else if (UDLIT_OPER_P (identifier))
+ write_literal_operator_name (identifier);
else
write_source_name (identifier);
}
@@ -1227,6 +1230,8 @@ write_unqualified_name (const tree decl)
write_string (oni[DECL_OVERLOADED_OPERATOR_P (decl)].mangled_name);
}
+ else if (UDLIT_OPER_P (DECL_NAME (decl)))
+ write_literal_operator_name (DECL_NAME (decl));
else
found = false;
@@ -1286,6 +1291,21 @@ write_source_name (tree identifier)
write_identifier (IDENTIFIER_POINTER (identifier));
}
+/* Write a user-defined literal operator.
+ IDENTIFIER is an LITERAL_IDENTIFIER_NODE. */
+
+static void
+write_literal_operator_name (tree identifier)
+{
+ const char* suffix = UDLIT_OP_SUFFIX (identifier);
+ char* buffer = XNEWVEC (char, strlen (UDLIT_OP_MANGLED_PREFIX)
+ + strlen (suffix) + 10);
+ sprintf (buffer, UDLIT_OP_MANGLED_FORMAT, suffix);
+
+ write_unsigned_number (strlen (buffer));
+ write_identifier (buffer);
+}
+
/* Encode 0 as _, and 1+ as n-1_. */
static void
@@ -3157,13 +3177,21 @@ mangle_decl_string (const tree decl)
return result;
}
+/* Return an identifier for the external mangled name of DECL. */
+
+static tree
+get_mangled_id (tree decl)
+{
+ tree id = mangle_decl_string (decl);
+ return targetm.mangle_decl_assembler_name (decl, id);
+}
+
/* Create an identifier for the external mangled name of DECL. */
void
mangle_decl (const tree decl)
{
- tree id = mangle_decl_string (decl);
- id = targetm.mangle_decl_assembler_name (decl, id);
+ tree id = get_mangled_id (decl);
SET_DECL_ASSEMBLER_NAME (decl, id);
if (G.need_abi_warning)
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index f4a3ea6ac99..bb58312b689 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1016,25 +1016,7 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
}
else if (sfk == sfk_constructor)
{
- bool bad = true;
- if (CP_TYPE_CONST_P (mem_type)
- && default_init_uninitialized_part (mem_type))
- {
- if (msg)
- error ("uninitialized non-static const member %q#D",
- field);
- }
- else if (TREE_CODE (mem_type) == REFERENCE_TYPE)
- {
- if (msg)
- error ("uninitialized non-static reference member %q#D",
- field);
- }
- else
- bad = false;
-
- if (bad && deleted_p)
- *deleted_p = true;
+ bool bad;
if (DECL_INITIAL (field))
{
@@ -1057,6 +1039,26 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
continue;
}
+ bad = false;
+ if (CP_TYPE_CONST_P (mem_type)
+ && default_init_uninitialized_part (mem_type))
+ {
+ if (msg)
+ error ("uninitialized non-static const member %q#D",
+ field);
+ bad = true;
+ }
+ else if (TREE_CODE (mem_type) == REFERENCE_TYPE)
+ {
+ if (msg)
+ error ("uninitialized non-static reference member %q#D",
+ field);
+ bad = true;
+ }
+
+ if (bad && deleted_p)
+ *deleted_p = true;
+
/* For an implicitly-defined default constructor to be constexpr,
every member must have a user-provided default constructor or
an explicit initializer. */
@@ -1373,18 +1375,31 @@ maybe_explain_implicit_delete (tree decl)
{
informed = true;
if (sfk == sfk_constructor)
- error ("a lambda closure type has a deleted default constructor");
+ inform (DECL_SOURCE_LOCATION (decl),
+ "a lambda closure type has a deleted default constructor");
else if (sfk == sfk_copy_assignment)
- error ("a lambda closure type has a deleted copy assignment operator");
+ inform (DECL_SOURCE_LOCATION (decl),
+ "a lambda closure type has a deleted copy assignment operator");
else
informed = false;
}
+ else if (DECL_ARTIFICIAL (decl)
+ && (sfk == sfk_copy_assignment
+ || sfk == sfk_copy_constructor)
+ && (type_has_user_declared_move_constructor (ctype)
+ || type_has_user_declared_move_assign (ctype)))
+ {
+ inform (0, "%q+#D is implicitly declared as deleted because %qT "
+ "declares a move constructor or move assignment operator",
+ decl, ctype);
+ informed = true;
+ }
if (!informed)
{
tree parm_type = TREE_VALUE (FUNCTION_FIRST_USER_PARMTYPE (decl));
bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
tree scope = push_scope (ctype);
- error ("%qD is implicitly deleted because the default "
+ inform (0, "%q+#D is implicitly deleted because the default "
"definition would be ill-formed:", decl);
pop_scope (scope);
synthesized_method_walk (ctype, sfk, const_p,
@@ -1741,6 +1756,15 @@ lazily_declare_fn (special_function_kind sfk, tree type)
/* Declare the function. */
fn = implicitly_declare_fn (sfk, type, const_p);
+ /* [class.copy]/8 If the class definition declares a move constructor or
+ move assignment operator, the implicitly declared copy constructor is
+ defined as deleted.... */
+ if ((sfk == sfk_copy_assignment
+ || sfk == sfk_copy_constructor)
+ && (type_has_user_declared_move_constructor (type)
+ || type_has_user_declared_move_assign (type)))
+ DECL_DELETED_FN (fn) = true;
+
/* For move variants, rather than declare them as deleted we just
don't declare them at all. */
if (DECL_DELETED_FN (fn)
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 7141c84fcf4..7b61d68208a 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5329,7 +5329,7 @@ arg_assoc (struct arg_lookup *k, tree n)
n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
- if (TREE_CODE (n) == BASELINK)
+ if (BASELINK_P (n))
n = BASELINK_FUNCTIONS (n);
if (TREE_CODE (n) == FUNCTION_DECL)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cabe9aac4bd..63f92620886 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -210,7 +210,6 @@ static void cp_lexer_commit_tokens
(cp_lexer *);
static void cp_lexer_rollback_tokens
(cp_lexer *);
-#ifdef ENABLE_CHECKING
static void cp_lexer_print_token
(FILE *, cp_token *);
static inline bool cp_lexer_debugging_p
@@ -219,15 +218,6 @@ static void cp_lexer_start_debugging
(cp_lexer *) ATTRIBUTE_UNUSED;
static void cp_lexer_stop_debugging
(cp_lexer *) ATTRIBUTE_UNUSED;
-#else
-/* If we define cp_lexer_debug_stream to NULL it will provoke warnings
- about passing NULL to functions that require non-NULL arguments
- (fputs, fprintf). It will never be used, so all we need is a value
- of the right type that's guaranteed not to be NULL. */
-#define cp_lexer_debug_stream stdout
-#define cp_lexer_print_token(str, tok) (void) 0
-#define cp_lexer_debugging_p(lexer) 0
-#endif /* ENABLE_CHECKING */
static cp_token_cache *cp_token_cache_new
(cp_token *, cp_token *);
@@ -235,39 +225,73 @@ static cp_token_cache *cp_token_cache_new
static void cp_parser_initial_pragma
(cp_token *);
+static tree cp_literal_operator_id
+ (const char *);
+
/* Manifest constants. */
#define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
#define CP_SAVED_TOKEN_STACK 5
/* Variables. */
-#ifdef ENABLE_CHECKING
/* The stream to which debugging output should be written. */
static FILE *cp_lexer_debug_stream;
-#endif /* ENABLE_CHECKING */
/* Nonzero if we are parsing an unevaluated operand: an operand to
sizeof, typeof, or alignof. */
int cp_unevaluated_operand;
-#ifdef ENABLE_CHECKING
-/* Dump up to NUM tokens in BUFFER to FILE. If NUM is 0, dump all the
- tokens. */
+/* Dump up to NUM tokens in BUFFER to FILE starting with token
+ START_TOKEN. If START_TOKEN is NULL, the dump starts with the
+ first token in BUFFER. If NUM is 0, dump all the tokens. If
+ CURR_TOKEN is set and it is one of the tokens in BUFFER, it will be
+ highlighted by surrounding it in [[ ]]. */
-void
-cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num)
+static void
+cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer,
+ cp_token *start_token, unsigned num,
+ cp_token *curr_token)
{
- unsigned i;
+ unsigned i, nprinted;
cp_token *token;
+ bool do_print;
fprintf (file, "%u tokens\n", VEC_length (cp_token, buffer));
+ if (buffer == NULL)
+ return;
+
if (num == 0)
num = VEC_length (cp_token, buffer);
- for (i = 0; VEC_iterate (cp_token, buffer, i, token) && i < num; i++)
+ if (start_token == NULL)
+ start_token = VEC_address (cp_token, buffer);
+
+ if (start_token > VEC_address (cp_token, buffer))
{
+ cp_lexer_print_token (file, VEC_index (cp_token, buffer, 0));
+ fprintf (file, " ... ");
+ }
+
+ do_print = false;
+ nprinted = 0;
+ for (i = 0; VEC_iterate (cp_token, buffer, i, token) && nprinted < num; i++)
+ {
+ if (token == start_token)
+ do_print = true;
+
+ if (!do_print)
+ continue;
+
+ nprinted++;
+ if (token == curr_token)
+ fprintf (file, "[[");
+
cp_lexer_print_token (file, token);
+
+ if (token == curr_token)
+ fprintf (file, "]]");
+
switch (token->type)
{
case CPP_SEMICOLON:
@@ -298,9 +322,227 @@ cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num)
void
cp_lexer_debug_tokens (VEC(cp_token,gc) *buffer)
{
- cp_lexer_dump_tokens (stderr, buffer, 0);
+ cp_lexer_dump_tokens (stderr, buffer, NULL, 0, NULL);
+}
+
+
+/* Dump the cp_parser tree field T to FILE if T is non-NULL. DESC is the
+ description for T. */
+
+static void
+cp_debug_print_tree_if_set (FILE *file, const char *desc, tree t)
+{
+ if (t)
+ {
+ fprintf (file, "%s: ", desc);
+ print_node_brief (file, "", t, 0);
+ }
+}
+
+
+/* Dump parser context C to FILE. */
+
+static void
+cp_debug_print_context (FILE *file, cp_parser_context *c)
+{
+ const char *status_s[] = { "OK", "ERROR", "COMMITTED" };
+ fprintf (file, "{ status = %s, scope = ", status_s[c->status]);
+ print_node_brief (file, "", c->object_type, 0);
+ fprintf (file, "}\n");
+}
+
+
+/* Print the stack of parsing contexts to FILE starting with FIRST. */
+
+static void
+cp_debug_print_context_stack (FILE *file, cp_parser_context *first)
+{
+ unsigned i;
+ cp_parser_context *c;
+
+ fprintf (file, "Parsing context stack:\n");
+ for (i = 0, c = first; c; c = c->next, i++)
+ {
+ fprintf (file, "\t#%u: ", i);
+ cp_debug_print_context (file, c);
+ }
+}
+
+
+/* Print the value of FLAG to FILE. DESC is a string describing the flag. */
+
+static void
+cp_debug_print_flag (FILE *file, const char *desc, bool flag)
+{
+ if (flag)
+ fprintf (file, "%s: true\n", desc);
+}
+
+
+/* Print an unparsed function entry UF to FILE. */
+
+static void
+cp_debug_print_unparsed_function (FILE *file, cp_unparsed_functions_entry *uf)
+{
+ unsigned i;
+ cp_default_arg_entry *default_arg_fn;
+ tree fn;
+
+ fprintf (file, "\tFunctions with default args:\n");
+ for (i = 0;
+ VEC_iterate (cp_default_arg_entry, uf->funs_with_default_args, i,
+ default_arg_fn);
+ i++)
+ {
+ fprintf (file, "\t\tClass type: ");
+ print_node_brief (file, "", default_arg_fn->class_type, 0);
+ fprintf (file, "\t\tDeclaration: ");
+ print_node_brief (file, "", default_arg_fn->decl, 0);
+ fprintf (file, "\n");
+ }
+
+ fprintf (file, "\n\tFunctions with definitions that require "
+ "post-processing\n\t\t");
+ for (i = 0; VEC_iterate (tree, uf->funs_with_definitions, i, fn); i++)
+ {
+ print_node_brief (file, "", fn, 0);
+ fprintf (file, " ");
+ }
+ fprintf (file, "\n");
+
+ fprintf (file, "\n\tNon-static data members with initializers that require "
+ "post-processing\n\t\t");
+ for (i = 0; VEC_iterate (tree, uf->nsdmis, i, fn); i++)
+ {
+ print_node_brief (file, "", fn, 0);
+ fprintf (file, " ");
+ }
+ fprintf (file, "\n");
+}
+
+
+/* Print the stack of unparsed member functions S to FILE. */
+
+static void
+cp_debug_print_unparsed_queues (FILE *file,
+ VEC(cp_unparsed_functions_entry, gc) *s)
+{
+ unsigned i;
+ cp_unparsed_functions_entry *uf;
+
+ fprintf (file, "Unparsed functions\n");
+ for (i = 0; VEC_iterate (cp_unparsed_functions_entry, s, i, uf); i++)
+ {
+ fprintf (file, "#%u:\n", i);
+ cp_debug_print_unparsed_function (file, uf);
+ }
+}
+
+
+/* Dump the tokens in a window of size WINDOW_SIZE around the next_token for
+ the given PARSER. If FILE is NULL, the output is printed on stderr. */
+
+static void
+cp_debug_parser_tokens (FILE *file, cp_parser *parser, int window_size)
+{
+ cp_token *next_token, *first_token, *start_token;
+
+ if (file == NULL)
+ file = stderr;
+
+ next_token = parser->lexer->next_token;
+ first_token = VEC_address (cp_token, parser->lexer->buffer);
+ start_token = (next_token > first_token + window_size / 2)
+ ? next_token - window_size / 2
+ : first_token;
+ cp_lexer_dump_tokens (file, parser->lexer->buffer, start_token, window_size,
+ next_token);
+}
+
+
+/* Dump debugging information for the given PARSER. If FILE is NULL,
+ the output is printed on stderr. */
+
+void
+cp_debug_parser (FILE *file, cp_parser *parser)
+{
+ const size_t window_size = 20;
+ cp_token *token;
+ expanded_location eloc;
+
+ if (file == NULL)
+ file = stderr;
+
+ fprintf (file, "Parser state\n\n");
+ fprintf (file, "Number of tokens: %u\n",
+ VEC_length (cp_token, parser->lexer->buffer));
+ cp_debug_print_tree_if_set (file, "Lookup scope", parser->scope);
+ cp_debug_print_tree_if_set (file, "Object scope",
+ parser->object_scope);
+ cp_debug_print_tree_if_set (file, "Qualifying scope",
+ parser->qualifying_scope);
+ cp_debug_print_context_stack (file, parser->context);
+ cp_debug_print_flag (file, "Allow GNU extensions",
+ parser->allow_gnu_extensions_p);
+ cp_debug_print_flag (file, "'>' token is greater-than",
+ parser->greater_than_is_operator_p);
+ cp_debug_print_flag (file, "Default args allowed in current "
+ "parameter list", parser->default_arg_ok_p);
+ cp_debug_print_flag (file, "Parsing integral constant-expression",
+ parser->integral_constant_expression_p);
+ cp_debug_print_flag (file, "Allow non-constant expression in current "
+ "constant-expression",
+ parser->allow_non_integral_constant_expression_p);
+ cp_debug_print_flag (file, "Seen non-constant expression",
+ parser->non_integral_constant_expression_p);
+ cp_debug_print_flag (file, "Local names and 'this' forbidden in "
+ "current context",
+ parser->local_variables_forbidden_p);
+ cp_debug_print_flag (file, "In unbraced linkage specification",
+ parser->in_unbraced_linkage_specification_p);
+ cp_debug_print_flag (file, "Parsing a declarator",
+ parser->in_declarator_p);
+ cp_debug_print_flag (file, "In template argument list",
+ parser->in_template_argument_list_p);
+ cp_debug_print_flag (file, "Parsing an iteration statement",
+ parser->in_statement & IN_ITERATION_STMT);
+ cp_debug_print_flag (file, "Parsing a switch statement",
+ parser->in_statement & IN_SWITCH_STMT);
+ cp_debug_print_flag (file, "Parsing a structured OpenMP block",
+ parser->in_statement & IN_OMP_BLOCK);
+ cp_debug_print_flag (file, "Parsing a an OpenMP loop",
+ parser->in_statement & IN_OMP_FOR);
+ cp_debug_print_flag (file, "Parsing an if statement",
+ parser->in_statement & IN_IF_STMT);
+ cp_debug_print_flag (file, "Parsing a type-id in an expression "
+ "context", parser->in_type_id_in_expr_p);
+ cp_debug_print_flag (file, "Declarations are implicitly extern \"C\"",
+ parser->implicit_extern_c);
+ cp_debug_print_flag (file, "String expressions should be translated "
+ "to execution character set",
+ parser->translate_strings_p);
+ cp_debug_print_flag (file, "Parsing function body outside of a "
+ "local class", parser->in_function_body);
+ cp_debug_print_flag (file, "Auto correct a colon to a scope operator",
+ parser->colon_corrects_to_scope_p);
+ if (parser->type_definition_forbidden_message)
+ fprintf (file, "Error message for forbidden type definitions: %s\n",
+ parser->type_definition_forbidden_message);
+ cp_debug_print_unparsed_queues (file, parser->unparsed_queues);
+ fprintf (file, "Number of class definitions in progress: %u\n",
+ parser->num_classes_being_defined);
+ fprintf (file, "Number of template parameter lists for the current "
+ "declaration: %u\n", parser->num_template_parameter_lists);
+ cp_debug_parser_tokens (file, parser, window_size);
+ token = parser->lexer->next_token;
+ fprintf (file, "Next token to parse:\n");
+ fprintf (file, "\tToken: ");
+ cp_lexer_print_token (file, token);
+ eloc = expand_location (token->location);
+ fprintf (file, "\n\tFile: %s\n", eloc.file);
+ fprintf (file, "\tLine: %d\n", eloc.line);
+ fprintf (file, "\tColumn: %d\n", eloc.column);
}
-#endif
/* Allocate memory for a new lexer object and return it. */
@@ -315,10 +557,9 @@ cp_lexer_alloc (void)
/* Allocate the memory. */
lexer = ggc_alloc_cleared_cp_lexer ();
-#ifdef ENABLE_CHECKING
/* Initially we are not debugging. */
lexer->debugging_p = false;
-#endif /* ENABLE_CHECKING */
+
lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
CP_SAVED_TOKEN_STACK);
@@ -388,10 +629,8 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
CP_SAVED_TOKEN_STACK);
-#ifdef ENABLE_CHECKING
/* Initially we are not debugging. */
lexer->debugging_p = false;
-#endif
gcc_assert (!lexer->next_token->purged_p);
return lexer;
@@ -409,15 +648,12 @@ cp_lexer_destroy (cp_lexer *lexer)
/* Returns nonzero if debugging information should be output. */
-#ifdef ENABLE_CHECKING
-
static inline bool
cp_lexer_debugging_p (cp_lexer *lexer)
{
return lexer->debugging_p;
}
-#endif /* ENABLE_CHECKING */
static inline cp_token_position
cp_lexer_token_position (cp_lexer *lexer, bool previous_p)
@@ -852,8 +1088,6 @@ cp_lexer_rollback_tokens (cp_lexer* lexer)
/* Print a representation of the TOKEN on the STREAM. */
-#ifdef ENABLE_CHECKING
-
static void
cp_lexer_print_token (FILE * stream, cp_token *token)
{
@@ -914,6 +1148,7 @@ static void
cp_lexer_start_debugging (cp_lexer* lexer)
{
lexer->debugging_p = true;
+ cp_lexer_debug_stream = stderr;
}
/* Stop emitting debugging information. */
@@ -922,10 +1157,9 @@ static void
cp_lexer_stop_debugging (cp_lexer* lexer)
{
lexer->debugging_p = false;
+ cp_lexer_debug_stream = NULL;
}
-#endif /* ENABLE_CHECKING */
-
/* Create a new cp_token_cache, representing a range of tokens. */
static cp_token_cache *
@@ -1531,6 +1765,12 @@ static tree cp_parser_identifier
(cp_parser *);
static tree cp_parser_string_literal
(cp_parser *, bool, bool);
+static tree cp_parser_userdef_char_literal
+ (cp_parser *);
+static tree cp_parser_userdef_string_literal
+ (cp_token *);
+static tree cp_parser_userdef_numeric_literal
+ (cp_parser *);
/* Basic concepts [gram.basic] */
@@ -2039,6 +2279,8 @@ static bool cp_parser_error_occurred
(cp_parser *);
static bool cp_parser_allow_gnu_extensions_p
(cp_parser *);
+static bool cp_parser_is_pure_string_literal
+ (cp_token *);
static bool cp_parser_is_string_literal
(cp_token *);
static bool cp_parser_is_keyword
@@ -2059,7 +2301,7 @@ cp_parser_parsing_tentatively (cp_parser* parser)
/* Returns nonzero if TOKEN is a string literal. */
static bool
-cp_parser_is_string_literal (cp_token* token)
+cp_parser_is_pure_string_literal (cp_token* token)
{
return (token->type == CPP_STRING ||
token->type == CPP_STRING16 ||
@@ -2068,6 +2310,20 @@ cp_parser_is_string_literal (cp_token* token)
token->type == CPP_UTF8STRING);
}
+/* Returns nonzero if TOKEN is a string literal
+ of a user-defined string literal. */
+
+static bool
+cp_parser_is_string_literal (cp_token* token)
+{
+ return (cp_parser_is_pure_string_literal (token) ||
+ token->type == CPP_STRING_USERDEF ||
+ token->type == CPP_STRING16_USERDEF ||
+ token->type == CPP_STRING32_USERDEF ||
+ token->type == CPP_WSTRING_USERDEF ||
+ token->type == CPP_UTF8STRING_USERDEF);
+}
+
/* Returns nonzero if TOKEN is the indicated KEYWORD. */
static bool
@@ -2503,8 +2759,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
The user should have said "typename A<T>::X". */
if (cxx_dialect < cxx0x && id == ridpointers[(int)RID_CONSTEXPR])
- inform (location, "C++0x %<constexpr%> only available with "
- "-std=c++0x or -std=gnu++0x");
+ inform (location, "C++11 %<constexpr%> only available with "
+ "-std=c++11 or -std=gnu++11");
else if (processing_template_decl && current_class_type
&& TYPE_BINFO (current_class_type))
{
@@ -3107,7 +3363,11 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
struct obstack str_ob;
cpp_string str, istr, *strs;
cp_token *tok;
- enum cpp_ttype type;
+ enum cpp_ttype type, curr_type;
+ int have_suffix_p = 0;
+ tree string_tree;
+ tree suffix_id = NULL_TREE;
+ bool curr_tok_is_userdef_p = false;
tok = cp_lexer_peek_token (parser->lexer);
if (!cp_parser_is_string_literal (tok))
@@ -3116,7 +3376,18 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
return error_mark_node;
}
- type = tok->type;
+ if (cpp_userdef_string_p (tok->type))
+ {
+ string_tree = USERDEF_LITERAL_VALUE (tok->u.value);
+ curr_type = cpp_userdef_string_remove_type (tok->type);
+ curr_tok_is_userdef_p = true;
+ }
+ else
+ {
+ string_tree = tok->u.value;
+ curr_type = tok->type;
+ }
+ type = curr_type;
/* Try to avoid the overhead of creating and destroying an obstack
for the common case of just one string. */
@@ -3125,10 +3396,19 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
{
cp_lexer_consume_token (parser->lexer);
- str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
- str.len = TREE_STRING_LENGTH (tok->u.value);
+ str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree);
+ str.len = TREE_STRING_LENGTH (string_tree);
count = 1;
+ if (curr_tok_is_userdef_p)
+ {
+ suffix_id = USERDEF_LITERAL_SUFFIX_ID (tok->u.value);
+ have_suffix_p = 1;
+ curr_type = cpp_userdef_string_remove_type (tok->type);
+ }
+ else
+ curr_type = tok->type;
+
strs = &str;
}
else
@@ -3140,14 +3420,35 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
{
cp_lexer_consume_token (parser->lexer);
count++;
- str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
- str.len = TREE_STRING_LENGTH (tok->u.value);
+ str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree);
+ str.len = TREE_STRING_LENGTH (string_tree);
- if (type != tok->type)
+ if (curr_tok_is_userdef_p)
+ {
+ tree curr_suffix_id = USERDEF_LITERAL_SUFFIX_ID (tok->u.value);
+ if (have_suffix_p == 0)
+ {
+ suffix_id = curr_suffix_id;
+ have_suffix_p = 1;
+ }
+ else if (have_suffix_p == 1
+ && curr_suffix_id != suffix_id)
+ {
+ error ("inconsistent user-defined literal suffixes"
+ " %qD and %qD in string literal",
+ suffix_id, curr_suffix_id);
+ have_suffix_p = -1;
+ }
+ curr_type = cpp_userdef_string_remove_type (tok->type);
+ }
+ else
+ curr_type = tok->type;
+
+ if (type != curr_type)
{
if (type == CPP_STRING)
- type = tok->type;
- else if (tok->type != CPP_STRING)
+ type = curr_type;
+ else if (curr_type != CPP_STRING)
error_at (tok->location,
"unsupported non-standard concatenation "
"of string literals");
@@ -3156,6 +3457,18 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
obstack_grow (&str_ob, &str, sizeof (cpp_string));
tok = cp_lexer_peek_token (parser->lexer);
+ if (cpp_userdef_string_p (tok->type))
+ {
+ string_tree = USERDEF_LITERAL_VALUE (tok->u.value);
+ curr_type = cpp_userdef_string_remove_type (tok->type);
+ curr_tok_is_userdef_p = true;
+ }
+ else
+ {
+ string_tree = tok->u.value;
+ curr_type = tok->type;
+ curr_tok_is_userdef_p = false;
+ }
}
while (cp_parser_is_string_literal (tok));
@@ -3193,6 +3506,13 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
}
value = fix_string_type (value);
+
+ if (have_suffix_p)
+ {
+ tree literal = build_userdef_literal (suffix_id, value, NULL_TREE);
+ tok->u.value = literal;
+ return cp_parser_userdef_string_literal (tok);
+ }
}
else
/* cpp_interpret_string has issued an error. */
@@ -3204,6 +3524,187 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
return value;
}
+/* Parse a user-defined char constant. Returns a call to a user-defined
+ literal operator taking the character as an argument. */
+
+static tree
+cp_parser_userdef_char_literal (cp_parser *parser)
+{
+ cp_token *token = NULL;
+ tree literal, suffix_id, value;
+ tree name, decl;
+ tree result;
+ VEC(tree,gc) *vec;
+
+ token = cp_lexer_consume_token (parser->lexer);
+ literal = token->u.value;
+ suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+ value = USERDEF_LITERAL_VALUE (literal);
+ name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+
+ /* Build up a call to the user-defined operator */
+ /* Lookup the name we got back from the id-expression. */
+ vec = make_tree_vector ();
+ VEC_safe_push (tree, gc, vec, value);
+ decl = lookup_function_nonclass (name, vec, /*block_p=*/false);
+ if (!decl || decl == error_mark_node)
+ {
+ error ("unable to find user-defined character literal operator %qD",
+ name);
+ release_tree_vector (vec);
+ return error_mark_node;
+ }
+ result = finish_call_expr (decl, &vec, false, true, tf_warning_or_error);
+ release_tree_vector (vec);
+
+ return result;
+}
+
+/* A subroutine of cp_parser_userdef_numeric_literal to
+ create a char... template parameter pack from a string node. */
+
+static tree
+make_char_string_pack (tree value)
+{
+ tree charvec;
+ tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
+ const char *str = TREE_STRING_POINTER (value);
+ int i, len = TREE_STRING_LENGTH (value) - 1;
+ tree argvec = make_tree_vec (1);
+
+ /* Fill in CHARVEC with all of the parameters. */
+ charvec = make_tree_vec (len);
+ for (i = 0; i < len; ++i)
+ TREE_VEC_ELT (charvec, i) = build_int_cst (char_type_node, str[i]);
+
+ /* Build the argument packs. */
+ SET_ARGUMENT_PACK_ARGS (argpack, charvec);
+ TREE_TYPE (argpack) = char_type_node;
+
+ TREE_VEC_ELT (argvec, 0) = argpack;
+
+ return argvec;
+}
+
+/* Parse a user-defined numeric constant. returns a call to a user-defined
+ literal operator. */
+
+static tree
+cp_parser_userdef_numeric_literal (cp_parser *parser)
+{
+ cp_token *token = NULL;
+ tree literal, suffix_id, value, num_string;
+ tree name, decl;
+ tree result = error_mark_node;
+ VEC(tree,gc) *args;
+
+ token = cp_lexer_consume_token (parser->lexer);
+ literal = token->u.value;
+ suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+ value = USERDEF_LITERAL_VALUE (literal);
+ num_string = USERDEF_LITERAL_NUM_STRING (literal);
+ name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+
+ /* Build up a call to the user-defined operator */
+ /* Lookup the name we got back from the id-expression. */
+ /* Try to find the literal operator by finishing the call expression
+ with the numeric argument. */
+ args = make_tree_vector ();
+ VEC_safe_push (tree, gc, args, value);
+ decl = lookup_function_nonclass (name, args, /*block_p=*/false);
+ if (decl && decl != error_mark_node)
+ {
+ result = finish_call_expr (decl, &args, false, true, tf_none);
+ if (result != error_mark_node)
+ {
+ release_tree_vector (args);
+ return result;
+ }
+ }
+ release_tree_vector (args);
+
+ /* If the numeric argument didn't work, look for a raw literal
+ operator taking a const char* argument consisting of the number
+ in string format. */
+ args = make_tree_vector ();
+ VEC_safe_push (tree, gc, args, num_string);
+ decl = lookup_function_nonclass (name, args, /*block_p=*/false);
+ if (decl && decl != error_mark_node)
+ {
+ result = finish_call_expr (decl, &args, false, true, tf_none);
+ if (result != error_mark_node)
+ {
+ release_tree_vector (args);
+ return result;
+ }
+ }
+ release_tree_vector (args);
+
+ /* If the raw literal didn't work, look for a non-type template
+ function with parameter pack char.... Call the function with
+ template parameter characters representing the number. */
+ args = make_tree_vector ();
+ decl = lookup_function_nonclass (name, args, /*block_p=*/false);
+ if (decl && decl != error_mark_node)
+ {
+ tree tmpl_args = make_char_string_pack (num_string);
+ decl = lookup_template_function (decl, tmpl_args);
+ result = finish_call_expr (decl, &args, false, true, tf_none);
+ if (result != error_mark_node)
+ {
+ release_tree_vector (args);
+ return result;
+ }
+ }
+ release_tree_vector (args);
+
+ if (result == error_mark_node)
+ error ("unable to find user-defined numeric literal operator %qD", name);
+
+ return result;
+}
+
+/* Parse a user-defined string constant. Returns a call to a user-defined
+ literal operator taking a character pointer and the length of the string
+ as arguments. */
+
+static tree
+cp_parser_userdef_string_literal (cp_token *token)
+{
+ tree literal, suffix_id, value;
+ tree name, decl;
+ tree result;
+ VEC(tree,gc) *vec;
+ int len;
+
+ literal = token->u.value;
+ suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal);
+ name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
+ value = USERDEF_LITERAL_VALUE (literal);
+ len = TREE_STRING_LENGTH (value) - 1;
+
+ /* Build up a call to the user-defined operator */
+ /* Lookup the name we got back from the id-expression. */
+ vec = make_tree_vector ();
+ VEC_safe_push (tree, gc, vec, value);
+ VEC_safe_push (tree, gc, vec, build_int_cst (size_type_node, len));
+ decl = lookup_function_nonclass (name, vec, /*block_p=*/false);
+ if (!decl || decl == error_mark_node)
+ {
+ error ("unable to find user-defined string literal operator %qD", name);
+ release_tree_vector (vec);
+ return error_mark_node;
+ }
+ result = finish_call_expr (decl, &vec, false, true, tf_none);
+ if (result == error_mark_node)
+ error ("unable to find valid user-defined string literal operator %qD."
+ " Possible missing length argument in string literal operator.",
+ name);
+ release_tree_vector (vec);
+
+ return result;
+}
+
/* Basic concepts [gram.basic] */
@@ -3347,12 +3848,16 @@ cp_parser_primary_expression (cp_parser *parser,
character-literal
floating-literal
string-literal
- boolean-literal */
+ boolean-literal
+ pointer-literal
+ user-defined-literal */
case CPP_CHAR:
case CPP_CHAR16:
case CPP_CHAR32:
case CPP_WCHAR:
case CPP_NUMBER:
+ if (TREE_CODE (token->u.value) == USERDEF_LITERAL)
+ return cp_parser_userdef_numeric_literal (parser);
token = cp_lexer_consume_token (parser->lexer);
if (TREE_CODE (token->u.value) == FIXED_CST)
{
@@ -3406,11 +3911,22 @@ cp_parser_primary_expression (cp_parser *parser,
}
return token->u.value;
+ case CPP_CHAR_USERDEF:
+ case CPP_CHAR16_USERDEF:
+ case CPP_CHAR32_USERDEF:
+ case CPP_WCHAR_USERDEF:
+ return cp_parser_userdef_char_literal (parser);
+
case CPP_STRING:
case CPP_STRING16:
case CPP_STRING32:
case CPP_WSTRING:
case CPP_UTF8STRING:
+ case CPP_STRING_USERDEF:
+ case CPP_STRING16_USERDEF:
+ case CPP_STRING32_USERDEF:
+ case CPP_WSTRING_USERDEF:
+ case CPP_UTF8STRING_USERDEF:
/* ??? Should wide strings be allowed when parser->translate_strings_p
is false (i.e. in attributes)? If not, we can kill the third
argument to cp_parser_string_literal. */
@@ -4246,6 +4762,14 @@ cp_parser_unqualified_id (cp_parser* parser,
/* If that didn't work, try a conversion-function-id. */
if (!cp_parser_parse_definitely (parser))
id = cp_parser_conversion_function_id (parser);
+ else if (UDLIT_OPER_P (id))
+ {
+ /* 17.6.3.3.5 */
+ const char *name = UDLIT_OP_SUFFIX (id);
+ if (name[0] != '_' && !in_system_header)
+ warning (0, "literal operator suffixes not preceded by %<_%>"
+ " are reserved for future standardization");
+ }
return id;
}
@@ -4521,8 +5045,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
&& (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
== TEMPLATE_ID_EXPR)))
permerror (input_location, TYPE_P (new_scope)
- ? "%qT is not a template"
- : "%qD is not a template",
+ ? G_("%qT is not a template")
+ : G_("%qD is not a template"),
new_scope);
/* If it is a class scope, try to complete it; we are about to
be looking up names inside the class. */
@@ -4888,7 +5412,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
/* `typeid' may not appear in an integral constant expression. */
- if (cp_parser_non_integral_constant_expression(parser, NIC_TYPEID))
+ if (cp_parser_non_integral_constant_expression (parser, NIC_TYPEID))
return error_mark_node;
}
break;
@@ -7304,6 +7828,12 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
case RID_UNDERLYING_TYPE:
kind = CPTK_UNDERLYING_TYPE;
break;
+ case RID_BASES:
+ kind = CPTK_BASES;
+ break;
+ case RID_DIRECT_BASES:
+ kind = CPTK_DIRECT_BASES;
+ break;
default:
gcc_unreachable ();
}
@@ -7348,9 +7878,17 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
/* Complete the trait expression, which may mean either processing
the trait expr now or saving it for template instantiation. */
- return kind != CPTK_UNDERLYING_TYPE
- ? finish_trait_expr (kind, type1, type2)
- : finish_underlying_type (type1);
+ switch(kind)
+ {
+ case CPTK_UNDERLYING_TYPE:
+ return finish_underlying_type (type1);
+ case CPTK_BASES:
+ return finish_bases (type1, false);
+ case CPTK_DIRECT_BASES:
+ return finish_bases (type1, true);
+ default:
+ return finish_trait_expr (kind, type1, type2);
+ }
}
/* Lambdas that appear in variable initializer or default argument scope
@@ -7630,6 +8168,31 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
/*ambiguous_decls=*/NULL,
capture_token->location);
+ if (capture_init_expr == error_mark_node)
+ {
+ unqualified_name_lookup_error (capture_id);
+ continue;
+ }
+ else if (DECL_P (capture_init_expr)
+ && (TREE_CODE (capture_init_expr) != VAR_DECL
+ && TREE_CODE (capture_init_expr) != PARM_DECL))
+ {
+ error_at (capture_token->location,
+ "capture of non-variable %qD ",
+ capture_init_expr);
+ inform (0, "%q+#D declared here", capture_init_expr);
+ continue;
+ }
+ if (TREE_CODE (capture_init_expr) == VAR_DECL
+ && decl_storage_duration (capture_init_expr) != dk_auto)
+ {
+ pedwarn (capture_token->location, 0, "capture of variable "
+ "%qD with non-automatic storage duration",
+ capture_init_expr);
+ inform (0, "%q+#D declared here", capture_init_expr);
+ continue;
+ }
+
capture_init_expr
= finish_id_expression
(capture_id,
@@ -7647,10 +8210,6 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
capture_token->location);
}
- if (TREE_CODE (capture_init_expr) == IDENTIFIER_NODE)
- capture_init_expr
- = unqualified_name_lookup_error (capture_init_expr);
-
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
&& !explicit_init_p)
{
@@ -9473,7 +10032,7 @@ cp_parser_declaration (cp_parser* parser)
/* If the next token is `extern' and the following token is a string
literal, then we have a linkage specification. */
if (token1.keyword == RID_EXTERN
- && cp_parser_is_string_literal (&token2))
+ && cp_parser_is_pure_string_literal (&token2))
cp_parser_linkage_specification (parser);
/* If the next token is `template', then we have either a template
declaration, an explicit instantiation, or an explicit
@@ -10904,6 +11463,22 @@ cp_parser_operator_function_id (cp_parser* parser)
return cp_parser_operator (parser);
}
+/* Return an identifier node for a user-defined literal operator.
+ The suffix identifier is chained to the operator name identifier. */
+
+static tree
+cp_literal_operator_id (const char* name)
+{
+ tree identifier;
+ char *buffer = XNEWVEC (char, strlen (UDLIT_OP_ANSI_PREFIX)
+ + strlen (name) + 10);
+ sprintf (buffer, UDLIT_OP_ANSI_FORMAT, name);
+ identifier = get_identifier (buffer);
+ /*IDENTIFIER_UDLIT_OPNAME_P (identifier) = 1; If we get a flag someday. */
+
+ return identifier;
+}
+
/* Parse an operator.
operator:
@@ -11123,6 +11698,37 @@ cp_parser_operator (cp_parser* parser)
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
return ansi_opname (ARRAY_REF);
+ case CPP_STRING:
+ if (cxx_dialect == cxx98)
+ maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS);
+ if (TREE_STRING_LENGTH (token->u.value) > 2)
+ {
+ error ("expected empty string after %<operator%> keyword");
+ return error_mark_node;
+ }
+ /* Consume the string. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Look for the suffix identifier. */
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_NAME)
+ {
+ id = cp_parser_identifier (parser);
+ if (id != error_mark_node)
+ {
+ const char *name = IDENTIFIER_POINTER (id);
+ return cp_literal_operator_id (name);
+ }
+ }
+ else
+ {
+ error ("expected suffix identifier");
+ return error_mark_node;
+ }
+
+ case CPP_STRING_USERDEF:
+ error ("missing space between %<\"\"%> and suffix identifier");
+ return error_mark_node;
+
default:
/* Anything else is an error. */
break;
@@ -12019,6 +12625,7 @@ cp_parser_template_argument_list (cp_parser* parser)
parser->integral_constant_expression_p = false;
saved_non_ice_p = parser->non_integral_constant_expression_p;
parser->non_integral_constant_expression_p = false;
+
/* Parse the arguments. */
do
{
@@ -12836,7 +13443,6 @@ cp_parser_simple_type_specifier (cp_parser* parser,
case RID_UNDERLYING_TYPE:
type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
-
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
token->location,
@@ -12844,6 +13450,14 @@ cp_parser_simple_type_specifier (cp_parser* parser,
return type;
+ case RID_BASES:
+ case RID_DIRECT_BASES:
+ type = cp_parser_trait_expr (parser, token->keyword);
+ if (decl_specs)
+ cp_parser_set_decl_spec_type (decl_specs, type,
+ token->location,
+ /*type_definition_p=*/false);
+ return type;
default:
break;
}
@@ -16536,17 +17150,20 @@ cp_parser_parameter_declaration (cp_parser *parser,
if (id_declarator && id_declarator->kind == cdk_id)
error_at (declarator_token_start->location,
- template_parm_p
- ? "template parameter pack %qD"
- " cannot have a default argument"
- : "parameter pack %qD cannot have a default argument",
+ template_parm_p
+ ? G_("template parameter pack %qD "
+ "cannot have a default argument")
+ : G_("parameter pack %qD cannot have "
+ "a default argument"),
id_declarator->u.id.unqualified_name);
else
error_at (declarator_token_start->location,
- template_parm_p
- ? "template parameter pack cannot have a default argument"
- : "parameter pack cannot have a default argument");
-
+ template_parm_p
+ ? G_("template parameter pack cannot have "
+ "a default argument")
+ : G_("parameter pack cannot have a "
+ "default argument"));
+
default_argument = NULL_TREE;
}
}
@@ -17576,8 +18193,8 @@ cp_parser_class_head (cp_parser* parser,
{
cp_parser_check_for_invalid_template_id (parser, id,
type_start_token->location);
- virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
}
+ virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
/* If it's not a `:' or a `{' then we can't really be looking at a
class-head, since a class-head only appears as part of a
@@ -20306,6 +20923,33 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
/* Finish up. */
finish_template_decl (parameter_list);
+ /* Check the template arguments for a literal operator template. */
+ if (decl
+ && (TREE_CODE (decl) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (decl))
+ && UDLIT_OPER_P (DECL_NAME (decl)))
+ {
+ bool ok = true;
+ if (parameter_list == NULL_TREE)
+ ok = false;
+ else
+ {
+ int num_parms = TREE_VEC_LENGTH (parameter_list);
+ if (num_parms != 1)
+ ok = false;
+ else
+ {
+ tree parm_list = TREE_VEC_ELT (parameter_list, 0);
+ tree parm = INNERMOST_TEMPLATE_PARMS (parm_list);
+ if (TREE_TYPE (parm) != char_type_node
+ || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+ ok = false;
+ }
+ }
+ if (!ok)
+ error ("literal operator template %qD has invalid parameter list."
+ " Expected non-type template argument pack <char...>",
+ decl);
+ }
/* Register member declarations. */
if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl))
finish_member_declaration (decl);
@@ -20617,7 +21261,8 @@ cp_parser_save_nsdmi (cp_parser* parser)
cp_token *last;
tree node;
- cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0);
+ /* Save tokens until the next comma or semicolon. */
+ cp_parser_cache_group (parser, CPP_COMMA, /*depth=*/0);
last = parser->lexer->next_token;
@@ -20630,7 +21275,7 @@ cp_parser_save_nsdmi (cp_parser* parser)
/* Parse a template-argument-list, as well as the trailing ">" (but
- not the opening ">"). See cp_parser_template_argument_list for the
+ not the opening "<"). See cp_parser_template_argument_list for the
return value. */
static tree
@@ -21719,6 +22364,12 @@ cp_parser_cache_group (cp_parser *parser,
kind of syntax error. */
return true;
+ /* If we're caching something finished by a comma (or semicolon),
+ such as an NSDMI, don't consume the comma. */
+ if (end == CPP_COMMA
+ && (token->type == CPP_SEMICOLON || token->type == CPP_COMMA))
+ return false;
+
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
/* See if it starts a new group. */
@@ -22607,7 +23258,8 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
/* If the next token is `extern' and the following token is a string
literal, then we have a linkage specification. */
if (token->keyword == RID_EXTERN
- && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2)))
+ && cp_parser_is_pure_string_literal
+ (cp_lexer_peek_nth_token (parser->lexer, 2)))
cp_parser_linkage_specification (parser);
/* Handle #pragma, if any. */
else if (token->type == CPP_PRAGMA)
diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h
index e08c0b415a0..b44d23cd8cd 100644
--- a/gcc/cp/parser.h
+++ b/gcc/cp/parser.h
@@ -352,9 +352,7 @@ typedef struct GTY(()) cp_parser {
} cp_parser;
/* In parser.c */
-#ifdef ENABLE_CHECKING
-extern void cp_lexer_dump_tokens (FILE *, VEC(cp_token,gc) *, unsigned);
extern void cp_lexer_debug_tokens (VEC(cp_token,gc) *);
-#endif
+extern void cp_debug_parser (FILE *, cp_parser *);
#endif /* GCC_CP_PARSER_H */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bfbd2444325..493e3e6bcc3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2980,6 +2980,9 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
}
break;
+ case BASES:
+ parameter_pack_p = true;
+ break;
default:
/* Not a parameter pack. */
break;
@@ -4647,7 +4650,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
"friend declarations");
else if (TREE_CODE (decl) == FUNCTION_DECL && (cxx_dialect == cxx98))
msg = G_("default template arguments may not be used in function templates "
- "without -std=c++0x or -std=gnu++0x");
+ "without -std=c++11 or -std=gnu++11");
else if (is_partial)
msg = G_("default template arguments may not be used in "
"partial specializations");
@@ -5274,7 +5277,7 @@ convert_nontype_argument_function (tree type, tree expr)
fn_no_ptr = fn;
if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
- if (TREE_CODE (fn_no_ptr) == BASELINK)
+ if (BASELINK_P (fn_no_ptr))
fn_no_ptr = BASELINK_FUNCTIONS (fn_no_ptr);
/* [temp.arg.nontype]/1
@@ -7798,7 +7801,7 @@ uses_template_parms (tree t)
|| EXPR_P (t)
|| TREE_CODE (t) == TEMPLATE_PARM_INDEX
|| TREE_CODE (t) == OVERLOAD
- || TREE_CODE (t) == BASELINK
+ || BASELINK_P (t)
|| TREE_CODE (t) == IDENTIFIER_NODE
|| TREE_CODE (t) == TRAIT_EXPR
|| TREE_CODE (t) == CONSTRUCTOR
@@ -9127,6 +9130,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree arg_pack = NULL_TREE;
tree orig_arg = NULL_TREE;
+ if (TREE_CODE (parm_pack) == BASES)
+ {
+ if (BASES_DIRECT (parm_pack))
+ return calculate_direct_bases (tsubst_expr (BASES_TYPE (parm_pack),
+ args, complain, in_decl, false));
+ else
+ return calculate_bases (tsubst_expr (BASES_TYPE (parm_pack),
+ args, complain, in_decl, false));
+ }
if (TREE_CODE (parm_pack) == PARM_DECL)
{
if (!cp_unevaluated_operand)
@@ -10269,6 +10281,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
= tsubst_expr (DECL_INITIAL (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/true);
+ else if (DECL_INITIAL (t))
+ {
+ /* Set up DECL_TEMPLATE_INFO so that we can get at the
+ NSDMI in perform_member_init. Still set DECL_INITIAL
+ so that we know there is one. */
+ DECL_INITIAL (r) = void_zero_node;
+ gcc_assert (DECL_LANG_SPECIFIC (r) == NULL);
+ retrofit_lang_decl (r);
+ DECL_TEMPLATE_INFO (r) = build_template_info (t, args);
+ }
/* We don't have to set DECL_CONTEXT here; it is set by
finish_member_declaration. */
DECL_CHAIN (r) = NULL_TREE;
@@ -11971,7 +11993,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
base, name,
/*template_p=*/false);
}
- else if (TREE_CODE (name) == BASELINK)
+ else if (BASELINK_P (name))
name = tsubst_baselink (name,
non_reference (TREE_TYPE (object)),
args, complain,
@@ -13489,6 +13511,9 @@ tsubst_copy_and_build (tree t,
tree unq = (tsubst_copy_and_build
(function, args, complain, in_decl, true,
integral_constant_expression_p));
+ if (unq == error_mark_node)
+ return error_mark_node;
+
if (unq != function)
{
tree fn = unq;
@@ -13937,8 +13962,8 @@ tsubst_copy_and_build (tree t,
{
tree r = build_lambda_expr ();
- tree type = tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
- TREE_TYPE (r) = type;
+ tree type = tsubst (LAMBDA_EXPR_CLOSURE (t), args, complain, NULL_TREE);
+ LAMBDA_EXPR_CLOSURE (r) = type;
CLASSTYPE_LAMBDA_EXPR (type) = r;
LAMBDA_EXPR_LOCATION (r)
@@ -15172,7 +15197,7 @@ resolve_nondeduced_context (tree orig_expr)
offset = expr;
expr = TREE_OPERAND (expr, 1);
}
- if (TREE_CODE (expr) == BASELINK)
+ if (BASELINK_P (expr))
{
baselink = expr;
expr = BASELINK_FUNCTIONS (expr);
@@ -15692,7 +15717,7 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
}
else
{
- tree bad_old_arg, bad_new_arg;
+ tree bad_old_arg = NULL_TREE, bad_new_arg = NULL_TREE;
tree old_args = ARGUMENT_PACK_ARGS (old_pack);
if (!comp_template_args_with_info (old_args, new_args,
@@ -18023,6 +18048,8 @@ instantiate_decl (tree d, int defer_ok,
d = DECL_CLONED_FUNCTION (d);
if (DECL_TEMPLATE_INSTANTIATED (d)
+ || (TREE_CODE (d) == FUNCTION_DECL
+ && DECL_DEFAULTED_FN (d) && DECL_INITIAL (d))
|| DECL_TEMPLATE_SPECIALIZATION (d))
/* D has already been instantiated or explicitly specialized, so
there's nothing for us to do here.
@@ -19287,7 +19314,7 @@ type_dependent_expression_p (tree expression)
if (TREE_CODE (expression) == SCOPE_REF)
return false;
- if (TREE_CODE (expression) == BASELINK)
+ if (BASELINK_P (expression))
expression = BASELINK_FUNCTIONS (expression);
if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 97f593cfb39..5f60eeedf4e 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1335,10 +1335,11 @@ lookup_conversion_operator (tree class_type, tree type)
}
/* TYPE is a class type. Return the index of the fields within
- the method vector with name NAME, or -1 if no such field exists. */
+ the method vector with name NAME, or -1 if no such field exists.
+ Does not lazily declare implicitly-declared member functions. */
-int
-lookup_fnfields_1 (tree type, tree name)
+static int
+lookup_fnfields_idx_nolazy (tree type, tree name)
{
VEC(tree,gc) *method_vec;
tree fn;
@@ -1348,34 +1349,6 @@ lookup_fnfields_1 (tree type, tree name)
if (!CLASS_TYPE_P (type))
return -1;
- if (COMPLETE_TYPE_P (type))
- {
- if ((name == ctor_identifier
- || name == base_ctor_identifier
- || name == complete_ctor_identifier))
- {
- if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
- lazily_declare_fn (sfk_constructor, type);
- if (CLASSTYPE_LAZY_COPY_CTOR (type))
- lazily_declare_fn (sfk_copy_constructor, type);
- if (CLASSTYPE_LAZY_MOVE_CTOR (type))
- lazily_declare_fn (sfk_move_constructor, type);
- }
- else if (name == ansi_assopname (NOP_EXPR))
- {
- if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
- lazily_declare_fn (sfk_copy_assignment, type);
- if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
- lazily_declare_fn (sfk_move_assignment, type);
- }
- else if ((name == dtor_identifier
- || name == base_dtor_identifier
- || name == complete_dtor_identifier
- || name == deleting_dtor_identifier)
- && CLASSTYPE_LAZY_DESTRUCTOR (type))
- lazily_declare_fn (sfk_destructor, type);
- }
-
method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec)
return -1;
@@ -1445,6 +1418,46 @@ lookup_fnfields_1 (tree type, tree name)
return -1;
}
+/* TYPE is a class type. Return the index of the fields within
+ the method vector with name NAME, or -1 if no such field exists. */
+
+int
+lookup_fnfields_1 (tree type, tree name)
+{
+ if (!CLASS_TYPE_P (type))
+ return -1;
+
+ if (COMPLETE_TYPE_P (type))
+ {
+ if ((name == ctor_identifier
+ || name == base_ctor_identifier
+ || name == complete_ctor_identifier))
+ {
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
+ lazily_declare_fn (sfk_constructor, type);
+ if (CLASSTYPE_LAZY_COPY_CTOR (type))
+ lazily_declare_fn (sfk_copy_constructor, type);
+ if (CLASSTYPE_LAZY_MOVE_CTOR (type))
+ lazily_declare_fn (sfk_move_constructor, type);
+ }
+ else if (name == ansi_assopname (NOP_EXPR))
+ {
+ if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
+ lazily_declare_fn (sfk_copy_assignment, type);
+ if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
+ lazily_declare_fn (sfk_move_assignment, type);
+ }
+ else if ((name == dtor_identifier
+ || name == base_dtor_identifier
+ || name == complete_dtor_identifier
+ || name == deleting_dtor_identifier)
+ && CLASSTYPE_LAZY_DESTRUCTOR (type))
+ lazily_declare_fn (sfk_destructor, type);
+ }
+
+ return lookup_fnfields_idx_nolazy (type, name);
+}
+
/* TYPE is a class type. Return the field within the method vector with
name NAME, or NULL_TREE if no such field exists. */
@@ -1457,6 +1470,17 @@ lookup_fnfields_slot (tree type, tree name)
return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
}
+/* As above, but avoid lazily declaring functions. */
+
+tree
+lookup_fnfields_slot_nolazy (tree type, tree name)
+{
+ int ix = lookup_fnfields_idx_nolazy (complete_type (type), name);
+ if (ix < 0)
+ return NULL_TREE;
+ return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
+}
+
/* Like lookup_fnfields_1, except that the name is extracted from
FUNCTION, which is a FUNCTION_DECL or a TEMPLATE_DECL. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index eed38e62f7b..d76df5156b4 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "c-family/c-objc.h"
#include "tree-inline.h"
#include "tree-mudflap.h"
+#include "intl.h"
#include "toplev.h"
#include "flags.h"
#include "output.h"
@@ -423,7 +424,7 @@ maybe_cleanup_point_expr (tree expr)
expression. The reason why we do this is because the original type might be
an aggregate and we cannot create a temporary variable for that type. */
-static tree
+tree
maybe_cleanup_point_expr_void (tree expr)
{
if (!processing_template_decl && stmts_are_full_exprs_p ())
@@ -2985,8 +2986,8 @@ finish_id_expression (tree id_expression,
else
{
error (TREE_CODE (decl) == VAR_DECL
- ? "use of %<auto%> variable from containing function"
- : "use of parameter from containing function");
+ ? G_("use of %<auto%> variable from containing function")
+ : G_("use of parameter from containing function"));
error (" %q+#D declared here", decl);
return error_mark_node;
}
@@ -3394,6 +3395,149 @@ finish_underlying_type (tree type)
return underlying_type;
}
+/* Implement the __direct_bases keyword: Return the direct base classes
+ of type */
+
+tree
+calculate_direct_bases (tree type)
+{
+ VEC(tree, gc) *vector = make_tree_vector();
+ tree bases_vec = NULL_TREE;
+ VEC(tree, none) *base_binfos;
+ tree binfo;
+ unsigned i;
+
+ complete_type (type);
+
+ if (!NON_UNION_CLASS_TYPE_P (type))
+ return make_tree_vec (0);
+
+ base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
+
+ /* Virtual bases are initialized first */
+ for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+ {
+ if (BINFO_VIRTUAL_P (binfo))
+ {
+ VEC_safe_push (tree, gc, vector, binfo);
+ }
+ }
+
+ /* Now non-virtuals */
+ for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++)
+ {
+ if (!BINFO_VIRTUAL_P (binfo))
+ {
+ VEC_safe_push (tree, gc, vector, binfo);
+ }
+ }
+
+
+ bases_vec = make_tree_vec (VEC_length (tree, vector));
+
+ for (i = 0; i < VEC_length (tree, vector); ++i)
+ {
+ TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i));
+ }
+ return bases_vec;
+}
+
+/* Implement the __bases keyword: Return the base classes
+ of type */
+
+/* Find morally non-virtual base classes by walking binfo hierarchy */
+/* Virtual base classes are handled separately in finish_bases */
+
+static tree
+dfs_calculate_bases_pre (tree binfo, ATTRIBUTE_UNUSED void *data_)
+{
+ /* Don't walk bases of virtual bases */
+ return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE;
+}
+
+static tree
+dfs_calculate_bases_post (tree binfo, void *data_)
+{
+ VEC(tree, gc) **data = (VEC(tree, gc) **) data_;
+ if (!BINFO_VIRTUAL_P (binfo))
+ {
+ VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo));
+ }
+ return NULL_TREE;
+}
+
+/* Calculates the morally non-virtual base classes of a class */
+static VEC(tree, gc) *
+calculate_bases_helper (tree type)
+{
+ VEC(tree, gc) *vector = make_tree_vector();
+
+ /* Now add non-virtual base classes in order of construction */
+ dfs_walk_all (TYPE_BINFO (type),
+ dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector);
+ return vector;
+}
+
+tree
+calculate_bases (tree type)
+{
+ VEC(tree, gc) *vector = make_tree_vector();
+ tree bases_vec = NULL_TREE;
+ unsigned i;
+ VEC(tree, gc) *vbases;
+ VEC(tree, gc) *nonvbases;
+ tree binfo;
+
+ complete_type (type);
+
+ if (!NON_UNION_CLASS_TYPE_P (type))
+ return make_tree_vec (0);
+
+ /* First go through virtual base classes */
+ for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
+ VEC_iterate (tree, vbases, i, binfo); i++)
+ {
+ VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo));
+ VEC_safe_splice (tree, gc, vector, vbase_bases);
+ release_tree_vector (vbase_bases);
+ }
+
+ /* Now for the non-virtual bases */
+ nonvbases = calculate_bases_helper (type);
+ VEC_safe_splice (tree, gc, vector, nonvbases);
+ release_tree_vector (nonvbases);
+
+ /* Last element is entire class, so don't copy */
+ bases_vec = make_tree_vec (VEC_length (tree, vector) - 1);
+
+ for (i = 0; i < VEC_length (tree, vector) - 1; ++i)
+ {
+ TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i);
+ }
+ release_tree_vector (vector);
+ return bases_vec;
+}
+
+tree
+finish_bases (tree type, bool direct)
+{
+ tree bases = NULL_TREE;
+
+ if (!processing_template_decl)
+ {
+ /* Parameter packs can only be used in templates */
+ error ("Parameter pack __bases only valid in template declaration");
+ return error_mark_node;
+ }
+
+ bases = cxx_make_type (BASES);
+ BASES_TYPE (bases) = type;
+ BASES_DIRECT (bases) = direct;
+ SET_TYPE_STRUCTURAL_EQUALITY (bases);
+
+ return bases;
+}
+
/* Perform C++-specific checks for __builtin_offsetof before calling
fold_offsetof. */
@@ -4971,7 +5115,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
step. */
expr = TREE_OPERAND (expr, 1);
- if (TREE_CODE (expr) == BASELINK)
+ if (BASELINK_P (expr))
/* See through BASELINK nodes to the underlying function. */
expr = BASELINK_FUNCTIONS (expr);
@@ -5210,23 +5354,20 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
}
}
-/* Returns true if TYPE is a complete type, an array of unknown bound,
- or (possibly cv-qualified) void, returns false otherwise. */
+/* If TYPE is an array of unknown bound, or (possibly cv-qualified)
+ void, or a complete type, returns it, otherwise NULL_TREE. */
-static bool
+static tree
check_trait_type (tree type)
{
- if (COMPLETE_TYPE_P (type))
- return true;
-
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))
- return true;
+ return type;
if (VOID_TYPE_P (type))
- return true;
+ return type;
- return false;
+ return complete_type_or_else (strip_array_types (type), NULL_TREE);
}
/* Process a trait expression. */
@@ -5276,10 +5417,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
return trait_expr;
}
- complete_type (type1);
- if (type2)
- complete_type (type2);
-
switch (kind)
{
case CPTK_HAS_NOTHROW_ASSIGN:
@@ -5298,20 +5435,15 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2)
case CPTK_IS_STD_LAYOUT:
case CPTK_IS_TRIVIAL:
if (!check_trait_type (type1))
- {
- error ("incomplete type %qT not allowed", type1);
- return error_mark_node;
- }
+ return error_mark_node;
break;
case CPTK_IS_BASE_OF:
if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
&& !same_type_ignoring_top_level_qualifiers_p (type1, type2)
- && !COMPLETE_TYPE_P (type2))
- {
- error ("incomplete type %qT not allowed", type2);
- return error_mark_node;
- }
+ && !complete_type_or_else (type2, NULL_TREE))
+ /* We already issued an error. */
+ return error_mark_node;
break;
case CPTK_IS_CLASS:
@@ -6548,6 +6680,12 @@ cxx_eval_component_reference (const constexpr_call *call, tree t,
error ("%qE is not a constant expression", orig_whole);
*non_constant_p = true;
}
+ if (DECL_MUTABLE_P (part))
+ {
+ if (!allow_non_constant)
+ error ("mutable %qD is not usable in a constant expression", part);
+ *non_constant_p = true;
+ }
if (*non_constant_p)
return t;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
@@ -7533,6 +7671,18 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant)
verify_constant (r, allow_non_constant, &non_constant_p);
+ if (TREE_CODE (t) != CONSTRUCTOR
+ && cp_has_mutable_p (TREE_TYPE (t)))
+ {
+ /* We allow a mutable type if the original expression was a
+ CONSTRUCTOR so that we can do aggregate initialization of
+ constexpr variables. */
+ if (!allow_non_constant)
+ error ("%qT cannot be the type of a complete constant expression "
+ "because it has mutable sub-objects", TREE_TYPE (t));
+ non_constant_p = true;
+ }
+
if (non_constant_p && !allow_non_constant)
return error_mark_node;
else if (non_constant_p && TREE_CONSTANT (t))
@@ -7733,6 +7883,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case TEMPLATE_PARM_INDEX:
case TRAIT_EXPR:
case IDENTIFIER_NODE:
+ case USERDEF_LITERAL:
/* We can see a FIELD_DECL in a pointer-to-member expression. */
case FIELD_DECL:
case PARM_DECL:
@@ -8209,7 +8360,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
return false;
default:
- sorry ("unexpected ast of kind %s", tree_code_name[TREE_CODE (t)]);
+ sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]);
gcc_unreachable();
return false;
}
@@ -8324,7 +8475,7 @@ build_lambda_object (tree lambda_expr)
/* N2927: "[The closure] class type is not an aggregate."
But we briefly treat it as an aggregate to make this simpler. */
- type = TREE_TYPE (lambda_expr);
+ type = LAMBDA_EXPR_CLOSURE (lambda_expr);
CLASSTYPE_NON_AGGREGATE (type) = 0;
expr = finish_compound_literal (type, expr, tf_warning_or_error);
CLASSTYPE_NON_AGGREGATE (type) = 1;
@@ -8365,7 +8516,7 @@ begin_lambda_type (tree lambda)
type = begin_class_definition (type, /*attributes=*/NULL_TREE);
/* Cross-reference the expression and the type. */
- TREE_TYPE (lambda) = type;
+ LAMBDA_EXPR_CLOSURE (lambda) = type;
CLASSTYPE_LAMBDA_EXPR (type) = lambda;
return type;
@@ -8399,7 +8550,7 @@ lambda_function (tree lambda)
{
tree type;
if (TREE_CODE (lambda) == LAMBDA_EXPR)
- type = TREE_TYPE (lambda);
+ type = LAMBDA_EXPR_CLOSURE (lambda);
else
type = lambda;
gcc_assert (LAMBDA_TYPE_P (type));
@@ -8714,7 +8865,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
/* If TREE_TYPE isn't set, we're still in the introducer, so check
for duplicates. */
- if (!TREE_TYPE (lambda))
+ if (!LAMBDA_EXPR_CLOSURE (lambda))
{
if (IDENTIFIER_MARKED (name))
{
@@ -8740,13 +8891,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
LAMBDA_EXPR_THIS_CAPTURE (lambda) = member;
/* Add it to the appropriate closure class if we've started it. */
- if (current_class_type && current_class_type == TREE_TYPE (lambda))
+ if (current_class_type
+ && current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
finish_member_declaration (member);
LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
- if (TREE_TYPE (lambda))
+ if (LAMBDA_EXPR_CLOSURE (lambda))
return build_capture_proxy (member);
/* For explicit captures we haven't started the function yet, so we wait
and build the proxy from cp_parser_lambda_body. */
@@ -8789,7 +8941,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
{
tree lambda = TREE_VALUE (node);
- current_class_type = TREE_TYPE (lambda);
+ current_class_type = LAMBDA_EXPR_CLOSURE (lambda);
var = add_capture (lambda,
id,
initializer,
@@ -8820,7 +8972,7 @@ lambda_expr_this_capture (tree lambda)
if (!this_capture
&& LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE)
{
- tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda));
+ tree containing_function = TYPE_CONTEXT (LAMBDA_EXPR_CLOSURE (lambda));
tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE);
tree init = NULL_TREE;
@@ -8870,7 +9022,8 @@ lambda_expr_this_capture (tree lambda)
else
{
/* To make sure that current_class_ref is for the lambda. */
- gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda));
+ gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref))
+ == LAMBDA_EXPR_CLOSURE (lambda));
result = this_capture;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 75aa2650300..707f2c8aeba 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1879,8 +1879,12 @@ bot_manip (tree* tp, int* walk_subtrees, void* data)
tree u;
if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
- u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),
- tf_warning_or_error);
+ {
+ u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),
+ tf_warning_or_error);
+ if (AGGR_INIT_ZERO_FIRST (TREE_OPERAND (t, 1)))
+ AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true;
+ }
else
u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t),
tf_warning_or_error);
@@ -3341,11 +3345,20 @@ stabilize_init (tree init, tree *initp)
/* Aggregate initialization: stabilize each of the field
initializers. */
unsigned i;
- tree value;
+ constructor_elt *ce;
bool good = true;
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, value)
- if (!stabilize_init (value, initp))
- good = false;
+ VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (t);
+ for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
+ {
+ tree type = TREE_TYPE (ce->value);
+ tree subinit;
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ || SCALAR_TYPE_P (type))
+ ce->value = stabilize_expr (ce->value, &subinit);
+ else if (!stabilize_init (ce->value, &subinit))
+ good = false;
+ *initp = add_stmt_to_compound (*initp, subinit);
+ }
return good;
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 305f8f5b937..0b1f217a908 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -510,8 +510,12 @@ composite_pointer_type_r (tree t1, tree t2,
&& TREE_CODE (pointee2) == POINTER_TYPE)
|| (TYPE_PTR_TO_MEMBER_P (pointee1)
&& TYPE_PTR_TO_MEMBER_P (pointee2)))
- result_type = composite_pointer_type_r (pointee1, pointee2, operation,
- complain);
+ {
+ result_type = composite_pointer_type_r (pointee1, pointee2, operation,
+ complain);
+ if (result_type == error_mark_node)
+ return error_mark_node;
+ }
else
{
if (complain & tf_error)
@@ -2128,8 +2132,16 @@ build_class_member_access_expr (tree object, tree member,
if (!CLASS_TYPE_P (object_type))
{
if (complain & tf_error)
- error ("request for member %qD in %qE, which is of non-class type %qT",
- member, object, object_type);
+ {
+ if (POINTER_TYPE_P (object_type)
+ && CLASS_TYPE_P (TREE_TYPE (object_type)))
+ error ("request for member %qD in %qE, which is of pointer "
+ "type %qT (maybe you meant to use %<->%> ?)",
+ member, object, object_type);
+ else
+ error ("request for member %qD in %qE, which is of non-class "
+ "type %qT", member, object, object_type);
+ }
return error_mark_node;
}
@@ -2508,8 +2520,16 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
if (!CLASS_TYPE_P (object_type))
{
if (complain & tf_error)
- error ("request for member %qD in %qE, which is of non-class type %qT",
- name, object, object_type);
+ {
+ if (POINTER_TYPE_P (object_type)
+ && CLASS_TYPE_P (TREE_TYPE (object_type)))
+ error ("request for member %qD in %qE, which is of pointer "
+ "type %qT (maybe you meant to use %<->%> ?)",
+ name, object, object_type);
+ else
+ error ("request for member %qD in %qE, which is of non-class "
+ "type %qT", name, object, object_type);
+ }
return error_mark_node;
}
@@ -2591,7 +2611,9 @@ finish_class_member_access_expr (tree object, tree name, bool template_p,
if (member == NULL_TREE)
{
if (complain & tf_error)
- error ("%qD has no member named %qE", object_type, name);
+ error ("%qD has no member named %qE",
+ TREE_CODE (access_path) == TREE_BINFO
+ ? TREE_TYPE (access_path) : object_type, name);
return error_mark_node;
}
if (member == error_mark_node)
@@ -4036,7 +4058,7 @@ cp_build_binary_op (location_t location,
else
{
op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
- op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
+ op1 = cp_convert (TREE_TYPE (op0), op1);
}
result_type = TREE_TYPE (op0);
}
@@ -4646,7 +4668,17 @@ cp_truthvalue_conversion (tree expr)
tree type = TREE_TYPE (expr);
if (TYPE_PTRMEM_P (type))
return build_binary_op (EXPR_LOCATION (expr),
- NE_EXPR, expr, integer_zero_node, 1);
+ NE_EXPR, expr, nullptr_node, 1);
+ else if (TYPE_PTR_P (type) || TYPE_PTRMEMFUNC_P (type))
+ {
+ /* With -Wzero-as-null-pointer-constant do not warn for an
+ 'if (p)' or a 'while (!p)', where p is a pointer. */
+ tree ret;
+ ++c_inhibit_evaluation_warnings;
+ ret = c_common_truthvalue_conversion (input_location, expr);
+ --c_inhibit_evaluation_warnings;
+ return ret;
+ }
else
return c_common_truthvalue_conversion (input_location, expr);
}
@@ -4924,7 +4956,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
if (TREE_CODE (arg) == OFFSET_REF)
PTRMEM_OK_P (val) = PTRMEM_OK_P (arg);
}
- else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
+ else if (BASELINK_P (TREE_OPERAND (arg, 1)))
{
tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
@@ -6313,34 +6345,41 @@ build_const_cast_1 (tree dst_type, tree expr, tsubst_flags_t complain,
return error_mark_node;
}
- if ((TYPE_PTR_P (src_type) || TYPE_PTRMEM_P (src_type))
- && comp_ptr_ttypes_const (dst_type, src_type))
+ if (TYPE_PTR_P (src_type) || TYPE_PTRMEM_P (src_type))
{
- if (valid_p)
- {
- *valid_p = true;
- /* This cast is actually a C-style cast. Issue a warning if
- the user is making a potentially unsafe cast. */
- check_for_casting_away_constness (src_type, dst_type, CAST_EXPR,
- complain);
- }
- if (reference_type)
+ if (comp_ptr_ttypes_const (dst_type, src_type))
{
- expr = cp_build_addr_expr (expr, complain);
- expr = build_nop (reference_type, expr);
- return convert_from_reference (expr);
- }
- else
- {
- expr = decay_conversion (expr);
- /* build_c_cast puts on a NOP_EXPR to make the result not an
- lvalue. Strip such NOP_EXPRs if VALUE is being used in
- non-lvalue context. */
- if (TREE_CODE (expr) == NOP_EXPR
- && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
- expr = TREE_OPERAND (expr, 0);
- return build_nop (dst_type, expr);
+ if (valid_p)
+ {
+ *valid_p = true;
+ /* This cast is actually a C-style cast. Issue a warning if
+ the user is making a potentially unsafe cast. */
+ check_for_casting_away_constness (src_type, dst_type,
+ CAST_EXPR, complain);
+ }
+ if (reference_type)
+ {
+ expr = cp_build_addr_expr (expr, complain);
+ expr = build_nop (reference_type, expr);
+ return convert_from_reference (expr);
+ }
+ else
+ {
+ expr = decay_conversion (expr);
+ /* build_c_cast puts on a NOP_EXPR to make the result not an
+ lvalue. Strip such NOP_EXPRs if VALUE is being used in
+ non-lvalue context. */
+ if (TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
+ return build_nop (dst_type, expr);
+ }
}
+ else if (valid_p
+ && !at_least_as_qualified_p (TREE_TYPE (dst_type),
+ TREE_TYPE (src_type)))
+ check_for_casting_away_constness (src_type, dst_type, CAST_EXPR,
+ complain);
}
if (complain & tf_error)
@@ -7126,7 +7165,7 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
/* Handle null pointer to member function conversions. */
if (null_ptr_cst_p (pfn))
{
- pfn = build_c_cast (input_location, type, integer_zero_node);
+ pfn = build_c_cast (input_location, type, nullptr_node);
return build_ptrmemfunc1 (to_type,
integer_zero_node,
pfn);
@@ -8300,7 +8339,7 @@ casts_away_constness (tree t1, tree t2)
tree
non_reference (tree t)
{
- if (TREE_CODE (t) == REFERENCE_TYPE)
+ if (t && TREE_CODE (t) == REFERENCE_TYPE)
t = TREE_TYPE (t);
return t;
}
@@ -8334,3 +8373,124 @@ lvalue_or_else (tree ref, enum lvalue_use use, tsubst_flags_t complain)
return 1;
}
+/* Return true if a user-defined literal operator is a raw operator. */
+
+bool
+check_raw_literal_operator (const_tree decl)
+{
+ tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ tree argtype;
+ int arity;
+ bool maybe_raw_p = false;
+
+ /* Count the number and type of arguments and check for ellipsis. */
+ for (argtype = argtypes, arity = 0;
+ argtype && argtype != void_list_node;
+ ++arity, argtype = TREE_CHAIN (argtype))
+ {
+ tree t = TREE_VALUE (argtype);
+
+ if (same_type_p (t, const_string_type_node))
+ maybe_raw_p = true;
+ }
+ if (!argtype)
+ return false; /* Found ellipsis. */
+
+ if (!maybe_raw_p || arity != 1)
+ return false;
+
+ return true;
+}
+
+
+/* Return true if a user-defined literal operator has one of the allowed
+ argument types. */
+
+bool
+check_literal_operator_args (const_tree decl,
+ bool *long_long_unsigned_p, bool *long_double_p)
+{
+ tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ if (processing_template_decl)
+ return (argtypes == NULL_TREE
+ || same_type_p (TREE_VALUE (argtypes), void_type_node));
+ else
+ {
+ tree argtype;
+ int arity;
+ int max_arity = 2;
+ bool found_string_p = false;
+ bool maybe_raw_p = false;
+ bool found_size_p = false;
+
+ *long_long_unsigned_p = false;
+ *long_double_p = false;
+
+ /* Count the number and type of arguments and check for ellipsis. */
+ for (argtype = argtypes, arity = 0;
+ argtype && argtype != void_list_node;
+ argtype = TREE_CHAIN (argtype))
+ {
+ tree t = TREE_VALUE (argtype);
+ ++arity;
+
+ if (TREE_CODE (t) == POINTER_TYPE)
+ {
+ t = TREE_TYPE (t);
+ if (cp_type_quals (t) != TYPE_QUAL_CONST)
+ return false;
+ t = TYPE_MAIN_VARIANT (t);
+ if (same_type_p (t, char_type_node))
+ {
+ found_string_p = true;
+ maybe_raw_p = true;
+ }
+ else if (same_type_p (t, wchar_type_node))
+ found_string_p = true;
+ else if (same_type_p (t, char16_type_node))
+ found_string_p = true;
+ else if (same_type_p (t, char32_type_node))
+ found_string_p = true;
+ else
+ return false;
+ }
+ else if (same_type_p (t, size_type_node))
+ {
+ if (!found_string_p)
+ return false;
+ found_size_p = true;
+ }
+ else if (same_type_p (t, long_long_unsigned_type_node))
+ {
+ max_arity = 1;
+ *long_long_unsigned_p = true;
+ }
+ else if (same_type_p (t, long_double_type_node))
+ {
+ max_arity = 1;
+ *long_double_p = true;
+ }
+ else if (same_type_p (t, char_type_node))
+ max_arity = 1;
+ else if (same_type_p (t, wchar_type_node))
+ max_arity = 1;
+ else if (same_type_p (t, char16_type_node))
+ max_arity = 1;
+ else if (same_type_p (t, char32_type_node))
+ max_arity = 1;
+ else
+ return false;
+ }
+ if (!argtype)
+ return false; /* Found ellipsis. */
+
+ if (arity > max_arity)
+ return false;
+
+ if (found_string_p && !maybe_raw_p && !found_size_p)
+ return false;
+
+ return true;
+ }
+}
+
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 3accab62133..57cd5e01d8c 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -428,8 +428,15 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type,
case OFFSET_TYPE:
bad_member:
- emit_diagnostic (diag_kind, input_location, 0,
- "invalid use of member (did you forget the %<&%> ?)");
+ if (DECL_FUNCTION_MEMBER_P (TREE_OPERAND (value, 1))
+ && ! flag_ms_extensions)
+ emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of member function "
+ "(did you forget the %<()%> ?)");
+ else
+ emit_diagnostic (diag_kind, input_location, 0,
+ "invalid use of member "
+ "(did you forget the %<&%> ?)");
break;
case TEMPLATE_TYPE_PARM:
@@ -566,7 +573,15 @@ split_nonconstant_init_1 (tree dest, tree init)
code = build2 (INIT_EXPR, inner_type, sub, value);
code = build_stmt (input_location, EXPR_STMT, code);
+ code = maybe_cleanup_point_expr_void (code);
add_stmt (code);
+ if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type))
+ {
+ code = (build_special_member_call
+ (sub, complete_dtor_identifier, NULL, inner_type,
+ LOOKUP_NORMAL, tf_warning_or_error));
+ finish_eh_cleanup (code);
+ }
num_split_elts++;
}
diff --git a/gcc/cppdefault.c b/gcc/cppdefault.c
index 9b1495feb94..099899a7726 100644
--- a/gcc/cppdefault.c
+++ b/gcc/cppdefault.c
@@ -1,6 +1,7 @@
/* CPP Library.
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2003, 2004, 2006, 2007, 2010 Free Software Foundation, Inc.
+ 1999, 2000, 2003, 2004, 2006, 2007, 2010, 2011
+ Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -25,18 +26,13 @@
#include "tm.h"
#include "cppdefault.h"
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
-#endif
-
-#ifndef STANDARD_INCLUDE_COMPONENT
-#define STANDARD_INCLUDE_COMPONENT 0
+#ifndef NATIVE_SYSTEM_HEADER_COMPONENT
+#define NATIVE_SYSTEM_HEADER_COMPONENT 0
#endif
#if defined (CROSS_DIRECTORY_STRUCTURE) && !defined (TARGET_SYSTEM_ROOT)
# undef LOCAL_INCLUDE_DIR
-# undef SYSTEM_INCLUDE_DIR
-# undef STANDARD_INCLUDE_DIR
+# undef NATIVE_SYSTEM_HEADER_DIR
#else
# undef CROSS_INCLUDE_DIR
#endif
@@ -89,13 +85,9 @@ const struct default_include cpp_include_defaults[]
/* Another place the target system's headers might be. */
{ TOOL_INCLUDE_DIR, "BINUTILS", 0, 1, 0, 0 },
#endif
-#ifdef SYSTEM_INCLUDE_DIR
- /* Some systems have an extra dir of include files. */
- { SYSTEM_INCLUDE_DIR, 0, 0, 0, 1, 0 },
-#endif
-#ifdef STANDARD_INCLUDE_DIR
+#ifdef NATIVE_SYSTEM_HEADER_DIR
/* /usr/include comes dead last. */
- { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0, 1, 0 },
+ { NATIVE_SYSTEM_HEADER_DIR, NATIVE_SYSTEM_HEADER_COMPONENT, 0, 0, 1, 0 },
#endif
{ 0, 0, 0, 0, 0, 0 }
};
@@ -136,4 +128,3 @@ cpp_relocated (void)
return relocated;
}
-
diff --git a/gcc/crtstuff.c b/gcc/crtstuff.c
deleted file mode 100644
index 010d472765d..00000000000
--- a/gcc/crtstuff.c
+++ /dev/null
@@ -1,650 +0,0 @@
-/* Specialized bits of code needed to support construction and
- destruction of file-scope objects in C++ code.
- Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
- Free Software Foundation, Inc.
- Contributed by Ron Guilmette (rfg@monkeys.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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-/* This file is a bit like libgcc2.c in that it is compiled
- multiple times and yields multiple .o files.
-
- This file is useful on target machines where the object file format
- supports multiple "user-defined" sections (e.g. COFF, ELF, ROSE). On
- such systems, this file allows us to avoid running collect (or any
- other such slow and painful kludge). Additionally, if the target
- system supports a .init section, this file allows us to support the
- linking of C++ code with a non-C++ main program.
-
- Note that if INIT_SECTION_ASM_OP is defined in the tm.h file, then
- this file *will* make use of the .init section. If that symbol is
- not defined however, then the .init section will not be used.
-
- Currently, only ELF and COFF are supported. It is likely however that
- ROSE could also be supported, if someone was willing to do the work to
- make whatever (small?) adaptations are needed. (Some work may be
- needed on the ROSE assembler and linker also.)
-
- This file must be compiled with gcc. */
-
-/* Target machine header files require this define. */
-#define IN_LIBGCC2
-
-/* FIXME: Including auto-host is incorrect, but until we have
- identified the set of defines that need to go into auto-target.h,
- this will have to do. */
-#include "auto-host.h"
-#undef pid_t
-#undef rlim_t
-#undef ssize_t
-#undef vfork
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "unwind-dw2-fde.h"
-
-#ifndef FORCE_CODE_SECTION_ALIGN
-# define FORCE_CODE_SECTION_ALIGN
-#endif
-
-#ifndef CRT_CALL_STATIC_FUNCTION
-# define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
-static void __attribute__((__used__)) \
-call_ ## FUNC (void) \
-{ \
- asm (SECTION_OP); \
- FUNC (); \
- FORCE_CODE_SECTION_ALIGN \
- asm (TEXT_SECTION_ASM_OP); \
-}
-#endif
-
-#if defined(OBJECT_FORMAT_ELF) \
- && !defined(OBJECT_FORMAT_FLAT) \
- && defined(HAVE_LD_EH_FRAME_HDR) \
- && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
- && defined(__FreeBSD__) && __FreeBSD__ >= 7
-#include <link.h>
-# define USE_PT_GNU_EH_FRAME
-#endif
-
-#if defined(OBJECT_FORMAT_ELF) \
- && !defined(OBJECT_FORMAT_FLAT) \
- && defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR) \
- && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
- && defined(__sun__) && defined(__svr4__)
-#include <link.h>
-# define USE_PT_GNU_EH_FRAME
-#endif
-
-#if defined(OBJECT_FORMAT_ELF) \
- && !defined(OBJECT_FORMAT_FLAT) \
- && defined(HAVE_LD_EH_FRAME_HDR) \
- && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
- && defined(__GLIBC__) && __GLIBC__ >= 2
-#include <link.h>
-/* uClibc pretends to be glibc 2.2 and DT_CONFIG is defined in its link.h.
- But it doesn't use PT_GNU_EH_FRAME ELF segment currently. */
-# if !defined(__UCLIBC__) \
- && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
- || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
-# define USE_PT_GNU_EH_FRAME
-# endif
-#endif
-#if defined(EH_FRAME_SECTION_NAME) && !defined(USE_PT_GNU_EH_FRAME)
-# define USE_EH_FRAME_REGISTRY
-#endif
-#if defined(EH_FRAME_SECTION_NAME) && EH_TABLES_CAN_BE_READ_ONLY
-# define EH_FRAME_SECTION_CONST const
-#else
-# define EH_FRAME_SECTION_CONST
-#endif
-
-#if !defined(DTOR_LIST_END) && defined(OBJECT_FORMAT_ELF) \
- && defined(HAVE_GAS_HIDDEN) && !defined(FINI_ARRAY_SECTION_ASM_OP)
-# define HIDDEN_DTOR_LIST_END
-#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
- these symbols to be weak as well.
-
- This exposes a core issue, how to handle creating weak references vs
- how to create weak definitions. Either we have to have the definition
- of TARGET_WEAK_ATTRIBUTE be conditional in the shared header files or
- have a second declaration if we want a function's references to be weak,
- but not its definition.
-
- Making TARGET_WEAK_ATTRIBUTE conditional seems like a good solution until
- one thinks about scaling to larger problems -- i.e., the condition under
- which TARGET_WEAK_ATTRIBUTE is active will eventually get far too
- complicated.
-
- So, we take an approach similar to #pragma weak -- we have a second
- declaration for functions that we want to have weak references.
-
- Neither way is particularly good. */
-
-/* References to __register_frame_info and __deregister_frame_info should
- be weak in this file if at all possible. */
-extern void __register_frame_info (const void *, struct object *)
- TARGET_ATTRIBUTE_WEAK;
-extern void __register_frame_info_bases (const void *, struct object *,
- void *, void *)
- TARGET_ATTRIBUTE_WEAK;
-extern void *__deregister_frame_info (const void *)
- TARGET_ATTRIBUTE_WEAK;
-extern void *__deregister_frame_info_bases (const void *)
- TARGET_ATTRIBUTE_WEAK;
-extern void __do_global_ctors_1 (void);
-
-/* Likewise for _Jv_RegisterClasses. */
-extern void _Jv_RegisterClasses (void *) TARGET_ATTRIBUTE_WEAK;
-
-#ifdef OBJECT_FORMAT_ELF
-
-/* Declare a pointer to void function type. */
-typedef void (*func_ptr) (void);
-#define STATIC static
-
-#else /* OBJECT_FORMAT_ELF */
-
-#include "gbl-ctors.h"
-
-#define STATIC
-
-#endif /* OBJECT_FORMAT_ELF */
-
-#ifdef CRT_BEGIN
-
-/* NOTE: In order to be able to support SVR4 shared libraries, we arrange
- to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
- __DTOR_END__ } per root executable and also one set of these symbols
- per shared library. So in any given whole process image, we may have
- multiple definitions of each of these symbols. In order to prevent
- these definitions from conflicting with one another, and in order to
- ensure that the proper lists are used for the initialization/finalization
- of each individual shared library (respectively), we give these symbols
- only internal (i.e. `static') linkage, and we also make it a point to
- refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
- symbol in crtbegin.o, where they are defined. */
-
-/* No need for .ctors/.dtors section if linker can place them in
- .init_array/.fini_array section. */
-#ifndef USE_INITFINI_ARRAY
-/* The -1 is a flag to __do_global_[cd]tors indicating that this table
- does not start with a count of elements. */
-#ifdef CTOR_LIST_BEGIN
-CTOR_LIST_BEGIN;
-#elif defined(CTORS_SECTION_ASM_OP)
-/* Hack: force cc1 to switch to .data section early, so that assembling
- __CTOR_LIST__ does not undo our behind-the-back change to .ctors. */
-static func_ptr force_to_data[1] __attribute__ ((__used__)) = { };
-asm (CTORS_SECTION_ASM_OP);
-STATIC func_ptr __CTOR_LIST__[1]
- __attribute__ ((__used__, aligned(sizeof(func_ptr))))
- = { (func_ptr) (-1) };
-#else
-STATIC func_ptr __CTOR_LIST__[1]
- __attribute__ ((__used__, section(".ctors"), aligned(sizeof(func_ptr))))
- = { (func_ptr) (-1) };
-#endif /* __CTOR_LIST__ alternatives */
-
-#ifdef DTOR_LIST_BEGIN
-DTOR_LIST_BEGIN;
-#elif defined(DTORS_SECTION_ASM_OP)
-asm (DTORS_SECTION_ASM_OP);
-STATIC func_ptr __DTOR_LIST__[1]
- __attribute__ ((aligned(sizeof(func_ptr))))
- = { (func_ptr) (-1) };
-#else
-STATIC func_ptr __DTOR_LIST__[1]
- __attribute__((section(".dtors"), aligned(sizeof(func_ptr))))
- = { (func_ptr) (-1) };
-#endif /* __DTOR_LIST__ alternatives */
-#endif /* USE_INITFINI_ARRAY */
-
-#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 EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
- __attribute__((section(EH_FRAME_SECTION_NAME), aligned(4)))
- = { };
-#endif /* USE_EH_FRAME_REGISTRY */
-
-#ifdef JCR_SECTION_NAME
-/* Stick a label at the beginning of the java class registration info
- so we can register them properly. */
-STATIC void *__JCR_LIST__[]
- __attribute__ ((used, section(JCR_SECTION_NAME), aligned(sizeof(void*))))
- = { };
-#endif /* JCR_SECTION_NAME */
-
-#if defined(INIT_SECTION_ASM_OP) || defined(INIT_ARRAY_SECTION_ASM_OP)
-
-#ifdef OBJECT_FORMAT_ELF
-
-/* Declare the __dso_handle variable. It should have a unique value
- in every shared-object; in a main program its value is zero. The
- object should in any case be protected. This means the instance
- in one DSO or the main program is not used in another object. The
- dynamic linker takes care of this. */
-
-#ifdef TARGET_LIBGCC_SDATA_SECTION
-extern void *__dso_handle __attribute__ ((__section__ (TARGET_LIBGCC_SDATA_SECTION)));
-#endif
-#ifdef HAVE_GAS_HIDDEN
-extern void *__dso_handle __attribute__ ((__visibility__ ("hidden")));
-#endif
-#ifdef CRTSTUFFS_O
-void *__dso_handle = &__dso_handle;
-#else
-void *__dso_handle = 0;
-#endif
-
-/* The __cxa_finalize function may not be available so we use only a
- weak declaration. */
-extern void __cxa_finalize (void *) TARGET_ATTRIBUTE_WEAK;
-
-/* Run all the global destructors on exit from the program. */
-
-/* Some systems place the number of pointers in the first word of the
- table. On SVR4 however, that word is -1. In all cases, the table is
- null-terminated. On SVR4, we start from the beginning of the list and
- invoke each per-compilation-unit destructor routine in order
- until we find that null.
-
- Note that this function MUST be static. There will be one of these
- functions in each root executable and one in each shared library, but
- although they all have the same code, each one is unique in that it
- refers to one particular associated `__DTOR_LIST__' which belongs to the
- same particular root executable or shared library file.
-
- On some systems, this routine is run more than once from the .fini,
- when exit is called recursively, so we arrange to remember where in
- the list we left off processing, and we resume at that point,
- should we be re-invoked. */
-
-static void __attribute__((used))
-__do_global_dtors_aux (void)
-{
- static _Bool completed;
-
- if (__builtin_expect (completed, 0))
- return;
-
-#ifdef CRTSTUFFS_O
- if (__cxa_finalize)
- __cxa_finalize (__dso_handle);
-#endif
-
-#ifdef FINI_ARRAY_SECTION_ASM_OP
- /* If we are using .fini_array then destructors will be run via that
- mechanism. */
-#elif defined(HIDDEN_DTOR_LIST_END)
- {
- /* Safer version that makes sure only .dtors function pointers are
- called even if the static variable is maliciously changed. */
- extern func_ptr __DTOR_END__[] __attribute__((visibility ("hidden")));
- static size_t dtor_idx;
- const size_t max_idx = __DTOR_END__ - __DTOR_LIST__ - 1;
- func_ptr f;
-
- while (dtor_idx < max_idx)
- {
- f = __DTOR_LIST__[++dtor_idx];
- f ();
- }
- }
-#else /* !defined (FINI_ARRAY_SECTION_ASM_OP) */
- {
- static func_ptr *p = __DTOR_LIST__ + 1;
- func_ptr f;
-
- while ((f = *p))
- {
- p++;
- f ();
- }
- }
-#endif /* !defined(FINI_ARRAY_SECTION_ASM_OP) */
-
-#ifdef USE_EH_FRAME_REGISTRY
-#ifdef CRT_GET_RFIB_DATA
- /* If we used the new __register_frame_info_bases interface,
- make sure that we deregister from the same place. */
- if (__deregister_frame_info_bases)
- __deregister_frame_info_bases (__EH_FRAME_BEGIN__);
-#else
- if (__deregister_frame_info)
- __deregister_frame_info (__EH_FRAME_BEGIN__);
-#endif
-#endif
-
- completed = 1;
-}
-
-/* Stick a call to __do_global_dtors_aux into the .fini section. */
-#ifdef FINI_SECTION_ASM_OP
-CRT_CALL_STATIC_FUNCTION (FINI_SECTION_ASM_OP, __do_global_dtors_aux)
-#elif defined (FINI_ARRAY_SECTION_ASM_OP)
-static func_ptr __do_global_dtors_aux_fini_array_entry[]
- __attribute__ ((__used__, section(".fini_array")))
- = { __do_global_dtors_aux };
-#else /* !FINI_SECTION_ASM_OP && !FINI_ARRAY_SECTION_ASM_OP */
-static void __attribute__((used))
-__do_global_dtors_aux_1 (void)
-{
- atexit (__do_global_dtors_aux);
-}
-CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_dtors_aux_1)
-#endif
-
-#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
-/* Stick a call to __register_frame_info into the .init section. For some
- reason calls with no arguments work more reliably in .init, so stick the
- call in another function. */
-
-static void __attribute__((used))
-frame_dummy (void)
-{
-#ifdef USE_EH_FRAME_REGISTRY
- static struct object object;
-#ifdef CRT_GET_RFIB_DATA
- void *tbase, *dbase;
- tbase = 0;
- CRT_GET_RFIB_DATA (dbase);
- if (__register_frame_info_bases)
- __register_frame_info_bases (__EH_FRAME_BEGIN__, &object, tbase, dbase);
-#else
- if (__register_frame_info)
- __register_frame_info (__EH_FRAME_BEGIN__, &object);
-#endif /* CRT_GET_RFIB_DATA */
-#endif /* USE_EH_FRAME_REGISTRY */
-#ifdef JCR_SECTION_NAME
- if (__JCR_LIST__[0])
- {
- void (*register_classes) (void *) = _Jv_RegisterClasses;
- __asm ("" : "+r" (register_classes));
- if (register_classes)
- register_classes (__JCR_LIST__);
- }
-#endif /* JCR_SECTION_NAME */
-}
-
-#ifdef INIT_SECTION_ASM_OP
-CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, frame_dummy)
-#else /* defined(INIT_SECTION_ASM_OP) */
-static func_ptr __frame_dummy_init_array_entry[]
- __attribute__ ((__used__, section(".init_array")))
- = { frame_dummy };
-#endif /* !defined(INIT_SECTION_ASM_OP) */
-#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
-
-#else /* OBJECT_FORMAT_ELF */
-
-/* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
- and once in crtend.o). It must be declared static to avoid a link
- error. Here, we define __do_global_ctors as an externally callable
- function. It is externally callable so that __main can invoke it when
- INVOKE__main is defined. This has the additional effect of forcing cc1
- to switch to the .text section. */
-
-static void __do_global_ctors_aux (void);
-void
-__do_global_ctors (void)
-{
-#ifdef INVOKE__main
- /* If __main won't actually call __do_global_ctors then it doesn't matter
- what's inside the function. The inside of __do_global_ctors_aux is
- called automatically in that case. And the Alliant fx2800 linker
- crashes on this reference. So prevent the crash. */
- __do_global_ctors_aux ();
-#endif
-}
-
-asm (INIT_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
-
-/* A routine to invoke all of the global constructors upon entry to the
- program. We put this into the .init section (for systems that have
- such a thing) so that we can properly perform the construction of
- file-scope static-storage C++ objects within shared libraries. */
-
-static void __attribute__((used))
-__do_global_ctors_aux (void) /* prologue goes in .init section */
-{
- FORCE_CODE_SECTION_ALIGN /* explicit align before switch to .text */
- asm (TEXT_SECTION_ASM_OP); /* don't put epilogue and body in .init */
- DO_GLOBAL_CTORS_BODY;
- atexit (__do_global_dtors);
-}
-
-#endif /* OBJECT_FORMAT_ELF */
-
-#elif defined(HAS_INIT_SECTION) /* ! INIT_SECTION_ASM_OP */
-
-extern void __do_global_dtors (void);
-
-/* This case is used by the Irix 6 port, which supports named sections but
- not an SVR4-style .fini section. __do_global_dtors can be non-static
- in this case because we protect it with -hidden_symbol. */
-
-void
-__do_global_dtors (void)
-{
- func_ptr *p, f;
- for (p = __DTOR_LIST__ + 1; (f = *p); p++)
- f ();
-
-#ifdef USE_EH_FRAME_REGISTRY
- if (__deregister_frame_info)
- __deregister_frame_info (__EH_FRAME_BEGIN__);
-#endif
-}
-
-#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
-/* A helper function for __do_global_ctors, which is in crtend.o. Here
- in crtbegin.o, we can reference a couple of symbols not visible there.
- Plus, since we're before libgcc.a, we have no problems referencing
- functions from there. */
-void
-__do_global_ctors_1(void)
-{
-#ifdef USE_EH_FRAME_REGISTRY
- static struct object object;
- if (__register_frame_info)
- __register_frame_info (__EH_FRAME_BEGIN__, &object);
-#endif
-#ifdef JCR_SECTION_NAME
- if (__JCR_LIST__[0])
- {
- void (*register_classes) (void *) = _Jv_RegisterClasses;
- __asm ("" : "+r" (register_classes));
- if (register_classes)
- register_classes (__JCR_LIST__);
- }
-#endif
-}
-#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
-
-#else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */
-#error "What are you doing with crtstuff.c, then?"
-#endif
-
-#elif defined(CRT_END) /* ! CRT_BEGIN */
-
-/* No need for .ctors/.dtors section if linker can place them in
- .init_array/.fini_array section. */
-#ifndef USE_INITFINI_ARRAY
-/* Put a word containing zero at the end of each of our two lists of function
- addresses. Note that the words defined here go into the .ctors and .dtors
- sections of the crtend.o file, and since that file is always linked in
- last, these words naturally end up at the very ends of the two lists
- contained in these two sections. */
-
-#ifdef CTOR_LIST_END
-CTOR_LIST_END;
-#elif defined(CTORS_SECTION_ASM_OP)
-/* Hack: force cc1 to switch to .data section early, so that assembling
- __CTOR_LIST__ does not undo our behind-the-back change to .ctors. */
-static func_ptr force_to_data[1] __attribute__ ((__used__)) = { };
-asm (CTORS_SECTION_ASM_OP);
-STATIC func_ptr __CTOR_END__[1]
- __attribute__((aligned(sizeof(func_ptr))))
- = { (func_ptr) 0 };
-#else
-STATIC func_ptr __CTOR_END__[1]
- __attribute__((section(".ctors"), aligned(sizeof(func_ptr))))
- = { (func_ptr) 0 };
-#endif
-
-#ifdef DTOR_LIST_END
-DTOR_LIST_END;
-#elif defined(HIDDEN_DTOR_LIST_END)
-#ifdef DTORS_SECTION_ASM_OP
-asm (DTORS_SECTION_ASM_OP);
-#endif
-func_ptr __DTOR_END__[1]
- __attribute__ ((used,
-#ifndef DTORS_SECTION_ASM_OP
- section(".dtors"),
-#endif
- aligned(sizeof(func_ptr)), visibility ("hidden")))
- = { (func_ptr) 0 };
-#elif defined(DTORS_SECTION_ASM_OP)
-asm (DTORS_SECTION_ASM_OP);
-STATIC func_ptr __DTOR_END__[1]
- __attribute__ ((used, aligned(sizeof(func_ptr))))
- = { (func_ptr) 0 };
-#else
-STATIC func_ptr __DTOR_END__[1]
- __attribute__((used, section(".dtors"), aligned(sizeof(func_ptr))))
- = { (func_ptr) 0 };
-#endif
-#endif /* USE_INITFINI_ARRAY */
-
-#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. */
-# if __INT_MAX__ == 2147483647
-typedef int int32;
-# elif __LONG_MAX__ == 2147483647
-typedef long int32;
-# elif __SHRT_MAX__ == 2147483647
-typedef short int32;
-# else
-# error "Missing a 4 byte integer"
-# endif
-STATIC EH_FRAME_SECTION_CONST int32 __FRAME_END__[]
- __attribute__ ((used, section(EH_FRAME_SECTION_NAME),
- aligned(sizeof(int32))))
- = { 0 };
-#endif /* EH_FRAME_SECTION_NAME */
-
-#ifdef JCR_SECTION_NAME
-/* Null terminate the .jcr section array. */
-STATIC void *__JCR_END__[1]
- __attribute__ ((used, section(JCR_SECTION_NAME),
- aligned(sizeof(void *))))
- = { 0 };
-#endif /* JCR_SECTION_NAME */
-
-#ifdef INIT_ARRAY_SECTION_ASM_OP
-
-/* If we are using .init_array, there is nothing to do. */
-
-#elif defined(INIT_SECTION_ASM_OP)
-
-#ifdef OBJECT_FORMAT_ELF
-static void __attribute__((used))
-__do_global_ctors_aux (void)
-{
- func_ptr *p;
- for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
- (*p) ();
-}
-
-/* Stick a call to __do_global_ctors_aux into the .init section. */
-CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_ctors_aux)
-#else /* OBJECT_FORMAT_ELF */
-
-/* Stick the real initialization code, followed by a normal sort of
- function epilogue at the very end of the .init section for this
- entire root executable file or for this entire shared library file.
-
- Note that we use some tricks here to get *just* the body and just
- a function epilogue (but no function prologue) into the .init
- section of the crtend.o file. Specifically, we switch to the .text
- section, start to define a function, and then we switch to the .init
- section just before the body code.
-
- Earlier on, we put the corresponding function prologue into the .init
- section of the crtbegin.o file (which will be linked in first).
-
- Note that we want to invoke all constructors for C++ file-scope static-
- storage objects AFTER any other possible initialization actions which
- may be performed by the code in the .init section contributions made by
- other libraries, etc. That's because those other initializations may
- include setup operations for very primitive things (e.g. initializing
- the state of the floating-point coprocessor, etc.) which should be done
- before we start to execute any of the user's code. */
-
-static void
-__do_global_ctors_aux (void) /* prologue goes in .text section */
-{
- asm (INIT_SECTION_ASM_OP);
- DO_GLOBAL_CTORS_BODY;
- atexit (__do_global_dtors);
-} /* epilogue and body go in .init section */
-
-FORCE_CODE_SECTION_ALIGN
-asm (TEXT_SECTION_ASM_OP);
-
-#endif /* OBJECT_FORMAT_ELF */
-
-#elif defined(HAS_INIT_SECTION) /* ! INIT_SECTION_ASM_OP */
-
-extern void __do_global_ctors (void);
-
-/* This case is used by the Irix 6 port, which supports named sections but
- not an SVR4-style .init section. __do_global_ctors can be non-static
- in this case because we protect it with -hidden_symbol. */
-void
-__do_global_ctors (void)
-{
- func_ptr *p;
-#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
- __do_global_ctors_1();
-#endif
- for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
- (*p) ();
-}
-
-#else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */
-#error "What are you doing with crtstuff.c, then?"
-#endif
-
-#else /* ! CRT_BEGIN && ! CRT_END */
-#error "One of CRT_BEGIN or CRT_END must be defined."
-#endif
diff --git a/gcc/cselib.c b/gcc/cselib.c
index b96c0cd07ab..ef397db8d1c 100644
--- a/gcc/cselib.c
+++ b/gcc/cselib.c
@@ -185,7 +185,7 @@ static cselib_val dummy_val;
that is constant through the whole function and should never be
eliminated. */
static cselib_val *cfa_base_preserved_val;
-static unsigned int cfa_base_preserved_regno;
+static unsigned int cfa_base_preserved_regno = INVALID_REGNUM;
/* Used to list all values that contain memory reference.
May or may not contain the useless values - the list is compacted
@@ -1451,7 +1451,7 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd,
if (GET_MODE (l->elt->val_rtx) == GET_MODE (orig))
{
rtx result;
- int regno = REGNO (orig);
+ unsigned regno = REGNO (orig);
/* The only thing that we are not willing to do (this
is requirement of dse and if others potential uses
@@ -1471,7 +1471,8 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd,
make the frame assumptions. */
if (regno == STACK_POINTER_REGNUM
|| regno == FRAME_POINTER_REGNUM
- || regno == HARD_FRAME_POINTER_REGNUM)
+ || regno == HARD_FRAME_POINTER_REGNUM
+ || regno == cfa_base_preserved_regno)
return orig;
bitmap_set_bit (evd->regs_active, regno);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index d297cdda0ca..a8c0e669352 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -255,9 +255,9 @@ diagnostic_action_after_output (diagnostic_context *context,
}
void
-diagnostic_report_current_module (diagnostic_context *context)
+diagnostic_report_current_module (diagnostic_context *context, location_t where)
{
- const struct line_map *map;
+ const struct line_map *map = NULL;
if (pp_needs_newline (context->printer))
{
@@ -265,10 +265,13 @@ diagnostic_report_current_module (diagnostic_context *context)
pp_needs_newline (context->printer) = false;
}
- if (input_location <= BUILTINS_LOCATION)
+ if (where <= BUILTINS_LOCATION)
return;
- map = linemap_lookup (line_table, input_location);
+ linemap_resolve_location (line_table, where,
+ LRK_MACRO_DEFINITION_LOCATION,
+ &map);
+
if (map && diagnostic_last_module_changed (context, map))
{
diagnostic_set_last_module (context, map);
@@ -278,18 +281,18 @@ diagnostic_report_current_module (diagnostic_context *context)
if (context->show_column)
pp_verbatim (context->printer,
"In file included from %s:%d:%d",
- map->to_file,
+ LINEMAP_FILE (map),
LAST_SOURCE_LINE (map), LAST_SOURCE_COLUMN (map));
else
pp_verbatim (context->printer,
"In file included from %s:%d",
- map->to_file, LAST_SOURCE_LINE (map));
+ LINEMAP_FILE (map), LAST_SOURCE_LINE (map));
while (! MAIN_FILE_P (map))
{
map = INCLUDED_FROM (line_table, map);
pp_verbatim (context->printer,
",\n from %s:%d",
- map->to_file, LAST_SOURCE_LINE (map));
+ LINEMAP_FILE (map), LAST_SOURCE_LINE (map));
}
pp_verbatim (context->printer, ":");
pp_newline (context->printer);
@@ -301,7 +304,7 @@ void
default_diagnostic_starter (diagnostic_context *context,
diagnostic_info *diagnostic)
{
- diagnostic_report_current_module (context);
+ diagnostic_report_current_module (context, diagnostic->location);
pp_set_prefix (context->printer, diagnostic_build_prefix (context,
diagnostic));
}
@@ -459,7 +462,10 @@ diagnostic_report_diagnostic (diagnostic_context *context,
/* FIXME: Stupid search. Optimize later. */
for (i = context->n_classification_history - 1; i >= 0; i --)
{
- if (context->classification_history[i].location <= location)
+ if (linemap_location_before_p
+ (line_table,
+ context->classification_history[i].location,
+ location))
{
if (context->classification_history[i].kind == (int) DK_POP)
{
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 80743549a35..4b1265b7886 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -253,7 +253,7 @@ extern diagnostic_context *global_dc;
/* Diagnostic related functions. */
extern void diagnostic_initialize (diagnostic_context *, int);
extern void diagnostic_finish (diagnostic_context *);
-extern void diagnostic_report_current_module (diagnostic_context *);
+extern void diagnostic_report_current_module (diagnostic_context *, location_t);
/* Force diagnostics controlled by OPTIDX to be kind KIND. */
extern diagnostic_t diagnostic_classify_diagnostic (diagnostic_context *,
diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
index 5212478389d..6c70a0a9cd0 100644
--- a/gcc/doc/cppopts.texi
+++ b/gcc/doc/cppopts.texi
@@ -583,6 +583,37 @@ correct column numbers in warnings or errors, even if tabs appear on the
line. If the value is less than 1 or greater than 100, the option is
ignored. The default is 8.
+@item -fdebug-cpp
+@opindex fdebug-cpp
+This option is only useful for debugging GCC. When used with
+@option{-E}, dumps debugging information about location maps. Every
+token in the output is preceded by the dump of the map its location
+belongs to. The dump of the map holding the location of a token would
+be:
+@smallexample
+@{@samp{P}:@file{/file/path};@samp{F}:@file{/includer/path};@samp{L}:@var{line_num};@samp{C}:@var{col_num};@samp{S}:@var{system_header_p};@samp{M}:@var{map_address};@samp{E}:@var{macro_expansion_p},@samp{loc}:@var{location}@}
+@end smallexample
+
+When used without @option{-E}, this option has no effect.
+
+@item -ftrack-macro-expansion@r{[}=@var{level}@r{]}
+@opindex ftrack-macro-expansion
+Track locations of tokens across macro expansions. This allows the
+compiler to emit diagnostic about the current macro expansion stack
+when a compilation error occurs in a macro expansion. Using this
+option makes the preprocessor and the compiler consume more
+memory. The @var{level} parameter can be used to choose the level of
+precision of token location tracking thus decreasing the memory
+consumption if necessary. Value @samp{0} of @var{level} de-activates
+this option just as if no @option{-ftrack-macro-expansion} was present
+on the command line. Value @samp{1} tracks tokens locations in a
+degraded mode for the sake of minimal memory overhead. In this mode
+all tokens resulting from the expansion of an argument of a
+function-like macro have the same location. Value @samp{2} tracks
+tokens locations completely. This value is the most memory hungry.
+When this option is given no argument, the default parameter value is
+@samp{2}.
+
@item -fexec-charset=@var{charset}
@opindex fexec-charset
@cindex character set, execution
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index fa8d8e95489..3df5b04795f 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3029,6 +3029,33 @@ compiled with more aggressive optimization options that produce faster
and larger code, while other functions can be called with less
aggressive options.
+@item OS_main/OS_task
+@cindex @code{OS_main} AVR function attribute
+@cindex @code{OS_task} AVR function attribute
+On AVR, functions with the @code{OS_main} or @code{OS_task} attribute
+do not save/restore any call-saved register in their prologue/epilogue.
+
+The @code{OS_main} attribute can be used when there @emph{is
+guarantee} that interrupts are disabled at the time when the function
+is entered. This will save resources when the stack pointer has to be
+changed to set up a frame for local variables.
+
+The @code{OS_task} attribute can be used when there is @emph{no
+guarantee} that interrupts are disabled at that time when the function
+is entered like for, e@.g@. task functions in a multi-threading operating
+system. In that case, changing the stack pointer register will be
+guarded by save/clear/restore of the global interrupt enable flag.
+
+The differences to the @code{naked} function attrubute are:
+@itemize @bullet
+@item @code{naked} functions do not have a return instruction whereas
+@code{OS_main} and @code{OS_task} functions will have a @code{RET} or
+@code{RETI} return instruction.
+@item @code{naked} functions do not set up a frame for local variables
+or a frame pointer whereas @code{OS_main} and @code{OS_task} do this
+as needed.
+@end itemize
+
@item pcs
@cindex @code{pcs} function attribute
@@ -4525,6 +4552,19 @@ The @code{dllexport} attribute is described in @ref{Function Attributes}.
@end table
+@subsection AVR Variable Attributes
+
+@table @code
+@item progmem
+@cindex @code{progmem} AVR variable attribute
+The @code{progmem} attribute is used on the AVR to place data in the program
+memory address space (flash). This is accomplished by putting
+respective variables into a section whose name starts with @code{.progmem}.
+
+AVR is a Harvard architecture processor and data and reas only data
+normally resides in the data memory address space (RAM).
+@end table
+
@subsection Blackfin Variable Attributes
Three attributes are currently defined for the Blackfin.
@@ -4794,16 +4834,6 @@ placed in either the @code{.bss_below100} section or the
@end table
-@subsection AVR Variable Attributes
-
-@table @code
-@item progmem
-@cindex @code{progmem} variable attribute
-The @code{progmem} attribute is used on the AVR to place data in the Program
-Memory address space. The AVR is a Harvard Architecture processor and data
-normally resides in the Data Memory address space.
-@end table
-
@node Type Attributes
@section Specifying Attributes of Types
@cindex attribute of types
diff --git a/gcc/doc/fragments.texi b/gcc/doc/fragments.texi
index 28edae98e67..31674f9a5d0 100644
--- a/gcc/doc/fragments.texi
+++ b/gcc/doc/fragments.texi
@@ -1,5 +1,6 @@
@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-@c 1999, 2000, 2001, 2003, 2004, 2005, 2008 Free Software Foundation, Inc.
+@c 1999, 2000, 2001, 2003, 2004, 2005, 2008, 2011
+@c Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -128,12 +129,6 @@ compiler. In that case, set @code{MULTILIB_EXTRA_OPTS} to be the list
of options to be used for all builds. If you set this, you should
probably set @code{CRTSTUFF_T_CFLAGS} to a dash followed by it.
-@findex NATIVE_SYSTEM_HEADER_DIR
-@item NATIVE_SYSTEM_HEADER_DIR
-If the default location for system headers is not @file{/usr/include},
-you must set this to the directory containing the headers. This value
-should match the value of the @code{SYSTEM_INCLUDE_DIR} macro.
-
@findex SPECS
@item SPECS
Unfortunately, setting @code{MULTILIB_EXTRA_OPTS} is not enough, since
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 83a7361386f..730f82baff8 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -903,6 +903,14 @@ ideas of what it is for. People use it as if it specified where to
install part of GCC@. Perhaps they make this assumption because
installing GCC creates the directory.
+@item --with-native-system-header-dir=@var{dirname}
+Specifies that @var{dirname} is the directory that contains native system
+header files, rather than @file{/usr/include}. This option is most useful
+if you are creating a compiler that should be isolated from the system
+as much as possible. It is most commonly used with the
+@option{--with-sysroot} option and will cause GCC to search
+@var{dirname} inside the system root specified by that option.
+
@item --enable-shared[=@var{package}[,@dots{}]]
Build shared versions of libraries, if shared libraries are supported on
the target platform. Unlike GCC 2.95.x and earlier, shared libraries
@@ -1736,6 +1744,10 @@ target libraries (which runs on the build system) and the compiler newly
installed with @code{make install}; it does not affect the compiler which is
used to build GCC itself.
+If you specify the @option{--with-native-system-header-dir=@var{dirname}}
+option then the compiler will search that directory within @var{dirname} for
+native system headers rather than the default @file{/usr/include}.
+
@item --with-build-sysroot
@itemx --with-build-sysroot=@var{dir}
Tells GCC to consider @var{dir} as the system root (see
@@ -1750,6 +1762,10 @@ This option affects the system root for the compiler used to build
target libraries (which runs on the build system); it does not affect
the compiler which is used to build GCC itself.
+If you specify the @option{--with-native-system-header-dir=@var{dirname}}
+option then the compiler will search that directory within @var{dirname} for
+native system headers rather than the default @file{/usr/include}.
+
@item --with-headers
@itemx --with-headers=@var{dir}
Deprecated in favor of @option{--with-sysroot}.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0d9b0614fa9..77039c0a6e3 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -235,7 +235,7 @@ Objective-C and Objective-C++ Dialects}.
-pedantic-errors @gol
-w -Wextra -Wall -Waddress -Waggregate-return -Warray-bounds @gol
-Wno-attributes -Wno-builtin-macro-redefined @gol
--Wc++-compat -Wc++0x-compat -Wcast-align -Wcast-qual @gol
+-Wc++-compat -Wc++11-compat -Wcast-align -Wcast-qual @gol
-Wchar-subscripts -Wclobbered -Wcomment @gol
-Wconversion -Wcoverage-mismatch -Wno-cpp -Wno-deprecated @gol
-Wno-deprecated-declarations -Wdisabled-optimization @gol
@@ -429,9 +429,9 @@ Objective-C and Objective-C++ Dialects}.
-iwithprefixbefore @var{dir} -isystem @var{dir} @gol
-imultilib @var{dir} -isysroot @var{dir} @gol
-M -MM -MF -MG -MP -MQ -MT -nostdinc @gol
--P -fworking-directory -remap @gol
--trigraphs -undef -U@var{macro} -Wp,@var{option} @gol
--Xpreprocessor @var{option}}
+-P -fdebug-cpp -ftrack-macro-expansion -fworking-directory @gol
+-remap -trigraphs -undef -U@var{macro} @gol
+-Wp,@var{option} -Xpreprocessor @var{option}}
@item Assembler Option
@xref{Assembler Options,,Passing Options to the Assembler}.
@@ -487,7 +487,7 @@ Objective-C and Objective-C++ Dialects}.
@emph{AVR Options}
@gccoptlist{-mmcu=@var{mcu} -mno-interrupts @gol
--mcall-prologues -mtiny-stack -mint8}
+-mcall-prologues -mtiny-stack -mint8 -mstrict-X}
@emph{Blackfin Options}
@gccoptlist{-mcpu=@var{cpu}@r{[}-@var{sirevision}@r{]} @gol
@@ -885,7 +885,8 @@ See RS/6000 and PowerPC Options.
-munaligned-doubles -mno-unaligned-doubles @gol
-mv8plus -mno-v8plus -mvis -mno-vis @gol
-mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol
--mfmaf -mno-fmaf -mpopc -mno-popc}
+-mfmaf -mno-fmaf -mpopc -mno-popc @gol
+-mfix-at697f}
@emph{SPU Options}
@gccoptlist{-mwarn-reloc -merror-reloc @gol
@@ -1573,16 +1574,13 @@ C++ code.
GNU dialect of @option{-std=c++98}. This is the default for
C++ code.
-@item c++0x
-The working draft of the upcoming ISO C++0x standard. This option
-enables experimental features that are likely to be included in
-C++0x. The working draft is constantly changing, and any feature that is
-enabled by this flag may be removed from future versions of GCC if it is
-not part of the C++0x standard.
+@item c++11
+The 2011 ISO C++ standard plus amendments. Support for C++11 is still
+experimental, and may change in incompatible ways in future releases.
-@item gnu++0x
-GNU dialect of @option{-std=c++0x}. This option enables
-experimental features that may be removed in future versions of GCC.
+@item gnu++11
+GNU dialect of @option{-std=c++11}. Support for C++11 is still
+experimental, and may change in incompatible ways in future releases.
@end table
@item -fgnu89-inline
@@ -1869,7 +1867,7 @@ Version 5 corrects the mangling of attribute const/volatile on
function pointer types, decltype of a plain decl, and use of a
function parameter in the declaration of another parameter.
-Version 6 corrects the promotion behavior of C++0x scoped enums.
+Version 6 corrects the promotion behavior of C++11 scoped enums.
See also @option{-Wabi}.
@@ -1904,14 +1902,14 @@ been added for putting variables into BSS without making them common.
@item -fconstexpr-depth=@var{n}
@opindex fconstexpr-depth
-Set the maximum nested evaluation depth for C++0x constexpr functions
+Set the maximum nested evaluation depth for C++11 constexpr functions
to @var{n}. A limit is needed to detect endless recursion during
constant expression evaluation. The minimum specified by the standard
is 512.
-@item -fno-deduce-init-list
-@opindex fno-deduce-init-list
-Disable deduction of a template type parameter as
+@item -fdeduce-init-list
+@opindex fdeduce-init-list
+Enable deduction of a template type parameter as
std::initializer_list from a brace-enclosed initializer list, i.e.
@smallexample
@@ -1926,9 +1924,10 @@ void f()
@}
@end smallexample
-This option is present because this deduction is an extension to the
-current specification in the C++0x working draft, and there was
-some concern about potential overload resolution problems.
+This deduction was implemented as a possible extension to the
+originally proposed semantics for the C++11 standard, but was not part
+of the final standard, so it is disabled by default. This option is
+deprecated, and may be removed in a future version of G++.
@item -ffriend-injection
@opindex ffriend-injection
@@ -2092,7 +2091,7 @@ Set the maximum instantiation depth for template classes to @var{n}.
A limit on the template instantiation depth is needed to detect
endless recursions during template class instantiation. ANSI/ISO C++
conforming programs must not rely on a maximum depth greater than 17
-(changed to 1024 in C++0x). The default value is 900, as the compiler
+(changed to 1024 in C++11). The default value is 900, as the compiler
can run out of stack space before hitting 1024 in some situations.
@item -fno-threadsafe-statics
@@ -2119,7 +2118,7 @@ if the runtime routine is not available.
@item -fvisibility-inlines-hidden
@opindex fvisibility-inlines-hidden
This switch declares that the user does not attempt to compare
-pointers to inline methods where the addresses of the two functions
+pointers to inline functions or methods where the addresses of the two functions
were taken in different shared objects.
The effect of this is that GCC may, effectively, mark inline methods with
@@ -2367,14 +2366,14 @@ by @option{-Wall}.
@item -Wno-narrowing @r{(C++ and Objective-C++ only)}
@opindex Wnarrowing
@opindex Wno-narrowing
-With -std=c++0x, suppress the diagnostic required by the standard for
+With -std=c++11, suppress the diagnostic required by the standard for
narrowing conversions within @samp{@{ @}}, e.g.
@smallexample
int i = @{ 2.2 @}; // error: narrowing from double to int
@end smallexample
-This flag can be useful for compiling valid C++98 code in C++0x mode.
+This flag can be useful for compiling valid C++98 code in C++11 mode.
@item -Wnoexcept @r{(C++ and Objective-C++ only)}
@opindex Wnoexcept
@@ -2992,7 +2991,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}.
@gccoptlist{-Waddress @gol
-Warray-bounds @r{(only with} @option{-O2}@r{)} @gol
--Wc++0x-compat @gol
+-Wc++11-compat @gol
-Wchar-subscripts @gol
-Wenum-compare @r{(in C/Objc; this is on by default in C++)} @gol
-Wimplicit-int @r{(C and Objective-C only)} @gol
@@ -3189,7 +3188,7 @@ 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 @r{(C and Objective-C only)}
+@item -Wno-format-zero-length
@opindex Wno-format-zero-length
@opindex Wformat-zero-length
If @option{-Wformat} is specified, do not warn about zero-length formats.
@@ -3222,7 +3221,7 @@ Enable @option{-Wformat} plus format checks not included in
@option{-Wformat}. Currently equivalent to @samp{-Wformat
-Wformat-nonliteral -Wformat-security -Wformat-y2k}.
-@item -Wnonnull @r{(C and Objective-C only)}
+@item -Wnonnull
@opindex Wnonnull
@opindex Wno-nonnull
Warn about passing a null pointer for arguments marked as
@@ -4001,19 +4000,19 @@ The message is in keeping with the output of @option{-fstack-usage}.
If the stack usage is fully static but exceeds the specified amount, it's:
@smallexample
-  warning: stack usage is 1120 bytes
+ warning: stack usage is 1120 bytes
@end smallexample
@item
If the stack usage is (partly) dynamic but bounded, it's:
@smallexample
-  warning: stack usage might be 1648 bytes
+ warning: stack usage might be 1648 bytes
@end smallexample
@item
If the stack usage is (partly) dynamic and not bounded, it's:
@smallexample
-  warning: stack usage might be unbounded
+ warning: stack usage might be unbounded
@end smallexample
@end itemize
@@ -4062,10 +4061,10 @@ Warn about ISO C constructs that are outside of the common subset of
ISO C and ISO C++, e.g.@: request for implicit conversion from
@code{void *} to a pointer to non-@code{void} type.
-@item -Wc++0x-compat @r{(C++ and Objective-C++ only)}
+@item -Wc++11-compat @r{(C++ and Objective-C++ only)}
Warn about C++ constructs whose meaning differs between ISO C++ 1998 and
-ISO C++ 200x, e.g., identifiers in ISO C++ 1998 that will become keywords
-in ISO C++ 200x. This warning is enabled by @option{-Wall}.
+ISO C++ 2011, e.g., identifiers in ISO C++ 1998 that will become keywords
+in ISO C++ 2011. This warning is enabled by @option{-Wall}.
@item -Wcast-qual
@opindex Wcast-qual
@@ -4143,6 +4142,12 @@ unsigned integers are disabled by default in C++ unless
Do not warn for conversions between @code{NULL} and non-pointer
types. @option{-Wconversion-null} is enabled by default.
+@item -Wzero-as-null-pointer-constant @r{(C++ and Objective-C++ only)}
+@opindex Wzero-as-null-pointer-constant
+@opindex Wno-zero-as-null-pointer-constant
+Warn when a literal '0' is used as null pointer constant. This can
+be useful to facilitate the conversion to @code{nullptr} in C++11.
+
@item -Wempty-body
@opindex Wempty-body
@opindex Wno-empty-body
@@ -9080,8 +9085,7 @@ compile time for more complete debug information. If this is set too
low, value expressions that are available and could be represented in
debug information may end up not being used; setting this higher may
enable the compiler to find more complex debug expressions, but compile
-time may grow exponentially, and even then, it may fail to find more
-usable expressions. The default is 10.
+time and memory use may grow. The default is 12.
@item min-nondebug-insn-uid
Use uids starting at this parameter for nondebug insns. The range below
@@ -9133,6 +9137,13 @@ partitions.
The maximum number of namespaces to consult for suggestions when C++
name lookup fails for an identifier. The default is 1000.
+@item sink-frequency-threshold
+The maximum relative execution frequency (in percents) of the target block
+relative to a statement's original block to allow statement sinking of a
+statement. Larger numbers result in more aggressive statement sinking.
+The default value is 75. A small positive adjustment is applied for
+statements with memory operands as those are even more profitable so sink.
+
@item max-stores-to-sink
The maximum number of conditional stores paires that can be sunk. Set to 0
if either vectorization (@option{-ftree-vectorize}) or if-conversion
@@ -10411,10 +10422,16 @@ assembly code. Permissible names are: @samp{arm2}, @samp{arm250},
@samp{fa526}, @samp{fa626},
@samp{fa606te}, @samp{fa626te}, @samp{fmp626}, @samp{fa726te}.
+
@option{-mcpu=generic-@var{arch}} is also permissible, and is
equivalent to @option{-march=@var{arch} -mtune=generic-@var{arch}}.
See @option{-mtune} for more information.
+@option{-mcpu=native} causes the compiler to auto-detect the CPU
+of the build computer. At present, this feature is only supported on
+Linux, and not all architectures are recognised. If the auto-detect is
+unsuccessful the option has no effect.
+
@item -mtune=@var{name}
@opindex mtune
This option is very similar to the @option{-mcpu=} option, except that
@@ -10433,6 +10450,11 @@ processors, balancing between optimizations that benefit some CPUs in the
range, and avoiding performance pitfalls of other CPUs. The effects of
this option may change in future GCC versions as CPU models come and go.
+@option{-mtune=native} causes the compiler to auto-detect the CPU
+of the build computer. At present, this feature is only supported on
+Linux, and not all architectures are recognised. If the auto-detect is
+unsuccessful the option has no effect.
+
@item -march=@var{name}
@opindex march
This specifies the name of the target ARM architecture. GCC uses this
@@ -10446,6 +10468,11 @@ of the @option{-mcpu=} option. Permissible names are: @samp{armv2},
@samp{armv7}, @samp{armv7-a}, @samp{armv7-r}, @samp{armv7-m},
@samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}.
+@option{-march=native} causes the compiler to auto-detect the architecture
+of the build computer. At present, this feature is only supported on
+Linux, and not all architectures are recognised. If the auto-detect is
+unsuccessful the option has no effect.
+
@item -mfpu=@var{name}
@itemx -mfpe=@var{number}
@itemx -mfp=@var{number}
@@ -10703,8 +10730,136 @@ char will be 1 byte, an int will be 1 byte, a long will be 2 bytes
and long long will be 4 bytes. Please note that this option does not
comply to the C standards, but it will provide you with smaller code
size.
+
+@item -mstrict-X
+@opindex mstrict-X
+Use register @code{X} in a way proposed by the hardware. This means
+that @code{X} will only be used in indirect, post-increment or
+pre-decrement addressing.
+
+Without this option, the @code{X} register may be used in the same way
+as @code{Y} or @code{Z} which then is emulated by additional
+instructions.
+For example, loading a value with @code{X+const} addressing with a
+small @code{const <= 63} to a register @var{Rn} will be printed as
+@example
+adiw r26, const
+ld @var{Rn}, X
+sbiw r26, const
+@end example
@end table
+@subsubsection @code{EIND} and Devices with more than 128k Bytes of Flash
+
+Pointers in the implementation are 16 bits wide.
+The address of a function or label is represented as word address so
+that indirect jumps and calls can address any code address in the
+range of 64k words.
+
+In order to faciliate indirect jump on devices with more than 128k
+bytes of program memory space, there is a special function register called
+@code{EIND} that serves as most significant part of the target address
+when @code{EICALL} or @code{EIJMP} instructions are used.
+
+Indirect jumps and calls on these devices are handled as follows and
+are subject to some limitations:
+
+@itemize @bullet
+
+@item
+The compiler never sets @code{EIND}.
+
+@item
+The startup code from libgcc never sets @code{EIND}.
+Notice that startup code is a blend of code from libgcc and avr-libc.
+For the impact of avr-libc on @code{EIND}, see the
+@w{@uref{http://nongnu.org/avr-libc/user-manual,avr-libc user manual}}.
+
+@item
+The compiler uses @code{EIND} implicitely in @code{EICALL}/@code{EIJMP}
+instructions or might read @code{EIND} directly.
+
+@item
+The compiler assumes that @code{EIND} never changes during the startup
+code or run of the application. In particular, @code{EIND} is not
+saved/restored in function or interrupt service routine
+prologue/epilogue.
+
+@item
+It is legitimate for user-specific startup code to set up @code{EIND}
+early, for example by means of initialization code located in
+section @code{.init3}, and thus prior to general startup code that
+initializes RAM and calls constructors.
+
+@item
+For indirect calls to functions and computed goto, the linker will
+generate @emph{stubs}. Stubs are jump pads sometimes also called
+@emph{trampolines}. Thus, the indirect call/jump will jump to such a stub.
+The stub contains a direct jump to the desired address.
+
+@item
+Stubs will be generated automatically by the linker if
+the following two conditions are met:
+@itemize @minus
+
+@item The address of a label is taken by means of the @code{gs} modifier
+(short for @emph{generate stubs}) like so:
+@example
+LDI r24, lo8(gs(@var{func}))
+LDI r25, hi8(gs(@var{func}))
+@end example
+@item The final location of that label is in a code segment
+@emph{outside} the segment where the stubs are located.
+@end itemize
+
+@item
+The compiler will emit such @code{gs} modifiers for code labels in the
+following situations:
+@itemize @minus
+@item Taking address of a function or code label.
+@item Computed goto.
+@item If prologue-save function is used, see @option{-mcall-prologues}
+command line option.
+@item Switch/case dispatch tables. If you do not want such dispatch
+tables you can specify the @option{-fno-jump-tables} command line option.
+@item C and C++ constructors/destructors called during startup/shutdown.
+@item If the tools hit a @code{gs()} modifier explained above.
+@end itemize
+
+@item
+The default linker script is arranged for code with @code{EIND = 0}.
+If code is supposed to work for a setup with @code{EIND != 0}, a custom
+linker script has to be used in order to place the sections whose
+name start with @code{.trampolines} into the segment where @code{EIND}
+points to.
+
+@item
+Jumping to non-symbolic addresses like so is @emph{not} supported:
+
+@example
+int main (void)
+@{
+ /* Call function at word address 0x2 */
+ return ((int(*)(void)) 0x2)();
+@}
+@end example
+
+Instead, a stub has to be set up:
+
+@example
+int main (void)
+@{
+ extern int func_4 (void);
+
+ /* Call function at byte address 0x4 */
+ return func_4();
+@}
+@end example
+
+and the application be linked with @code{-Wl,--defsym,func_4=0x4}.
+Alternatively, @code{func_4} can be defined in the linker script.
+@end itemize
+
@node Blackfin Options
@subsection Blackfin Options
@cindex Blackfin Options
@@ -12904,7 +13059,12 @@ Note that while the throughput of the sequence is higher than the throughput
of the non-reciprocal instruction, the precision of the sequence can be
decreased by up to 2 ulp (i.e. the inverse of 1.0 equals 0.99999994).
-Note that GCC implements 1.0f/sqrtf(x) in terms of RSQRTSS (or RSQRTPS)
+Note that GCC implements @code{1.0f/sqrtf(@var{x})} in terms of RSQRTSS
+(or RSQRTPS) already with @option{-ffast-math} (or the above option
+combination), and doesn't need @option{-mrecip}.
+
+Also note that GCC emits the above sequence with additional Newton-Raphson step
+for vectorized single float division and vectorized @code{sqrtf(@var{x})}
already with @option{-ffast-math} (or the above option combination), and
doesn't need @option{-mrecip}.
@@ -17564,6 +17724,11 @@ With @option{-mfmaf}, GCC generates code that takes advantage of the UltraSPARC
Fused Multiply-Add Floating-point extensions. The default is @option{-mfmaf}
when targetting a cpu that supports such instructions, such as Niagara-3 and
later.
+
+@item -mfix-at697f
+@opindex mfix-at697f
+Enable the documented workaround for the single erratum of the Atmel AT697F
+processor (which corresponds to erratum #13 of the AT697E processor).
@end table
These @samp{-m} options are supported in addition to the above
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index fe27210d293..4a0bcfa1bf1 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -4041,6 +4041,12 @@ be computed modulo @math{2*@var{N}}. Note that if
@code{rtx_equal_p(operand1, operand2)}, this can be implemented
with just operand 1 and selector elements modulo @var{N}.
+In order to make things easy for a number of targets, if there is no
+@samp{vec_perm} pattern for mode @var{m}, but there is for mode @var{q}
+where @var{q} is a vector of @code{QImode} of the same width as @var{m},
+the middle-end will lower the mode @var{m} @code{VEC_PERM_EXPR} to
+mode @var{q}.
+
@cindex @code{vec_perm_const@var{m}} instruction pattern
@item @samp{vec_perm_const@var{m}}
Like @samp{vec_perm} except that the permutation is a compile-time
@@ -4266,6 +4272,17 @@ are vectors with N signed/unsigned elements of size S@. Multiply the high/low
elements of the two vectors, and put the N/2 products of size 2*S in the
output vector (operand 0).
+@cindex @code{vec_widen_ushiftl_hi_@var{m}} instruction pattern
+@cindex @code{vec_widen_ushiftl_lo_@var{m}} instruction pattern
+@cindex @code{vec_widen_sshiftl_hi_@var{m}} instruction pattern
+@cindex @code{vec_widen_sshiftl_lo_@var{m}} instruction pattern
+@item @samp{vec_widen_ushiftl_hi_@var{m}}, @samp{vec_widen_ushiftl_lo_@var{m}}
+@itemx @samp{vec_widen_sshiftl_hi_@var{m}}, @samp{vec_widen_sshiftl_lo_@var{m}}
+Signed/Unsigned widening shift left. The first input (operand 1) is a vector
+with N signed/unsigned elements of size S@. Operand 2 is a constant. Shift
+the high/low elements of operand 1, and put the N/2 results of size 2*S in the
+output vector (operand 0).
+
@cindex @code{mulhisi3} instruction pattern
@item @samp{mulhisi3}
Multiply operands 1 and 2, which have mode @code{HImode}, and store
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 90cef1c5f38..422f74c5874 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -470,33 +470,15 @@ initialize the necessary environment variables.
Define this macro as a C string constant if you wish to override the
standard choice of @file{/usr/local/include} as the default prefix to
try when searching for local header files. @code{LOCAL_INCLUDE_DIR}
-comes before @code{SYSTEM_INCLUDE_DIR} in the search order.
+comes before @code{NATIVE_SYSTEM_HEADER_DIR} (set in
+@file{config.gcc}, normally @file{/usr/include}) in the search order.
Cross compilers do not search either @file{/usr/local/include} or its
replacement.
@end defmac
-@defmac SYSTEM_INCLUDE_DIR
-Define this macro as a C string constant if you wish to specify a
-system-specific directory to search for header files before the standard
-directory. @code{SYSTEM_INCLUDE_DIR} comes before
-@code{STANDARD_INCLUDE_DIR} in the search order.
-
-Cross compilers do not use this macro and do not search the directory
-specified.
-@end defmac
-
-@defmac STANDARD_INCLUDE_DIR
-Define this macro as a C string constant if you wish to override the
-standard choice of @file{/usr/include} as the default prefix to
-try when searching for header files.
-
-Cross compilers ignore this macro and do not search either
-@file{/usr/include} or its replacement.
-@end defmac
-
-@defmac STANDARD_INCLUDE_COMPONENT
-The ``component'' corresponding to @code{STANDARD_INCLUDE_DIR}.
+@defmac NATIVE_SYSTEM_HEADER_COMPONENT
+The ``component'' corresponding to @code{NATIVE_SYSTEM_HEADER_DIR}.
See @code{INCLUDE_DEFAULTS}, below, for the description of components.
If you do not define this macro, no component is used.
@end defmac
@@ -505,8 +487,8 @@ If you do not define this macro, no component is used.
Define this macro if you wish to override the entire default search path
for include files. For a native compiler, the default search path
usually consists of @code{GCC_INCLUDE_DIR}, @code{LOCAL_INCLUDE_DIR},
-@code{SYSTEM_INCLUDE_DIR}, @code{GPLUSPLUS_INCLUDE_DIR}, and
-@code{STANDARD_INCLUDE_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
+@code{GPLUSPLUS_INCLUDE_DIR}, and
+@code{NATIVE_SYSTEM_HEADER_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
and @code{GCC_INCLUDE_DIR} are defined automatically by @file{Makefile},
and specify private search areas for GCC@. The directory
@code{GPLUSPLUS_INCLUDE_DIR} is used only for C++ programs.
@@ -5729,12 +5711,8 @@ misalignment value (@var{misalign}).
Return true if vector alignment is reachable (by peeling N iterations) for the given type.
@end deftypefn
-@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_VEC_PERM (tree @var{type}, tree *@var{mask_element_type})
-Target builtin that implements vector permute.
-@end deftypefn
-
-@deftypefn {Target Hook} bool TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK (tree @var{vec_type}, tree @var{mask})
-Return true if a vector created for @code{builtin_vec_perm} is valid.
+@deftypefn {Target Hook} bool TARGET_VECTORIZE_VEC_PERM_CONST_OK (enum @var{machine_mode}, const unsigned char *@var{sel})
+Return true if a vector created for @code{vec_perm_const} is valid.
@end deftypefn
@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_CONVERSION (unsigned @var{code}, tree @var{dest_type}, tree @var{src_type})
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 187122eea81..cede91edb52 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -468,33 +468,15 @@ initialize the necessary environment variables.
Define this macro as a C string constant if you wish to override the
standard choice of @file{/usr/local/include} as the default prefix to
try when searching for local header files. @code{LOCAL_INCLUDE_DIR}
-comes before @code{SYSTEM_INCLUDE_DIR} in the search order.
+comes before @code{NATIVE_SYSTEM_HEADER_DIR} (set in
+@file{config.gcc}, normally @file{/usr/include}) in the search order.
Cross compilers do not search either @file{/usr/local/include} or its
replacement.
@end defmac
-@defmac SYSTEM_INCLUDE_DIR
-Define this macro as a C string constant if you wish to specify a
-system-specific directory to search for header files before the standard
-directory. @code{SYSTEM_INCLUDE_DIR} comes before
-@code{STANDARD_INCLUDE_DIR} in the search order.
-
-Cross compilers do not use this macro and do not search the directory
-specified.
-@end defmac
-
-@defmac STANDARD_INCLUDE_DIR
-Define this macro as a C string constant if you wish to override the
-standard choice of @file{/usr/include} as the default prefix to
-try when searching for header files.
-
-Cross compilers ignore this macro and do not search either
-@file{/usr/include} or its replacement.
-@end defmac
-
-@defmac STANDARD_INCLUDE_COMPONENT
-The ``component'' corresponding to @code{STANDARD_INCLUDE_DIR}.
+@defmac NATIVE_SYSTEM_HEADER_COMPONENT
+The ``component'' corresponding to @code{NATIVE_SYSTEM_HEADER_DIR}.
See @code{INCLUDE_DEFAULTS}, below, for the description of components.
If you do not define this macro, no component is used.
@end defmac
@@ -503,8 +485,8 @@ If you do not define this macro, no component is used.
Define this macro if you wish to override the entire default search path
for include files. For a native compiler, the default search path
usually consists of @code{GCC_INCLUDE_DIR}, @code{LOCAL_INCLUDE_DIR},
-@code{SYSTEM_INCLUDE_DIR}, @code{GPLUSPLUS_INCLUDE_DIR}, and
-@code{STANDARD_INCLUDE_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
+@code{GPLUSPLUS_INCLUDE_DIR}, and
+@code{NATIVE_SYSTEM_HEADER_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
and @code{GCC_INCLUDE_DIR} are defined automatically by @file{Makefile},
and specify private search areas for GCC@. The directory
@code{GPLUSPLUS_INCLUDE_DIR} is used only for C++ programs.
@@ -5667,12 +5649,8 @@ misalignment value (@var{misalign}).
Return true if vector alignment is reachable (by peeling N iterations) for the given type.
@end deftypefn
-@hook TARGET_VECTORIZE_BUILTIN_VEC_PERM
-Target builtin that implements vector permute.
-@end deftypefn
-
-@hook TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK
-Return true if a vector created for @code{builtin_vec_perm} is valid.
+@hook TARGET_VECTORIZE_VEC_PERM_CONST_OK
+Return true if a vector created for @code{vec_perm_const} is valid.
@end deftypefn
@hook TARGET_VECTORIZE_BUILTIN_CONVERSION
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c11f666bfbf..e6f86a49854 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -98,6 +98,7 @@ along with GCC; see the file COPYING3. If not see
static void dwarf2out_source_line (unsigned int, const char *, int, bool);
static rtx last_var_location_insn;
+static rtx cached_next_real_insn;
#ifdef VMS_DEBUGGING_INFO
int vms_file_stats_name (const char *, long long *, long *, char *, int *);
@@ -1090,6 +1091,7 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
char label[MAX_ARTIFICIAL_LABEL_BYTES];
last_var_location_insn = NULL_RTX;
+ cached_next_real_insn = NULL_RTX;
if (dwarf2out_do_cfi_asm ())
fprintf (asm_out_file, "\t.cfi_endproc\n");
@@ -12502,7 +12504,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
legitimate to make the Dwarf info refer to the whole register which
contains the given subreg. */
if (REG_P (SUBREG_REG (rtl)) && subreg_lowpart_p (rtl))
- loc_result = loc_descriptor (SUBREG_REG (rtl), mode, initialized);
+ loc_result = loc_descriptor (SUBREG_REG (rtl),
+ GET_MODE (SUBREG_REG (rtl)), initialized);
else
goto do_default;
break;
@@ -15414,7 +15417,11 @@ add_gnat_descriptive_type_attribute (dw_die_ref die, tree type,
dtype_die = lookup_type_die (dtype);
if (!dtype_die)
{
+ /* The descriptive type indirectly references TYPE if this is also the
+ case for TYPE itself. Do not deal with the circularity here. */
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 1;
gen_type_die (dtype, context_die);
+ TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 0;
dtype_die = lookup_type_die (dtype);
gcc_assert (dtype_die);
}
@@ -20122,10 +20129,11 @@ dwarf2out_var_location (rtx loc_note)
{
char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
struct var_loc_node *newloc;
- rtx next_real;
+ rtx next_real, next_note;
static const char *last_label;
static const char *last_postcall_label;
static bool last_in_cold_section_p;
+ static rtx expected_next_loc_note;
tree decl;
bool var_loc_p;
@@ -20144,7 +20152,35 @@ dwarf2out_var_location (rtx loc_note)
if (var_loc_p && !DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
return;
- next_real = next_real_insn (loc_note);
+ /* Optimize processing a large consecutive sequence of location
+ notes so we don't spend too much time in next_real_insn. If the
+ next insn is another location note, remember the next_real_insn
+ calculation for next time. */
+ next_real = cached_next_real_insn;
+ if (next_real)
+ {
+ if (expected_next_loc_note != loc_note)
+ next_real = NULL_RTX;
+ }
+
+ next_note = NEXT_INSN (loc_note);
+ if (! next_note
+ || INSN_DELETED_P (next_note)
+ || GET_CODE (next_note) != NOTE
+ || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION
+ && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION))
+ next_note = NULL_RTX;
+
+ if (! next_real)
+ next_real = next_real_insn (loc_note);
+
+ if (next_note)
+ {
+ expected_next_loc_note = next_note;
+ cached_next_real_insn = next_real;
+ }
+ else
+ cached_next_real_insn = NULL_RTX;
/* If there are no instructions which would be affected by this note,
don't do anything. */
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index dae7669297a..c2bc56b9758 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1696,6 +1696,12 @@ set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
&& !TREE_THIS_VOLATILE (base))
MEM_READONLY_P (ref) = 1;
+ /* Mark static const strings readonly as well. */
+ if (base && TREE_CODE (base) == STRING_CST
+ && TREE_READONLY (base)
+ && TREE_STATIC (base))
+ MEM_READONLY_P (ref) = 1;
+
/* If this expression uses it's parent's alias set, mark it such
that we won't change it. */
if (component_uses_parent_alias_set (t))
@@ -3324,21 +3330,6 @@ next_label (rtx insn)
return insn;
}
-/* Return the last CODE_LABEL before the insn INSN, or 0 if there is none. */
-
-rtx
-prev_label (rtx insn)
-{
- while (insn)
- {
- insn = PREV_INSN (insn);
- if (insn == 0 || LABEL_P (insn))
- break;
- }
-
- return insn;
-}
-
/* Return the last label to mark the same position as LABEL. Return LABEL
itself if it is null or any return rtx. */
diff --git a/gcc/expr.c b/gcc/expr.c
index b020978f367..84cfe5c23ee 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4544,6 +4544,27 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart,
}
}
+/* Return the alignment of the object EXP, also considering its type
+ when we do not know of explicit misalignment.
+ ??? Note that, in the general case, the type of an expression is not kept
+ consistent with misalignment information by the front-end, for
+ example when taking the address of a member of a packed structure.
+ However, in most of the cases, expressions have the alignment of
+ their type, so we optimistically fall back to the alignment of the
+ type when we cannot compute a misalignment. */
+
+static unsigned int
+get_object_or_type_alignment (tree exp)
+{
+ unsigned HOST_WIDE_INT misalign;
+ unsigned int align = get_object_alignment_1 (exp, &misalign);
+ if (misalign != 0)
+ align = (misalign & -misalign);
+ else
+ align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), align);
+ return align;
+}
+
/* Expand an assignment that stores the value of FROM into TO. If NONTEMPORAL
is true, try generating a nontemporal store. */
@@ -4553,7 +4574,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
rtx to_rtx = 0;
rtx result;
enum machine_mode mode;
- int align;
+ unsigned int align;
enum insn_code icode;
/* Don't crash if the lhs of the assignment was erroneous. */
@@ -4571,8 +4592,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
if ((TREE_CODE (to) == MEM_REF
|| TREE_CODE (to) == TARGET_MEM_REF)
&& mode != BLKmode
- && ((align = MAX (TYPE_ALIGN (TREE_TYPE (to)), get_object_alignment (to)))
- < (signed) GET_MODE_ALIGNMENT (mode))
+ && ((align = get_object_or_type_alignment (to))
+ < GET_MODE_ALIGNMENT (mode))
&& ((icode = optab_handler (movmisalign_optab, mode))
!= CODE_FOR_nothing))
{
@@ -8646,27 +8667,9 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
case VEC_EXTRACT_EVEN_EXPR:
case VEC_EXTRACT_ODD_EXPR:
- {
- expand_operands (treeop0, treeop1,
- NULL_RTX, &op0, &op1, EXPAND_NORMAL);
- this_optab = optab_for_tree_code (code, type, optab_default);
- temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
- OPTAB_WIDEN);
- gcc_assert (temp);
- return temp;
- }
-
case VEC_INTERLEAVE_HIGH_EXPR:
case VEC_INTERLEAVE_LOW_EXPR:
- {
- expand_operands (treeop0, treeop1,
- NULL_RTX, &op0, &op1, EXPAND_NORMAL);
- this_optab = optab_for_tree_code (code, type, optab_default);
- temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
- OPTAB_WIDEN);
- gcc_assert (temp);
- return temp;
- }
+ goto binop;
case VEC_LSHIFT_EXPR:
case VEC_RSHIFT_EXPR:
@@ -8711,6 +8714,19 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
return target;
}
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ {
+ tree oprnd0 = treeop0;
+ tree oprnd1 = treeop1;
+
+ expand_operands (oprnd0, oprnd1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
+ target = expand_widen_pattern_expr (ops, op0, op1, NULL_RTX,
+ target, unsignedp);
+ gcc_assert (target);
+ return target;
+ }
+
case VEC_PACK_TRUNC_EXPR:
case VEC_PACK_SAT_EXPR:
case VEC_PACK_FIX_TRUNC_EXPR:
@@ -8718,9 +8734,11 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode,
goto binop;
case VEC_PERM_EXPR:
- target = expand_vec_perm_expr (type, treeop0, treeop1, treeop2, target);
- gcc_assert (target);
- return target;
+ expand_operands (treeop0, treeop1, target, &op0, &op1, EXPAND_NORMAL);
+ op2 = expand_normal (treeop2);
+ temp = expand_vec_perm (mode, op0, op1, op2, target);
+ gcc_assert (temp);
+ return temp;
case DOT_PROD_EXPR:
{
@@ -9241,7 +9259,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (exp));
struct mem_address addr;
enum insn_code icode;
- int align;
+ unsigned int align;
get_address_description (exp, &addr);
op0 = addr_for_mem_ref (&addr, as, true);
@@ -9249,9 +9267,9 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
temp = gen_rtx_MEM (mode, op0);
set_mem_attributes (temp, exp, 0);
set_mem_addr_space (temp, as);
- align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+ align = get_object_or_type_alignment (exp);
if (mode != BLKmode
- && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+ && align < GET_MODE_ALIGNMENT (mode)
/* If the target does not have special handling for unaligned
loads of mode then it can use regular moves for them. */
&& ((icode = optab_handler (movmisalign_optab, mode))
@@ -9278,7 +9296,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
tree base = TREE_OPERAND (exp, 0);
gimple def_stmt;
enum insn_code icode;
- int align;
+ unsigned align;
/* Handle expansion of non-aliased memory with non-BLKmode. That
might end up in a register. */
if (TREE_CODE (base) == ADDR_EXPR)
@@ -9329,7 +9347,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
gimple_assign_rhs1 (def_stmt), mask);
TREE_OPERAND (exp, 0) = base;
}
- align = MAX (TYPE_ALIGN (TREE_TYPE (exp)), get_object_alignment (exp));
+ align = get_object_or_type_alignment (exp);
op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM);
op0 = memory_address_addr_space (address_mode, op0, as);
if (!integer_zerop (TREE_OPERAND (exp, 1)))
@@ -9345,7 +9363,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
if (TREE_THIS_VOLATILE (exp))
MEM_VOLATILE_P (temp) = 1;
if (mode != BLKmode
- && (unsigned) align < GET_MODE_ALIGNMENT (mode)
+ && align < GET_MODE_ALIGNMENT (mode)
/* If the target does not have special handling for unaligned
loads of mode then it can use regular moves for them. */
&& ((icode = optab_handler (movmisalign_optab, mode))
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5b0fea7b1ba..e4c258903f7 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -112,13 +112,13 @@ static tree decode_field_reference (location_t, tree, HOST_WIDE_INT *,
static int all_ones_mask_p (const_tree, int);
static tree sign_bit_p (tree, const_tree);
static int simple_operand_p (const_tree);
+static bool simple_operand_p_2 (tree);
static tree range_binop (enum tree_code, tree, tree, int, tree, int);
static tree range_predecessor (tree);
static tree range_successor (tree);
static tree fold_range_test (location_t, enum tree_code, tree, tree, tree);
static tree fold_cond_expr_with_comparison (location_t, tree, tree, tree, tree);
static tree unextend (tree, int, int, tree);
-static tree fold_truthop (location_t, enum tree_code, tree, tree, tree);
static tree optimize_minmax_comparison (location_t, enum tree_code,
tree, tree, tree);
static tree extract_muldiv (tree, tree, enum tree_code, tree, bool *);
@@ -2100,15 +2100,14 @@ pedantic_non_lvalue_loc (location_t loc, tree x)
return protected_set_expr_location_unshare (x, loc);
}
-/* Given a tree comparison code, return the code that is the logical inverse
- of the given code. It is not safe to do this for floating-point
- comparisons, except for NE_EXPR and EQ_EXPR, so we receive a machine mode
- as well: if reversing the comparison is unsafe, return ERROR_MARK. */
+/* Given a tree comparison code, return the code that is the logical inverse.
+ It is generally not safe to do this for floating-point comparisons, except
+ for EQ_EXPR and NE_EXPR, so we return ERROR_MARK in this case. */
enum tree_code
invert_tree_comparison (enum tree_code code, bool honor_nans)
{
- if (honor_nans && flag_trapping_math)
+ if (honor_nans && flag_trapping_math && code != EQ_EXPR && code != NE_EXPR)
return ERROR_MARK;
switch (code)
@@ -3500,7 +3499,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
return lhs;
}
-/* Subroutine for fold_truthop: decode a field reference.
+/* Subroutine for fold_truth_andor_1: decode a field reference.
If EXP is a comparison reference, we return the innermost reference.
@@ -3668,7 +3667,7 @@ sign_bit_p (tree exp, const_tree val)
return NULL_TREE;
}
-/* Subroutine for fold_truthop: determine if an operand is simple enough
+/* Subroutine for fold_truth_andor_1: determine if an operand is simple enough
to be evaluated unconditionally. */
static int
@@ -3678,7 +3677,7 @@ simple_operand_p (const_tree exp)
STRIP_NOPS (exp);
return (CONSTANT_CLASS_P (exp)
- || TREE_CODE (exp) == SSA_NAME
+ || TREE_CODE (exp) == SSA_NAME
|| (DECL_P (exp)
&& ! TREE_ADDRESSABLE (exp)
&& ! TREE_THIS_VOLATILE (exp)
@@ -3692,6 +3691,36 @@ simple_operand_p (const_tree exp)
registers aren't expensive. */
&& (! TREE_STATIC (exp) || DECL_REGISTER (exp))));
}
+
+/* Subroutine for fold_truth_andor: determine if an operand is simple enough
+ to be evaluated unconditionally.
+ I addition to simple_operand_p, we assume that comparisons, conversions,
+ and logic-not operations are simple, if their operands are simple, too. */
+
+static bool
+simple_operand_p_2 (tree exp)
+{
+ enum tree_code code;
+
+ if (TREE_SIDE_EFFECTS (exp)
+ || tree_could_trap_p (exp))
+ return false;
+
+ while (CONVERT_EXPR_P (exp))
+ exp = TREE_OPERAND (exp, 0);
+
+ code = TREE_CODE (exp);
+
+ if (TREE_CODE_CLASS (code) == tcc_comparison)
+ return (simple_operand_p (TREE_OPERAND (exp, 0))
+ && simple_operand_p (TREE_OPERAND (exp, 1)));
+
+ if (code == TRUTH_NOT_EXPR)
+ return simple_operand_p_2 (TREE_OPERAND (exp, 0));
+
+ return simple_operand_p (exp);
+}
+
/* The following functions are subroutines to fold_range_test and allow it to
try to change a logical combination of comparisons into a range test.
@@ -4888,7 +4917,7 @@ fold_range_test (location_t loc, enum tree_code code, tree type,
return 0;
}
-/* Subroutine for fold_truthop: C is an INTEGER_CST interpreted as a P
+/* Subroutine for fold_truth_andor_1: C is an INTEGER_CST interpreted as a P
bit value. Arrange things so the extra bits will be set to zero if and
only if C is signed-extended to its full width. If MASK is nonzero,
it is an INTEGER_CST that should be AND'ed with the extra bits. */
@@ -5025,8 +5054,8 @@ merge_truthop_with_opposite_arm (location_t loc, tree op, tree cmpop,
We return the simplified tree or 0 if no optimization is possible. */
static tree
-fold_truthop (location_t loc, enum tree_code code, tree truth_type,
- tree lhs, tree rhs)
+fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type,
+ tree lhs, tree rhs)
{
/* If this is the "or" of two comparisons, we can do something if
the comparisons are NE_EXPR. If this is the "and", we can do something
@@ -5054,8 +5083,6 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
tree lntype, rntype, result;
HOST_WIDE_INT first_bit, end_bit;
int volatilep;
- tree orig_lhs = lhs, orig_rhs = rhs;
- enum tree_code orig_code = code;
/* Start by getting the comparison codes. Fail if anything is volatile.
If one operand is a BIT_AND_EXPR with the constant one, treat it as if
@@ -5119,8 +5146,7 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
/* 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
- that can be merged. Avoid doing this if the RHS is a floating-point
- comparison since those can trap. */
+ that can be merged. */
if (BRANCH_COST (optimize_function_for_speed_p (cfun),
false) >= 2
@@ -5149,13 +5175,6 @@ fold_truthop (location_t loc, enum tree_code code, tree truth_type,
build2 (BIT_IOR_EXPR, TREE_TYPE (ll_arg),
ll_arg, rl_arg),
build_int_cst (TREE_TYPE (ll_arg), 0));
-
- if (LOGICAL_OP_NON_SHORT_CIRCUIT)
- {
- if (code != orig_code || lhs != orig_lhs || rhs != orig_rhs)
- return build2_loc (loc, code, truth_type, lhs, rhs);
- return NULL_TREE;
- }
}
/* See if the comparisons can be merged. Then get all the parameters for
@@ -8380,13 +8399,69 @@ fold_truth_andor (location_t loc, enum tree_code code, tree type,
lhs is another similar operation, try to merge its rhs with our
rhs. Then try to merge our lhs and rhs. */
if (TREE_CODE (arg0) == code
- && 0 != (tem = fold_truthop (loc, code, type,
- TREE_OPERAND (arg0, 1), arg1)))
+ && 0 != (tem = fold_truth_andor_1 (loc, code, type,
+ TREE_OPERAND (arg0, 1), arg1)))
return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), tem);
- if ((tem = fold_truthop (loc, code, type, arg0, arg1)) != 0)
+ if ((tem = fold_truth_andor_1 (loc, code, type, arg0, arg1)) != 0)
return tem;
+ if ((BRANCH_COST (optimize_function_for_speed_p (cfun),
+ false) >= 2)
+ && LOGICAL_OP_NON_SHORT_CIRCUIT
+ && (code == TRUTH_AND_EXPR
+ || code == TRUTH_ANDIF_EXPR
+ || code == TRUTH_OR_EXPR
+ || code == TRUTH_ORIF_EXPR))
+ {
+ enum tree_code ncode, icode;
+
+ ncode = (code == TRUTH_ANDIF_EXPR || code == TRUTH_AND_EXPR)
+ ? TRUTH_AND_EXPR : TRUTH_OR_EXPR;
+ icode = ncode == TRUTH_AND_EXPR ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
+
+ /* Transform ((A AND-IF B) AND[-IF] C) into (A AND-IF (B AND C)),
+ or ((A OR-IF B) OR[-IF] C) into (A OR-IF (B OR C))
+ We don't want to pack more than two leafs to a non-IF AND/OR
+ expression.
+ If tree-code of left-hand operand isn't an AND/OR-IF code and not
+ equal to IF-CODE, then we don't want to add right-hand operand.
+ If the inner right-hand side of left-hand operand has
+ side-effects, or isn't simple, then we can't add to it,
+ as otherwise we might destroy if-sequence. */
+ if (TREE_CODE (arg0) == icode
+ && simple_operand_p_2 (arg1)
+ /* Needed for sequence points to handle trappings, and
+ side-effects. */
+ && simple_operand_p_2 (TREE_OPERAND (arg0, 1)))
+ {
+ tem = fold_build2_loc (loc, ncode, type, TREE_OPERAND (arg0, 1),
+ arg1);
+ return fold_build2_loc (loc, icode, type, TREE_OPERAND (arg0, 0),
+ tem);
+ }
+ /* Same as abouve but for (A AND[-IF] (B AND-IF C)) -> ((A AND B) AND-IF C),
+ or (A OR[-IF] (B OR-IF C) -> ((A OR B) OR-IF C). */
+ else if (TREE_CODE (arg1) == icode
+ && simple_operand_p_2 (arg0)
+ /* Needed for sequence points to handle trappings, and
+ side-effects. */
+ && simple_operand_p_2 (TREE_OPERAND (arg1, 0)))
+ {
+ tem = fold_build2_loc (loc, ncode, type,
+ arg0, TREE_OPERAND (arg1, 0));
+ return fold_build2_loc (loc, icode, type, tem,
+ TREE_OPERAND (arg1, 1));
+ }
+ /* Transform (A AND-IF B) into (A AND B), or (A OR-IF B)
+ into (A OR B).
+ For sequence point consistancy, we need to check for trapping,
+ and side-effects. */
+ else if (code == icode && simple_operand_p_2 (arg0)
+ && simple_operand_p_2 (arg1))
+ return fold_build2_loc (loc, ncode, type, arg0, arg1);
+ }
+
return NULL_TREE;
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 5e3d024b897..ade1906d255 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,207 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makef-lang.in (gfortranspec.o): Pass SHLIB instead of SHLIB_LINK.
+
+2011-10-30 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/50573
+ * check.c (gfc_check_dshift): Update argument checking for BOZ.
+ Update checking SHIFT against BITSIZE of I or J.
+ * intrinsic.texi: Update docs for DSHIFTL and DSHIFTR.
+
+2011-10-28 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * check.c (gfc_check_atan_2): Typo in comment.
+ (gfc_check_nearest): If 's' is constant, check that it is not 0.
+ * simplify.c (simplify_dshift, gfc_simplify_ibclr, gfc_simplify_ibits,
+ gfc_simplify_ibset, simplify_shift, gfc_simplify_ishftc,
+ gfc_simplify_nearest): Remove dead code.
+
+2011-10-23 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * simplify.c (simplify_transformation_to_array): Fix memory leak.
+
+2011-10-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/50821
+ * check.c (gfc_check_ishftc): Check args are constant before
+ extracting the integer.
+
+2011-10-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/50514
+ * check.c (less_than_bitsize1): Check |shift| <= bit_size(i).
+ (gfc_check_ishftc): Check |shift| <= bit_size(i) and check
+ that size is positive.
+
+2011-10-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/50524
+ * resolve.c (resolve_ref): Check return value of resolve_substring().
+
+2011-10-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * io.c (match_dt_format): Match a user-defined operator or a kind
+ type prefixed string.
+
+2011-10-19 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * check.c (gfc_check_sizeof): Reject procedures as argument of SIZEOF.
+ * intrinsinc.texi (SIZEOF): Document it.
+ (STORAGE_SIZE): Fix special characters. Fix line breaks.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans.c (gfc_build_array_ref): If type is not an array, check that
+ there is nothing to do, and do nothing.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-types.c (gfc_build_array_type): Don't force lower bound to one
+ in the deferred case.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * simplify.c (simplify_cobound): Accept non-last-in-ref-chain coarrays.
+ Don't set already set array ref.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ * array.c (gfc_find_array_ref): Remove coarray-specific handling.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * check.c (dim_corank_check): Use gfc_get_corank to get corank.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-intrinsic.c (walk_coarray): Change AR_ELEMENT to AR_SECTION.
+
+ PR fortran/50420
+ * trans-intrinsic.c (walk_coarray): Use gfc_walk_array_ref for
+ the scalarization chain initialization.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-intrinsic.c (walk_coarray): Allow subreferences after a
+ coarray object reference.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-array.c (gfc_walk_array_ref): Allow zero rank arrays
+ if they are coarrays.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.h (gfc_walk_array_ref): New prototype.
+ * trans-array.c (gfc_walk_array_ref): New function, containing
+ all but the beginning of gfc_walk_variable_expr's code.
+ (gfc_walk_variable_expr): Use gfc_walk_array_ref.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-array.c (gfc_conv_expr_descriptor): Use loop.dimen instead of
+ ndim for the descriptor's rank.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * trans-array.c (gfc_conv_expr_descriptor): Count codimensions starting
+ from zero, and add then the relevant offset (either ndim or loop.dimen)
+ depending on context.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.c (gfc_conv_expr_descriptor): Save some horizontal space.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ * trans-array.c (gfc_conv_expr_descriptor): Move ndim initialization
+ earlier.
+
+2011-10-18 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * decl.c (verify_c_interop_param): Renamed to
+ 'gfc_verify_c_interop_param'. Add error message for polymorphic
+ arguments.
+ (verify_c_interop): Renamed to 'gfc_verify_c_interop'. Reject
+ polymorphic variables.
+ (verify_bind_c_sym): Renamed 'verify_c_interop'.
+ * gfortran.h (verify_c_interop,verify_c_interop_param): Renamed.
+ * check.c (gfc_check_sizeof): Ditto.
+ * resolve.c (gfc_iso_c_func_interface,resolve_fl_procedure): Ditto.
+ * symbol.c (verify_bind_c_derived_type): Ditto.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * cpp.c (print_line, cb_define): Adjust to avoid using internals
+ of struct line_map. Use the public API instead.
+
+2011-10-17 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ PR fortran/50752
+ * primary.c (match_kind_param): Avoid segfault.
+
+2011-10-16 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ * frontend-passes.c (current_ns): Make static.
+ (create_var): Note parent of newly created namespace.
+ (optimize_namespace): Don't wak sibling namespaces
+ if they are EXEC_BLOCK because this is handled...
+ (gfc_code_walker): ... here. Also walk ASSOCIATE lists.
+
+2011-10-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * primary.c (match_kind_param): Detect ISO_C_BINDING kinds.
+ (get_kind): Pass on 'is_iso_c' flag.
+ (match_integer_constant,match_real_constant,match_logical_constant):
+ Set 'ts.is_c_interop'.
+
+2011-10-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50547
+ * resolve.c (resolve_formal_arglist): Remove unneeded error message.
+ Some reshuffling.
+
+2011-10-15 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.texi (Fortran 2008 status, TS 29113 status,
+ Further Interoperability of Fortran with C): Update implementation
+ status, change references from TR 29113 to TS 29113.
+ * intrinsic.texi (RANK): Change TR 29113 to TS 29113.
+ * invoke.text (-std=): Ditto, change -std=f2008tr to -std=f2008ts.
+ * lang.opt (std=): Ditto.
+ * options.c (gfc_handle_option, set_default_std_flags): Ditto and
+ change GFC_STD_F2008_TR to GFC_STD_F2008_TS.
+ * libgfortran.h: Ditto.
+ * intrinsic.c (add_functions, gfc_check_intrinsic_standard): Ditto.
+ * decl.c (verify_c_interop_param): Ditto.
+
+2011-10-14 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50570
+ * expr.c (gfc_check_vardef_context): Don't throw an error on
+ non-pointer assignments involving an intent(in) pointer dummy.
+
+2011-10-14 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/50718
+ * trans-expr.c (gfc_conv_procedure_call): Fix -fcheck=pointer
+ for dummy arguments with VALUE attribute.
+
2011-10-11 Tobias Burnus <burnus@net-b.de>
Janus Weil <janus@gcc.gnu.org>
diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index b766da651a2..2602b157ab8 100644
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -79,7 +79,7 @@ fortran: f951$(exeext)
gfortranspec.o: $(srcdir)/fortran/gfortranspec.c $(SYSTEM_H) $(TM_H) $(GCC_H) \
$(CONFIG_H) coretypes.h intl.h $(OPTS_H)
- (SHLIB_LINK='$(SHLIB_LINK)'; \
+ (SHLIB='$(SHLIB)'; \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
$(INCLUDES) $(srcdir)/fortran/gfortranspec.c)
diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c
index aa9cc0c3ab3..3e6b9d2591c 100644
--- a/gcc/fortran/array.c
+++ b/gcc/fortran/array.c
@@ -2296,8 +2296,7 @@ gfc_find_array_ref (gfc_expr *e)
for (ref = e->ref; ref; ref = ref->next)
if (ref->type == REF_ARRAY
- && (ref->u.ar.type == AR_FULL || ref->u.ar.type == AR_SECTION
- || (ref->u.ar.type == AR_ELEMENT && ref->u.ar.dimen == 0)))
+ && (ref->u.ar.type == AR_FULL || ref->u.ar.type == AR_SECTION))
break;
if (ref == NULL)
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index 9b8ec21a763..d9b9a9cd580 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -286,6 +286,22 @@ less_than_bitsize1 (const char *arg1, gfc_expr *expr1, const char *arg2,
{
gfc_extract_int (expr2, &i2);
i3 = gfc_validate_kind (BT_INTEGER, expr1->ts.kind, false);
+
+ /* For ISHFT[C], check that |shift| <= bit_size(i). */
+ if (arg2 == NULL)
+ {
+ if (i2 < 0)
+ i2 = -i2;
+
+ if (i2 > gfc_integer_kinds[i3].bit_size)
+ {
+ gfc_error ("The absolute value of SHIFT at %L must be less "
+ "than or equal to BIT_SIZE('%s')",
+ &expr2->where, arg1);
+ return FAILURE;
+ }
+ }
+
if (or_equal)
{
if (i2 > gfc_integer_kinds[i3].bit_size)
@@ -511,7 +527,6 @@ dim_check (gfc_expr *dim, int n, bool optional)
static gfc_try
dim_corank_check (gfc_expr *dim, gfc_expr *array)
{
- gfc_array_ref *ar;
int corank;
gcc_assert (array->expr_type == EXPR_VARIABLE);
@@ -519,8 +534,7 @@ dim_corank_check (gfc_expr *dim, gfc_expr *array)
if (dim->expr_type != EXPR_CONSTANT)
return SUCCESS;
- ar = gfc_find_array_ref (array);
- corank = ar->as->corank;
+ corank = gfc_get_corank (array);
if (mpz_cmp_ui (dim->value.integer, 1) < 0
|| mpz_cmp_ui (dim->value.integer, corank) > 0)
@@ -920,7 +934,7 @@ null_arg:
gfc_try
gfc_check_atan_2 (gfc_expr *y, gfc_expr *x)
{
- /* gfc_notify_std would be a wast of time as the return value
+ /* gfc_notify_std would be a waste of time as the return value
is seemingly used only for the generic resolution. The error
will be: Too many arguments. */
if ((gfc_option.allow_std & GFC_STD_F2008) == 0)
@@ -1469,7 +1483,14 @@ gfc_check_dshift (gfc_expr *i, gfc_expr *j, gfc_expr *shift)
if (type_check (j, 1, BT_INTEGER) == FAILURE)
return FAILURE;
- if (same_type_check (i, 0, j, 1) == FAILURE)
+ if (i->is_boz && j->is_boz)
+ {
+ gfc_error ("'I' at %L and 'J' at %L cannot both be BOZ literal "
+ "constants", &i->where, &j->where);
+ return FAILURE;
+ }
+
+ if (!i->is_boz && !j->is_boz && same_type_check (i, 0, j, 1) == FAILURE)
return FAILURE;
if (type_check (shift, 2, BT_INTEGER) == FAILURE)
@@ -1478,8 +1499,18 @@ gfc_check_dshift (gfc_expr *i, gfc_expr *j, gfc_expr *shift)
if (nonnegative_check ("SHIFT", shift) == FAILURE)
return FAILURE;
- if (less_than_bitsize1 ("I", i, "SHIFT", shift, true) == FAILURE)
- return FAILURE;
+ if (i->is_boz)
+ {
+ if (less_than_bitsize1 ("J", j, "SHIFT", shift, true) == FAILURE)
+ return FAILURE;
+ i->ts.kind = j->ts.kind;
+ }
+ else
+ {
+ if (less_than_bitsize1 ("I", i, "SHIFT", shift, true) == FAILURE)
+ return FAILURE;
+ j->ts.kind = i->ts.kind;
+ }
return SUCCESS;
}
@@ -1929,6 +1960,9 @@ gfc_check_ishft (gfc_expr *i, gfc_expr *shift)
|| type_check (shift, 1, BT_INTEGER) == FAILURE)
return FAILURE;
+ if (less_than_bitsize1 ("I", i, NULL, shift, true) == FAILURE)
+ return FAILURE;
+
return SUCCESS;
}
@@ -1940,7 +1974,42 @@ gfc_check_ishftc (gfc_expr *i, gfc_expr *shift, gfc_expr *size)
|| type_check (shift, 1, BT_INTEGER) == FAILURE)
return FAILURE;
- if (size != NULL && type_check (size, 2, BT_INTEGER) == FAILURE)
+ if (size != NULL)
+ {
+ int i2, i3;
+
+ if (type_check (size, 2, BT_INTEGER) == FAILURE)
+ return FAILURE;
+
+ if (less_than_bitsize1 ("I", i, "SIZE", size, true) == FAILURE)
+ return FAILURE;
+
+ if (size->expr_type == EXPR_CONSTANT)
+ {
+ gfc_extract_int (size, &i3);
+ if (i3 <= 0)
+ {
+ gfc_error ("SIZE at %L must be positive", &size->where);
+ return FAILURE;
+ }
+
+ if (shift->expr_type == EXPR_CONSTANT)
+ {
+ gfc_extract_int (shift, &i2);
+ if (i2 < 0)
+ i2 = -i2;
+
+ if (i2 > i3)
+ {
+ gfc_error ("The absolute value of SHIFT at %L must be less "
+ "than or equal to SIZE at %L", &shift->where,
+ &size->where);
+ return FAILURE;
+ }
+ }
+ }
+ }
+ else if (less_than_bitsize1 ("I", i, NULL, shift, true) == FAILURE)
return FAILURE;
return SUCCESS;
@@ -2658,6 +2727,16 @@ gfc_check_nearest (gfc_expr *x, gfc_expr *s)
if (type_check (s, 1, BT_REAL) == FAILURE)
return FAILURE;
+ if (s->expr_type == EXPR_CONSTANT)
+ {
+ if (mpfr_sgn (s->value.real) == 0)
+ {
+ gfc_error ("Argument 'S' of NEAREST at %L shall not be zero",
+ &s->where);
+ return FAILURE;
+ }
+ }
+
return SUCCESS;
}
@@ -3446,8 +3525,15 @@ gfc_check_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
gfc_try
-gfc_check_sizeof (gfc_expr *arg ATTRIBUTE_UNUSED)
+gfc_check_sizeof (gfc_expr *arg)
{
+ if (arg->ts.type == BT_PROCEDURE)
+ {
+ gfc_error ("'%s' argument of '%s' intrinsic at %L may not be a procedure",
+ gfc_current_intrinsic_arg[0]->name, gfc_current_intrinsic,
+ &arg->where);
+ return FAILURE;
+ }
return SUCCESS;
}
@@ -3455,7 +3541,7 @@ gfc_check_sizeof (gfc_expr *arg ATTRIBUTE_UNUSED)
gfc_try
gfc_check_c_sizeof (gfc_expr *arg)
{
- if (verify_c_interop (&arg->ts) != SUCCESS)
+ if (gfc_verify_c_interop (&arg->ts) != SUCCESS)
{
gfc_error ("'%s' argument of '%s' intrinsic at %L must be an "
"interoperable data entity",
diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c
index 9368d890973..2f18893313b 100644
--- a/gcc/fortran/cpp.c
+++ b/gcc/fortran/cpp.c
@@ -818,27 +818,29 @@ print_line (source_location src_loc, const char *special_flags)
if (!gfc_cpp_option.no_line_commands)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
-
- size_t to_file_len = strlen (map->to_file);
- unsigned char *to_file_quoted =
- (unsigned char *) alloca (to_file_len * 4 + 1);
+ expanded_location loc;
+ size_t to_file_len;
+ unsigned char *to_file_quoted;
unsigned char *p;
- print.src_line = SOURCE_LINE (map, src_loc);
+ loc = expand_location (src_loc);
+ to_file_len = strlen (loc.file);
+ to_file_quoted = (unsigned char *) alloca (to_file_len * 4 + 1);
+
+ print.src_line = loc.line;
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
- (const unsigned char *) map->to_file, to_file_len);
+ (const unsigned char *) loc.file, to_file_len);
*p = '\0';
fprintf (print.outf, "# %u \"%s\"%s",
print.src_line == 0 ? 1 : print.src_line,
to_file_quoted, special_flags);
- if (map->sysp == 2)
+ if (loc.sysp == 2)
fputs (" 3 4", print.outf);
- else if (map->sysp == 1)
+ else if (loc.sysp == 1)
fputs (" 3", print.outf);
putc ('\n', print.outf);
@@ -935,7 +937,7 @@ cb_define (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- if (linemap_lookup (line_table, line)->to_line != 0)
+ if (LOCATION_LINE (line) != 0)
print.src_line++;
}
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 0ee25759113..2dd38b9485e 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -961,7 +961,7 @@ get_proc_name (const char *name, gfc_symbol **result, bool module_fcn_entry)
across platforms. */
gfc_try
-verify_c_interop_param (gfc_symbol *sym)
+gfc_verify_c_interop_param (gfc_symbol *sym)
{
int is_c_interop = 0;
gfc_try retval = SUCCESS;
@@ -1000,20 +1000,24 @@ verify_c_interop_param (gfc_symbol *sym)
{
if (sym->ns->proc_name->attr.is_bind_c == 1)
{
- is_c_interop =
- (verify_c_interop (&(sym->ts))
- == SUCCESS ? 1 : 0);
+ is_c_interop = (gfc_verify_c_interop (&(sym->ts)) == SUCCESS ? 1 : 0);
if (is_c_interop != 1)
{
/* Make personalized messages to give better feedback. */
if (sym->ts.type == BT_DERIVED)
- gfc_error ("Type '%s' at %L is a parameter to the BIND(C) "
- "procedure '%s' but is not C interoperable "
+ gfc_error ("Variable '%s' at %L is a dummy argument to the "
+ "BIND(C) procedure '%s' but is not C interoperable "
"because derived type '%s' is not C interoperable",
sym->name, &(sym->declared_at),
sym->ns->proc_name->name,
sym->ts.u.derived->name);
+ else if (sym->ts.type == BT_CLASS)
+ gfc_error ("Variable '%s' at %L is a dummy argument to the "
+ "BIND(C) procedure '%s' but is not C interoperable "
+ "because it is polymorphic",
+ sym->name, &(sym->declared_at),
+ sym->ns->proc_name->name);
else
gfc_warning ("Variable '%s' at %L is a parameter to the "
"BIND(C) procedure '%s' but may not be C "
@@ -1069,7 +1073,7 @@ verify_c_interop_param (gfc_symbol *sym)
retval = FAILURE;
}
else if (sym->attr.optional == 1
- && gfc_notify_std (GFC_STD_F2008_TR, "TR29113: Variable '%s' "
+ && gfc_notify_std (GFC_STD_F2008_TS, "TS29113: Variable '%s' "
"at %L with OPTIONAL attribute in "
"procedure '%s' which is BIND(C)",
sym->name, &(sym->declared_at),
@@ -3711,11 +3715,13 @@ set_com_block_bind_c (gfc_common_head *com_block, int is_bind_c)
/* Verify that the given gfc_typespec is for a C interoperable type. */
gfc_try
-verify_c_interop (gfc_typespec *ts)
+gfc_verify_c_interop (gfc_typespec *ts)
{
if (ts->type == BT_DERIVED && ts->u.derived != NULL)
return (ts->u.derived->ts.is_c_interop || ts->u.derived->attr.is_bind_c)
? SUCCESS : FAILURE;
+ else if (ts->type == BT_CLASS)
+ return FAILURE;
else if (ts->is_c_interop != 1)
return FAILURE;
@@ -3788,7 +3794,7 @@ verify_bind_c_sym (gfc_symbol *tmp_sym, gfc_typespec *ts,
the given ts (current_ts), so look in both. */
if (tmp_sym->ts.type != BT_UNKNOWN || ts->type != BT_UNKNOWN)
{
- if (verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
+ if (gfc_verify_c_interop (&(tmp_sym->ts)) != SUCCESS)
{
/* See if we're dealing with a sym in a common block or not. */
if (is_in_common == 1)
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index 8a09a28b289..504c7cf7d6b 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -4635,7 +4635,7 @@ gfc_check_vardef_context (gfc_expr* e, bool pointer, bool alloc_obj,
sym->name, context, &e->where);
return FAILURE;
}
- if (!pointer && !is_pointer)
+ if (!pointer && !is_pointer && !sym->attr.pointer)
{
if (context)
gfc_error ("Dummy argument '%s' with INTENT(IN) in variable"
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index dcbaf06d170..5b1a644e247 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -60,7 +60,7 @@ static gfc_code *inserted_block, **changed_statement;
/* The namespace we are currently dealing with. */
-gfc_namespace *current_ns;
+static gfc_namespace *current_ns;
/* If we are within any forall loop. */
@@ -261,6 +261,7 @@ create_var (gfc_expr * e)
(*current_code)->next = NULL;
/* Insert the BLOCK at the right position. */
*current_code = inserted_block;
+ ns->parent = current_ns;
}
else
ns = inserted_block->ext.block.ns;
@@ -509,8 +510,12 @@ optimize_namespace (gfc_namespace *ns)
gfc_code_walker (&ns->code, cfe_code, cfe_expr_0, NULL);
gfc_code_walker (&ns->code, optimize_code, optimize_expr, NULL);
+ /* BLOCKs are handled in the expression walker below. */
for (ns = ns->contained; ns; ns = ns->sibling)
- optimize_namespace (ns);
+ {
+ if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
+ optimize_namespace (ns);
+ }
}
/* Replace code like
@@ -1143,6 +1148,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
gfc_code *b;
gfc_actual_arglist *a;
gfc_code *co;
+ gfc_association_list *alist;
/* There might be statement insertions before the current code,
which must not affect the expression walker. */
@@ -1151,6 +1157,13 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
switch (co->op)
{
+
+ case EXEC_BLOCK:
+ WALK_SUBCODE (co->ext.block.ns->code);
+ for (alist = co->ext.block.assoc; alist; alist = alist->next)
+ WALK_SUBEXPR (alist->target);
+ break;
+
case EXEC_DO:
WALK_SUBEXPR (co->ext.iterator->var);
WALK_SUBEXPR (co->ext.iterator->start);
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 1bd5ec36edd..da3477d7a0b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2581,8 +2581,8 @@ gfc_symtree* gfc_find_symtree_in_proc (const char *, gfc_namespace *);
int gfc_find_symbol (const char *, gfc_namespace *, int, gfc_symbol **);
int gfc_find_sym_tree (const char *, gfc_namespace *, int, gfc_symtree **);
int gfc_get_symbol (const char *, gfc_namespace *, gfc_symbol **);
-gfc_try verify_c_interop (gfc_typespec *);
-gfc_try verify_c_interop_param (gfc_symbol *);
+gfc_try gfc_verify_c_interop (gfc_typespec *);
+gfc_try gfc_verify_c_interop_param (gfc_symbol *);
gfc_try verify_bind_c_sym (gfc_symbol *, gfc_typespec *, int, gfc_common_head *);
gfc_try verify_bind_c_derived_type (gfc_symbol *);
gfc_try verify_com_block_vars_c_interop (gfc_common_head *);
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 389c05bfaab..f847df38409 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -772,7 +772,7 @@ compile option was used.
@menu
* Fortran 2003 status::
* Fortran 2008 status::
-* TR 29113 status::
+* TS 29113 status::
@end menu
@node Fortran 2003 status
@@ -1003,8 +1003,11 @@ the intrinsic module @code{ISO_FORTRAN_ENV}.
@code{ISO_C_BINDINGS} and @code{COMPILER_VERSION} and @code{COMPILER_OPTIONS}
of @code{ISO_FORTRAN_ENV}.
-@item Experimental coarray, use the @option{-fcoarray=single} or
-@option{-fcoarray=lib} flag to enable it.
+@item Coarray support for serial programs with @option{-fcoarray=single} flag
+and experimental support for multiple images with the @option{-fcoarray=lib}
+flag.
+
+@item The @code{DO CONCURRENT} construct is supported.
@item The @code{BLOCK} construct is supported.
@@ -1049,19 +1052,25 @@ arrays are supported for named constants (@code{PARAMETER}).
-@node TR 29113 status
-@section Fortran 29113 status
+@node TS 29113 status
+@section Technical Specification 29113 Status
-GNU Fortran supports some of the new features of the technical report (TR)
-29113 on Further Interoperability of Fortran with C.
-@uref{http://gcc.gnu.org/wiki/Fortran2008Status, wiki} has some information
-about the current TR 29113 implementation status. In particular, the
+GNU Fortran supports some of the new features of the Technical
+Specification (TS) 29113 on Further Interoperability of Fortran with C.
+The @uref{http://gcc.gnu.org/wiki/TS29113Status, wiki} has some information
+about the current TS 29113 implementation status. In particular, the
following is implemented.
@itemize
-@item The @option{-std=f2008} option.
-@item The OPTIONAL attribute is now allowed for dummy arguments of
-BIND(C) procedures.
+@item The @option{-std=f2008ts} option.
+
+@item The @code{OPTIONAL} attribute is allowed for dummy arguments
+of @code{BIND(C) procedures.}
+
+@item The RANK intrinsic is supported.
+
+@item GNU Fortran's implementation for variables with @code{ASYNCHRONOUS}
+attribute is compatible with TS 29113.
@end itemize
@@ -2446,15 +2455,13 @@ END MODULE m
Assumed-shape and allocatable arrays are passed using an array descriptor
(dope vector). The internal structure of the array descriptor used
by GNU Fortran is not yet documented and will change. There will also be
-a Technical Report (TR 29113) which standardizes an interoperable
+a Technical Specification (TS 29113) which standardizes an interoperable
array descriptor. Until then, you can use the Chasm Language
Interoperability Tools, @url{http://chasm-interop.sourceforge.net/},
which provide an interface to GNU Fortran's array descriptor.
-The technical report 29113 will presumably also include support for
-C-interoperable @code{OPTIONAL} and for assumed-rank and assumed-type
-dummy arguments. However, the TR has neither been approved nor implemented
-in GNU Fortran; therefore, these features are not yet available.
+GNU Fortran already supports the C-interoperable @code{OPTIONAL}
+attribute; for absent arguments, a @code{NULL} pointer is passed.
@@ -2620,9 +2627,9 @@ Possible values are (bitwise or-ed) @code{GFC_STD_F77} (1),
@code{GFC_STD_F95_OBS} (2), @code{GFC_STD_F95_DEL} (4), @code{GFC_STD_F95}
(8), @code{GFC_STD_F2003} (16), @code{GFC_STD_GNU} (32),
@code{GFC_STD_LEGACY} (64), @code{GFC_STD_F2008} (128),
-@code{GFC_STD_F2008_OBS} (256) and GFC_STD_F2008_TR (512). Default:
+@code{GFC_STD_F2008_OBS} (256) and GFC_STD_F2008_TS (512). Default:
@code{GFC_STD_F95_OBS | GFC_STD_F95_DEL | GFC_STD_F95 | GFC_STD_F2003
-| GFC_STD_F2008 | GFC_STD_F2008_TR | GFC_STD_F2008_OBS | GFC_STD_F77
+| GFC_STD_F2008 | GFC_STD_F2008_TS | GFC_STD_F2008_OBS | GFC_STD_F77
| GFC_STD_GNU | GFC_STD_LEGACY}.
@item @var{option}[1] @tab Standard-warning flag; prints a warning to
standard error. Default: @code{GFC_STD_F95_DEL | GFC_STD_LEGACY}.
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 5946ddd8be2..8f437cc05fe 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -2434,9 +2434,9 @@ add_functions (void)
make_generic ("range", GFC_ISYM_RANGE, GFC_STD_F95);
add_sym_1 ("rank", GFC_ISYM_RANK, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di,
- GFC_STD_F2008_TR, gfc_check_rank, gfc_simplify_rank, NULL,
+ GFC_STD_F2008_TS, gfc_check_rank, gfc_simplify_rank, NULL,
a, BT_REAL, dr, REQUIRED);
- make_generic ("rank", GFC_ISYM_RANK, GFC_STD_F2008_TR);
+ make_generic ("rank", GFC_ISYM_RANK, GFC_STD_F2008_TS);
add_sym_2 ("real", GFC_ISYM_REAL, CLASS_ELEMENTAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F77,
gfc_check_real, gfc_simplify_real, gfc_resolve_real,
@@ -3989,8 +3989,8 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
symstd_msg = "new in Fortran 2008";
break;
- case GFC_STD_F2008_TR:
- symstd_msg = "new in TR 29113";
+ case GFC_STD_F2008_TS:
+ symstd_msg = "new in TS 29113";
break;
case GFC_STD_GNU:
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index a093bec8c7c..24af4d5ac7d 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -3794,22 +3794,27 @@ Elemental function
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{I} @tab Shall be of type @code{INTEGER}.
-@item @var{J} @tab Shall be of type @code{INTEGER}, and of the same kind
-as @var{I}.
-@item @var{SHIFT} @tab Shall be of type @code{INTEGER}.
+@item @var{I} @tab Shall be of type @code{INTEGER} or a BOZ constant.
+@item @var{J} @tab Shall be of type @code{INTEGER} or a BOZ constant.
+If both @var{I} and @var{J} have integer type, then they shall have
+the same kind type parameter. @var{I} and @var{J} shall not both be
+BOZ constants.
+@item @var{SHIFT} @tab Shall be of type @code{INTEGER}. It shall
+be nonnegative. If @var{I} is not a BOZ constant, then @var{SHIFT}
+shall be less than or equal to @code{BIT_SIZE(I)}; otherwise,
+@var{SHIFT} shall be less than or equal to @code{BIT_SIZE(J)}.
@end multitable
@item @emph{Return value}:
-The return value has same type and kind as @var{I}.
+If either @var{I} or @var{J} is a BOZ constant, it is first converted
+as if by the intrinsic function @code{INT} to an integer type with the
+kind type parameter of the other.
@item @emph{See also}:
@ref{DSHIFTR}
-
@end table
-
@node DSHIFTR
@section @code{DSHIFTR} --- Combined right shift
@fnindex DSHIFTR
@@ -3834,22 +3839,27 @@ Elemental function
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{I} @tab Shall be of type @code{INTEGER}.
-@item @var{J} @tab Shall be of type @code{INTEGER}, and of the same kind
-as @var{I}.
-@item @var{SHIFT} @tab Shall be of type @code{INTEGER}.
+@item @var{I} @tab Shall be of type @code{INTEGER} or a BOZ constant.
+@item @var{J} @tab Shall be of type @code{INTEGER} or a BOZ constant.
+If both @var{I} and @var{J} have integer type, then they shall have
+the same kind type parameter. @var{I} and @var{J} shall not both be
+BOZ constants.
+@item @var{SHIFT} @tab Shall be of type @code{INTEGER}. It shall
+be nonnegative. If @var{I} is not a BOZ constant, then @var{SHIFT}
+shall be less than or equal to @code{BIT_SIZE(I)}; otherwise,
+@var{SHIFT} shall be less than or equal to @code{BIT_SIZE(J)}.
@end multitable
@item @emph{Return value}:
-The return value has same type and kind as @var{I}.
+If either @var{I} or @var{J} is a BOZ constant, it is first converted
+as if by the intrinsic function @code{INT} to an integer type with the
+kind type parameter of the other.
@item @emph{See also}:
@ref{DSHIFTL}
-
@end table
-
@node DTIME
@section @code{DTIME} --- Execution time subroutine (or function)
@fnindex DTIME
@@ -10222,7 +10232,7 @@ See @code{PRECISION} for an example.
@code{RANK(A)} returns the rank of a scalar or array data object.
@item @emph{Standard}:
-Technical Report (TR) 29113
+Technical Specification (TS) 29113
@item @emph{Class}:
Inquiry function
@@ -11459,7 +11469,8 @@ number of bytes occupied by the argument. If the argument has the
to is returned. If the argument is of a derived type with @code{POINTER}
or @code{ALLOCATABLE} components, the return value doesn't account for
the sizes of the data pointed to by these components. If the argument is
-polymorphic, the size according to the declared type is returned.
+polymorphic, the size according to the declared type is returned. The argument
+may not be a procedure or procedure pointer.
@item @emph{Example}:
@smallexample
@@ -11816,8 +11827,10 @@ Inquiry function
@end multitable
@item @emph{Return Value}:
-The result is a scalar integer with the kind type parameter speciï¬ed by KIND (or default integer type if KIND is missing). The result value is the size expressed in bits for an element of an array that
-has the dynamic type and type parameters of A.
+The result is a scalar integer with the kind type parameter specified by KIND
+(or default integer type if KIND is missing). The result value is the size
+expressed in bits for an element of an array that has the dynamic type and type
+parameters of A.
@item @emph{See also}:
@ref{C_SIZEOF}, @ref{SIZEOF}
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 44f384eff78..5bb9b9dbbdf 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -368,9 +368,10 @@ extensions, and may be useful for old non-standard programs. The
conformance to the Fortran 95, Fortran 2003 and Fortran 2008 standards,
respectively; errors are given for all extensions beyond the relevant
language standard, and warnings are given for the Fortran 77 features
-that are permitted but obsolescent in later standards. @samp{-std=f2008tr}
+that are permitted but obsolescent in later standards. @samp{-std=f2008ts}
allows the Fortran 2008 standard including the additions of the
-technical report (TR) 29113.
+Technical Specification (TS) 29113 on Further Interoperability of Fortran
+with C.
@end table
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index 58c942f6d5b..a291bb8b167 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -2548,17 +2548,31 @@ match_dt_format (gfc_dt *dt)
if ((m = gfc_match_st_label (&label)) == MATCH_YES)
{
- if (dt->format_expr != NULL || dt->format_label != NULL)
+ char c;
+
+ /* Need to check if the format label is actually either an operand
+ to a user-defined operator or is a kind type parameter. That is,
+ print 2.ip.8 ! .ip. is a user-defined operator return CHARACTER.
+ print 1_'(I0)', i ! 1_'(I0)' is a default character string. */
+
+ gfc_gobble_whitespace ();
+ c = gfc_peek_ascii_char ();
+ if (c == '.' || c == '_')
+ gfc_current_locus = where;
+ else
{
- gfc_free_st_label (label);
- goto conflict;
- }
+ if (dt->format_expr != NULL || dt->format_label != NULL)
+ {
+ gfc_free_st_label (label);
+ goto conflict;
+ }
- if (gfc_reference_st_label (label, ST_LABEL_FORMAT) == FAILURE)
- return MATCH_ERROR;
+ if (gfc_reference_st_label (label, ST_LABEL_FORMAT) == FAILURE)
+ return MATCH_ERROR;
- dt->format_label = label;
- return MATCH_YES;
+ dt->format_label = label;
+ return MATCH_YES;
+ }
}
else if (m == MATCH_ERROR)
/* The label was zero or too large. Emit the correct diagnosis. */
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 1a3d073b3fb..081041bebe7 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -590,9 +590,9 @@ std=f2008
Fortran
Conform to the ISO Fortran 2008 standard
-std=f2008tr
+std=f2008ts
Fortran
-Conform to the ISO Fortran 2008 standard including TR 29113
+Conform to the ISO Fortran 2008 standard including TS 29113
std=f95
Fortran
diff --git a/gcc/fortran/libgfortran.h b/gcc/fortran/libgfortran.h
index b2137bbf80f..874cd9537bb 100644
--- a/gcc/fortran/libgfortran.h
+++ b/gcc/fortran/libgfortran.h
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see
Note that no features were obsoleted nor deleted in F2003.
Please remember to keep those definitions in sync with
gfortran.texi. */
-#define GFC_STD_F2008_TR (1<<9) /* POST-F2008 technical reports. */
+#define GFC_STD_F2008_TS (1<<9) /* POST-F2008 technical reports. */
#define GFC_STD_F2008_OBS (1<<8) /* Obsolescent in F2008. */
#define GFC_STD_F2008 (1<<7) /* New in F2008. */
#define GFC_STD_LEGACY (1<<6) /* Backward compatibility. */
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 4c59bd59eeb..dcb11e85d1c 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -49,7 +49,7 @@ set_default_std_flags (void)
{
gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F95_DEL
| GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F95 | GFC_STD_F77
- | GFC_STD_F2008_OBS | GFC_STD_F2008_TR | GFC_STD_GNU | GFC_STD_LEGACY;
+ | GFC_STD_F2008_OBS | GFC_STD_F2008_TS | GFC_STD_GNU | GFC_STD_LEGACY;
gfc_option.warn_std = GFC_STD_F95_DEL | GFC_STD_LEGACY;
}
@@ -945,10 +945,10 @@ gfc_handle_option (size_t scode, const char *arg, int value,
gfc_option.warn_tabs = 0;
break;
- case OPT_std_f2008tr:
+ case OPT_std_f2008ts:
gfc_option.allow_std = GFC_STD_F95_OBS | GFC_STD_F77
| GFC_STD_F2003 | GFC_STD_F95 | GFC_STD_F2008 | GFC_STD_F2008_OBS
- | GFC_STD_F2008_TR;
+ | GFC_STD_F2008_TS;
gfc_option.warn_std = GFC_STD_F95_OBS | GFC_STD_F2008_OBS;
gfc_option.max_identifier_length = 63;
gfc_option.warn_ampersand = 1;
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index bccf7d49cf9..23dc0b66400 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -32,16 +32,20 @@ int matching_actual_arglist = 0;
/* Matches a kind-parameter expression, which is either a named
symbolic constant or a nonnegative integer constant. If
- successful, sets the kind value to the correct integer. */
+ successful, sets the kind value to the correct integer.
+ The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
+ symbol like e.g. 'c_int'. */
static match
-match_kind_param (int *kind)
+match_kind_param (int *kind, int *is_iso_c)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
gfc_symbol *sym;
const char *p;
match m;
+ *is_iso_c = 0;
+
m = gfc_match_small_literal_int (kind, NULL);
if (m != MATCH_NO)
return m;
@@ -56,6 +60,8 @@ match_kind_param (int *kind)
if (sym == NULL)
return MATCH_NO;
+ *is_iso_c = sym->attr.is_iso_c;
+
if (sym->attr.flavor != FL_PARAMETER)
return MATCH_NO;
@@ -77,20 +83,24 @@ match_kind_param (int *kind)
/* Get a trailing kind-specification for non-character variables.
Returns:
- the integer kind value or:
- -1 if an error was generated
- -2 if no kind was found */
+ * the integer kind value or
+ * -1 if an error was generated,
+ * -2 if no kind was found.
+ The argument 'is_iso_c' signals whether the kind is an ISO_C_BINDING
+ symbol like e.g. 'c_int'. */
static int
-get_kind (void)
+get_kind (int *is_iso_c)
{
int kind;
match m;
+ *is_iso_c = 0;
+
if (gfc_match_char ('_') != MATCH_YES)
return -2;
- m = match_kind_param (&kind);
+ m = match_kind_param (&kind, is_iso_c);
if (m == MATCH_NO)
gfc_error ("Missing kind-parameter at %C");
@@ -188,7 +198,7 @@ match_digits (int signflag, int radix, char *buffer)
static match
match_integer_constant (gfc_expr **result, int signflag)
{
- int length, kind;
+ int length, kind, is_iso_c;
locus old_loc;
char *buffer;
gfc_expr *e;
@@ -208,7 +218,7 @@ match_integer_constant (gfc_expr **result, int signflag)
match_digits (signflag, 10, buffer);
- kind = get_kind ();
+ kind = get_kind (&is_iso_c);
if (kind == -2)
kind = gfc_default_integer_kind;
if (kind == -1)
@@ -221,6 +231,7 @@ match_integer_constant (gfc_expr **result, int signflag)
}
e = gfc_convert_integer (buffer, kind, 10, &gfc_current_locus);
+ e->ts.is_c_interop = is_iso_c;
if (gfc_range_check (e) != ARITH_OK)
{
@@ -473,7 +484,7 @@ backup:
static match
match_real_constant (gfc_expr **result, int signflag)
{
- int kind, count, seen_dp, seen_digits;
+ int kind, count, seen_dp, seen_digits, is_iso_c;
locus old_loc, temp_loc;
char *p, *buffer, c, exp_char;
gfc_expr *e;
@@ -611,7 +622,7 @@ done:
c = gfc_next_ascii_char ();
}
- kind = get_kind ();
+ kind = get_kind (&is_iso_c);
if (kind == -1)
goto cleanup;
@@ -665,6 +676,7 @@ done:
e = gfc_convert_real (buffer, kind, &gfc_current_locus);
if (negate)
mpfr_neg (e->value.real, e->value.real, GFC_RND_MODE);
+ e->ts.is_c_interop = is_iso_c;
switch (gfc_range_check (e))
{
@@ -1099,13 +1111,13 @@ static match
match_logical_constant (gfc_expr **result)
{
gfc_expr *e;
- int i, kind;
+ int i, kind, is_iso_c;
i = match_logical_constant_string ();
if (i == -1)
return MATCH_NO;
- kind = get_kind ();
+ kind = get_kind (&is_iso_c);
if (kind == -1)
return MATCH_ERROR;
if (kind == -2)
@@ -1118,6 +1130,7 @@ match_logical_constant (gfc_expr **result)
}
e = gfc_get_logical_expr (kind, &gfc_current_locus, i);
+ e->ts.is_c_interop = is_iso_c;
*result = e;
return MATCH_YES;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index edeb49daf7d..30f5f55e214 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -269,50 +269,18 @@ resolve_formal_arglist (gfc_symbol *proc)
if (sym->attr.if_source != IFSRC_UNKNOWN)
resolve_formal_arglist (sym);
- /* F08:C1279. */
- if (gfc_pure (proc)
- && sym->attr.flavor == FL_PROCEDURE && !gfc_pure (sym))
+ if (sym->attr.subroutine || sym->attr.external)
{
- gfc_error ("Dummy procedure '%s' of PURE procedure at %L must "
- "also be PURE", sym->name, &sym->declared_at);
- continue;
+ if (sym->attr.flavor == FL_UNKNOWN)
+ gfc_add_flavor (&sym->attr, FL_PROCEDURE, sym->name, &sym->declared_at);
}
-
- if (sym->attr.subroutine || sym->attr.external || sym->attr.intrinsic)
+ else
{
- if (proc->attr.implicit_pure && !gfc_pure(sym))
- proc->attr.implicit_pure = 0;
-
- /* F08:C1289. */
- if (gfc_elemental (proc))
- {
- gfc_error ("Dummy procedure at %L not allowed in ELEMENTAL "
- "procedure", &sym->declared_at);
- continue;
- }
-
- if (sym->attr.function
- && sym->ts.type == BT_UNKNOWN
- && sym->attr.intrinsic)
- {
- gfc_intrinsic_sym *isym;
- isym = gfc_find_function (sym->name);
- if (isym == NULL || !isym->specific)
- {
- gfc_error ("Unable to find a specific INTRINSIC procedure "
- "for the reference '%s' at %L", sym->name,
- &sym->declared_at);
- }
- sym->ts = isym->ts;
- }
-
- continue;
+ if (sym->ts.type == BT_UNKNOWN && !proc->attr.intrinsic
+ && (!sym->attr.function || sym->result == sym))
+ gfc_set_default_type (sym, 1, sym->ns);
}
- if (sym->ts.type == BT_UNKNOWN && !proc->attr.intrinsic
- && (!sym->attr.function || sym->result == sym))
- gfc_set_default_type (sym, 1, sym->ns);
-
gfc_resolve_array_spec (sym->as, 0);
/* We can't tell if an array with dimension (:) is assumed or deferred
@@ -343,44 +311,64 @@ resolve_formal_arglist (gfc_symbol *proc)
if (sym->attr.flavor == FL_UNKNOWN)
gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, &sym->declared_at);
- if (gfc_pure (proc) && !sym->attr.pointer
- && sym->attr.flavor != FL_PROCEDURE)
+ if (gfc_pure (proc))
{
- if (proc->attr.function && sym->attr.intent != INTENT_IN)
+ if (sym->attr.flavor == FL_PROCEDURE)
{
- if (sym->attr.value)
- gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Argument '%s' "
- "of pure function '%s' at %L with VALUE "
- "attribute but without INTENT(IN)", sym->name,
- proc->name, &sym->declared_at);
- else
- gfc_error ("Argument '%s' of pure function '%s' at %L must be "
- "INTENT(IN) or VALUE", sym->name, proc->name,
- &sym->declared_at);
+ /* F08:C1279. */
+ if (!gfc_pure (sym))
+ {
+ gfc_error ("Dummy procedure '%s' of PURE procedure at %L must "
+ "also be PURE", sym->name, &sym->declared_at);
+ continue;
+ }
}
-
- if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN)
+ else if (!sym->attr.pointer)
{
- if (sym->attr.value)
- gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Argument '%s' "
- "of pure subroutine '%s' at %L with VALUE "
- "attribute but without INTENT", sym->name,
- proc->name, &sym->declared_at);
- else
- gfc_error ("Argument '%s' of pure subroutine '%s' at %L must "
- "have its INTENT specified or have the VALUE "
- "attribute", sym->name, proc->name, &sym->declared_at);
+ if (proc->attr.function && sym->attr.intent != INTENT_IN)
+ {
+ if (sym->attr.value)
+ gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Argument '%s'"
+ " of pure function '%s' at %L with VALUE "
+ "attribute but without INTENT(IN)",
+ sym->name, proc->name, &sym->declared_at);
+ else
+ gfc_error ("Argument '%s' of pure function '%s' at %L must "
+ "be INTENT(IN) or VALUE", sym->name, proc->name,
+ &sym->declared_at);
+ }
+
+ if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN)
+ {
+ if (sym->attr.value)
+ gfc_notify_std (GFC_STD_F2008, "Fortran 2008: Argument '%s'"
+ " of pure subroutine '%s' at %L with VALUE "
+ "attribute but without INTENT", sym->name,
+ proc->name, &sym->declared_at);
+ else
+ gfc_error ("Argument '%s' of pure subroutine '%s' at %L "
+ "must have its INTENT specified or have the "
+ "VALUE attribute", sym->name, proc->name,
+ &sym->declared_at);
+ }
}
}
- if (proc->attr.implicit_pure && !sym->attr.pointer
- && sym->attr.flavor != FL_PROCEDURE)
+ if (proc->attr.implicit_pure)
{
- if (proc->attr.function && sym->attr.intent != INTENT_IN)
- proc->attr.implicit_pure = 0;
+ if (sym->attr.flavor == FL_PROCEDURE)
+ {
+ if (!gfc_pure(sym))
+ proc->attr.implicit_pure = 0;
+ }
+ else if (!sym->attr.pointer)
+ {
+ if (proc->attr.function && sym->attr.intent != INTENT_IN)
+ proc->attr.implicit_pure = 0;
- if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN)
- proc->attr.implicit_pure = 0;
+ if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN)
+ proc->attr.implicit_pure = 0;
+ }
}
if (gfc_elemental (proc))
@@ -2821,7 +2809,7 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_actual_arglist *args,
&(args->expr->where));
/* See if we have interoperable type and type param. */
- if (verify_c_interop (arg_ts) == SUCCESS
+ if (gfc_verify_c_interop (arg_ts) == SUCCESS
|| gfc_check_any_c_kind (arg_ts) == SUCCESS)
{
if (args_sym->attr.target == 1)
@@ -4858,7 +4846,8 @@ resolve_ref (gfc_expr *expr)
break;
case REF_SUBSTRING:
- resolve_substring (ref);
+ if (resolve_substring (ref) == FAILURE)
+ return FAILURE;
break;
}
@@ -10556,7 +10545,7 @@ resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
{
/* Skip implicitly typed dummy args here. */
if (curr_arg->sym->attr.implicit_type == 0)
- if (verify_c_interop_param (curr_arg->sym) == FAILURE)
+ if (gfc_verify_c_interop_param (curr_arg->sym) == FAILURE)
/* If something is found to fail, record the fact so we
can mark the symbol for the procedure as not being
BIND(C) to try and prevent multiple errors being
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 13a9c5147c0..01071cfe138 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -516,6 +516,7 @@ simplify_transformation_to_array (gfc_expr *result, gfc_expr *array, gfc_expr *d
linked-list traversal. Masked elements are set to NULL. */
gfc_array_size (array, &size);
arraysize = mpz_get_ui (size);
+ mpz_clear (size);
arrayvec = XCNEWVEC (gfc_expr*, arraysize);
@@ -1898,13 +1899,7 @@ simplify_dshift (gfc_expr *arg1, gfc_expr *arg2, gfc_expr *shiftarg,
k = gfc_validate_kind (BT_INTEGER, arg1->ts.kind, false);
size = gfc_integer_kinds[k].bit_size;
- if (gfc_extract_int (shiftarg, &shift) != NULL)
- {
- gfc_error ("Invalid SHIFT argument of DSHIFTL at %L", &shiftarg->where);
- return &gfc_bad_expr;
- }
-
- gcc_assert (shift >= 0 && shift <= size);
+ gfc_extract_int (shiftarg, &shift);
/* DSHIFTR(I,J,SHIFT) = DSHIFTL(I,J,SIZE-SHIFT). */
if (right)
@@ -2508,21 +2503,10 @@ gfc_simplify_ibclr (gfc_expr *x, gfc_expr *y)
if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
return NULL;
- if (gfc_extract_int (y, &pos) != NULL || pos < 0)
- {
- gfc_error ("Invalid second argument of IBCLR at %L", &y->where);
- return &gfc_bad_expr;
- }
+ gfc_extract_int (y, &pos);
k = gfc_validate_kind (x->ts.type, x->ts.kind, false);
- if (pos >= gfc_integer_kinds[k].bit_size)
- {
- gfc_error ("Second argument of IBCLR exceeds bit size at %L",
- &y->where);
- return &gfc_bad_expr;
- }
-
result = gfc_copy_expr (x);
convert_mpz_to_unsigned (result->value.integer,
@@ -2550,17 +2534,8 @@ gfc_simplify_ibits (gfc_expr *x, gfc_expr *y, gfc_expr *z)
|| z->expr_type != EXPR_CONSTANT)
return NULL;
- if (gfc_extract_int (y, &pos) != NULL || pos < 0)
- {
- gfc_error ("Invalid second argument of IBITS at %L", &y->where);
- return &gfc_bad_expr;
- }
-
- if (gfc_extract_int (z, &len) != NULL || len < 0)
- {
- gfc_error ("Invalid third argument of IBITS at %L", &z->where);
- return &gfc_bad_expr;
- }
+ gfc_extract_int (y, &pos);
+ gfc_extract_int (z, &len);
k = gfc_validate_kind (BT_INTEGER, x->ts.kind, false);
@@ -2613,21 +2588,10 @@ gfc_simplify_ibset (gfc_expr *x, gfc_expr *y)
if (x->expr_type != EXPR_CONSTANT || y->expr_type != EXPR_CONSTANT)
return NULL;
- if (gfc_extract_int (y, &pos) != NULL || pos < 0)
- {
- gfc_error ("Invalid second argument of IBSET at %L", &y->where);
- return &gfc_bad_expr;
- }
+ gfc_extract_int (y, &pos);
k = gfc_validate_kind (x->ts.type, x->ts.kind, false);
- if (pos >= gfc_integer_kinds[k].bit_size)
- {
- gfc_error ("Second argument of IBSET exceeds bit size at %L",
- &y->where);
- return &gfc_bad_expr;
- }
-
result = gfc_copy_expr (x);
convert_mpz_to_unsigned (result->value.integer,
@@ -3003,11 +2967,8 @@ simplify_shift (gfc_expr *e, gfc_expr *s, const char *name,
if (e->expr_type != EXPR_CONSTANT || s->expr_type != EXPR_CONSTANT)
return NULL;
- if (gfc_extract_int (s, &shift) != NULL)
- {
- gfc_error ("Invalid second argument of %s at %L", name, &s->where);
- return &gfc_bad_expr;
- }
+
+ gfc_extract_int (s, &shift);
k = gfc_validate_kind (BT_INTEGER, e->ts.kind, false);
bitsize = gfc_integer_kinds[k].bit_size;
@@ -3145,11 +3106,7 @@ gfc_simplify_ishftc (gfc_expr *e, gfc_expr *s, gfc_expr *sz)
if (e->expr_type != EXPR_CONSTANT || s->expr_type != EXPR_CONSTANT)
return NULL;
- if (gfc_extract_int (s, &shift) != NULL)
- {
- gfc_error ("Invalid second argument of ISHFTC at %L", &s->where);
- return &gfc_bad_expr;
- }
+ gfc_extract_int (s, &shift);
k = gfc_validate_kind (e->ts.type, e->ts.kind, false);
isize = gfc_integer_kinds[k].bit_size;
@@ -3159,18 +3116,8 @@ gfc_simplify_ishftc (gfc_expr *e, gfc_expr *s, gfc_expr *sz)
if (sz->expr_type != EXPR_CONSTANT)
return NULL;
- if (gfc_extract_int (sz, &ssize) != NULL || ssize <= 0)
- {
- gfc_error ("Invalid third argument of ISHFTC at %L", &sz->where);
- return &gfc_bad_expr;
- }
+ gfc_extract_int (sz, &ssize);
- if (ssize > isize)
- {
- gfc_error ("Magnitude of third argument of ISHFTC exceeds "
- "BIT_SIZE of first argument at %L", &s->where);
- return &gfc_bad_expr;
- }
}
else
ssize = isize;
@@ -3182,10 +3129,7 @@ gfc_simplify_ishftc (gfc_expr *e, gfc_expr *s, gfc_expr *sz)
if (ashift > ssize)
{
- if (sz != NULL)
- gfc_error ("Magnitude of second argument of ISHFTC exceeds "
- "third argument at %L", &s->where);
- else
+ if (sz == NULL)
gfc_error ("Magnitude of second argument of ISHFTC exceeds "
"BIT_SIZE of first argument at %L", &s->where);
return &gfc_bad_expr;
@@ -3512,11 +3456,9 @@ simplify_cobound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind, int upper)
switch (ref->u.ar.type)
{
case AR_ELEMENT:
- if (ref->next == NULL)
+ if (ref->u.ar.as->corank > 0)
{
- gcc_assert (ref->u.ar.as->corank > 0
- && ref->u.ar.as->rank == 0);
- as = ref->u.ar.as;
+ gcc_assert (as == ref->u.ar.as);
goto done;
}
as = NULL;
@@ -4383,13 +4325,6 @@ gfc_simplify_nearest (gfc_expr *x, gfc_expr *s)
if (x->expr_type != EXPR_CONSTANT || s->expr_type != EXPR_CONSTANT)
return NULL;
- if (mpfr_sgn (s->value.real) == 0)
- {
- gfc_error ("Second argument of NEAREST at %L shall not be zero",
- &s->where);
- return &gfc_bad_expr;
- }
-
result = gfc_copy_expr (x);
/* Save current values of emin and emax. */
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 4b506fe83e8..67d65cb16b9 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -3209,7 +3209,8 @@ gfc_new_charlen (gfc_namespace *ns, gfc_charlen *old_cl)
/* Free the charlen list from cl to end (end is not freed).
Free the whole list if end is NULL. */
-void gfc_free_charlen (gfc_charlen *cl, gfc_charlen *end)
+void
+gfc_free_charlen (gfc_charlen *cl, gfc_charlen *end)
{
gfc_charlen *cl2;
@@ -3635,7 +3636,7 @@ verify_bind_c_derived_type (gfc_symbol *derived_sym)
else
{
/* Grab the typespec for the given component and test the kind. */
- is_c_interop = verify_c_interop (&(curr_comp->ts));
+ is_c_interop = gfc_verify_c_interop (&(curr_comp->ts));
if (is_c_interop != SUCCESS)
{
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 585dc438d63..3472804e4c6 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -5974,28 +5974,31 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
tree to;
tree base;
+ ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
+
if (se->want_coarray)
{
+ gfc_array_ref *ar = &info->ref->u.ar;
+
codim = gfc_get_corank (expr);
- for (n = ss->data.info.dimen; n < ss->data.info.dimen + codim - 1;
- n++)
+ for (n = 0; n < codim - 1; n++)
{
/* Make sure we are not lost somehow. */
- gcc_assert (info->ref->u.ar.dimen_type[n] == DIMEN_THIS_IMAGE);
+ gcc_assert (ar->dimen_type[n + ndim] == DIMEN_THIS_IMAGE);
/* Make sure the call to gfc_conv_section_startstride won't
generate unnecessary code to calculate stride. */
- gcc_assert (info->ref->u.ar.stride[n] == NULL);
+ gcc_assert (ar->stride[n + ndim] == NULL);
- gfc_conv_section_startstride (&loop, ss, n);
- loop.from[n] = info->start[n];
- loop.to[n] = info->end[n];
+ gfc_conv_section_startstride (&loop, ss, n + ndim);
+ loop.from[n + loop.dimen] = info->start[n + ndim];
+ loop.to[n + loop.dimen] = info->end[n + ndim];
}
- gcc_assert (n == ss->data.info.dimen + codim - 1);
- evaluate_bound (&loop.pre, info->start, info->ref->u.ar.start,
- info->descriptor, n, true);
- loop.from[n] = info->start[n];
+ gcc_assert (n == codim - 1);
+ evaluate_bound (&loop.pre, info->start, ar->start,
+ info->descriptor, n + ndim, true);
+ loop.from[n + loop.dimen] = info->start[n + ndim];
}
else
codim = 0;
@@ -6046,7 +6049,6 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
else
base = NULL_TREE;
- ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
for (n = 0; n < ndim; n++)
{
stride = gfc_conv_array_stride (desc, n);
@@ -6148,13 +6150,13 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
gfc_rank_cst[dim], stride);
}
- for (n = ndim; n < ndim + codim; n++)
+ for (n = loop.dimen; n < loop.dimen + codim; n++)
{
from = loop.from[n];
to = loop.to[n];
gfc_conv_descriptor_lbound_set (&loop.pre, parm,
gfc_rank_cst[n], from);
- if (n < ndim + codim - 1)
+ if (n < loop.dimen + codim - 1)
gfc_conv_descriptor_ubound_set (&loop.pre, parm,
gfc_rank_cst[n], to);
}
@@ -7601,14 +7603,22 @@ static gfc_ss *
gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
{
gfc_ref *ref;
- gfc_array_ref *ar;
- gfc_ss *newss;
- int n;
for (ref = expr->ref; ref; ref = ref->next)
if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
break;
+ return gfc_walk_array_ref (ss, expr, ref);
+}
+
+
+gfc_ss *
+gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
+{
+ gfc_array_ref *ar;
+ gfc_ss *newss;
+ int n;
+
for (; ref; ref = ref->next)
{
if (ref->type == REF_SUBSTRING)
@@ -7690,8 +7700,10 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
gcc_unreachable ();
}
}
- /* We should have at least one non-elemental dimension. */
- gcc_assert (newss->data.info.dimen > 0);
+ /* We should have at least one non-elemental dimension,
+ unless we are creating a descriptor for a (scalar) coarray. */
+ gcc_assert (newss->data.info.dimen > 0
+ || newss->data.info.ref->u.ar.as->corank > 0);
ss = newss;
break;
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index 73d8c40c9e9..4d737bde94f 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -70,6 +70,8 @@ void gfc_trans_static_array_pointer (gfc_symbol *);
gfc_ss *gfc_walk_expr (gfc_expr *);
/* Workhorse for gfc_walk_expr. */
gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
+/* Workhorse for gfc_walk_variable_expr. */
+gfc_ss *gfc_walk_array_ref (gfc_ss *, gfc_expr *, gfc_ref * ref);
/* Walk the arguments of an elemental function. */
gfc_ss *gfc_walk_elemental_function_args (gfc_ss *, gfc_actual_arglist *,
gfc_ss_type);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index ca0523fedca..09b98d03faf 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -3357,10 +3357,16 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
else
goto end_pointer_check;
+ tmp = parmse.expr;
+
+ /* If the argument is passed by value, we need to strip the
+ INDIRECT_REF. */
+ if (!POINTER_TYPE_P (TREE_TYPE (parmse.expr)))
+ tmp = gfc_build_addr_expr (NULL_TREE, tmp);
cond = fold_build2_loc (input_location, EQ_EXPR,
- boolean_type_node, parmse.expr,
- fold_convert (TREE_TYPE (parmse.expr),
+ boolean_type_node, tmp,
+ fold_convert (TREE_TYPE (tmp),
null_pointer_node));
}
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index ed18bfa6bde..83fc4fc52ef 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -940,15 +940,20 @@ walk_coarray (gfc_expr *e)
{
gfc_ref *ref;
- ss = gfc_get_array_ss (gfc_ss_terminator, e, 0, GFC_SS_SECTION);
-
ref = e->ref;
- while (ref->next)
- ref = ref->next;
+ while (ref)
+ {
+ if (ref->type == REF_ARRAY
+ && ref->u.ar.codimen > 0)
+ break;
+
+ ref = ref->next;
+ }
- gcc_assert (ref->type == REF_ARRAY && ref->u.ar.codimen > 0);
- ref->u.ar.type = AR_FULL;
- ss->data.info.ref = ref;
+ gcc_assert (ref != NULL);
+ if (ref->u.ar.type == AR_ELEMENT)
+ ref->u.ar.type = AR_SECTION;
+ ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
}
return ss;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 4c5990e7ae1..cb5f30e28e0 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1254,7 +1254,7 @@ gfc_build_array_type (tree type, gfc_array_spec * as,
for (n = as->rank; n < as->rank + as->corank; n++)
{
- if (as->lower[n] == NULL)
+ if (as->type != AS_DEFERRED && as->lower[n] == NULL)
lbound[n] = gfc_index_one_node;
else
lbound[n] = gfc_conv_array_bound (as->lower[n]);
diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c
index 0176aece2b8..88bd389c545 100644
--- a/gcc/fortran/trans.c
+++ b/gcc/fortran/trans.c
@@ -323,7 +323,14 @@ gfc_build_array_ref (tree base, tree offset, tree decl)
return fold_convert (TYPE_MAIN_VARIANT (type), base);
}
- gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+ /* Scalar coarray, there is nothing to do. */
+ if (TREE_CODE (type) != ARRAY_TYPE)
+ {
+ gcc_assert (decl == NULL_TREE);
+ gcc_assert (integer_zerop (offset));
+ return base;
+ }
+
type = TREE_TYPE (type);
if (DECL_P (base))
diff --git a/gcc/function.c b/gcc/function.c
index 35ddfd6894f..2058d754080 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2892,17 +2892,6 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
SET_DECL_RTL (parm, stack_parm);
}
-/* A subroutine of assign_parm_setup_reg, called through note_stores.
- This collects sets and clobbers of hard registers in a HARD_REG_SET,
- which is pointed to by DATA. */
-static void
-record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
-{
- HARD_REG_SET *pset = (HARD_REG_SET *)data;
- if (REG_P (x) && HARD_REGISTER_P (x))
- add_to_hard_reg_set (pset, GET_MODE (x), REGNO (x));
-}
-
/* A subroutine of assign_parms. Allocate a pseudo to hold the current
parameter. Get it there. Perform all ABI specified conversions. */
@@ -3617,7 +3606,7 @@ gimplify_parameters (void)
&& compare_tree_int (DECL_SIZE_UNIT (parm),
STACK_CHECK_MAX_VAR_SIZE) > 0))
{
- local = create_tmp_reg (type, get_name (parm));
+ local = create_tmp_var (type, get_name (parm));
DECL_IGNORED_P (local) = 0;
/* If PARM was addressable, move that flag over
to the local copy, as its address will be taken,
@@ -3625,6 +3614,9 @@ gimplify_parameters (void)
as we'll query that flag during gimplification. */
if (TREE_ADDRESSABLE (parm))
TREE_ADDRESSABLE (local) = 1;
+ else if (TREE_CODE (type) == COMPLEX_TYPE
+ || TREE_CODE (type) == VECTOR_TYPE)
+ DECL_GIMPLE_REG_P (local) = 1;
}
else
{
@@ -3636,7 +3628,7 @@ gimplify_parameters (void)
local = build_fold_indirect_ref (addr);
t = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
- t = build_call_expr (t, 1, DECL_SIZE_UNIT (parm),
+ t = build_call_expr (t, 2, DECL_SIZE_UNIT (parm),
size_int (DECL_ALIGN (parm)));
/* The call has been built for a variable-sized object. */
@@ -5286,25 +5278,6 @@ prologue_epilogue_contains (const_rtx insn)
#ifdef HAVE_simple_return
-/* A for_each_rtx subroutine of record_hard_reg_sets. */
-static int
-record_hard_reg_uses_1 (rtx *px, void *data)
-{
- rtx x = *px;
- HARD_REG_SET *pused = (HARD_REG_SET *)data;
-
- if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
- add_to_hard_reg_set (pused, GET_MODE (x), REGNO (x));
- return 0;
-}
-
-/* Like record_hard_reg_sets, but called through note_uses. */
-static void
-record_hard_reg_uses (rtx *px, void *data)
-{
- for_each_rtx (px, record_hard_reg_uses_1, data);
-}
-
/* Return true if INSN requires the stack frame to be set up.
PROLOGUE_USED contains the hard registers used in the function
prologue. SET_UP_BY_PROLOGUE is the set of registers we expect the
@@ -5527,6 +5500,20 @@ emit_return_into_block (bool simple_p, basic_block bb)
}
#endif
+/* Set JUMP_LABEL for a return insn. */
+
+void
+set_return_jump_label (rtx returnjump)
+{
+ rtx pat = PATTERN (returnjump);
+ if (GET_CODE (pat) == PARALLEL)
+ pat = XVECEXP (pat, 0, 0);
+ if (ANY_RETURN_P (pat))
+ JUMP_LABEL (returnjump) = pat;
+ else
+ JUMP_LABEL (returnjump) = ret_rtx;
+}
+
/* Return true if BB has any active insns. */
static bool
bb_active_p (basic_block bb)
@@ -5804,7 +5791,7 @@ thread_prologue_and_epilogue_insns (void)
to convert jumps to it to (potentially conditional) return
insns later. This means we don't necessarily need a prologue
for paths reaching it. */
- if (last_bb)
+ if (last_bb && optimize)
{
if (!last_bb_active)
bitmap_clear_bit (&bb_flags, last_bb->index);
@@ -6062,7 +6049,7 @@ thread_prologue_and_epilogue_insns (void)
emit_return_into_block (false, last_bb);
epilogue_end = BB_END (last_bb);
if (JUMP_P (epilogue_end))
- JUMP_LABEL (epilogue_end) = ret_rtx;
+ set_return_jump_label (epilogue_end);
single_succ_edge (last_bb)->flags &= ~EDGE_FALLTHRU;
goto epilogue_done;
}
@@ -6127,15 +6114,7 @@ thread_prologue_and_epilogue_insns (void)
inserted = true;
if (JUMP_P (returnjump))
- {
- rtx pat = PATTERN (returnjump);
- if (GET_CODE (pat) == PARALLEL)
- pat = XVECEXP (pat, 0, 0);
- if (ANY_RETURN_P (pat))
- JUMP_LABEL (returnjump) = pat;
- else
- JUMP_LABEL (returnjump) = ret_rtx;
- }
+ set_return_jump_label (returnjump);
}
else
#endif
diff --git a/gcc/gcc-ar.c b/gcc/gcc-ar.c
new file mode 100644
index 00000000000..706b2f389e5
--- /dev/null
+++ b/gcc/gcc-ar.c
@@ -0,0 +1,96 @@
+/* Wrapper for ar/ranlib/nm to pass the LTO plugin.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+ Contributed by Andi Kleen.
+
+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 3, 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 COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "libiberty.h"
+
+#ifndef PERSONALITY
+#error "Please set personality"
+#endif
+
+static const char standard_libexec_prefix[] = STANDARD_LIBEXEC_PREFIX;
+static const char standard_bin_prefix[] = STANDARD_BINDIR_PREFIX;
+static const char *const target_machine = TARGET_MACHINE;
+
+static const char dir_separator[] = { DIR_SEPARATOR, 0 };
+
+int
+main(int ac, char **av)
+{
+ const char *nprefix;
+ const char *exe_name;
+ char *plugin;
+ int k, status, err;
+ const char *err_msg;
+ const char **nargv;
+ bool is_ar = !strcmp (PERSONALITY, "ar");
+
+ exe_name = PERSONALITY;
+#ifdef CROSS_DIRECTORY_STRUCTURE
+ exe_name = concat (target_machine, "-", exe_name, NULL);
+#endif
+
+ /* Find plugin */
+ /* XXX implement more magic from gcc.c? */
+ nprefix = getenv ("GCC_EXEC_PREFIX");
+ if (!nprefix)
+ nprefix = standard_libexec_prefix;
+
+ nprefix = make_relative_prefix (av[0],
+ standard_bin_prefix,
+ nprefix);
+ plugin = concat (nprefix,
+ dir_separator,
+ DEFAULT_TARGET_MACHINE,
+ dir_separator,
+ DEFAULT_TARGET_VERSION,
+ dir_separator,
+ LTOPLUGINSONAME,
+ NULL);
+ if (access (plugin, X_OK))
+ {
+ fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
+ exit (1);
+ }
+
+ /* Create new command line with plugin */
+ nargv = XCNEWVEC (const char *, ac + 4);
+ nargv[0] = exe_name;
+ nargv[1] = "--plugin";
+ nargv[2] = plugin;
+ if (is_ar && av[1] && av[1][0] != '-')
+ av[1] = concat("-", av[1], NULL);
+ for (k = 1; k < ac; k++)
+ nargv[2 + k] = av[k];
+ nargv[2 + k] = NULL;
+
+ /* Run utility */
+ /* ??? the const is misplaced in pex_one's argv? */
+ err_msg = pex_one (PEX_LAST|PEX_SEARCH,
+ exe_name,
+ CONST_CAST2 (char * const *, const char **, nargv),
+ concat("gcc-", exe_name, NULL),
+ NULL,NULL, &status, &err);
+ if (err_msg)
+ fprintf(stderr, "Error running %s: %s\n", exe_name, err_msg);
+
+ return err;
+}
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 3bfdf77b401..0fd4edda28f 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -6851,7 +6851,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
LTOPLUGINSONAME, R_OK,
false);
if (!linker_plugin_file_spec)
- fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found");
+ fatal_error ("-fuse-linker-plugin, but %s not found", LTOPLUGINSONAME);
}
#endif
lto_gcc_spec = argv[0];
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 0820741a051..6063d81daa5 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1817,6 +1817,11 @@ struct file_rule_st files_rules[] = {
REG_EXTENDED, NULL_REGEX,
"gt-objc-objc-act.h", "objc/objc-act.c", NULL_FRULACT },
+ /* objc/objc-map.h gives gt-objc-objc-map.h for objc/objc-map.c ! */
+ { DIR_PREFIX_REGEX "objc/objc-map\\.h$",
+ REG_EXTENDED, NULL_REGEX,
+ "gt-objc-objc-map.h", "objc/objc-map.c", NULL_FRULACT },
+
/* General cases. For header *.h and source *.c files, we need
* special actions to handle the language. */
diff --git a/gcc/genopinit.c b/gcc/genopinit.c
index 1954783d831..44eba24f11a 100644
--- a/gcc/genopinit.c
+++ b/gcc/genopinit.c
@@ -276,6 +276,7 @@ static const char * const optabs[] =
"set_optab_handler (vec_shr_optab, $A, CODE_FOR_$(vec_shr_$a$))",
"set_optab_handler (vec_realign_load_optab, $A, CODE_FOR_$(vec_realign_load_$a$))",
"set_direct_optab_handler (vec_perm_optab, $A, CODE_FOR_$(vec_perm$a$))",
+ "set_direct_optab_handler (vec_perm_const_optab, $A, CODE_FOR_$(vec_perm_const$a$))",
"set_convert_optab_handler (vcond_optab, $A, $B, CODE_FOR_$(vcond$a$b$))",
"set_convert_optab_handler (vcondu_optab, $A, $B, CODE_FOR_$(vcondu$a$b$))",
"set_optab_handler (ssum_widen_optab, $A, CODE_FOR_$(widen_ssum$I$a3$))",
@@ -292,6 +293,10 @@ static const char * const optabs[] =
"set_optab_handler (vec_widen_umult_lo_optab, $A, CODE_FOR_$(vec_widen_umult_lo_$a$))",
"set_optab_handler (vec_widen_smult_hi_optab, $A, CODE_FOR_$(vec_widen_smult_hi_$a$))",
"set_optab_handler (vec_widen_smult_lo_optab, $A, CODE_FOR_$(vec_widen_smult_lo_$a$))",
+ "set_optab_handler (vec_widen_ushiftl_hi_optab, $A, CODE_FOR_$(vec_widen_ushiftl_hi_$a$))",
+ "set_optab_handler (vec_widen_ushiftl_lo_optab, $A, CODE_FOR_$(vec_widen_ushiftl_lo_$a$))",
+ "set_optab_handler (vec_widen_sshiftl_hi_optab, $A, CODE_FOR_$(vec_widen_sshiftl_hi_$a$))",
+ "set_optab_handler (vec_widen_sshiftl_lo_optab, $A, CODE_FOR_$(vec_widen_sshiftl_lo_$a$))",
"set_optab_handler (vec_unpacks_hi_optab, $A, CODE_FOR_$(vec_unpacks_hi_$a$))",
"set_optab_handler (vec_unpacks_lo_optab, $A, CODE_FOR_$(vec_unpacks_lo_$a$))",
"set_optab_handler (vec_unpacku_hi_optab, $A, CODE_FOR_$(vec_unpacku_hi_$a$))",
diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
index 97d25b9b653..e57d61787df 100644
--- a/gcc/ggc-none.c
+++ b/gcc/ggc-none.c
@@ -39,6 +39,15 @@ ggc_alloc_typed_stat (enum gt_types_enum ARG_UNUSED (gte), size_t size
return xmalloc (size);
}
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ return requested_size;
+}
+
void *
ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
{
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 624f02971e5..ee796cbb7e9 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1,6 +1,6 @@
/* "Bag-of-pages" garbage collector for the GNU compiler.
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009,
- 2010 Free Software Foundation, Inc.
+ 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -50,6 +50,11 @@ along with GCC; see the file COPYING3. If not see
#define USING_MALLOC_PAGE_GROUPS
#endif
+#if defined(HAVE_MADVISE) && HAVE_DECL_MADVISE && defined(MADV_DONTNEED) \
+ && defined(USING_MMAP)
+# define USING_MADVISE
+#endif
+
/* Strategy:
This garbage-collecting allocator allocates objects on one of a set
@@ -216,6 +221,10 @@ static const size_t extra_order_size_table[] = {
#define ROUND_UP(x, f) (CEIL (x, f) * (f))
+/* Round X to next multiple of the page size */
+
+#define PAGE_ALIGN(x) (((x) + G.pagesize - 1) & ~(G.pagesize - 1))
+
/* The Ith entry is the number of objects on a page or order I. */
static unsigned objects_per_page_table[NUM_ORDERS];
@@ -277,6 +286,9 @@ typedef struct page_entry
/* The lg of size of objects allocated from this page. */
unsigned char order;
+ /* Discarded page? */
+ bool discarded;
+
/* A bit vector indicating whether or not objects are in use. The
Nth bit is one if the Nth object on this page is allocated. This
array is dynamically sized. */
@@ -462,7 +474,7 @@ static struct globals
can override this by defining GGC_QUIRE_SIZE explicitly. */
#ifndef GGC_QUIRE_SIZE
# ifdef USING_MMAP
-# define GGC_QUIRE_SIZE 256
+# define GGC_QUIRE_SIZE 512 /* 2MB for 4K pages */
# else
# define GGC_QUIRE_SIZE 16
# endif
@@ -475,7 +487,7 @@ static int ggc_allocated_p (const void *);
static page_entry *lookup_page_table_entry (const void *);
static void set_page_table_entry (void *, page_entry *);
#ifdef USING_MMAP
-static char *alloc_anon (char *, size_t);
+static char *alloc_anon (char *, size_t, bool check);
#endif
#ifdef USING_MALLOC_PAGE_GROUPS
static size_t page_group_index (char *, char *);
@@ -654,7 +666,7 @@ debug_print_page_list (int order)
compile error unless exactly one of the HAVE_* is defined. */
static inline char *
-alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size)
+alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size, bool check)
{
#ifdef HAVE_MMAP_ANON
char *page = (char *) mmap (pref, size, PROT_READ | PROT_WRITE,
@@ -667,6 +679,8 @@ alloc_anon (char *pref ATTRIBUTE_UNUSED, size_t size)
if (page == (char *) MAP_FAILED)
{
+ if (!check)
+ return NULL;
perror ("virtual memory exhausted");
exit (FATAL_EXIT_CODE);
}
@@ -729,6 +743,7 @@ alloc_page (unsigned order)
entry_size = num_objects * OBJECT_SIZE (order);
if (entry_size < G.pagesize)
entry_size = G.pagesize;
+ entry_size = PAGE_ALIGN (entry_size);
entry = NULL;
page = NULL;
@@ -740,6 +755,10 @@ alloc_page (unsigned order)
if (p != NULL)
{
+ if (p->discarded)
+ G.bytes_mapped += p->bytes;
+ p->discarded = false;
+
/* Recycle the allocated memory from this page ... */
*pp = p->next;
page = p->page;
@@ -764,13 +783,18 @@ alloc_page (unsigned order)
extras on the freelist. (Can only do this optimization with
mmap for backing store.) */
struct page_entry *e, *f = G.free_pages;
- int i;
+ int i, entries = GGC_QUIRE_SIZE;
- page = alloc_anon (NULL, G.pagesize * GGC_QUIRE_SIZE);
+ page = alloc_anon (NULL, G.pagesize * GGC_QUIRE_SIZE, false);
+ if (page == NULL)
+ {
+ page = alloc_anon(NULL, G.pagesize, true);
+ entries = 1;
+ }
/* This loop counts down so that the chain will be in ascending
memory order. */
- for (i = GGC_QUIRE_SIZE - 1; i >= 1; i--)
+ for (i = entries - 1; i >= 1; i--)
{
e = XCNEWVAR (struct page_entry, page_entry_size);
e->order = order;
@@ -783,7 +807,7 @@ alloc_page (unsigned order)
G.free_pages = f;
}
else
- page = alloc_anon (NULL, entry_size);
+ page = alloc_anon (NULL, entry_size, true);
#endif
#ifdef USING_MALLOC_PAGE_GROUPS
else
@@ -956,7 +980,90 @@ free_page (page_entry *entry)
static void
release_pages (void)
{
-#ifdef USING_MMAP
+#ifdef USING_MADVISE
+ page_entry *p, *start_p;
+ char *start;
+ size_t len;
+ size_t mapped_len;
+ page_entry *next, *prev, *newprev;
+ size_t free_unit = (GGC_QUIRE_SIZE/2) * G.pagesize;
+
+ /* First free larger continuous areas to the OS.
+ This allows other allocators to grab these areas if needed.
+ This is only done on larger chunks to avoid fragmentation.
+ This does not always work because the free_pages list is only
+ approximately sorted. */
+
+ p = G.free_pages;
+ prev = NULL;
+ while (p)
+ {
+ start = p->page;
+ start_p = p;
+ len = 0;
+ mapped_len = 0;
+ newprev = prev;
+ while (p && p->page == start + len)
+ {
+ len += p->bytes;
+ if (!p->discarded)
+ mapped_len += p->bytes;
+ newprev = p;
+ p = p->next;
+ }
+ if (len >= free_unit)
+ {
+ while (start_p != p)
+ {
+ next = start_p->next;
+ free (start_p);
+ start_p = next;
+ }
+ munmap (start, len);
+ if (prev)
+ prev->next = p;
+ else
+ G.free_pages = p;
+ G.bytes_mapped -= mapped_len;
+ continue;
+ }
+ prev = newprev;
+ }
+
+ /* Now give back the fragmented pages to the OS, but keep the address
+ space to reuse it next time. */
+
+ for (p = G.free_pages; p; )
+ {
+ if (p->discarded)
+ {
+ p = p->next;
+ continue;
+ }
+ start = p->page;
+ len = p->bytes;
+ start_p = p;
+ p = p->next;
+ while (p && p->page == start + len)
+ {
+ len += p->bytes;
+ p = p->next;
+ }
+ /* Give the page back to the kernel, but don't free the mapping.
+ This avoids fragmentation in the virtual memory map of the
+ process. Next time we can reuse it by just touching it. */
+ madvise (start, len, MADV_DONTNEED);
+ /* Don't count those pages as mapped to not touch the garbage collector
+ unnecessarily. */
+ G.bytes_mapped -= len;
+ while (start_p != p)
+ {
+ start_p->discarded = true;
+ start_p = start_p->next;
+ }
+ }
+#endif
+#if defined(USING_MMAP) && !defined(USING_MADVISE)
page_entry *p, *next;
char *start;
size_t len;
@@ -1054,6 +1161,47 @@ static unsigned char size_lookup[NUM_SIZE_LOOKUP] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9
};
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated, as well as the size
+ order. */
+
+static void
+ggc_round_alloc_size_1 (size_t requested_size,
+ size_t *size_order,
+ size_t *alloced_size)
+{
+ size_t order, object_size;
+
+ if (requested_size < NUM_SIZE_LOOKUP)
+ {
+ order = size_lookup[requested_size];
+ object_size = OBJECT_SIZE (order);
+ }
+ else
+ {
+ order = 10;
+ while (requested_size > (object_size = OBJECT_SIZE (order)))
+ order++;
+ }
+
+ if (size_order)
+ *size_order = order;
+ if (alloced_size)
+ *alloced_size = object_size;
+}
+
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ size_t size = 0;
+
+ ggc_round_alloc_size_1 (requested_size, NULL, &size);
+ return size;
+}
+
/* Typed allocation function. Does nothing special in this collector. */
void *
@@ -1072,17 +1220,7 @@ ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
struct page_entry *entry;
void *result;
- if (size < NUM_SIZE_LOOKUP)
- {
- order = size_lookup[size];
- object_size = OBJECT_SIZE (order);
- }
- else
- {
- order = 10;
- while (size > (object_size = OBJECT_SIZE (order)))
- order++;
- }
+ ggc_round_alloc_size_1 (size, &order, &object_size);
/* If there are non-full pages for this size allocation, they are at
the head of the list. */
@@ -1522,14 +1660,14 @@ init_ggc (void)
believe, is an unaligned page allocation, which would cause us to
hork badly if we tried to use it. */
{
- char *p = alloc_anon (NULL, G.pagesize);
+ char *p = alloc_anon (NULL, G.pagesize, true);
struct page_entry *e;
if ((size_t)p & (G.pagesize - 1))
{
/* How losing. Discard this one and try another. If we still
can't get something useful, give up. */
- p = alloc_anon (NULL, G.pagesize);
+ p = alloc_anon (NULL, G.pagesize, true);
gcc_assert (!((size_t)p & (G.pagesize - 1)));
}
@@ -2102,7 +2240,7 @@ ggc_pch_total_size (struct ggc_pch_data *d)
unsigned i;
for (i = 0; i < NUM_ORDERS; i++)
- a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ a += PAGE_ALIGN (d->d.totals[i] * OBJECT_SIZE (i));
return a;
}
@@ -2115,7 +2253,7 @@ ggc_pch_this_base (struct ggc_pch_data *d, void *base)
for (i = 0; i < NUM_ORDERS; i++)
{
d->base[i] = a;
- a += ROUND_UP (d->d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ a += PAGE_ALIGN (d->d.totals[i] * OBJECT_SIZE (i));
}
}
@@ -2308,7 +2446,7 @@ ggc_pch_read (FILE *f, void *addr)
if (d.totals[i] == 0)
continue;
- bytes = ROUND_UP (d.totals[i] * OBJECT_SIZE (i), G.pagesize);
+ bytes = PAGE_ALIGN (d.totals[i] * OBJECT_SIZE (i));
num_objs = bytes / OBJECT_SIZE (i);
entry = XCNEWVAR (struct page_entry, (sizeof (struct page_entry)
- sizeof (long)
diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c
index d0c1d79f53d..5257ada28fa 100644
--- a/gcc/ggc-zone.c
+++ b/gcc/ggc-zone.c
@@ -1073,6 +1073,24 @@ free_chunk (char *ptr, size_t size, struct alloc_zone *zone)
fprintf (G.debug_file, "Deallocating object, chunk=%p\n", (void *)chunk);
}
+/* For a given size of memory requested for allocation, return the
+ actual size that is going to be allocated. */
+
+size_t
+ggc_round_alloc_size (size_t requested_size)
+{
+ size_t size;
+
+ /* Make sure that zero-sized allocations get a unique and freeable
+ pointer. */
+ if (requested_size == 0)
+ size = MAX_ALIGNMENT;
+ else
+ size = (requested_size + MAX_ALIGNMENT - 1) & -MAX_ALIGNMENT;
+
+ return size;
+}
+
/* Allocate a chunk of memory of at least ORIG_SIZE bytes, in ZONE. */
void *
@@ -1084,14 +1102,7 @@ ggc_internal_alloc_zone_stat (size_t orig_size, struct alloc_zone *zone
struct small_page_entry *entry;
struct alloc_chunk *chunk, **pp;
void *result;
- size_t size = orig_size;
-
- /* Make sure that zero-sized allocations get a unique and freeable
- pointer. */
- if (size == 0)
- size = MAX_ALIGNMENT;
- else
- size = (size + MAX_ALIGNMENT - 1) & -MAX_ALIGNMENT;
+ size_t size = ggc_round_alloc_size (orig_size);
/* Try to allocate the object from several different sources. Each
of these cases is responsible for setting RESULT and SIZE to
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 30eca66c302..704237cc045 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -145,6 +145,8 @@ extern void gt_pch_save (FILE *f);
/* The internal primitive. */
extern void *ggc_internal_alloc_stat (size_t MEM_STAT_DECL);
+extern size_t ggc_round_alloc_size (size_t requested_size);
+
#define ggc_internal_alloc(s) ggc_internal_alloc_stat (s MEM_STAT_INFO)
/* Allocate an object of the specified type and size. */
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 7df7e694aa2..53bfb9641f8 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -534,25 +534,22 @@ void
gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
{
tree lhs;
- tree tmp = NULL_TREE; /* Silence warning. */
gimple stmt, new_stmt;
gimple_stmt_iterator i;
gimple_seq stmts = gimple_seq_alloc();
struct gimplify_ctx gctx;
- gimple last = NULL;
- gimple laststore = NULL;
+ gimple last;
+ gimple laststore;
tree reaching_vuse;
stmt = gsi_stmt (*si_p);
gcc_assert (is_gimple_call (stmt));
- lhs = gimple_call_lhs (stmt);
- reaching_vuse = gimple_vuse (stmt);
-
push_gimplify_context (&gctx);
gctx.into_ssa = gimple_in_ssa_p (cfun);
+ lhs = gimple_call_lhs (stmt);
if (lhs == NULL_TREE)
{
gimplify_and_add (expr, &stmts);
@@ -571,105 +568,83 @@ gimplify_and_update_call_from_tree (gimple_stmt_iterator *si_p, tree expr)
}
}
else
- tmp = get_initialized_tmp_var (expr, &stmts, NULL);
+ {
+ tree tmp = get_initialized_tmp_var (expr, &stmts, NULL);
+ new_stmt = gimple_build_assign (lhs, tmp);
+ i = gsi_last (stmts);
+ gsi_insert_after_without_update (&i, new_stmt,
+ GSI_CONTINUE_LINKING);
+ }
pop_gimplify_context (NULL);
if (gimple_has_location (stmt))
annotate_all_with_location (stmts, gimple_location (stmt));
- /* The replacement can expose previously unreferenced variables. */
+ /* First iterate over the replacement statements backward, assigning
+ virtual operands to their defining statements. */
+ laststore = NULL;
+ for (i = gsi_last (stmts); !gsi_end_p (i); gsi_prev (&i))
+ {
+ new_stmt = gsi_stmt (i);
+ if (gimple_assign_single_p (new_stmt)
+ && !is_gimple_reg (gimple_assign_lhs (new_stmt)))
+ {
+ tree vdef;
+ if (!laststore)
+ vdef = gimple_vdef (stmt);
+ else
+ vdef = make_ssa_name (gimple_vop (cfun), new_stmt);
+ gimple_set_vdef (new_stmt, vdef);
+ if (TREE_CODE (vdef) == SSA_NAME)
+ SSA_NAME_DEF_STMT (vdef) = new_stmt;
+ laststore = new_stmt;
+ }
+ }
+
+ /* Second iterate over the statements forward, assigning virtual
+ operands to their uses. */
+ last = NULL;
+ reaching_vuse = gimple_vuse (stmt);
for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i))
{
+ /* Do not insert the last stmt in this loop but remember it
+ for replacing the original statement. */
if (last)
{
gsi_insert_before (si_p, last, GSI_NEW_STMT);
gsi_next (si_p);
}
new_stmt = gsi_stmt (i);
+ /* The replacement can expose previously unreferenced variables. */
if (gimple_in_ssa_p (cfun))
find_new_referenced_vars (new_stmt);
/* If the new statement possibly has a VUSE, update it with exact SSA
name we know will reach this one. */
if (gimple_has_mem_ops (new_stmt))
- {
- /* If we've also seen a previous store create a new VDEF for
- the latter one, and make that the new reaching VUSE. */
- if (laststore)
- {
- reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
- gimple_set_vdef (laststore, reaching_vuse);
- update_stmt (laststore);
- laststore = NULL;
- }
- gimple_set_vuse (new_stmt, reaching_vuse);
- gimple_set_modified (new_stmt, true);
- }
- if (gimple_assign_single_p (new_stmt)
- && !is_gimple_reg (gimple_assign_lhs (new_stmt)))
- {
- laststore = new_stmt;
- }
+ gimple_set_vuse (new_stmt, reaching_vuse);
+ gimple_set_modified (new_stmt, true);
+ if (gimple_vdef (new_stmt))
+ reaching_vuse = gimple_vdef (new_stmt);
last = new_stmt;
}
- if (lhs == NULL_TREE)
+ /* If the new sequence does not do a store release the virtual
+ definition of the original statement. */
+ if (reaching_vuse
+ && reaching_vuse == gimple_vuse (stmt))
{
- /* If we replace a call without LHS that has a VDEF and our new
- sequence ends with a store we must make that store have the same
- vdef in order not to break the sequencing. This can happen
- for instance when folding memcpy calls into assignments. */
- if (gimple_vdef (stmt) && laststore)
- {
- gimple_set_vdef (laststore, gimple_vdef (stmt));
- if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
- SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore;
- update_stmt (laststore);
- }
- else if (gimple_in_ssa_p (cfun))
+ tree vdef = gimple_vdef (stmt);
+ if (vdef
+ && TREE_CODE (vdef) == SSA_NAME)
{
unlink_stmt_vdef (stmt);
- release_defs (stmt);
+ release_ssa_name (vdef);
}
- new_stmt = last;
- }
- else
- {
- if (last)
- {
- gsi_insert_before (si_p, last, GSI_NEW_STMT);
- gsi_next (si_p);
- }
- if (laststore && is_gimple_reg (lhs))
- {
- gimple_set_vdef (laststore, gimple_vdef (stmt));
- update_stmt (laststore);
- if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
- SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = laststore;
- laststore = NULL;
- }
- else if (laststore)
- {
- reaching_vuse = make_ssa_name (gimple_vop (cfun), laststore);
- gimple_set_vdef (laststore, reaching_vuse);
- update_stmt (laststore);
- laststore = NULL;
- }
- new_stmt = gimple_build_assign (lhs, tmp);
- if (!is_gimple_reg (tmp))
- gimple_set_vuse (new_stmt, reaching_vuse);
- if (!is_gimple_reg (lhs))
- {
- gimple_set_vdef (new_stmt, gimple_vdef (stmt));
- if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME)
- SSA_NAME_DEF_STMT (gimple_vdef (stmt)) = new_stmt;
- }
- else if (reaching_vuse == gimple_vuse (stmt))
- unlink_stmt_vdef (stmt);
}
- gimple_set_location (new_stmt, gimple_location (stmt));
- gsi_replace (si_p, new_stmt, false);
+ /* Finally replace rhe original statement with the last. */
+ gsi_replace (si_p, last, false);
}
/* Return the string length, maximum string length or maximum value of
@@ -1082,53 +1057,82 @@ gimple_extract_devirt_binfo_from_cst (tree cst)
simplifies to a constant value. Return true if any changes were made.
It is assumed that the operands have been previously folded. */
-bool
+static bool
gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
{
gimple stmt = gsi_stmt (*gsi);
tree callee;
+ bool changed = false;
+ unsigned i;
- /* Check for builtins that CCP can handle using information not
- available in the generic fold routines. */
- callee = gimple_call_fndecl (stmt);
- if (!inplace && callee && DECL_BUILT_IN (callee))
- {
- tree result = gimple_fold_builtin (stmt);
-
- if (result)
- {
- if (!update_call_from_tree (gsi, result))
- gimplify_and_update_call_from_tree (gsi, result);
- return true;
- }
- }
+ /* Fold *& in call arguments. */
+ for (i = 0; i < gimple_call_num_args (stmt); ++i)
+ if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
+ {
+ tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
+ if (tmp)
+ {
+ gimple_call_set_arg (stmt, i, tmp);
+ changed = true;
+ }
+ }
/* Check for virtual calls that became direct calls. */
callee = gimple_call_fn (stmt);
if (callee && TREE_CODE (callee) == OBJ_TYPE_REF)
{
- tree binfo, fndecl, obj;
- HOST_WIDE_INT token;
-
if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
{
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
- return true;
+ changed = true;
}
+ else
+ {
+ tree obj = OBJ_TYPE_REF_OBJECT (callee);
+ tree binfo = gimple_extract_devirt_binfo_from_cst (obj);
+ if (binfo)
+ {
+ HOST_WIDE_INT token
+ = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
+ tree fndecl = gimple_get_virt_method_for_binfo (token, binfo);
+ if (fndecl)
+ {
+ gimple_call_set_fndecl (stmt, fndecl);
+ changed = true;
+ }
+ }
+ }
+ }
- obj = OBJ_TYPE_REF_OBJECT (callee);
- binfo = gimple_extract_devirt_binfo_from_cst (obj);
- if (!binfo)
- return false;
- token = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
- fndecl = gimple_get_virt_method_for_binfo (token, binfo);
- if (!fndecl)
- return false;
- gimple_call_set_fndecl (stmt, fndecl);
- return true;
+ /* Check whether propagating into the function address made the
+ call direct, and thus possibly non-inlineable.
+ ??? This asks for a more conservative setting of the non-inlinable
+ flag, namely true for all indirect calls. But that would require
+ that we can re-compute the flag conservatively, thus it isn't
+ ever initialized from something else than return/argument type
+ checks . */
+ callee = gimple_call_fndecl (stmt);
+ if (callee
+ && !gimple_check_call_matching_types (stmt, callee))
+ gimple_call_set_cannot_inline (stmt, true);
+
+ if (inplace)
+ return changed;
+
+ /* Check for builtins that CCP can handle using information not
+ available in the generic fold routines. */
+ if (callee && DECL_BUILT_IN (callee))
+ {
+ tree result = gimple_fold_builtin (stmt);
+ if (result)
+ {
+ if (!update_call_from_tree (gsi, result))
+ gimplify_and_update_call_from_tree (gsi, result);
+ changed = true;
+ }
}
- return false;
+ return changed;
}
/* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE argument
@@ -1187,17 +1191,6 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
break;
case GIMPLE_CALL:
- /* Fold *& in call arguments. */
- for (i = 0; i < gimple_call_num_args (stmt); ++i)
- if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
- {
- tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
- if (tmp)
- {
- gimple_call_set_arg (stmt, i, tmp);
- changed = true;
- }
- }
changed |= gimple_fold_call (gsi, inplace);
break;
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 577d28bb1f7..981d5b094d9 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -343,6 +343,8 @@ dump_binary_rhs (pretty_printer *buffer, gimple gs, int spc, int flags)
case VEC_EXTRACT_ODD_EXPR:
case VEC_INTERLEAVE_HIGH_EXPR:
case VEC_INTERLEAVE_LOW_EXPR:
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
for (p = tree_code_name [(int) code]; *p; p++)
pp_character (buffer, TOUPPER (*p));
pp_string (buffer, " <");
@@ -610,8 +612,6 @@ pp_points_to_solution (pretty_printer *buffer, struct pt_solution *pt)
pp_character (buffer, '}');
if (pt->vars_contains_global)
pp_string (buffer, " (glob)");
- if (pt->vars_contains_restrict)
- pp_string (buffer, " (restr)");
}
}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 19f02dc9cd1..b2874bb071b 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -5313,9 +5313,24 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
|| gimple_code (stmt) == GIMPLE_COND))
{
for (i = 0; i < gimple_num_ops (stmt); ++i)
- if (gimple_op (stmt, i)
- && TREE_CODE (gimple_op (stmt, i)) == ADDR_EXPR)
- ret |= visit_addr (stmt, TREE_OPERAND (gimple_op (stmt, i), 0), data);
+ {
+ tree op = gimple_op (stmt, i);
+ if (op == NULL_TREE)
+ ;
+ else if (TREE_CODE (op) == ADDR_EXPR)
+ ret |= visit_addr (stmt, TREE_OPERAND (op, 0), data);
+ /* COND_EXPR and VCOND_EXPR rhs1 argument is a comparison
+ tree with two operands. */
+ else if (i == 1 && COMPARISON_CLASS_P (op))
+ {
+ if (TREE_CODE (TREE_OPERAND (op, 0)) == ADDR_EXPR)
+ ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 0),
+ 0), data);
+ if (TREE_CODE (TREE_OPERAND (op, 1)) == ADDR_EXPR)
+ ret |= visit_addr (stmt, TREE_OPERAND (TREE_OPERAND (op, 1),
+ 0), data);
+ }
+ }
}
else if (is_gimple_call (stmt))
{
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 75e19a72b87..666c44c8591 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -909,7 +909,6 @@ unsigned get_gimple_rhs_num_ops (enum tree_code);
#define gimple_alloc(c, n) gimple_alloc_stat (c, n MEM_STAT_INFO)
gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
const char *gimple_decl_printable_name (tree, int);
-bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace);
tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree);
tree gimple_extract_devirt_binfo_from_cst (tree);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 2c9ba1d78aa..8c2c5ac2c9c 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -7256,8 +7256,10 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case TRUTH_XOR_EXPR:
{
tree orig_type = TREE_TYPE (*expr_p);
+ tree new_type, xop0, xop1;
*expr_p = gimple_boolify (*expr_p);
- if (!useless_type_conversion_p (orig_type, TREE_TYPE (*expr_p)))
+ new_type = TREE_TYPE (*expr_p);
+ if (!useless_type_conversion_p (orig_type, new_type))
{
*expr_p = fold_convert_loc (input_location, orig_type, *expr_p);
ret = GS_OK;
@@ -7281,7 +7283,18 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
default:
break;
}
-
+ /* Now make sure that operands have compatible type to
+ expression's new_type. */
+ xop0 = TREE_OPERAND (*expr_p, 0);
+ xop1 = TREE_OPERAND (*expr_p, 1);
+ if (!useless_type_conversion_p (new_type, TREE_TYPE (xop0)))
+ TREE_OPERAND (*expr_p, 0) = fold_convert_loc (input_location,
+ new_type,
+ xop0);
+ if (!useless_type_conversion_p (new_type, TREE_TYPE (xop1)))
+ TREE_OPERAND (*expr_p, 1) = fold_convert_loc (input_location,
+ new_type,
+ xop1);
/* Continue classified as tcc_binary. */
goto expr_2;
}
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 3802fa8e463..2eaf210c94f 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Make-lang.in (gospec.o): Pass SHLIB instead of SHLIB_LINK.
+
2011-08-24 Roberto Lublinerman <rluble@gmail.com>
* lang.opt: Add fgo-optimize-.
diff --git a/gcc/go/Make-lang.in b/gcc/go/Make-lang.in
index d7ae7aee6fb..62a4d6f0dee 100644
--- a/gcc/go/Make-lang.in
+++ b/gcc/go/Make-lang.in
@@ -32,7 +32,7 @@ go: go1$(exeext)
gospec.o: $(srcdir)/go/gospec.c $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
$(CONFIG_H) opts.h
- (SHLIB_LINK='$(SHLIB_LINK)'; \
+ (SHLIB='$(SHLIB)'; \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
$(INCLUDES) $(srcdir)/go/gospec.c)
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index bf829b520ee..e308b9a4c31 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -234,8 +234,7 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
else if (rhs_type->interface_type() != NULL)
return Expression::convert_interface_to_type(context, lhs_type, rhs_type,
rhs_tree, location);
- else if (lhs_type->is_open_array_type()
- && rhs_type->is_nil_type())
+ else if (lhs_type->is_slice_type() && rhs_type->is_nil_type())
{
// Assigning nil to an open array.
go_assert(TREE_CODE(lhs_type_tree) == RECORD_TYPE);
@@ -3315,7 +3314,7 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*,
mpfr_clear(imag);
}
- if (type->is_open_array_type() && type->named_type() == NULL)
+ if (type->is_slice_type() && type->named_type() == NULL)
{
Type* element_type = type->array_type()->element_type()->forwarded();
bool is_byte = element_type == Type::lookup_integer_type("uint8");
@@ -3663,7 +3662,7 @@ Type_conversion_expression::do_get_tree(Translate_context* context)
len);
}
}
- else if (type->is_open_array_type() && expr_type->is_string_type())
+ else if (type->is_slice_type() && expr_type->is_string_type())
{
Type* e = type->array_type()->element_type()->forwarded();
go_assert(e->integer_type() != NULL);
@@ -3831,9 +3830,9 @@ Unsafe_type_conversion_expression::do_get_tree(Translate_context* context)
source_location loc = this->location();
bool use_view_convert = false;
- if (t->is_open_array_type())
+ if (t->is_slice_type())
{
- go_assert(et->is_open_array_type());
+ go_assert(et->is_slice_type());
use_view_convert = true;
}
else if (t->map_type() != NULL)
@@ -3994,6 +3993,10 @@ class Unary_expression : public Expression
}
bool
+ do_must_eval_subexpressions_in_order(int*) const
+ { return this->op_ == OPERATOR_MULT; }
+
+ bool
do_is_addressable() const
{ return this->op_ == OPERATOR_MULT; }
@@ -7045,6 +7048,7 @@ class Builtin_call_expression : public Call_expression
BUILTIN_CLOSE,
BUILTIN_COMPLEX,
BUILTIN_COPY,
+ BUILTIN_DELETE,
BUILTIN_IMAG,
BUILTIN_LEN,
BUILTIN_MAKE,
@@ -7110,6 +7114,8 @@ Builtin_call_expression::Builtin_call_expression(Gogo* gogo,
this->code_ = BUILTIN_COMPLEX;
else if (name == "copy")
this->code_ = BUILTIN_COPY;
+ else if (name == "delete")
+ this->code_ = BUILTIN_DELETE;
else if (name == "imag")
this->code_ = BUILTIN_IMAG;
else if (name == "len")
@@ -7203,34 +7209,15 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
if (this->classification() == EXPRESSION_ERROR)
return this;
+ source_location loc = this->location();
+
if (this->is_varargs() && this->code_ != BUILTIN_APPEND)
{
this->report_error(_("invalid use of %<...%> with builtin function"));
- return Expression::make_error(this->location());
+ return Expression::make_error(loc);
}
- if (this->code_ == BUILTIN_NEW)
- {
- const Expression_list* args = this->args();
- if (args == NULL || args->size() < 1)
- this->report_error(_("not enough arguments"));
- else if (args->size() > 1)
- this->report_error(_("too many arguments"));
- else
- {
- Expression* arg = args->front();
- if (!arg->is_type_expression())
- {
- error_at(arg->location(), "expected type");
- this->set_is_error();
- }
- else
- return Expression::make_allocation(arg->type(), this->location());
- }
- }
- else if (this->code_ == BUILTIN_MAKE)
- return this->lower_make();
- else if (this->is_constant())
+ if (this->is_constant())
{
// We can only lower len and cap if there are no function calls
// in the arguments. Otherwise we have to make the call.
@@ -7251,8 +7238,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
Type* type;
if (this->integer_constant_value(true, ival, &type))
{
- Expression* ret = Expression::make_integer(&ival, type,
- this->location());
+ Expression* ret = Expression::make_integer(&ival, type, loc);
mpz_clear(ival);
return ret;
}
@@ -7262,8 +7248,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
mpfr_init(rval);
if (this->float_constant_value(rval, &type))
{
- Expression* ret = Expression::make_float(&rval, type,
- this->location());
+ Expression* ret = Expression::make_float(&rval, type, loc);
mpfr_clear(rval);
return ret;
}
@@ -7272,8 +7257,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
mpfr_init(imag);
if (this->complex_constant_value(rval, imag, &type))
{
- Expression* ret = Expression::make_complex(&rval, &imag, type,
- this->location());
+ Expression* ret = Expression::make_complex(&rval, &imag, type, loc);
mpfr_clear(rval);
mpfr_clear(imag);
return ret;
@@ -7281,34 +7265,100 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
mpfr_clear(rval);
mpfr_clear(imag);
}
- else if (this->code_ == BUILTIN_RECOVER)
+
+ switch (this->code_)
{
+ default:
+ break;
+
+ case BUILTIN_NEW:
+ {
+ const Expression_list* args = this->args();
+ if (args == NULL || args->size() < 1)
+ this->report_error(_("not enough arguments"));
+ else if (args->size() > 1)
+ this->report_error(_("too many arguments"));
+ else
+ {
+ Expression* arg = args->front();
+ if (!arg->is_type_expression())
+ {
+ error_at(arg->location(), "expected type");
+ this->set_is_error();
+ }
+ else
+ return Expression::make_allocation(arg->type(), loc);
+ }
+ }
+ break;
+
+ case BUILTIN_MAKE:
+ return this->lower_make();
+
+ case BUILTIN_RECOVER:
if (function != NULL)
function->func_value()->set_calls_recover();
else
{
// Calling recover outside of a function always returns the
// nil empty interface.
- Type* eface = Type::make_interface_type(NULL, this->location());
- return Expression::make_cast(eface,
- Expression::make_nil(this->location()),
- this->location());
+ Type* eface = Type::make_interface_type(NULL, loc);
+ return Expression::make_cast(eface, Expression::make_nil(loc), loc);
}
- }
- else if (this->code_ == BUILTIN_APPEND)
- {
- // Lower the varargs.
- const Expression_list* args = this->args();
- if (args == NULL || args->empty())
- return this;
- Type* slice_type = args->front()->type();
- if (!slice_type->is_open_array_type())
- {
- error_at(args->front()->location(), "argument 1 must be a slice");
- this->set_is_error();
+ break;
+
+ case BUILTIN_APPEND:
+ {
+ // Lower the varargs.
+ const Expression_list* args = this->args();
+ if (args == NULL || args->empty())
return this;
- }
- this->lower_varargs(gogo, function, inserter, slice_type, 2);
+ Type* slice_type = args->front()->type();
+ if (!slice_type->is_slice_type())
+ {
+ error_at(args->front()->location(), "argument 1 must be a slice");
+ this->set_is_error();
+ return this;
+ }
+ this->lower_varargs(gogo, function, inserter, slice_type, 2);
+ }
+ break;
+
+ case BUILTIN_DELETE:
+ {
+ // Lower to a runtime function call.
+ const Expression_list* args = this->args();
+ if (args == NULL || args->size() < 2)
+ this->report_error(_("not enough arguments"));
+ else if (args->size() > 2)
+ this->report_error(_("too many arguments"));
+ else if (args->front()->type()->map_type() == NULL)
+ this->report_error(_("argument 1 must be a map"));
+ else
+ {
+ // Since this function returns no value it must appear in
+ // a statement by itself, so we don't have to worry about
+ // order of evaluation of values around it. Evaluate the
+ // map first to get order of evaluation right.
+ Map_type* mt = args->front()->type()->map_type();
+ Temporary_statement* map_temp =
+ Statement::make_temporary(mt, args->front(), loc);
+ inserter->insert(map_temp);
+
+ Temporary_statement* key_temp =
+ Statement::make_temporary(mt->key_type(), args->back(), loc);
+ inserter->insert(key_temp);
+
+ Expression* e1 = Expression::make_temporary_reference(map_temp,
+ loc);
+ Expression* e2 = Expression::make_temporary_reference(key_temp,
+ loc);
+ e2 = Expression::make_unary(OPERATOR_AND, e2, loc);
+ return Runtime::make_call(Runtime::MAPDELETE, this->location(),
+ 2, e1, e2);
+ }
+ }
+ break;
}
return this;
@@ -7342,7 +7392,7 @@ Builtin_call_expression::lower_make()
bool is_slice = false;
bool is_map = false;
bool is_chan = false;
- if (type->is_open_array_type())
+ if (type->is_slice_type())
is_slice = true;
else if (type->map_type() != NULL)
is_map = true;
@@ -7554,7 +7604,7 @@ Builtin_call_expression::do_is_constant() const
if (arg_type->points_to() != NULL
&& arg_type->points_to()->array_type() != NULL
- && !arg_type->points_to()->is_open_array_type())
+ && !arg_type->points_to()->is_slice_type())
arg_type = arg_type->points_to();
if (arg_type->array_type() != NULL
@@ -7633,7 +7683,7 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant,
if (arg_type->points_to() != NULL
&& arg_type->points_to()->array_type() != NULL
- && !arg_type->points_to()->is_open_array_type())
+ && !arg_type->points_to()->is_slice_type())
arg_type = arg_type->points_to();
if (arg_type->array_type() != NULL
@@ -7842,6 +7892,7 @@ Builtin_call_expression::do_discarding_value()
case BUILTIN_CLOSE:
case BUILTIN_COPY:
+ case BUILTIN_DELETE:
case BUILTIN_PANIC:
case BUILTIN_PRINT:
case BUILTIN_PRINTLN:
@@ -7879,6 +7930,7 @@ Builtin_call_expression::do_type()
return Type::lookup_integer_type("int");
case BUILTIN_CLOSE:
+ case BUILTIN_DELETE:
case BUILTIN_PANIC:
case BUILTIN_PRINT:
case BUILTIN_PRINTLN:
@@ -8080,7 +8132,7 @@ Builtin_call_expression::do_check_types(Gogo*)
Type* arg_type = this->one_arg()->type();
if (arg_type->points_to() != NULL
&& arg_type->points_to()->array_type() != NULL
- && !arg_type->points_to()->is_open_array_type())
+ && !arg_type->points_to()->is_slice_type())
arg_type = arg_type->points_to();
if (this->code_ == BUILTIN_CAP)
{
@@ -8135,7 +8187,7 @@ Builtin_call_expression::do_check_types(Gogo*)
|| type->channel_type() != NULL
|| type->map_type() != NULL
|| type->function_type() != NULL
- || type->is_open_array_type())
+ || type->is_slice_type())
;
else
this->report_error(_("unsupported argument type to "
@@ -8150,6 +8202,8 @@ Builtin_call_expression::do_check_types(Gogo*)
{
if (this->one_arg()->type()->channel_type() == NULL)
this->report_error(_("argument must be channel"));
+ else if (!this->one_arg()->type()->channel_type()->may_send())
+ this->report_error(_("cannot close receive-only channel"));
}
break;
@@ -8192,7 +8246,7 @@ Builtin_call_expression::do_check_types(Gogo*)
break;
Type* e1;
- if (arg1_type->is_open_array_type())
+ if (arg1_type->is_slice_type())
e1 = arg1_type->array_type()->element_type();
else
{
@@ -8201,7 +8255,7 @@ Builtin_call_expression::do_check_types(Gogo*)
}
Type* e2;
- if (arg2_type->is_open_array_type())
+ if (arg2_type->is_slice_type())
e2 = arg2_type->array_type()->element_type();
else if (arg2_type->is_string_type())
e2 = Type::lookup_integer_type("uint8");
@@ -8229,6 +8283,17 @@ Builtin_call_expression::do_check_types(Gogo*)
this->report_error(_("too many arguments"));
break;
}
+
+ // The language permits appending a string to a []byte, as a
+ // special case.
+ if (args->back()->type()->is_string_type())
+ {
+ const Array_type* at = args->front()->type()->array_type();
+ const Type* e = at->element_type()->forwarded();
+ if (e == Type::lookup_integer_type("uint8"))
+ break;
+ }
+
std::string reason;
if (!Type::are_assignable(args->front()->type(), args->back()->type(),
&reason))
@@ -8321,7 +8386,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
{
arg_type = arg_type->points_to();
go_assert(arg_type->array_type() != NULL
- && !arg_type->is_open_array_type());
+ && !arg_type->is_slice_type());
go_assert(POINTER_TYPE_P(TREE_TYPE(arg_tree)));
arg_tree = build_fold_indirect_ref(arg_tree);
}
@@ -8515,7 +8580,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
fnname = "__go_print_interface";
}
}
- else if (type->is_open_array_type())
+ else if (type->is_slice_type())
{
static tree print_slice_fndecl;
pfndecl = &print_slice_fndecl;
@@ -8694,7 +8759,7 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
Type* arg2_type = arg2->type();
tree arg2_val;
tree arg2_len;
- if (arg2_type->is_open_array_type())
+ if (arg2_type->is_slice_type())
{
at = arg2_type->array_type();
arg2_tree = save_expr(arg2_tree);
@@ -8767,30 +8832,50 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
return error_mark_node;
Array_type* at = arg1->type()->array_type();
- Type* element_type = at->element_type();
+ Type* element_type = at->element_type()->forwarded();
- arg2_tree = Expression::convert_for_assignment(context, at,
- arg2->type(),
- arg2_tree,
- location);
- if (arg2_tree == error_mark_node)
- return error_mark_node;
+ tree arg2_val;
+ tree arg2_len;
+ tree element_size;
+ if (arg2->type()->is_string_type()
+ && element_type == Type::lookup_integer_type("uint8"))
+ {
+ arg2_tree = save_expr(arg2_tree);
+ arg2_val = String_type::bytes_tree(gogo, arg2_tree);
+ arg2_len = String_type::length_tree(gogo, arg2_tree);
+ element_size = size_int(1);
+ }
+ else
+ {
+ arg2_tree = Expression::convert_for_assignment(context, at,
+ arg2->type(),
+ arg2_tree,
+ location);
+ if (arg2_tree == error_mark_node)
+ return error_mark_node;
+
+ arg2_tree = save_expr(arg2_tree);
+
+ arg2_val = at->value_pointer_tree(gogo, arg2_tree);
+ arg2_len = at->length_tree(gogo, arg2_tree);
+
+ Btype* element_btype = element_type->get_backend(gogo);
+ tree element_type_tree = type_to_tree(element_btype);
+ if (element_type_tree == error_mark_node)
+ return error_mark_node;
+ element_size = TYPE_SIZE_UNIT(element_type_tree);
+ }
- arg2_tree = save_expr(arg2_tree);
- tree arg2_val = at->value_pointer_tree(gogo, arg2_tree);
- tree arg2_len = at->length_tree(gogo, arg2_tree);
- if (arg2_val == error_mark_node || arg2_len == error_mark_node)
- return error_mark_node;
arg2_val = fold_convert_loc(location, ptr_type_node, arg2_val);
arg2_len = fold_convert_loc(location, size_type_node, arg2_len);
-
- tree element_type_tree = type_to_tree(element_type->get_backend(gogo));
- if (element_type_tree == error_mark_node)
- return error_mark_node;
- tree element_size = TYPE_SIZE_UNIT(element_type_tree);
element_size = fold_convert_loc(location, size_type_node,
element_size);
+ if (arg2_val == error_mark_node
+ || arg2_len == error_mark_node
+ || element_size == error_mark_node)
+ return error_mark_node;
+
// We rebuild the decl each time since the slice types may
// change.
tree append_fndecl = NULL_TREE;
@@ -9078,7 +9163,7 @@ Call_expression::lower_varargs(Gogo* gogo, Named_object* function,
source_location loc = this->location();
go_assert(param_count > 0);
- go_assert(varargs_type->is_open_array_type());
+ go_assert(varargs_type->is_slice_type());
size_t arg_count = this->args_ == NULL ? 0 : this->args_->size();
if (arg_count < param_count - 1)
@@ -9903,7 +9988,7 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
return Expression::make_array_index(left, start, end, location);
else if (type->points_to() != NULL
&& type->points_to()->array_type() != NULL
- && !type->points_to()->is_open_array_type())
+ && !type->points_to()->is_slice_type())
{
Expression* deref = Expression::make_unary(OPERATOR_MULT, left,
location);
@@ -10007,6 +10092,13 @@ class Array_index_expression : public Expression
}
bool
+ do_must_eval_subexpressions_in_order(int* skip) const
+ {
+ *skip = 1;
+ return true;
+ }
+
+ bool
do_is_addressable() const;
void
@@ -10060,7 +10152,7 @@ Array_index_expression::do_type()
this->type_ = Type::make_error_type();
else if (this->end_ == NULL)
this->type_ = type->element_type();
- else if (type->is_open_array_type())
+ else if (type->is_slice_type())
{
// A slice of a slice has the same type as the original
// slice.
@@ -10150,7 +10242,7 @@ Array_index_expression::do_check_types(Gogo*)
// A slice of an array requires an addressable array. A slice of a
// slice is always possible.
- if (this->end_ != NULL && !array_type->is_open_array_type())
+ if (this->end_ != NULL && !array_type->is_slice_type())
{
if (!this->array_->is_addressable())
this->report_error(_("array is not addressable"));
@@ -10169,7 +10261,7 @@ Array_index_expression::do_is_addressable() const
return false;
// An index into a slice is addressable.
- if (this->array_->type()->is_open_array_type())
+ if (this->array_->type()->is_slice_type())
return true;
// An index into an array is addressable if the array is
@@ -10431,6 +10523,13 @@ class String_index_expression : public Expression
this->location());
}
+ bool
+ do_must_eval_subexpressions_in_order(int* skip) const
+ {
+ *skip = 1;
+ return true;
+ }
+
tree
do_get_tree(Translate_context*);
@@ -12234,7 +12333,7 @@ Expression*
Expression::make_slice_composite_literal(Type* type, Expression_list* vals,
source_location location)
{
- go_assert(type->is_open_array_type());
+ go_assert(type->is_slice_type());
return new Open_array_construction_expression(type, vals, location);
}
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 8cdf94d2e78..a1f03c429fc 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -582,6 +582,18 @@ class Expression
must_eval_in_order() const
{ return this->do_must_eval_in_order(); }
+ // Return whether subexpressions of this expression must be
+ // evaluated in order. This is true of index expressions and
+ // pointer indirections. This sets *SKIP to the number of
+ // subexpressions to skip during traversing, as index expressions
+ // only requiring moving the index, not the array.
+ bool
+ must_eval_subexpressions_in_order(int* skip) const
+ {
+ *skip = 0;
+ return this->do_must_eval_subexpressions_in_order(skip);
+ }
+
// Return the tree for this expression.
tree
get_tree(Translate_context*);
@@ -717,6 +729,13 @@ class Expression
do_must_eval_in_order() const
{ return false; }
+ // Child class implements whether this expressions requires that
+ // subexpressions be evaluated in order. The child implementation
+ // may set *SKIP if it should be non-zero.
+ virtual bool
+ do_must_eval_subexpressions_in_order(int* /* skip */) const
+ { return false; }
+
// Child class implements conversion to tree.
virtual tree
do_get_tree(Translate_context*) = 0;
@@ -1526,6 +1545,13 @@ class Index_expression : public Parser_expression
this->location());
}
+ bool
+ do_must_eval_subexpressions_in_order(int* skip) const
+ {
+ *skip = 1;
+ return true;
+ }
+
void
do_dump_expression(Ast_dump_context*) const;
@@ -1623,6 +1649,13 @@ class Map_index_expression : public Expression
this->location());
}
+ bool
+ do_must_eval_subexpressions_in_order(int* skip) const
+ {
+ *skip = 1;
+ return true;
+ }
+
// A map index expression is an lvalue but it is not addressable.
tree
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index f1f7680d004..e20063b817f 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -85,6 +85,10 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
Named_object* byte_type = this->declare_type("byte", loc);
byte_type->set_type_value(uint8_type);
+ // "rune" is an alias for "int".
+ Named_object* rune_type = this->declare_type("rune", loc);
+ rune_type->set_type_value(int_type);
+
this->add_named_type(Type::make_integer_type("uintptr", true,
pointer_size,
RUNTIME_TYPE_KIND_UINTPTR));
@@ -201,6 +205,11 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
imag_type->set_is_varargs();
imag_type->set_is_builtin();
this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
+
+ Function_type* delete_type = Type::make_function_type(NULL, NULL, NULL, loc);
+ delete_type->set_is_varargs();
+ delete_type->set_is_builtin();
+ this->globals_->add_function_declaration("delete", NULL, delete_type, loc);
}
// Munge name for use in an error message.
@@ -3662,7 +3671,7 @@ Variable::type_from_range(Expression* expr, bool get_index_type,
if (t->array_type() != NULL
|| (t->points_to() != NULL
&& t->points_to()->array_type() != NULL
- && !t->points_to()->is_open_array_type()))
+ && !t->points_to()->is_slice_type()))
{
if (get_index_type)
return Type::lookup_integer_type("int");
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 8c42fa2b24f..6f7b8f21b24 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -3839,6 +3839,23 @@ Parse::return_stat()
if (this->expression_may_start_here())
vals = this->expression_list(NULL, false);
this->gogo_->add_statement(Statement::make_return_statement(vals, location));
+
+ if (vals == NULL
+ && this->gogo_->current_function()->func_value()->results_are_named())
+ {
+ Named_object* function = this->gogo_->current_function();
+ Function::Results* results = function->func_value()->result_variables();
+ for (Function::Results::const_iterator p = results->begin();
+ p != results->end();
+ ++p)
+ {
+ Named_object* no = this->gogo_->lookup((*p)->name(), NULL);
+ go_assert(no != NULL);
+ if (!no->is_result_variable())
+ error_at(location, "%qs is shadowed during return",
+ (*p)->message_name().c_str());
+ }
+ }
}
// IfStmt = "if" [ SimpleStmt ";" ] Expression Block
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index a72942d385d..d742e5b0c79 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -94,6 +94,9 @@ DEF_GO_RUNTIME(MAPACCESS2, "runtime.mapaccess2",
DEF_GO_RUNTIME(MAPASSIGN2, "runtime.mapassign2",
P4(MAP, POINTER, POINTER, BOOL), R0())
+// Delete a key from a map.
+DEF_GO_RUNTIME(MAPDELETE, "runtime.mapdelete", P2(MAP, POINTER), R0())
+
// Begin a range over a map.
DEF_GO_RUNTIME(MAPITERINIT, "runtime.mapiterinit", P2(MAP, MAPITER), R0())
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 8c1f168d950..abc629e12c3 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -652,6 +652,47 @@ Statement::make_assignment(Expression* lhs, Expression* rhs,
return new Assignment_statement(lhs, rhs, location);
}
+// The Move_subexpressions class is used to move all top-level
+// subexpressions of an expression. This is used for things like
+// index expressions in which we must evaluate the index value before
+// it can be changed by a multiple assignment.
+
+class Move_subexpressions : public Traverse
+{
+ public:
+ Move_subexpressions(int skip, Block* block)
+ : Traverse(traverse_expressions),
+ skip_(skip), block_(block)
+ { }
+
+ protected:
+ int
+ expression(Expression**);
+
+ private:
+ // The number of subexpressions to skip moving. This is used to
+ // avoid moving the array itself, as we only need to move the index.
+ int skip_;
+ // The block where new temporary variables should be added.
+ Block* block_;
+};
+
+int
+Move_subexpressions::expression(Expression** pexpr)
+{
+ if (this->skip_ > 0)
+ --this->skip_;
+ else if ((*pexpr)->temporary_reference_expression() == NULL)
+ {
+ source_location loc = (*pexpr)->location();
+ Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
+ this->block_->add_statement(temp);
+ *pexpr = Expression::make_temporary_reference(temp, loc);
+ }
+ // We only need to move top-level subexpressions.
+ return TRAVERSE_SKIP_COMPONENTS;
+}
+
// The Move_ordered_evals class is used to find any subexpressions of
// an expression that have an evaluation order dependency. It creates
// temporary variables to hold them.
@@ -679,6 +720,15 @@ Move_ordered_evals::expression(Expression** pexpr)
// We have to look at subexpressions first.
if ((*pexpr)->traverse_subexpressions(this) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
+
+ int i;
+ if ((*pexpr)->must_eval_subexpressions_in_order(&i))
+ {
+ Move_subexpressions ms(i, this->block_);
+ if ((*pexpr)->traverse_subexpressions(&ms) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ }
+
if ((*pexpr)->must_eval_in_order())
{
source_location loc = (*pexpr)->location();
@@ -901,10 +951,10 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
// First move out any subexpressions on the left hand side. The
// right hand side will be evaluated in the required order anyhow.
Move_ordered_evals moe(b);
- for (Expression_list::const_iterator plhs = this->lhs_->begin();
+ for (Expression_list::iterator plhs = this->lhs_->begin();
plhs != this->lhs_->end();
++plhs)
- (*plhs)->traverse_subexpressions(&moe);
+ Expression::traverse(&*plhs, &moe);
std::vector<Temporary_statement*> temps;
temps.reserve(this->lhs_->size());
@@ -4319,7 +4369,7 @@ Send_statement::do_get_backend(Translate_context* context)
case Type::TYPE_ARRAY:
is_small = false;
- can_take_address = !element_type->is_open_array_type();
+ can_take_address = !element_type->is_slice_type();
break;
default:
@@ -5181,7 +5231,7 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
Type* range_type = this->range_->type();
if (range_type->points_to() != NULL
&& range_type->points_to()->array_type() != NULL
- && !range_type->points_to()->is_open_array_type())
+ && !range_type->points_to()->is_slice_type())
range_type = range_type->points_to();
Type* index_type;
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 68c35f40764..c596de95b44 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -240,7 +240,7 @@ Type::points_to() const
// Return whether this is an open array type.
bool
-Type::is_open_array_type() const
+Type::is_slice_type() const
{
return this->array_type() != NULL && this->array_type()->length() == NULL;
}
@@ -457,7 +457,7 @@ Type::are_compatible_for_binop(const Type* lhs, const Type* rhs)
if (lhs->is_nil_type()
&& (rhs->points_to() != NULL
|| rhs->interface_type() != NULL
- || rhs->is_open_array_type()
+ || rhs->is_slice_type()
|| rhs->map_type() != NULL
|| rhs->channel_type() != NULL
|| rhs->function_type() != NULL))
@@ -465,7 +465,7 @@ Type::are_compatible_for_binop(const Type* lhs, const Type* rhs)
if (rhs->is_nil_type()
&& (lhs->points_to() != NULL
|| lhs->interface_type() != NULL
- || lhs->is_open_array_type()
+ || lhs->is_slice_type()
|| lhs->map_type() != NULL
|| lhs->channel_type() != NULL
|| lhs->function_type() != NULL))
@@ -556,7 +556,7 @@ Type::are_assignable_check_hidden(const Type* lhs, const Type* rhs,
if (rhs->is_nil_type()
&& (lhs->points_to() != NULL
|| lhs->function_type() != NULL
- || lhs->is_open_array_type()
+ || lhs->is_slice_type()
|| lhs->map_type() != NULL
|| lhs->channel_type() != NULL
|| lhs->interface_type() != NULL))
@@ -662,7 +662,7 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
{
if (rhs->integer_type() != NULL)
return true;
- if (rhs->is_open_array_type() && rhs->named_type() == NULL)
+ if (rhs->is_slice_type() && rhs->named_type() == NULL)
{
const Type* e = rhs->array_type()->element_type()->forwarded();
if (e->integer_type() != NULL
@@ -674,7 +674,7 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
// A string may be converted to []byte or []int.
if (rhs->is_string_type()
- && lhs->is_open_array_type()
+ && lhs->is_slice_type()
&& lhs->named_type() == NULL)
{
const Type* e = lhs->array_type()->element_type()->forwarded();
@@ -6480,7 +6480,7 @@ Find_type_use::type(Type* type)
// essentially a pointer: a pointer, a slice, a function, a map, or
// a channel.
if (type->points_to() != NULL
- || type->is_open_array_type()
+ || type->is_slice_type()
|| type->function_type() != NULL
|| type->map_type() != NULL
|| type->channel_type() != NULL)
@@ -6699,7 +6699,7 @@ Named_type::convert(Gogo* gogo)
case TYPE_ARRAY:
// Slice types were completed in create_placeholder.
- if (!base->is_open_array_type())
+ if (!base->is_slice_type())
{
Btype* bet = base->array_type()->get_backend_element(gogo);
Bexpression* blen = base->array_type()->get_backend_length(gogo);
@@ -6789,7 +6789,7 @@ Named_type::create_placeholder(Gogo* gogo)
break;
case TYPE_ARRAY:
- if (base->is_open_array_type())
+ if (base->is_slice_type())
bt = gogo->backend()->placeholder_struct_type(this->name(),
this->location_);
else
@@ -6822,7 +6822,7 @@ Named_type::create_placeholder(Gogo* gogo)
this->named_btype_ = bt;
- if (base->is_open_array_type())
+ if (base->is_slice_type())
{
// We do not record slices as dependencies of other types,
// because we can fill them in completely here with the final
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index cb3fcaa7154..2ec828f6b2a 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -741,9 +741,9 @@ class Type
array_type() const
{ return this->convert<const Array_type, TYPE_ARRAY>(); }
- // Return whether if this is an open array type.
+ // Return whether if this is a slice type.
bool
- is_open_array_type() const;
+ is_slice_type() const;
// If this is a map type, return it. Otherwise, return NULL.
Map_type*
diff --git a/gcc/godump.c b/gcc/godump.c
index f9f767c8113..a42e641d181 100644
--- a/gcc/godump.c
+++ b/gcc/godump.c
@@ -62,7 +62,47 @@ static GTY(()) VEC(tree,gc) *queue;
static htab_t macro_hash;
-/* For the hash tables. */
+/* The type of a value in macro_hash. */
+
+struct macro_hash_value
+{
+ /* The name stored in the hash table. */
+ char *name;
+ /* The value of the macro. */
+ char *value;
+};
+
+/* Calculate the hash value for an entry in the macro hash table. */
+
+static hashval_t
+macro_hash_hashval (const void *val)
+{
+ const struct macro_hash_value *mhval = (const struct macro_hash_value *) val;
+ return htab_hash_string (mhval->name);
+}
+
+/* Compare values in the macro hash table for equality. */
+
+static int
+macro_hash_eq (const void *v1, const void *v2)
+{
+ const struct macro_hash_value *mhv1 = (const struct macro_hash_value *) v1;
+ const struct macro_hash_value *mhv2 = (const struct macro_hash_value *) v2;
+ return strcmp (mhv1->name, mhv2->name) == 0;
+}
+
+/* Free values deleted from the macro hash table. */
+
+static void
+macro_hash_del (void *v)
+{
+ struct macro_hash_value *mhv = (struct macro_hash_value *) v;
+ XDELETEVEC (mhv->name);
+ XDELETEVEC (mhv->value);
+ XDELETE (mhv);
+}
+
+/* For the string hash tables. */
static int
string_hash_eq (const void *y1, const void *y2)
@@ -77,10 +117,12 @@ go_define (unsigned int lineno, const char *buffer)
{
const char *p;
const char *name_end;
+ size_t out_len;
char *out_buffer;
char *q;
bool saw_operand;
bool need_operand;
+ struct macro_hash_value *mhval;
char *copy;
hashval_t hashval;
void **slot;
@@ -105,17 +147,17 @@ go_define (unsigned int lineno, const char *buffer)
memcpy (copy, buffer, name_end - buffer);
copy[name_end - buffer] = '\0';
+ mhval = XNEW (struct macro_hash_value);
+ mhval->name = copy;
+ mhval->value = NULL;
+
hashval = htab_hash_string (copy);
- slot = htab_find_slot_with_hash (macro_hash, copy, hashval, NO_INSERT);
- if (slot != NULL)
- {
- XDELETEVEC (copy);
- return;
- }
+ slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, NO_INSERT);
/* For simplicity, we force all names to be hidden by adding an
initial underscore, and let the user undo this as needed. */
- out_buffer = XNEWVEC (char, strlen (p) * 2 + 1);
+ out_len = strlen (p) * 2 + 1;
+ out_buffer = XNEWVEC (char, out_len);
q = out_buffer;
saw_operand = false;
need_operand = false;
@@ -141,6 +183,7 @@ go_define (unsigned int lineno, const char *buffer)
don't worry about them. */
const char *start;
char *n;
+ struct macro_hash_value idval;
if (saw_operand)
goto unknown;
@@ -151,8 +194,9 @@ go_define (unsigned int lineno, const char *buffer)
n = XALLOCAVEC (char, p - start + 1);
memcpy (n, start, p - start);
n[p - start] = '\0';
- slot = htab_find_slot (macro_hash, n, NO_INSERT);
- if (slot == NULL || *slot == NULL)
+ idval.name = n;
+ idval.value = NULL;
+ if (htab_find (macro_hash, &idval) == NULL)
{
/* This is a reference to a name which was not defined
as a macro. */
@@ -382,18 +426,30 @@ go_define (unsigned int lineno, const char *buffer)
if (need_operand)
goto unknown;
+ gcc_assert ((size_t) (q - out_buffer) < out_len);
*q = '\0';
- slot = htab_find_slot_with_hash (macro_hash, copy, hashval, INSERT);
- *slot = copy;
+ mhval->value = out_buffer;
- fprintf (go_dump_file, "const _%s = %s\n", copy, out_buffer);
+ if (slot == NULL)
+ {
+ slot = htab_find_slot_with_hash (macro_hash, mhval, hashval, INSERT);
+ gcc_assert (slot != NULL && *slot == NULL);
+ }
+ else
+ {
+ if (*slot != NULL)
+ macro_hash_del (*slot);
+ }
+
+ *slot = mhval;
- XDELETEVEC (out_buffer);
return;
unknown:
fprintf (go_dump_file, "// unknowndefine %s\n", buffer);
+ if (slot != NULL)
+ htab_clear_slot (macro_hash, slot);
XDELETEVEC (out_buffer);
XDELETEVEC (copy);
}
@@ -403,16 +459,16 @@ go_define (unsigned int lineno, const char *buffer)
static void
go_undef (unsigned int lineno, const char *buffer)
{
+ struct macro_hash_value mhval;
void **slot;
real_debug_hooks->undef (lineno, buffer);
- slot = htab_find_slot (macro_hash, buffer, NO_INSERT);
- if (slot == NULL)
- return;
- fprintf (go_dump_file, "// undef _%s\n", buffer);
- /* We don't delete the slot from the hash table because that will
- cause a duplicate const definition. */
+ mhval.name = CONST_CAST (char *, buffer);
+ mhval.value = NULL;
+ slot = htab_find_slot (macro_hash, &mhval, NO_INSERT);
+ if (slot != NULL)
+ htab_clear_slot (macro_hash, slot);
}
/* A function or variable decl. */
@@ -909,32 +965,37 @@ go_output_typedef (struct godump_container *container, tree decl)
element = TREE_CHAIN (element))
{
const char *name;
+ struct macro_hash_value *mhval;
void **slot;
+ char buf[100];
name = IDENTIFIER_POINTER (TREE_PURPOSE (element));
/* Sometimes a name will be defined as both an enum constant
and a macro. Avoid duplicate definition errors by
treating enum constants as macros. */
- slot = htab_find_slot (macro_hash, name, INSERT);
- if (*slot == NULL)
- {
- *slot = CONST_CAST (char *, name);
- fprintf (go_dump_file, "const _%s = ", name);
- if (host_integerp (TREE_VALUE (element), 0))
- fprintf (go_dump_file, HOST_WIDE_INT_PRINT_DEC,
- tree_low_cst (TREE_VALUE (element), 0));
- else if (host_integerp (TREE_VALUE (element), 1))
- fprintf (go_dump_file, HOST_WIDE_INT_PRINT_UNSIGNED,
- ((unsigned HOST_WIDE_INT)
- tree_low_cst (TREE_VALUE (element), 1)));
- else
- fprintf (go_dump_file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
- ((unsigned HOST_WIDE_INT)
- TREE_INT_CST_HIGH (TREE_VALUE (element))),
- TREE_INT_CST_LOW (TREE_VALUE (element)));
- fprintf (go_dump_file, "\n");
- }
+ mhval = XNEW (struct macro_hash_value);
+ mhval->name = xstrdup (name);
+ mhval->value = NULL;
+ slot = htab_find_slot (macro_hash, mhval, INSERT);
+ if (*slot != NULL)
+ macro_hash_del (*slot);
+
+ if (host_integerp (TREE_VALUE (element), 0))
+ snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DEC,
+ tree_low_cst (TREE_VALUE (element), 0));
+ else if (host_integerp (TREE_VALUE (element), 1))
+ snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_UNSIGNED,
+ ((unsigned HOST_WIDE_INT)
+ tree_low_cst (TREE_VALUE (element), 1)));
+ else
+ snprintf (buf, sizeof buf, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ ((unsigned HOST_WIDE_INT)
+ TREE_INT_CST_HIGH (TREE_VALUE (element))),
+ TREE_INT_CST_LOW (TREE_VALUE (element)));
+
+ mhval->value = xstrdup (buf);
+ *slot = mhval;
}
pointer_set_insert (container->decls_seen, TREE_TYPE (decl));
if (TYPE_CANONICAL (TREE_TYPE (decl)) != NULL_TREE)
@@ -1039,6 +1100,17 @@ go_output_var (struct godump_container *container, tree decl)
}
}
+/* Output the final value of a preprocessor macro or enum constant.
+ This is called via htab_traverse_noresize. */
+
+static int
+go_print_macro (void **slot, void *arg ATTRIBUTE_UNUSED)
+{
+ struct macro_hash_value *mhval = (struct macro_hash_value *) *slot;
+ fprintf (go_dump_file, "const _%s = %s\n", mhval->name, mhval->value);
+ return 1;
+}
+
/* Build a hash table with the Go keywords. */
static const char * const keywords[] = {
@@ -1123,6 +1195,8 @@ go_finish (const char *filename)
}
}
+ htab_traverse_noresize (macro_hash, go_print_macro, NULL);
+
/* To emit dummy definitions. */
pointer_set_traverse (container.pot_dummy_types, find_dummy_types,
(void *) &container);
@@ -1163,7 +1237,8 @@ dump_go_spec_init (const char *filename, const struct gcc_debug_hooks *hooks)
go_debug_hooks.global_decl = go_global_decl;
go_debug_hooks.type_decl = go_type_decl;
- macro_hash = htab_create (100, htab_hash_string, string_hash_eq, NULL);
+ macro_hash = htab_create (100, macro_hash_hashval, macro_hash_eq,
+ macro_hash_del);
return &go_debug_hooks;
}
diff --git a/gcc/gthr-aix.h b/gcc/gthr-aix.h
deleted file mode 100644
index 6827e8f316d..00000000000
--- a/gcc/gthr-aix.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Threads compatibility routines for libgcc2 and libobjc. */
-/* Compile this one with gcc. */
-/* Copyright (C) 2000, 2009 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_GTHR_AIX_H
-#define GCC_GTHR_AIX_H
-
-#ifdef _THREAD_SAFE
-#include "gthr-posix.h"
-#else
-#include "gthr-single.h"
-#endif
-
-#endif /* GCC_GTHR_AIX_H */
diff --git a/gcc/gthr-lynx.h b/gcc/gthr-lynx.h
deleted file mode 100644
index 13b81d2fedb..00000000000
--- a/gcc/gthr-lynx.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Threads compatibility routines for libgcc2 and libobjc for
- LynxOS. */
-/* Compile this one with gcc. */
-/* Copyright (C) 2004, 2008, 2009 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_GTHR_LYNX_H
-#define GCC_GTHR_LYNX_H
-
-#ifdef _MULTITHREADED
-
-/* Using the macro version of pthread_setspecific leads to a
- compilation error. Instead we have two choices either kill all
- macros in pthread.h with defining _POSIX_THREADS_CALLS or undefine
- individual macros where we should fall back on the function
- implementation. We choose the second approach. */
-
-#include <pthread.h>
-#undef pthread_setspecific
-
-/* When using static libc on LynxOS, we cannot define pthread_create
- weak. If the multi-threaded application includes iostream.h,
- gthr-posix.h is included and pthread_create will be defined weak.
- If pthread_create is weak its defining module in libc is not
- necessarily included in the link and the symbol is resolved to zero.
- Therefore the first call to it will crash.
-
- Since -mthreads is a multilib switch on LynxOS we know that at this
- point we are compiling for multi-threaded. Omitting the weak
- definitions at this point should have no effect. */
-
-#undef GTHREAD_USE_WEAK
-#define GTHREAD_USE_WEAK 0
-
-#include "gthr-posix.h"
-
-#else
-#include "gthr-single.h"
-#endif
-
-#endif /* GCC_GTHR_LYNX_H */
diff --git a/gcc/gthr-posix.c b/gcc/gthr-posix.c
deleted file mode 100644
index 1987ba738c2..00000000000
--- a/gcc/gthr-posix.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/* POSIX threads dummy routines for systems without weak definitions. */
-/* Compile this one with gcc. */
-/* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "tconfig.h"
-#include "tm.h"
-# define __gthrw_pragma(pragma) _Pragma (#pragma)
-/* Define so we provide weak definitions of functions used by libobjc only. */
-#define _LIBOBJC_WEAK
-#include "gthr.h"
-
-int
-pthread_once (pthread_once_t *once ATTRIBUTE_UNUSED,
- void (*func) (void) ATTRIBUTE_UNUSED)
-{
- return -1;
-}
-
-int
-pthread_key_create (pthread_key_t *key ATTRIBUTE_UNUSED,
- void (*dtor) (void *) ATTRIBUTE_UNUSED)
-{
- return -1;
-}
-
-int
-pthread_key_delete (pthread_key_t key ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-void *
-pthread_getspecific (pthread_key_t key ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_setspecific (pthread_key_t key ATTRIBUTE_UNUSED,
- const void *ptr ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_create (pthread_t *thread ATTRIBUTE_UNUSED,
- const pthread_attr_t *attr ATTRIBUTE_UNUSED,
- void *(*start_routine) (void *) ATTRIBUTE_UNUSED,
- void *arg ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_join (pthread_t thread ATTRIBUTE_UNUSED,
- void **value_ptr ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-void
-pthread_exit (void *value_ptr ATTRIBUTE_UNUSED)
-{
-}
-
-int
-pthread_detach (pthread_t thread ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_cancel (pthread_t thread ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_mutex_lock (pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_mutex_trylock (pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-#ifdef _POSIX_TIMEOUTS
-#if _POSIX_TIMEOUTS >= 0
-int
-pthread_mutex_timedlock (pthread_mutex_t *mutex ATTRIBUTE_UNUSED,
- const struct timespec *abs_timeout ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-#endif
-#endif /* _POSIX_TIMEOUTS */
-
-int
-pthread_mutex_unlock (pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_mutexattr_init (pthread_mutexattr_t *attr ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_mutexattr_settype (pthread_mutexattr_t *attr ATTRIBUTE_UNUSED,
- int type ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_mutexattr_destroy (pthread_mutexattr_t *attr ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_cond_broadcast (pthread_cond_t *cond ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_cond_destroy (pthread_cond_t *cond ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_cond_init (pthread_cond_t *cond ATTRIBUTE_UNUSED,
- const pthread_condattr_t *attr ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_cond_signal (pthread_cond_t *cond ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_cond_wait (pthread_cond_t *cond ATTRIBUTE_UNUSED,
- pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_cond_timedwait (pthread_cond_t *cond ATTRIBUTE_UNUSED,
- pthread_mutex_t *mutex ATTRIBUTE_UNUSED,
- const struct timespec *abstime ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_mutex_init (pthread_mutex_t *mutex ATTRIBUTE_UNUSED,
- const pthread_mutexattr_t *attr ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_mutex_destroy (pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-pthread_t
-pthread_self (void)
-{
- return (pthread_t) 0;
-}
-
-#ifdef _POSIX_PRIORITY_SCHEDULING
-#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
-int
-sched_get_priority_max (int policy ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-sched_get_priority_min (int policy ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
-#endif /* _POSIX_PRIORITY_SCHEDULING */
-
-int
-sched_yield (void)
-{
- return 0;
-}
-
-int
-pthread_attr_destroy (pthread_attr_t *attr ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_attr_init (pthread_attr_t *attr ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_attr_setdetachstate (pthread_attr_t *attr ATTRIBUTE_UNUSED,
- int detachstate ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
-int
-pthread_getschedparam (pthread_t thread ATTRIBUTE_UNUSED,
- int *policy ATTRIBUTE_UNUSED,
- struct sched_param *param ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-int
-pthread_setschedparam (pthread_t thread ATTRIBUTE_UNUSED,
- int policy ATTRIBUTE_UNUSED,
- const struct sched_param *param ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
-
diff --git a/gcc/gthr-vxworks.h b/gcc/gthr-vxworks.h
deleted file mode 100644
index d4da14ef492..00000000000
--- a/gcc/gthr-vxworks.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/* Threads compatibility routines for libgcc2 and libobjc for VxWorks. */
-/* Compile this one with gcc. */
-/* Copyright (C) 1997, 1999, 2000, 2008, 2009 Free Software Foundation, Inc.
- Contributed by Mike Stump <mrs@wrs.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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_GTHR_VXWORKS_H
-#define GCC_GTHR_VXWORKS_H
-
-#ifdef _LIBOBJC
-
-/* libobjc requires the optional pthreads component. */
-#include "gthr-posix.h"
-
-#else
-#ifdef __cplusplus
-#define UNUSED(x)
-#else
-#define UNUSED(x) x __attribute__((unused))
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define __GTHREADS 1
-#define __gthread_active_p() 1
-
-/* Mutexes are easy, except that they need to be initialized at runtime. */
-
-#include <semLib.h>
-
-typedef SEM_ID __gthread_mutex_t;
-/* All VxWorks mutexes are recursive. */
-typedef SEM_ID __gthread_recursive_mutex_t;
-#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
-#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
-
-static inline void
-__gthread_mutex_init_function (__gthread_mutex_t *mutex)
-{
- *mutex = semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
-}
-
-static inline int
-__gthread_mutex_destroy (__gthread_mutex_t * UNUSED(mutex))
-{
- return 0;
-}
-
-static inline int
-__gthread_mutex_lock (__gthread_mutex_t *mutex)
-{
- return semTake (*mutex, WAIT_FOREVER);
-}
-
-static inline int
-__gthread_mutex_trylock (__gthread_mutex_t *mutex)
-{
- return semTake (*mutex, NO_WAIT);
-}
-
-static inline int
-__gthread_mutex_unlock (__gthread_mutex_t *mutex)
-{
- return semGive (*mutex);
-}
-
-static inline void
-__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
-{
- __gthread_mutex_init_function (mutex);
-}
-
-static inline int
-__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
-{
- return __gthread_mutex_lock (mutex);
-}
-
-static inline int
-__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
-{
- return __gthread_mutex_trylock (mutex);
-}
-
-static inline int
-__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
-{
- return __gthread_mutex_unlock (mutex);
-}
-
-/* pthread_once is complicated enough that it's implemented
- out-of-line. See config/vxlib.c. */
-
-typedef struct
-{
-#if !defined(__RTP__)
-#if defined(__PPC__)
- __attribute ((aligned (__alignof (unsigned))))
-#endif
- volatile unsigned char busy;
-#endif
- volatile unsigned char done;
-#if !defined(__RTP__) && defined(__PPC__)
- /* PPC's test-and-set implementation requires a 4 byte aligned
- object, of which it only sets the first byte. We use padding
- here, in order to maintain some amount of backwards
- compatibility. Without this padding, gthread_once objects worked
- by accident because they happen to be static objects and the ppc
- port automatically increased their alignment to 4 bytes. */
- unsigned char pad1;
- unsigned char pad2;
-#endif
-}
-__gthread_once_t;
-
-#if defined (__RTP__)
-# define __GTHREAD_ONCE_INIT { 0 }
-#elif defined (__PPC__)
-# define __GTHREAD_ONCE_INIT { 0, 0, 0, 0 }
-#else
-# define __GTHREAD_ONCE_INIT { 0, 0 }
-#endif
-
-extern int __gthread_once (__gthread_once_t *__once, void (*__func)(void));
-
-/* Thread-specific data requires a great deal of effort, since VxWorks
- is not really set up for it. See config/vxlib.c for the gory
- details. All the TSD routines are sufficiently complex that they
- need to be implemented out of line. */
-
-typedef unsigned int __gthread_key_t;
-
-extern int __gthread_key_create (__gthread_key_t *__keyp, void (*__dtor)(void *));
-extern int __gthread_key_delete (__gthread_key_t __key);
-
-extern void *__gthread_getspecific (__gthread_key_t __key);
-extern int __gthread_setspecific (__gthread_key_t __key, void *__ptr);
-
-#undef UNUSED
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* not _LIBOBJC */
-
-#endif /* gthr-vxworks.h */
diff --git a/gcc/gthr.h b/gcc/gthr.h
deleted file mode 100644
index 0c7bfb17aa3..00000000000
--- a/gcc/gthr.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* Threads compatibility routines for libgcc2. */
-/* Compile this one with gcc. */
-/* Copyright (C) 1997, 1998, 2004, 2008, 2009, 2011
- 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_GTHR_H
-#define GCC_GTHR_H
-
-#ifndef HIDE_EXPORTS
-#pragma GCC visibility push(default)
-#endif
-
-/* 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
- int __gthread_active_p ()
- that returns 1 if thread system is active, 0 if not.
-
- The threads interface must define the following types:
- __gthread_key_t
- __gthread_once_t
- __gthread_mutex_t
- __gthread_recursive_mutex_t
-
- The threads interface must define the following macros:
-
- __GTHREAD_ONCE_INIT
- to initialize __gthread_once_t
- __GTHREAD_MUTEX_INIT
- to initialize __gthread_mutex_t to get a fast
- non-recursive mutex.
- __GTHREAD_MUTEX_INIT_FUNCTION
- some systems can't initialize a mutex without a
- function call. On such systems, define this to a
- function which looks like this:
- void __GTHREAD_MUTEX_INIT_FUNCTION (__gthread_mutex_t *)
- Don't define __GTHREAD_MUTEX_INIT in this case
- __GTHREAD_RECURSIVE_MUTEX_INIT
- __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
- as above, but for a recursive mutex.
-
- The threads interface must define the following static functions:
-
- int __gthread_once (__gthread_once_t *once, void (*func) ())
-
- int __gthread_key_create (__gthread_key_t *keyp, void (*dtor) (void *))
- int __gthread_key_delete (__gthread_key_t key)
-
- void *__gthread_getspecific (__gthread_key_t key)
- int __gthread_setspecific (__gthread_key_t key, const void *ptr)
-
- int __gthread_mutex_destroy (__gthread_mutex_t *mutex);
-
- int __gthread_mutex_lock (__gthread_mutex_t *mutex);
- int __gthread_mutex_trylock (__gthread_mutex_t *mutex);
- int __gthread_mutex_unlock (__gthread_mutex_t *mutex);
-
- int __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex);
- int __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex);
- int __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex);
-
- The following are supported in POSIX threads only. They are required to
- fix a deadlock in static initialization inside libsupc++. The header file
- gthr-posix.h defines a symbol __GTHREAD_HAS_COND to signify that these extra
- features are supported.
-
- Types:
- __gthread_cond_t
-
- Macros:
- __GTHREAD_COND_INIT
- __GTHREAD_COND_INIT_FUNCTION
-
- Interface:
- int __gthread_cond_broadcast (__gthread_cond_t *cond);
- int __gthread_cond_wait (__gthread_cond_t *cond, __gthread_mutex_t *mutex);
- int __gthread_cond_wait_recursive (__gthread_cond_t *cond,
- __gthread_recursive_mutex_t *mutex);
-
- All functions returning int should return zero on success or the error
- number. If the operation is not supported, -1 is returned.
-
- If the following are also defined, you should
- #define __GTHREADS_CXX0X 1
- to enable the c++0x thread library.
-
- Types:
- __gthread_t
- __gthread_time_t
-
- Interface:
- int __gthread_create (__gthread_t *thread, void *(*func) (void*),
- void *args);
- int __gthread_join (__gthread_t thread, void **value_ptr);
- int __gthread_detach (__gthread_t thread);
- int __gthread_equal (__gthread_t t1, __gthread_t t2);
- __gthread_t __gthread_self (void);
- int __gthread_yield (void);
-
- int __gthread_mutex_timedlock (__gthread_mutex_t *m,
- const __gthread_time_t *abs_timeout);
- int __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *m,
- const __gthread_time_t *abs_time);
-
- int __gthread_cond_signal (__gthread_cond_t *cond);
- int __gthread_cond_timedwait (__gthread_cond_t *cond,
- __gthread_mutex_t *mutex,
- const __gthread_time_t *abs_timeout);
- int __gthread_cond_timedwait_recursive (__gthread_cond_t *cond,
- __gthread_recursive_mutex_t *mutex,
- const __gthread_time_t *abs_time)
-
- Currently supported threads packages are
- TPF threads with -D__tpf__
- POSIX/Unix98 threads with -D_PTHREADS
- DCE threads with -D_DCE_THREADS
-
-*/
-
-/* Check first for thread specific defines. */
-#if defined (__tpf__)
-#include "gthr-tpf.h"
-#elif _PTHREADS
-#include "gthr-posix.h"
-#elif _DCE_THREADS
-#include "gthr-dce.h"
-
-/* Include GTHREAD_FILE if one is defined. */
-#elif defined(HAVE_GTHR_DEFAULT)
-#if SUPPORTS_WEAK
-#ifndef GTHREAD_USE_WEAK
-#define GTHREAD_USE_WEAK 1
-#endif
-#endif
-#include "gthr-default.h"
-
-/* Fallback to single thread definitions. */
-#else
-#include "gthr-single.h"
-#endif
-
-#ifndef HIDE_EXPORTS
-#pragma GCC visibility pop
-#endif
-
-#endif /* ! GCC_GTHR_H */
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index a5b4aebefee..d87a608b901 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -129,9 +129,9 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "diagnostic-core.h"
+#include "hard-reg-set.h"
#include "rtl.h"
#include "tm_p.h"
-#include "hard-reg-set.h"
#include "regs.h"
#include "function.h"
#include "flags.h"
@@ -213,6 +213,7 @@ struct common_sched_info_def *common_sched_info;
#define INTER_TICK(INSN) (HID (INSN)->inter_tick)
#define FEEDS_BACKTRACK_INSN(INSN) (HID (INSN)->feeds_backtrack_insn)
#define SHADOW_P(INSN) (HID (INSN)->shadow_p)
+#define MUST_RECOMPUTE_SPEC_P(INSN) (HID (INSN)->must_recompute_spec)
/* If INSN_TICK of an instruction is equal to INVALID_TICK,
then it should be recalculated from scratch. */
@@ -706,6 +707,24 @@ record_delay_slot_pair (rtx i1, rtx i2, int cycles, int stages)
*slot = p;
}
+/* Examine the delay pair hashtable to see if INSN is a shadow for another,
+ and return the other insn if so. Return NULL otherwise. */
+rtx
+real_insn_for_shadow (rtx insn)
+{
+ struct delay_pair *pair;
+
+ if (delay_htab == NULL)
+ return NULL_RTX;
+
+ pair
+ = (struct delay_pair *)htab_find_with_hash (delay_htab_i2, insn,
+ htab_hash_pointer (insn));
+ if (!pair || pair->stages > 0)
+ return NULL_RTX;
+ return pair->i1;
+}
+
/* For a pair P of insns, return the fixed distance in cycles from the first
insn after which the second must be scheduled. */
static int
@@ -820,6 +839,7 @@ static void change_queue_index (rtx, int);
static void extend_h_i_d (void);
static void init_h_i_d (rtx);
+static int haifa_speculate_insn (rtx, ds_t, rtx *);
static void generate_recovery_code (rtx);
static void process_insn_forw_deps_be_in_spec (rtx, rtx, ds_t);
static void begin_speculative_block (rtx);
@@ -827,7 +847,7 @@ static void add_to_speculative_block (rtx);
static void init_before_recovery (basic_block *);
static void create_check_block_twin (rtx, bool);
static void fix_recovery_deps (basic_block);
-static void haifa_change_pattern (rtx, rtx);
+static bool haifa_change_pattern (rtx, rtx);
static void dump_new_block_header (int, basic_block, rtx, rtx);
static void restore_bb_notes (basic_block);
static void fix_jump_move (rtx);
@@ -1056,7 +1076,178 @@ print_curr_reg_pressure (void)
}
fprintf (sched_dump, "\n");
}
+
+/* Determine if INSN has a condition that is clobbered if a register
+ in SET_REGS is modified. */
+static bool
+cond_clobbered_p (rtx insn, HARD_REG_SET set_regs)
+{
+ rtx pat = PATTERN (insn);
+ gcc_assert (GET_CODE (pat) == COND_EXEC);
+ if (TEST_HARD_REG_BIT (set_regs, REGNO (XEXP (COND_EXEC_TEST (pat), 0))))
+ {
+ sd_iterator_def sd_it;
+ dep_t dep;
+ haifa_change_pattern (insn, ORIG_PAT (insn));
+ FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
+ DEP_STATUS (dep) &= ~DEP_CANCELLED;
+ TODO_SPEC (insn) = HARD_DEP;
+ if (sched_verbose >= 2)
+ fprintf (sched_dump,
+ ";;\t\tdequeue insn %s because of clobbered condition\n",
+ (*current_sched_info->print_insn) (insn, 0));
+ return true;
+ }
+
+ return false;
+}
+
+/* Look at the remaining dependencies for insn NEXT, and compute and return
+ the TODO_SPEC value we should use for it. This is called after one of
+ NEXT's dependencies has been resolved. */
+
+static ds_t
+recompute_todo_spec (rtx next)
+{
+ ds_t new_ds;
+ sd_iterator_def sd_it;
+ dep_t dep, control_dep = NULL;
+ int n_spec = 0;
+ int n_control = 0;
+ bool first_p = true;
+
+ if (sd_lists_empty_p (next, SD_LIST_BACK))
+ /* NEXT has all its dependencies resolved. */
+ return 0;
+
+ if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
+ return HARD_DEP;
+
+ /* Now we've got NEXT with speculative deps only.
+ 1. Look at the deps to see what we have to do.
+ 2. Check if we can do 'todo'. */
+ new_ds = 0;
+
+ FOR_EACH_DEP (next, SD_LIST_BACK, sd_it, dep)
+ {
+ ds_t ds = DEP_STATUS (dep) & SPECULATIVE;
+
+ if (DEBUG_INSN_P (DEP_PRO (dep)) && !DEBUG_INSN_P (next))
+ continue;
+
+ if (ds)
+ {
+ n_spec++;
+ if (first_p)
+ {
+ first_p = false;
+
+ new_ds = ds;
+ }
+ else
+ new_ds = ds_merge (new_ds, ds);
+ }
+ if (DEP_TYPE (dep) == REG_DEP_CONTROL)
+ {
+ n_control++;
+ control_dep = dep;
+ DEP_STATUS (dep) &= ~DEP_CANCELLED;
+ }
+ }
+
+ if (n_control == 1 && n_spec == 0)
+ {
+ rtx pro, other, new_pat;
+ rtx cond = NULL_RTX;
+ bool success;
+ rtx prev = NULL_RTX;
+ int i;
+ unsigned regno;
+
+ if ((current_sched_info->flags & DO_PREDICATION) == 0
+ || (ORIG_PAT (next) != NULL_RTX
+ && PREDICATED_PAT (next) == NULL_RTX))
+ return HARD_DEP;
+
+ pro = DEP_PRO (control_dep);
+ other = real_insn_for_shadow (pro);
+ if (other != NULL_RTX)
+ pro = other;
+
+ cond = sched_get_reverse_condition_uncached (pro);
+ regno = REGNO (XEXP (cond, 0));
+
+ /* Find the last scheduled insn that modifies the condition register.
+ If we have a true dependency on it, it sets it to the correct value,
+ otherwise it must be a later insn scheduled in-between that clobbers
+ the condition. */
+ FOR_EACH_VEC_ELT_REVERSE (rtx, scheduled_insns, i, prev)
+ {
+ sd_iterator_def sd_it;
+ dep_t dep;
+ HARD_REG_SET t;
+ bool found;
+
+ find_all_hard_reg_sets (prev, &t);
+ if (!TEST_HARD_REG_BIT (t, regno))
+ continue;
+
+ found = false;
+ FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep)
+ {
+ if (DEP_PRO (dep) == prev && DEP_TYPE (dep) == REG_DEP_TRUE)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return HARD_DEP;
+ break;
+ }
+ if (ORIG_PAT (next) == NULL_RTX)
+ {
+ ORIG_PAT (next) = PATTERN (next);
+ new_pat = gen_rtx_COND_EXEC (VOIDmode, cond, PATTERN (next));
+ success = haifa_change_pattern (next, new_pat);
+ if (!success)
+ return HARD_DEP;
+ PREDICATED_PAT (next) = new_pat;
+ }
+ else if (PATTERN (next) != PREDICATED_PAT (next))
+ {
+ bool success = haifa_change_pattern (next,
+ PREDICATED_PAT (next));
+ gcc_assert (success);
+ }
+ DEP_STATUS (control_dep) |= DEP_CANCELLED;
+ return DEP_CONTROL;
+ }
+
+ if (PREDICATED_PAT (next) != NULL_RTX)
+ {
+ int tick = INSN_TICK (next);
+ bool success = haifa_change_pattern (next,
+ ORIG_PAT (next));
+ INSN_TICK (next) = tick;
+ gcc_assert (success);
+ }
+
+ /* We can't handle the case where there are both speculative and control
+ dependencies, so we return HARD_DEP in such a case. Also fail if
+ we have speculative dependencies with not enough points, or more than
+ one control dependency. */
+ if ((n_spec > 0 && n_control > 0)
+ || (n_spec > 0
+ /* Too few points? */
+ && ds_weak (new_ds) < spec_info->data_weakness_cutoff)
+ || (n_control > 1))
+ return HARD_DEP;
+
+ return new_ds;
+}
+
/* Pointer to the last instruction scheduled. */
static rtx last_scheduled_insn;
@@ -1963,6 +2154,51 @@ sched_setup_bb_reg_pressure_info (basic_block bb, rtx after)
setup_insn_max_reg_pressure (after, false);
}
+/* If doing predication while scheduling, verify whether INSN, which
+ has just been scheduled, clobbers the conditions of any
+ instructions that must be predicated in order to break their
+ dependencies. If so, remove them from the queues so that they will
+ only be scheduled once their control dependency is resolved. */
+
+static void
+check_clobbered_conditions (rtx insn)
+{
+ HARD_REG_SET t;
+ int i;
+
+ if ((current_sched_info->flags & DO_PREDICATION) == 0)
+ return;
+
+ find_all_hard_reg_sets (insn, &t);
+
+ restart:
+ for (i = 0; i < ready.n_ready; i++)
+ {
+ rtx x = ready_element (&ready, i);
+ if (TODO_SPEC (x) == DEP_CONTROL && cond_clobbered_p (x, t))
+ {
+ ready_remove_insn (x);
+ goto restart;
+ }
+ }
+ for (i = 0; i <= max_insn_queue_index; i++)
+ {
+ rtx link;
+ int q = NEXT_Q_AFTER (q_ptr, i);
+
+ restart_queue:
+ for (link = insn_queue[q]; link; link = XEXP (link, 1))
+ {
+ rtx x = XEXP (link, 0);
+ if (TODO_SPEC (x) == DEP_CONTROL && cond_clobbered_p (x, t))
+ {
+ queue_remove (x);
+ goto restart_queue;
+ }
+ }
+ }
+}
+
/* A structure that holds local state for the loop in schedule_block. */
struct sched_block_state
{
@@ -2023,7 +2259,7 @@ schedule_insn (rtx insn)
/* Scheduling instruction should have all its dependencies resolved and
should have been removed from the ready list. */
- gcc_assert (sd_lists_empty_p (insn, SD_LIST_BACK));
+ gcc_assert (sd_lists_empty_p (insn, SD_LIST_HARD_BACK));
/* Reset debug insns invalidated by moving this insn. */
if (MAY_HAVE_DEBUG_INSNS && !DEBUG_INSN_P (insn))
@@ -2033,6 +2269,12 @@ schedule_insn (rtx insn)
rtx dbg = DEP_PRO (dep);
struct reg_use_data *use, *next;
+ if (DEP_STATUS (dep) & DEP_CANCELLED)
+ {
+ sd_iterator_next (&sd_it);
+ continue;
+ }
+
gcc_assert (DEBUG_INSN_P (dbg));
if (sched_verbose >= 6)
@@ -2086,17 +2328,36 @@ schedule_insn (rtx insn)
INSN_TICK untouched. This is a machine-dependent issue, actually. */
INSN_TICK (insn) = clock_var;
+ check_clobbered_conditions (insn);
+
/* Update dependent instructions. */
for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
sd_iterator_cond (&sd_it, &dep);)
{
rtx next = DEP_CON (dep);
+ bool cancelled = (DEP_STATUS (dep) & DEP_CANCELLED) != 0;
/* Resolve the dependence between INSN and NEXT.
sd_resolve_dep () moves current dep to another list thus
advancing the iterator. */
sd_resolve_dep (sd_it);
+ if (cancelled)
+ {
+ if (QUEUE_INDEX (next) != QUEUE_SCHEDULED)
+ {
+ int tick = INSN_TICK (next);
+ gcc_assert (ORIG_PAT (next) != NULL_RTX);
+ haifa_change_pattern (next, ORIG_PAT (next));
+ INSN_TICK (next) = tick;
+ if (sd_lists_empty_p (next, SD_LIST_BACK))
+ TODO_SPEC (next) = 0;
+ else if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
+ TODO_SPEC (next) = HARD_DEP;
+ }
+ continue;
+ }
+
/* Don't bother trying to mark next as ready if insn is a debug
insn. If insn is the last hard dependency, it will have
already been discounted. */
@@ -2270,24 +2531,6 @@ mark_backtrack_feeds (rtx insn, int set_p)
}
}
-/* Make a copy of the INSN_LIST list LINK and return it. */
-static rtx
-copy_insn_list (rtx link)
-{
- rtx new_queue;
- rtx *pqueue = &new_queue;
-
- for (; link; link = XEXP (link, 1))
- {
- rtx x = XEXP (link, 0);
- rtx newlink = alloc_INSN_LIST (x, NULL);
- *pqueue = newlink;
- pqueue = &XEXP (newlink, 1);
- }
- *pqueue = NULL_RTX;
- return new_queue;
-}
-
/* Save the current scheduler state so that we can backtrack to it
later if necessary. PAIR gives the insns that make it necessary to
save this point. SCHED_BLOCK is the local state of schedule_block
@@ -2314,7 +2557,7 @@ save_backtrack_point (struct delay_pair *pair,
for (i = 0; i <= max_insn_queue_index; i++)
{
int q = NEXT_Q_AFTER (q_ptr, i);
- save->insn_queue[i] = copy_insn_list (insn_queue[q]);
+ save->insn_queue[i] = copy_INSN_LIST (insn_queue[q]);
}
save->clock_var = clock_var;
@@ -2351,6 +2594,49 @@ save_backtrack_point (struct delay_pair *pair,
}
}
+/* Walk the ready list and all queues. If any insns have unresolved backwards
+ dependencies, these must be cancelled deps, broken by predication. Set or
+ clear (depending on SET) the DEP_CANCELLED bit in DEP_STATUS. */
+
+static void
+toggle_cancelled_flags (bool set)
+{
+ int i;
+ sd_iterator_def sd_it;
+ dep_t dep;
+
+ if (ready.n_ready > 0)
+ {
+ rtx *first = ready_lastpos (&ready);
+ for (i = 0; i < ready.n_ready; i++)
+ FOR_EACH_DEP (first[i], SD_LIST_BACK, sd_it, dep)
+ if (!DEBUG_INSN_P (DEP_PRO (dep)))
+ {
+ if (set)
+ DEP_STATUS (dep) |= DEP_CANCELLED;
+ else
+ DEP_STATUS (dep) &= ~DEP_CANCELLED;
+ }
+ }
+ for (i = 0; i <= max_insn_queue_index; i++)
+ {
+ int q = NEXT_Q_AFTER (q_ptr, i);
+ rtx link;
+ for (link = insn_queue[q]; link; link = XEXP (link, 1))
+ {
+ rtx insn = XEXP (link, 0);
+ FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
+ if (!DEBUG_INSN_P (DEP_PRO (dep)))
+ {
+ if (set)
+ DEP_STATUS (dep) |= DEP_CANCELLED;
+ else
+ DEP_STATUS (dep) &= ~DEP_CANCELLED;
+ }
+ }
+ }
+}
+
/* Pop entries from the SCHEDULED_INSNS vector up to and including INSN.
Restore their dependencies to an unresolved state, and mark them as
queued nowhere. */
@@ -2358,6 +2644,12 @@ save_backtrack_point (struct delay_pair *pair,
static void
unschedule_insns_until (rtx insn)
{
+ VEC (rtx, heap) *recompute_vec;
+
+ recompute_vec = VEC_alloc (rtx, heap, 0);
+
+ /* Make two passes over the insns to be unscheduled. First, we clear out
+ dependencies and other trivial bookkeeping. */
for (;;)
{
rtx last;
@@ -2379,14 +2671,40 @@ unschedule_insns_until (rtx insn)
sd_iterator_cond (&sd_it, &dep);)
{
rtx con = DEP_CON (dep);
- TODO_SPEC (con) = HARD_DEP;
- INSN_TICK (con) = INVALID_TICK;
sd_unresolve_dep (sd_it);
+ if (!MUST_RECOMPUTE_SPEC_P (con))
+ {
+ MUST_RECOMPUTE_SPEC_P (con) = 1;
+ VEC_safe_push (rtx, heap, recompute_vec, con);
+ }
}
if (last == insn)
break;
}
+
+ /* A second pass, to update ready and speculation status for insns
+ depending on the unscheduled ones. The first pass must have
+ popped the scheduled_insns vector up to the point where we
+ restart scheduling, as recompute_todo_spec requires it to be
+ up-to-date. */
+ while (!VEC_empty (rtx, recompute_vec))
+ {
+ rtx con;
+
+ con = VEC_pop (rtx, recompute_vec);
+ MUST_RECOMPUTE_SPEC_P (con) = 0;
+ if (!sd_lists_empty_p (con, SD_LIST_HARD_BACK))
+ {
+ TODO_SPEC (con) = HARD_DEP;
+ INSN_TICK (con) = INVALID_TICK;
+ if (PREDICATED_PAT (con) != NULL_RTX)
+ haifa_change_pattern (con, ORIG_PAT (con));
+ }
+ else if (QUEUE_INDEX (con) != QUEUE_SCHEDULED)
+ TODO_SPEC (con) = recompute_todo_spec (con);
+ }
+ VEC_free (rtx, heap, recompute_vec);
}
/* Restore scheduler state from the topmost entry on the backtracking queue.
@@ -2396,7 +2714,6 @@ unschedule_insns_until (rtx insn)
static void
restore_last_backtrack_point (struct sched_block_state *psched_block)
-
{
rtx link;
int i;
@@ -2420,8 +2737,9 @@ restore_last_backtrack_point (struct sched_block_state *psched_block)
rtx *first = ready_lastpos (&ready);
for (i = 0; i < ready.n_ready; i++)
{
- QUEUE_INDEX (first[i]) = QUEUE_NOWHERE;
- INSN_TICK (first[i]) = INVALID_TICK;
+ rtx insn = first[i];
+ QUEUE_INDEX (insn) = QUEUE_NOWHERE;
+ INSN_TICK (insn) = INVALID_TICK;
}
}
for (i = 0; i <= max_insn_queue_index; i++)
@@ -2445,8 +2763,10 @@ restore_last_backtrack_point (struct sched_block_state *psched_block)
rtx *first = ready_lastpos (&ready);
for (i = 0; i < ready.n_ready; i++)
{
- QUEUE_INDEX (first[i]) = QUEUE_READY;
- INSN_TICK (first[i]) = save->clock_var;
+ rtx insn = first[i];
+ QUEUE_INDEX (insn) = QUEUE_READY;
+ TODO_SPEC (insn) = recompute_todo_spec (insn);
+ INSN_TICK (insn) = save->clock_var;
}
}
@@ -2462,11 +2782,14 @@ restore_last_backtrack_point (struct sched_block_state *psched_block)
{
rtx x = XEXP (link, 0);
QUEUE_INDEX (x) = i;
+ TODO_SPEC (x) = recompute_todo_spec (x);
INSN_TICK (x) = save->clock_var + i;
}
}
free (save->insn_queue);
+ toggle_cancelled_flags (true);
+
clock_var = save->clock_var;
last_clock_var = save->last_clock_var;
cycle_issued_insns = save->cycle_issued_insns;
@@ -2547,6 +2870,9 @@ estimate_insn_tick (bitmap processed, rtx insn, int budget)
rtx pro = DEP_PRO (dep);
int t;
+ if (DEP_STATUS (dep) & DEP_CANCELLED)
+ continue;
+
if (QUEUE_INDEX (pro) == QUEUE_SCHEDULED)
gcc_assert (INSN_TICK (pro) + dep_cost (dep) <= INSN_TICK (insn));
else
@@ -4217,6 +4543,7 @@ schedule_block (basic_block *target_bb)
gcc_assert (failed);
failed_insn = failed->delay_pair->i1;
+ toggle_cancelled_flags (false);
unschedule_insns_until (failed_insn);
while (failed != backtrack_queue)
free_topmost_backtrack_point (true);
@@ -4732,8 +5059,6 @@ fix_inter_tick (rtx head, rtx tail)
bitmap_clear (&processed);
}
-static int haifa_speculate_insn (rtx, ds_t, rtx *);
-
/* Check if NEXT is ready to be added to the ready or queue list.
If "yes", add it to the proper list.
Returns:
@@ -4747,57 +5072,15 @@ try_ready (rtx next)
old_ts = TODO_SPEC (next);
- gcc_assert (!(old_ts & ~(SPECULATIVE | HARD_DEP))
+ gcc_assert (!(old_ts & ~(SPECULATIVE | HARD_DEP | DEP_CONTROL))
&& ((old_ts & HARD_DEP)
- || (old_ts & SPECULATIVE)));
-
- if (sd_lists_empty_p (next, SD_LIST_BACK))
- /* NEXT has all its dependencies resolved. */
- new_ts = 0;
- else
- {
- /* One of the NEXT's dependencies has been resolved.
- Recalculate NEXT's status. */
-
- if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
- new_ts = HARD_DEP;
- else
- /* Now we've got NEXT with speculative deps only.
- 1. Look at the deps to see what we have to do.
- 2. Check if we can do 'todo'. */
- {
- sd_iterator_def sd_it;
- dep_t dep;
- bool first_p = true;
-
- new_ts = 0;
-
- FOR_EACH_DEP (next, SD_LIST_BACK, sd_it, dep)
- {
- ds_t ds = DEP_STATUS (dep) & SPECULATIVE;
+ || (old_ts & SPECULATIVE)
+ || (old_ts & DEP_CONTROL)));
- if (DEBUG_INSN_P (DEP_PRO (dep))
- && !DEBUG_INSN_P (next))
- continue;
-
- if (first_p)
- {
- first_p = false;
-
- new_ts = ds;
- }
- else
- new_ts = ds_merge (new_ts, ds);
- }
-
- if (ds_weak (new_ts) < spec_info->data_weakness_cutoff)
- /* Too few points. */
- new_ts = HARD_DEP;
- }
- }
+ new_ts = recompute_todo_spec (next);
if (new_ts & HARD_DEP)
- gcc_assert (new_ts == HARD_DEP && new_ts == old_ts
+ gcc_assert (new_ts == old_ts
&& QUEUE_INDEX (next) == QUEUE_NOWHERE);
else if (current_sched_info->new_ready)
new_ts = current_sched_info->new_ready (next, new_ts);
@@ -4820,7 +5103,7 @@ try_ready (rtx next)
int res;
rtx new_pat;
- gcc_assert (!(new_ts & ~SPECULATIVE));
+ gcc_assert ((new_ts & SPECULATIVE) && !(new_ts & ~SPECULATIVE));
res = haifa_speculate_insn (next, new_ts, &new_pat);
@@ -4846,7 +5129,8 @@ try_ready (rtx next)
save it. */
ORIG_PAT (next) = PATTERN (next);
- haifa_change_pattern (next, new_pat);
+ res = haifa_change_pattern (next, new_pat);
+ gcc_assert (res);
break;
default:
@@ -4871,16 +5155,19 @@ try_ready (rtx next)
/*gcc_assert (QUEUE_INDEX (next) == QUEUE_NOWHERE);*/
change_queue_index (next, QUEUE_NOWHERE);
+
return -1;
}
else if (!(new_ts & BEGIN_SPEC)
- && ORIG_PAT (next) && !IS_SPECULATION_CHECK_P (next))
+ && ORIG_PAT (next) && PREDICATED_PAT (next) == NULL_RTX
+ && !IS_SPECULATION_CHECK_P (next))
/* We should change pattern of every previously speculative
instruction - and we determine if NEXT was speculative by using
ORIG_PAT field. Except one case - speculation checks have ORIG_PAT
pat too, so skip them. */
{
- haifa_change_pattern (next, ORIG_PAT (next));
+ bool success = haifa_change_pattern (next, ORIG_PAT (next));
+ gcc_assert (success);
ORIG_PAT (next) = 0;
}
@@ -4898,7 +5185,8 @@ try_ready (rtx next)
if (new_ts & BE_IN_CONTROL)
fprintf (spec_info->dump, "; in-control-spec;");
}
-
+ if (TODO_SPEC (next) & DEP_CONTROL)
+ fprintf (sched_dump, " predicated");
fprintf (sched_dump, "\n");
}
@@ -5874,38 +6162,33 @@ fix_recovery_deps (basic_block rec)
add_jump_dependencies (insn, jump);
}
-/* Change pattern of INSN to NEW_PAT. */
-void
-sched_change_pattern (rtx insn, rtx new_pat)
+/* Change pattern of INSN to NEW_PAT. Invalidate cached haifa
+ instruction data. */
+static bool
+haifa_change_pattern (rtx insn, rtx new_pat)
{
sd_iterator_def sd_it;
dep_t dep;
int t;
t = validate_change (insn, &PATTERN (insn), new_pat, 0);
- gcc_assert (t);
+ if (!t)
+ return false;
dfa_clear_single_insn_cache (insn);
- for (sd_it = sd_iterator_start (insn, (SD_LIST_FORW | SD_LIST_BACK
- | SD_LIST_RES_BACK));
- sd_iterator_cond (&sd_it, &dep);)
+ sd_it = sd_iterator_start (insn,
+ SD_LIST_FORW | SD_LIST_BACK | SD_LIST_RES_BACK);
+ while (sd_iterator_cond (&sd_it, &dep))
{
DEP_COST (dep) = UNKNOWN_DEP_COST;
sd_iterator_next (&sd_it);
}
-}
-
-/* Change pattern of INSN to NEW_PAT. Invalidate cached haifa
- instruction data. */
-static void
-haifa_change_pattern (rtx insn, rtx new_pat)
-{
- sched_change_pattern (insn, new_pat);
/* Invalidate INSN_COST, so it'll be recalculated. */
INSN_COST (insn) = -1;
/* Invalidate INSN_TICK, so it'll be recalculated. */
INSN_TICK (insn) = INVALID_TICK;
+ return true;
}
/* -1 - can't speculate,
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 272cbb7175f..784e2e8b106 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -4166,6 +4166,64 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
FOR_BB_INSNS (merge_bb, insn)
if (NONDEBUG_INSN_P (insn))
df_simulate_find_defs (insn, merge_set);
+
+ /* If shrink-wrapping, disable this optimization when test_bb is
+ the first basic block and merge_bb exits. The idea is to not
+ move code setting up a return register as that may clobber a
+ register used to pass function parameters, which then must be
+ saved in caller-saved regs. A caller-saved reg requires the
+ prologue, killing a shrink-wrap opportunity. */
+ if ((flag_shrink_wrap && !epilogue_completed)
+ && ENTRY_BLOCK_PTR->next_bb == test_bb
+ && single_succ_p (new_dest)
+ && single_succ (new_dest) == EXIT_BLOCK_PTR
+ && bitmap_intersect_p (df_get_live_in (new_dest), merge_set))
+ {
+ regset return_regs;
+ unsigned int i;
+
+ return_regs = BITMAP_ALLOC (&reg_obstack);
+
+ /* Start off with the intersection of regs used to pass
+ params and regs used to return values. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (FUNCTION_ARG_REGNO_P (i)
+ && targetm.calls.function_value_regno_p (i))
+ bitmap_set_bit (return_regs, INCOMING_REGNO (i));
+
+ bitmap_and_into (return_regs, df_get_live_out (ENTRY_BLOCK_PTR));
+ bitmap_and_into (return_regs, df_get_live_in (EXIT_BLOCK_PTR));
+ if (!bitmap_empty_p (return_regs))
+ {
+ FOR_BB_INSNS_REVERSE (new_dest, insn)
+ if (NONDEBUG_INSN_P (insn))
+ {
+ df_ref *def_rec;
+ unsigned int uid = INSN_UID (insn);
+
+ /* If this insn sets any reg in return_regs.. */
+ for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
+ {
+ df_ref def = *def_rec;
+ unsigned r = DF_REF_REGNO (def);
+
+ if (bitmap_bit_p (return_regs, r))
+ break;
+ }
+ /* ..then add all reg uses to the set of regs
+ we're interested in. */
+ if (*def_rec)
+ df_simulate_uses (insn, return_regs);
+ }
+ if (bitmap_intersect_p (merge_set, return_regs))
+ {
+ BITMAP_FREE (return_regs);
+ BITMAP_FREE (merge_set);
+ return FALSE;
+ }
+ }
+ BITMAP_FREE (return_regs);
+ }
}
no_body:
diff --git a/gcc/input.c b/gcc/input.c
index e5e051f9eae..4077f9e5dbd 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -1,5 +1,5 @@
/* Data and functions related to line maps and input files.
- Copyright (C) 2004, 2007, 2008, 2009, 2010
+ Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -30,24 +30,118 @@ location_t input_location;
struct line_maps *line_table;
+/* Expand the source location LOC into a human readable location. If
+ LOC resolves to a builtin location, the file name of the readable
+ location is set to the string "<built-in>". */
+
expanded_location
expand_location (source_location loc)
{
expanded_location xloc;
+ const struct line_map *map;
+
+ loc = linemap_resolve_location (line_table, loc,
+ LRK_SPELLING_LOCATION, &map);
+ xloc = linemap_expand_location (line_table, map, loc);
+
if (loc <= BUILTINS_LOCATION)
- {
- xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
- xloc.line = 0;
- xloc.column = 0;
- xloc.sysp = 0;
- }
- else
- {
- const struct line_map *map = linemap_lookup (line_table, loc);
- xloc.file = map->to_file;
- xloc.line = SOURCE_LINE (map, loc);
- xloc.column = SOURCE_COLUMN (map, loc);
- xloc.sysp = map->sysp != 0;
- };
+ xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
+
return xloc;
}
+
+#define ONE_K 1024
+#define ONE_M (ONE_K * ONE_K)
+
+/* Display a number as an integer multiple of either:
+ - 1024, if said integer is >= to 10 K (in base 2)
+ - 1024 * 1024, if said integer is >= 10 M in (base 2)
+ */
+#define SCALE(x) ((unsigned long) ((x) < 10 * ONE_K \
+ ? (x) \
+ : ((x) < 10 * ONE_M \
+ ? (x) / ONE_K \
+ : (x) / ONE_M)))
+
+/* For a given integer, display either:
+ - the character 'k', if the number is higher than 10 K (in base 2)
+ but strictly lower than 10 M (in base 2)
+ - the character 'M' if the number is higher than 10 M (in base2)
+ - the charcter ' ' if the number is strictly lower than 10 K */
+#define STAT_LABEL(x) ((x) < 10 * ONE_K ? ' ' : ((x) < 10 * ONE_M ? 'k' : 'M'))
+
+/* Display an integer amount as multiple of 1K or 1M (in base 2).
+ Display the correct unit (either k, M, or ' ') after the amout, as
+ well. */
+#define FORMAT_AMOUNT(size) SCALE (size), STAT_LABEL (size)
+
+/* Dump statistics to stderr about the memory usage of the line_table
+ set of line maps. This also displays some statistics about macro
+ expansion. */
+
+void
+dump_line_table_statistics (void)
+{
+ struct linemap_stats s;
+ long total_used_map_size,
+ macro_maps_size,
+ total_allocated_map_size;
+
+ memset (&s, 0, sizeof (s));
+
+ linemap_get_statistics (line_table, &s);
+
+ macro_maps_size = s.macro_maps_used_size
+ + s.macro_maps_locations_size;
+
+ total_allocated_map_size = s.ordinary_maps_allocated_size
+ + s.macro_maps_allocated_size
+ + s.macro_maps_locations_size;
+
+ total_used_map_size = s.ordinary_maps_used_size
+ + s.macro_maps_used_size
+ + s.macro_maps_locations_size;
+
+ fprintf (stderr, "Number of expanded macros: %5ld\n",
+ s.num_expanded_macros);
+ if (s.num_expanded_macros != 0)
+ fprintf (stderr, "Average number of tokens per macro expansion: %5ld\n",
+ s.num_macro_tokens / s.num_expanded_macros);
+ fprintf (stderr,
+ "\nLine Table allocations during the "
+ "compilation process\n");
+ fprintf (stderr, "Number of ordinary maps used: %5ld%c\n",
+ SCALE (s.num_ordinary_maps_used),
+ STAT_LABEL (s.num_ordinary_maps_used));
+ fprintf (stderr, "Ordinary map used size: %5ld%c\n",
+ SCALE (s.ordinary_maps_used_size),
+ STAT_LABEL (s.ordinary_maps_used_size));
+ fprintf (stderr, "Number of ordinary maps allocated: %5ld%c\n",
+ SCALE (s.num_ordinary_maps_allocated),
+ STAT_LABEL (s.num_ordinary_maps_allocated));
+ fprintf (stderr, "Ordinary maps allocated size: %5ld%c\n",
+ SCALE (s.ordinary_maps_allocated_size),
+ STAT_LABEL (s.ordinary_maps_allocated_size));
+ fprintf (stderr, "Number of macro maps used: %5ld%c\n",
+ SCALE (s.num_macro_maps_used),
+ STAT_LABEL (s.num_macro_maps_used));
+ fprintf (stderr, "Macro maps used size: %5ld%c\n",
+ SCALE (s.macro_maps_used_size),
+ STAT_LABEL (s.macro_maps_used_size));
+ fprintf (stderr, "Macro maps locations size: %5ld%c\n",
+ SCALE (s.macro_maps_locations_size),
+ STAT_LABEL (s.macro_maps_locations_size));
+ fprintf (stderr, "Macro maps size: %5ld%c\n",
+ SCALE (macro_maps_size),
+ STAT_LABEL (macro_maps_size));
+ fprintf (stderr, "Duplicated maps locations size: %5ld%c\n",
+ SCALE (s.duplicated_macro_maps_locations_size),
+ STAT_LABEL (s.duplicated_macro_maps_locations_size));
+ fprintf (stderr, "Total allocated maps size: %5ld%c\n",
+ SCALE (total_allocated_map_size),
+ STAT_LABEL (total_allocated_map_size));
+ fprintf (stderr, "Total used maps size: %5ld%c\n",
+ SCALE (total_used_map_size),
+ STAT_LABEL (total_used_map_size));
+ fprintf (stderr, "\n");
+}
diff --git a/gcc/input.h b/gcc/input.h
index 59290642090..f2f351311fc 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -37,20 +37,6 @@ extern GTY(()) struct line_maps *line_table;
extern char builtins_location_check[(BUILTINS_LOCATION
< RESERVED_LOCATION_COUNT) ? 1 : -1];
-typedef struct
-{
- /* The name of the source file involved. */
- const char *file;
-
- /* The line-location in the source file. */
- int line;
-
- int column;
-
- /* In a system header?. */
- bool sysp;
-} expanded_location;
-
extern expanded_location expand_location (source_location);
/* Historically GCC used location_t, while cpp used source_location.
@@ -61,10 +47,14 @@ extern location_t input_location;
#define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
#define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
+#define LOCATION_COLUMN(LOC)((expand_location (LOC)).column)
#define input_line LOCATION_LINE (input_location)
#define input_filename LOCATION_FILE (input_location)
-#define in_system_header_at(LOC) ((expand_location (LOC)).sysp != 0)
+#define in_system_header_at(LOC) \
+ ((linemap_location_in_system_header_p (line_table, LOC)))
#define in_system_header (in_system_header_at (input_location))
+void dump_line_table_statistics (void);
+
#endif
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index f069914cf64..31c88e501e7 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -822,8 +822,10 @@ edge_badness (struct cgraph_edge *edge, bool dump)
/* Result must be integer in range 0...INT_MAX.
Set the base of fixed point calculation so we don't lose much of
precision for small bandesses (those are interesting) yet we don't
- overflow for growths that are still in interesting range. */
- badness = ((gcov_type)growth) * (1<<18);
+ overflow for growths that are still in interesting range.
+
+ Fixed point arithmetic with point at 8th bit. */
+ badness = ((gcov_type)growth) * (1<<(19+8));
badness = (badness + div / 2) / div;
/* Overall growth of inlining all calls of function matters: we want to
@@ -838,10 +840,14 @@ edge_badness (struct cgraph_edge *edge, bool dump)
We might mix the valud into the fraction by taking into account
relative growth of the unit, but for now just add the number
into resulting fraction. */
+ if (badness > INT_MAX / 2)
+ {
+ badness = INT_MAX / 2;
+ if (dump)
+ fprintf (dump_file, "Badness overflow\n");
+ }
growth_for_all = estimate_growth (callee);
badness += growth_for_all;
- if (badness > INT_MAX - 1)
- badness = INT_MAX - 1;
if (dump)
{
fprintf (dump_file,
@@ -1384,6 +1390,7 @@ inline_small_functions (void)
struct cgraph_node *where, *callee;
int badness = fibheap_min_key (heap);
int current_badness;
+ int cached_badness;
int growth;
edge = (struct cgraph_edge *) fibheap_extract_min (heap);
@@ -1392,16 +1399,18 @@ inline_small_functions (void)
if (!edge->inline_failed)
continue;
- /* Be sure that caches are maintained consistent. */
-#ifdef ENABLE_CHECKING
+ /* Be sure that caches are maintained consistent.
+ We can not make this ENABLE_CHECKING only because it cause differnt
+ updates of the fibheap queue. */
+ cached_badness = edge_badness (edge, false);
reset_edge_growth_cache (edge);
reset_node_growth_cache (edge->callee);
-#endif
/* When updating the edge costs, we only decrease badness in the keys.
Increases of badness are handled lazilly; when we see key with out
of date value on it, we re-insert it now. */
current_badness = edge_badness (edge, false);
+ gcc_assert (cached_badness == current_badness);
gcc_assert (current_badness >= badness);
if (current_badness != badness)
{
@@ -1512,8 +1521,13 @@ inline_small_functions (void)
/* We inlined last offline copy to the body. This might lead
to callees of function having fewer call sites and thus they
- may need updating. */
- if (callee->global.inlined_to)
+ may need updating.
+
+ FIXME: the callee size could also shrink because more information
+ is propagated from caller. We don't track when this happen and
+ thus we need to recompute everything all the time. Once this is
+ solved, "|| 1" should go away. */
+ if (callee->global.inlined_to || 1)
update_all_callee_keys (heap, callee, updated_nodes);
else
update_callee_keys (heap, edge->callee, updated_nodes);
@@ -1935,6 +1949,8 @@ early_inliner (void)
= estimate_num_insns (edge->call_stmt, &eni_size_weights);
es->call_stmt_time
= estimate_num_insns (edge->call_stmt, &eni_time_weights);
+ edge->call_stmt_cannot_inline_p
+ = gimple_call_cannot_inline_p (edge->call_stmt);
}
timevar_pop (TV_INTEGRATION);
iterations++;
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 54ba4178020..e624426d698 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -419,31 +419,154 @@ detect_type_change_ssa (tree arg, gimple call, struct ipa_jump_func *jfunc)
return detect_type_change (arg, arg, call, jfunc, 0);
}
+/* Callback of walk_aliased_vdefs. Flags that it has been invoked to the
+ boolean variable pointed to by DATA. */
+
+static bool
+mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
+ void *data)
+{
+ bool *b = (bool *) data;
+ *b = true;
+ return true;
+}
+
+/* Return true if the formal parameter PARM might have been modified in this
+ function before reaching the statement STMT. PARM_AINFO is a pointer to a
+ structure containing temporary information about PARM. */
+
+static bool
+is_parm_modified_before_stmt (struct param_analysis_info *parm_ainfo,
+ gimple stmt, tree parm)
+{
+ bool modified = false;
+ ao_ref refd;
+
+ if (parm_ainfo->modified)
+ return true;
+
+ gcc_checking_assert (gimple_vuse (stmt) != NULL_TREE);
+ ao_ref_init (&refd, parm);
+ walk_aliased_vdefs (&refd, gimple_vuse (stmt), mark_modified,
+ &modified, &parm_ainfo->visited_statements);
+ if (modified)
+ {
+ parm_ainfo->modified = true;
+ return true;
+ }
+ return false;
+}
+
+/* If STMT is an assignment that loads a value from an parameter declaration,
+ return the index of the parameter in ipa_node_params which has not been
+ modified. Otherwise return -1. */
+
+static int
+load_from_unmodified_param (struct ipa_node_params *info,
+ struct param_analysis_info *parms_ainfo,
+ gimple stmt)
+{
+ int index;
+ tree op1;
+
+ if (!gimple_assign_single_p (stmt))
+ return -1;
+
+ op1 = gimple_assign_rhs1 (stmt);
+ if (TREE_CODE (op1) != PARM_DECL)
+ return -1;
+
+ index = ipa_get_param_decl_index (info, op1);
+ if (index < 0
+ || is_parm_modified_before_stmt (&parms_ainfo[index], stmt, op1))
+ return -1;
+
+ return index;
+}
/* Given that an actual argument is an SSA_NAME (given in NAME) and is a result
- of an assignment statement STMT, try to find out whether NAME can be
- described by a (possibly polynomial) pass-through jump-function or an
- ancestor jump function and if so, write the appropriate function into
- JFUNC */
+ of an assignment statement STMT, try to determine whether we are actually
+ handling any of the following cases and construct an appropriate jump
+ function into JFUNC if so:
+
+ 1) The passed value is loaded from a formal parameter which is not a gimple
+ register (most probably because it is addressable, the value has to be
+ scalar) and we can guarantee the value has not changed. This case can
+ therefore be described by a simple pass-through jump function. For example:
+
+ foo (int a)
+ {
+ int a.0;
+
+ a.0_2 = a;
+ bar (a.0_2);
+
+ 2) The passed value can be described by a simple arithmetic pass-through
+ jump function. E.g.
+
+ foo (int a)
+ {
+ int D.2064;
+
+ D.2064_4 = a.1(D) + 4;
+ bar (D.2064_4);
+
+ This case can also occur in combination of the previous one, e.g.:
+
+ foo (int a, int z)
+ {
+ int a.0;
+ int D.2064;
+
+ a.0_3 = a;
+ D.2064_4 = a.0_3 + 4;
+ foo (D.2064_4);
+
+ 3) The passed value is an address of an object within another one (which
+ also passed by reference). Such situations are described by an ancestor
+ jump function and describe situations such as:
+
+ B::foo() (struct B * const this)
+ {
+ struct A * D.1845;
+
+ D.1845_2 = &this_1(D)->D.1748;
+ A::bar (D.1845_2);
+
+ INFO is the structure describing individual parameters access different
+ stages of IPA optimizations. PARMS_AINFO contains the information that is
+ only needed for intraprocedural analysis. */
static void
compute_complex_assign_jump_func (struct ipa_node_params *info,
+ struct param_analysis_info *parms_ainfo,
struct ipa_jump_func *jfunc,
gimple call, gimple stmt, tree name)
{
HOST_WIDE_INT offset, size, max_size;
- tree op1, op2, base, ssa;
+ tree op1, tc_ssa, base, ssa;
int index;
op1 = gimple_assign_rhs1 (stmt);
- op2 = gimple_assign_rhs2 (stmt);
- if (TREE_CODE (op1) == SSA_NAME
- && SSA_NAME_IS_DEFAULT_DEF (op1))
+ if (TREE_CODE (op1) == SSA_NAME)
{
- index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1));
- if (index < 0)
- return;
+ if (SSA_NAME_IS_DEFAULT_DEF (op1))
+ index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1));
+ else
+ index = load_from_unmodified_param (info, parms_ainfo,
+ SSA_NAME_DEF_STMT (op1));
+ tc_ssa = op1;
+ }
+ else
+ {
+ index = load_from_unmodified_param (info, parms_ainfo, stmt);
+ tc_ssa = gimple_assign_lhs (stmt);
+ }
+
+ if (index >= 0)
+ {
+ tree op2 = gimple_assign_rhs2 (stmt);
if (op2)
{
@@ -458,8 +581,8 @@ compute_complex_assign_jump_func (struct ipa_node_params *info,
jfunc->value.pass_through.operation = gimple_assign_rhs_code (stmt);
jfunc->value.pass_through.operand = op2;
}
- else if (gimple_assign_unary_nop_p (stmt)
- && !detect_type_change_ssa (op1, call, jfunc))
+ else if (gimple_assign_single_p (stmt)
+ && !detect_type_change_ssa (tc_ssa, call, jfunc))
{
jfunc->type = IPA_JF_PASS_THROUGH;
jfunc->value.pass_through.formal_id = index;
@@ -665,12 +788,14 @@ compute_known_type_jump_func (tree op, struct ipa_jump_func *jfunc,
/* Determine the jump functions of scalar arguments. Scalar means SSA names
and constants of a number of selected types. INFO is the ipa_node_params
- structure associated with the caller, FUNCTIONS is a pointer to an array of
- jump function structures associated with CALL which is the call statement
- being examined.*/
+ structure associated with the caller, PARMS_AINFO describes state of
+ analysis with respect to individual formal parameters. ARGS is the
+ ipa_edge_args structure describing the callsite CALL which is the call
+ statement being examined.*/
static void
compute_scalar_jump_functions (struct ipa_node_params *info,
+ struct param_analysis_info *parms_ainfo,
struct ipa_edge_args *args,
gimple call)
{
@@ -705,7 +830,8 @@ compute_scalar_jump_functions (struct ipa_node_params *info,
{
gimple stmt = SSA_NAME_DEF_STMT (arg);
if (is_gimple_assign (stmt))
- compute_complex_assign_jump_func (info, jfunc, call, stmt, arg);
+ compute_complex_assign_jump_func (info, parms_ainfo, jfunc,
+ call, stmt, arg);
else if (gimple_code (stmt) == GIMPLE_PHI)
compute_complex_ancestor_jump_func (info, jfunc, call, stmt);
}
@@ -748,43 +874,6 @@ type_like_member_ptr_p (tree type, tree *method_ptr, tree *delta)
return true;
}
-/* Callback of walk_aliased_vdefs. Flags that it has been invoked to the
- boolean variable pointed to by DATA. */
-
-static bool
-mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
- void *data)
-{
- bool *b = (bool *) data;
- *b = true;
- return true;
-}
-
-/* Return true if the formal parameter PARM might have been modified in this
- function before reaching the statement CALL. PARM_INFO is a pointer to a
- structure containing intermediate information about PARM. */
-
-static bool
-is_parm_modified_before_call (struct param_analysis_info *parm_info,
- gimple call, tree parm)
-{
- bool modified = false;
- ao_ref refd;
-
- if (parm_info->modified)
- return true;
-
- ao_ref_init (&refd, parm);
- walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
- &modified, &parm_info->visited_statements);
- if (modified)
- {
- parm_info->modified = true;
- return true;
- }
- return false;
-}
-
/* Go through arguments of the CALL and for every one that looks like a member
pointer, check whether it can be safely declared pass-through and if so,
mark that to the corresponding item of jump FUNCTIONS. Return true iff
@@ -794,7 +883,7 @@ is_parm_modified_before_call (struct param_analysis_info *parm_info,
static bool
compute_pass_through_member_ptrs (struct ipa_node_params *info,
- struct param_analysis_info *parms_info,
+ struct param_analysis_info *parms_ainfo,
struct ipa_edge_args *args,
gimple call)
{
@@ -813,7 +902,8 @@ compute_pass_through_member_ptrs (struct ipa_node_params *info,
int index = ipa_get_param_decl_index (info, arg);
gcc_assert (index >=0);
- if (!is_parm_modified_before_call (&parms_info[index], call, arg))
+ if (!is_parm_modified_before_stmt (&parms_ainfo[index], call,
+ arg))
{
struct ipa_jump_func *jfunc = ipa_get_ith_jump_func (args,
num);
@@ -968,7 +1058,7 @@ compute_cst_member_ptr_arguments (struct ipa_edge_args *args,
to this callsite. */
static void
-ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_info,
+ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_ainfo,
struct cgraph_edge *cs)
{
struct ipa_node_params *info = IPA_NODE_REF (cs->caller);
@@ -981,11 +1071,11 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_info,
VEC_safe_grow_cleared (ipa_jump_func_t, gc, args->jump_functions, arg_num);
/* We will deal with constants and SSA scalars first: */
- compute_scalar_jump_functions (info, args, call);
+ compute_scalar_jump_functions (info, parms_ainfo, args, call);
/* Let's check whether there are any potential member pointers and if so,
whether we can determine their functions as pass_through. */
- if (!compute_pass_through_member_ptrs (info, parms_info, args, call))
+ if (!compute_pass_through_member_ptrs (info, parms_ainfo, args, call))
return;
/* Finally, let's check whether we actually pass a new constant member
@@ -998,7 +1088,7 @@ ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_info,
static void
ipa_compute_jump_functions (struct cgraph_node *node,
- struct param_analysis_info *parms_info)
+ struct param_analysis_info *parms_ainfo)
{
struct cgraph_edge *cs;
@@ -1010,11 +1100,11 @@ ipa_compute_jump_functions (struct cgraph_node *node,
functions unless they may become known during lto/whopr. */
if (!callee->analyzed && !flag_lto)
continue;
- ipa_compute_jump_functions_for_edge (parms_info, cs);
+ ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
}
for (cs = node->indirect_calls; cs; cs = cs->next_callee)
- ipa_compute_jump_functions_for_edge (parms_info, cs);
+ ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
}
/* If RHS looks like a rhs of a statement loading pfn from a member
@@ -1111,7 +1201,7 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt)
}
/* Analyze the CALL and examine uses of formal parameters of the caller NODE
- (described by INFO). PARMS_INFO is a pointer to a vector containing
+ (described by INFO). PARMS_AINFO is a pointer to a vector containing
intermediate information about each formal parameter. Currently it checks
whether the call calls a pointer that is a formal parameter and if so, the
parameter is marked with the called flag and an indirect call graph edge
@@ -1170,7 +1260,7 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt)
static void
ipa_analyze_indirect_call_uses (struct cgraph_node *node,
struct ipa_node_params *info,
- struct param_analysis_info *parms_info,
+ struct param_analysis_info *parms_ainfo,
gimple call, tree target)
{
gimple def;
@@ -1283,7 +1373,7 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
return;
index = ipa_get_param_decl_index (info, rec);
- if (index >= 0 && !is_parm_modified_before_call (&parms_info[index],
+ if (index >= 0 && !is_parm_modified_before_stmt (&parms_ainfo[index],
call, rec))
ipa_note_param_call (node, index, call);
@@ -1347,20 +1437,20 @@ ipa_analyze_virtual_call_uses (struct cgraph_node *node,
}
/* Analyze a call statement CALL whether and how it utilizes formal parameters
- of the caller (described by INFO). PARMS_INFO is a pointer to a vector
+ of the caller (described by INFO). PARMS_AINFO is a pointer to a vector
containing intermediate information about each formal parameter. */
static void
ipa_analyze_call_uses (struct cgraph_node *node,
struct ipa_node_params *info,
- struct param_analysis_info *parms_info, gimple call)
+ struct param_analysis_info *parms_ainfo, gimple call)
{
tree target = gimple_call_fn (call);
if (!target)
return;
if (TREE_CODE (target) == SSA_NAME)
- ipa_analyze_indirect_call_uses (node, info, parms_info, call, target);
+ ipa_analyze_indirect_call_uses (node, info, parms_ainfo, call, target);
else if (TREE_CODE (target) == OBJ_TYPE_REF)
ipa_analyze_virtual_call_uses (node, info, call, target);
}
@@ -1368,15 +1458,15 @@ ipa_analyze_call_uses (struct cgraph_node *node,
/* Analyze the call statement STMT with respect to formal parameters (described
in INFO) of caller given by NODE. Currently it only checks whether formal
- parameters are called. PARMS_INFO is a pointer to a vector containing
+ parameters are called. PARMS_AINFO is a pointer to a vector containing
intermediate information about each formal parameter. */
static void
ipa_analyze_stmt_uses (struct cgraph_node *node, struct ipa_node_params *info,
- struct param_analysis_info *parms_info, gimple stmt)
+ struct param_analysis_info *parms_ainfo, gimple stmt)
{
if (is_gimple_call (stmt))
- ipa_analyze_call_uses (node, info, parms_info, stmt);
+ ipa_analyze_call_uses (node, info, parms_ainfo, stmt);
}
/* Callback of walk_stmt_load_store_addr_ops for the visit_load.
@@ -1403,12 +1493,12 @@ visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
/* Scan the function body of NODE and inspect the uses of formal parameters.
Store the findings in various structures of the associated ipa_node_params
- structure, such as parameter flags, notes etc. PARMS_INFO is a pointer to a
+ structure, such as parameter flags, notes etc. PARMS_AINFO is a pointer to a
vector containing intermediate information about each formal parameter. */
static void
ipa_analyze_params_uses (struct cgraph_node *node,
- struct param_analysis_info *parms_info)
+ struct param_analysis_info *parms_ainfo)
{
tree decl = node->decl;
basic_block bb;
@@ -1440,7 +1530,7 @@ ipa_analyze_params_uses (struct cgraph_node *node,
if (is_gimple_debug (stmt))
continue;
- ipa_analyze_stmt_uses (node, info, parms_info, stmt);
+ ipa_analyze_stmt_uses (node, info, parms_ainfo, stmt);
walk_stmt_load_store_addr_ops (stmt, info,
visit_ref_for_mod_analysis,
visit_ref_for_mod_analysis,
@@ -1464,7 +1554,7 @@ void
ipa_analyze_node (struct cgraph_node *node)
{
struct ipa_node_params *info;
- struct param_analysis_info *parms_info;
+ struct param_analysis_info *parms_ainfo;
int i, param_count;
ipa_check_create_node_params ();
@@ -1475,15 +1565,15 @@ ipa_analyze_node (struct cgraph_node *node)
ipa_initialize_node_params (node);
param_count = ipa_get_param_count (info);
- parms_info = XALLOCAVEC (struct param_analysis_info, param_count);
- memset (parms_info, 0, sizeof (struct param_analysis_info) * param_count);
+ parms_ainfo = XALLOCAVEC (struct param_analysis_info, param_count);
+ memset (parms_ainfo, 0, sizeof (struct param_analysis_info) * param_count);
- ipa_analyze_params_uses (node, parms_info);
- ipa_compute_jump_functions (node, parms_info);
+ ipa_analyze_params_uses (node, parms_ainfo);
+ ipa_compute_jump_functions (node, parms_ainfo);
for (i = 0; i < param_count; i++)
- if (parms_info[i].visited_statements)
- BITMAP_FREE (parms_info[i].visited_statements);
+ if (parms_ainfo[i].visited_statements)
+ BITMAP_FREE (parms_ainfo[i].visited_statements);
current_function_decl = NULL;
pop_cfun ();
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index d1861e9ed54..7e0769fb592 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -958,7 +958,6 @@ split_function (struct split_point *split_point)
tree retval = NULL, real_retval = NULL;
bool split_part_return_p = false;
gimple last_stmt = NULL;
- bool conv_needed = false;
unsigned int i;
tree arg;
@@ -1000,12 +999,8 @@ split_function (struct split_point *split_point)
else
arg = parm;
- if (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm))
- != TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
- {
- conv_needed = true;
- arg = fold_convert (DECL_ARG_TYPE (parm), arg);
- }
+ if (!useless_type_conversion_p (DECL_ARG_TYPE (parm), TREE_TYPE (arg)))
+ arg = fold_convert (DECL_ARG_TYPE (parm), arg);
VEC_safe_push (tree, heap, args_to_pass, arg);
}
@@ -1135,14 +1130,13 @@ split_function (struct split_point *split_point)
/* Produce the call statement. */
gsi = gsi_last_bb (call_bb);
- if (conv_needed)
- FOR_EACH_VEC_ELT (tree, args_to_pass, i, arg)
- if (!is_gimple_val (arg))
- {
- arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
- false, GSI_NEW_STMT);
- VEC_replace (tree, args_to_pass, i, arg);
- }
+ FOR_EACH_VEC_ELT (tree, args_to_pass, i, arg)
+ if (!is_gimple_val (arg))
+ {
+ arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
+ false, GSI_CONTINUE_LINKING);
+ VEC_replace (tree, args_to_pass, i, arg);
+ }
call = gimple_build_call_vec (node->decl, args_to_pass);
gimple_set_block (call, DECL_INITIAL (current_function_decl));
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index dfb6500541c..715d1f5885c 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,12 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Make-lang.in (jvspec.o): Pass SHLIB instead of SHLIB_LINK.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * jcf-parse.c (set_source_filename): Adjust to the new map API.
+
2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
* class.c (build_static_field_ref): Delete old interface with two
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
index 1d9fd2b2988..4d6b63b3708 100644
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -58,7 +58,7 @@ JAVA_TARGET_INDEPENDENT_BIN_TOOLS = jcf-dump
jvspec.o: $(srcdir)/java/jvspec.c $(SYSTEM_H) coretypes.h $(TM_H) \
$(GCC_H) $(CONFIG_H) java/jcf.h java/javaop.h $(OPTS_H)
- (SHLIB_LINK='$(SHLIB_LINK)'; \
+ (SHLIB='$(SHLIB)'; \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
$(INCLUDES) $(srcdir)/java/jvspec.c $(OUTPUT_OPTION))
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index 37cea2870a8..04c04f575cf 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -355,7 +355,7 @@ set_source_filename (JCF *jcf, int index)
}
sfname = find_sourcefile (sfname);
- line_table->maps[line_table->used-1].to_file = sfname;
+ ORDINARY_MAP_FILE_NAME (LINEMAPS_LAST_ORDINARY_MAP (line_table)) = sfname;
if (current_class == main_class) main_input_filename = sfname;
}
diff --git a/gcc/jump.c b/gcc/jump.c
index 0273adf4af6..f852f827729 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1086,6 +1086,7 @@ mark_jump_label_1 (rtx x, rtx insn, bool in_mem, bool is_target)
return;
case RETURN:
+ case SIMPLE_RETURN:
if (is_target)
{
gcc_assert (JUMP_LABEL (insn) == NULL || JUMP_LABEL (insn) == x);
@@ -1408,7 +1409,7 @@ redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
int i;
const char *fmt;
- if ((code == LABEL_REF && XEXP (x, 0) == olabel)
+ if ((code == LABEL_REF && XEXP (x, 0) == olabel)
|| x == olabel)
{
x = redirect_target (nlabel);
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c
deleted file mode 100644
index 57c40c5800f..00000000000
--- a/gcc/libgcc2.c
+++ /dev/null
@@ -1,2252 +0,0 @@
-/* More subroutines needed by GCC output code on some machines. */
-/* Compile this one with gcc. */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
- 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 3, 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.
-
-Under Section 7 of GPL version 3, you are granted additional
-permissions described in the GCC Runtime Library Exception, version
-3.1, as published by the Free Software Foundation.
-
-You should have received a copy of the GNU General Public License and
-a copy of the GCC Runtime Library Exception along with this program;
-see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-<http://www.gnu.org/licenses/>. */
-
-#include "tconfig.h"
-#include "tsystem.h"
-#include "coretypes.h"
-#include "tm.h"
-
-#ifdef HAVE_GAS_HIDDEN
-#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
-#else
-#define ATTRIBUTE_HIDDEN
-#endif
-
-/* Work out the largest "word" size that we can deal with on this target. */
-#if MIN_UNITS_PER_WORD > 4
-# define LIBGCC2_MAX_UNITS_PER_WORD 8
-#elif (MIN_UNITS_PER_WORD > 2 \
- || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4))
-# define LIBGCC2_MAX_UNITS_PER_WORD 4
-#else
-# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
-#endif
-
-/* Work out what word size we are using for this compilation.
- The value can be set on the command line. */
-#ifndef LIBGCC2_UNITS_PER_WORD
-#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
-#endif
-
-#if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD
-
-#include "libgcc2.h"
-
-#ifdef DECLARE_LIBRARY_RENAMES
- DECLARE_LIBRARY_RENAMES
-#endif
-
-#if defined (L_negdi2)
-DWtype
-__negdi2 (DWtype u)
-{
- const DWunion uu = {.ll = u};
- const DWunion w = { {.low = -uu.s.low,
- .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } };
-
- return w.ll;
-}
-#endif
-
-#ifdef L_addvsi3
-Wtype
-__addvSI3 (Wtype a, Wtype b)
-{
- const Wtype w = (UWtype) a + (UWtype) b;
-
- if (b >= 0 ? w < a : w > a)
- abort ();
-
- return w;
-}
-#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
-SItype
-__addvsi3 (SItype a, SItype b)
-{
- const SItype w = (USItype) a + (USItype) b;
-
- if (b >= 0 ? w < a : w > a)
- abort ();
-
- return w;
-}
-#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
-#endif
-
-#ifdef L_addvdi3
-DWtype
-__addvDI3 (DWtype a, DWtype b)
-{
- const DWtype w = (UDWtype) a + (UDWtype) b;
-
- if (b >= 0 ? w < a : w > a)
- abort ();
-
- return w;
-}
-#endif
-
-#ifdef L_subvsi3
-Wtype
-__subvSI3 (Wtype a, Wtype b)
-{
- const Wtype w = (UWtype) a - (UWtype) b;
-
- if (b >= 0 ? w > a : w < a)
- abort ();
-
- return w;
-}
-#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
-SItype
-__subvsi3 (SItype a, SItype b)
-{
- const SItype w = (USItype) a - (USItype) b;
-
- if (b >= 0 ? w > a : w < a)
- abort ();
-
- return w;
-}
-#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
-#endif
-
-#ifdef L_subvdi3
-DWtype
-__subvDI3 (DWtype a, DWtype b)
-{
- const DWtype w = (UDWtype) a - (UDWtype) b;
-
- if (b >= 0 ? w > a : w < a)
- abort ();
-
- return w;
-}
-#endif
-
-#ifdef L_mulvsi3
-Wtype
-__mulvSI3 (Wtype a, Wtype b)
-{
- const DWtype w = (DWtype) a * (DWtype) b;
-
- if ((Wtype) (w >> W_TYPE_SIZE) != (Wtype) w >> (W_TYPE_SIZE - 1))
- abort ();
-
- return w;
-}
-#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
-#undef WORD_SIZE
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-SItype
-__mulvsi3 (SItype a, SItype b)
-{
- const DItype w = (DItype) a * (DItype) b;
-
- if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1))
- abort ();
-
- return w;
-}
-#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
-#endif
-
-#ifdef L_negvsi2
-Wtype
-__negvSI2 (Wtype a)
-{
- const Wtype w = -(UWtype) a;
-
- if (a >= 0 ? w > 0 : w < 0)
- abort ();
-
- return w;
-}
-#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
-SItype
-__negvsi2 (SItype a)
-{
- const SItype w = -(USItype) a;
-
- if (a >= 0 ? w > 0 : w < 0)
- abort ();
-
- return w;
-}
-#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
-#endif
-
-#ifdef L_negvdi2
-DWtype
-__negvDI2 (DWtype a)
-{
- const DWtype w = -(UDWtype) a;
-
- if (a >= 0 ? w > 0 : w < 0)
- abort ();
-
- return w;
-}
-#endif
-
-#ifdef L_absvsi2
-Wtype
-__absvSI2 (Wtype a)
-{
- Wtype w = a;
-
- if (a < 0)
-#ifdef L_negvsi2
- w = __negvSI2 (a);
-#else
- w = -(UWtype) a;
-
- if (w < 0)
- abort ();
-#endif
-
- return w;
-}
-#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
-SItype
-__absvsi2 (SItype a)
-{
- SItype w = a;
-
- if (a < 0)
-#ifdef L_negvsi2
- w = __negvsi2 (a);
-#else
- w = -(USItype) a;
-
- if (w < 0)
- abort ();
-#endif
-
- return w;
-}
-#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
-#endif
-
-#ifdef L_absvdi2
-DWtype
-__absvDI2 (DWtype a)
-{
- DWtype w = a;
-
- if (a < 0)
-#ifdef L_negvdi2
- w = __negvDI2 (a);
-#else
- w = -(UDWtype) a;
-
- if (w < 0)
- abort ();
-#endif
-
- return w;
-}
-#endif
-
-#ifdef L_mulvdi3
-DWtype
-__mulvDI3 (DWtype u, DWtype v)
-{
- /* The unchecked multiplication needs 3 Wtype x Wtype multiplications,
- but the checked multiplication needs only two. */
- const DWunion uu = {.ll = u};
- const DWunion vv = {.ll = v};
-
- if (__builtin_expect (uu.s.high == uu.s.low >> (W_TYPE_SIZE - 1), 1))
- {
- /* u fits in a single Wtype. */
- if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
- {
- /* v fits in a single Wtype as well. */
- /* A single multiplication. No overflow risk. */
- return (DWtype) uu.s.low * (DWtype) vv.s.low;
- }
- else
- {
- /* Two multiplications. */
- DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
- * (UDWtype) (UWtype) vv.s.low};
- DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.low
- * (UDWtype) (UWtype) vv.s.high};
-
- if (vv.s.high < 0)
- w1.s.high -= uu.s.low;
- if (uu.s.low < 0)
- w1.ll -= vv.ll;
- w1.ll += (UWtype) w0.s.high;
- if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
- {
- w0.s.high = w1.s.low;
- return w0.ll;
- }
- }
- }
- else
- {
- if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
- {
- /* v fits into a single Wtype. */
- /* Two multiplications. */
- DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
- * (UDWtype) (UWtype) vv.s.low};
- DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.high
- * (UDWtype) (UWtype) vv.s.low};
-
- if (uu.s.high < 0)
- w1.s.high -= vv.s.low;
- if (vv.s.low < 0)
- w1.ll -= uu.ll;
- w1.ll += (UWtype) w0.s.high;
- if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
- {
- w0.s.high = w1.s.low;
- return w0.ll;
- }
- }
- else
- {
- /* A few sign checks and a single multiplication. */
- if (uu.s.high >= 0)
- {
- if (vv.s.high >= 0)
- {
- if (uu.s.high == 0 && vv.s.high == 0)
- {
- const DWtype w = (UDWtype) (UWtype) uu.s.low
- * (UDWtype) (UWtype) vv.s.low;
- if (__builtin_expect (w >= 0, 1))
- return w;
- }
- }
- else
- {
- if (uu.s.high == 0 && vv.s.high == (Wtype) -1)
- {
- DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
- * (UDWtype) (UWtype) vv.s.low};
-
- ww.s.high -= uu.s.low;
- if (__builtin_expect (ww.s.high < 0, 1))
- return ww.ll;
- }
- }
- }
- else
- {
- if (vv.s.high >= 0)
- {
- if (uu.s.high == (Wtype) -1 && vv.s.high == 0)
- {
- DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
- * (UDWtype) (UWtype) vv.s.low};
-
- ww.s.high -= vv.s.low;
- if (__builtin_expect (ww.s.high < 0, 1))
- return ww.ll;
- }
- }
- else
- {
- if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1)
- {
- DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
- * (UDWtype) (UWtype) vv.s.low};
-
- ww.s.high -= uu.s.low;
- ww.s.high -= vv.s.low;
- if (__builtin_expect (ww.s.high >= 0, 1))
- return ww.ll;
- }
- }
- }
- }
- }
-
- /* Overflow. */
- abort ();
-}
-#endif
-
-
-/* Unless shift functions are defined with full ANSI prototypes,
- parameter b will be promoted to int if shift_count_type is smaller than an int. */
-#ifdef L_lshrdi3
-DWtype
-__lshrdi3 (DWtype u, shift_count_type b)
-{
- if (b == 0)
- return u;
-
- const DWunion uu = {.ll = u};
- const shift_count_type bm = W_TYPE_SIZE - b;
- DWunion w;
-
- if (bm <= 0)
- {
- w.s.high = 0;
- w.s.low = (UWtype) uu.s.high >> -bm;
- }
- else
- {
- const UWtype carries = (UWtype) uu.s.high << bm;
-
- w.s.high = (UWtype) uu.s.high >> b;
- w.s.low = ((UWtype) uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
-#endif
-
-#ifdef L_ashldi3
-DWtype
-__ashldi3 (DWtype u, shift_count_type b)
-{
- if (b == 0)
- return u;
-
- const DWunion uu = {.ll = u};
- const shift_count_type bm = W_TYPE_SIZE - b;
- DWunion w;
-
- if (bm <= 0)
- {
- w.s.low = 0;
- w.s.high = (UWtype) uu.s.low << -bm;
- }
- else
- {
- const UWtype carries = (UWtype) uu.s.low >> bm;
-
- w.s.low = (UWtype) uu.s.low << b;
- w.s.high = ((UWtype) uu.s.high << b) | carries;
- }
-
- return w.ll;
-}
-#endif
-
-#ifdef L_ashrdi3
-DWtype
-__ashrdi3 (DWtype u, shift_count_type b)
-{
- if (b == 0)
- return u;
-
- const DWunion uu = {.ll = u};
- const shift_count_type bm = W_TYPE_SIZE - b;
- DWunion w;
-
- if (bm <= 0)
- {
- /* w.s.high = 1..1 or 0..0 */
- w.s.high = uu.s.high >> (W_TYPE_SIZE - 1);
- w.s.low = uu.s.high >> -bm;
- }
- else
- {
- const UWtype carries = (UWtype) uu.s.high << bm;
-
- w.s.high = uu.s.high >> b;
- w.s.low = ((UWtype) uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
-#endif
-
-#ifdef L_bswapsi2
-SItype
-__bswapsi2 (SItype u)
-{
- return ((((u) & 0xff000000) >> 24)
- | (((u) & 0x00ff0000) >> 8)
- | (((u) & 0x0000ff00) << 8)
- | (((u) & 0x000000ff) << 24));
-}
-#endif
-#ifdef L_bswapdi2
-DItype
-__bswapdi2 (DItype u)
-{
- return ((((u) & 0xff00000000000000ull) >> 56)
- | (((u) & 0x00ff000000000000ull) >> 40)
- | (((u) & 0x0000ff0000000000ull) >> 24)
- | (((u) & 0x000000ff00000000ull) >> 8)
- | (((u) & 0x00000000ff000000ull) << 8)
- | (((u) & 0x0000000000ff0000ull) << 24)
- | (((u) & 0x000000000000ff00ull) << 40)
- | (((u) & 0x00000000000000ffull) << 56));
-}
-#endif
-#ifdef L_ffssi2
-#undef int
-int
-__ffsSI2 (UWtype u)
-{
- UWtype count;
-
- if (u == 0)
- return 0;
-
- count_trailing_zeros (count, u);
- return count + 1;
-}
-#endif
-
-#ifdef L_ffsdi2
-#undef int
-int
-__ffsDI2 (DWtype u)
-{
- const DWunion uu = {.ll = u};
- UWtype word, count, add;
-
- if (uu.s.low != 0)
- word = uu.s.low, add = 0;
- else if (uu.s.high != 0)
- word = uu.s.high, add = W_TYPE_SIZE;
- else
- return 0;
-
- count_trailing_zeros (count, word);
- return count + add + 1;
-}
-#endif
-
-#ifdef L_muldi3
-DWtype
-__muldi3 (DWtype u, DWtype v)
-{
- const DWunion uu = {.ll = u};
- const DWunion vv = {.ll = v};
- DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)};
-
- w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
- + (UWtype) uu.s.high * (UWtype) vv.s.low);
-
- return w.ll;
-}
-#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)
-{
- UWtype q, r;
- UWtype c0, c1, b1;
-
- if ((Wtype) d >= 0)
- {
- if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
- {
- /* Dividend, divisor, and quotient are nonnegative. */
- sdiv_qrnnd (q, r, a1, a0, d);
- }
- else
- {
- /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d. */
- sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
- /* Divide (c1*2^32 + c0) by d. */
- sdiv_qrnnd (q, r, c1, c0, d);
- /* Add 2^31 to quotient. */
- q += (UWtype) 1 << (W_TYPE_SIZE - 1);
- }
- }
- else
- {
- b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
- c1 = a1 >> 1; /* A/2 */
- c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
-
- if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
- {
- sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
-
- r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
- if ((d & 1) != 0)
- {
- if (r >= q)
- r = r - q;
- else if (q - r <= d)
- {
- r = r - q + d;
- q--;
- }
- else
- {
- r = r - q + 2*d;
- q -= 2;
- }
- }
- }
- else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
- {
- c1 = (b1 - 1) - c1;
- c0 = ~c0; /* logical NOT */
-
- sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
-
- q = ~q; /* (A/2)/b1 */
- r = (b1 - 1) - r;
-
- r = 2*r + (a0 & 1); /* A/(2*b1) */
-
- if ((d & 1) != 0)
- {
- if (r >= q)
- r = r - q;
- else if (q - r <= d)
- {
- r = r - q + d;
- q--;
- }
- else
- {
- r = r - q + 2*d;
- q -= 2;
- }
- }
- }
- else /* Implies c1 = b1 */
- { /* Hence a1 = d - 1 = 2*b1 - 1 */
- if (a0 >= -d)
- {
- q = -1;
- r = a0 + d;
- }
- else
- {
- q = -2;
- r = a0 + 2*d;
- }
- }
- }
-
- *rp = r;
- return q;
-}
-#else
-/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
-UWtype
-__udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
- UWtype a1 __attribute__ ((__unused__)),
- UWtype a0 __attribute__ ((__unused__)),
- UWtype d __attribute__ ((__unused__)))
-{
- return 0;
-}
-#endif
-#endif
-
-#if (defined (L_udivdi3) || defined (L_divdi3) || \
- defined (L_umoddi3) || defined (L_moddi3))
-#define L_udivmoddi4
-#endif
-
-#ifdef L_clz
-const UQItype __clz_tab[256] =
-{
- 0,1,2,2,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,
- 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,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,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
-};
-#endif
-
-#ifdef L_clzsi2
-#undef int
-int
-__clzSI2 (UWtype x)
-{
- Wtype ret;
-
- count_leading_zeros (ret, x);
-
- return ret;
-}
-#endif
-
-#ifdef L_clzdi2
-#undef int
-int
-__clzDI2 (UDWtype x)
-{
- const DWunion uu = {.ll = x};
- UWtype word;
- Wtype ret, add;
-
- if (uu.s.high)
- word = uu.s.high, add = 0;
- else
- word = uu.s.low, add = W_TYPE_SIZE;
-
- count_leading_zeros (ret, word);
- return ret + add;
-}
-#endif
-
-#ifdef L_ctzsi2
-#undef int
-int
-__ctzSI2 (UWtype x)
-{
- Wtype ret;
-
- count_trailing_zeros (ret, x);
-
- return ret;
-}
-#endif
-
-#ifdef L_ctzdi2
-#undef int
-int
-__ctzDI2 (UDWtype x)
-{
- const DWunion uu = {.ll = x};
- UWtype word;
- Wtype ret, add;
-
- if (uu.s.low)
- word = uu.s.low, add = 0;
- else
- word = uu.s.high, add = W_TYPE_SIZE;
-
- count_trailing_zeros (ret, word);
- return ret + add;
-}
-#endif
-
-#ifdef L_clrsbsi2
-#undef int
-int
-__clrsbSI2 (Wtype x)
-{
- Wtype ret;
-
- if (x < 0)
- x = ~x;
- if (x == 0)
- return W_TYPE_SIZE - 1;
- count_leading_zeros (ret, x);
- return ret - 1;
-}
-#endif
-
-#ifdef L_clrsbdi2
-#undef int
-int
-__clrsbDI2 (DWtype x)
-{
- const DWunion uu = {.ll = x};
- UWtype word;
- Wtype ret, add;
-
- if (uu.s.high == 0)
- word = uu.s.low, add = W_TYPE_SIZE;
- else if (uu.s.high == -1)
- word = ~uu.s.low, add = W_TYPE_SIZE;
- else if (uu.s.high >= 0)
- word = uu.s.high, add = 0;
- else
- word = ~uu.s.high, add = 0;
-
- if (word == 0)
- ret = W_TYPE_SIZE;
- else
- count_leading_zeros (ret, word);
-
- return ret + add - 1;
-}
-#endif
-
-#ifdef L_popcount_tab
-const UQItype __popcount_tab[256] =
-{
- 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
- 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
- 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
- 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
- 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
-};
-#endif
-
-#ifdef L_popcountsi2
-#undef int
-int
-__popcountSI2 (UWtype x)
-{
- int i, ret = 0;
-
- for (i = 0; i < W_TYPE_SIZE; i += 8)
- ret += __popcount_tab[(x >> i) & 0xff];
-
- return ret;
-}
-#endif
-
-#ifdef L_popcountdi2
-#undef int
-int
-__popcountDI2 (UDWtype x)
-{
- int i, ret = 0;
-
- for (i = 0; i < 2*W_TYPE_SIZE; i += 8)
- ret += __popcount_tab[(x >> i) & 0xff];
-
- return ret;
-}
-#endif
-
-#ifdef L_paritysi2
-#undef int
-int
-__paritySI2 (UWtype x)
-{
-#if W_TYPE_SIZE > 64
-# error "fill out the table"
-#endif
-#if W_TYPE_SIZE > 32
- x ^= x >> 32;
-#endif
-#if W_TYPE_SIZE > 16
- x ^= x >> 16;
-#endif
- x ^= x >> 8;
- x ^= x >> 4;
- x &= 0xf;
- return (0x6996 >> x) & 1;
-}
-#endif
-
-#ifdef L_paritydi2
-#undef int
-int
-__parityDI2 (UDWtype x)
-{
- const DWunion uu = {.ll = x};
- UWtype nx = uu.s.low ^ uu.s.high;
-
-#if W_TYPE_SIZE > 64
-# error "fill out the table"
-#endif
-#if W_TYPE_SIZE > 32
- nx ^= nx >> 32;
-#endif
-#if W_TYPE_SIZE > 16
- nx ^= nx >> 16;
-#endif
- nx ^= nx >> 8;
- nx ^= nx >> 4;
- nx &= 0xf;
- return (0x6996 >> nx) & 1;
-}
-#endif
-
-#ifdef L_udivmoddi4
-
-#if (defined (L_udivdi3) || defined (L_divdi3) || \
- defined (L_umoddi3) || defined (L_moddi3))
-static inline __attribute__ ((__always_inline__))
-#endif
-UDWtype
-__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
-{
- const DWunion nn = {.ll = n};
- const DWunion dd = {.ll = d};
- DWunion rr;
- UWtype d0, d1, n0, n1, n2;
- UWtype q0, q1;
- UWtype b, bm;
-
- d0 = dd.s.low;
- d1 = dd.s.high;
- n0 = nn.s.low;
- n1 = nn.s.high;
-
-#if !UDIV_NEEDS_NORMALIZATION
- if (d1 == 0)
- {
- if (d0 > n1)
- {
- /* 0q = nn / 0D */
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
- q1 = 0;
-
- /* Remainder in n0. */
- }
- else
- {
- /* qq = NN / 0d */
-
- if (d0 == 0)
- d0 = 1 / d0; /* Divide intentionally by zero. */
-
- udiv_qrnnd (q1, n1, 0, n1, d0);
- udiv_qrnnd (q0, n0, n1, n0, d0);
-
- /* Remainder in n0. */
- }
-
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = 0;
- *rp = rr.ll;
- }
- }
-
-#else /* UDIV_NEEDS_NORMALIZATION */
-
- if (d1 == 0)
- {
- if (d0 > n1)
- {
- /* 0q = nn / 0D */
-
- count_leading_zeros (bm, d0);
-
- if (bm != 0)
- {
- /* Normalize, i.e. make the most significant bit of the
- denominator set. */
-
- d0 = d0 << bm;
- n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
- n0 = n0 << bm;
- }
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
- q1 = 0;
-
- /* Remainder in n0 >> bm. */
- }
- else
- {
- /* qq = NN / 0d */
-
- if (d0 == 0)
- d0 = 1 / d0; /* Divide intentionally by zero. */
-
- count_leading_zeros (bm, d0);
-
- if (bm == 0)
- {
- /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- leading quotient digit q1 = 1).
-
- This special case is necessary, not an optimization.
- (Shifts counts of W_TYPE_SIZE are undefined.) */
-
- n1 -= d0;
- q1 = 1;
- }
- else
- {
- /* Normalize. */
-
- b = W_TYPE_SIZE - bm;
-
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd (q1, n1, n2, n1, d0);
- }
-
- /* n1 != d0... */
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
-
- /* Remainder in n0 >> bm. */
- }
-
- if (rp != 0)
- {
- rr.s.low = n0 >> bm;
- rr.s.high = 0;
- *rp = rr.ll;
- }
- }
-#endif /* UDIV_NEEDS_NORMALIZATION */
-
- else
- {
- if (d1 > n1)
- {
- /* 00 = nn / DD */
-
- q0 = 0;
- q1 = 0;
-
- /* Remainder in n1n0. */
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- }
- else
- {
- /* 0q = NN / dd */
-
- count_leading_zeros (bm, d1);
- if (bm == 0)
- {
- /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- quotient digit q0 = 0 or 1).
-
- This special case is necessary, not an optimization. */
-
- /* The condition on the next line takes advantage of that
- n1 >= d1 (true due to program flow). */
- if (n1 > d1 || n0 >= d0)
- {
- q0 = 1;
- sub_ddmmss (n1, n0, n1, n0, d1, d0);
- }
- else
- q0 = 0;
-
- q1 = 0;
-
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- }
- else
- {
- UWtype m1, m0;
- /* Normalize. */
-
- b = W_TYPE_SIZE - bm;
-
- d1 = (d1 << bm) | (d0 >> b);
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd (q0, n1, n2, n1, d1);
- umul_ppmm (m1, m0, q0, d0);
-
- if (m1 > n1 || (m1 == n1 && m0 > n0))
- {
- q0--;
- sub_ddmmss (m1, m0, m1, m0, d1, d0);
- }
-
- q1 = 0;
-
- /* Remainder in (n1n0 - m1m0) >> bm. */
- if (rp != 0)
- {
- sub_ddmmss (n1, n0, n1, n0, m1, m0);
- rr.s.low = (n1 << b) | (n0 >> bm);
- rr.s.high = n1 >> bm;
- *rp = rr.ll;
- }
- }
- }
- }
-
- const DWunion ww = {{.low = q0, .high = q1}};
- return ww.ll;
-}
-#endif
-
-#ifdef L_divdi3
-DWtype
-__divdi3 (DWtype u, DWtype v)
-{
- Wtype c = 0;
- DWunion uu = {.ll = u};
- DWunion vv = {.ll = v};
- DWtype w;
-
- if (uu.s.high < 0)
- c = ~c,
- uu.ll = -uu.ll;
- if (vv.s.high < 0)
- c = ~c,
- vv.ll = -vv.ll;
-
- w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
- if (c)
- w = -w;
-
- return w;
-}
-#endif
-
-#ifdef L_moddi3
-DWtype
-__moddi3 (DWtype u, DWtype v)
-{
- Wtype c = 0;
- DWunion uu = {.ll = u};
- DWunion vv = {.ll = v};
- DWtype w;
-
- if (uu.s.high < 0)
- c = ~c,
- uu.ll = -uu.ll;
- if (vv.s.high < 0)
- vv.ll = -vv.ll;
-
- (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
- if (c)
- w = -w;
-
- return w;
-}
-#endif
-
-#ifdef L_umoddi3
-UDWtype
-__umoddi3 (UDWtype u, UDWtype v)
-{
- UDWtype w;
-
- (void) __udivmoddi4 (u, v, &w);
-
- return w;
-}
-#endif
-
-#ifdef L_udivdi3
-UDWtype
-__udivdi3 (UDWtype n, UDWtype d)
-{
- return __udivmoddi4 (n, d, (UDWtype *) 0);
-}
-#endif
-
-#ifdef L_cmpdi2
-cmp_return_type
-__cmpdi2 (DWtype a, DWtype b)
-{
- const DWunion au = {.ll = a};
- const DWunion bu = {.ll = b};
-
- if (au.s.high < bu.s.high)
- return 0;
- else if (au.s.high > bu.s.high)
- return 2;
- if ((UWtype) au.s.low < (UWtype) bu.s.low)
- return 0;
- else if ((UWtype) au.s.low > (UWtype) bu.s.low)
- return 2;
- return 1;
-}
-#endif
-
-#ifdef L_ucmpdi2
-cmp_return_type
-__ucmpdi2 (DWtype a, DWtype b)
-{
- const DWunion au = {.ll = a};
- const DWunion bu = {.ll = b};
-
- if ((UWtype) au.s.high < (UWtype) bu.s.high)
- return 0;
- else if ((UWtype) au.s.high > (UWtype) bu.s.high)
- return 2;
- if ((UWtype) au.s.low < (UWtype) bu.s.low)
- return 0;
- else if ((UWtype) au.s.low > (UWtype) bu.s.low)
- return 2;
- return 1;
-}
-#endif
-
-#if defined(L_fixunstfdi) && LIBGCC2_HAS_TF_MODE
-UDWtype
-__fixunstfDI (TFtype a)
-{
- if (a < 0)
- return 0;
-
- /* Compute high word of result, as a flonum. */
- const TFtype b = (a / Wtype_MAXp1_F);
- /* Convert that to fixed (but not to DWtype!),
- and shift it into the high word. */
- UDWtype v = (UWtype) b;
- v <<= W_TYPE_SIZE;
- /* Remove high part from the TFtype, leaving the low part as flonum. */
- a -= (TFtype)v;
- /* Convert that to fixed (but not to DWtype!) and add it in.
- Sometimes A comes out negative. This is significant, since
- A has more bits than a long int does. */
- if (a < 0)
- v -= (UWtype) (- a);
- else
- v += (UWtype) a;
- return v;
-}
-#endif
-
-#if defined(L_fixtfdi) && LIBGCC2_HAS_TF_MODE
-DWtype
-__fixtfdi (TFtype a)
-{
- if (a < 0)
- return - __fixunstfDI (-a);
- return __fixunstfDI (a);
-}
-#endif
-
-#if defined(L_fixunsxfdi) && LIBGCC2_HAS_XF_MODE
-UDWtype
-__fixunsxfDI (XFtype a)
-{
- if (a < 0)
- return 0;
-
- /* Compute high word of result, as a flonum. */
- const XFtype b = (a / Wtype_MAXp1_F);
- /* Convert that to fixed (but not to DWtype!),
- and shift it into the high word. */
- UDWtype v = (UWtype) b;
- v <<= W_TYPE_SIZE;
- /* Remove high part from the XFtype, leaving the low part as flonum. */
- a -= (XFtype)v;
- /* Convert that to fixed (but not to DWtype!) and add it in.
- Sometimes A comes out negative. This is significant, since
- A has more bits than a long int does. */
- if (a < 0)
- v -= (UWtype) (- a);
- else
- v += (UWtype) a;
- return v;
-}
-#endif
-
-#if defined(L_fixxfdi) && LIBGCC2_HAS_XF_MODE
-DWtype
-__fixxfdi (XFtype a)
-{
- if (a < 0)
- return - __fixunsxfDI (-a);
- return __fixunsxfDI (a);
-}
-#endif
-
-#if defined(L_fixunsdfdi) && LIBGCC2_HAS_DF_MODE
-UDWtype
-__fixunsdfDI (DFtype a)
-{
- /* Get high part of result. The division here will just moves the radix
- point and will not cause any rounding. Then the conversion to integral
- type chops result as desired. */
- const UWtype hi = a / Wtype_MAXp1_F;
-
- /* Get low part of result. Convert `hi' to floating type and scale it back,
- then subtract this from the number being converted. This leaves the low
- part. Convert that to integral type. */
- const UWtype lo = a - (DFtype) hi * Wtype_MAXp1_F;
-
- /* Assemble result from the two parts. */
- return ((UDWtype) hi << W_TYPE_SIZE) | lo;
-}
-#endif
-
-#if defined(L_fixdfdi) && LIBGCC2_HAS_DF_MODE
-DWtype
-__fixdfdi (DFtype a)
-{
- if (a < 0)
- return - __fixunsdfDI (-a);
- return __fixunsdfDI (a);
-}
-#endif
-
-#if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE
-UDWtype
-__fixunssfDI (SFtype a)
-{
-#if LIBGCC2_HAS_DF_MODE
- /* Convert the SFtype to a DFtype, because that is surely not going
- to lose any bits. Some day someone else can write a faster version
- that avoids converting to DFtype, and verify it really works right. */
- const DFtype dfa = a;
-
- /* Get high part of result. The division here will just moves the radix
- point and will not cause any rounding. Then the conversion to integral
- type chops result as desired. */
- const UWtype hi = dfa / Wtype_MAXp1_F;
-
- /* Get low part of result. Convert `hi' to floating type and scale it back,
- then subtract this from the number being converted. This leaves the low
- part. Convert that to integral type. */
- const UWtype lo = dfa - (DFtype) hi * Wtype_MAXp1_F;
-
- /* Assemble result from the two parts. */
- return ((UDWtype) hi << W_TYPE_SIZE) | lo;
-#elif FLT_MANT_DIG < W_TYPE_SIZE
- if (a < 1)
- return 0;
- if (a < Wtype_MAXp1_F)
- return (UWtype)a;
- if (a < Wtype_MAXp1_F * Wtype_MAXp1_F)
- {
- /* Since we know that there are fewer significant bits in the SFmode
- quantity than in a word, we know that we can convert out all the
- significant bits in one step, and thus avoid losing bits. */
-
- /* ??? This following loop essentially performs frexpf. If we could
- use the real libm function, or poke at the actual bits of the fp
- format, it would be significantly faster. */
-
- UWtype shift = 0, counter;
- SFtype msb;
-
- a /= Wtype_MAXp1_F;
- for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1)
- {
- SFtype counterf = (UWtype)1 << counter;
- if (a >= counterf)
- {
- shift |= counter;
- a /= counterf;
- }
- }
-
- /* Rescale into the range of one word, extract the bits of that
- one word, and shift the result into position. */
- a *= Wtype_MAXp1_F;
- counter = a;
- return (DWtype)counter << shift;
- }
- return -1;
-#else
-# error
-#endif
-}
-#endif
-
-#if defined(L_fixsfdi) && LIBGCC2_HAS_SF_MODE
-DWtype
-__fixsfdi (SFtype a)
-{
- if (a < 0)
- return - __fixunssfDI (-a);
- return __fixunssfDI (a);
-}
-#endif
-
-#if defined(L_floatdixf) && LIBGCC2_HAS_XF_MODE
-XFtype
-__floatdixf (DWtype u)
-{
-#if W_TYPE_SIZE > XF_SIZE
-# error
-#endif
- XFtype d = (Wtype) (u >> W_TYPE_SIZE);
- d *= Wtype_MAXp1_F;
- d += (UWtype)u;
- return d;
-}
-#endif
-
-#if defined(L_floatundixf) && LIBGCC2_HAS_XF_MODE
-XFtype
-__floatundixf (UDWtype u)
-{
-#if W_TYPE_SIZE > XF_SIZE
-# error
-#endif
- XFtype d = (UWtype) (u >> W_TYPE_SIZE);
- d *= Wtype_MAXp1_F;
- d += (UWtype)u;
- return d;
-}
-#endif
-
-#if defined(L_floatditf) && LIBGCC2_HAS_TF_MODE
-TFtype
-__floatditf (DWtype u)
-{
-#if W_TYPE_SIZE > TF_SIZE
-# error
-#endif
- TFtype d = (Wtype) (u >> W_TYPE_SIZE);
- d *= Wtype_MAXp1_F;
- d += (UWtype)u;
- return d;
-}
-#endif
-
-#if defined(L_floatunditf) && LIBGCC2_HAS_TF_MODE
-TFtype
-__floatunditf (UDWtype u)
-{
-#if W_TYPE_SIZE > TF_SIZE
-# error
-#endif
- TFtype d = (UWtype) (u >> W_TYPE_SIZE);
- d *= Wtype_MAXp1_F;
- d += (UWtype)u;
- return d;
-}
-#endif
-
-#if (defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE) \
- || (defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE)
-#define DI_SIZE (W_TYPE_SIZE * 2)
-#define F_MODE_OK(SIZE) \
- (SIZE < DI_SIZE \
- && SIZE > (DI_SIZE - SIZE + FSSIZE) \
- && !AVOID_FP_TYPE_CONVERSION(SIZE))
-#if defined(L_floatdisf)
-#define FUNC __floatdisf
-#define FSTYPE SFtype
-#define FSSIZE SF_SIZE
-#else
-#define FUNC __floatdidf
-#define FSTYPE DFtype
-#define FSSIZE DF_SIZE
-#endif
-
-FSTYPE
-FUNC (DWtype u)
-{
-#if FSSIZE >= W_TYPE_SIZE
- /* When the word size is small, we never get any rounding error. */
- FSTYPE f = (Wtype) (u >> W_TYPE_SIZE);
- f *= Wtype_MAXp1_F;
- f += (UWtype)u;
- return f;
-#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \
- || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \
- || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
-
-#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE))
-# define FSIZE DF_SIZE
-# define FTYPE DFtype
-#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE))
-# define FSIZE XF_SIZE
-# define FTYPE XFtype
-#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
-# define FSIZE TF_SIZE
-# define FTYPE TFtype
-#else
-# error
-#endif
-
-#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE))
-
- /* Protect against double-rounding error.
- Represent any low-order bits, that might be truncated by a bit that
- won't be lost. The bit can go in anywhere below the rounding position
- of the FSTYPE. A fixed mask and bit position handles all usual
- configurations. */
- if (! (- ((DWtype) 1 << FSIZE) < u
- && u < ((DWtype) 1 << FSIZE)))
- {
- if ((UDWtype) u & (REP_BIT - 1))
- {
- u &= ~ (REP_BIT - 1);
- u |= REP_BIT;
- }
- }
-
- /* Do the calculation in a wider type so that we don't lose any of
- the precision of the high word while multiplying it. */
- FTYPE f = (Wtype) (u >> W_TYPE_SIZE);
- f *= Wtype_MAXp1_F;
- f += (UWtype)u;
- return (FSTYPE) f;
-#else
-#if FSSIZE >= W_TYPE_SIZE - 2
-# error
-#endif
- /* Finally, the word size is larger than the number of bits in the
- required FSTYPE, and we've got no suitable wider type. The only
- way to avoid double rounding is to special case the
- extraction. */
-
- /* If there are no high bits set, fall back to one conversion. */
- if ((Wtype)u == u)
- return (FSTYPE)(Wtype)u;
-
- /* Otherwise, find the power of two. */
- Wtype hi = u >> W_TYPE_SIZE;
- if (hi < 0)
- hi = -hi;
-
- UWtype count, shift;
- count_leading_zeros (count, hi);
-
- /* No leading bits means u == minimum. */
- if (count == 0)
- return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2));
-
- shift = 1 + W_TYPE_SIZE - count;
-
- /* Shift down the most significant bits. */
- hi = u >> shift;
-
- /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */
- if ((UWtype)u << (W_TYPE_SIZE - shift))
- hi |= 1;
-
- /* Convert the one word of data, and rescale. */
- FSTYPE f = hi, e;
- if (shift == W_TYPE_SIZE)
- e = Wtype_MAXp1_F;
- /* The following two cases could be merged if we knew that the target
- supported a native unsigned->float conversion. More often, we only
- have a signed conversion, and have to add extra fixup code. */
- else if (shift == W_TYPE_SIZE - 1)
- e = Wtype_MAXp1_F / 2;
- else
- e = (Wtype)1 << shift;
- return f * e;
-#endif
-}
-#endif
-
-#if (defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE) \
- || (defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE)
-#define DI_SIZE (W_TYPE_SIZE * 2)
-#define F_MODE_OK(SIZE) \
- (SIZE < DI_SIZE \
- && SIZE > (DI_SIZE - SIZE + FSSIZE) \
- && !AVOID_FP_TYPE_CONVERSION(SIZE))
-#if defined(L_floatundisf)
-#define FUNC __floatundisf
-#define FSTYPE SFtype
-#define FSSIZE SF_SIZE
-#else
-#define FUNC __floatundidf
-#define FSTYPE DFtype
-#define FSSIZE DF_SIZE
-#endif
-
-FSTYPE
-FUNC (UDWtype u)
-{
-#if FSSIZE >= W_TYPE_SIZE
- /* When the word size is small, we never get any rounding error. */
- FSTYPE f = (UWtype) (u >> W_TYPE_SIZE);
- f *= Wtype_MAXp1_F;
- f += (UWtype)u;
- return f;
-#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \
- || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \
- || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
-
-#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE))
-# define FSIZE DF_SIZE
-# define FTYPE DFtype
-#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE))
-# define FSIZE XF_SIZE
-# define FTYPE XFtype
-#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
-# define FSIZE TF_SIZE
-# define FTYPE TFtype
-#else
-# error
-#endif
-
-#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE))
-
- /* Protect against double-rounding error.
- Represent any low-order bits, that might be truncated by a bit that
- won't be lost. The bit can go in anywhere below the rounding position
- of the FSTYPE. A fixed mask and bit position handles all usual
- configurations. */
- if (u >= ((UDWtype) 1 << FSIZE))
- {
- if ((UDWtype) u & (REP_BIT - 1))
- {
- u &= ~ (REP_BIT - 1);
- u |= REP_BIT;
- }
- }
-
- /* Do the calculation in a wider type so that we don't lose any of
- the precision of the high word while multiplying it. */
- FTYPE f = (UWtype) (u >> W_TYPE_SIZE);
- f *= Wtype_MAXp1_F;
- f += (UWtype)u;
- return (FSTYPE) f;
-#else
-#if FSSIZE == W_TYPE_SIZE - 1
-# error
-#endif
- /* Finally, the word size is larger than the number of bits in the
- required FSTYPE, and we've got no suitable wider type. The only
- way to avoid double rounding is to special case the
- extraction. */
-
- /* If there are no high bits set, fall back to one conversion. */
- if ((UWtype)u == u)
- return (FSTYPE)(UWtype)u;
-
- /* Otherwise, find the power of two. */
- UWtype hi = u >> W_TYPE_SIZE;
-
- UWtype count, shift;
- count_leading_zeros (count, hi);
-
- shift = W_TYPE_SIZE - count;
-
- /* Shift down the most significant bits. */
- hi = u >> shift;
-
- /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */
- if ((UWtype)u << (W_TYPE_SIZE - shift))
- hi |= 1;
-
- /* Convert the one word of data, and rescale. */
- FSTYPE f = hi, e;
- if (shift == W_TYPE_SIZE)
- e = Wtype_MAXp1_F;
- /* The following two cases could be merged if we knew that the target
- supported a native unsigned->float conversion. More often, we only
- have a signed conversion, and have to add extra fixup code. */
- else if (shift == W_TYPE_SIZE - 1)
- e = Wtype_MAXp1_F / 2;
- else
- e = (Wtype)1 << shift;
- return f * e;
-#endif
-}
-#endif
-
-#if defined(L_fixunsxfsi) && LIBGCC2_HAS_XF_MODE
-/* Reenable the normal types, in case limits.h needs them. */
-#undef char
-#undef short
-#undef int
-#undef long
-#undef unsigned
-#undef float
-#undef double
-#undef MIN
-#undef MAX
-#include <limits.h>
-
-UWtype
-__fixunsxfSI (XFtype a)
-{
- if (a >= - (DFtype) Wtype_MIN)
- return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
- return (Wtype) a;
-}
-#endif
-
-#if defined(L_fixunsdfsi) && LIBGCC2_HAS_DF_MODE
-/* Reenable the normal types, in case limits.h needs them. */
-#undef char
-#undef short
-#undef int
-#undef long
-#undef unsigned
-#undef float
-#undef double
-#undef MIN
-#undef MAX
-#include <limits.h>
-
-UWtype
-__fixunsdfSI (DFtype a)
-{
- if (a >= - (DFtype) Wtype_MIN)
- return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
- return (Wtype) a;
-}
-#endif
-
-#if defined(L_fixunssfsi) && LIBGCC2_HAS_SF_MODE
-/* Reenable the normal types, in case limits.h needs them. */
-#undef char
-#undef short
-#undef int
-#undef long
-#undef unsigned
-#undef float
-#undef double
-#undef MIN
-#undef MAX
-#include <limits.h>
-
-UWtype
-__fixunssfSI (SFtype a)
-{
- if (a >= - (SFtype) Wtype_MIN)
- return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
- return (Wtype) a;
-}
-#endif
-
-/* Integer power helper used from __builtin_powi for non-constant
- exponents. */
-
-#if (defined(L_powisf2) && LIBGCC2_HAS_SF_MODE) \
- || (defined(L_powidf2) && LIBGCC2_HAS_DF_MODE) \
- || (defined(L_powixf2) && LIBGCC2_HAS_XF_MODE) \
- || (defined(L_powitf2) && LIBGCC2_HAS_TF_MODE)
-# if defined(L_powisf2)
-# define TYPE SFtype
-# define NAME __powisf2
-# elif defined(L_powidf2)
-# define TYPE DFtype
-# define NAME __powidf2
-# elif defined(L_powixf2)
-# define TYPE XFtype
-# define NAME __powixf2
-# elif defined(L_powitf2)
-# define TYPE TFtype
-# define NAME __powitf2
-# endif
-
-#undef int
-#undef unsigned
-TYPE
-NAME (TYPE x, int m)
-{
- unsigned int n = m < 0 ? -m : m;
- TYPE y = n % 2 ? x : 1;
- while (n >>= 1)
- {
- x = x * x;
- if (n % 2)
- y = y * x;
- }
- return m < 0 ? 1/y : y;
-}
-
-#endif
-
-#if ((defined(L_mulsc3) || defined(L_divsc3)) && LIBGCC2_HAS_SF_MODE) \
- || ((defined(L_muldc3) || defined(L_divdc3)) && LIBGCC2_HAS_DF_MODE) \
- || ((defined(L_mulxc3) || defined(L_divxc3)) && LIBGCC2_HAS_XF_MODE) \
- || ((defined(L_multc3) || defined(L_divtc3)) && LIBGCC2_HAS_TF_MODE)
-
-#undef float
-#undef double
-#undef long
-
-#if defined(L_mulsc3) || defined(L_divsc3)
-# define MTYPE SFtype
-# define CTYPE SCtype
-# define MODE sc
-# define CEXT f
-# define NOTRUNC __FLT_EVAL_METHOD__ == 0
-#elif defined(L_muldc3) || defined(L_divdc3)
-# define MTYPE DFtype
-# define CTYPE DCtype
-# define MODE dc
-# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64
-# define CEXT l
-# define NOTRUNC 1
-# else
-# define CEXT
-# define NOTRUNC __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1
-# endif
-#elif defined(L_mulxc3) || defined(L_divxc3)
-# define MTYPE XFtype
-# define CTYPE XCtype
-# define MODE xc
-# define CEXT l
-# define NOTRUNC 1
-#elif defined(L_multc3) || defined(L_divtc3)
-# define MTYPE TFtype
-# define CTYPE TCtype
-# define MODE tc
-# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
-# define CEXT l
-# else
-# define CEXT LIBGCC2_TF_CEXT
-# endif
-# define NOTRUNC 1
-#else
-# error
-#endif
-
-#define CONCAT3(A,B,C) _CONCAT3(A,B,C)
-#define _CONCAT3(A,B,C) A##B##C
-
-#define CONCAT2(A,B) _CONCAT2(A,B)
-#define _CONCAT2(A,B) A##B
-
-/* All of these would be present in a full C99 implementation of <math.h>
- and <complex.h>. Our problem is that only a few systems have such full
- implementations. Further, libgcc_s.so isn't currently linked against
- libm.so, and even for systems that do provide full C99, the extra overhead
- of all programs using libgcc having to link against libm. So avoid it. */
-
-#define isnan(x) __builtin_expect ((x) != (x), 0)
-#define isfinite(x) __builtin_expect (!isnan((x) - (x)), 1)
-#define isinf(x) __builtin_expect (!isnan(x) & !isfinite(x), 0)
-
-#define INFINITY CONCAT2(__builtin_huge_val, CEXT) ()
-#define I 1i
-
-/* Helpers to make the following code slightly less gross. */
-#define COPYSIGN CONCAT2(__builtin_copysign, CEXT)
-#define FABS CONCAT2(__builtin_fabs, CEXT)
-
-/* Verify that MTYPE matches up with CEXT. */
-extern void *compile_type_assert[sizeof(INFINITY) == sizeof(MTYPE) ? 1 : -1];
-
-/* Ensure that we've lost any extra precision. */
-#if NOTRUNC
-# define TRUNC(x)
-#else
-# define TRUNC(x) __asm__ ("" : "=m"(x) : "m"(x))
-#endif
-
-#if defined(L_mulsc3) || defined(L_muldc3) \
- || defined(L_mulxc3) || defined(L_multc3)
-
-CTYPE
-CONCAT3(__mul,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d)
-{
- MTYPE ac, bd, ad, bc, x, y;
- CTYPE res;
-
- ac = a * c;
- bd = b * d;
- ad = a * d;
- bc = b * c;
-
- TRUNC (ac);
- TRUNC (bd);
- TRUNC (ad);
- TRUNC (bc);
-
- x = ac - bd;
- y = ad + bc;
-
- if (isnan (x) && isnan (y))
- {
- /* Recover infinities that computed as NaN + iNaN. */
- _Bool recalc = 0;
- if (isinf (a) || isinf (b))
- {
- /* z is infinite. "Box" the infinity and change NaNs in
- the other factor to 0. */
- a = COPYSIGN (isinf (a) ? 1 : 0, a);
- b = COPYSIGN (isinf (b) ? 1 : 0, b);
- if (isnan (c)) c = COPYSIGN (0, c);
- if (isnan (d)) d = COPYSIGN (0, d);
- recalc = 1;
- }
- if (isinf (c) || isinf (d))
- {
- /* w is infinite. "Box" the infinity and change NaNs in
- the other factor to 0. */
- c = COPYSIGN (isinf (c) ? 1 : 0, c);
- d = COPYSIGN (isinf (d) ? 1 : 0, d);
- if (isnan (a)) a = COPYSIGN (0, a);
- if (isnan (b)) b = COPYSIGN (0, b);
- recalc = 1;
- }
- if (!recalc
- && (isinf (ac) || isinf (bd)
- || isinf (ad) || isinf (bc)))
- {
- /* Recover infinities from overflow by changing NaNs to 0. */
- if (isnan (a)) a = COPYSIGN (0, a);
- if (isnan (b)) b = COPYSIGN (0, b);
- if (isnan (c)) c = COPYSIGN (0, c);
- if (isnan (d)) d = COPYSIGN (0, d);
- recalc = 1;
- }
- if (recalc)
- {
- x = INFINITY * (a * c - b * d);
- y = INFINITY * (a * d + b * c);
- }
- }
-
- __real__ res = x;
- __imag__ res = y;
- return res;
-}
-#endif /* complex multiply */
-
-#if defined(L_divsc3) || defined(L_divdc3) \
- || defined(L_divxc3) || defined(L_divtc3)
-
-CTYPE
-CONCAT3(__div,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d)
-{
- MTYPE denom, ratio, x, y;
- CTYPE res;
-
- /* ??? We can get better behavior from logarithmic scaling instead of
- the division. But that would mean starting to link libgcc against
- libm. We could implement something akin to ldexp/frexp as gcc builtins
- fairly easily... */
- if (FABS (c) < FABS (d))
- {
- ratio = c / d;
- denom = (c * ratio) + d;
- x = ((a * ratio) + b) / denom;
- y = ((b * ratio) - a) / denom;
- }
- else
- {
- ratio = d / c;
- denom = (d * ratio) + c;
- x = ((b * ratio) + a) / denom;
- y = (b - (a * ratio)) / denom;
- }
-
- /* Recover infinities and zeros that computed as NaN+iNaN; the only cases
- are nonzero/zero, infinite/finite, and finite/infinite. */
- if (isnan (x) && isnan (y))
- {
- if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b)))
- {
- x = COPYSIGN (INFINITY, c) * a;
- y = COPYSIGN (INFINITY, c) * b;
- }
- else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d))
- {
- a = COPYSIGN (isinf (a) ? 1 : 0, a);
- b = COPYSIGN (isinf (b) ? 1 : 0, b);
- x = INFINITY * (a * c + b * d);
- y = INFINITY * (b * c - a * d);
- }
- else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b))
- {
- c = COPYSIGN (isinf (c) ? 1 : 0, c);
- d = COPYSIGN (isinf (d) ? 1 : 0, d);
- x = 0.0 * (a * c + b * d);
- y = 0.0 * (b * c - a * d);
- }
- }
-
- __real__ res = x;
- __imag__ res = y;
- return res;
-}
-#endif /* complex divide */
-
-#endif /* all complex float routines */
-
-/* From here on down, the routines use normal data types. */
-
-#define SItype bogus_type
-#define USItype bogus_type
-#define DItype bogus_type
-#define UDItype bogus_type
-#define SFtype bogus_type
-#define DFtype bogus_type
-#undef Wtype
-#undef UWtype
-#undef HWtype
-#undef UHWtype
-#undef DWtype
-#undef UDWtype
-
-#undef char
-#undef short
-#undef int
-#undef long
-#undef unsigned
-#undef float
-#undef double
-
-#ifdef L__gcc_bcmp
-
-/* Like bcmp except the sign is meaningful.
- Result is negative if S1 is less than S2,
- positive if S1 is greater, 0 if S1 and S2 are equal. */
-
-int
-__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
-{
- while (size > 0)
- {
- const unsigned char c1 = *s1++, c2 = *s2++;
- if (c1 != c2)
- return c1 - c2;
- size--;
- }
- return 0;
-}
-
-#endif
-
-/* __eprintf used to be used by GCC's private version of <assert.h>.
- We no longer provide that header, but this routine remains in libgcc.a
- for binary backward compatibility. Note that it is not included in
- the shared version of libgcc. */
-#ifdef L_eprintf
-#ifndef inhibit_libc
-
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
-#include <stdio.h>
-
-void
-__eprintf (const char *string, const char *expression,
- unsigned int line, const char *filename)
-{
- fprintf (stderr, string, expression, line, filename);
- fflush (stderr);
- abort ();
-}
-
-#endif
-#endif
-
-
-#ifdef L_clear_cache
-/* Clear part of an instruction cache. */
-
-void
-__clear_cache (char *beg __attribute__((__unused__)),
- char *end __attribute__((__unused__)))
-{
-#ifdef CLEAR_INSN_CACHE
- CLEAR_INSN_CACHE (beg, end);
-#endif /* CLEAR_INSN_CACHE */
-}
-
-#endif /* L_clear_cache */
-
-#ifdef L_trampoline
-
-/* Jump to a trampoline, loading the static chain address. */
-
-#if defined(WINNT) && ! defined(__CYGWIN__)
-#include <windows.h>
-int getpagesize (void);
-int mprotect (char *,int, int);
-
-int
-getpagesize (void)
-{
-#ifdef _ALPHA_
- return 8192;
-#else
- return 4096;
-#endif
-}
-
-int
-mprotect (char *addr, int len, int prot)
-{
- DWORD np, op;
-
- if (prot == 7)
- np = 0x40;
- else if (prot == 5)
- np = 0x20;
- else if (prot == 4)
- np = 0x10;
- else if (prot == 3)
- np = 0x04;
- else if (prot == 1)
- np = 0x02;
- else if (prot == 0)
- np = 0x01;
- else
- return -1;
-
- if (VirtualProtect (addr, len, np, &op))
- return 0;
- else
- return -1;
-}
-
-#endif /* WINNT && ! __CYGWIN__ */
-
-#ifdef TRANSFER_FROM_TRAMPOLINE
-TRANSFER_FROM_TRAMPOLINE
-#endif
-#endif /* L_trampoline */
-
-#ifndef __CYGWIN__
-#ifdef L__main
-
-#include "gbl-ctors.h"
-
-/* 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. */
-#ifndef NAME__MAIN
-#define NAME__MAIN "__main"
-#define SYMBOL__MAIN __main
-#endif
-
-#if defined (INIT_SECTION_ASM_OP) || defined (INIT_ARRAY_SECTION_ASM_OP)
-#undef HAS_INIT_SECTION
-#define HAS_INIT_SECTION
-#endif
-
-#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
-
-/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
- code to run constructors. In that case, we need to handle EH here, too. */
-
-#ifdef EH_FRAME_SECTION_NAME
-#include "unwind-dw2-fde.h"
-extern unsigned char __EH_FRAME_BEGIN__[];
-#endif
-
-/* Run all the global destructors on exit from the program. */
-
-void
-__do_global_dtors (void)
-{
-#ifdef DO_GLOBAL_DTORS_BODY
- DO_GLOBAL_DTORS_BODY;
-#else
- static func_ptr *p = __DTOR_LIST__ + 1;
- while (*p)
- {
- p++;
- (*(p-1)) ();
- }
-#endif
-#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
- {
- static int completed = 0;
- if (! completed)
- {
- completed = 1;
- __deregister_frame_info (__EH_FRAME_BEGIN__);
- }
- }
-#endif
-}
-#endif
-
-#ifndef HAS_INIT_SECTION
-/* Run all the global constructors on entry to the program. */
-
-void
-__do_global_ctors (void)
-{
-#ifdef EH_FRAME_SECTION_NAME
- {
- static struct object object;
- __register_frame_info (__EH_FRAME_BEGIN__, &object);
- }
-#endif
- DO_GLOBAL_CTORS_BODY;
- atexit (__do_global_dtors);
-}
-#endif /* no HAS_INIT_SECTION */
-
-#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
-/* Subroutine called automatically by `main'.
- Compiling a global function named `main'
- produces an automatic call to this function at the beginning.
-
- 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. */
-
-extern void SYMBOL__MAIN (void);
-void
-SYMBOL__MAIN (void)
-{
- /* Support recursive calls to `main': run initializers just once. */
- static int initialized;
- if (! initialized)
- {
- initialized = 1;
- __do_global_ctors ();
- }
-}
-#endif /* no HAS_INIT_SECTION or INVOKE__main */
-
-#endif /* L__main */
-#endif /* __CYGWIN__ */
-
-#ifdef L_ctors
-
-#include "gbl-ctors.h"
-
-/* Provide default definitions for the lists of constructors and
- destructors, so that we don't get linker errors. These symbols are
- intentionally bss symbols, so that gld and/or collect will provide
- the right values. */
-
-/* We declare the lists here with two elements each,
- so that they are valid empty lists if no other definition is loaded.
-
- If we are using the old "set" extensions to have the gnu linker
- collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
- must be in the bss/common section.
-
- Long term no port should use those extensions. But many still do. */
-#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
-#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
-func_ptr __CTOR_LIST__[2] = {0, 0};
-func_ptr __DTOR_LIST__[2] = {0, 0};
-#else
-func_ptr __CTOR_LIST__[2];
-func_ptr __DTOR_LIST__[2];
-#endif
-#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
-#endif /* L_ctors */
-#endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */
diff --git a/gcc/lists.c b/gcc/lists.c
index 4628e68b9fe..a962d3e01f3 100644
--- a/gcc/lists.c
+++ b/gcc/lists.c
@@ -164,6 +164,37 @@ free_INSN_LIST_list (rtx *listp)
free_list (listp, &unused_insn_list);
}
+/* Make a copy of the INSN_LIST list LINK and return it. */
+rtx
+copy_INSN_LIST (rtx link)
+{
+ rtx new_queue;
+ rtx *pqueue = &new_queue;
+
+ for (; link; link = XEXP (link, 1))
+ {
+ rtx x = XEXP (link, 0);
+ rtx newlink = alloc_INSN_LIST (x, NULL);
+ *pqueue = newlink;
+ pqueue = &XEXP (newlink, 1);
+ }
+ *pqueue = NULL_RTX;
+ return new_queue;
+}
+
+/* Duplicate the INSN_LIST elements of COPY and prepend them to OLD. */
+rtx
+concat_INSN_LIST (rtx copy, rtx old)
+{
+ rtx new_rtx = old;
+ for (; copy ; copy = XEXP (copy, 1))
+ {
+ new_rtx = alloc_INSN_LIST (XEXP (copy, 0), new_rtx);
+ PUT_REG_NOTE_KIND (new_rtx, REG_NOTE_KIND (copy));
+ }
+ return new_rtx;
+}
+
/* This function will free up an individual EXPR_LIST node. */
void
free_EXPR_LIST_node (rtx ptr)
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 833bf84743b..98ae19b4aab 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -512,7 +512,13 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
|| referenced_from_other_partition_p (&node->ref_list, set, vset)), 1);
bp_pack_value (&bp, node->lowered, 1);
bp_pack_value (&bp, in_other_partition, 1);
- bp_pack_value (&bp, node->alias && !boundary_p, 1);
+ /* Real aliases in a boundary become non-aliases. However we still stream
+ alias info on weakrefs.
+ TODO: We lose a bit of information here - when we know that variable is
+ defined in other unit, we may use the info on aliases to resolve
+ symbol1 != symbol2 type tests that we can do only for locally defined objects
+ otherwise. */
+ bp_pack_value (&bp, node->alias && (!boundary_p || DECL_EXTERNAL (node->decl)), 1);
bp_pack_value (&bp, node->frequency, 2);
bp_pack_value (&bp, node->only_called_at_startup, 1);
bp_pack_value (&bp, node->only_called_at_exit, 1);
@@ -530,7 +536,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
}
- if ((node->alias || node->thunk.thunk_p) && !boundary_p)
+ if ((node->alias || node->thunk.thunk_p)
+ && (!boundary_p || (node->alias && DECL_EXTERNAL (node->decl))))
{
streamer_write_hwi_in_range (ob->main_stream, 0, 1,
node->thunk.alias != NULL);
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index d4e80c79573..1847738fbc3 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. If not see
#include "lto-streamer.h"
#include "tree-streamer.h"
#include "tree-pass.h"
+#include "streamer-hooks.h"
/* The table to hold the file names. */
static htab_t file_name_hash_table;
@@ -180,15 +181,23 @@ lto_input_location_bitpack (struct data_in *data_in, struct bitpack_d *bp)
}
-/* Read a location from input block IB. */
+/* Read a location from input block IB.
+ If the input_location streamer hook exists, call it.
+ Otherwise, proceed with reading the location from the
+ expanded location bitpack. */
location_t
lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
{
- struct bitpack_d bp;
+ if (streamer_hooks.input_location)
+ return streamer_hooks.input_location (ib, data_in);
+ else
+ {
+ struct bitpack_d bp;
- bp = streamer_read_bitpack (ib);
- return lto_input_location_bitpack (data_in, &bp);
+ bp = streamer_read_bitpack (ib);
+ return lto_input_location_bitpack (data_in, &bp);
+ }
}
@@ -755,27 +764,40 @@ fixup_call_stmt_edges (struct cgraph_node *orig, gimple *stmts)
}
}
-/* Read the body of function FN_DECL from DATA_IN using input block IB. */
+
+/* Input the base body of struct function FN from DATA_IN
+ using input block IB. */
static void
-input_function (tree fn_decl, struct data_in *data_in,
- struct lto_input_block *ib)
+input_struct_function_base (struct function *fn, struct data_in *data_in,
+ struct lto_input_block *ib)
{
- struct function *fn;
- enum LTO_tags tag;
- gimple *stmts;
- basic_block bb;
struct bitpack_d bp;
- struct cgraph_node *node;
- tree args, narg, oarg;
int len;
- fn = DECL_STRUCT_FUNCTION (fn_decl);
- tag = streamer_read_record_start (ib);
- clear_line_info (data_in);
+ /* Read the static chain and non-local goto save area. */
+ fn->static_chain_decl = stream_read_tree (ib, data_in);
+ fn->nonlocal_goto_save_area = stream_read_tree (ib, data_in);
- gimple_register_cfg_hooks ();
- lto_tag_check (tag, LTO_function);
+ /* Read all the local symbols. */
+ len = streamer_read_hwi (ib);
+ if (len > 0)
+ {
+ int i;
+ VEC_safe_grow (tree, gc, fn->local_decls, len);
+ for (i = 0; i < len; i++)
+ {
+ tree t = stream_read_tree (ib, data_in);
+ VEC_replace (tree, fn->local_decls, i, t);
+ }
+ }
+
+ /* Input the function start and end loci. */
+ fn->function_start_locus = lto_input_location (ib, data_in);
+ fn->function_end_locus = lto_input_location (ib, data_in);
+
+ /* Input the current IL state of the function. */
+ fn->curr_properties = streamer_read_uhwi (ib);
/* Read all the attributes for FN. */
bp = streamer_read_bitpack (ib);
@@ -793,30 +815,30 @@ input_function (tree fn_decl, struct data_in *data_in,
fn->calls_setjmp = bp_unpack_value (&bp, 1);
fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
fn->va_list_gpr_size = bp_unpack_value (&bp, 8);
+}
- /* Input the function start and end loci. */
- fn->function_start_locus = lto_input_location (ib, data_in);
- fn->function_end_locus = lto_input_location (ib, data_in);
- /* Input the current IL state of the function. */
- fn->curr_properties = streamer_read_uhwi (ib);
+/* Read the body of function FN_DECL from DATA_IN using input block IB. */
- /* Read the static chain and non-local goto save area. */
- fn->static_chain_decl = stream_read_tree (ib, data_in);
- fn->nonlocal_goto_save_area = stream_read_tree (ib, data_in);
+static void
+input_function (tree fn_decl, struct data_in *data_in,
+ struct lto_input_block *ib)
+{
+ struct function *fn;
+ enum LTO_tags tag;
+ gimple *stmts;
+ basic_block bb;
+ struct cgraph_node *node;
+ tree args, narg, oarg;
- /* Read all the local symbols. */
- len = streamer_read_hwi (ib);
- if (len > 0)
- {
- int i;
- VEC_safe_grow (tree, gc, fn->local_decls, len);
- for (i = 0; i < len; i++)
- {
- tree t = stream_read_tree (ib, data_in);
- VEC_replace (tree, fn->local_decls, i, t);
- }
- }
+ fn = DECL_STRUCT_FUNCTION (fn_decl);
+ tag = streamer_read_record_start (ib);
+ clear_line_info (data_in);
+
+ gimple_register_cfg_hooks ();
+ lto_tag_check (tag, LTO_function);
+
+ input_struct_function_base (fn, data_in, ib);
/* Read all function arguments. We need to re-map them here to the
arguments of the merged function declaration. */
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index c14b3a98df6..62cf9a1832f 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -172,15 +172,21 @@ lto_output_location_bitpack (struct bitpack_d *bp,
/* Emit location LOC to output block OB.
- When bitpack is handy, it is more space effecient to call
+ If the output_location streamer hook exists, call it.
+ Otherwise, when bitpack is handy, it is more space efficient to call
lto_output_location_bitpack with existing bitpack. */
void
lto_output_location (struct output_block *ob, location_t loc)
{
- struct bitpack_d bp = bitpack_create (ob->main_stream);
- lto_output_location_bitpack (&bp, ob, loc);
- streamer_write_bitpack (&bp);
+ if (streamer_hooks.output_location)
+ streamer_hooks.output_location (ob, loc);
+ else
+ {
+ struct bitpack_d bp = bitpack_create (ob->main_stream);
+ lto_output_location_bitpack (&bp, ob, loc);
+ streamer_write_bitpack (&bp);
+ }
}
@@ -713,36 +719,30 @@ produce_asm (struct output_block *ob, tree fn)
}
-/* Output the body of function NODE->DECL. */
+/* Output the base body of struct function FN using output block OB. */
static void
-output_function (struct cgraph_node *node)
+output_struct_function_base (struct output_block *ob, struct function *fn)
{
struct bitpack_d bp;
- tree function;
- struct function *fn;
- basic_block bb;
- struct output_block *ob;
unsigned i;
tree t;
- function = node->decl;
- fn = DECL_STRUCT_FUNCTION (function);
- ob = create_output_block (LTO_section_function_body);
-
- clear_line_info (ob);
- ob->cgraph_node = node;
-
- gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+ /* Output the static chain and non-local goto save area. */
+ stream_write_tree (ob, fn->static_chain_decl, true);
+ stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
- /* Set current_function_decl and cfun. */
- current_function_decl = function;
- push_cfun (fn);
+ /* Output all the local variables in the function. */
+ streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
+ FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
+ stream_write_tree (ob, t, true);
- /* Make string 0 be a NULL string. */
- streamer_write_char_stream (ob->string_stream, 0);
+ /* Output the function start and end loci. */
+ lto_output_location (ob, fn->function_start_locus);
+ lto_output_location (ob, fn->function_end_locus);
- streamer_write_record_start (ob, LTO_function);
+ /* Output current IL state of the function. */
+ streamer_write_uhwi (ob, fn->curr_properties);
/* Write all the attributes for FN. */
bp = bitpack_create (ob->main_stream);
@@ -761,22 +761,38 @@ output_function (struct cgraph_node *node)
bp_pack_value (&bp, fn->va_list_fpr_size, 8);
bp_pack_value (&bp, fn->va_list_gpr_size, 8);
streamer_write_bitpack (&bp);
+}
- /* Output the function start and end loci. */
- lto_output_location (ob, fn->function_start_locus);
- lto_output_location (ob, fn->function_end_locus);
- /* Output current IL state of the function. */
- streamer_write_uhwi (ob, fn->curr_properties);
+/* Output the body of function NODE->DECL. */
- /* Output the static chain and non-local goto save area. */
- stream_write_tree (ob, fn->static_chain_decl, true);
- stream_write_tree (ob, fn->nonlocal_goto_save_area, true);
+static void
+output_function (struct cgraph_node *node)
+{
+ tree function;
+ struct function *fn;
+ basic_block bb;
+ struct output_block *ob;
- /* Output all the local variables in the function. */
- streamer_write_hwi (ob, VEC_length (tree, fn->local_decls));
- FOR_EACH_VEC_ELT (tree, fn->local_decls, i, t)
- stream_write_tree (ob, t, true);
+ function = node->decl;
+ fn = DECL_STRUCT_FUNCTION (function);
+ ob = create_output_block (LTO_section_function_body);
+
+ clear_line_info (ob);
+ ob->cgraph_node = node;
+
+ gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+ /* Set current_function_decl and cfun. */
+ current_function_decl = function;
+ push_cfun (fn);
+
+ /* Make string 0 be a NULL string. */
+ streamer_write_char_stream (ob->string_stream, 0);
+
+ streamer_write_record_start (ob, LTO_function);
+
+ output_struct_function_base (ob, fn);
/* Output the head of the arguments list. */
stream_write_tree (ob, DECL_ARGUMENTS (function), true);
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index f26b3aca510..1bf7ded2524 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -43,6 +43,8 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "diagnostic.h"
#include "obstack.h"
+#include "opts.h"
+#include "options.h"
int debug; /* true if -save-temps. */
int verbose; /* true if -v. */
@@ -280,6 +282,52 @@ fork_execute (char **argv)
/* Template of LTRANS dumpbase suffix. */
#define DUMPBASE_SUFFIX ".ltrans18446744073709551615"
+/* Create decoded options from the COLLECT_GCC and COLLECT_GCC_OPTIONS
+ environment according to LANG_MASK. */
+
+static void
+get_options_from_collect_gcc_options (const char *collect_gcc,
+ const char *collect_gcc_options,
+ unsigned int lang_mask,
+ struct cl_decoded_option **decoded_options,
+ unsigned int *decoded_options_count)
+{
+ char *argv_storage;
+ const char **argv;
+ int i, j, argc;
+
+ /* Count arguments, account for the program name. */
+ argc = 2;
+ for (j = 0; collect_gcc_options[j] != '\0'; ++j)
+ if (collect_gcc_options[j] == '\'')
+ ++argc;
+ if (argc % 2 != 0)
+ fatal ("malformed COLLECT_GCC_OPTIONS");
+
+ /* Copy the options to a argv-like array. */
+ argc /= 2;
+ argv = (const char **) xmalloc ((argc + 2) * sizeof (char *));
+ argv[0] = collect_gcc;
+ argv_storage = xstrdup (collect_gcc_options);
+ for (i = 1, j = 0; argv_storage[j] != '\0'; ++j)
+ {
+ if (argv_storage[j] == '\'')
+ {
+ argv[i++] = &argv_storage[++j];
+ while (argv_storage[j] != '\'')
+ ++j;
+ argv_storage[j] = '\0';
+ }
+ }
+ argv[i] = NULL;
+
+ decode_cmdline_options_to_array (argc, (const char **)argv,
+ lang_mask,
+ decoded_options, decoded_options_count);
+ free (argv);
+}
+
+
/* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
static void
@@ -290,99 +338,88 @@ run_gcc (unsigned argc, char *argv[])
const char **argv_ptr;
char *list_option_full = NULL;
const char *linker_output = NULL;
- const char *collect_gcc_options, *collect_gcc;
- struct obstack env_obstack;
- bool seen_o = false;
+ const char *collect_gcc, *collect_gcc_options;
int parallel = 0;
int jobserver = 0;
bool no_partition = false;
+ struct cl_decoded_option *decoded_options;
+ unsigned int decoded_options_count;
+ struct obstack argv_obstack;
+ int new_head_argc;
/* Get the driver and options. */
collect_gcc = getenv ("COLLECT_GCC");
if (!collect_gcc)
fatal ("environment variable COLLECT_GCC must be set");
-
- /* Set the CFLAGS environment variable. */
collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
if (!collect_gcc_options)
fatal ("environment variable COLLECT_GCC_OPTIONS must be set");
+ get_options_from_collect_gcc_options (collect_gcc, collect_gcc_options,
+ CL_LANG_ALL,
+ &decoded_options,
+ &decoded_options_count);
- /* Count arguments. */
- i = 0;
- for (j = 0; collect_gcc_options[j] != '\0'; ++j)
- if (collect_gcc_options[j] == '\'')
- ++i;
+ /* Initalize the common arguments for the driver. */
+ obstack_init (&argv_obstack);
+ obstack_ptr_grow (&argv_obstack, collect_gcc);
+ obstack_ptr_grow (&argv_obstack, "-xlto");
+ obstack_ptr_grow (&argv_obstack, "-c");
+ for (j = 1; j < decoded_options_count; ++j)
+ {
+ struct cl_decoded_option *option = &decoded_options[j];
- if (i % 2 != 0)
- fatal ("malformed COLLECT_GCC_OPTIONS");
+ /* Do not pass on frontend specific flags not suitable for lto. */
+ if (!(cl_options[option->opt_index].flags
+ & (CL_COMMON|CL_TARGET|CL_DRIVER|CL_LTO)))
+ continue;
- /* Initalize the common arguments for the driver. */
- new_argv = (const char **) xmalloc ((15 + i / 2 + argc) * sizeof (char *));
- argv_ptr = new_argv;
- *argv_ptr++ = collect_gcc;
- *argv_ptr++ = "-xlto";
- *argv_ptr++ = "-c";
- for (j = 0; collect_gcc_options[j] != '\0'; ++j)
- if (collect_gcc_options[j] == '\'')
- {
- char *option;
-
- ++j;
- i = j;
- while (collect_gcc_options[j] != '\'')
- ++j;
-
- obstack_init (&env_obstack);
- obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
- obstack_1grow (&env_obstack, 0);
- option = XOBFINISH (&env_obstack, char *);
- if (seen_o)
- {
- linker_output = option;
- seen_o = false;
- continue;
- }
-
- /* If we see -o, skip it and skip and record its argument. */
- if (option[0] == '-' && option[1] == 'o')
- {
- if (option[2] == '\0')
- seen_o = true;
- else
- linker_output = &option[2];
- continue;
- }
+ switch (option->opt_index)
+ {
+ case OPT_o:
+ linker_output = option->arg;
+ /* We generate new intermediate output, drop this arg. */
+ continue;
- if (strcmp (option, "-save-temps") == 0)
+ case OPT_save_temps:
debug = 1;
- if (strcmp (option, "-v") == 0)
+ break;
+
+ case OPT_v:
verbose = 1;
+ break;
- if (strcmp (option, "-flto-partition=none") == 0)
+ case OPT_flto_partition_none:
no_partition = true;
- /* We've handled these LTO options, do not pass them on. */
- if (strncmp (option, "-flto=", 6) == 0
- || !strcmp (option, "-flto"))
- {
- lto_mode = LTO_MODE_WHOPR;
- if (option[5] == '=')
- {
- if (!strcmp (option + 6, "jobserver"))
- {
- jobserver = 1;
- parallel = 1;
- }
- else
- {
- parallel = atoi (option + 6);
- if (parallel <= 1)
- parallel = 0;
- }
- }
- }
- else
- *argv_ptr++ = option;
- }
+ break;
+
+ case OPT_flto_:
+ if (strcmp (option->arg, "jobserver") == 0)
+ {
+ jobserver = 1;
+ parallel = 1;
+ }
+ else
+ {
+ parallel = atoi (option->arg);
+ if (parallel <= 1)
+ parallel = 0;
+ }
+ /* Fallthru. */
+
+ case OPT_flto:
+ lto_mode = LTO_MODE_WHOPR;
+ /* We've handled these LTO options, do not pass them on. */
+ continue;
+
+ default:
+ break;
+ }
+
+ /* Pass the option on. */
+ for (i = 0; i < option->canonical_option_num_elements; ++i)
+ obstack_ptr_grow (&argv_obstack, option->canonical_option[i]);
+ }
+
if (no_partition)
{
lto_mode = LTO_MODE_LTO;
@@ -410,22 +447,23 @@ run_gcc (unsigned argc, char *argv[])
}
if (!bit_bucket)
{
- *argv_ptr++ = "-dumpdir";
- *argv_ptr++ = output_dir;
+ obstack_ptr_grow (&argv_obstack, "-dumpdir");
+ obstack_ptr_grow (&argv_obstack, output_dir);
}
- *argv_ptr++ = "-dumpbase";
+ obstack_ptr_grow (&argv_obstack, "-dumpbase");
}
- else
- argv_ptr--;
+
+ /* Remember at which point we can scrub args to re-use the commons. */
+ new_head_argc = obstack_object_size (&argv_obstack) / sizeof (void *);
if (lto_mode == LTO_MODE_LTO)
{
flto_out = make_temp_file (".lto.o");
if (linker_output)
- argv_ptr[0] = linker_output;
- argv_ptr[1] = "-o";
- argv_ptr[2] = flto_out;
+ obstack_ptr_grow (&argv_obstack, linker_output);
+ obstack_ptr_grow (&argv_obstack, "-o");
+ obstack_ptr_grow (&argv_obstack, flto_out);
}
else
{
@@ -439,7 +477,7 @@ run_gcc (unsigned argc, char *argv[])
+ sizeof (".wpa") + 1);
strcpy (dumpbase, linker_output);
strcat (dumpbase, ".wpa");
- argv_ptr[0] = dumpbase;
+ obstack_ptr_grow (&argv_obstack, dumpbase);
}
if (linker_output && debug)
@@ -455,19 +493,21 @@ run_gcc (unsigned argc, char *argv[])
(strlen (ltrans_output_file) + list_option_len + 1));
tmp = list_option_full;
- argv_ptr[1] = tmp;
+ obstack_ptr_grow (&argv_obstack, tmp);
strcpy (tmp, list_option);
tmp += list_option_len;
strcpy (tmp, ltrans_output_file);
- argv_ptr[2] = "-fwpa";
+ obstack_ptr_grow (&argv_obstack, "-fwpa");
}
/* Append the input objects and possible preceeding arguments. */
for (i = 1; i < argc; ++i)
- argv_ptr[2 + i] = argv[i];
- argv_ptr[2 + i] = NULL;
+ obstack_ptr_grow (&argv_obstack, argv[i]);
+ obstack_ptr_grow (&argv_obstack, NULL);
+ new_argv = XOBFINISH (&argv_obstack, const char **);
+ argv_ptr = &new_argv[new_head_argc];
fork_execute (CONST_CAST (char **, new_argv));
if (lto_mode == LTO_MODE_LTO)
@@ -480,11 +520,13 @@ run_gcc (unsigned argc, char *argv[])
{
FILE *stream = fopen (ltrans_output_file, "r");
FILE *mstream = NULL;
+ struct obstack env_obstack;
if (!stream)
fatal_perror ("fopen: %s", ltrans_output_file);
/* Parse the list of LTRANS inputs from the WPA stage. */
+ obstack_init (&env_obstack);
nr = 0;
for (;;)
{
@@ -537,7 +579,6 @@ cont:
/* Replace the .o suffix with a .ltrans.o suffix and write
the resulting name to the LTRANS output list. */
- obstack_init (&env_obstack);
obstack_grow (&env_obstack, input_name, strlen (input_name) - 2);
obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
output_name = XOBFINISH (&env_obstack, char *);
@@ -617,9 +658,10 @@ cont:
free (output_names);
free (input_names);
free (list_option_full);
+ obstack_free (&env_obstack, NULL);
}
- obstack_free (&env_obstack, NULL);
+ obstack_free (&argv_obstack, NULL);
}
@@ -662,6 +704,7 @@ main (int argc, char *argv[])
/* We may be called with all the arguments stored in some file and
passed with @file. Expand them into argv before processing. */
expandargv (&argc, &argv);
+
run_gcc (argc, argv);
return 0;
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index e350fd83b05..5de85dd4f33 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,17 @@
+2011-10-09 Jan Hubicka <jh@suse.cz>
+
+ * lto.c (node_cmp, varpool_node_cmp): New functions.
+ (lto_balanced_map): Honnor -fno-toplevel-reorder of vars&functions.
+ (cmp_partitions): Rename to ...
+ (cmp_partitions_size): ... this one.
+ (cmp_partitions_order): New function.
+ (lto_wpa_write_files): Sort partitions by order when
+ -fno-toplevel-reorder is used.
+
+2011-10-09 Andi Kleen <ak@linux.intel.com>
+
+ * lto.c (lto_section_read): Call fatal_error on IO or mmap errors.
+
2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
* lto-lang.c (def_builtin_1): Delete old interface with two
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index a77eeb48c55..c50a97ec205 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -1237,7 +1237,10 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
{
fd = open (file_data->file_name, O_RDONLY|O_BINARY);
if (fd == -1)
- return NULL;
+ {
+ fatal_error ("Cannot open %s", file_data->file_name);
+ return NULL;
+ }
fd_name = xstrdup (file_data->file_name);
}
@@ -1255,7 +1258,10 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
result = (char *) mmap (NULL, computed_len, PROT_READ, MAP_PRIVATE,
fd, computed_offset);
if (result == MAP_FAILED)
- return NULL;
+ {
+ fatal_error ("Cannot map %s", file_data->file_name);
+ return NULL;
+ }
return result + diff;
#else
@@ -1264,6 +1270,7 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
|| read (fd, result, len) != (ssize_t) len)
{
free (result);
+ fatal_error ("Cannot read %s", file_data->file_name);
result = NULL;
}
#ifdef __MINGW32__
@@ -1474,6 +1481,8 @@ add_varpool_node_to_partition (ltrans_partition part, struct varpool_node *vnode
{
varpool_node_set_iterator vsi;
+ vnode = varpool_variable_node (vnode, NULL);
+
/* If NODE is already there, we have nothing to do. */
vsi = varpool_node_set_find (part->varpool_set, vnode);
if (!vsi_end_p (vsi))
@@ -1658,6 +1667,23 @@ lto_1_to_1_map (void)
ltrans_partitions);
}
+/* Helper function for qsort; sort nodes by order. */
+static int
+node_cmp (const void *pa, const void *pb)
+{
+ const struct cgraph_node *a = *(const struct cgraph_node * const *) pa;
+ const struct cgraph_node *b = *(const struct cgraph_node * const *) pb;
+ return b->order - a->order;
+}
+
+/* Helper function for qsort; sort nodes by order. */
+static int
+varpool_node_cmp (const void *pa, const void *pb)
+{
+ const struct varpool_node *a = *(const struct varpool_node * const *) pa;
+ const struct varpool_node *b = *(const struct varpool_node * const *) pb;
+ return b->order - a->order;
+}
/* Group cgraph nodes into equally-sized partitions.
@@ -1701,9 +1727,11 @@ static void
lto_balanced_map (void)
{
int n_nodes = 0;
+ int n_varpool_nodes = 0, varpool_pos = 0;
struct cgraph_node **postorder =
XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
struct cgraph_node **order = XNEWVEC (struct cgraph_node *, cgraph_max_uid);
+ struct varpool_node **varpool_order = NULL;
int i, postorder_len;
struct cgraph_node *node;
int total_size = 0, best_total_size = 0;
@@ -1715,6 +1743,7 @@ lto_balanced_map (void)
int best_n_nodes = 0, best_n_varpool_nodes = 0, best_i = 0, best_cost =
INT_MAX, best_internal = 0;
int npartitions;
+ int current_order = -1;
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
gcc_assert (!vnode->aux);
@@ -1724,6 +1753,7 @@ lto_balanced_map (void)
multiple partitions, this is just an estimate of real size. This is why
we keep partition_size updated after every partition is finalized. */
postorder_len = ipa_reverse_postorder (postorder);
+
for (i = 0; i < postorder_len; i++)
{
node = postorder[i];
@@ -1735,6 +1765,23 @@ lto_balanced_map (void)
}
free (postorder);
+ if (!flag_toplevel_reorder)
+ {
+ qsort (order, n_nodes, sizeof (struct cgraph_node *), node_cmp);
+
+ for (vnode = varpool_nodes; vnode; vnode = vnode->next)
+ if (partition_varpool_node_p (vnode))
+ n_varpool_nodes++;
+ varpool_order = XNEWVEC (struct varpool_node *, n_varpool_nodes);
+
+ n_varpool_nodes = 0;
+ for (vnode = varpool_nodes; vnode; vnode = vnode->next)
+ if (partition_varpool_node_p (vnode))
+ varpool_order[n_varpool_nodes++] = vnode;
+ qsort (varpool_order, n_varpool_nodes, sizeof (struct varpool_node *),
+ varpool_node_cmp);
+ }
+
/* Compute partition size and create the first partition. */
partition_size = total_size / PARAM_VALUE (PARAM_LTO_PARTITIONS);
if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE))
@@ -1749,8 +1796,20 @@ lto_balanced_map (void)
{
if (order[i]->aux)
continue;
+
+ current_order = order[i]->order;
+
+ if (!flag_toplevel_reorder)
+ while (varpool_pos < n_varpool_nodes && varpool_order[varpool_pos]->order < current_order)
+ {
+ if (!varpool_order[varpool_pos]->aux)
+ add_varpool_node_to_partition (partition, varpool_order[varpool_pos]);
+ varpool_pos++;
+ }
+
add_cgraph_node_to_partition (partition, order[i]);
total_size -= inline_summary (order[i])->size;
+
/* Once we added a new node to the partition, we also want to add
all referenced variables unless they was already added into some
@@ -1789,7 +1848,7 @@ lto_balanced_map (void)
gcc_assert (node->analyzed);
- /* Compute boundary cost of callgrpah edges. */
+ /* Compute boundary cost of callgraph edges. */
for (edge = node->callees; edge; edge = edge->next_callee)
if (edge->callee->analyzed)
{
@@ -1841,7 +1900,8 @@ lto_balanced_map (void)
vnode = ipa_ref_varpool_node (ref);
if (!vnode->finalized)
continue;
- if (!vnode->aux && partition_varpool_node_p (vnode))
+ if (!vnode->aux && flag_toplevel_reorder
+ && partition_varpool_node_p (vnode))
add_varpool_node_to_partition (partition, vnode);
vsi = varpool_node_set_find (partition->varpool_set, vnode);
if (!vsi_end_p (vsi)
@@ -1871,7 +1931,8 @@ lto_balanced_map (void)
vnode = ipa_ref_refering_varpool_node (ref);
gcc_assert (vnode->finalized);
- if (!vnode->aux && partition_varpool_node_p (vnode))
+ if (!vnode->aux && flag_toplevel_reorder
+ && partition_varpool_node_p (vnode))
add_varpool_node_to_partition (partition, vnode);
vsi = varpool_node_set_find (partition->varpool_set, vnode);
if (!vsi_end_p (vsi)
@@ -1960,9 +2021,22 @@ lto_balanced_map (void)
}
/* Varables that are not reachable from the code go into last partition. */
- for (vnode = varpool_nodes; vnode; vnode = vnode->next)
- if (partition_varpool_node_p (vnode) && !vnode->aux)
- add_varpool_node_to_partition (partition, vnode);
+ if (flag_toplevel_reorder)
+ {
+ for (vnode = varpool_nodes; vnode; vnode = vnode->next)
+ if (partition_varpool_node_p (vnode) && !vnode->aux)
+ add_varpool_node_to_partition (partition, vnode);
+ }
+ else
+ {
+ while (varpool_pos < n_varpool_nodes)
+ {
+ if (!varpool_order[varpool_pos]->aux)
+ add_varpool_node_to_partition (partition, varpool_order[varpool_pos]);
+ varpool_pos++;
+ }
+ free (varpool_order);
+ }
free (order);
}
@@ -2127,7 +2201,7 @@ static lto_file *current_lto_file;
longest compilation being executed too late. */
static int
-cmp_partitions (const void *a, const void *b)
+cmp_partitions_size (const void *a, const void *b)
{
const struct ltrans_partition_def *pa
= *(struct ltrans_partition_def *const *)a;
@@ -2136,6 +2210,28 @@ cmp_partitions (const void *a, const void *b)
return pb->insns - pa->insns;
}
+/* Helper for qsort; compare partitions and return one with smaller order. */
+
+static int
+cmp_partitions_order (const void *a, const void *b)
+{
+ const struct ltrans_partition_def *pa
+ = *(struct ltrans_partition_def *const *)a;
+ const struct ltrans_partition_def *pb
+ = *(struct ltrans_partition_def *const *)b;
+ int ordera = -1, orderb = -1;
+
+ if (VEC_length (cgraph_node_ptr, pa->cgraph_set->nodes))
+ ordera = VEC_index (cgraph_node_ptr, pa->cgraph_set->nodes, 0)->order;
+ else if (VEC_length (varpool_node_ptr, pa->varpool_set->nodes))
+ ordera = VEC_index (varpool_node_ptr, pa->varpool_set->nodes, 0)->order;
+ if (VEC_length (cgraph_node_ptr, pb->cgraph_set->nodes))
+ orderb = VEC_index (cgraph_node_ptr, pb->cgraph_set->nodes, 0)->order;
+ else if (VEC_length (varpool_node_ptr, pb->varpool_set->nodes))
+ orderb = VEC_index (varpool_node_ptr, pb->varpool_set->nodes, 0)->order;
+ return orderb - ordera;
+}
+
/* Write all output files in WPA mode and the file with the list of
LTRANS units. */
@@ -2184,7 +2280,12 @@ lto_wpa_write_files (void)
blen = strlen (temp_filename);
n_sets = VEC_length (ltrans_partition, ltrans_partitions);
- VEC_qsort (ltrans_partition, ltrans_partitions, cmp_partitions);
+
+ /* Sort partitions by size so small ones are compiled last.
+ FIXME: Even when not reordering we may want to output one list for parallel make
+ and other for final link command. */
+ VEC_qsort (ltrans_partition, ltrans_partitions,
+ flag_toplevel_reorder ? cmp_partitions_size : cmp_partitions_order);
for (i = 0; i < n_sets; i++)
{
size_t len;
diff --git a/gcc/mkconfig.sh b/gcc/mkconfig.sh
index d96af1d2f2b..e93d45fabb3 100644
--- a/gcc/mkconfig.sh
+++ b/gcc/mkconfig.sh
@@ -89,9 +89,8 @@ if [ -n "$HEADERS" ]; then
fi
# If this is tm.h, now include insn-flags.h only if IN_GCC is defined
-# but neither GENERATOR_FILE nor USED_FOR_TARGET is defined. Also
-# include libgcc_tm.h if USED_FOR_TARGET is defined. (Much of this is
-# temporary.)
+# but neither GENERATOR_FILE nor USED_FOR_TARGET is defined. (Much of this
+# is temporary.)
case $output in
tm.h )
@@ -99,9 +98,6 @@ case $output in
#if defined IN_GCC && !defined GENERATOR_FILE && !defined USED_FOR_TARGET
# include "insn-flags.h"
#endif
-#ifdef USED_FOR_TARGET
-# include "libgcc_tm.h"
-#endif
EOF
;;
esac
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index f2fd445fa06..0ea9a4d9a62 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -1173,6 +1173,8 @@ generate_prolog_epilog (partial_schedule_ptr ps, struct loop *loop,
/* Put the prolog on the entry edge. */
e = loop_preheader_edge (loop);
split_edge_and_insert (e, get_insns ());
+ if (!flag_resched_modulo_sched)
+ e->dest->flags |= BB_DISABLE_SCHEDULE;
end_sequence ();
@@ -1186,9 +1188,24 @@ generate_prolog_epilog (partial_schedule_ptr ps, struct loop *loop,
gcc_assert (single_exit (loop));
e = single_exit (loop);
split_edge_and_insert (e, get_insns ());
+ if (!flag_resched_modulo_sched)
+ e->dest->flags |= BB_DISABLE_SCHEDULE;
+
end_sequence ();
}
+/* Mark LOOP as software pipelined so the later
+ scheduling passes don't touch it. */
+static void
+mark_loop_unsched (struct loop *loop)
+{
+ unsigned i;
+ basic_block *bbs = get_loop_body (loop);
+
+ for (i = 0; i < loop->num_nodes; i++)
+ bbs[i]->flags |= BB_DISABLE_SCHEDULE;
+}
+
/* Return true if all the BBs of the loop are empty except the
loop header. */
static bool
@@ -1714,9 +1731,10 @@ sms_schedule (void)
permute_partial_schedule (ps, g->closing_branch->first_note);
/* Mark this loop as software pipelined so the later
- scheduling passes doesn't touch it. */
+ scheduling passes don't touch it. */
if (! flag_resched_modulo_sched)
- g->bb->flags |= BB_DISABLE_SCHEDULE;
+ mark_loop_unsched (loop);
+
/* The life-info is not valid any more. */
df_set_bb_dirty (g->bb);
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index e195ed5dd1b..26b98983ea1 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,69 @@
+2011-10-29 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/47997
+ * objc-act.c (objc_build_string_object): Remove redundant second
+ call to fix_string_type (). Add a checking assert that we are,
+ indeed, passed a STRING_CST.
+
+2011-10-18 Mikael Pettersson <mikpe@it.uu.se>
+
+ PR objc/50743
+ * objc-act.c (check_duplicates): Cast TREE_VEC_LENGTH result to
+ size_t to avoid signed/unsigned
+ comparison.
+ (insert_method_into_method_map): Likewise.
+
+2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * objc-map.h: New file.
+ * objc-map.c: New file.
+ * config-lang.in (gtfiles): Added objc-map.h.
+ * Make-lang.in (OBJC_OBJS): Added objc-map.o.
+ (objc/objc-map.o): New rule.
+ (objc/objc-act.o): Depend on objc/objc-map.h.
+ * objc-next-runtime-abi-02.c: Added a TODO comment.
+ * objc-act.c: Include objc-map.h.
+ (nst_method_hash_list, cls_method_hash_list): Removed.
+ (instance_method_map, class_method_map): New.
+ (cls_name_hash_list, als_name_hash_list): Removed.
+ (class_name_map, alias_name_map): Removed.
+ (ivar_offset_hash_list): Removed.
+ (hash_class_name_enter, hash_class_name_lookup, hash_enter,
+ hash_lookup, hash_add_attr, add_method_to_hash_list): Removed.
+ (interface_hash_init): New.
+ (objc_init): Call interface_hash_init.
+ (objc_write_global_declarations): Iterate over class_method_map
+ and instance_method_map instead of cls_method_hash_list and
+ nst_method_hash_list.
+ (objc_declare_alias): Use alias_name_map instead of
+ cls_name_hash_list.
+ (objc_is_class_name): Use class_name_map and alias_name_map
+ instead of cls_name_hash_list and als_name_hash_list.
+ (interface_tuple, interface_htab, hash_interface, eq_interface):
+ Removed.
+ (interface_map): New.
+ (add_class): Renamed to add_interface. Use interface_map instead
+ of interface_htab.
+ (lookup_interface): Use interface_map instead of interface_htab.
+ (check_duplicates): Changed first argument to be a tree,
+ potentially a TREE_VEC, instead of a hash. Changed implementation
+ to match.
+ (lookup_method_in_hash_lists): Use class_method_map and
+ instance_method_map instead of cls_method_hash_list and
+ nst_method_hash_list.
+ (objc_build_selector_expr): Likewise.
+ (hash_func): Removed.
+ (hash_init): Create instance_method_map, class_method_map,
+ class_name_map, and alias_name_map. Do not create
+ nst_method_hash_list, cls_method_hash_list, cls_name_hash_list,
+ als_name_hash_list, and ivar_offset_hash_list.
+ (insert_method_into_method_map): New.
+ (objc_add_method): Use insert_method_into_method_map instead of
+ add_method_to_hash_list.
+ (start_class): Call add_interface instead of add_class.
+ * objc-act.h (cls_name_hash_list, als_name_hash_list,
+ nst_method_hash_list, cls_method_hash_list): Removed.
+
2011-10-11 Michael Meissner <meissner@linux.vnet.ibm.com>
* objc-next-runtime-abi-01.c (objc_build_exc_ptr): Delete old
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index f9b3907fe1c..5cca11a6b4d 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -55,7 +55,8 @@ OBJC_OBJS = objc/objc-lang.o objc/objc-act.o \
objc/objc-gnu-runtime-abi-01.o \
objc/objc-next-runtime-abi-01.o \
objc/objc-next-runtime-abi-02.o \
- objc/objc-encoding.o
+ objc/objc-encoding.o \
+ objc/objc-map.o
objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
@@ -129,6 +130,7 @@ objc/objc-act.o : objc/objc-act.c \
$(HASHTAB_H) $(GIMPLE_H) \
$(C_PRAGMA_H) $(C_TARGET_H) \
objc/objc-encoding.h \
+ objc/objc-map.h \
objc/objc-runtime-hooks.h \
objc/objc-runtime-shared-support.h
@@ -139,6 +141,12 @@ objc/objc-encoding.o : objc/objc-encoding.c \
objc/objc-encoding.h \
objc/objc-runtime-shared-support.h
+objc/objc-map.o : objc/objc-map.c \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ objc/objc-map.h
+
objc.srcextra:
#
diff --git a/gcc/objc/config-lang.in b/gcc/objc/config-lang.in
index 0de0650c0de..48f8582d74c 100644
--- a/gcc/objc/config-lang.in
+++ b/gcc/objc/config-lang.in
@@ -36,4 +36,4 @@ lang_requires="c"
# Order is important. If you change this list, make sure you test
# building without C++ as well; that is, remove the gcc/cp directory,
# and build with --enable-languages=c,objc.
-gtfiles="\$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
+gtfiles="\$(srcdir)/objc/objc-map.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-parser.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-lang.h \$(srcdir)/c-objc-common.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-cppbuiltin.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c"
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 72a486d9c83..4a024f419a7 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "langhooks.h"
#include "objc-act.h"
+#include "objc-map.h"
#include "input.h"
#include "function.h"
#include "output.h"
@@ -157,27 +158,25 @@ static void objc_generate_cxx_cdtors (void);
static void objc_decl_method_attributes (tree*, tree, int);
static tree build_keyword_selector (tree);
-/* Hash tables to manage the global pool of method prototypes. */
static void hash_init (void);
-hash *nst_method_hash_list = 0;
-hash *cls_method_hash_list = 0;
+/* Hash tables to manage the global pool of method prototypes. Each
+ of these maps map a method name (selector) identifier to either a
+ single tree (for methods with a single method prototype) or a
+ TREE_VEC (for methods with multiple method prototypes). */
+static GTY(()) objc_map_t instance_method_map = 0;
+static GTY(()) objc_map_t class_method_map = 0;
/* Hash tables to manage the global pool of class names. */
-hash *cls_name_hash_list = 0;
-hash *als_name_hash_list = 0;
+static GTY(()) objc_map_t class_name_map = 0;
+static GTY(()) objc_map_t alias_name_map = 0;
-hash *ivar_offset_hash_list = 0;
-
-static void hash_class_name_enter (hash *, tree, tree);
-static hash hash_class_name_lookup (hash *, tree);
-
-static hash hash_lookup (hash *, tree);
static tree lookup_method (tree, tree);
static tree lookup_method_static (tree, tree, int);
-static tree add_class (tree, tree);
+static void interface_hash_init (void);
+static tree add_interface (tree, tree);
static void add_category (tree, tree);
static inline tree lookup_category (tree, tree);
@@ -207,7 +206,7 @@ static void generate_struct_by_value_array (void) ATTRIBUTE_NORETURN;
static void mark_referenced_methods (void);
static bool objc_type_valid_for_messaging (tree type, bool allow_classes);
-static tree check_duplicates (hash, int, int);
+static tree check_duplicates (tree, int, int);
/*** Private Interface (data) ***/
/* Flags for lookup_method_static(). */
@@ -380,6 +379,7 @@ objc_init (void)
/* Set up stuff used by FE parser and all runtimes. */
errbuf = XNEWVEC (char, 1024 * 10);
+ interface_hash_init ();
hash_init ();
objc_encoding_init ();
/* ... and then check flags and set-up for the selected runtime ... */
@@ -418,19 +418,15 @@ objc_write_global_declarations (void)
if (warn_selector)
{
- int slot;
- hash hsh;
+ objc_map_iterator_t i;
- /* Run through the selector hash tables and print a warning for any
- selector which has multiple methods. */
+ objc_map_iterator_initialize (class_method_map, &i);
+ while (objc_map_iterator_move_to_next (class_method_map, &i))
+ check_duplicates (objc_map_iterator_current_value (class_method_map, i), 0, 1);
- for (slot = 0; slot < SIZEHASHTABLE; slot++)
- {
- for (hsh = cls_method_hash_list[slot]; hsh; hsh = hsh->next)
- check_duplicates (hsh, 0, 1);
- for (hsh = nst_method_hash_list[slot]; hsh; hsh = hsh->next)
- check_duplicates (hsh, 0, 0);
- }
+ objc_map_iterator_initialize (instance_method_map, &i);
+ while (objc_map_iterator_move_to_next (instance_method_map, &i))
+ check_duplicates (objc_map_iterator_current_value (instance_method_map, i), 0, 0);
}
/* TODO: consider an early exit here if either errorcount or sorrycount
@@ -3132,9 +3128,8 @@ objc_build_string_object (tree string)
struct string_descriptor *desc, key;
void **loc;
- /* Prep the string argument. */
- string = fix_string_type (string);
- TREE_SET_CODE (string, STRING_CST);
+ /* We should be passed a STRING_CST. */
+ gcc_checking_assert (TREE_CODE (string) == STRING_CST);
length = TREE_STRING_LENGTH (string) - 1;
/* The target may have different ideas on how to construct an ObjC string
@@ -3351,8 +3346,7 @@ objc_declare_alias (tree alias_ident, tree class_ident)
#ifdef OBJCPLUS
pop_lang_context ();
#endif
- hash_class_name_enter (als_name_hash_list, alias_ident,
- underlying_class);
+ objc_map_put (alias_name_map, alias_ident, underlying_class);
}
}
@@ -3392,15 +3386,13 @@ objc_declare_class (tree identifier)
the TYPE_OBJC_INTERFACE. If later an @interface is found,
we'll replace the ident with the interface. */
TYPE_OBJC_INTERFACE (record) = identifier;
- hash_class_name_enter (cls_name_hash_list, identifier, NULL_TREE);
+ objc_map_put (class_name_map, identifier, NULL_TREE);
}
}
tree
objc_is_class_name (tree ident)
{
- hash target;
-
if (ident && TREE_CODE (ident) == IDENTIFIER_NODE)
{
tree t = identifier_global_value (ident);
@@ -3428,16 +3420,17 @@ objc_is_class_name (tree ident)
if (lookup_interface (ident))
return ident;
- target = hash_class_name_lookup (cls_name_hash_list, ident);
- if (target)
- return target->key;
+ {
+ tree target;
- target = hash_class_name_lookup (als_name_hash_list, ident);
- if (target)
- {
- gcc_assert (target->list && target->list->value);
- return target->list->value;
- }
+ target = objc_map_get (class_name_map, ident);
+ if (target != OBJC_MAP_NOT_FOUND)
+ return ident;
+
+ target = objc_map_get (alias_name_map, ident);
+ if (target != OBJC_MAP_NOT_FOUND)
+ return target;
+ }
return 0;
}
@@ -3761,25 +3754,30 @@ objc_generate_write_barrier (tree lhs, enum tree_code modifycode, tree rhs)
return result;
}
-struct GTY(()) interface_tuple {
- tree id;
- tree class_name;
-};
+/* Implementation of the table mapping a class name (as an identifier)
+ to a class node. The two public functions for it are
+ lookup_interface() and add_interface(). add_interface() is only
+ used in this file, so we can make it static. */
-static GTY ((param_is (struct interface_tuple))) htab_t interface_htab;
+static GTY(()) objc_map_t interface_map;
-static hashval_t
-hash_interface (const void *p)
+static void
+interface_hash_init (void)
{
- const struct interface_tuple *d = (const struct interface_tuple *) p;
- return IDENTIFIER_HASH_VALUE (d->id);
+ interface_map = objc_map_alloc_ggc (200);
}
-static int
-eq_interface (const void *p1, const void *p2)
+static tree
+add_interface (tree class_name, tree name)
{
- const struct interface_tuple *d = (const struct interface_tuple *) p1;
- return d->id == p2;
+ /* Put interfaces on list in reverse order. */
+ TREE_CHAIN (class_name) = interface_chain;
+ interface_chain = class_name;
+
+ /* Add it to the map. */
+ objc_map_put (interface_map, name, class_name);
+
+ return interface_chain;
}
tree
@@ -3794,19 +3792,12 @@ lookup_interface (tree ident)
return NULL_TREE;
{
- struct interface_tuple **slot;
- tree i = NULL_TREE;
+ tree interface = objc_map_get (interface_map, ident);
- if (interface_htab)
- {
- slot = (struct interface_tuple **)
- htab_find_slot_with_hash (interface_htab, ident,
- IDENTIFIER_HASH_VALUE (ident),
- NO_INSERT);
- if (slot && *slot)
- i = (*slot)->class_name;
- }
- return i;
+ if (interface == OBJC_MAP_NOT_FOUND)
+ return NULL_TREE;
+ else
+ return interface;
}
}
@@ -5052,71 +5043,75 @@ build_function_type_for_method (tree return_type, tree method,
return ftype;
}
+/* The 'method' argument is a tree; this tree could either be a single
+ method, which is returned, or could be a TREE_VEC containing a list
+ of methods. In that case, the first one is returned, and warnings
+ are issued as appropriate. */
static tree
-check_duplicates (hash hsh, int methods, int is_class)
+check_duplicates (tree method, int methods, int is_class)
{
- tree meth = NULL_TREE;
-
- if (hsh)
- {
- meth = hsh->key;
-
- if (hsh->list)
- {
- /* We have two or more methods with the same name but
- different types. */
- attr loop;
-
- /* But just how different are those types? If
- -Wno-strict-selector-match is specified, we shall not
- complain if the differences are solely among types with
- identical size and alignment. */
- if (!warn_strict_selector_match)
- {
- for (loop = hsh->list; loop; loop = loop->next)
- if (!comp_proto_with_proto (meth, loop->value, 0))
- goto issue_warning;
-
- return meth;
- }
-
- issue_warning:
- if (methods)
- {
- bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
-
- warning_at (input_location, 0,
- "multiple methods named %<%c%E%> found",
- (is_class ? '+' : '-'),
- METHOD_SEL_NAME (meth));
- inform (DECL_SOURCE_LOCATION (meth), "using %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (meth)));
- }
- else
- {
- bool type = TREE_CODE (meth) == INSTANCE_METHOD_DECL;
+ tree first_method;
+ size_t i;
- warning_at (input_location, 0,
- "multiple selectors named %<%c%E%> found",
- (is_class ? '+' : '-'),
- METHOD_SEL_NAME (meth));
- inform (DECL_SOURCE_LOCATION (meth), "found %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (meth)));
- }
-
- for (loop = hsh->list; loop; loop = loop->next)
- {
- bool type = TREE_CODE (loop->value) == INSTANCE_METHOD_DECL;
+ if (method == NULL_TREE)
+ return NULL_TREE;
- inform (DECL_SOURCE_LOCATION (loop->value), "also found %<%c%s%>",
- (type ? '-' : '+'),
- identifier_to_locale (gen_method_decl (loop->value)));
- }
- }
+ if (TREE_CODE (method) != TREE_VEC)
+ return method;
+
+ /* We have two or more methods with the same name but different
+ types. */
+ first_method = TREE_VEC_ELT (method, 0);
+
+ /* But just how different are those types? If
+ -Wno-strict-selector-match is specified, we shall not complain if
+ the differences are solely among types with identical size and
+ alignment. */
+ if (!warn_strict_selector_match)
+ {
+ for (i = 0; i < (size_t) TREE_VEC_LENGTH (method); i++)
+ if (!comp_proto_with_proto (first_method, TREE_VEC_ELT (method, i), 0))
+ goto issue_warning;
+
+ return first_method;
+ }
+
+ issue_warning:
+ if (methods)
+ {
+ bool type = TREE_CODE (first_method) == INSTANCE_METHOD_DECL;
+
+ warning_at (input_location, 0,
+ "multiple methods named %<%c%E%> found",
+ (is_class ? '+' : '-'),
+ METHOD_SEL_NAME (first_method));
+ inform (DECL_SOURCE_LOCATION (first_method), "using %<%c%s%>",
+ (type ? '-' : '+'),
+ identifier_to_locale (gen_method_decl (first_method)));
}
- return meth;
+ else
+ {
+ bool type = TREE_CODE (first_method) == INSTANCE_METHOD_DECL;
+
+ warning_at (input_location, 0,
+ "multiple selectors named %<%c%E%> found",
+ (is_class ? '+' : '-'),
+ METHOD_SEL_NAME (first_method));
+ inform (DECL_SOURCE_LOCATION (first_method), "found %<%c%s%>",
+ (type ? '-' : '+'),
+ identifier_to_locale (gen_method_decl (first_method)));
+ }
+
+ for (i = 0; i < (size_t) TREE_VEC_LENGTH (method); i++)
+ {
+ bool type = TREE_CODE (TREE_VEC_ELT (method, i)) == INSTANCE_METHOD_DECL;
+
+ inform (DECL_SOURCE_LOCATION (TREE_VEC_ELT (method, i)), "also found %<%c%s%>",
+ (type ? '-' : '+'),
+ identifier_to_locale (gen_method_decl (TREE_VEC_ELT (method, i))));
+ }
+
+ return first_method;
}
/* If RECEIVER is a class reference, return the identifier node for
@@ -5294,17 +5289,18 @@ objc_build_message_expr (tree receiver, tree message_args)
static tree
lookup_method_in_hash_lists (tree sel_name, int is_class)
{
- hash method_prototype = NULL;
+ tree method_prototype = OBJC_MAP_NOT_FOUND;
if (!is_class)
- method_prototype = hash_lookup (nst_method_hash_list,
- sel_name);
-
- if (!method_prototype)
+ method_prototype = objc_map_get (instance_method_map, sel_name);
+
+ if (method_prototype == OBJC_MAP_NOT_FOUND)
{
- method_prototype = hash_lookup (cls_method_hash_list,
- sel_name);
+ method_prototype = objc_map_get (class_method_map, sel_name);
is_class = 1;
+
+ if (method_prototype == OBJC_MAP_NOT_FOUND)
+ return NULL_TREE;
}
return check_duplicates (method_prototype, 1, is_class);
@@ -5714,21 +5710,19 @@ objc_build_selector_expr (location_t loc, tree selnamelist)
/* 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;
+ tree method;
/* First try with instance methods. */
- hsh = hash_lookup (nst_method_hash_list, selname);
+ method = objc_map_get (instance_method_map, selname);
/* If not found, try with class methods. */
- if (!hsh)
+ if (method == OBJC_MAP_NOT_FOUND)
{
- hsh = hash_lookup (cls_method_hash_list, selname);
- }
+ method = objc_map_get (class_method_map, selname);
- /* If still not found, print out a warning. */
- if (!hsh)
- {
- warning (0, "undeclared selector %qE", selname);
+ /* If still not found, print out a warning. */
+ if (method == OBJC_MAP_NOT_FOUND)
+ warning (0, "undeclared selector %qE", selname);
}
}
@@ -5761,131 +5755,99 @@ build_ivar_reference (tree id)
return (*runtime.build_ivar_reference) (input_location, base, id);
}
-/* Compute a hash value for a given method SEL_NAME. */
-
-static size_t
-hash_func (tree sel_name)
-{
- const unsigned char *s
- = (const unsigned char *)IDENTIFIER_POINTER (sel_name);
- size_t h = 0;
-
- while (*s)
- h = h * 67 + *s++ - 113;
- return h;
-}
-
static void
hash_init (void)
{
- nst_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
- cls_method_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
-
- cls_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
- als_name_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+ instance_method_map = objc_map_alloc_ggc (1000);
+ class_method_map = objc_map_alloc_ggc (1000);
- ivar_offset_hash_list = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+ class_name_map = objc_map_alloc_ggc (200);
+ alias_name_map = objc_map_alloc_ggc (200);
/* Initialize the hash table used to hold the constant string objects. */
string_htab = htab_create_ggc (31, string_hash,
string_eq, NULL);
}
-/* This routine adds sel_name to the hash list. sel_name is a class or alias
- name for the class. If alias name, then value is its underlying class.
- If class, the value is NULL_TREE. */
-
+/* Use the following to add a method to class_method_map or
+ instance_method_map. It will add the method, keyed by the
+ METHOD_SEL_NAME. If the method already exists, but with one or
+ more different prototypes, it will store a TREE_VEC in the map,
+ with the method prototypes in the vector. */
static void
-hash_class_name_enter (hash *hashlist, tree sel_name, tree value)
+insert_method_into_method_map (bool class_method, tree method)
{
- hash obj;
- int slot = hash_func (sel_name) % SIZEHASHTABLE;
+ tree method_name = METHOD_SEL_NAME (method);
+ tree existing_entry;
+ objc_map_t map;
- obj = ggc_alloc_hashed_entry ();
- if (value != NULL_TREE)
- {
- /* Save the underlying class for the 'alias' in the hash table */
- attr obj_attr = ggc_alloc_hashed_attribute ();
- obj_attr->value = value;
- obj->list = obj_attr;
- }
+ if (class_method)
+ map = class_method_map;
else
- obj->list = 0;
- obj->next = hashlist[slot];
- obj->key = sel_name;
-
- hashlist[slot] = obj; /* append to front */
+ map = instance_method_map;
-}
+ /* Check if the method already exists in the map. */
+ existing_entry = objc_map_get (map, method_name);
-/*
- Searches in the hash table looking for a match for class or alias name.
-*/
-
-static hash
-hash_class_name_lookup (hash *hashlist, tree sel_name)
-{
- hash target;
-
- target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
-
- while (target)
+ /* If not, we simply add it to the map. */
+ if (existing_entry == OBJC_MAP_NOT_FOUND)
+ objc_map_put (map, method_name, method);
+ else
{
- if (sel_name == target->key)
- return target;
-
- target = target->next;
- }
- return 0;
-}
-
-/* WARNING!!!! hash_enter is called with a method, and will peek
- inside to find its selector! But hash_lookup is given a selector
- directly, and looks for the selector that's inside the found
- entry's key (method) for comparison. */
-
-static void
-hash_enter (hash *hashlist, tree method)
-{
- hash obj;
- int slot = hash_func (METHOD_SEL_NAME (method)) % SIZEHASHTABLE;
-
- obj = ggc_alloc_hashed_entry ();
- obj->list = 0;
- obj->next = hashlist[slot];
- obj->key = method;
-
- hashlist[slot] = obj; /* append to front */
-}
-
-static hash
-hash_lookup (hash *hashlist, tree sel_name)
-{
- hash target;
+ tree new_entry;
+
+ /* If an entry already exists, it's more complicated. We'll
+ have to check whether the method prototype is the same or
+ not. */
+ if (TREE_CODE (existing_entry) != TREE_VEC)
+ {
+ /* If the method prototypes are the same, there is nothing
+ to do. */
+ if (comp_proto_with_proto (method, existing_entry, 1))
+ return;
- target = hashlist[hash_func (sel_name) % SIZEHASHTABLE];
+ /* If not, create a vector to store both the method already
+ in the map, and the new one that we are adding. */
+ new_entry = make_tree_vec (2);
+
+ TREE_VEC_ELT (new_entry, 0) = existing_entry;
+ TREE_VEC_ELT (new_entry, 1) = method;
+ }
+ else
+ {
+ /* An entry already exists, and it's already a vector. This
+ means that at least 2 different method prototypes were
+ already found, and we're considering registering yet
+ another one. */
+ size_t i;
+
+ /* Check all the existing prototypes. If any matches the
+ one we need to add, there is nothing to do because it's
+ already there. */
+ for (i = 0; i < (size_t) TREE_VEC_LENGTH (existing_entry); i++)
+ if (comp_proto_with_proto (method, TREE_VEC_ELT (existing_entry, i), 1))
+ return;
- while (target)
- {
- if (sel_name == METHOD_SEL_NAME (target->key))
- return target;
+ /* Else, create a new, bigger vector and add the new method
+ at the end of it. This is inefficient but extremely
+ rare; in any sane program most methods have a single
+ prototype, and very few, if any, will have more than
+ 2! */
+ new_entry = make_tree_vec (TREE_VEC_LENGTH (existing_entry) + 1);
+
+ /* Copy the methods from the existing vector. */
+ for (i = 0; i < (size_t) TREE_VEC_LENGTH (existing_entry); i++)
+ TREE_VEC_ELT (new_entry, i) = TREE_VEC_ELT (existing_entry, i);
+
+ /* Add the new method at the end. */
+ TREE_VEC_ELT (new_entry, i) = method;
+ }
- target = target->next;
+ /* Store the new vector in the map. */
+ objc_map_put (map, method_name, new_entry);
}
- return 0;
}
-static void
-hash_add_attr (hash entry, tree value)
-{
- attr obj;
-
- obj = ggc_alloc_hashed_attribute ();
- obj->next = entry->list;
- obj->value = value;
-
- entry->list = obj; /* append to front */
-}
static tree
lookup_method (tree mchain, tree method)
@@ -5988,31 +5950,6 @@ lookup_method_static (tree interface, tree ident, int flags)
}
}
-/* Add the method to the hash list if it doesn't contain an identical
- method already. */
-
-static void
-add_method_to_hash_list (hash *hash_list, tree method)
-{
- hash hsh;
-
- if (!(hsh = hash_lookup (hash_list, METHOD_SEL_NAME (method))))
- {
- /* Install on a global chain. */
- hash_enter (hash_list, method);
- }
- else
- {
- /* Check types against those; if different, add to a list. */
- attr loop;
- int already_there = comp_proto_with_proto (method, hsh->key, 1);
- for (loop = hsh->list; !already_there && loop; loop = loop->next)
- already_there |= comp_proto_with_proto (method, loop->value, 1);
- if (!already_there)
- hash_add_attr (hsh, method);
- }
-}
-
static tree
objc_add_method (tree klass, tree method, int is_class, bool is_optional)
{
@@ -6135,10 +6072,10 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional)
}
if (is_class)
- add_method_to_hash_list (cls_method_hash_list, method);
+ insert_method_into_method_map (true, method);
else
{
- add_method_to_hash_list (nst_method_hash_list, method);
+ insert_method_into_method_map (false, method);
/* Instance methods in root classes (and categories thereof)
may act as class methods as a last resort. We also add
@@ -6151,37 +6088,12 @@ objc_add_method (tree klass, tree method, int is_class, bool is_optional)
if (TREE_CODE (klass) == PROTOCOL_INTERFACE_TYPE
|| !CLASS_SUPER_NAME (klass))
- add_method_to_hash_list (cls_method_hash_list, method);
+ insert_method_into_method_map (true, method);
}
return method;
}
-static tree
-add_class (tree class_name, tree name)
-{
- struct interface_tuple **slot;
-
- /* Put interfaces on list in reverse order. */
- TREE_CHAIN (class_name) = interface_chain;
- interface_chain = class_name;
-
- if (interface_htab == NULL)
- interface_htab = htab_create_ggc (31, hash_interface, eq_interface, NULL);
- slot = (struct interface_tuple **)
- htab_find_slot_with_hash (interface_htab, name,
- IDENTIFIER_HASH_VALUE (name),
- INSERT);
- if (!*slot)
- {
- *slot = ggc_alloc_cleared_interface_tuple ();
- (*slot)->id = name;
- }
- (*slot)->class_name = class_name;
-
- return interface_chain;
-}
-
static void
add_category (tree klass, tree category)
{
@@ -6951,8 +6863,8 @@ start_class (enum tree_code code, tree class_name, tree super_name,
{
warning (0, "cannot find interface declaration for %qE",
class_name);
- add_class (implementation_template = objc_implementation_context,
- class_name);
+ add_interface (implementation_template = objc_implementation_context,
+ class_name);
}
/* If a super class has been specified in the implementation,
@@ -6985,7 +6897,7 @@ start_class (enum tree_code code, tree class_name, tree super_name,
warning (0, "duplicate interface declaration for class %qE", class_name);
#endif
else
- add_class (klass, class_name);
+ add_interface (klass, class_name);
if (protocol_list)
CLASS_PROTOCOL_LIST (klass)
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 33f90fdb785..e958e669af0 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -252,12 +252,6 @@ struct GTY(()) hashed_entry {
#define SIZEHASHTABLE 257
-extern GTY ((length ("SIZEHASHTABLE"))) hash *nst_method_hash_list;
-extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_method_hash_list;
-
-extern GTY ((length ("SIZEHASHTABLE"))) hash *cls_name_hash_list;
-extern GTY ((length ("SIZEHASHTABLE"))) hash *als_name_hash_list;
-
/* An array of all the local variables in the current function that
need to be marked as volatile. */
extern GTY(()) VEC(tree,gc) *local_variables_to_volatilize;
diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c
new file mode 100644
index 00000000000..77a98c1d825
--- /dev/null
+++ b/gcc/objc/objc-map.c
@@ -0,0 +1,161 @@
+/* objc-map.c -- Implementation of map data structures for ObjC compiler
+ Copyright 2011 Free Software Foundation, Inc.
+ Written by Nicola Pero <nicola.pero@meta-innovation.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser Public License as published by the
+Free Software Foundation; either version 3, 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 Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program; if not, write to the Free Software
+Foundation, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "ggc.h"
+#include "objc-map.h"
+
+#define OUT_OF_MEMORY { fprintf (stderr, "Out of memory\n"); abort (); }
+
+static
+size_t
+ATTRIBUTE_PURE
+next_power_of_two (size_t x)
+{
+ size_t result = 1;
+
+ if (x < 2)
+ return 2;
+
+ /* Avoid the long calculation if x is already a power of two. Since
+ we internally always increase/shrink tables by powers of 2, the
+ calculation should only be done once, when the table is first
+ set up. */
+ if ((x & (x - 1)) == 0)
+ return x;
+
+ /* Calculate log_2 by counting how many times we can divide by 2
+ before reaching 0. */
+ while (x > 0)
+ {
+ x = x >> 1;
+ result = result << 1;
+ }
+ return result;
+}
+
+objc_map_t
+objc_map_alloc_ggc (size_t initial_capacity)
+{
+ objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc_stat (1, sizeof (struct objc_map_private));
+ if (map == NULL)
+ OUT_OF_MEMORY;
+
+ initial_capacity = next_power_of_two (initial_capacity);
+
+ map->number_of_slots = initial_capacity;
+ map->mask = initial_capacity - 1;
+ map->maximum_load_factor = 70;
+ map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
+
+ map->slots = (tree *)ggc_internal_cleared_vec_alloc_stat (initial_capacity, sizeof (tree));
+ map->values = (tree *)ggc_internal_cleared_vec_alloc_stat (initial_capacity, sizeof (tree));
+
+ if (map->slots == NULL)
+ OUT_OF_MEMORY;
+
+ if (map->values == NULL)
+ OUT_OF_MEMORY;
+
+ return map;
+}
+
+void
+objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred)
+{
+ if (map->number_of_non_empty_slots != 0)
+ return;
+
+ map->maximum_load_factor = number_between_zero_and_one_hundred;
+ map->max_number_of_non_empty_slots = (map->number_of_slots * number_between_zero_and_one_hundred) / 100;
+}
+
+int
+objc_map_maximum_load_factor (objc_map_t map)
+{
+ return map->maximum_load_factor;
+}
+
+static void
+objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
+{
+ tree *old_slots = map->slots;
+ tree *old_values = map->values;
+ size_t i, old_number_of_slots = map->number_of_slots;
+
+ if (new_number_of_slots < (map->number_of_non_empty_slots))
+ new_number_of_slots = 2 * map->number_of_non_empty_slots;
+
+ new_number_of_slots = next_power_of_two (new_number_of_slots);
+
+ map->number_of_slots = new_number_of_slots;
+ map->mask = map->number_of_slots - 1;
+ map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
+
+
+ map->slots = (tree *)ggc_internal_cleared_vec_alloc_stat (map->number_of_slots, sizeof (tree));
+ map->values = (tree *)ggc_internal_cleared_vec_alloc_stat (map->number_of_slots, sizeof (tree));
+
+ if (map->slots == NULL)
+ OUT_OF_MEMORY;
+
+ if (map->values == NULL)
+ OUT_OF_MEMORY;
+
+ for (i = 0; i < old_number_of_slots; i++)
+ if (old_slots[i] != OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ {
+ size_t k = IDENTIFIER_HASH_VALUE (old_slots[i]) & map->mask;
+
+ if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ {
+ map->slots[k] = old_slots[i];
+ map->values[k] = old_values[i];
+ }
+ else
+ {
+ size_t j = 1;
+ while (1)
+ {
+ k = (k + j) & map->mask;
+ if (map->slots[k] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ {
+ map->slots[k] = old_slots[i];
+ map->values[k] = old_values[i];
+ break;
+ }
+ j++;
+ }
+ }
+ }
+
+ ggc_free (old_slots);
+ ggc_free (old_values);
+}
+
+void
+objc_map_private_grow (struct objc_map_private *map)
+{
+ objc_map_private_resize (map, map->number_of_slots * 2);
+}
+
+#include "gt-objc-objc-map.h"
diff --git a/gcc/objc/objc-map.h b/gcc/objc/objc-map.h
new file mode 100644
index 00000000000..c4565de186e
--- /dev/null
+++ b/gcc/objc/objc-map.h
@@ -0,0 +1,309 @@
+/* objc-map.h -- Implementation of map data structures for ObjC compiler
+ Copyright 2011 Free Software Foundation, Inc.
+ Written by Nicola Pero <nicola.pero@meta-innovation.com>
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser Public License as published by the
+Free Software Foundation; either version 3, 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 Lesser Public License for more details.
+
+You should have received a copy of the GNU Lesser Public License
+along with this program; if not, write to the Free Software
+Foundation, 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef OBJC_MAP_H
+#define OBJC_MAP_H
+
+/* A map is a data structure that maps a key to a value. In this file
+ we currently have maps that can map a GCC identifier (a tree) to
+ some other GCC tree. This is what the ObjC frontend mostly needs:
+ being able to look up an identifier into an ObjC data structure. A
+ typical usage is mapping ObjC class names (as identifiers) to a
+ tree representing the class.
+
+ This implementation is fast. :-) */
+
+/**
+ ** Private definitions.
+ **/
+
+/* We include private declaration and definitions that are required to
+ provide the implementation of inline functions. You should ignore
+ these definitions (and the implementation of the inline functions)
+ as they are not part of the public API and may change. */
+typedef unsigned int objc_map_private_hash_t;
+
+/* This is used as sentinel. */
+#define OBJC_MAP_PRIVATE_EMPTY_SLOT (tree)0
+
+struct GTY(()) objc_map_private {
+ /* Total number of slots. This is the maximum number of elements
+ that can be currently stored in the map before resizing. This is
+ the number of slots in the C array. Important: this is
+ guaranteed to be a power of 2. When we create (or resize) the
+ map, we round up the size to the next power of 2. This allows us
+ to convert a hash to a position in the hashtable by simply doing
+ "position = hash & mask", where mask is number_of_slots - 1
+ instead of using a modulo (which requires a division). */
+ size_t number_of_slots;
+
+ /* This is number_of_slots - 1, precomputed. */
+ size_t mask;
+
+ /* Number of slots that are not empty (ie, that are active). We
+ keep counts using this variable which can easily be checked
+ against max_number_of_non_empty_slots. */
+ size_t number_of_non_empty_slots;
+
+ /* This is the load factor limit. When the number of non empty
+ slots equals this number, we need to resize the array. This is
+ calculated once, when the slots are resized, and then kept cached
+ so it can be compared quickly when elements are added. */
+ size_t max_number_of_non_empty_slots;
+
+ /* The maximum load factor. */
+ int maximum_load_factor;
+
+ /* These are the keys. */
+ tree * GTY ((length ("%h.number_of_slots"))) slots;
+
+ /* These are the values. values[i] is the the value corresponding
+ to slots[i]. */
+ tree * GTY ((length ("%h.number_of_slots"))) values;
+};
+
+/* Private functions used to resize the map. They may be called by
+ the inline functions when adding elements. */
+extern void
+objc_map_private_grow (struct objc_map_private *map);
+
+
+/**
+ ** The definition of a map.
+ **/
+typedef struct objc_map_private *objc_map_t;
+
+
+/**
+ ** Creating a map.
+ **/
+
+/* objc_map_alloc_ggc() creates a new map which is under GGC. The initial
+ capacity must be specified as an argument; this is used to size the map
+ when it is created. */
+objc_map_t objc_map_alloc_ggc (size_t initial_capacity);
+
+/**
+ ** Performance tuning.
+ **/
+
+/* Set a maximum load factor for the data structure. This is the main
+ tuning parameter to improve performance (at the expense of
+ memory). */
+void objc_map_set_maximum_load_factor (objc_map_t map, int number_between_zero_and_one_hundred);
+
+/* Read the maximum load factor. */
+int objc_map_maximum_load_factor (objc_map_t map);
+
+
+/**
+ ** Getting the value corresponding to a key.
+ **/
+
+/* This is the value returned by objc_map_get() when the value
+ corresponding to a key is not found. */
+#define OBJC_MAP_NOT_FOUND (tree)1
+
+/* objc_map_get() returns the value associated with a certain key,
+ or OBJC_MAP_NOT_FOUND if there is no value associated with that key.
+ Note that you can also use it to simply check if the map contains a
+ pair with a certain key; just compare the result of calling
+ objc_map_get() to OBJC_MAP_NOT_FOUND.
+
+ It is essential to always check the results of the call to make
+ sure it is not OBJC_MAP_NOT_FOUND.
+
+ NULL is a valid value, so a key can be inserted into a map with
+ value NULL, and objc_map_get() will return NULL in that case.
+ So a result of NULL means that they key *was* found, and the value
+ associated with it was NULL. */
+static inline tree
+objc_map_get (objc_map_t map, /* struct tree_identifier * */tree key)
+{
+ /* The inline implementation is private and may change without notice. */
+ objc_map_private_hash_t hash = IDENTIFIER_HASH_VALUE (key);
+ size_t i = hash & map->mask;
+ size_t j = 1;
+
+ if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ return OBJC_MAP_NOT_FOUND;
+
+ if (map->slots[i] == key)
+ return map->values[i];
+
+ while (1)
+ {
+ i = (i + j) & map->mask;
+
+ if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ return OBJC_MAP_NOT_FOUND;
+
+ if (map->slots[i] == key)
+ return map->values[i];
+
+ j++;
+ }
+}
+
+/* objc_map_put() puts a key/value pair into the map. If the map does
+ not contain the key, it is added to it with the specified value.
+ If the map already contains the key, the previous value is replaced
+ with the new one.
+
+ You can use any identifier as key, with the exception of NULL.
+
+ You can use any tree as value, including NULL. */
+static inline
+void objc_map_put (objc_map_t map, /*struct tree_identifier * */tree key, tree value)
+{
+ /* The inline implementation is private and may change without notice. */
+ objc_map_private_hash_t hash = IDENTIFIER_HASH_VALUE (key);
+ size_t i, j = 0;
+
+ if (map->number_of_non_empty_slots == map->max_number_of_non_empty_slots)
+ objc_map_private_grow (map);
+
+ i = hash & map->mask;
+
+ while (1)
+ {
+ if (map->slots[i] == OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ {
+ map->number_of_non_empty_slots++;
+ map->slots[i] = key;
+ map->values[i] = value;
+ return;
+ }
+ if (map->slots[i] == key)
+ {
+ map->values[i] = value;
+ return;
+ }
+
+ j++;
+ i = (i + j) & map->mask;
+ }
+}
+
+/**
+ ** Iterating over a map using an iterator.
+ **/
+
+/* When using iterators you can iterate directly on the elements in
+ the map, and take an action over each one.
+
+ Here is how you iterate over a hmap_pointer using iterators:
+
+ objc_map_iterator_t i;
+
+ objc_map_iterator_initialize (map, &i);
+
+ while (objc_map_iterator_move_to_next (map, &i))
+ {
+ tree p = objc_map_iterator_current_key (map, i);
+ tree q = objc_map_iterator_current_value (map, i);
+
+ ... do something with p and q ...
+ }
+
+ You'll notice that the functions that modify the iterator (to
+ initialize it, or move it to the next element) take a pointer to it
+ as argument (as in "&i"), while the functions that only read its
+ state (to read the current key/value, or remove the current
+ key/value from the map) take it as a direct argument (as in "i").
+
+ Note that all the objc_map_iterator_*() functions are inline and if
+ you follow the pattern above, the compiler should be able to inline
+ everything into a very efficient loop, roughly equivalent to
+ hand-writing a C loop that iterates directly onto the hmap_pointer
+ internal data structures. */
+
+/* A objc_map_iterator_t variable encapsulates the state of an
+ iteration. The fact that this is actually a size_t (pointing to
+ the index of the slot that we return next) is an internal, private
+ detail of the implementation and may change without notice. */
+typedef size_t objc_map_iterator_t;
+
+/* Initialize an iterator to iterate over the specified objc_map. You
+ must use this before starting the iteration, to get a working
+ iterator. */
+static inline
+void
+objc_map_iterator_initialize (objc_map_t map ATTRIBUTE_UNUSED, objc_map_iterator_t *i)
+{
+ /* The inline implementation is private and may change without notice. */
+ /* This is trivial, but the same API would work to initialize more
+ complicated iterators. */
+ *i = 0;
+}
+
+#define OBJC_MAP_FAILURE 0
+#define OBJC_MAP_SUCCESS 1
+
+/* Move the iterator to the next key/value pair, and return
+ OBJC_MAP_SUCCESS if there is such a key/value pair, and
+ OBJC_MAP_FAILURE if there are no more ones. The iterator must have
+ been initialized using objc_map_iterator_initialize(). Note that
+ because this function is modifying the iterator, you need to pass a
+ pointer to it. */
+static inline
+int
+objc_map_iterator_move_to_next (objc_map_t map, objc_map_iterator_t *i)
+{
+ /* The inline implementation is private and may change without notice. */
+ while (1)
+ {
+ void *slot;
+ if (*i == map->number_of_slots)
+ return OBJC_MAP_FAILURE;
+
+ slot = map->slots[*i];
+ *i = *i + 1;
+ if (slot != OBJC_MAP_PRIVATE_EMPTY_SLOT)
+ return OBJC_MAP_SUCCESS;
+ }
+}
+
+/* Return the current key. You can only call it after you have called
+ objc_map_iterator_move_to_next() at least once (to move to the
+ first element), and only if the last call returned
+ OBJC_MAP_SUCCESS. The behaviour is otherwise undefined, probably a
+ segmentation fault. */
+static inline
+tree
+objc_map_iterator_current_key (objc_map_t map, objc_map_iterator_t i)
+{
+ /* The inline implementation is private and may change without notice. */
+ return map->slots[i - 1];
+}
+
+/* Return the current value. You can only call it after you have
+ called objc_map_iterator_move_to_next() at least once (to move to
+ the first element), and only if the last call returned
+ OBJC_MAP_SUCCESS. The behaviour is otherwise undefined, probably a
+ segmentation fault. */
+static inline
+tree
+objc_map_iterator_current_value (objc_map_t map, objc_map_iterator_t i)
+{
+ /* The inline implementation is private and may change without notice. */
+ return map->values[i - 1];
+}
+
+#endif /* OBJC_MAP_H */
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index 56df2afaf0c..4512c846cc0 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -231,6 +231,7 @@ static tree begin_catch (struct objc_try_context **, tree, tree, tree, bool);
static void finish_catch (struct objc_try_context **, tree);
static tree finish_try_stmt (struct objc_try_context **);
+/* TODO: Use an objc-map. */
static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
bool
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 51ab2a5016a..bed3b9dcd25 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,10 @@
+2011-10-14 Nicola Pero <nicola.pero@meta-innovation.com>
+
+ * Make-lang.in (OBJCXX_OBJS): Added objc-map.o.
+ (objcp/objc-map.o): New rule.
+ (objcp/objcp-act.o): Depend on objc/objc-map.h.
+ * config-lang.in (gtfiles): Added objc-map.h.
+
2011-07-11 Nicola Pero <nicola.pero@meta-innovation.com>
* Make-lang.in (objcp/objc-runtime-shared-support.o): Do not
diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in
index 3dac1735e15..4255bd63909 100644
--- a/gcc/objcp/Make-lang.in
+++ b/gcc/objcp/Make-lang.in
@@ -58,6 +58,7 @@ OBJCXX_OBJS = objcp/objcp-act.o objcp/objcp-lang.o objcp/objcp-decl.o \
objcp/objc-next-runtime-abi-01.o \
objcp/objc-next-runtime-abi-02.o \
objcp/objc-encoding.o \
+ objcp/objc-map.o \
$(CXX_AND_OBJCXX_OBJS)
obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o
@@ -149,6 +150,7 @@ objcp/objcp-act.o : objc/objc-act.c \
$(RTL_H) $(EXPR_H) $(TARGET_H) \
objcp/objcp-decl.h \
objc/objc-encoding.h \
+ objc/objc-map.h \
objc/objc-runtime-hooks.h \
objc/objc-runtime-shared-support.h \
objcp/objcp-decl.h
@@ -165,6 +167,14 @@ objcp/objc-encoding.o : objc/objc-encoding.c \
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
$(OUTPUT_OPTION)
+objcp/objc-map.o : objc/objc-map.c \
+ $(START_HDRS) \
+ $(GGC_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) input.h \
+ $(OBSTACK_H) \
+ objc/objc-map.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+ $(OUTPUT_OPTION)
+
po-generated:
#
diff --git a/gcc/objcp/config-lang.in b/gcc/objcp/config-lang.in
index e80666da5b5..5fd0f06b33b 100644
--- a/gcc/objcp/config-lang.in
+++ b/gcc/objcp/config-lang.in
@@ -46,5 +46,5 @@ subdir_requires="objc cp"
# This list is separated in two parts: the first one is identical to
# the C++ one, the second one contains our ObjC++ additions.
gtfiles="\$(srcdir)/cp/rtti.c \$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.h \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-family/c-common.c \$(srcdir)/c-family/c-common.h \$(srcdir)/c-family/c-objc.h \$(srcdir)/c-family/c-lex.c \$(srcdir)/c-family/c-pragma.h \$(srcdir)/c-family/c-pragma.c \$(srcdir)/cp/class.c \$(srcdir)/cp/cp-objcp-common.c \
-\$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"
+\$(srcdir)/objc/objc-map.h \$(srcdir)/objc/objc-act.h \$(srcdir)/objc/objc-act.c \$(srcdir)/objc/objc-runtime-shared-support.c \$(srcdir)/objc/objc-gnu-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-01.c \$(srcdir)/objc/objc-next-runtime-abi-02.c \$(srcdir)/c-family/c-cppbuiltin.c"
diff --git a/gcc/optabs.c b/gcc/optabs.c
index d8ab97e2142..276cb8660e6 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -479,6 +479,14 @@ optab_for_tree_code (enum tree_code code, const_tree type,
return TYPE_UNSIGNED (type) ?
vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ return TYPE_UNSIGNED (type) ?
+ vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab;
+
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ return TYPE_UNSIGNED (type) ?
+ vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab;
+
case VEC_UNPACK_HI_EXPR:
return TYPE_UNSIGNED (type) ?
vec_unpacku_hi_optab : vec_unpacks_hi_optab;
@@ -735,6 +743,41 @@ expand_vec_shift_expr (sepops ops, rtx target)
return eops[0].value;
}
+/* Create a new vector value in VMODE with all elements set to OP. The
+ mode of OP must be the element mode of VMODE. If OP is a constant,
+ then the return value will be a constant. */
+
+static rtx
+expand_vector_broadcast (enum machine_mode vmode, rtx op)
+{
+ enum insn_code icode;
+ rtvec vec;
+ rtx ret;
+ int i, n;
+
+ gcc_checking_assert (VECTOR_MODE_P (vmode));
+
+ n = GET_MODE_NUNITS (vmode);
+ vec = rtvec_alloc (n);
+ for (i = 0; i < n; ++i)
+ RTVEC_ELT (vec, i) = op;
+
+ if (CONSTANT_P (op))
+ return gen_rtx_CONST_VECTOR (vmode, vec);
+
+ /* ??? If the target doesn't have a vec_init, then we have no easy way
+ of performing this operation. Most of this sort of generic support
+ is hidden away in the vector lowering support in gimple. */
+ icode = optab_handler (vec_init_optab, vmode);
+ if (icode == CODE_FOR_nothing)
+ return NULL;
+
+ ret = gen_reg_rtx (vmode);
+ emit_insn (GEN_FCN (icode) (ret, gen_rtx_PARALLEL (vmode, vec)));
+
+ return ret;
+}
+
/* This subroutine of expand_doubleword_shift handles the cases in which
the effective shift value is >= BITS_PER_WORD. The arguments and return
value are the same as for the parent routine, except that SUPERWORD_OP1
@@ -1533,6 +1576,60 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
}
}
+ /* If this is a vector shift by a scalar, see if we can do a vector
+ shift by a vector. If so, broadcast the scalar into a vector. */
+ if (mclass == MODE_VECTOR_INT)
+ {
+ optab otheroptab = NULL;
+
+ if (binoptab == ashl_optab)
+ otheroptab = vashl_optab;
+ else if (binoptab == ashr_optab)
+ otheroptab = vashr_optab;
+ else if (binoptab == lshr_optab)
+ otheroptab = vlshr_optab;
+ else if (binoptab == rotl_optab)
+ otheroptab = vrotl_optab;
+ else if (binoptab == rotr_optab)
+ otheroptab = vrotr_optab;
+
+ if (otheroptab && optab_handler (otheroptab, mode) != CODE_FOR_nothing)
+ {
+ rtx vop1 = expand_vector_broadcast (mode, op1);
+ if (vop1)
+ {
+ temp = expand_binop_directly (mode, otheroptab, op0, vop1,
+ target, unsignedp, methods, last);
+ if (temp)
+ return temp;
+ }
+ }
+ }
+
+ /* Certain vector operations can be implemented with vector permutation. */
+ if (VECTOR_MODE_P (mode))
+ {
+ enum tree_code tcode = ERROR_MARK;
+ rtx sel;
+
+ if (binoptab == vec_interleave_high_optab)
+ tcode = VEC_INTERLEAVE_HIGH_EXPR;
+ else if (binoptab == vec_interleave_low_optab)
+ tcode = VEC_INTERLEAVE_LOW_EXPR;
+ else if (binoptab == vec_extract_even_optab)
+ tcode = VEC_EXTRACT_EVEN_EXPR;
+ else if (binoptab == vec_extract_odd_optab)
+ tcode = VEC_EXTRACT_ODD_EXPR;
+
+ if (tcode != ERROR_MARK
+ && can_vec_perm_for_code_p (tcode, mode, &sel))
+ {
+ temp = expand_vec_perm (mode, op0, op1, sel, target);
+ gcc_assert (temp != NULL);
+ return temp;
+ }
+ }
+
/* Look for a wider mode of the same class for which we think we
can open-code the operation. Check for a widening multiply at the
wider mode as well. */
@@ -4727,6 +4824,60 @@ can_float_p (enum machine_mode fltmode, enum machine_mode fixmode,
tab = unsignedp ? ufloat_optab : sfloat_optab;
return convert_optab_handler (tab, fltmode, fixmode);
}
+
+/* Function supportable_convert_operation
+
+ Check whether an operation represented by the code CODE is a
+ convert operation that is supported by the target platform in
+ vector form (i.e., when operating on arguments of type VECTYPE_IN
+ producing a result of type VECTYPE_OUT).
+
+ Convert operations we currently support directly are FIX_TRUNC and FLOAT.
+ This function checks if these operations are supported
+ by the target platform either directly (via vector tree-codes), or via
+ target builtins.
+
+ Output:
+ - CODE1 is code of vector operation to be used when
+ vectorizing the operation, if available.
+ - DECL is decl of target builtin functions to be used
+ when vectorizing the operation, if available. In this case,
+ CODE1 is CALL_EXPR. */
+
+bool
+supportable_convert_operation (enum tree_code code,
+ tree vectype_out, tree vectype_in,
+ tree *decl, enum tree_code *code1)
+{
+ enum machine_mode m1,m2;
+ int truncp;
+
+ m1 = TYPE_MODE (vectype_out);
+ m2 = TYPE_MODE (vectype_in);
+
+ /* First check if we can done conversion directly. */
+ if ((code == FIX_TRUNC_EXPR
+ && can_fix_p (m1,m2,TYPE_UNSIGNED (vectype_out), &truncp)
+ != CODE_FOR_nothing)
+ || (code == FLOAT_EXPR
+ && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
+ != CODE_FOR_nothing))
+ {
+ *code1 = code;
+ return true;
+ }
+
+ /* Now check for builtin. */
+ if (targetm.vectorize.builtin_conversion
+ && targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
+ {
+ *code1 = CALL_EXPR;
+ *decl = targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in);
+ return true;
+ }
+ return false;
+}
+
/* Generate code to convert FROM to floating point
and store in TO. FROM must be fixed point and not VOIDmode.
@@ -6132,6 +6283,10 @@ init_optabs (void)
init_optab (vec_widen_umult_lo_optab, UNKNOWN);
init_optab (vec_widen_smult_hi_optab, UNKNOWN);
init_optab (vec_widen_smult_lo_optab, UNKNOWN);
+ init_optab (vec_widen_ushiftl_hi_optab, UNKNOWN);
+ init_optab (vec_widen_ushiftl_lo_optab, UNKNOWN);
+ init_optab (vec_widen_sshiftl_hi_optab, UNKNOWN);
+ init_optab (vec_widen_sshiftl_lo_optab, UNKNOWN);
init_optab (vec_unpacks_hi_optab, UNKNOWN);
init_optab (vec_unpacks_lo_optab, UNKNOWN);
init_optab (vec_unpacku_hi_optab, UNKNOWN);
@@ -6621,90 +6776,319 @@ vector_compare_rtx (tree cond, bool unsignedp, enum insn_code icode)
}
/* Return true if VEC_PERM_EXPR can be expanded using SIMD extensions
- of the CPU. */
+ of the CPU. SEL may be NULL, which stands for an unknown constant. */
+
bool
-expand_vec_perm_expr_p (enum machine_mode mode, tree v0, tree v1, tree mask)
+can_vec_perm_p (enum machine_mode mode, bool variable,
+ const unsigned char *sel)
{
- int v0_mode_s = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))));
- int mask_mode_s = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask))));
+ enum machine_mode qimode;
- if (TREE_CODE (mask) == VECTOR_CST
- && targetm.vectorize.builtin_vec_perm_ok (TREE_TYPE (v0), mask))
+ /* If the target doesn't implement a vector mode for the vector type,
+ then no operations are supported. */
+ if (!VECTOR_MODE_P (mode))
+ return false;
+
+ if (!variable)
+ {
+ if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing
+ && (sel == NULL
+ || targetm.vectorize.vec_perm_const_ok == NULL
+ || targetm.vectorize.vec_perm_const_ok (mode, sel)))
+ return true;
+ }
+
+ if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
return true;
- if (v0_mode_s != mask_mode_s
- || TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0))
- != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))
- || TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1))
- != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)))
+ /* We allow fallback to a QI vector mode, and adjust the mask. */
+ if (GET_MODE_INNER (mode) == QImode)
+ return false;
+ qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
+ if (!VECTOR_MODE_P (qimode))
+ return false;
+
+ /* ??? For completeness, we ought to check the QImode version of
+ vec_perm_const_optab. But all users of this implicit lowering
+ feature implement the variable vec_perm_optab. */
+ if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
return false;
- return direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing;
+ /* In order to support the lowering of variable permutations,
+ we need to support shifts and adds. */
+ if (variable)
+ {
+ if (GET_MODE_UNIT_SIZE (mode) > 2
+ && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
+ && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
+ return false;
+ if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
+ return false;
+ }
+
+ return true;
}
-/* Generate instructions for VEC_COND_EXPR given its type and three
- operands. */
-rtx
-expand_vec_perm_expr (tree type, tree v0, tree v1, tree mask, rtx target)
+/* Return true if we can implement VEC_INTERLEAVE_{HIGH,LOW}_EXPR or
+ VEC_EXTRACT_{EVEN,ODD}_EXPR with VEC_PERM_EXPR for this target.
+ If PSEL is non-null, return the selector for the permutation. */
+
+bool
+can_vec_perm_for_code_p (enum tree_code code, enum machine_mode mode,
+ rtx *psel)
{
- struct expand_operand ops[4];
+ bool need_sel_test = false;
enum insn_code icode;
- enum machine_mode mode = TYPE_MODE (type);
- gcc_checking_assert (expand_vec_perm_expr_p (mode, v0, v1, mask));
+ /* If the target doesn't implement a vector mode for the vector type,
+ then no operations are supported. */
+ if (!VECTOR_MODE_P (mode))
+ return false;
- if (TREE_CODE (mask) == VECTOR_CST)
+ /* Do as many tests as possible without reqiring the selector. */
+ icode = direct_optab_handler (vec_perm_optab, mode);
+ if (icode == CODE_FOR_nothing && GET_MODE_INNER (mode) != QImode)
+ {
+ enum machine_mode qimode
+ = mode_for_vector (QImode, GET_MODE_SIZE (mode));
+ if (VECTOR_MODE_P (qimode))
+ icode = direct_optab_handler (vec_perm_optab, qimode);
+ }
+ if (icode == CODE_FOR_nothing)
{
- tree m_type, call;
- tree fn = targetm.vectorize.builtin_vec_perm (TREE_TYPE (v0), &m_type);
+ icode = direct_optab_handler (vec_perm_const_optab, mode);
+ if (icode != CODE_FOR_nothing
+ && targetm.vectorize.vec_perm_const_ok != NULL)
+ need_sel_test = true;
+ }
+ if (icode == CODE_FOR_nothing)
+ return false;
- if (!fn)
- goto vec_perm;
+ /* If the selector is required, or if we need to test it, build it. */
+ if (psel || need_sel_test)
+ {
+ int i, nelt = GET_MODE_NUNITS (mode), alt = 0;
+ unsigned char *data = XALLOCAVEC (unsigned char, nelt);
- if (m_type != TREE_TYPE (TREE_TYPE (mask)))
+ switch (code)
{
- int units = TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask));
- tree cvt = build_vector_type (m_type, units);
- mask = fold_convert (cvt, mask);
+ case VEC_EXTRACT_ODD_EXPR:
+ alt = 1;
+ /* FALLTHRU */
+ case VEC_EXTRACT_EVEN_EXPR:
+ for (i = 0; i < nelt; ++i)
+ data[i] = i * 2 + alt;
+ break;
+
+ case VEC_INTERLEAVE_HIGH_EXPR:
+ alt = nelt / 2;
+ /* FALLTHRU */
+ case VEC_INTERLEAVE_LOW_EXPR:
+ for (i = 0; i < nelt / 2; ++i)
+ {
+ data[i * 2] = i + alt;
+ data[i * 2 + 1] = i + nelt + alt;
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
}
- call = fold_build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
- call = build_call_nary (type, call, 3, v0, v1, mask);
+ if (need_sel_test
+ && !targetm.vectorize.vec_perm_const_ok (mode, data))
+ return false;
+
+ if (psel)
+ {
+ rtvec vec = rtvec_alloc (nelt);
+ enum machine_mode imode = mode;
+
+ for (i = 0; i < nelt; ++i)
+ RTVEC_ELT (vec, i) = GEN_INT (data[i]);
+
+ if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
+ {
+ imode = int_mode_for_mode (GET_MODE_INNER (mode));
+ imode = mode_for_vector (imode, nelt);
+ gcc_assert (GET_MODE_CLASS (imode) == MODE_VECTOR_INT);
+ }
- return expand_expr_real_1 (call, target, VOIDmode, EXPAND_NORMAL, NULL);
+ *psel = gen_rtx_CONST_VECTOR (imode, vec);
+ }
}
- vec_perm:
- icode = direct_optab_handler (vec_perm_optab, mode);
+ return true;
+}
- if (icode == CODE_FOR_nothing)
- return 0;
+/* A subroutine of expand_vec_perm for expanding one vec_perm insn. */
- create_output_operand (&ops[0], target, mode);
- create_input_operand (&ops[3], expand_normal (mask),
- TYPE_MODE (TREE_TYPE (mask)));
+static rtx
+expand_vec_perm_1 (enum insn_code icode, rtx target,
+ rtx v0, rtx v1, rtx sel)
+{
+ enum machine_mode tmode = GET_MODE (target);
+ enum machine_mode smode = GET_MODE (sel);
+ struct expand_operand ops[4];
- if (operand_equal_p (v0, v1, 0))
- {
- rtx rtx_v0 = expand_normal (v0);
- if (!insn_operand_matches (icode, 1, rtx_v0))
- rtx_v0 = force_reg (mode, rtx_v0);
+ create_output_operand (&ops[0], target, tmode);
+ create_input_operand (&ops[3], sel, smode);
- gcc_checking_assert (insn_operand_matches (icode, 2, rtx_v0));
+ /* Make an effort to preserve v0 == v1. The target expander is able to
+ rely on this to determine if we're permuting a single input operand. */
+ if (rtx_equal_p (v0, v1))
+ {
+ if (!insn_operand_matches (icode, 1, v0))
+ v0 = force_reg (tmode, v0);
+ gcc_checking_assert (insn_operand_matches (icode, 1, v0));
+ gcc_checking_assert (insn_operand_matches (icode, 2, v0));
- create_fixed_operand (&ops[1], rtx_v0);
- create_fixed_operand (&ops[2], rtx_v0);
+ create_fixed_operand (&ops[1], v0);
+ create_fixed_operand (&ops[2], v0);
}
else
{
- create_input_operand (&ops[1], expand_normal (v0), mode);
- create_input_operand (&ops[2], expand_normal (v1), mode);
+ create_input_operand (&ops[1], v0, tmode);
+ create_input_operand (&ops[2], v1, tmode);
}
- expand_insn (icode, 4, ops);
- return ops[0].value;
+ if (maybe_expand_insn (icode, 4, ops))
+ return ops[0].value;
+ return NULL_RTX;
}
+/* Generate instructions for vec_perm optab given its mode
+ and three operands. */
+
+rtx
+expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
+{
+ enum insn_code icode;
+ enum machine_mode qimode;
+ unsigned int i, w, e, u;
+ rtx tmp, sel_qi = NULL;
+ rtvec vec;
+
+ if (!target || GET_MODE (target) != mode)
+ target = gen_reg_rtx (mode);
+
+ w = GET_MODE_SIZE (mode);
+ e = GET_MODE_NUNITS (mode);
+ u = GET_MODE_UNIT_SIZE (mode);
+
+ /* Set QIMODE to a different vector mode with byte elements.
+ If no such mode, or if MODE already has byte elements, use VOIDmode. */
+ qimode = VOIDmode;
+ if (GET_MODE_INNER (mode) != QImode)
+ {
+ qimode = mode_for_vector (QImode, w);
+ if (!VECTOR_MODE_P (qimode))
+ qimode = VOIDmode;
+ }
+
+ /* If the input is a constant, expand it specially. */
+ if (CONSTANT_P (sel))
+ {
+ icode = direct_optab_handler (vec_perm_const_optab, mode);
+ if (icode != CODE_FOR_nothing)
+ {
+ tmp = expand_vec_perm_1 (icode, target, v0, v1, sel);
+ if (tmp)
+ return tmp;
+ }
+
+ /* Fall back to a constant byte-based permutation. */
+ if (qimode != VOIDmode)
+ {
+ vec = rtvec_alloc (w);
+ for (i = 0; i < e; ++i)
+ {
+ unsigned int j, this_e;
+
+ this_e = INTVAL (XVECEXP (sel, 0, i));
+ this_e &= 2 * e - 1;
+ this_e *= u;
+
+ for (j = 0; j < u; ++j)
+ RTVEC_ELT (vec, i * u + j) = GEN_INT (this_e + j);
+ }
+ sel_qi = gen_rtx_CONST_VECTOR (qimode, vec);
+
+ icode = direct_optab_handler (vec_perm_const_optab, qimode);
+ if (icode != CODE_FOR_nothing)
+ {
+ tmp = expand_vec_perm_1 (icode, gen_lowpart (qimode, target),
+ gen_lowpart (qimode, v0),
+ gen_lowpart (qimode, v1), sel_qi);
+ if (tmp)
+ return gen_lowpart (mode, tmp);
+ }
+ }
+ }
+
+ /* Otherwise expand as a fully variable permuation. */
+ icode = direct_optab_handler (vec_perm_optab, mode);
+ if (icode != CODE_FOR_nothing)
+ {
+ tmp = expand_vec_perm_1 (icode, target, v0, v1, sel);
+ if (tmp)
+ return tmp;
+ }
+
+ /* As a special case to aid several targets, lower the element-based
+ permutation to a byte-based permutation and try again. */
+ if (qimode == VOIDmode)
+ return NULL_RTX;
+ icode = direct_optab_handler (vec_perm_optab, qimode);
+ if (icode == CODE_FOR_nothing)
+ return NULL_RTX;
+
+ if (sel_qi == NULL)
+ {
+ /* Multiply each element by its byte size. */
+ enum machine_mode selmode = GET_MODE (sel);
+ if (u == 2)
+ sel = expand_simple_binop (selmode, PLUS, sel, sel,
+ sel, 0, OPTAB_DIRECT);
+ else
+ sel = expand_simple_binop (selmode, ASHIFT, sel,
+ GEN_INT (exact_log2 (u)),
+ sel, 0, OPTAB_DIRECT);
+ gcc_assert (sel != NULL);
+
+ /* Broadcast the low byte each element into each of its bytes. */
+ vec = rtvec_alloc (w);
+ for (i = 0; i < w; ++i)
+ {
+ int this_e = i / u * u;
+ if (BYTES_BIG_ENDIAN)
+ this_e += u - 1;
+ RTVEC_ELT (vec, i) = GEN_INT (this_e);
+ }
+ tmp = gen_rtx_CONST_VECTOR (qimode, vec);
+ sel = gen_lowpart (qimode, sel);
+ sel = expand_vec_perm (qimode, sel, sel, tmp, NULL);
+ gcc_assert (sel != NULL);
+
+ /* Add the byte offset to each byte element. */
+ /* Note that the definition of the indicies here is memory ordering,
+ so there should be no difference between big and little endian. */
+ vec = rtvec_alloc (w);
+ for (i = 0; i < w; ++i)
+ RTVEC_ELT (vec, i) = GEN_INT (i % u);
+ tmp = gen_rtx_CONST_VECTOR (qimode, vec);
+ sel_qi = expand_simple_binop (qimode, PLUS, sel, tmp,
+ sel, 0, OPTAB_DIRECT);
+ gcc_assert (sel_qi != NULL);
+ }
+
+ tmp = expand_vec_perm_1 (icode, gen_lowpart (qimode, target),
+ gen_lowpart (qimode, v0),
+ gen_lowpart (qimode, v1), sel_qi);
+ if (tmp)
+ tmp = gen_lowpart (mode, tmp);
+ return tmp;
+}
/* Return insn code for a conditional operator with a comparison in
mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 2ca0fcdd804..d70b3fa0f91 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -351,6 +351,12 @@ enum optab_index
OTI_vec_widen_umult_lo,
OTI_vec_widen_smult_hi,
OTI_vec_widen_smult_lo,
+ /* Widening shift left.
+ The high/low part of the resulting vector is returned. */
+ OTI_vec_widen_ushiftl_hi,
+ OTI_vec_widen_ushiftl_lo,
+ OTI_vec_widen_sshiftl_hi,
+ OTI_vec_widen_sshiftl_lo,
/* Extract and widen the high/low part of a vector of signed or
floating point elements. */
OTI_vec_unpacks_hi,
@@ -544,6 +550,10 @@ enum optab_index
#define vec_widen_umult_lo_optab (&optab_table[OTI_vec_widen_umult_lo])
#define vec_widen_smult_hi_optab (&optab_table[OTI_vec_widen_smult_hi])
#define vec_widen_smult_lo_optab (&optab_table[OTI_vec_widen_smult_lo])
+#define vec_widen_ushiftl_hi_optab (&optab_table[OTI_vec_widen_ushiftl_hi])
+#define vec_widen_ushiftl_lo_optab (&optab_table[OTI_vec_widen_ushiftl_lo])
+#define vec_widen_sshiftl_hi_optab (&optab_table[OTI_vec_widen_sshiftl_hi])
+#define vec_widen_sshiftl_lo_optab (&optab_table[OTI_vec_widen_sshiftl_lo])
#define vec_unpacks_hi_optab (&optab_table[OTI_vec_unpacks_hi])
#define vec_unpacks_lo_optab (&optab_table[OTI_vec_unpacks_lo])
#define vec_unpacku_hi_optab (&optab_table[OTI_vec_unpacku_hi])
@@ -638,9 +648,6 @@ enum direct_optab_index
DOI_reload_in,
DOI_reload_out,
- /* Vector shuffling. */
- DOI_vec_perm,
-
/* Block move operation. */
DOI_movmem,
@@ -716,6 +723,10 @@ enum direct_optab_index
DOI_atomic_thread_fence,
DOI_atomic_signal_fence,
+ /* Vector permutation. */
+ DOI_vec_perm,
+ DOI_vec_perm_const,
+
DOI_MAX
};
@@ -732,7 +743,6 @@ typedef struct direct_optab_d *direct_optab;
#endif
#define reload_in_optab (&direct_optab_table[(int) DOI_reload_in])
#define reload_out_optab (&direct_optab_table[(int) DOI_reload_out])
-#define vec_perm_optab (&direct_optab_table[(int) DOI_vec_perm])
#define movmem_optab (&direct_optab_table[(int) DOI_movmem])
#define setmem_optab (&direct_optab_table[(int) DOI_setmem])
#define cmpstr_optab (&direct_optab_table[(int) DOI_cmpstr])
@@ -815,6 +825,9 @@ typedef struct direct_optab_d *direct_optab;
(&direct_optab_table[(int) DOI_atomic_thread_fence])
#define atomic_signal_fence_optab \
(&direct_optab_table[(int) DOI_atomic_signal_fence])
+
+#define vec_perm_optab (&direct_optab_table[DOI_vec_perm])
+#define vec_perm_const_optab (&direct_optab_table[(int) DOI_vec_perm_const])
/* Target-dependent globals. */
struct target_optabs {
@@ -959,6 +972,12 @@ extern bool can_compare_and_swap_p (enum machine_mode);
extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
enum memmodel, enum memmodel);
+/* Check whether an operation represented by the code CODE is a
+ convert operation that is supported by the target platform in
+ vector form */
+bool supportable_convert_operation (enum tree_code, tree, tree, tree *,
+ enum tree_code *);
+
/* Generate code for a FIX_EXPR. */
extern void expand_fix (rtx, rtx, int);
@@ -977,10 +996,13 @@ extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx);
extern rtx expand_vec_shift_expr (sepops, rtx);
/* Return tree if target supports vector operations for VEC_PERM_EXPR. */
-bool expand_vec_perm_expr_p (enum machine_mode, tree, tree, tree);
+extern bool can_vec_perm_p (enum machine_mode, bool, const unsigned char *);
+
+/* Return true if target supports vector operations using VEC_PERM_EXPR. */
+extern bool can_vec_perm_for_code_p (enum tree_code, enum machine_mode, rtx *);
/* Generate code for VEC_PERM_EXPR. */
-extern rtx expand_vec_perm_expr (tree, tree, tree, tree, rtx);
+extern rtx expand_vec_perm (enum machine_mode, rtx, rtx, rtx, rtx);
/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
if the target does not have such an insn. */
diff --git a/gcc/params.def b/gcc/params.def
index 76814afe68e..a7ae0918579 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -111,7 +111,7 @@ DEFPARAM (PARAM_EARLY_INLINER_MAX_ITERATIONS,
/* Limit on probability of entry BB. */
DEFPARAM (PARAM_COMDAT_SHARING_PROBABILITY,
"comdat-sharing-probability",
- "Probability that COMDAT function will be shared with different compilatoin unit",
+ "Probability that COMDAT function will be shared with different compilation unit",
20, 0, 0)
/* Limit on probability of entry BB. */
@@ -566,6 +566,11 @@ DEFPARAM(PARAM_MAX_RELOAD_SEARCH_INSNS,
"The maximum number of instructions to search backward when looking for equivalent reload",
100, 0, 0)
+DEFPARAM(PARAM_SINK_FREQUENCY_THRESHOLD,
+ "sink-frequency-threshold",
+ "Target block's relative execution frequency (as a percentage) required to sink a statement",
+ 75, 0, 100)
+
DEFPARAM(PARAM_MAX_SCHED_REGION_BLOCKS,
"max-sched-region-blocks",
"The maximum number of blocks in a region to be considered for interblock scheduling",
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 3906bffc68b..63d1cae4ede 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -1,5 +1,5 @@
/* Support for GCC plugin mechanism.
- Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -149,7 +149,7 @@ add_new_plugin (const char* plugin_name)
plugin_name, ".so", NULL);
if (access (plugin_name, R_OK))
fatal_error
- ("inacessible plugin file %s expanded from short plugin name %s: %m",
+ ("inaccessible plugin file %s expanded from short plugin name %s: %m",
plugin_name, base_name);
}
else
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index 6cf5a4801ca..c7164125d0c 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,26 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * EXCLUDES (gthr-aix.h, gthr-dce.h, gthr-posix.c, gthr-posix.h)
+ (gthr-rtems.h, gthr-single.h, gthr-solaris.h, gthr-vxworks.h)
+ (gthr-win32.h, gthr.h): Remove.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * EXCLUDES (config/vxlib.c, gbl-ctors.h, libgcc2.c, libgcc2.h)
+ (longlong.h): Remove.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * EXCLUDES (crtstuff.c): Remove.
+
+2011-10-30 Joseph Myers <joseph@codesourcery.com>
+
+ * ja.po: Update.
+
+2011-10-25 Joseph Myers <joseph@codesourcery.com>
+
+ * ja.po: Update.
+
2011-10-03 Joseph Myers <joseph@codesourcery.com>
* de.po: Update.
diff --git a/gcc/po/EXCLUDES b/gcc/po/EXCLUDES
index 5a4ad770973..e04b9239363 100644
--- a/gcc/po/EXCLUDES
+++ b/gcc/po/EXCLUDES
@@ -22,26 +22,10 @@
# .def are examined to begin with.
# These files are part of libgcc, or target headers provided by gcc.
-config/vxlib.c
-crtstuff.c
-gbl-ctors.h
gcov-io.h
gcov-iov.c
-gthr-aix.h
-gthr-dce.h
-gthr-posix.c
-gthr-posix.h
-gthr-rtems.h
-gthr-single.h
-gthr-solaris.h
-gthr-vxworks.h
-gthr-win32.h
-gthr.h
-libgcc2.c
-libgcc2.h
limitx.h
limity.h
-longlong.h
# These programs are meant to be executed only by GCC maintainers or
# installers. Such files do not need to be translated, as these
diff --git a/gcc/po/ja.po b/gcc/po/ja.po
index 0e71fa80ed5..7fdc2162ca4 100644
--- a/gcc/po/ja.po
+++ b/gcc/po/ja.po
@@ -20,7 +20,7 @@ msgstr ""
"Project-Id-Version: gcc 4.6.1\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
"POT-Creation-Date: 2011-06-21 10:27+0000\n"
-"PO-Revision-Date: 2011-09-02 18:40+0900\n"
+"PO-Revision-Date: 2011-10-30 18:48+0900\n"
"Last-Translator: Yasuaki Taniguchi <yasuakit@gmail.com>\n"
"Language-Team: Japanese <translation-team-ja@lists.sourceforge.net>\n"
"Language: ja\n"
@@ -834,12 +834,12 @@ msgstr " -v, --version ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã‚’表示ã—ã¦çµ
#: gcov.c:420
#, c-format
msgid " -a, --all-blocks Show information for every basic block\n"
-msgstr ""
+msgstr " -a, --all-blocks å„基本ブロックã«é–¢ã™ã‚‹æƒ…報を表示ã™ã‚‹\n"
#: gcov.c:421
#, c-format
msgid " -b, --branch-probabilities Include branch probabilities in output\n"
-msgstr ""
+msgstr " -b, --branch-probabilities 出力ã«åˆ†å²å¯èƒ½æ€§æƒ…報をå«ã‚ã‚‹\n"
#: gcov.c:422
#, c-format
@@ -847,6 +847,8 @@ msgid ""
" -c, --branch-counts Given counts of branches taken\n"
" rather than percentages\n"
msgstr ""
+" -c, --branch-counts 分å²ã«é–¢ã™ã‚‹ç™¾åˆ†çŽ‡ã§ã¯ç„¡ãè¡Œã‚ã‚ŒãŸ\n"
+" 回数をå–å¾—ã™ã‚‹\n"
#: gcov.c:424
#, c-format
@@ -859,21 +861,23 @@ msgid ""
" -l, --long-file-names Use long output file names for included\n"
" source files\n"
msgstr ""
+" -l, --long-file-names インクルードã•ã‚ŒãŸã‚½ãƒ¼ã‚¹ãƒ•ã‚¡ã‚¤ãƒ«ã«é–¢ã™ã‚‹é•·ã„\n"
+" 出力ファイルåを使用ã™ã‚‹\n"
#: gcov.c:427
#, c-format
msgid " -f, --function-summaries Output summaries for each function\n"
-msgstr ""
+msgstr " -f, --function-summaries å„関数ã«é–¢ã™ã‚‹è¦ç´„を出力ã™ã‚‹\n"
#: gcov.c:428
#, c-format
msgid " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n"
-msgstr ""
+msgstr " -o, --object-directory DIR|FILE オブジェクトファイルを DIR 内ã¾ãŸã¯å‘¼ã³å‡ºã—用 FILE 内ã§æ¤œç´¢ã™ã‚‹\n"
#: gcov.c:429
#, c-format
msgid " -p, --preserve-paths Preserve all pathname components\n"
-msgstr ""
+msgstr " -p, --preserve-paths ã™ã¹ã¦ã®ãƒ‘スåè¦ç´ ã‚’ä¿è­·ã™ã‚‹\n"
#: gcov.c:430
#, c-format
@@ -977,7 +981,7 @@ msgstr "%s: ç ´æã—ã¦ã„ã¾ã™\n"
#: gcov.c:1045
#, c-format
msgid "%s:cannot open data file, assuming not executed\n"
-msgstr ""
+msgstr "%s:データファイルを開ã‘ã¾ã›ã‚“。実行ã•ã‚Œã¦ã„ãªã„ã¨è¦‹ãªã—ã¾ã™\n"
#: gcov.c:1052
#, c-format
@@ -1027,7 +1031,7 @@ msgstr ""
#: gcov.c:1379
#, c-format
msgid "%s:graph is unsolvable for '%s'\n"
-msgstr ""
+msgstr "%s: '%s' 用ã®ã‚°ãƒ©ãƒ•ãŒè§£æ±ºã§ãã¾ã›ã‚“\n"
#: gcov.c:1459
#, c-format
@@ -1037,7 +1041,7 @@ msgstr "%s '%s'\n"
#: gcov.c:1462
#, c-format
msgid "Lines executed:%s of %d\n"
-msgstr ""
+msgstr "実行ã•ã‚ŒãŸè¡Œ:%s of %d\n"
#: gcov.c:1466
#, c-format
@@ -1047,7 +1051,7 @@ msgstr "実行å¯èƒ½ãªè¡ŒãŒã‚ã‚Šã¾ã›ã‚“\n"
#: gcov.c:1472
#, c-format
msgid "Branches executed:%s of %d\n"
-msgstr ""
+msgstr "実行ã•ã‚ŒãŸåˆ†å²:%s of %d\n"
#: gcov.c:1476
#, c-format
@@ -1057,12 +1061,12 @@ msgstr ""
#: gcov.c:1482
#, c-format
msgid "No branches\n"
-msgstr ""
+msgstr "分å²ãŒã‚ã‚Šã¾ã›ã‚“\n"
#: gcov.c:1484
#, c-format
msgid "Calls executed:%s of %d\n"
-msgstr ""
+msgstr "実行ã•ã‚ŒãŸå‘¼ã³å‡ºã—:%s of %d\n"
#: gcov.c:1488
#, c-format
@@ -1075,24 +1079,24 @@ msgid "%s:no lines for '%s'\n"
msgstr "%s: '%s' ã«å¯¾ã™ã‚‹è¡ŒãŒã‚ã‚Šã¾ã›ã‚“\n"
#: gcov.c:1843
-#, fuzzy, c-format
+#, c-format
msgid "call %2d returned %s\n"
-msgstr "呼ã³å‡ºã— %d ã®æˆ»ã‚Š = %d\n"
+msgstr ""
#: gcov.c:1848
-#, fuzzy, c-format
+#, c-format
msgid "call %2d never executed\n"
-msgstr "呼ã³å‡ºã— %d ã¯ä¸€åº¦ã‚‚実行ã›ãš\n"
+msgstr ""
#: gcov.c:1853
-#, fuzzy, c-format
+#, c-format
msgid "branch %2d taken %s%s\n"
-msgstr "ブランム%d å—ç† = %d%%\n"
+msgstr ""
#: gcov.c:1857
-#, fuzzy, c-format
+#, c-format
msgid "branch %2d never executed\n"
-msgstr "ブランム%d ã¯ä¸€åº¦ã‚‚実行ã•ã‚Œãš\n"
+msgstr ""
#: gcov.c:1862
#, c-format
@@ -1100,9 +1104,9 @@ msgid "unconditional %2d taken %s\n"
msgstr ""
#: gcov.c:1865
-#, fuzzy, c-format
+#, c-format
msgid "unconditional %2d never executed\n"
-msgstr "呼ã³å‡ºã— %d ã¯ä¸€åº¦ã‚‚実行ã›ãš\n"
+msgstr ""
#: gcov.c:1901
#, c-format
@@ -1412,11 +1416,11 @@ msgstr "次ã®ã‚ªãƒ—ションã¯æ–‡æ›¸åŒ–ã•ã‚Œã¦ã„ã¾ã›ã‚“"
#: opts.c:1183
msgid "The following options take separate arguments"
-msgstr ""
+msgstr "次ã®ã‚ªãƒ—ションã¯åˆ†é›¢ã—ãŸå¼•æ•°ã‚’å–ã‚Šã¾ã™"
#: opts.c:1185
msgid "The following options take joined arguments"
-msgstr ""
+msgstr "次ã®ã‚ªãƒ—ションã¯çµåˆã—ãŸå¼•æ•°ã‚’å–ã‚Šã¾ã™"
#: opts.c:1196
msgid "The following options are language-related"
@@ -1472,7 +1476,7 @@ msgstr "命令ãŒåˆ¶ç´„を満ãŸã—ã¾ã›ã‚“:"
#: targhooks.c:1469
#, c-format
msgid "created and used with differing settings of '%s'"
-msgstr ""
+msgstr "作æˆæ™‚ã¨ä½¿ç”¨æ™‚㧠'%s' ã®è¨­å®šãŒç•°ãªã‚Šã¾ã™"
#: targhooks.c:1471
msgid "out of memory"
@@ -1480,11 +1484,11 @@ msgstr "メモリãŒè¶³ã‚Šã¾ã›ã‚“"
#: targhooks.c:1486
msgid "created and used with different settings of -fpic"
-msgstr ""
+msgstr "作æˆæ™‚ã¨ä½¿ç”¨æ™‚㧠-fpic ã®è¨­å®šãŒç•°ãªã‚Šã¾ã™"
#: targhooks.c:1488
msgid "created and used with different settings of -fpie"
-msgstr ""
+msgstr "作æˆæ™‚ã¨ä½¿ç”¨æ™‚㧠-fpie ã®è¨­å®šãŒç•°ãªã‚Šã¾ã™"
#: tlink.c:386
#, c-format
@@ -1717,11 +1721,11 @@ msgstr ""
#: params.def:100
msgid "The maximum depth of recursive inlining for inline functions"
-msgstr ""
+msgstr "インライン関数をå†å¸°çš„ã«ã‚¤ãƒ³ãƒ©ã‚¤ãƒ³åŒ–ã™ã‚‹æ™‚ã®æœ€å¤§æ·±åº¦"
#: params.def:105
msgid "The maximum depth of recursive inlining for non-inline functions"
-msgstr ""
+msgstr "éžã‚¤ãƒ³ãƒ©ã‚¤ãƒ³é–¢æ•°ã‚’å†å¸°çš„ã«ã‚¤ãƒ³ãƒ©ã‚¤ãƒ³åŒ–ã™ã‚‹æ™‚ã®æœ€å¤§æ·±åº¦"
#: params.def:110
msgid "Inline recursively only when the probability of call being executed exceeds the parameter"
@@ -1761,16 +1765,15 @@ msgstr ""
#: params.def:180
msgid "The size of function body to be considered large"
-msgstr ""
+msgstr "大ãã„ã¨è¦‹ãªã•ã‚Œã‚‹é–¢æ•°æœ¬ä½“ã®ã‚µã‚¤ã‚º"
#: params.def:184
msgid "Maximal growth due to inlining of large function (in percent)"
msgstr ""
#: params.def:188
-#, fuzzy
msgid "The size of translation unit to be considered large"
-msgstr "翻訳å˜ä½å…¨ä½“をファイルã«ãƒ€ãƒ³ãƒ—ã™ã‚‹"
+msgstr "大ãã„ã¨è¦‹ãªã•ã‚Œã‚‹ç¿»è¨³å˜ä½ã®ã‚µã‚¤ã‚º"
#: params.def:192
msgid "How much can given compilation unit grow because of the inlining (in percent)"
@@ -1786,20 +1789,19 @@ msgstr ""
#: params.def:204
msgid "The size of stack frame to be considered large"
-msgstr ""
+msgstr "大ãã„ã¨è¦‹ãªã•ã‚Œã‚‹ã‚¹ã‚¿ãƒƒã‚¯ãƒ•ãƒ¬ãƒ¼ãƒ ã®ã‚µã‚¤ã‚º"
#: params.def:208
msgid "Maximal stack frame growth due to inlining (in percent)"
-msgstr ""
+msgstr "インライン化ã«ã‚ˆã£ã¦å¢—加ã™ã‚‹ã‚¹ã‚¿ãƒƒã‚¯ãƒ•ãƒ¬ãƒ¼ãƒ ã®æœ€å¤§é‡ (百分率)"
#: params.def:215
msgid "The maximum amount of memory to be allocated by GCSE"
-msgstr ""
+msgstr "GCSE ã«ã‚ˆã£ã¦é…ç½®ã•ã‚Œã‚‹ãƒ¡ãƒ¢ãƒªã®æœ€å¤§é‡"
#: params.def:222
-#, fuzzy
msgid "The maximum ratio of insertions to deletions of expressions in GCSE"
-msgstr "RPTS 用ã®æœ€å¤§å復数を指定ã™ã‚‹"
+msgstr ""
#: params.def:233
msgid "The threshold ratio for performing partial redundancy elimination after reload"
@@ -1963,9 +1965,8 @@ msgid "Bound on number of candidates below that all candidates are considered in
msgstr ""
#: params.def:470
-#, fuzzy
msgid "Bound on number of iv uses in loop optimized in iv optimizations"
-msgstr "目立ãŸãªã„ã€ã‚³ã‚¹ãƒˆã®ã‹ã‹ã‚‹æœ€é©åŒ–ã‚’è¡Œãªã†"
+msgstr ""
#: params.def:478
msgid "If number of candidates in the set is smaller, we always try to remove unused ivs during its optimization"
@@ -2044,9 +2045,8 @@ msgid "The minimum probability of reaching a source block for interblock specula
msgstr ""
#: params.def:594
-#, fuzzy
msgid "The maximum number of iterations through CFG to extend regions"
-msgstr "RPTS 用ã®æœ€å¤§å復数を指定ã™ã‚‹"
+msgstr ""
#: params.def:599
msgid "The maximum conflict delay for an insn to be considered for speculative motion"
@@ -2077,9 +2077,8 @@ msgid "The maximum number of RTL nodes that can be recorded as combiner's last v
msgstr ""
#: params.def:637
-#, fuzzy
msgid "The upper bound for sharing integer constants"
-msgstr "`%s' ã®åˆ—挙値ãŒæ•´æ•°å®šæ•°ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
+msgstr "整数定数を共有ã™ã‚‹ãŸã‚ã®ä¸Šé™å€¤"
#: params.def:656
msgid "Minimum number of virtual mappings to consider switching to full virtual renames"
@@ -2111,11 +2110,11 @@ msgstr ""
#: params.def:714
msgid "The number of insns executed before prefetch is completed"
-msgstr ""
+msgstr "プリフェッãƒãŒå®Œäº†ã™ã‚‹å‰ã«å®Ÿè¡Œã•ã‚Œã‚‹å‘½ä»¤æ•°"
#: params.def:721
msgid "The number of prefetches that can run at the same time"
-msgstr ""
+msgstr "åŒæ™‚ã«å®Ÿè¡Œå¯èƒ½ãªãƒ—リフェッãƒã®æ•°"
#: params.def:728
msgid "The size of L1 cache"
@@ -2162,9 +2161,8 @@ msgid "size of tiles for loop blocking"
msgstr ""
#: params.def:806
-#, fuzzy
msgid "maximum number of parameters in a SCoP"
-msgstr "RPTS 用ã®æœ€å¤§å復数を指定ã™ã‚‹"
+msgstr "SCoP 内ã®ãƒ‘ラメータã®æœ€å¤§æ•°"
#: params.def:813
msgid "maximum number of basic blocks per function to be analyzed by Graphite"
@@ -2597,9 +2595,9 @@ msgid "invalid %%E value"
msgstr "無効㪠%%E 値"
#: config/alpha/alpha.c:5431 config/alpha/alpha.c:5479
-#, fuzzy, c-format
+#, c-format
msgid "unknown relocation unspec"
-msgstr "ä¸æ˜Žãªè¨­å®šæ¸ˆã‚³ãƒ³ã‚¹ãƒˆãƒ©ã‚¯ã‚¿åž‹ã§ã™"
+msgstr ""
#: config/alpha/alpha.c:5440 config/crx/crx.c:1119
#: config/rs6000/rs6000.c:16490 config/spu/spu.c:1726
@@ -3000,32 +2998,32 @@ msgstr "被演算å­ã‚³ãƒ¼ãƒ‰ '%c' ã«ç„¡åŠ¹ãªè¢«æ¼”ç®—å­åž‹ãŒä½¿ç”¨ã•ã‚Œã¾
#: config/i386/i386.c:14106 config/i386/i386.c:14146
#, c-format
msgid "operand is not a condition code, invalid operand code 'D'"
-msgstr ""
+msgstr "被演算å­ã¯æ¡ä»¶ã‚³ãƒ¼ãƒ‰ã§ã¯ã‚ã‚Šã¾ã›ã‚“。無効ãªè¢«æ¼”ç®—å­ã‚³ãƒ¼ãƒ‰ 'D' ã§ã™"
#: config/i386/i386.c:14172
#, c-format
msgid "operand is neither a constant nor a condition code, invalid operand code 'C'"
-msgstr ""
+msgstr "被演算å­ã¯å®šæ•°ã§ã‚‚æ¡ä»¶ã‚³ãƒ¼ãƒ‰ã§ã‚‚ã‚ã‚Šã¾ã›ã‚“。無効ãªè¢«æ¼”ç®—å­ã‚³ãƒ¼ãƒ‰ 'C' ã§ã™"
#: config/i386/i386.c:14182
#, c-format
msgid "operand is neither a constant nor a condition code, invalid operand code 'F'"
-msgstr ""
+msgstr "被演算å­ã¯å®šæ•°ã§ã‚‚æ¡ä»¶ã‚³ãƒ¼ãƒ‰ã§ã‚‚ã‚ã‚Šã¾ã›ã‚“。無効ãªè¢«æ¼”ç®—å­ã‚³ãƒ¼ãƒ‰ 'F' ã§ã™"
#: config/i386/i386.c:14200
#, c-format
msgid "operand is neither a constant nor a condition code, invalid operand code 'c'"
-msgstr ""
+msgstr "被演算å­ã¯å®šæ•°ã§ã‚‚æ¡ä»¶ã‚³ãƒ¼ãƒ‰ã§ã‚‚ã‚ã‚Šã¾ã›ã‚“。無効ãªè¢«æ¼”ç®—å­ã‚³ãƒ¼ãƒ‰ 'c' ã§ã™"
#: config/i386/i386.c:14210
#, c-format
msgid "operand is neither a constant nor a condition code, invalid operand code 'f'"
-msgstr ""
+msgstr "被演算å­ã¯å®šæ•°ã§ã‚‚æ¡ä»¶ã‚³ãƒ¼ãƒ‰ã§ã‚‚ã‚ã‚Šã¾ã›ã‚“。無効ãªè¢«æ¼”ç®—å­ã‚³ãƒ¼ãƒ‰ 'f' ã§ã™"
#: config/i386/i386.c:14313
#, c-format
msgid "operand is not a condition code, invalid operand code 'Y'"
-msgstr ""
+msgstr "被演算å­ã¯æ¡ä»¶ã‚³ãƒ¼ãƒ‰ã§ã¯ã‚ã‚Šã¾ã›ã‚“。無効ãªè¢«æ¼”ç®—å­ã‚³ãƒ¼ãƒ‰ 'Y' ã§ã™"
#: config/i386/i386.c:14339
#, c-format
@@ -3098,7 +3096,7 @@ msgstr "%%dã€%%xã€ã¾ãŸã¯ %%X ã®ç„¡åŠ¹ãªä½¿ç”¨æ³•ã§ã™"
#: config/lm32/lm32.c:529
#, c-format
msgid "only 0.0 can be loaded as an immediate"
-msgstr ""
+msgstr "å³å€¤ã¨ã—ã¦ãƒ­ãƒ¼ãƒ‰ã§ãã‚‹ã®ã¯ 0.0 ã®ã¿ã§ã™"
#: config/lm32/lm32.c:599
msgid "bad operand"
@@ -3138,15 +3136,15 @@ msgstr "%%N コードã¸ã®ç„¡åŠ¹ãªè¢«æ¼”ç®—å­ã§ã™"
#: config/m32r/m32r.c:2290
msgid "pre-increment address is not a register"
-msgstr ""
+msgstr "å‰ç½®å¢—分アドレスãŒãƒ¬ã‚¸ã‚¹ã‚¿ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: config/m32r/m32r.c:2297
msgid "pre-decrement address is not a register"
-msgstr ""
+msgstr "å‰ç½®æ¸›åˆ†ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒãƒ¬ã‚¸ã‚¹ã‚¿ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: config/m32r/m32r.c:2304
msgid "post-increment address is not a register"
-msgstr ""
+msgstr "後置増分アドレスãŒãƒ¬ã‚¸ã‚¹ã‚¿ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: config/m32r/m32r.c:2380 config/m32r/m32r.c:2394
#: config/rs6000/rs6000.c:25500
@@ -3252,7 +3250,7 @@ msgstr "stack/frame/arg ãƒã‚¤ãƒ³ã‚¿ç„¡ã—㧠mips_debugger_offset ãŒå‘¼ã°ã‚Œã
#: config/mmix/mmix.c:1589 config/mmix/mmix.c:1719
msgid "MMIX Internal: Expected a CONST_INT, not this"
-msgstr ""
+msgstr "MMIX 内部: CONST_INT ãŒäºˆæœŸã•ã‚Œã¾ã™ãŒã€ç•°ãªã£ã¦ã„ã¾ã™"
#: config/mmix/mmix.c:1668
msgid "MMIX Internal: Bad value for 'm', not a CONST_INT"
@@ -3260,11 +3258,11 @@ msgstr "MMIX 内部: 'm' ã«å¯¾ã™ã‚‹èª¤ã£ãŸå€¤ã§ã™ã€‚CONST_INT ã§ã¯ã‚ã‚Š
#: config/mmix/mmix.c:1687
msgid "MMIX Internal: Expected a register, not this"
-msgstr ""
+msgstr "MMIX 内部: レジスタãŒäºˆæœŸã•ã‚Œã¾ã™ãŒã€ç•°ãªã£ã¦ã„ã¾ã™"
#: config/mmix/mmix.c:1697
msgid "MMIX Internal: Expected a constant, not this"
-msgstr ""
+msgstr "MMIX 内部: 定数ãŒäºˆæœŸã•ã‚Œã¾ã™ãŒã€ç•°ãªã£ã¦ã„ã¾ã™"
#. We need the original here.
#: config/mmix/mmix.c:1781
@@ -3301,7 +3299,7 @@ msgstr ""
#: config/picochip/picochip.c:2983 config/picochip/picochip.c:3015
msgid "Bad address, not (reg+disp):"
-msgstr ""
+msgstr "誤ã£ãŸã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã™ã€‚ (reg+disp) ã§ã¯ã‚ã‚Šã¾ã›ã‚“:"
#: config/picochip/picochip.c:3029
msgid "Bad address, not register:"
@@ -3526,15 +3524,15 @@ msgstr "%%S ã¸ã®ç„¡åŠ¹ãªè¢«æ¼”ç®—å­ã§ã™"
#: config/sh/sh.c:9271
msgid "created and used with different architectures / ABIs"
-msgstr ""
+msgstr "作æˆæ™‚ã¨ä½¿ç”¨æ™‚㧠アーキテクãƒãƒ£/ABI ãŒç•°ãªã‚Šã¾ã™"
#: config/sh/sh.c:9273
msgid "created and used with different ABIs"
-msgstr ""
+msgstr "作æˆæ™‚ã¨ä½¿ç”¨æ™‚㧠ABI ãŒç•°ãªã‚Šã¾ã™"
#: config/sh/sh.c:9275
msgid "created and used with different endianness"
-msgstr ""
+msgstr "作æˆæ™‚ã¨ä½¿ç”¨æ™‚ã§ã‚¨ãƒ³ãƒ‡ã‚£ã‚¢ãƒ³ãŒç•°ãªã‚Šã¾ã™"
#: config/sparc/sparc.c:7445 config/sparc/sparc.c:7451
#, c-format
@@ -3617,7 +3615,7 @@ msgstr ""
#: config/vax/vax.c:427
#, c-format
msgid "symbol with offset used in PIC mode"
-msgstr ""
+msgstr "PIC モードã§ä½¿ç”¨ã•ã‚Œã‚‹ã‚ªãƒ•ã‚»ãƒƒãƒˆä»˜ãã®ã‚·ãƒ³ãƒœãƒ«ã§ã™"
#: config/vax/vax.c:513
#, c-format
@@ -3819,37 +3817,37 @@ msgstr "%s: %qs ã®ã‚¤ãƒ³ã‚¹ã‚¿ãƒ³ã‚¹å†…:\n"
#: cp/error.c:2897
#, c-format
msgid "%s:%d:%d: recursively instantiated from %qs\n"
-msgstr ""
+msgstr "%s:%d:%d: %qs ã‹ã‚‰å†å¸°çš„ã«å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ\n"
#: cp/error.c:2898
-#, fuzzy, c-format
+#, c-format
msgid "%s:%d:%d: instantiated from %qs\n"
-msgstr "%s:%d: `%s' ã‹ã‚‰å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ\n"
+msgstr "%s:%d:%d: %qs ã‹ã‚‰å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ\n"
#: cp/error.c:2903 cp/error.c:2904
#, c-format
msgid "%s:%d: recursively instantiated from %qs\n"
-msgstr ""
+msgstr "%s:%d: %qs ã‹ã‚‰å†å¸°çš„ã«å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ\n"
#: cp/error.c:2912
#, c-format
msgid "%s:%d:%d: recursively instantiated from here"
-msgstr ""
+msgstr "%s:%d:%d: ã“ã“ã‹ã‚‰å†å¸°çš„ã«å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ"
#: cp/error.c:2913
-#, fuzzy, c-format
+#, c-format
msgid "%s:%d:%d: instantiated from here"
-msgstr "%s:%d: ã“ã“ã§å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ\n"
+msgstr "%s:%d:%d: ã“ã“ã‹ã‚‰å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ"
#: cp/error.c:2918
#, c-format
msgid "%s:%d: recursively instantiated from here"
-msgstr ""
+msgstr "%s:%d: ã“ã“ã‹ã‚‰å†å¸°çš„ã«å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ"
#: cp/error.c:2919
-#, fuzzy, c-format
+#, c-format
msgid "%s:%d: instantiated from here"
-msgstr "%s:%d: ã“ã“ã§å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ\n"
+msgstr "%s:%d: ã“ã“ã‹ã‚‰å®Ÿä½“化ã•ã‚Œã¾ã—ãŸ"
#: cp/error.c:2962
#, c-format
@@ -3947,9 +3945,8 @@ msgid "wrong type argument to conjugation"
msgstr "複素共役(~)ã¸ã®å¼•æ•°ã®åž‹ãŒé–“é•ã£ã¦ã„ã¾ã™"
#: cp/typeck.c:5063
-#, fuzzy
msgid "in argument to unary !"
-msgstr "å˜é …プラスã¸ã®å¼•æ•°ã®åž‹ãŒé–“é•ã£ã¦ã„ã¾ã™"
+msgstr ""
#: cp/typeck.c:5112
msgid "no pre-increment operator for type"
@@ -4030,22 +4027,21 @@ msgstr "致命的エラー:"
#: fortran/expr.c:607
#, c-format
msgid "Constant expression required at %C"
-msgstr ""
+msgstr "%C ã§ã¯å®šæ•°å¼ãŒè¦æ±‚ã•ã‚Œã¾ã™"
#: fortran/expr.c:610
#, c-format
msgid "Integer expression required at %C"
-msgstr ""
+msgstr "%C ã§ã¯æ•´æ•°å¼ãŒè¦æ±‚ã•ã‚Œã¾ã™"
#: fortran/expr.c:615
-#, fuzzy, c-format
+#, c-format
msgid "Integer value too large in expression at %C"
-msgstr "å¼ã®æ•´æ•°ãŒã‚ªãƒ¼ãƒãƒ¼ãƒ•ãƒ­ãƒ¼ã—ã¾ã—ãŸ"
+msgstr "%C ã®å¼å†…ã§æ•´æ•°å€¤ãŒå¤§ãã™ãŽã¾ã™"
#: fortran/expr.c:3147
-#, fuzzy
msgid "array assignment"
-msgstr "代入"
+msgstr "é…列代入"
#: fortran/gfortranspec.c:303
#, c-format
@@ -4081,7 +4077,7 @@ msgstr "éžè² ã®å¹…ãŒå¿…è¦ã§ã™"
#: fortran/io.c:551
msgid "Unexpected element '%c' in format string at %L"
-msgstr ""
+msgstr "予期ã—ãªã„è¦ç´  '%c' ãŒæ›¸å¼æ–‡å­—列内 (ä½ç½® %L) ã«ã‚ã‚Šã¾ã™"
#: fortran/io.c:553
msgid "Unexpected end of format string"
@@ -4089,15 +4085,15 @@ msgstr "予期ã—ãªã„書å¼æ–‡å­—列終了ã§ã™"
#: fortran/io.c:554
msgid "Zero width in format descriptor"
-msgstr ""
+msgstr "å¹… 0 ã®æ›¸å¼è¨˜è¿°å­ã§ã™"
#: fortran/io.c:574
msgid "Missing leading left parenthesis"
-msgstr ""
+msgstr "å‰ã«å·¦å°æ‹¬å¼§ãŒã‚ã‚Šã¾ã›ã‚“"
#: fortran/io.c:603
msgid "Left parenthesis required after '*'"
-msgstr ""
+msgstr "'*' ã®å¾Œã«ã¯å·¦å°æ‹¬å¼§ãŒå¿…è¦ã§ã™"
#: fortran/io.c:634
msgid "Expected P edit descriptor"
@@ -4117,9 +4113,8 @@ msgid "Positive width required with T descriptor"
msgstr ""
#: fortran/io.c:844
-#, fuzzy
msgid "E specifier not allowed with g0 descriptor"
-msgstr "åž‹æŒ‡å®šå­ `%s' 㯠struct ã‚„ class ã®å¾Œã«ã¯ä½¿ãˆã¾ã›ã‚“"
+msgstr ""
#: fortran/io.c:914
msgid "Positive exponent width required"
@@ -4363,9 +4358,8 @@ msgid "Start expression in DO loop"
msgstr ""
#: fortran/resolve.c:6233
-#, fuzzy
msgid "End expression in DO loop"
-msgstr "オペランドã¨ã—ã¦ç„¡åŠ¹ãªå¼"
+msgstr ""
#: fortran/resolve.c:6237
msgid "Step expression in DO loop"
@@ -4565,7 +4559,7 @@ msgstr " --bootclasspath PATH 組ã¿è¾¼ã¿ã‚¯ãƒ©ã‚¹ãƒ‘スを上書ãã™ã‚‹\
#: java/jcf-dump.c:1148
#, c-format
msgid " --extdirs PATH Set extensions directory path\n"
-msgstr ""
+msgstr " --extdirs PATH æ‹¡å¼µã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ‘スを設定ã™ã‚‹\n"
#: java/jcf-dump.c:1149
#, c-format
@@ -4735,18 +4729,18 @@ msgstr "é™çš„リンクã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“"
#: config/pa/pa-hpux11.h:111 config/pa/pa64-hpux.h:30 config/pa/pa64-hpux.h:33
#: config/pa/pa64-hpux.h:42 config/pa/pa64-hpux.h:45
msgid "warning: consider linking with '-static' as system libraries with"
-msgstr ""
+msgstr "警告: システムライブラリã¨ãƒªãƒ³ã‚¯ã™ã‚‹æ™‚㯠'-static' を指定ã™ã‚‹ã“ã¨ã‚’検討ã—ã¦ãã ã•ã„"
#: config/pa/pa-hpux10.h:90 config/pa/pa-hpux10.h:93 config/pa/pa-hpux10.h:101
#: config/pa/pa-hpux10.h:104 config/pa/pa-hpux11.h:109
#: config/pa/pa-hpux11.h:112 config/pa/pa64-hpux.h:31 config/pa/pa64-hpux.h:34
#: config/pa/pa64-hpux.h:43 config/pa/pa64-hpux.h:46
msgid " profiling support are only provided in archive format"
-msgstr ""
+msgstr " プロファイリングサãƒãƒ¼ãƒˆã¯æ›¸åº«ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆå†…ã§ã®ã¿æä¾›ã•ã‚Œã¾ã™"
#: config/rs6000/darwin.h:99
msgid " conflicting code gen style switches are used"
-msgstr ""
+msgstr " 競åˆã—ã¦ã„るコード生æˆã‚¹ã‚¿ã‚¤ãƒ«ã‚¹ã‚¤ãƒƒãƒãŒä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™"
#: config/arm/arm.h:178
msgid "-msoft-float and -mhard_float may not be used together"
@@ -4806,7 +4800,7 @@ msgstr "-femit-class-file 㯠-fsyntax-only ã«åˆã‚ã›ã¦ä½¿ç”¨ã—ã¦ãã ã•
#: config/i386/linux-unwind.h:186
msgid "ax ; {int $0x80 | syscall"
-msgstr ""
+msgstr "ax ; {int $0x80 | syscall"
#: config/s390/tpf.h:120
msgid "static is not supported on TPF-OS"
@@ -4870,7 +4864,7 @@ msgstr "--encoding=<encoding>\t入力エンコーディングをé¸æŠžã™ã‚‹ (ãƒ
#: java/lang.opt:206
msgid "--extdirs=<path>\tSet the extension directory path"
-msgstr ""
+msgstr "--extdirs=<path>\tæ‹¡å¼µã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ‘スを設定ã™ã‚‹"
#: java/lang.opt:216
msgid "Input file is a file with a list of filenames to compile"
@@ -5389,7 +5383,7 @@ msgstr ""
#: config/frv/frv.opt:31
msgid "Enable label alignment optimizations"
-msgstr ""
+msgstr "ラベル整列最é©åŒ–を有効ã«ã™ã‚‹"
#: config/frv/frv.opt:35
msgid "Dynamically allocate cc registers"
@@ -5453,7 +5447,7 @@ msgstr "64 個ã®æ±Žç”¨ãƒ¬ã‚¸ã‚¹ã‚¿ (GPR) を使用ã™ã‚‹"
#: config/frv/frv.opt:116
msgid "Enable use of GPREL for read-only data in FDPIC"
-msgstr ""
+msgstr "FDPIC 内ã®èª­ã¿å–り専用データ用 GPREL ã®ä½¿ç”¨ã‚’有効ã«ã™ã‚‹"
#: config/frv/frv.opt:120 config/rs6000/rs6000.opt:216
#: config/pdp11/pdp11.opt:67
@@ -5461,9 +5455,8 @@ msgid "Use hardware floating point"
msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢æµ®å‹•å°æ•°ç‚¹ã‚’利用ã™ã‚‹"
#: config/frv/frv.opt:124 config/bfin/bfin.opt:77
-#, fuzzy
msgid "Enable inlining of PLT in function calls"
-msgstr "関数呼ã³å‡ºã—ã®å‰å¾Œã§ãƒ¬ã‚¸ã‚¹ã‚¿ã®ä¿å­˜ã‚’有効ã«ã™ã‚‹"
+msgstr "関数呼ã³å‡ºã—内㧠PLT ã®ã‚¤ãƒ³ãƒ©ã‚¤ãƒ³åŒ–を有効ã«ã™ã‚‹"
#: config/frv/frv.opt:128
msgid "Enable PIC support for building libraries"
@@ -5479,7 +5472,7 @@ msgstr "大域関数ã®ç›´æŽ¥å‘¼ã³å‡ºã—を無効ã«ã™ã‚‹"
#: config/frv/frv.opt:140
msgid "Use media instructions"
-msgstr ""
+msgstr "media 命令を使用ã™ã‚‹"
#: config/frv/frv.opt:144
msgid "Use multiply add/subtract instructions"
@@ -5495,7 +5488,7 @@ msgstr "入れå­ã«ã•ã‚ŒãŸæ¡ä»¶ä»˜ã実行ã®æœ€é©åŒ–を有効ã«ã™ã‚‹"
#: config/frv/frv.opt:157
msgid "Do not mark ABI switches in e_flags"
-msgstr ""
+msgstr "e_flags 内㮠ABI スイッãƒã‚’マークã—ãªã„"
#: config/frv/frv.opt:161
msgid "Remove redundant membars"
@@ -5507,7 +5500,7 @@ msgstr ""
#: config/frv/frv.opt:169
msgid "Enable setting GPRs to the result of comparisons"
-msgstr ""
+msgstr "比較çµæžœã‚’汎用レジスタã«è¨­å®šã™ã‚‹ã“ã¨ã‚’有効ã«ã™ã‚‹"
#: config/frv/frv.opt:173
msgid "Change the amount of scheduler lookahead"
@@ -5566,9 +5559,8 @@ msgid "Return pointers in both a0 and d0"
msgstr ""
#: config/mn10300/mn10300.opt:56
-#, fuzzy
msgid "Allow gcc to generate LIW instructions"
-msgstr "gcc ㌠repeat/erepeat 命令を使用ã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹"
+msgstr "gcc ㌠LIW 命令を生æˆã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹"
#: config/s390/tpf.opt:23
msgid "Enable TPF-OS tracing code"
@@ -5641,11 +5633,11 @@ msgstr ""
#: config/s390/s390.opt:91
msgid "Warn if a function uses alloca or creates an array with dynamic size"
-msgstr ""
+msgstr "関数㧠alloca を使用ã™ã‚‹ã‹ã€ã¾ãŸã¯å‹•çš„サイズã®é…列を作æˆã—ãŸå ´åˆã«ã€è­¦å‘Šã™ã‚‹"
#: config/s390/s390.opt:95
msgid "Warn if a single function's framesize exceeds the given framesize"
-msgstr ""
+msgstr "一ã¤ã®é–¢æ•°ã®ãƒ•ãƒ¬ãƒ¼ãƒ ã‚µã‚¤ã‚ºãŒä¸Žãˆã‚‰ã‚ŒãŸãƒ•ãƒ¬ãƒ¼ãƒ ã‚µã‚¤ã‚ºã‚’超éŽã™ã‚‹å ´åˆã«è­¦å‘Šã™ã‚‹"
#: config/s390/s390.opt:99
msgid "z/Architecture"
@@ -5693,7 +5685,7 @@ msgstr "GP レジスタä¸ä½¿ç”¨ã®ã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹"
#: config/ia64/ia64.opt:56
msgid "gp is constant (but save/restore gp on indirect calls)"
-msgstr "gp を定数ã¨ã™ã‚‹ï¼ˆä½†ã€é–“接呼ã³å‡ºã—ã§ã¯ gp ã‚’ save/restore ã™ã‚‹ï¼‰"
+msgstr "gp を定数ã¨ã™ã‚‹ï¼ˆãŸã ã—ã€é–“接呼ã³å‡ºã—ã§ã¯ gp ã‚’ save/restore ã™ã‚‹ï¼‰"
#: config/ia64/ia64.opt:60
msgid "Generate self-relocatable code"
@@ -5742,39 +5734,39 @@ msgstr "より良ã„スケジューリング用ã«äº‹å‰ã«ã‚¹ãƒˆãƒƒãƒ—ビット
#: config/ia64/ia64.opt:107 config/spu/spu.opt:72 config/sh/sh.opt:258
#: config/pa/pa.opt:51
msgid "Specify range of registers to make fixed"
-msgstr ""
+msgstr "固定ã™ã‚‹ãƒ¬ã‚¸ã‚¹ã‚¿ã®ç¯„囲を指定ã™ã‚‹"
#: config/ia64/ia64.opt:119
msgid "Use data speculation before reload"
-msgstr ""
+msgstr "reload å‰ã«ãƒ‡ãƒ¼ã‚¿æŠ•æ©Ÿã‚’使用ã™ã‚‹"
#: config/ia64/ia64.opt:123
msgid "Use data speculation after reload"
-msgstr ""
+msgstr "reload 後ã«ãƒ‡ãƒ¼ã‚¿æŠ•æ©Ÿã‚’使用ã™ã‚‹"
#: config/ia64/ia64.opt:127
msgid "Use control speculation"
-msgstr ""
+msgstr "制御投機を使用ã™ã‚‹"
#: config/ia64/ia64.opt:131
msgid "Use in block data speculation before reload"
-msgstr ""
+msgstr "reload å‰ã«ãƒ–ロック内データ投機を使用ã™ã‚‹"
#: config/ia64/ia64.opt:135
msgid "Use in block data speculation after reload"
-msgstr ""
+msgstr "reload 後ã«ãƒ–ロック内データ投機を使用ã™ã‚‹"
#: config/ia64/ia64.opt:139
msgid "Use in block control speculation"
-msgstr ""
+msgstr "ブロック内制御投機を使用ã™ã‚‹"
#: config/ia64/ia64.opt:143
msgid "Use simple data speculation check"
-msgstr ""
+msgstr "å˜ç´”データ投機検査を使用ã™ã‚‹"
#: config/ia64/ia64.opt:147
msgid "Use simple data speculation check for control speculation"
-msgstr ""
+msgstr "制御投機用ã®å˜ç´”データ投機検査を使用ã™ã‚‹"
#: config/ia64/ia64.opt:151
msgid "If set, data speculative instructions will be chosen for schedule only if there are no other choices at the moment "
@@ -5790,7 +5782,7 @@ msgstr ""
#: config/ia64/ia64.opt:163
msgid "Place a stop bit after every cycle when scheduling"
-msgstr ""
+msgstr "スケジューリング時ã®å„サイクル後ã«ã‚¹ãƒˆãƒƒãƒ—ビットをé…ç½®ã™ã‚‹"
#: config/ia64/ia64.opt:167
msgid "Assume that floating-point stores and loads are not likely to cause conflict when placed into one instruction group"
@@ -5806,7 +5798,7 @@ msgstr ""
#: config/ia64/ia64.opt:179
msgid "Don't generate checks for control speculation in selective scheduling"
-msgstr ""
+msgstr "é¸æŠžçš„スケジューリング内ã§ã¯åˆ¶å¾¡æŠ•æ©Ÿç”¨ã®æ¤œæŸ»ã‚’生æˆã—ãªã„"
#: config/ia64/vms_symvec_libgcc_s.opt:3
msgid "! It would be better to auto-generate this file."
@@ -6110,7 +6102,7 @@ msgstr "'rtd' を使用ã™ã‚‹ç•°ãªã‚‹å‘¼ã³å‡ºã—è¦ç´„を使用ã™ã‚‹"
#: config/m68k/m68k.opt:160 config/bfin/bfin.opt:61
msgid "Enable separate data segment"
-msgstr ""
+msgstr "分離データセグメントを有効ã«ã™ã‚‹"
#: config/m68k/m68k.opt:164 config/bfin/bfin.opt:57
msgid "ID of shared library to build"
@@ -6150,7 +6142,7 @@ msgstr "無視ã•ã‚Œã‚‹ (廃止)"
#: config/i386/mingw.opt:23
msgid "Warn about none ISO msvcrt scanf/printf width extensions"
-msgstr ""
+msgstr "éž ISO ã® msvcrt scanf/printf ã®å¹…æ‹¡å¼µã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
#: config/i386/mingw.opt:27
msgid "For nested functions on stack executable permission is set."
@@ -6202,7 +6194,7 @@ msgstr "分å²ã®ã‚³ã‚¹ãƒˆã‚’指定ã™ã‚‹ (1-5, ä»»æ„ã®å€‹æ•°)"
#: config/i386/i386.opt:114
msgid "Data greater than given threshold will go into .ldata section in x86-64 medium model"
-msgstr ""
+msgstr "x86-64 メディアモデルã§ã¯ä¸Žãˆã‚‰ã‚ŒãŸé–¾å€¤ã‚ˆã‚Šå¤§ãã„データを .ldata セクションã«é…ç½®ã™ã‚‹"
#: config/i386/i386.opt:118
msgid "Use given x86-64 code model"
@@ -6218,16 +6210,15 @@ msgstr "FPU 用㮠sin, cos, sqrt を生æˆã™ã‚‹"
#: config/i386/i386.opt:129
msgid "Always use Dynamic Realigned Argument Pointer (DRAP) to realign stack"
-msgstr ""
+msgstr "スタックをå†æ•´åˆ—ã™ã‚‹ãŸã‚ã«å‹•çš„å†æ•´åˆ—引数ãƒã‚¤ãƒ³ã‚¿ (Dynamic Realigned Argument Pointer, DRAP) を常ã«ä½¿ç”¨ã™ã‚‹"
#: config/i386/i386.opt:133
msgid "Return values of functions in FPU registers"
msgstr "FPU レジスタ内ã®æ©Ÿèƒ½ã®å€¤ã‚’è¿”ã™"
#: config/i386/i386.opt:137
-#, fuzzy
msgid "Generate floating point mathematics using given instruction set"
-msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢æµ®å‹•å°æ•°ç‚¹å‘½ä»¤ã‚’使用ã™ã‚‹"
+msgstr "与ãˆã‚‰ã‚ŒãŸå‘½ä»¤é›†åˆã‚’使用ã—ã¦æµ®å‹•å°æ•°æ•°å€¤è¨ˆç®—を生æˆã™ã‚‹"
#: config/i386/i386.opt:149
msgid "Inline all known string operations"
@@ -6315,8 +6306,9 @@ msgid "Return 8-byte vectors in memory"
msgstr "8 ãƒã‚¤ãƒˆãƒ™ã‚¯ãƒˆãƒ«ã‚’メモリã«è¿”ã™"
#: config/i386/i386.opt:253
+#, fuzzy
msgid "Generate reciprocals instead of divss and sqrtss."
-msgstr ""
+msgstr "divss ãŠã‚ˆã³ sqrtss ã®ä»£ã‚ã‚Šã«é€†æ•° (reciprocal) を生æˆã™ã‚‹"
#: config/i386/i386.opt:257
msgid "Generate cld instruction in the function prologue."
@@ -6332,7 +6324,7 @@ msgstr ""
#: config/i386/i386.opt:271
msgid "Use 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer."
-msgstr ""
+msgstr "自動ベクトル化㧠256 ビット AVX 命令ã®ä»£ã‚ã‚Šã« 128 ビット AVX 命令を使用ã™ã‚‹"
#: config/i386/i386.opt:277
msgid "Generate 32bit i386 code"
@@ -6383,9 +6375,8 @@ msgid "Do not support SSE4.1 and SSE4.2 built-in functions and code generation"
msgstr "SSE4.1 㨠SSE4.2 ã®çµ„ã¿è¾¼ã¿é–¢æ•°ã¨ã‚³ãƒ¼ãƒ‰ç”Ÿæˆã‚’サãƒãƒ¼ãƒˆã—ãªã„"
#: config/i386/i386.opt:328
-#, fuzzy
msgid "%<-msse5%> was removed"
-msgstr "'-msse5' ã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
+msgstr "%<-msse5%> ã¯å‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
#: config/i386/i386.opt:333
msgid "Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2 and AVX built-in functions and code generation"
@@ -6545,7 +6536,7 @@ msgstr "PowerPC-64 命令セットを使用ã™ã‚‹"
#: config/rs6000/rs6000.opt:152
msgid "Use PowerPC General Purpose group optional instructions"
-msgstr "PowerPC 一般用途グループオプション命令を使用ã™ã‚‹"
+msgstr "PowerPC 汎用グループオプション命令を使用ã™ã‚‹"
#: config/rs6000/rs6000.opt:156
msgid "Use PowerPC Graphics group optional instructions"
@@ -7003,7 +6994,7 @@ msgstr "リトルエンディアンコードを生æˆã™ã‚‹"
#: config/mcore/mcore.opt:56 config/fr30/fr30.opt:27
msgid "Assume that run-time support has been provided, so omit -lsim from the linker command line"
-msgstr ""
+msgstr "実行時サãƒãƒ¼ãƒˆãŒæä¾›ã•ã‚Œã‚‹ã¨è¦‹ãªã—ã€ãƒªãƒ³ã‚«ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã« -lsim ã‚’å«ã‚ãªã„"
#: config/mcore/mcore.opt:60
msgid "Use arbitrary sized immediates in bit operations"
@@ -7015,7 +7006,7 @@ msgstr "ãƒã‚¤ãƒˆã‚¢ã‚¯ã‚»ã‚¹ã‚ˆã‚Šãƒ¯ãƒ¼ãƒ‰ã‚¢ã‚¯ã‚»ã‚¹ã‚’é¸ã¶"
#: config/mcore/mcore.opt:71
msgid "Set the maximum amount for a single stack increment operation"
-msgstr "å˜ä¸€ã®ã‚¹ã‚¿ãƒƒã‚¯ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆæ“作ã®æœ€å¤§å€¤ã‚’設定ã™ã‚‹"
+msgstr "å˜ä¸€ã®ã‚¹ã‚¿ãƒƒã‚¯å¢—分æ“作ã®æœ€å¤§å€¤ã‚’設定ã™ã‚‹"
#: config/mcore/mcore.opt:75
msgid "Always treat bitfields as int-sized"
@@ -7235,7 +7226,7 @@ msgstr "double ã‚’ 64 ビット境界ã«æ•´åˆ—ã™ã‚‹"
#: config/sh/sh.opt:246
msgid "Division strategy, one of: call, call2, fp, inv, inv:minlat, inv20u, inv20l, inv:call, inv:call2, inv:fp, call-div1, call-fp, call-table"
-msgstr ""
+msgstr "除算戦略ã€æ¬¡ã®ã„ãšã‚Œã‹: call, call2, fp, inv, inv:minlat, inv20u, inv20l, inv:call, inv:call2, inv:fp, call-div1, call-fp, call-table"
#: config/sh/sh.opt:250
msgid "Specify name for 32 bit signed division function"
@@ -7283,7 +7274,7 @@ msgstr "リトルエンディアンモードã§ã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹"
#: config/sh/sh.opt:298
msgid "Mark MAC register as call-clobbered"
-msgstr ""
+msgstr "MAC レジスタを呼ã³å‡ºã—ã§ç ´å£Šã•ã‚Œã‚‹ã¨ãƒžãƒ¼ã‚¯ã™ã‚‹"
#: config/sh/sh.opt:304
msgid "Make structs a multiple of 4 bytes (warning: ABI altered)"
@@ -7961,7 +7952,7 @@ msgstr "68HCS12 用ã«ã‚³ãƒ³ãƒ‘イルã™ã‚‹"
#: config/m68hc11/m68hc11.opt:49
msgid "Auto pre/post decrement increment allowed"
-msgstr "自動 pre/post デクリメント インクリメントを許容ã™ã‚‹"
+msgstr "自動 å‰ç½®/後置 減分/増分 を許容ã™ã‚‹"
#: config/m68hc11/m68hc11.opt:53
msgid "Min/max instructions allowed"
@@ -7973,7 +7964,7 @@ msgstr "関数呼ã³å‡ºã—ã¨æˆ»ã‚Šç”¨ã« call 㨠rtc を使用ã™ã‚‹"
#: config/m68hc11/m68hc11.opt:61
msgid "Auto pre/post decrement increment not allowed"
-msgstr "自動 pre/post デクリメント インクリメントを許容ã—ãªã„"
+msgstr "自動 å‰ç½®/後置 減分/増分を許容ã—ãªã„"
#: config/m68hc11/m68hc11.opt:65
msgid "Use jsr and rts for function calls and returns"
@@ -8347,7 +8338,7 @@ msgstr ""
#: config/bfin/bfin.opt:69
msgid "Link with the fast floating-point library"
-msgstr ""
+msgstr "高速ãªæµ®å‹•å°æ•°ãƒ©ã‚¤ãƒ–ラリã¨ãƒªãƒ³ã‚¯ã™ã‚‹"
#: config/bfin/bfin.opt:81
msgid "Do stack checking using bounds in L1 scratch memory"
@@ -8383,7 +8374,7 @@ msgstr ""
#: config/picochip/picochip.opt:31
msgid "Specify whether the byte access instructions should be used. Enabled by default."
-msgstr ""
+msgstr "ãƒã‚¤ãƒˆã‚¢ã‚¯ã‚»ã‚¹å‘½ä»¤ã‚’使用ã™ã‚‹ã‹ã©ã†ã‹ã‚’指定ã™ã‚‹ã€‚デフォルトã§ã¯æœ‰åŠ¹ã¨ãªã‚‹"
#: config/picochip/picochip.opt:35
msgid "Enable debug output to be generated."
@@ -8391,11 +8382,11 @@ msgstr "デãƒãƒƒã‚°å‡ºåŠ›ã®ç”Ÿæˆã‚’有効ã«ã™ã‚‹"
#: config/picochip/picochip.opt:39
msgid "Allow a symbol value to be used as an immediate value in an instruction."
-msgstr ""
+msgstr "命令内ã§ã‚·ãƒ³ãƒœãƒ«å€¤ãŒå³å€¤ã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹"
#: config/picochip/picochip.opt:43
msgid "Generate warnings when inefficient code is known to be generated."
-msgstr ""
+msgstr "éžåŠ¹çŽ‡ãªã‚³ãƒ¼ãƒ‰ãŒç”Ÿæˆã•ã‚ŒãŸæ™‚ã«è­¦å‘Šã™ã‚‹"
#: config/vxworks.opt:36
msgid "Assume the VxWorks RTP environment"
@@ -8419,7 +8410,7 @@ msgstr "コンパイル時 CFString オブジェクトを生æˆã™ã‚‹"
#: config/darwin.opt:205
msgid "Warn if constant CFString objects contain non-portable characters"
-msgstr ""
+msgstr "定数 CFString オブジェクトãŒç§»æ¤æ€§ã®ç„¡ã„文字をå«ã‚€å ´åˆã«è­¦å‘Šã™ã‚‹"
#: config/darwin.opt:210
msgid "Generate AT&T-style stubs for Mach-O"
@@ -8431,7 +8422,7 @@ msgstr "実行å¯èƒ½ãƒ•ã‚¡ã‚¤ãƒ«ç”¨ (共有ライブラリã§ã¯ãªã) ã«é©ã
#: config/darwin.opt:218
msgid "Generate code suitable for fast turn around debugging"
-msgstr ""
+msgstr "デãƒãƒƒã‚°ã‚’高速ã«è¡Œã†ãŸã‚ã«é©ã—ãŸã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹"
#: config/darwin.opt:227
msgid "The earliest MacOS X version on which this program will run"
@@ -8443,15 +8434,15 @@ msgstr "sizeof(bool) ã‚’ 1 ã«è¨­å®šã™ã‚‹"
#: config/darwin.opt:235
msgid "Generate code for darwin loadable kernel extensions"
-msgstr ""
+msgstr "darwin ロードå¯èƒ½ã‚«ãƒ¼ãƒãƒ«æ‹¡å¼µç”¨ã®ã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹"
#: config/darwin.opt:239
msgid "Generate code for the kernel or loadable kernel extensions"
-msgstr ""
+msgstr "カーãƒãƒ«ç”¨ã€ã¾ãŸã¯ãƒ­ãƒ¼ãƒ‰å¯èƒ½ã‚«ãƒ¼ãƒãƒ«æ‹¡å¼µç”¨ã®ã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹"
#: config/darwin.opt:243
msgid "-iframework <dir>\tAdd <dir> to the end of the system framework include path"
-msgstr ""
+msgstr "-iframework <dir>\t<dir> をシステムフレームワークインクルードパスã®æœ«å°¾ã«åŠ ãˆã‚‹"
#: config/lynx.opt:23
msgid "Support legacy multi-threading"
@@ -8738,7 +8729,6 @@ msgid "Use multiply high instructions for high part of 32x32 multiply"
msgstr ""
#: config/microblaze/microblaze.opt:92
-#, fuzzy
msgid "Use hardware floating point conversion instructions"
msgstr "ãƒãƒ¼ãƒ‰ã‚¦ã‚§ã‚¢æµ®å‹•å°æ•°ç‚¹å¤‰æ›å‘½ä»¤ã‚’使用ã™ã‚‹"
@@ -8863,7 +8853,7 @@ msgstr ""
#: c-family/c.opt:249
msgid "-MT <target>\tAdd an unquoted target"
-msgstr ""
+msgstr "-MT <target>\tターゲット (引用符を付ã‘ãªã„) を追加ã™ã‚‹"
#: c-family/c.opt:253
msgid "Do not generate #line directives"
@@ -8899,11 +8889,11 @@ msgstr "組ã¿è¾¼ã¿å‰å‡¦ç†ãƒžã‚¯ãƒ­ãŒæœªå®šç¾©ã«ãªã‚‹ã‹å†å®šç¾©ã•ã‚ŒãŸ
#: c-family/c.opt:288
msgid "Warn about C constructs that are not in the common subset of C and C++"
-msgstr ""
+msgstr "C 㨠C++ ã®å…±é€šéƒ¨åˆ†é›†åˆã§ã¯ç„¡ã„ C 構文ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
#: c-family/c.opt:292
msgid "Warn about C++ constructs whose meaning differs between ISO C++ 1998 and ISO C++ 200x"
-msgstr ""
+msgstr "ISO C++ 1998 㨠ISO C++ 200x ã§æ„味ãŒç•°ãªã‚‹ C++ 構文ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
#: c-family/c.opt:296
msgid "Warn about casts which discard qualifiers"
@@ -8963,7 +8953,7 @@ msgstr "if ã¾ãŸã¯ else æ–‡ã®ä¸­èº«ãŒç©ºã®å ´åˆã«è­¦å‘Šã™ã‚‹"
#: c-family/c.opt:352
msgid "Warn about stray tokens after #elif and #endif"
-msgstr ""
+msgstr "#elif ãŠã‚ˆã³ #endif ã®å¾Œã«ã‚ã‚‹ã¯ãã‚ŒãŸãƒˆãƒ¼ã‚¯ãƒ³ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
#: c-family/c.opt:356
msgid "Warn about comparison of different enum types"
@@ -8978,9 +8968,8 @@ msgid "Warn if testing floating point numbers for equality"
msgstr "浮動å°æ•°ç‚¹æ•°ã®ç­‰ä¾¡æ¯”較ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
#: c-family/c.opt:372
-#, fuzzy
msgid "Warn about printf/scanf/strftime/strfmon format string anomalies"
-msgstr "printf/scanf/strftime/strfmon å½¢å¼ã®å¤‰å‰‡çš„ãªã‚‚ã®ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
+msgstr "printf/scanf/strftime/strfmon 書å¼æ–‡å­—列異常ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
#: c-family/c.opt:376
msgid "Warn if passing too many arguments to a function for its format string"
@@ -8999,9 +8988,8 @@ msgid "Warn about possible security problems with format functions"
msgstr "セキュリティå•é¡Œã«ãªã‚‹å¯èƒ½æ€§ãŒã‚る書å¼é–¢æ•°ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
#: c-family/c.opt:392
-#, fuzzy
msgid "Warn about strftime formats yielding 2-digit years"
-msgstr "strftime å½¢å¼ãŒäºŒæ¡ã§å¹´ã‚’表ã—ã¦ã„る時ã®è­¦å‘Šã—ãªã„"
+msgstr "strftime 書å¼ãŒ 2 æ¡ã®å¹´ã®å ´åˆã«è­¦å‘Šã™ã‚‹"
#: c-family/c.opt:396
msgid "Warn about zero-length formats"
@@ -9410,7 +9398,7 @@ msgstr "フレンド関数を囲ã¾ã‚ŒãŸåå‰ç©ºé–“内ã«å…¥ã‚Œã‚‹"
#: c-family/c.opt:823
msgid "Don't emit dllexported inline functions unless needed"
-msgstr ""
+msgstr "å¿…è¦ãŒç„¡ã„é™ã‚Š dllexported インライン関数を発行ã—ãªã„"
#: c-family/c.opt:830
msgid "Allow implicit conversions between vectors with differing numbers of subparts and/or differing element types."
@@ -9502,7 +9490,7 @@ msgstr "自動テンプレート実体化を有効ã«ã™ã‚‹"
#: c-family/c.opt:942
msgid "Generate run time type descriptor information"
-msgstr ""
+msgstr "実行時型記述å­æƒ…報を生æˆã™ã‚‹"
#: c-family/c.opt:946
msgid "Use the same size for double as for float"
@@ -9890,19 +9878,16 @@ msgid "Warn about functions which might be candidates for __attribute__((pure))"
msgstr "関数㌠__attribute__((pure)) ã®å€™è£œã¨ãªã‚Šãã†ãªå ´åˆã«è­¦å‘Šã™ã‚‹"
#: common.opt:608
-#, fuzzy
msgid "Warn about enumerated switches, with no default, missing a case"
-msgstr "列挙定数㮠switch 㧠case 指定ãŒæ¬ ã‘ã¦ã„ã‚‹ã‚‚ã®ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
+msgstr "列挙定数を使用ã—㟠switch 文㧠default æ–‡ãŒç„¡ã„ã‹ç‰¹å®šã® case ãŒç„¡ã„å ´åˆã«è­¦å‘Šã™ã‚‹"
#: common.opt:612
-#, fuzzy
msgid "Warn about enumerated switches missing a \"default:\" statement"
-msgstr "列挙定数㮠switch 㧠case 指定ãŒæ¬ ã‘ã¦ã„ã‚‹ã‚‚ã®ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
+msgstr "列挙定数を使用ã—㟠switch 文㧠\"default:\" æ–‡ãŒç„¡ã„å ´åˆã«è­¦å‘Šã™ã‚‹"
#: common.opt:616
-#, fuzzy
msgid "Warn about all enumerated switches missing a specific case"
-msgstr "列挙定数㮠switch 㧠case 指定ãŒæ¬ ã‘ã¦ã„ã‚‹ã‚‚ã®ã«é–¢ã—ã¦è­¦å‘Šã™ã‚‹"
+msgstr "列挙定数を使用ã—㟠switch æ–‡ã§ç‰¹å®šã® case ãŒç„¡ã„å ´åˆã«è­¦å‘Šã™ã‚‹"
#: common.opt:620
msgid "Do not suppress warnings from system headers"
@@ -10001,9 +9986,8 @@ msgid "Generate auto-inc/dec instructions"
msgstr "自動増加/減少命令を生æˆã™ã‚‹"
#: common.opt:821
-#, fuzzy
msgid "Generate code to check bounds before indexing arrays"
-msgstr "é…列ã®æ·»å­—ã¨æ·»å­—境界を検査ã™ã‚‹ã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹"
+msgstr "é…列ã®æ·»ãˆå­—を使用ã™ã‚‹å‰ã«å¢ƒç•Œæ¤œæŸ»ã‚’è¡Œã†ã‚³ãƒ¼ãƒ‰ã‚’生æˆã™ã‚‹"
#: common.opt:825
#, fuzzy
@@ -10044,7 +10028,7 @@ msgstr ""
#: common.opt:864
msgid "Looks for opportunities to reduce stack adjustments and stack references."
-msgstr ""
+msgstr "スタック調整ãŠã‚ˆã³ã‚¹ã‚¿ãƒƒã‚¯å‚照を削減ã™ã‚‹æ©Ÿä¼šã‚’探ã™"
#: common.opt:868
msgid "Do not put uninitialized globals in the common section"
@@ -10059,18 +10043,16 @@ msgid "Run only the second compilation of -fcompare-debug"
msgstr ""
#: common.opt:884
-#, fuzzy
msgid "Perform comparison elimination after register allocation has finished"
-msgstr "グローãƒãƒ«å…±é€šéƒ¨åˆ†å¼ã‚’除去ã™ã‚‹"
+msgstr "レジスタã¯ä½ç½®ãŒå®Œäº†ã—ãŸå¾Œã«æ¯”較ã®é™¤åŽ»ã‚’è¡Œã†"
#: common.opt:888
msgid "Do not perform optimizations increasing noticeably stack usage"
-msgstr ""
+msgstr "スタック使用é‡ã‚’è‘—ã—ã増加ã•ã›ã‚‹æœ€é©åŒ–ã‚’è¡Œã‚ãªã„"
#: common.opt:892
-#, fuzzy
msgid "Perform a register copy-propagation optimization pass"
-msgstr "最é©åŒ–éŽç¨‹ã®ãƒ¬ã‚¸ã‚¹ã‚¿ã¤ã‘変ãˆã‚’è¡Œãªã†"
+msgstr ""
#: common.opt:896
msgid "Perform cross-jumping optimization"
@@ -10102,7 +10084,7 @@ msgstr "-fdbg-cnt=<counter>:<limit>[,<counter>:<limit>,...]\tデãƒãƒƒã‚°ã‚«ã‚¦ã
#: common.opt:928
msgid "Map one directory name to another in debug information"
-msgstr ""
+msgstr "デãƒãƒƒã‚°æƒ…報内ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªãƒ¼åã‚’ä»–ã®ã‚‚ã®ã«ãƒžãƒƒãƒ—ã™ã‚‹"
#: common.opt:934
msgid "Defer popping functions args from stack until later"
@@ -10117,9 +10099,8 @@ msgid "Delete useless null pointer checks"
msgstr "ç„¡æ„味㪠null ãƒã‚¤ãƒ³ã‚¿æ¤œæŸ»ã‚’削除ã™ã‚‹"
#: common.opt:946
-#, fuzzy
msgid "Try to convert virtual calls to direct ones."
-msgstr "リンカ㌠PIC 呼ã³å‡ºã—を直接呼ã³å‡ºã—ã«å¤‰æ›´ã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹ã‚ˆã†ã«è©¦ã¿ã‚‹"
+msgstr "仮想呼ã³å‡ºã—を直接呼ã³å‡ºã—ã«å¤‰æ›ã™ã‚‹ã“ã¨ã‚’試ã¿ã‚‹"
#: common.opt:950
#, fuzzy
@@ -10138,7 +10119,7 @@ msgstr "-fdump-<type>\t様々ãªã‚³ãƒ³ãƒ‘イラ内部情報をファイルã«ãƒ€
#: common.opt:978
msgid "-fdump-final-insns=filename\tDump to filename the insns at the end of translation"
-msgstr ""
+msgstr "-fdump-final-insns=filename\t翻訳終了時㫠filename ã¸å‘½ä»¤ã‚’ダンプã™ã‚‹"
#: common.opt:982
msgid "-fdump-go-spec=filename\tWrite all declarations to file as Go code"
@@ -10174,7 +10155,7 @@ msgstr ""
#: common.opt:1014 common.opt:1018
msgid "Perform unused type elimination in debug info"
-msgstr ""
+msgstr "デãƒãƒƒã‚°æƒ…報内ã§ä½¿ç”¨ã•ã‚Œã¦ã„ãªã„åž‹ã®é™¤åŽ»ã‚’è¡Œã†"
#: common.opt:1022
msgid "Do not suppress C++ class debug information."
@@ -10182,25 +10163,24 @@ msgstr "C++ クラスデãƒãƒƒã‚°æƒ…報を抑止ã—ãªã„。"
#: common.opt:1026
msgid "Generate debug information to support Identical Code Folding (ICF)"
-msgstr ""
+msgstr "Identical Code Folding (ICF) をサãƒãƒ¼ãƒˆã™ã‚‹ãŸã‚ã®ãƒ‡ãƒãƒƒã‚°æƒ…報を生æˆã™ã‚‹"
#: common.opt:1030
msgid "Enable exception handling"
msgstr "例外処ç†ã‚’有効ã«ã™ã‚‹"
#: common.opt:1034
-#, fuzzy
msgid "Perform a number of minor, expensive optimizations"
-msgstr "目立ãŸãªã„ã€ã‚³ã‚¹ãƒˆã®ã‹ã‹ã‚‹æœ€é©åŒ–ã‚’è¡Œãªã†"
+msgstr "多ãã®ã€ç›®ç«‹ãŸãªã„ãŒã‚³ã‚¹ãƒˆãŒé«˜ã„最é©åŒ–ã‚’è¡Œã†"
#: common.opt:1038
msgid "-fexcess-precision=[fast|standard]\tSpecify handling of excess floating-point precision"
-msgstr ""
+msgstr "-fexcess-precision=[fast|standard]\t余分ãªæµ®å‹•å°æ•°ç‚¹ç²¾åº¦ã®å–り扱ã„を指定ã™ã‚‹"
#: common.opt:1041
#, c-format
msgid "unknown excess precision style %qs"
-msgstr ""
+msgstr "ä¸æ˜Žãªä½™åˆ†ãªç²¾åº¦ã‚¹ã‚¿ã‚¤ãƒ« %qs ã§ã™"
#: common.opt:1054
msgid "Assume no NaNs or infinities are generated"
@@ -10223,52 +10203,45 @@ msgid "-ffp-contract=[off|on|fast] Perform floating-point expression contraction
msgstr ""
#: common.opt:1077
-#, fuzzy, c-format
+#, c-format
msgid "unknown floating point contraction style %qs"
-msgstr "浮動å°æ•°ç‚¹å®šæ•°ã‚’ TOC 内ã«é…ç½®ã™ã‚‹"
+msgstr "ä¸æ˜Žãªæµ®å‹•å°æ•°çŸ­ç¸®å½¢ %qs ã§ã™"
#: common.opt:1094
msgid "Allow function addresses to be held in registers"
msgstr "関数アドレスをレジスタã«æŒãŸã›ã‚‹äº‹ã‚’許å¯ã™ã‚‹"
#: common.opt:1098
-#, fuzzy
msgid "Place each function into its own section"
-msgstr "å„々ã®é–¢æ•°ã‚’ãれ自身ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã«é…ç½®ã™ã‚‹"
+msgstr "ãã‚Œãžã‚Œã®é–¢æ•°ã‚’ãれ自身ã®ã‚»ã‚¯ã‚·ãƒ§ãƒ³ã«é…ç½®ã™ã‚‹"
#: common.opt:1102
-#, fuzzy
msgid "Perform global common subexpression elimination"
-msgstr "グローãƒãƒ«å…±é€šéƒ¨åˆ†å¼ã‚’除去ã™ã‚‹"
+msgstr "大域共通部分å¼ã®é™¤åŽ»ã‚’è¡Œã†"
#: common.opt:1106
-#, fuzzy
msgid "Perform enhanced load motion during global common subexpression elimination"
-msgstr "グローãƒãƒ«å…±é€šéƒ¨åˆ†å¼ã‚’除去ã™ã‚‹"
+msgstr ""
#: common.opt:1110
-#, fuzzy
msgid "Perform store motion after global common subexpression elimination"
-msgstr "グローãƒãƒ«å…±é€šéƒ¨åˆ†å¼ã‚’除去ã™ã‚‹"
+msgstr ""
#: common.opt:1114
msgid "Perform redundant load after store elimination in global common subexpression"
msgstr ""
#: common.opt:1119
-#, fuzzy
msgid "Perform global common subexpression elimination after register allocation"
-msgstr "グローãƒãƒ«å…±é€šéƒ¨åˆ†å¼ã‚’除去ã™ã‚‹"
+msgstr "レジスタé…置後ã«å¤§åŸŸå…±é€šéƒ¨åˆ†å¼ã®é™¤åŽ»ã‚’è¡Œã†"
#: common.opt:1125
-#, fuzzy
msgid "Enable in and out of Graphite representation"
-msgstr "自動テンプレート実体化を有効ã«ã™ã‚‹"
+msgstr ""
#: common.opt:1129
-#, fuzzy
msgid "Enable Graphite Identity transformation"
-msgstr "呼ã³å‡ºã—グラフ情報をé€å‡ºã™ã‚‹"
+msgstr ""
#: common.opt:1133
msgid "Mark all loops as parallel"
@@ -10307,9 +10280,8 @@ msgid "Perform conversion of conditional jumps to branchless equivalents"
msgstr ""
#: common.opt:1173
-#, fuzzy
msgid "Perform conversion of conditional jumps to conditional execution"
-msgstr "æ¡ä»¶çš„ãªå®Ÿè¡Œã¸ã®å¤‰æ›´ã®ãŸã‚ã®é–¾å€¤ã‚’変更ã™ã‚‹"
+msgstr ""
#: common.opt:1177
msgid "Convert conditional jumps in innermost loops to branchless equivalents"
@@ -10377,13 +10349,12 @@ msgid "Perform interprocedural points-to analysis"
msgstr ""
#: common.opt:1253
-#, fuzzy
msgid "Discover pure and const functions"
-msgstr "使ã‚ã‚Œãªã„仮想関数を切りæ¨ã¦ã‚‹"
+msgstr "純粋ãŠã‚ˆã³å®šæ•°é–¢æ•°ã‚’見ã¤ã‘ã‚‹"
#: common.opt:1257
msgid "Discover readonly and non addressable static variables"
-msgstr ""
+msgstr "読ã¿å–り専用ãŠã‚ˆã³ã‚¢ãƒ‰ãƒ¬ã‚¹ä»˜ã‘ã§ããªã„é™çš„変数を見ã¤ã‘ã‚‹"
#: common.opt:1261
msgid "Perform matrix layout flattening and transposing based"
@@ -10416,9 +10387,8 @@ msgid "Use IRA based register pressure calculation"
msgstr ""
#: common.opt:1305
-#, fuzzy
msgid "Share slots for saving different hard registers."
-msgstr "引数レジスタã«ãƒ­ãƒ¼ã‚«ãƒ«ã®ã‚‚ã®ã‚’æ ¼ç´ã™ã‚‹"
+msgstr ""
#: common.opt:1309
msgid "Share stack slots for spilled pseudo-registers."
@@ -10622,19 +10592,19 @@ msgstr "ループ内ã®é…列ã§ã€å¯èƒ½ã§ã‚ã‚Œã°ãƒ—リフェッãƒå‘½ä»¤ã‚’
#: common.opt:1521
msgid "Enable basic program profiling code"
-msgstr ""
+msgstr "基本プログラムプロファイリングコードを有効ã«ã™ã‚‹"
#: common.opt:1525
msgid "Insert arc-based program profiling code"
-msgstr ""
+msgstr "円弧ベースプログラムプロファイリングコードを挿入ã™ã‚‹"
#: common.opt:1529
msgid "Set the top-level directory for storing the profile data."
-msgstr ""
+msgstr "プロファイルデータä¿å­˜ç”¨ã®æœ€ä¸Šä½ãƒ‡ã‚£ãƒ¬ã‚¯ãƒªãƒ¼ã‚’設定ã™ã‚‹"
#: common.opt:1534
msgid "Enable correction of flow inconsistent profile data input"
-msgstr ""
+msgstr "フロー一貫性ãŒç„¡ã„データ入力ã®è¨‚正を有効ã«ã™ã‚‹"
#: common.opt:1538
msgid "Enable common options for generating profile info for profile feedback directed optimizations"
@@ -10654,7 +10624,7 @@ msgstr ""
#: common.opt:1554
msgid "Insert code to profile values of expressions"
-msgstr ""
+msgstr "å¼ã®å€¤ã‚’プロファイルã™ã‚‹ãŸã‚ã®ã‚³ãƒ¼ãƒ‰ã‚’挿入ã™ã‚‹"
#: common.opt:1561
msgid "-frandom-seed=<string>\tMake compile reproducible using <string>"
@@ -11837,7 +11807,7 @@ msgstr "ラベル %q+D ãŒä½¿ç”¨ã•ã‚Œã¾ã—ãŸãŒã€å®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“
#: c-decl.c:1150
#, gcc-internal-format
msgid "nested function %q+D declared but never defined"
-msgstr ""
+msgstr "入れå­ã«ãªã£ãŸé–¢æ•° %q+D ãŒå®£è¨€ã•ã‚Œã¾ã—ãŸãŒå®šç¾©ã•ã‚Œã¦ã„ã¾ã›ã‚“"
#: c-decl.c:1162
#, gcc-internal-format
@@ -11894,7 +11864,7 @@ msgstr ""
#: c-decl.c:1613
#, gcc-internal-format
msgid "prototype for %q+D follows non-prototype definition"
-msgstr ""
+msgstr "éžãƒ—ロトタイプ定義ã«ç¶šã„㦠%q+D 用ã®ãƒ—ロトタイプãŒã‚ã‚Šã¾ã™"
#: c-decl.c:1628
#, gcc-internal-format
@@ -11970,9 +11940,9 @@ msgid "redefinition of typedef %q+D with different type"
msgstr "%q+D ãŒç•°ãªã‚‹åž‹ã§å†å®šç¾©ã•ã‚Œã¾ã—ãŸ"
#: c-decl.c:1818
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "redefinition of typedef %q+D with variably modified type"
-msgstr "%q+D ãŒç•°ãªã‚‹åž‹ã§å†å®šç¾©ã•ã‚Œã¾ã—ãŸ"
+msgstr ""
#: c-decl.c:1825
#, gcc-internal-format
@@ -12017,17 +11987,17 @@ msgstr "%q+D ã®éžã‚¹ãƒ¬ãƒƒãƒ‰å±€æ‰€å®£è¨€ã®å¾Œã«ã‚¹ãƒ¬ãƒƒãƒ‰å±€æ‰€å®£è¨€ãŒã
#: c-decl.c:2001
#, gcc-internal-format
msgid "extern declaration of %q+D follows declaration with no linkage"
-msgstr ""
+msgstr "リンク無ã—宣言ã®å¾Œã« %q+D ã® extern 宣言ãŒç¶šã„ã¦ã„ã¾ã™"
#: c-decl.c:2037
#, gcc-internal-format
msgid "declaration of %q+D with no linkage follows extern declaration"
-msgstr ""
+msgstr "extern 宣言ã®å¾Œã«ãƒªãƒ³ã‚¯ç„¡ã— %q+D ã®å®£è¨€ãŒç¶šã„ã¦ã„ã¾ã™"
#: c-decl.c:2043
#, gcc-internal-format
msgid "redeclaration of %q+D with no linkage"
-msgstr ""
+msgstr "リンク無㗠%q+D ã®å†å®šç¾©ã§ã™"
#: c-decl.c:2069
#, gcc-internal-format
@@ -12355,7 +12325,7 @@ msgstr "ISO C ã¯å‰æ–¹ä»®å¼•æ•°å®£è¨€ã‚’ç¦ã˜ã¾ã™"
#: c-decl.c:4614
#, gcc-internal-format
msgid "defining a type in a compound literal is invalid in C++"
-msgstr ""
+msgstr "複åˆãƒªãƒ†ãƒ©ãƒ«å†…ã§ã®åž‹å®šç¾©ã¯ C++ ã§ã¯ç„¡åŠ¹ã§ã™"
#: c-decl.c:4666 c-decl.c:4681
#, gcc-internal-format
@@ -13394,23 +13364,23 @@ msgstr "文字列リテラルãŒäºˆæœŸã•ã‚Œã¾ã™"
#: c-parser.c:1829
#, gcc-internal-format
msgid "expression in static assertion is not an integer"
-msgstr ""
+msgstr "é™çš„アサーション内ã®å¼ãŒæ•´æ•°ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: c-parser.c:1836
#, gcc-internal-format
msgid "expression in static assertion is not an integer constant expression"
-msgstr ""
+msgstr "é™çš„アサーション内ã®å¼ãŒæ•´æ•°å®šæ•°å¼ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: c-parser.c:1841
#, gcc-internal-format
msgid "expression in static assertion is not constant"
-msgstr ""
+msgstr "é™çš„アサーション内ã®å¼ãŒå®šæ•°ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#. Report the error.
#: c-parser.c:1846 cp/semantics.c:4719
#, gcc-internal-format
msgid "static assertion failed: %E"
-msgstr ""
+msgstr "é™çš„アサーションã«å¤±æ•—ã—ã¾ã—ãŸ: %E"
#: c-parser.c:2207 c-parser.c:3063 c-parser.c:3709 c-parser.c:3983
#: c-parser.c:5084 c-parser.c:5175 c-parser.c:5800 c-parser.c:6083
@@ -14126,12 +14096,12 @@ msgstr "å˜é …感嘆符(!)ã¸ã®å¼•æ•°ã®åž‹ãŒé–“é•ã£ã¦ã„ã¾ã™"
#: c-typeck.c:3578
#, gcc-internal-format
msgid "increment of enumeration value is invalid in C++"
-msgstr "列挙値ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã¯ C++ ã§ã¯ç„¡åŠ¹ã§ã™"
+msgstr "列挙値ã®å¢—分㯠C++ ã§ã¯ç„¡åŠ¹ã§ã™"
#: c-typeck.c:3581
#, gcc-internal-format
msgid "decrement of enumeration value is invalid in C++"
-msgstr "列挙値ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã¯ C++ ã§ã¯ç„¡åŠ¹ã§ã™"
+msgstr "列挙値ã®æ¸›åˆ†ã¯ C++ ã§ã¯ç„¡åŠ¹ã§ã™"
#: c-typeck.c:3594
#, gcc-internal-format
@@ -14141,22 +14111,22 @@ msgstr "ISO C ã¯è¤‡ç´ æ•°åž‹ã«é–¢ã™ã‚‹ %<++%> 㨠%<--%> をサãƒãƒ¼ãƒˆã—ã
#: c-typeck.c:3613 c-typeck.c:3645
#, gcc-internal-format
msgid "wrong type argument to increment"
-msgstr "インクリメントã™ã‚‹å¼•æ•°ã®åž‹ãŒé–“é•ã£ã¦ã„ã¾ã™"
+msgstr "増分ã™ã‚‹å¼•æ•°ã®åž‹ãŒé–“é•ã£ã¦ã„ã¾ã™"
#: c-typeck.c:3615 c-typeck.c:3648
#, gcc-internal-format
msgid "wrong type argument to decrement"
-msgstr "デクリメントã™ã‚‹å¼•æ•°ã®åž‹ãŒé–“é•ã£ã¦ã„ã¾ã™"
+msgstr "減分ã™ã‚‹å¼•æ•°ã®åž‹ãŒé–“é•ã£ã¦ã„ã¾ã™"
#: c-typeck.c:3635
#, gcc-internal-format
msgid "increment of pointer to unknown structure"
-msgstr "ä¸æ˜Žãªæ§‹é€ ä½“ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "ä¸æ˜Žãªæ§‹é€ ä½“ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã®å¢—分ã§ã™"
#: c-typeck.c:3638
#, gcc-internal-format
msgid "decrement of pointer to unknown structure"
-msgstr "ä¸æ˜Žãªæ§‹é€ ä½“ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "ä¸æ˜Žãªæ§‹é€ ä½“ã¸ã®ãƒã‚¤ãƒ³ã‚¿ã®æ¸›åˆ†ã§ã™"
#: c-typeck.c:3722
#, gcc-internal-format
@@ -14171,12 +14141,12 @@ msgstr "読ã¿å–り専用ä½ç½® %qE ã¸ã®ä»£å…¥ã§ã™"
#: c-typeck.c:3895 c-family/c-common.c:8658
#, gcc-internal-format
msgid "increment of read-only location %qE"
-msgstr "読ã¿å–り専用ä½ç½® %qE ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用ä½ç½® %qE ã®å¢—分ã§ã™"
#: c-typeck.c:3898 c-family/c-common.c:8659
#, gcc-internal-format
msgid "decrement of read-only location %qE"
-msgstr "読ã¿å–り専用ä½ç½® %qE ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用ä½ç½® %qE ã®æ¸›åˆ†ã§ã™"
#: c-typeck.c:3939
#, gcc-internal-format
@@ -19788,12 +19758,12 @@ msgstr "読ã¿å–り専用オブジェクト内ã®ãƒ¡ãƒ³ãƒ %qD ã¸ã®ä»£å…¥ã§ã
#: c-family/c-common.c:8611
#, gcc-internal-format
msgid "increment of member %qD in read-only object"
-msgstr "読ã¿å–り専用オブジェクト内ã®ãƒ¡ãƒ³ãƒ %qD ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用オブジェクト内ã®ãƒ¡ãƒ³ãƒ %qD ã®å¢—分ã§ã™"
#: c-family/c-common.c:8613
#, gcc-internal-format
msgid "decrement of member %qD in read-only object"
-msgstr "読ã¿å–り専用オブジェクト内ã®ãƒ¡ãƒ³ãƒ %qD ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用オブジェクト内ã®ãƒ¡ãƒ³ãƒ %qD ã®æ¸›åˆ†ã§ã™"
#: c-family/c-common.c:8615
#, gcc-internal-format
@@ -19808,12 +19778,12 @@ msgstr "読ã¿å–り専用メンム%qD ã¸ã®ä»£å…¥ã§ã™"
#: c-family/c-common.c:8620
#, gcc-internal-format
msgid "increment of read-only member %qD"
-msgstr "読ã¿å–り専用メンム%qD ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用メンム%qD ã®å¢—分ã§ã™"
#: c-family/c-common.c:8621
#, gcc-internal-format
msgid "decrement of read-only member %qD"
-msgstr "読ã¿å–り専用メンム%qD ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用メンム%qD ã®æ¸›åˆ†ã§ã™"
#: c-family/c-common.c:8622
#, gcc-internal-format
@@ -19828,12 +19798,12 @@ msgstr "読ã¿å–り専用変数 %qD ã¸ã®ä»£å…¥ã§ã™"
#: c-family/c-common.c:8627
#, gcc-internal-format
msgid "increment of read-only variable %qD"
-msgstr "読ã¿å–り専用変数 %qD ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用変数 %qD ã®å¢—分ã§ã™"
#: c-family/c-common.c:8628
#, gcc-internal-format
msgid "decrement of read-only variable %qD"
-msgstr "読ã¿å–り専用変数 %qD ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用変数 %qD ã®æ¸›åˆ†ã§ã™"
#: c-family/c-common.c:8629
#, gcc-internal-format
@@ -19848,12 +19818,12 @@ msgstr "読ã¿å–り専用パラメータ %qD ã¸ã®ä»£å…¥ã§ã™"
#: c-family/c-common.c:8633
#, gcc-internal-format
msgid "increment of read-only parameter %qD"
-msgstr "読ã¿å–り専用パラメータ %qD ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用パラメータ %qD ã®å¢—分ã§ã™"
#: c-family/c-common.c:8634
#, gcc-internal-format
msgid "decrement of read-only parameter %qD"
-msgstr "読ã¿å–り専用パラメータ %qD ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用パラメータ %qD ã®æ¸›åˆ†ã§ã™"
#: c-family/c-common.c:8635
#, gcc-internal-format
@@ -19868,12 +19838,12 @@ msgstr "読ã¿å–り専用åå‰ä»˜ã戻り値 %qD ã¸ã®ä»£å…¥ã§ã™"
#: c-family/c-common.c:8642
#, gcc-internal-format
msgid "increment of read-only named return value %qD"
-msgstr "読ã¿å–り専用åå‰ä»˜ã戻り値 %qD ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用åå‰ä»˜ã戻り値 %qD ã®å¢—分ã§ã™"
#: c-family/c-common.c:8644
#, gcc-internal-format
msgid "decrement of read-only named return value %qD"
-msgstr "読ã¿å–り専用åå‰ä»˜ã戻り値 %qD ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "読ã¿å–り専用åå‰ä»˜ã戻り値 %qD ã®æ¸›åˆ†ã§ã™"
#: c-family/c-common.c:8646
#, gcc-internal-format
@@ -19888,12 +19858,12 @@ msgstr "関数 %qD ã¸ã®ä»£å…¥ã§ã™"
#: c-family/c-common.c:8652
#, gcc-internal-format
msgid "increment of function %qD"
-msgstr "関数 %qD ã®ã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "関数 %qD ã®å¢—分ã§ã™"
#: c-family/c-common.c:8653
#, gcc-internal-format
msgid "decrement of function %qD"
-msgstr "関数 %qD ã®ãƒ‡ã‚¯ãƒªãƒ¡ãƒ³ãƒˆã§ã™"
+msgstr "関数 %qD ã®æ¸›åˆ†ã§ã™"
#: c-family/c-common.c:8654
#, gcc-internal-format
@@ -19913,12 +19883,12 @@ msgstr "代入ã®å·¦å´ã®è¢«æ¼”ç®—å­ã¨ã—ã¦å·¦è¾ºå€¤ãŒå¿…è¦ã§ã™"
#: c-family/c-common.c:8677
#, gcc-internal-format
msgid "lvalue required as increment operand"
-msgstr "インクリメントã®è¢«æ¼”ç®—å­ã¨ã—ã¦å·¦è¾ºå€¤ãŒå¿…è¦ã§ã™"
+msgstr "増分ã®è¢«æ¼”ç®—å­ã¨ã—ã¦å·¦è¾ºå€¤ãŒå¿…è¦ã§ã™"
#: c-family/c-common.c:8680
#, gcc-internal-format
msgid "lvalue required as decrement operand"
-msgstr "デクリメントã®è¢«æ¼”ç®—å­ã¨ã—ã¦å·¦è¾ºå€¤ãŒå¿…è¦ã§ã™"
+msgstr "減分ã®è¢«æ¼”ç®—å­ã¨ã—ã¦å·¦è¾ºå€¤ãŒå¿…è¦ã§ã™"
#: c-family/c-common.c:8683
#, gcc-internal-format
@@ -20557,12 +20527,12 @@ msgstr ""
#: c-family/c-omp.c:375 cp/semantics.c:4431
#, gcc-internal-format
msgid "missing increment expression"
-msgstr "インクリメントå¼ãŒã‚ã‚Šã¾ã›ã‚“"
+msgstr "増分å¼ãŒã‚ã‚Šã¾ã›ã‚“"
#: c-family/c-omp.c:444 cp/semantics.c:4287
#, gcc-internal-format
msgid "invalid increment expression"
-msgstr "無効ãªã‚¤ãƒ³ã‚¯ãƒªãƒ¡ãƒ³ãƒˆå¼ã§ã™"
+msgstr "無効ãªå¢—分å¼ã§ã™"
#: c-family/c-opts.c:303
#, gcc-internal-format
@@ -20572,7 +20542,7 @@ msgstr "-I- ãŒäºŒå›žæŒ‡å®šã•ã‚Œã¾ã—ãŸ"
#: c-family/c-opts.c:306
#, gcc-internal-format
msgid "obsolete option -I- used, please use -iquote instead"
-msgstr "廃止ã‚ã‚ŒãŸã‚ªãƒ—ション -I- ãŒä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚代ã‚ã‚Šã« -iquote を使用ã—ã¦ãã ã•ã„"
+msgstr "廃止ã•ã‚ŒãŸã‚ªãƒ—ション -I- ãŒä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™ã€‚代ã‚ã‚Šã« -iquote を使用ã—ã¦ãã ã•ã„"
#: c-family/c-opts.c:486
#, gcc-internal-format
@@ -29221,14 +29191,14 @@ msgid "%qE does not have class type"
msgstr ""
#: cp/parser.c:5612 cp/typeck.c:2326
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "invalid use of %qD"
-msgstr "`restrict' ã®ç”¨æ³•ãŒä¸é©åˆ‡ã§ã™"
+msgstr "無効㪠%qD ã®ä½¿ç”¨ã§ã™"
#: cp/parser.c:5875
#, gcc-internal-format
msgid "non-scalar type"
-msgstr ""
+msgstr "éžã‚¹ã‚«ãƒ©ãƒ¼åž‹"
#: cp/parser.c:5964
#, fuzzy, gcc-internal-format
@@ -29303,12 +29273,12 @@ msgstr "仮引数 `%s' ã§æŒ‡å®šã•ã‚ŒãŸè¨˜æ†¶ã‚¯ãƒ©ã‚¹"
#: cp/parser.c:8218
#, gcc-internal-format
msgid "expected labeled-statement"
-msgstr ""
+msgstr "ラベル付ãæ–‡ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:8256
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "case label %qE not within a switch statement"
-msgstr "case ラベル㌠switch æ–‡ã®ä¸­ã«ã‚ã‚Šã¾ã›ã‚“"
+msgstr "case ラベル %qE ㌠switch æ–‡ã®ä¸­ã«ã‚ã‚Šã¾ã›ã‚“"
#: cp/parser.c:8331
#, gcc-internal-format
@@ -29374,14 +29344,14 @@ msgstr ""
#: cp/parser.c:9886
#, gcc-internal-format
msgid "%<friend%> used outside of class"
-msgstr ""
+msgstr "%<friend%> ãŒã‚¯ãƒ©ã‚¹ã®å¤–å´ã§ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™"
#. Complain about `auto' as a storage specifier, if
#. we're complaining about C++0x compatibility.
#: cp/parser.c:9945
#, gcc-internal-format
msgid "%<auto%> will change meaning in C++0x; please remove it"
-msgstr ""
+msgstr "%<auto%> 㯠C++0x ã§æ„味ãŒå¤‰æ›´ã«ãªã‚Šã¾ã™ã€‚削除ã—ã¦ãã ã•ã„"
#: cp/parser.c:9981
#, gcc-internal-format
@@ -29401,7 +29371,7 @@ msgstr ""
#: cp/parser.c:10182
#, gcc-internal-format
msgid "invalid linkage-specification"
-msgstr ""
+msgstr "無効ãªãƒªãƒ³ã‚¯æŒ‡å®šã§ã™"
#: cp/parser.c:10309
#, gcc-internal-format
@@ -29436,7 +29406,7 @@ msgstr ""
#: cp/parser.c:11103
#, gcc-internal-format
msgid "expected operator"
-msgstr ""
+msgstr "演算å­ãŒäºˆæœŸã•ã‚Œã¾ã™"
#. Warn that we do not support `export'.
#: cp/parser.c:11140
@@ -29467,7 +29437,7 @@ msgstr ""
#: cp/parser.c:11671 cp/parser.c:20945
#, gcc-internal-format
msgid "expected %<<%>"
-msgstr ""
+msgstr "%<<%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:11678
#, gcc-internal-format
@@ -29488,13 +29458,13 @@ msgstr "マクロ引数リストã«ã‚ã‚Šå¾—ãªã„トークン"
#: cp/parser.c:11828 cp/parser.c:11943 cp/parser.c:12153
#, gcc-internal-format
msgid "expected template-name"
-msgstr ""
+msgstr "テンプレートåãŒäºˆæœŸã•ã‚Œã¾ã™"
#. Explain what went wrong.
#: cp/parser.c:11874
#, gcc-internal-format
msgid "non-template %qD used as template"
-msgstr ""
+msgstr "éžãƒ†ãƒ³ãƒ—レート %qD ãŒãƒ†ãƒ³ãƒ—レートã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™"
#: cp/parser.c:11876
#, gcc-internal-format
@@ -29509,7 +29479,7 @@ msgstr ""
#: cp/parser.c:12118 cp/parser.c:12136 cp/parser.c:12277
#, gcc-internal-format
msgid "expected template-argument"
-msgstr ""
+msgstr "テンプレート引数ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:12260
#, gcc-internal-format
@@ -29534,7 +29504,7 @@ msgstr ""
#: cp/parser.c:12654
#, gcc-internal-format
msgid "expected type specifier"
-msgstr ""
+msgstr "型指定ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:12871
#, gcc-internal-format
@@ -29544,7 +29514,7 @@ msgstr ""
#: cp/parser.c:12898
#, gcc-internal-format
msgid "expected type-name"
-msgstr ""
+msgstr "åž‹åãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:13085
#, gcc-internal-format
@@ -29552,9 +29522,9 @@ msgid "elaborated-type-specifier for a scoped enum must not use the %<%D%> keywo
msgstr ""
#: cp/parser.c:13269
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "declaration %qD does not declare anything"
-msgstr "宣言ãŒä½•ã‚‚宣言ã—ã¦ã„ã¾ã›ã‚“"
+msgstr "宣言 %qD ãŒä½•ã‚‚宣言ã—ã¦ã„ã¾ã›ã‚“"
#: cp/parser.c:13355
#, fuzzy, gcc-internal-format
@@ -29584,7 +29554,7 @@ msgstr ""
#: cp/parser.c:13559
#, gcc-internal-format
msgid "expected %<;%> or %<{%>"
-msgstr ""
+msgstr "%<;%> ã¾ãŸã¯ %<{%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:13606
#, gcc-internal-format
@@ -29602,9 +29572,9 @@ msgid "declaration of %qD in %qD which does not enclose %qD"
msgstr ""
#: cp/parser.c:13643
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "multiple definition of %q#T"
-msgstr "`%s' ãŒå†å®šç¾©ã•ã‚Œã¾ã—ãŸ"
+msgstr "%q#T ãŒè¤‡æ•°å®šç¾©ã•ã‚Œã¦ã„ã¾ã™"
#: cp/parser.c:13669
#, gcc-internal-format
@@ -29617,19 +29587,19 @@ msgid "opaque-enum-specifier must use a simple identifier"
msgstr ""
#: cp/parser.c:13847
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "%qD is not a namespace-name"
-msgstr "\"%s\" ã¯æ­£å¸¸ãªãƒ•ã‚¡ã‚¤ãƒ«åã§ã¯ã‚ã‚Šã¾ã›ã‚“"
+msgstr "%qD ã¯åå‰ç©ºé–“åã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: cp/parser.c:13848
#, gcc-internal-format
msgid "expected namespace-name"
-msgstr ""
+msgstr "åå‰ç©ºé–“åãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:13973
#, gcc-internal-format
msgid "%<namespace%> definition is not allowed here"
-msgstr ""
+msgstr "ã“ã“ã§ã¯ %<namespace%> 定義ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
#: cp/parser.c:14114
#, gcc-internal-format
@@ -29639,7 +29609,7 @@ msgstr ""
#: cp/parser.c:14536
#, gcc-internal-format
msgid "a function-definition is not allowed here"
-msgstr ""
+msgstr "ã“ã“ã§ã¯é–¢æ•°å®šç¾©ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
#: cp/parser.c:14548
#, fuzzy, gcc-internal-format
@@ -29709,32 +29679,32 @@ msgstr ""
#: cp/parser.c:15323
#, gcc-internal-format
msgid "invalid declarator"
-msgstr ""
+msgstr "無効ãªå®£è¨€å­ã§ã™"
#: cp/parser.c:15389
#, gcc-internal-format
msgid "expected declarator"
-msgstr ""
+msgstr "宣言å­ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:15484
#, gcc-internal-format
msgid "%qD is a namespace"
-msgstr ""
+msgstr "%qD ã¯åå‰ç©ºé–“ã§ã™"
#: cp/parser.c:15500
#, gcc-internal-format
msgid "expected ptr-operator"
-msgstr ""
+msgstr "ãƒã‚¤ãƒ³ã‚¿æ¼”ç®—å­ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:15559
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "duplicate cv-qualifier"
-msgstr "é‡è¤‡ã—㟠case ã®å€¤"
+msgstr ""
#: cp/parser.c:15681 cp/typeck2.c:427
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "invalid use of %<auto%>"
-msgstr "`restrict' ã®ç”¨æ³•ãŒä¸é©åˆ‡ã§ã™"
+msgstr "無効㪠%<auto%> ã®ä½¿ç”¨ã§ã™"
#: cp/parser.c:15700
#, fuzzy, gcc-internal-format
@@ -29744,12 +29714,12 @@ msgstr "\"%s\" ã¯ãƒžã‚¯ãƒ­ä»®å¼•æ•°ãƒªã‚¹ãƒˆã«ç¾ã‚Œã¦ã¯ãªã‚Šã¾ã›ã‚“"
#: cp/parser.c:15781
#, gcc-internal-format
msgid "expected type-specifier"
-msgstr ""
+msgstr "型指定å­ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:16025
#, gcc-internal-format
msgid "expected %<,%> or %<...%>"
-msgstr ""
+msgstr "%<,%> ã¾ãŸã¯ %<...%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:16082
#, fuzzy, gcc-internal-format
@@ -29757,9 +29727,9 @@ msgid "types may not be defined in parameter types"
msgstr "\"%s\" ã¯ãƒžã‚¯ãƒ­ä»®å¼•æ•°ãƒªã‚¹ãƒˆã«ç¾ã‚Œã¦ã¯ãªã‚Šã¾ã›ã‚“"
#: cp/parser.c:16306
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "file ends in default argument"
-msgstr "無効ãªãƒ‡ãƒ•ã‚©ãƒ«ãƒˆãƒ†ãƒ³ãƒ—レート引数"
+msgstr "デフォルト引数内ã§ãƒ•ã‚¡ã‚¤ãƒ«ãŒçµ‚了ã—ã¦ã„ã¾ã™"
#: cp/parser.c:16352
#, gcc-internal-format
@@ -29782,24 +29752,24 @@ msgid "expected class-name"
msgstr ""
#: cp/parser.c:17063
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "expected %<;%> after class definition"
-msgstr "èªè­˜ã§ããªã„ wide sub 命令ã§ã™"
+msgstr "クラス定義ã®å¾Œã«ã¯ %<;%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:17065
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "expected %<;%> after struct definition"
-msgstr "èªè­˜ã§ããªã„ wide sub 命令ã§ã™"
+msgstr "構造体定義ã®å¾Œã«ã¯ %<;%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:17067
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "expected %<;%> after union definition"
-msgstr "`%s' ã® extern 宣言ãŒãƒã‚¹ãƒˆã—ã¦ã„ã¾ã™"
+msgstr "共用体定義ã®å¾Œã«ã¯ %<;%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:17351
#, gcc-internal-format
msgid "expected %<{%> or %<:%>"
-msgstr ""
+msgstr "%<{%> ã¾ãŸã¯ %<:%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:17363
#, gcc-internal-format
@@ -29812,9 +29782,9 @@ msgid "qualified name does not name a class"
msgstr ""
#: cp/parser.c:17382
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "invalid class name in declaration of %qD"
-msgstr "`%s' ã®å®£è¨€ã«ãŠã„ã¦è¤‡æ•°ã®ä¿å­˜ã‚¯ãƒ©ã‚¹"
+msgstr "%qD ã®å®£è¨€å†…ã«ç„¡åŠ¹ãªã‚¯ãƒ©ã‚¹åã§ã™"
#: cp/parser.c:17415
#, gcc-internal-format
@@ -29829,7 +29799,7 @@ msgstr ""
#: cp/parser.c:17457
#, gcc-internal-format
msgid "function template %qD redeclared as a class template"
-msgstr ""
+msgstr "関数テンプレート %qD ãŒã‚¯ãƒ©ã‚¹ãƒ†ãƒ³ãƒ—レートã¨ã—ã¦å†å®šç¾©ã•ã‚Œã¾ã—ãŸ"
#: cp/parser.c:17488
#, gcc-internal-format
@@ -29837,9 +29807,9 @@ msgid "could not resolve typename type"
msgstr ""
#: cp/parser.c:17540
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "previous definition of %q+#T"
-msgstr "å‰æ–¹ã§ã® `%s' ã®å®£è¨€"
+msgstr "%q+#T ã®å‰ã®å®šç¾©"
#: cp/parser.c:17604 cp/parser.c:20990
#, gcc-internal-format
@@ -29852,9 +29822,9 @@ msgid "a class-key must be used when declaring a friend"
msgstr ""
#: cp/parser.c:17832
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "friend declaration does not name a class or function"
-msgstr "friend 宣言ãŒã‚¯ãƒ©ã‚¹å®šç¾©ã®ä¸­ã«ã‚ã‚Šã¾ã›ã‚“"
+msgstr ""
#: cp/parser.c:18016
#, gcc-internal-format
@@ -29864,7 +29834,7 @@ msgstr ""
#: cp/parser.c:18064
#, gcc-internal-format
msgid "expected %<;%> at end of member declaration"
-msgstr ""
+msgstr "メンãƒå®£è¨€ã®æœ€å¾Œã«ã¯ %<;%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:18130
#, gcc-internal-format
@@ -29983,137 +29953,137 @@ msgstr "テンプレート型統一中 `%s' ãŒä½¿ç”¨ã•ã‚Œã¾ã—ãŸ"
#: cp/parser.c:20750
#, gcc-internal-format
msgid "%<__thread%> before %qD"
-msgstr ""
+msgstr "%<__thread%> ㌠%qD ã®å‰ã«ã‚ã‚Šã¾ã™"
#: cp/parser.c:20854
#, gcc-internal-format
msgid "expected %<new%>"
-msgstr ""
+msgstr "%<new%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20857
#, gcc-internal-format
msgid "expected %<delete%>"
-msgstr ""
+msgstr "%<delete%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20860
#, gcc-internal-format
msgid "expected %<return%>"
-msgstr ""
+msgstr "%<return%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20866
#, gcc-internal-format
msgid "expected %<extern%>"
-msgstr ""
+msgstr "%<extern%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20869
#, gcc-internal-format
msgid "expected %<static_assert%>"
-msgstr ""
+msgstr "%<static_assert%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20872
#, gcc-internal-format
msgid "expected %<decltype%>"
-msgstr ""
+msgstr "%<decltype%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20875
#, gcc-internal-format
msgid "expected %<operator%>"
-msgstr ""
+msgstr "%<operator%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20878
#, gcc-internal-format
msgid "expected %<class%>"
-msgstr ""
+msgstr "%<class%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20881
#, gcc-internal-format
msgid "expected %<template%>"
-msgstr ""
+msgstr "%<template%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20884
#, gcc-internal-format
msgid "expected %<namespace%>"
-msgstr ""
+msgstr "%<namespace%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20887
#, gcc-internal-format
msgid "expected %<using%>"
-msgstr ""
+msgstr "%<using%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20890
#, gcc-internal-format
msgid "expected %<asm%>"
-msgstr ""
+msgstr "%<asm%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20893
#, gcc-internal-format
msgid "expected %<try%>"
-msgstr ""
+msgstr "%<try%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20896
#, gcc-internal-format
msgid "expected %<catch%>"
-msgstr ""
+msgstr "%<catch%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20899
#, gcc-internal-format
msgid "expected %<throw%>"
-msgstr ""
+msgstr "%<throw%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20902
#, gcc-internal-format
msgid "expected %<__label__%>"
-msgstr ""
+msgstr "%<__label__%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20905
#, gcc-internal-format
msgid "expected %<@try%>"
-msgstr ""
+msgstr "%<@try%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20908
#, gcc-internal-format
msgid "expected %<@synchronized%>"
-msgstr ""
+msgstr "%<@synchronized%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20911
#, gcc-internal-format
msgid "expected %<@throw%>"
-msgstr ""
+msgstr "%<@throw%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20936
#, gcc-internal-format
msgid "expected %<[%>"
-msgstr ""
+msgstr "%<[%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20942
#, gcc-internal-format
msgid "expected %<::%>"
-msgstr ""
+msgstr "%<::%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20954
#, gcc-internal-format
msgid "expected %<...%>"
-msgstr ""
+msgstr "%<...%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20957
#, gcc-internal-format
msgid "expected %<*%>"
-msgstr ""
+msgstr "%<*%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20960
#, gcc-internal-format
msgid "expected %<~%>"
-msgstr ""
+msgstr "%<~%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20966
#, gcc-internal-format
msgid "expected %<:%> or %<::%>"
-msgstr ""
+msgstr "%<:%> ã¾ãŸã¯ %<::%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:20994
#, gcc-internal-format
msgid "expected %<class%>, %<typename%>, or %<template%>"
-msgstr ""
+msgstr "%<class%>ã€%<typename%>ã€ã¾ãŸã¯ %<template%> ãŒäºˆæœŸã•ã‚Œã¾ã™"
#: cp/parser.c:21225
#, gcc-internal-format
@@ -30293,14 +30263,14 @@ msgid "specialization of %qD after instantiation"
msgstr ""
#: cp/pt.c:1728
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "%s %+#D"
-msgstr "%s: %s"
+msgstr "%s %+#D"
#: cp/pt.c:1811
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "%qD is not a function template"
-msgstr "キャストã«ã‚ˆã‚‹é–¢æ•°ã®åž‹ãŒé©åˆã—ã¾ã›ã‚“"
+msgstr "%qD ã¯é–¢æ•°ãƒ†ãƒ³ãƒ—レートã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: cp/pt.c:2020
#, gcc-internal-format
@@ -30335,16 +30305,14 @@ msgid "definition provided for explicit instantiation"
msgstr ""
#: cp/pt.c:2295
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "too many template parameter lists in declaration of %qD"
-msgstr "%s: 警告: `%s' ã®å®£è¨€ã§ã®ä»®å¼•æ•°ãƒªã‚¹ãƒˆãŒå¤šã™ãŽã¾ã™\n"
+msgstr "%qD ã®å®£è¨€å†…ã§ãƒ†ãƒ³ãƒ—レート仮引数リストãŒå¤šã™ãŽã¾ã™"
#: cp/pt.c:2298
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "too few template parameter lists in declaration of %qD"
-msgstr ""
-"\n"
-"%s: 警告: `%s' ã®å®£è¨€ã§ã®ä»®å¼•æ•°ãƒªã‚¹ãƒˆãŒå°‘ãªã™ãŽã¾ã™\n"
+msgstr "%qD ã®å®£è¨€å†…ã§ãƒ†ãƒ³ãƒ—レート仮引数リストãŒå°‘ãªã™ãŽã¾ã™"
#: cp/pt.c:2300
#, gcc-internal-format
@@ -30362,14 +30330,14 @@ msgid "default argument specified in explicit specialization"
msgstr ""
#: cp/pt.c:2381
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "%qD is not a template function"
-msgstr "`%s' ã¯é€šå¸¸ã€éž static ãªé–¢æ•°ã§ã™"
+msgstr "%qD ã¯ãƒ†ãƒ³ãƒ—レート関数ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: cp/pt.c:2389
#, gcc-internal-format
msgid "%qD is not declared in %qD"
-msgstr ""
+msgstr "%qD 㯠%qD 内ã§ã¯å®£è¨€ã•ã‚Œã¦ã„ã¾ã›ã‚“"
#. From [temp.expl.spec]:
#.
@@ -30385,9 +30353,9 @@ msgid "specialization of implicitly-declared special member function"
msgstr ""
#: cp/pt.c:2495
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "no member function %qD declared in %qT"
-msgstr "ãƒã‚¹ãƒˆã—ãŸé–¢æ•° `%s' 㯠`extern' ã«å®£è¨€ã•ã‚Œã¾ã—ãŸ"
+msgstr "メンãƒé–¢æ•° %qD 㯠%qT 内ã§ã¯å®£è¨€ã•ã‚Œã¦ã„ã¾ã›ã‚“"
#: cp/pt.c:3114
#, gcc-internal-format
@@ -30412,17 +30380,17 @@ msgstr ""
#: cp/pt.c:3233 cp/pt.c:4253
#, gcc-internal-format
msgid " %qD"
-msgstr ""
+msgstr " %qD"
#: cp/pt.c:3235
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid " <anonymous>"
-msgstr "<ç„¡å %s>"
+msgstr " <ç„¡å>"
#: cp/pt.c:3352
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "declaration of %q+#D"
-msgstr "`%s' ãŒå†å®£è¨€ã•ã‚Œã¾ã—ãŸ"
+msgstr "%q+#D ã®å®£è¨€ã§ã™"
#: cp/pt.c:3353
#, gcc-internal-format
@@ -30467,19 +30435,19 @@ msgid "partial specialization of %qT after instantiation of %qT"
msgstr ""
#: cp/pt.c:4503
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "no default argument for %qD"
-msgstr "フォーマットã¸ã®å¼•æ•°ãŒå°‘ãªã™ãŽã¾ã™"
+msgstr "%qD 用ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå¼•æ•°ãŒã‚ã‚Šã¾ã›ã‚“"
#: cp/pt.c:4524
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "parameter pack %qE must be at the end of the template parameter list"
-msgstr "仮引数リストã‹ã‚‰ã®ä»®å¼•æ•°åを欠ã„ã¦ã„ã¾ã™"
+msgstr ""
#: cp/pt.c:4527
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "parameter pack %qT must be at the end of the template parameter list"
-msgstr "仮引数リストã‹ã‚‰ã®ä»®å¼•æ•°åを欠ã„ã¦ã„ã¾ã™"
+msgstr ""
#: cp/pt.c:4564
#, gcc-internal-format
@@ -30509,7 +30477,7 @@ msgstr "クロスコンパイル時ã®å®Ÿæ•°å€¤ãƒ†ãƒ³ãƒ—レート仮引数"
#: cp/pt.c:4720
#, gcc-internal-format
msgid "template class without a name"
-msgstr ""
+msgstr "åå‰ç„¡ã—テンプレートクラスã§ã™"
#. [temp.mem]
#.
@@ -30517,7 +30485,7 @@ msgstr ""
#: cp/pt.c:4730
#, gcc-internal-format
msgid "destructor %qD declared as member template"
-msgstr ""
+msgstr "デストラクタ %qD ãŒãƒ¡ãƒ³ãƒãƒ†ãƒ³ãƒ—レートã¨ã—ã¦å®£è¨€ã•ã‚Œã¦ã„ã¾ã™"
#. [basic.stc.dynamic.allocation]
#.
@@ -30525,14 +30493,14 @@ msgstr ""
#. template. ... Template allocation functions shall
#. have two or more parameters.
#: cp/pt.c:4745
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "invalid template declaration of %qD"
-msgstr "`%s' ã® extern 宣言ãŒãƒã‚¹ãƒˆã—ã¦ã„ã¾ã™"
+msgstr "%qD ã®ç„¡åŠ¹ãªãƒ†ãƒ³ãƒ—レート宣言ã§ã™"
#: cp/pt.c:4862
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "template definition of non-template %q#D"
-msgstr "インスタンスメソッド `%s' ã®å®šç¾©ãŒé‡è¤‡ã—ã¦ã„ã¾ã™ã€‚"
+msgstr "éžãƒ†ãƒ³ãƒ—レート %q#D ã®ãƒ†ãƒ³ãƒ—レート定義ã§ã™"
#: cp/pt.c:4905
#, gcc-internal-format
@@ -30565,14 +30533,14 @@ msgid "use template<> for an explicit specialization"
msgstr ""
#: cp/pt.c:5043
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "%qT is not a template type"
-msgstr "`%s' ã¯ä¸å®Œå…¨åž‹ã§ã™"
+msgstr "%qT ã¯ãƒ†ãƒ³ãƒ—レート型ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: cp/pt.c:5056
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "template specifiers not specified in declaration of %qD"
-msgstr "friend 関数宣言内ã®è¨˜æ†¶ã‚¯ãƒ©ã‚¹æŒ‡å®šå­ã¯ç„¡åŠ¹ã§ã™"
+msgstr ""
#: cp/pt.c:5067
#, gcc-internal-format, gfc-internal-format
@@ -30589,14 +30557,14 @@ msgstr[0] "`%s' ã®å®£è¨€ã¯ä»®å¼•æ•°ã‚’覆ã„éš ã—ã¾ã™"
msgstr[1] "`%s' ã®å®£è¨€ã¯ä»®å¼•æ•°ã‚’覆ã„éš ã—ã¾ã™"
#: cp/pt.c:5108
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "template parameter %q+#D"
-msgstr "マクロ仮引数 \"%s\" ãŒé‡è¤‡ã—ã¦ã„ã¾ã™"
+msgstr "テンプレート仮引数 %q+#D ã§ã™"
#: cp/pt.c:5109
#, gcc-internal-format
msgid "redeclared here as %q#D"
-msgstr ""
+msgstr "ã“ã“㧠%q#D ã¨ã—ã¦å†å®£è¨€ã•ã‚Œã¦ã„ã¾ã™"
#. We have in [temp.param]:
#.
@@ -30605,12 +30573,12 @@ msgstr ""
#: cp/pt.c:5119
#, gcc-internal-format
msgid "redefinition of default argument for %q#D"
-msgstr ""
+msgstr "%q#D 用ã®ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆå¼•æ•°ã®å†å®šç¾©ã§ã™"
#: cp/pt.c:5121
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "original definition appeared here"
-msgstr "関数ã®å®šç¾©ãŒ `typedef' ã¨å®£è¨€ã•ã‚Œã¾ã—ãŸ"
+msgstr "å…ƒã®å®šç¾©ã¯ã“ã“ã«å‡ºç¾ã—ã¦ã„ã¾ã™"
#: cp/pt.c:5209
#, gcc-internal-format
@@ -30618,9 +30586,9 @@ msgid "%qE is not a valid template argument for type %qT because function %qD ha
msgstr ""
#: cp/pt.c:5231 cp/pt.c:5571
-#, fuzzy, gcc-internal-format
+#, gcc-internal-format
msgid "%qE is not a valid template argument for type %qT"
-msgstr "`%s' ã®å¼•æ•°ã¨ã—ã¦ç„¡åŠ¹ãªåž‹"
+msgstr ""
#: cp/pt.c:5233
#, gcc-internal-format
@@ -31558,17 +31526,17 @@ msgstr "%qE ã¯åˆæœŸåŒ–ã•ã‚Œã¦ã„ã¾ã›ã‚“"
#: cp/semantics.c:6843
#, gcc-internal-format
msgid "%q#D is not const"
-msgstr ""
+msgstr "%q#D 㯠const ã§ã¯ã‚ã‚Šã¾ã›ã‚“"
#: cp/semantics.c:6846
#, gcc-internal-format
msgid "%q#D is volatile"
-msgstr ""
+msgstr "%q#D 㯠volatile ã§ã™"
#: cp/semantics.c:6849
#, gcc-internal-format
msgid "%qD was not initialized with a constant expression"
-msgstr ""
+msgstr "%qD ã¯å®šæ•°å¼ã§åˆæœŸåŒ–ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
#: cp/semantics.c:6858
#, gcc-internal-format
diff --git a/gcc/profile.c b/gcc/profile.c
index 893e2cd17c7..41108394e98 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -437,6 +437,39 @@ read_profile_edge_counts (gcov_type *exec_counts)
return num_edges;
}
+#define OVERLAP_BASE 10000
+
+/* Compare the static estimated profile to the actual profile, and
+ return the "degree of overlap" measure between them.
+
+ Degree of overlap is a number between 0 and OVERLAP_BASE. It is
+ the sum of each basic block's minimum relative weights between
+ two profiles. And overlap of OVERLAP_BASE means two profiles are
+ identical. */
+
+static int
+compute_frequency_overlap (void)
+{
+ gcov_type count_total = 0, freq_total = 0;
+ int overlap = 0;
+ basic_block bb;
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ {
+ count_total += bb->count;
+ freq_total += bb->frequency;
+ }
+
+ if (count_total == 0 || freq_total == 0)
+ return 0;
+
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
+ overlap += MIN (bb->count * OVERLAP_BASE / count_total,
+ bb->frequency * OVERLAP_BASE / freq_total);
+
+ return overlap;
+}
+
/* Compute the branch probabilities for the various branches.
Annotate them accordingly.
@@ -607,7 +640,13 @@ compute_branch_probabilities (unsigned cfg_checksum, unsigned lineno_checksum)
}
}
if (dump_file)
- dump_flow_info (dump_file, dump_flags);
+ {
+ int overlap = compute_frequency_overlap ();
+ dump_flow_info (dump_file, dump_flags);
+ fprintf (dump_file, "Static profile overlap: %d.%d%%\n",
+ overlap / (OVERLAP_BASE / 100),
+ overlap % (OVERLAP_BASE / 100));
+ }
total_num_passes += passes;
if (dump_file)
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 8c8a99a225b..d103afee018 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -92,6 +92,7 @@ REG_NOTE (LABEL_OPERAND)
respectively. */
REG_NOTE (DEP_OUTPUT)
REG_NOTE (DEP_ANTI)
+REG_NOTE (DEP_CONTROL)
/* REG_BR_PROB is attached to JUMP_INSNs and CALL_INSNs. It has an
integer value. For jumps, it is the probability that this is a
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index aca005d7afd..b0f03434b36 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -824,6 +824,14 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
if (hard_regno_nregs[regno][mode]
> hard_regno_nregs[regno][vd->e[regno].mode])
goto no_move_special_case;
+
+ /* And likewise, if we are narrowing on big endian the transformation
+ is also invalid. */
+ if (hard_regno_nregs[regno][mode]
+ < hard_regno_nregs[regno][vd->e[regno].mode]
+ && (GET_MODE_SIZE (vd->e[regno].mode) > UNITS_PER_WORD
+ ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+ goto no_move_special_case;
}
/* If the destination is also a register, try to find a source
@@ -840,6 +848,12 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
changed = true;
goto did_replacement;
}
+ /* We need to re-extract as validate_change clobbers
+ recog_data. */
+ extract_insn (insn);
+ if (! constrain_operands (1))
+ fatal_insn_not_found (insn);
+ preprocess_constraints ();
}
/* Otherwise, try all valid registers and see if its valid. */
@@ -862,6 +876,12 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
changed = true;
goto did_replacement;
}
+ /* We need to re-extract as validate_change clobbers
+ recog_data. */
+ extract_insn (insn);
+ if (! constrain_operands (1))
+ fatal_insn_not_found (insn);
+ preprocess_constraints ();
}
}
}
diff --git a/gcc/regrename.c b/gcc/regrename.c
index bfff1033018..1823558f451 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -39,6 +39,8 @@
#include "tree-pass.h"
#include "df.h"
#include "target.h"
+#include "emit-rtl.h"
+#include "regrename.h"
/* This file implements the RTL register renaming pass of the compiler. It is
a semi-local pass whose goal is to maximize the usage of the register file
@@ -73,47 +75,6 @@
#error "Use a different bitmap implementation for untracked_operands."
#endif
-/* We keep linked lists of DU_HEAD structures, each of which describes
- a chain of occurrences of a reg. */
-struct du_head
-{
- /* The next chain. */
- struct du_head *next_chain;
- /* The first and last elements of this chain. */
- struct du_chain *first, *last;
- /* Describe the register being tracked, register number and count. */
- unsigned regno;
- int nregs;
-
- /* A unique id to be used as an index into the conflicts bitmaps. */
- unsigned id;
- /* A bitmap to record conflicts with other chains. */
- bitmap_head conflicts;
- /* Conflicts with untracked hard registers. */
- HARD_REG_SET hard_conflicts;
-
- /* Nonzero if the chain crosses a call. */
- unsigned int need_caller_save_reg:1;
- /* Nonzero if the register is used in a way that prevents renaming,
- such as the SET_DEST of a CALL_INSN or an asm operand that used
- to be a hard register. */
- unsigned int cannot_rename:1;
-};
-
-/* This struct describes a single occurrence of a register. */
-struct du_chain
-{
- /* Links to the next occurrence of the register. */
- struct du_chain *next_use;
-
- /* The insn where the register appears. */
- rtx insn;
- /* The location inside the insn. */
- rtx *loc;
- /* The register class required by the insn at this location. */
- ENUM_BITFIELD(reg_class) cl : 16;
-};
-
enum scan_actions
{
terminate_write,
@@ -144,15 +105,14 @@ static int this_tick = 0;
static struct obstack rename_obstack;
-static void do_replace (struct du_head *, int);
+/* If nonnull, the code calling into the register renamer requested
+ information about insn operands, and we store it here. */
+VEC(insn_rr_info, heap) *insn_rr;
+
static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
enum op_type);
static bool build_def_use (basic_block);
-typedef struct du_head *du_head_p;
-DEF_VEC_P (du_head_p);
-DEF_VEC_ALLOC_P (du_head_p, heap);
-
/* The id to be given to the next opened chain. */
static unsigned current_id;
@@ -173,10 +133,15 @@ static HARD_REG_SET live_in_chains;
between this and live_in_chains is empty. */
static HARD_REG_SET live_hard_regs;
+/* Set while scanning RTL if INSN_RR is nonnull, i.e. if the current analysis
+ is for a caller that requires operand data. Used in
+ record_operand_use. */
+static operand_rr_info *cur_operand;
+
/* Return the chain corresponding to id number ID. Take into account that
chains may have been merged. */
-static du_head_p
-chain_from_id (unsigned int id)
+du_head_p
+regrename_chain_from_id (unsigned int id)
{
du_head_p first_chain = VEC_index (du_head_p, id_to_chain, id);
du_head_p chain = first_chain;
@@ -237,6 +202,19 @@ mark_conflict (struct du_head *chains, unsigned id)
}
}
+/* Examine cur_operand, and if it is nonnull, record information about the
+ use THIS_DU which is part of the chain HEAD. */
+
+static void
+record_operand_use (struct du_head *head, struct du_chain *this_du)
+{
+ if (cur_operand == NULL)
+ return;
+ gcc_assert (cur_operand->n_chains < MAX_REGS_PER_ADDRESS);
+ cur_operand->heads[cur_operand->n_chains] = head;
+ cur_operand->chains[cur_operand->n_chains++] = this_du;
+}
+
/* Create a new chain for THIS_NREGS registers starting at THIS_REGNO,
and record its occurrence in *LOC, which is being written to in INSN.
This access requires a register of class CL. */
@@ -299,6 +277,7 @@ create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
this_du->loc = loc;
this_du->insn = insn;
this_du->cl = cl;
+ record_operand_use (head, this_du);
return head;
}
@@ -313,7 +292,7 @@ merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head)
IOR_HARD_REG_SET (*pset, head->hard_conflicts);
EXECUTE_IF_SET_IN_BITMAP (&head->conflicts, 0, i, bi)
{
- du_head_p other = chain_from_id (i);
+ du_head_p other = regrename_chain_from_id (i);
unsigned j = other->nregs;
gcc_assert (other != head);
while (j-- > 0)
@@ -368,6 +347,69 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
return true;
}
+/* For the chain THIS_HEAD, compute and return the best register to
+ rename to. SUPER_CLASS is the superunion of register classes in
+ the chain. UNAVAILABLE is a set of registers that cannot be used.
+ OLD_REG is the register currently used for the chain. */
+
+int
+find_best_rename_reg (du_head_p this_head, enum reg_class super_class,
+ HARD_REG_SET *unavailable, int old_reg)
+{
+ bool has_preferred_class;
+ enum reg_class preferred_class;
+ int pass;
+ int best_new_reg = old_reg;
+
+ /* Further narrow the set of registers we can use for renaming.
+ If the chain needs a call-saved register, mark the call-used
+ registers as unavailable. */
+ if (this_head->need_caller_save_reg)
+ IOR_HARD_REG_SET (*unavailable, call_used_reg_set);
+
+ /* Mark registers that overlap this chain's lifetime as unavailable. */
+ merge_overlapping_regs (unavailable, this_head);
+
+ /* Compute preferred rename class of super union of all the classes
+ in the chain. */
+ preferred_class
+ = (enum reg_class) targetm.preferred_rename_class (super_class);
+
+ /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
+ over registers that belong to PREFERRED_CLASS and try to find the
+ best register within the class. If that failed, we iterate in
+ the second pass over registers that don't belong to the class.
+ If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
+ ascending order without any preference. */
+ has_preferred_class = (preferred_class != NO_REGS);
+ for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
+ {
+ int new_reg;
+ for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
+ {
+ if (has_preferred_class
+ && (pass == 0)
+ != TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ new_reg))
+ continue;
+
+ /* In the first pass, we force the renaming of registers that
+ don't belong to PREFERRED_CLASS to registers that do, even
+ though the latters were used not very long ago. */
+ if (check_new_reg_p (old_reg, new_reg, this_head,
+ *unavailable)
+ && ((pass == 0
+ && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+ best_new_reg))
+ || tick[best_new_reg] > tick[new_reg]))
+ best_new_reg = new_reg;
+ }
+ if (pass == 0 && best_new_reg != old_reg)
+ break;
+ }
+ return best_new_reg;
+}
+
/* Perform register renaming on the current function. */
static void
rename_chains (void)
@@ -390,22 +432,16 @@ rename_chains (void)
FOR_EACH_VEC_ELT (du_head_p, id_to_chain, i, this_head)
{
- int new_reg, best_new_reg, best_nregs;
+ int best_new_reg;
int n_uses;
struct du_chain *tmp;
HARD_REG_SET this_unavailable;
int reg = this_head->regno;
- int pass;
enum reg_class super_class = NO_REGS;
- enum reg_class preferred_class;
- bool has_preferred_class;
if (this_head->cannot_rename)
continue;
- best_new_reg = reg;
- best_nregs = this_head->nregs;
-
if (fixed_regs[reg] || global_regs[reg]
#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
|| (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM)
@@ -437,56 +473,8 @@ rename_chains (void)
if (n_uses < 2)
continue;
- /* Further narrow the set of registers we can use for renaming.
- If the chain needs a call-saved register, mark the call-used
- registers as unavailable. */
- if (this_head->need_caller_save_reg)
- IOR_HARD_REG_SET (this_unavailable, call_used_reg_set);
-
- /* And mark registers that overlap its lifetime as unavailable. */
- merge_overlapping_regs (&this_unavailable, this_head);
-
- /* Compute preferred rename class of super union of all the classes
- in the chain. */
- preferred_class
- = (enum reg_class) targetm.preferred_rename_class (super_class);
-
- /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
- over registers that belong to PREFERRED_CLASS and try to find the
- best register within the class. If that failed, we iterate in
- the second pass over registers that don't belong to the class.
- If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
- ascending order without any preference. */
- has_preferred_class = (preferred_class != NO_REGS);
- for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
- {
- for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
- {
- if (has_preferred_class
- && ((pass == 0) != TEST_HARD_REG_BIT
- (reg_class_contents[preferred_class], new_reg)))
- continue;
-
- /* In the first pass, we force the renaming of registers that
- don't belong to PREFERRED_CLASS to registers that do, even
- though the latters were used not very long ago. */
- if (check_new_reg_p (reg, new_reg, this_head,
- this_unavailable)
- && ((pass == 0
- && (!TEST_HARD_REG_BIT
- (reg_class_contents[preferred_class],
- best_new_reg)))
- || tick[best_new_reg] > tick[new_reg]))
- {
- enum machine_mode mode
- = GET_MODE (*this_head->first->loc);
- best_new_reg = new_reg;
- best_nregs = hard_regno_nregs[new_reg][mode];
- }
- }
- if (pass == 0 && best_new_reg != reg)
- break;
- }
+ best_new_reg = find_best_rename_reg (this_head, super_class,
+ &this_unavailable, reg);
if (dump_file)
{
@@ -507,9 +495,7 @@ rename_chains (void)
if (dump_file)
fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
- do_replace (this_head, best_new_reg);
- this_head->regno = best_new_reg;
- this_head->nregs = best_nregs;
+ regrename_do_replace (this_head, best_new_reg);
tick[best_new_reg] = ++this_tick;
df_set_regs_ever_live (best_new_reg, true);
}
@@ -675,8 +661,8 @@ merge_chains (du_head_p c1, du_head_p c2)
/* Analyze the current function and build chains for renaming. */
-static void
-regrename_analyze (void)
+void
+regrename_analyze (bitmap bb_mask)
{
struct bb_rename_info *rename_info;
int i;
@@ -694,7 +680,10 @@ regrename_analyze (void)
{
struct bb_rename_info *ri = rename_info + i;
ri->bb = bb;
- bb->aux = ri;
+ if (bb_mask != NULL && !bitmap_bit_p (bb_mask, bb->index))
+ bb->aux = NULL;
+ else
+ bb->aux = ri;
i++;
}
@@ -735,6 +724,16 @@ regrename_analyze (void)
current_id = old_length;
bitmap_clear (&this_info->incoming_open_chains_set);
open_chains = NULL;
+ if (insn_rr != NULL)
+ {
+ rtx insn;
+ FOR_BB_INSNS (bb1, insn)
+ {
+ insn_rr_info *p = VEC_index (insn_rr_info, insn_rr,
+ INSN_UID (insn));
+ p->op_info = NULL;
+ }
+ }
continue;
}
@@ -798,7 +797,7 @@ regrename_analyze (void)
{
edge e;
edge_iterator ei;
- struct du_head *chain = chain_from_id (j);
+ struct du_head *chain = regrename_chain_from_id (j);
int n_preds_used = 0, n_preds_joined = 0;
FOR_EACH_EDGE (e, ei, bb->preds)
@@ -825,7 +824,7 @@ regrename_analyze (void)
EXECUTE_IF_SET_IN_BITMAP (&src_ri->open_chains_set,
0, k, bi2)
{
- struct du_head *outgoing_chain = chain_from_id (k);
+ struct du_head *outgoing_chain = regrename_chain_from_id (k);
if (outgoing_chain->regno == chain->regno
&& outgoing_chain->nregs == chain->nregs)
@@ -863,7 +862,7 @@ regrename_analyze (void)
{
edge e;
edge_iterator ei;
- struct du_head *chain = chain_from_id (j);
+ struct du_head *chain = regrename_chain_from_id (j);
int n_succs_used = 0, n_succs_joined = 0;
FOR_EACH_EDGE (e, ei, bb->succs)
@@ -888,7 +887,7 @@ regrename_analyze (void)
EXECUTE_IF_SET_IN_BITMAP (&dest_ri->incoming_open_chains_set,
0, k, bi2)
{
- struct du_head *incoming_chain = chain_from_id (k);
+ struct du_head *incoming_chain = regrename_chain_from_id (k);
if (incoming_chain->regno == chain->regno
&& incoming_chain->nregs == chain->nregs)
@@ -928,11 +927,12 @@ regrename_analyze (void)
bb->aux = NULL;
}
-static void
-do_replace (struct du_head *head, int reg)
+void
+regrename_do_replace (struct du_head *head, int reg)
{
struct du_chain *chain;
unsigned int base_regno = head->regno;
+ enum machine_mode mode;
for (chain = head->first; chain; chain = chain->next_use)
{
@@ -953,6 +953,10 @@ do_replace (struct du_head *head, int reg)
df_insn_rescan (chain->insn);
}
+
+ mode = GET_MODE (*head->first->loc);
+ head->regno = reg;
+ head->nregs = hard_regno_nregs[reg][mode];
}
@@ -1106,6 +1110,7 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
head->first = this_du;
else
head->last->next_use = this_du;
+ record_operand_use (head, this_du);
head->last = this_du;
}
/* Avoid adding the same location in a DEBUG_INSN multiple times,
@@ -1468,10 +1473,11 @@ restore_operands (rtx insn, int n_ops, rtx *old_operands, rtx *old_dups)
/* For each output operand of INSN, call scan_rtx to create a new
open chain. Do this only for normal or earlyclobber outputs,
- depending on EARLYCLOBBER. */
+ depending on EARLYCLOBBER. If INSN_INFO is nonnull, use it to
+ record information about the operands in the insn. */
static void
-record_out_operands (rtx insn, bool earlyclobber)
+record_out_operands (rtx insn, bool earlyclobber, insn_rr_info *insn_info)
{
int n_ops = recog_data.n_operands;
int alt = which_alternative;
@@ -1493,6 +1499,9 @@ record_out_operands (rtx insn, bool earlyclobber)
|| recog_op_alt[opn][alt].earlyclobber != earlyclobber)
continue;
+ if (insn_info)
+ cur_operand = insn_info->op_info + i;
+
prev_open = open_chains;
scan_rtx (insn, loc, cl, mark_write, OP_OUT);
@@ -1510,6 +1519,7 @@ record_out_operands (rtx insn, bool earlyclobber)
open_chains->cannot_rename = 1;
}
}
+ cur_operand = NULL;
}
/* Build def/use chain. */
@@ -1535,6 +1545,7 @@ build_def_use (basic_block bb)
int predicated;
enum rtx_code set_code = SET;
enum rtx_code clobber_code = CLOBBER;
+ insn_rr_info *insn_info = NULL;
/* Process the insn, determining its effect on the def-use
chains and live hard registers. We perform the following
@@ -1567,6 +1578,15 @@ build_def_use (basic_block bb)
n_ops = recog_data.n_operands;
untracked_operands = 0;
+ if (insn_rr != NULL)
+ {
+ insn_info = VEC_index (insn_rr_info, insn_rr, INSN_UID (insn));
+ insn_info->op_info = XOBNEWVEC (&rename_obstack, operand_rr_info,
+ recog_data.n_operands);
+ memset (insn_info->op_info, 0,
+ sizeof (operand_rr_info) * recog_data.n_operands);
+ }
+
/* Simplify the code below by rewriting things to reflect
matching constraints. Also promote OP_OUT to OP_INOUT in
predicated instructions, but only for register operands
@@ -1625,7 +1645,7 @@ build_def_use (basic_block bb)
/* Step 1b: Begin new chains for earlyclobbered writes inside
operands. */
- record_out_operands (insn, true);
+ record_out_operands (insn, true, insn_info);
/* Step 2: Mark chains for which we have reads outside operands
as unrenamable.
@@ -1674,11 +1694,14 @@ build_def_use (basic_block bb)
|| untracked_operands & (1 << opn))
continue;
+ if (insn_info)
+ cur_operand = i == opn ? insn_info->op_info + i : NULL;
if (recog_op_alt[opn][alt].is_address)
scan_rtx_address (insn, loc, cl, mark_read, VOIDmode);
else
scan_rtx (insn, loc, cl, mark_read, type);
}
+ cur_operand = NULL;
/* Step 3B: Record updates for regs in REG_INC notes, and
source regs in REG_FRAME_RELATED_EXPR notes. */
@@ -1729,7 +1752,7 @@ build_def_use (basic_block bb)
restore_operands (insn, n_ops, old_operands, old_dups);
/* Step 6b: Begin new chains for writes inside operands. */
- record_out_operands (insn, false);
+ record_out_operands (insn, false, insn_info);
/* Step 6c: Record destination regs in REG_FRAME_RELATED_EXPR
notes for update. */
@@ -1766,6 +1789,26 @@ build_def_use (basic_block bb)
return true;
}
+/* Initialize the register renamer. If INSN_INFO is true, ensure that
+ insn_rr is nonnull. */
+void
+regrename_init (bool insn_info)
+{
+ gcc_obstack_init (&rename_obstack);
+ insn_rr = NULL;
+ if (insn_info)
+ VEC_safe_grow_cleared (insn_rr_info, heap, insn_rr, get_max_uid ());
+}
+
+/* Free all global data used by the register renamer. */
+void
+regrename_finish (void)
+{
+ VEC_free (insn_rr_info, heap, insn_rr);
+ free_chain_data ();
+ obstack_free (&rename_obstack, NULL);
+}
+
/* Perform register renaming on the current function. */
static unsigned int
@@ -1776,14 +1819,13 @@ regrename_optimize (void)
df_analyze ();
df_set_flags (DF_DEFER_INSN_RESCAN);
- gcc_obstack_init (&rename_obstack);
+ regrename_init (false);
- regrename_analyze ();
+ regrename_analyze (NULL);
rename_chains ();
- free_chain_data ();
- obstack_free (&rename_obstack, NULL);
+ regrename_finish ();
return 0;
}
diff --git a/gcc/regrename.h b/gcc/regrename.h
new file mode 100644
index 00000000000..f3969a14fc2
--- /dev/null
+++ b/gcc/regrename.h
@@ -0,0 +1,101 @@
+/* This file contains definitions for the register renamer.
+ Copyright (C) 2011
+ 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 3, 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 COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_REGRENAME_H
+#define GCC_REGRENAME_H
+
+/* We keep linked lists of DU_HEAD structures, each of which describes
+ a chain of occurrences of a reg. */
+struct du_head
+{
+ /* The next chain. */
+ struct du_head *next_chain;
+ /* The first and last elements of this chain. */
+ struct du_chain *first, *last;
+ /* Describes the register being tracked. */
+ unsigned regno;
+ int nregs;
+
+ /* A unique id to be used as an index into the conflicts bitmaps. */
+ unsigned id;
+ /* A bitmap to record conflicts with other chains. */
+ bitmap_head conflicts;
+ /* Conflicts with untracked hard registers. */
+ HARD_REG_SET hard_conflicts;
+
+ /* Nonzero if the chain crosses a call. */
+ unsigned int need_caller_save_reg:1;
+ /* Nonzero if the register is used in a way that prevents renaming,
+ such as the SET_DEST of a CALL_INSN or an asm operand that used
+ to be a hard register. */
+ unsigned int cannot_rename:1;
+};
+
+typedef struct du_head *du_head_p;
+DEF_VEC_P (du_head_p);
+DEF_VEC_ALLOC_P (du_head_p, heap);
+
+/* This struct describes a single occurrence of a register. */
+struct du_chain
+{
+ /* Links to the next occurrence of the register. */
+ struct du_chain *next_use;
+
+ /* The insn where the register appears. */
+ rtx insn;
+ /* The location inside the insn. */
+ rtx *loc;
+ /* The register class required by the insn at this location. */
+ ENUM_BITFIELD(reg_class) cl : 16;
+};
+
+/* This struct describes data gathered during regrename_analyze about
+ a single operand of an insn. */
+typedef struct
+{
+ /* The number of chains recorded for this operand. */
+ int n_chains;
+ /* Holds either the chain for the operand itself, or for the registers in
+ a memory operand. */
+ struct du_chain *chains[MAX_REGS_PER_ADDRESS];
+ struct du_head *heads[MAX_REGS_PER_ADDRESS];
+} operand_rr_info;
+
+/* A struct to hold a vector of operand_rr_info structures describing the
+ operands of an insn. */
+typedef struct
+{
+ operand_rr_info *op_info;
+} insn_rr_info;
+
+DEF_VEC_O (insn_rr_info);
+DEF_VEC_ALLOC_O (insn_rr_info, heap);
+
+extern VEC(insn_rr_info, heap) *insn_rr;
+
+extern void regrename_init (bool);
+extern void regrename_finish (void);
+extern void regrename_analyze (bitmap);
+extern du_head_p regrename_chain_from_id (unsigned int);
+extern int find_best_rename_reg (du_head_p, enum reg_class, HARD_REG_SET *,
+ int);
+extern void regrename_do_replace (du_head_p, int);
+
+#endif
diff --git a/gcc/reload.c b/gcc/reload.c
index 53dcd2dafed..7dbc163da4d 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -256,7 +256,6 @@ static int push_secondary_reload (int, rtx, int, int, enum reg_class,
enum insn_code *, secondary_reload_info *);
static enum reg_class find_valid_class (enum machine_mode, enum machine_mode,
int, unsigned int);
-static int reload_inner_reg_of_subreg (rtx, enum machine_mode, int);
static void push_replacement (rtx *, int, enum machine_mode);
static void dup_replacements (rtx *, rtx *);
static void combine_reloads (void);
@@ -791,39 +790,39 @@ find_reusable_reload (rtx *p_in, rtx out, enum reg_class rclass,
return n_reloads;
}
-/* Return nonzero if X is a SUBREG which will require reloading of its
- SUBREG_REG expression. */
+/* Return true if X is a SUBREG that will need reloading of its SUBREG_REG
+ expression. MODE is the mode that X will be used in. OUTPUT is true if
+ the function is invoked for the output part of an enclosing reload. */
-static int
-reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, int output)
+static bool
+reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, bool output)
{
rtx inner;
/* Only SUBREGs are problematical. */
if (GET_CODE (x) != SUBREG)
- return 0;
+ return false;
inner = SUBREG_REG (x);
- /* If INNER is a constant or PLUS, then INNER must be reloaded. */
+ /* If INNER is a constant or PLUS, then INNER will need reloading. */
if (CONSTANT_P (inner) || GET_CODE (inner) == PLUS)
- return 1;
+ return true;
- /* If INNER is not a hard register, then INNER will not need to
- be reloaded. */
- if (!REG_P (inner)
- || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
- return 0;
+ /* If INNER is not a hard register, then INNER will not need reloading. */
+ if (!(REG_P (inner) && HARD_REGISTER_P (inner)))
+ return false;
/* If INNER is not ok for MODE, then INNER will need reloading. */
- if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
- return 1;
-
- /* If the outer part is a word or smaller, INNER larger than a
- word and the number of regs for INNER is not the same as the
- number of words in INNER, then INNER will need reloading. */
- return (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
- && output
+ if (!HARD_REGNO_MODE_OK (subreg_regno (x), mode))
+ return true;
+
+ /* If this is for an output, and the outer part is a word or smaller,
+ INNER is larger than a word and the number of registers in INNER is
+ not the same as the number of words in INNER, then INNER will need
+ reloading (with an in-out reload). */
+ return (output
+ && GET_MODE_SIZE (mode) <= UNITS_PER_WORD
&& GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
&& ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
!= (int) hard_regno_nregs[REGNO (inner)][GET_MODE (inner)]));
@@ -990,9 +989,9 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
For machines that extend byte loads, do this for any SUBREG of a pseudo
where both M1 and M2 are a word or smaller, M1 is wider than M2, and
M2 is an integral mode that gets extended when loaded.
- Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where either M1 is not valid for R or M2 is wider than a word but we
+ only need one register to store an M2-sized quantity in R.
(However, if OUT is nonzero, we need to reload the reg *and*
the subreg, so do nothing here, and let following statement handle it.)
@@ -1082,17 +1081,16 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
inmode = GET_MODE (in);
}
- /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where M1 is not valid for R if it was not handled by the code above.
+
+ Similar issue for (SUBREG constant ...) if it was not handled by the
+ code above. This can happen if SUBREG_BYTE != 0.
However, we must reload the inner reg *as well as* the subreg in
that case. */
- /* Similar issue for (SUBREG constant ...) if it was not handled by the
- code above. This can happen if SUBREG_BYTE != 0. */
-
- if (in != 0 && reload_inner_reg_of_subreg (in, inmode, 0))
+ if (in != 0 && reload_inner_reg_of_subreg (in, inmode, false))
{
enum reg_class in_class = rclass;
@@ -1117,10 +1115,10 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
/* Similarly for paradoxical and problematical SUBREGs on the output.
Note that there is no reason we need worry about the previous value
- of SUBREG_REG (out); even if wider than out,
- storing in a subreg is entitled to clobber it all
- (except in the case of STRICT_LOW_PART,
- and in that case the constraint should label it input-output.) */
+ of SUBREG_REG (out); even if wider than out, storing in a subreg is
+ entitled to clobber it all (except in the case of a word mode subreg
+ or of a STRICT_LOW_PART, in that latter case the constraint should
+ label it input-output.) */
if (out != 0 && GET_CODE (out) == SUBREG
&& (subreg_lowpart_p (out) || strict_low)
#ifdef CANNOT_CHANGE_MODE_CLASS
@@ -1144,14 +1142,12 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
))
|| (REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
- && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
- && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
- > UNITS_PER_WORD)
- && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
- / UNITS_PER_WORD)
- != (int) hard_regno_nregs[REGNO (SUBREG_REG (out))]
- [GET_MODE (SUBREG_REG (out))]))
- || ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
+ /* The case of a word mode subreg
+ is handled differently in the following statement. */
+ && ! (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
+ && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
+ > UNITS_PER_WORD))
+ && ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode))
|| (secondary_reload_class (0, rclass, outmode, out) != NO_REGS
&& (secondary_reload_class (0, rclass, GET_MODE (SUBREG_REG (out)),
SUBREG_REG (out))
@@ -1178,31 +1174,32 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
outmode = GET_MODE (out);
}
- /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
- either M1 is not valid for R or M2 is wider than a word but we only
- need one word to store an M2-sized quantity in R.
+ /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R
+ where either M1 is not valid for R or M2 is wider than a word but we
+ only need one register to store an M2-sized quantity in R.
However, we must reload the inner reg *as well as* the subreg in
- that case. In this case, the inner reg is an in-out reload. */
+ that case and the inner reg is an in-out reload. */
- if (out != 0 && reload_inner_reg_of_subreg (out, outmode, 1))
+ if (out != 0 && reload_inner_reg_of_subreg (out, outmode, true))
{
+ enum reg_class in_out_class
+ = find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
+ subreg_regno_offset (REGNO (SUBREG_REG (out)),
+ GET_MODE (SUBREG_REG (out)),
+ SUBREG_BYTE (out),
+ GET_MODE (out)),
+ REGNO (SUBREG_REG (out)));
+
/* This relies on the fact that emit_reload_insns outputs the
instructions for output reloads of type RELOAD_OTHER in reverse
order of the reloads. Thus if the outer reload is also of type
RELOAD_OTHER, we are guaranteed that this inner reload will be
output after the outer reload. */
- dont_remove_subreg = 1;
push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
- &SUBREG_REG (out),
- find_valid_class (outmode, GET_MODE (SUBREG_REG (out)),
- subreg_regno_offset (REGNO (SUBREG_REG (out)),
- GET_MODE (SUBREG_REG (out)),
- SUBREG_BYTE (out),
- GET_MODE (out)),
- REGNO (SUBREG_REG (out))),
- VOIDmode, VOIDmode, 0, 0,
- opnum, RELOAD_OTHER);
+ &SUBREG_REG (out), in_out_class, VOIDmode, VOIDmode,
+ 0, 0, opnum, RELOAD_OTHER);
+ dont_remove_subreg = 1;
}
/* If IN appears in OUT, we can't share any input-only reload for IN. */
@@ -7231,7 +7228,7 @@ regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
{
rtx elt = XVECEXP (PATTERN (insn), 0, i);
if ((GET_CODE (elt) == CLOBBER
- || (sets == 1 && GET_CODE (PATTERN (insn)) == SET))
+ || (sets == 1 && GET_CODE (elt) == SET))
&& REG_P (XEXP (elt, 0)))
{
unsigned int test = REGNO (XEXP (elt, 0));
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 6070eaa81a6..04a839ede7b 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -3918,6 +3918,10 @@ set_initial_label_offsets (void)
if (XEXP (x, 0))
set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+ for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
+ if (XEXP (x, 0))
+ set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+
for_each_eh_label (set_initial_eh_label_offset);
}
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 179bf5fbdaf..40d73a76a71 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -467,7 +467,7 @@ find_end_label (rtx kind)
/* The return we make may have delay slots too. */
rtx insn = gen_return ();
insn = emit_jump_insn (insn);
- JUMP_LABEL (insn) = ret_rtx;
+ set_return_jump_label (insn);
emit_barrier ();
if (num_delay_slots (insn) > 0)
obstack_ptr_grow (&unfilled_slots_obstack, insn);
@@ -3349,6 +3349,21 @@ delete_jump (rtx insn)
delete_computation (insn);
}
+static rtx
+label_before_next_insn (rtx x, rtx scan_limit)
+{
+ rtx insn = next_active_insn (x);
+ while (insn)
+ {
+ insn = PREV_INSN (insn);
+ if (insn == scan_limit || insn == NULL_RTX)
+ return NULL_RTX;
+ if (LABEL_P (insn))
+ break;
+ }
+ return insn;
+}
+
/* Once we have tried two ways to fill a delay slot, make a pass over the
code to try to improve the results and to do such things as more jump
@@ -3634,7 +3649,7 @@ relax_delay_slots (rtx first)
identical to the one in its delay slot. In this case, we can just
delete the branch and the insn in its delay slot. */
if (next && NONJUMP_INSN_P (next)
- && prev_label (next_active_insn (next)) == target_label
+ && label_before_next_insn (next, insn) == target_label
&& simplejump_p (insn)
&& XVECLEN (pat, 0) == 2
&& rtx_equal_p (PATTERN (next), PATTERN (XVECEXP (pat, 0, 1))))
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 567aff93668..41536bea02c 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -265,7 +265,8 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
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. */
+ In a CODE_LABEL, part of the two-bit alternate entry field.
+ 1 in a CONCAT is VAL_EXPR_IS_COPIED in var-tracking.c. */
unsigned int jump : 1;
/* In a CODE_LABEL, part of the two-bit alternate entry field.
1 in a MEM if it cannot trap.
@@ -278,7 +279,9 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
constants pool.
1 in a CALL_INSN logically equivalent to ECF_CONST and TREE_READONLY.
1 in a NOTE, or EXPR_LIST for a const call.
- 1 in a JUMP_INSN of an annulling branch. */
+ 1 in a JUMP_INSN of an annulling branch.
+ 1 in a CONCAT is VAL_EXPR_IS_CLOBBERED in var-tracking.c.
+ 1 in a preserved VALUE is PRESERVED_VALUE_P in cselib.c. */
unsigned int unchanging : 1;
/* 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
@@ -290,7 +293,8 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
non-local label.
In a SYMBOL_REF, this flag is used for machine-specific purposes.
In a PREFETCH, this flag indicates that it should be considered a scheduling
- barrier. */
+ barrier.
+ 1 in a CONCAT is VAL_NEEDS_RESOLUTION in var-tracking.c. */
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;
@@ -311,19 +315,24 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
In a REG, this is not needed for that purpose, and used instead
in `leaf_renumber_regs_insn'.
1 in a SYMBOL_REF, means that emit_library_call
- has used it as the function. */
+ has used it as the function.
+ 1 in a CONCAT is VAL_HOLDS_TRACK_EXPR in var-tracking.c.
+ 1 in a VALUE or DEBUG_EXPR is VALUE_RECURSED_INTO in var-tracking.c. */
unsigned int used : 1;
/* 1 in an INSN or a SET if this rtx is related to the call frame,
either changing how we compute the frame address or saving and
restoring registers in the prologue and epilogue.
1 in a REG or MEM if it is a pointer.
1 in a SYMBOL_REF if it addresses something in the per-function
- constant string pool. */
+ constant string pool.
+ 1 in a VALUE is VALUE_CHANGED in var-tracking.c. */
unsigned frame_related : 1;
/* 1 in a REG or PARALLEL that is the current function's return value.
1 in a MEM if it refers to a scalar.
1 in a SYMBOL_REF for a weak symbol.
- 1 in a CALL_INSN logically equivalent to ECF_PURE and DECL_PURE_P. */
+ 1 in a CALL_INSN logically equivalent to ECF_PURE and DECL_PURE_P.
+ 1 in a CONCAT is VAL_EXPR_HAS_REVERSE in var-tracking.c.
+ 1 in a VALUE or DEBUG_EXPR is NO_LOC_P in var-tracking.c. */
unsigned return_val : 1;
/* The first element of the operands of this rtx.
@@ -1803,7 +1812,6 @@ extern rtx next_real_insn (rtx);
extern rtx prev_active_insn (rtx);
extern rtx next_active_insn (rtx);
extern int active_insn_p (const_rtx);
-extern rtx prev_label (rtx);
extern rtx next_label (rtx);
extern rtx skip_consecutive_labels (rtx);
extern rtx next_cc0_user (rtx);
@@ -1932,6 +1940,11 @@ extern rtx find_last_value (rtx, rtx *, rtx, int);
extern int refers_to_regno_p (unsigned int, unsigned int, const_rtx, rtx *);
extern int reg_overlap_mentioned_p (const_rtx, const_rtx);
extern const_rtx set_of (const_rtx, const_rtx);
+extern void record_hard_reg_sets (rtx, const_rtx, void *);
+extern void record_hard_reg_uses (rtx *, void *);
+#ifdef HARD_CONST
+extern void find_all_hard_reg_sets (const_rtx, HARD_REG_SET *);
+#endif
extern void note_stores (const_rtx, void (*) (rtx, const_rtx, void *), void *);
extern void note_uses (rtx *, void (*) (rtx *, void *), void *);
extern int dead_or_set_p (const_rtx, const_rtx);
@@ -2027,12 +2040,14 @@ extern void subreg_get_info (unsigned int, enum machine_mode,
/* lists.c */
-extern void free_EXPR_LIST_list (rtx *);
-extern void free_INSN_LIST_list (rtx *);
-extern void free_EXPR_LIST_node (rtx);
-extern void free_INSN_LIST_node (rtx);
-extern rtx alloc_INSN_LIST (rtx, rtx);
-extern rtx alloc_EXPR_LIST (int, rtx, rtx);
+extern void free_EXPR_LIST_list (rtx *);
+extern void free_INSN_LIST_list (rtx *);
+extern void free_EXPR_LIST_node (rtx);
+extern void free_INSN_LIST_node (rtx);
+extern rtx alloc_INSN_LIST (rtx, rtx);
+extern rtx copy_INSN_LIST (rtx);
+extern rtx concat_INSN_LIST (rtx, rtx);
+extern rtx alloc_EXPR_LIST (int, rtx, rtx);
extern void remove_free_INSN_LIST_elem (rtx, rtx *);
extern rtx remove_list_elem (rtx, rtx *);
extern rtx remove_free_INSN_LIST_node (rtx *);
@@ -2503,6 +2518,7 @@ extern int sibcall_epilogue_contains (const_rtx);
extern void mark_temp_addr_taken (rtx);
extern void update_temp_slot_address (rtx, rtx);
extern void maybe_copy_prologue_epilogue_insn (rtx, rtx);
+extern void set_return_jump_label (rtx);
/* In stmt.c */
extern void expand_null_return (void);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index d6e84a22221..54d9eb1ef67 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -25,8 +25,8 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "tm.h"
#include "diagnostic-core.h"
-#include "rtl.h"
#include "hard-reg-set.h"
+#include "rtl.h"
#include "insn-config.h"
#include "recog.h"
#include "target.h"
@@ -999,6 +999,56 @@ set_of (const_rtx pat, const_rtx insn)
note_stores (INSN_P (insn) ? PATTERN (insn) : insn, set_of_1, &data);
return data.found;
}
+
+/* This function, called through note_stores, collects sets and
+ clobbers of hard registers in a HARD_REG_SET, which is pointed to
+ by DATA. */
+void
+record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
+{
+ HARD_REG_SET *pset = (HARD_REG_SET *)data;
+ if (REG_P (x) && HARD_REGISTER_P (x))
+ add_to_hard_reg_set (pset, GET_MODE (x), REGNO (x));
+}
+
+/* Examine INSN, and compute the set of hard registers written by it.
+ Store it in *PSET. Should only be called after reload. */
+void
+find_all_hard_reg_sets (const_rtx insn, HARD_REG_SET *pset)
+{
+ rtx link;
+
+ CLEAR_HARD_REG_SET (*pset);
+ note_stores (PATTERN (insn), record_hard_reg_sets, pset);
+ if (CALL_P (insn))
+ IOR_HARD_REG_SET (*pset, call_used_reg_set);
+ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_INC)
+ record_hard_reg_sets (XEXP (link, 0), NULL, pset);
+}
+
+/* A for_each_rtx subroutine of record_hard_reg_uses. */
+static int
+record_hard_reg_uses_1 (rtx *px, void *data)
+{
+ rtx x = *px;
+ HARD_REG_SET *pused = (HARD_REG_SET *)data;
+
+ if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ {
+ int nregs = hard_regno_nregs[REGNO (x)][GET_MODE (x)];
+ while (nregs-- > 0)
+ SET_HARD_REG_BIT (*pused, REGNO (x) + nregs);
+ }
+ return 0;
+}
+
+/* Like record_hard_reg_sets, but called through note_uses. */
+void
+record_hard_reg_uses (rtx *px, void *data)
+{
+ for_each_rtx (px, record_hard_reg_uses_1, data);
+}
/* Given an INSN, return a SET expression if this insn has only a single SET.
It may also have CLOBBERs, USEs, or SET whose output
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index ed592c8278a..a778721d20b 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -52,12 +52,6 @@ along with GCC; see the file COPYING3. If not see
#define CHECK (false)
#endif
-/* In deps->last_pending_memory_flush marks JUMP_INSNs that weren't
- added to the list because of flush_pending_lists, stands just
- for itself and not for any other pending memory reads/writes. */
-#define NON_FLUSH_JUMP_KIND REG_DEP_ANTI
-#define NON_FLUSH_JUMP_P(x) (REG_NOTE_KIND (x) == NON_FLUSH_JUMP_KIND)
-
/* Holds current parameters for the dependency analyzer. */
struct sched_deps_info_def *sched_deps_info;
@@ -74,6 +68,9 @@ ds_to_dk (ds_t ds)
if (ds & DEP_OUTPUT)
return REG_DEP_OUTPUT;
+ if (ds & DEP_CONTROL)
+ return REG_DEP_CONTROL;
+
gcc_assert (ds & DEP_ANTI);
return REG_DEP_ANTI;
@@ -91,6 +88,9 @@ dk_to_ds (enum reg_note dk)
case REG_DEP_OUTPUT:
return DEP_OUTPUT;
+ case REG_DEP_CONTROL:
+ return DEP_CONTROL;
+
default:
gcc_assert (dk == REG_DEP_ANTI);
return DEP_ANTI;
@@ -187,6 +187,10 @@ dump_dep (FILE *dump, dep_t dep, int flags)
t = 'o';
break;
+ case REG_DEP_CONTROL:
+ t = 'c';
+ break;
+
case REG_DEP_ANTI:
t = 'a';
break;
@@ -420,13 +424,22 @@ static bool
dep_spec_p (dep_t dep)
{
if (current_sched_info->flags & DO_SPECULATION)
- return (DEP_STATUS (dep) & SPECULATIVE) != 0;
+ {
+ if (DEP_STATUS (dep) & SPECULATIVE)
+ return true;
+ }
+ if (current_sched_info->flags & DO_PREDICATION)
+ {
+ if (DEP_TYPE (dep) == REG_DEP_CONTROL)
+ return true;
+ }
return false;
}
static regset reg_pending_sets;
static regset reg_pending_clobbers;
static regset reg_pending_uses;
+static regset reg_pending_control_uses;
static enum reg_pending_barrier_mode reg_pending_barrier;
/* Hard registers implicitly clobbered or used (or may be implicitly
@@ -454,10 +467,12 @@ static HARD_REG_SET implicit_reg_pending_uses;
static bitmap_head *true_dependency_cache = NULL;
static bitmap_head *output_dependency_cache = NULL;
static bitmap_head *anti_dependency_cache = NULL;
+static bitmap_head *control_dependency_cache = NULL;
static bitmap_head *spec_dependency_cache = NULL;
static int cache_size;
static int deps_may_trap_p (const_rtx);
+static void add_dependence_1 (rtx, rtx, enum reg_note);
static void add_dependence_list (rtx, rtx, int, enum reg_note);
static void add_dependence_list_and_free (struct deps_desc *, rtx,
rtx *, int, enum reg_note);
@@ -538,6 +553,27 @@ sched_get_condition_with_rev_uncached (const_rtx insn, bool *rev)
return 0;
}
+/* Return the condition under which INSN does not execute (i.e. the
+ not-taken condition for a conditional branch), or NULL if we cannot
+ find such a condition. The caller should make a copy of the condition
+ before using it. */
+rtx
+sched_get_reverse_condition_uncached (const_rtx insn)
+{
+ bool rev;
+ rtx cond = sched_get_condition_with_rev_uncached (insn, &rev);
+ if (cond == NULL_RTX)
+ return cond;
+ if (!rev)
+ {
+ enum rtx_code revcode = reversed_comparison_code (cond, insn);
+ cond = gen_rtx_fmt_ee (revcode, GET_MODE (cond),
+ XEXP (cond, 0),
+ XEXP (cond, 1));
+ }
+ return cond;
+}
+
/* Caching variant of sched_get_condition_with_rev_uncached.
We only do actual work the first time we come here for an insn; the
results are cached in INSN_CACHED_COND and INSN_REVERSE_COND. */
@@ -861,12 +897,10 @@ sd_find_dep_between (rtx pro, rtx con, bool resolved_p)
int elem_luid = INSN_LUID (pro);
int insn_luid = INSN_LUID (con);
- gcc_assert (output_dependency_cache != NULL
- && anti_dependency_cache != NULL);
-
if (!bitmap_bit_p (&true_dependency_cache[insn_luid], elem_luid)
&& !bitmap_bit_p (&output_dependency_cache[insn_luid], elem_luid)
- && !bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
+ && !bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid)
+ && !bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
return NULL;
}
@@ -919,7 +953,8 @@ ask_dependency_caches (dep_t dep)
gcc_assert (true_dependency_cache != NULL
&& output_dependency_cache != NULL
- && anti_dependency_cache != NULL);
+ && anti_dependency_cache != NULL
+ && control_dependency_cache != NULL);
if (!(current_sched_info->flags & USE_DEPS_LIST))
{
@@ -931,6 +966,8 @@ ask_dependency_caches (dep_t dep)
present_dep_type = REG_DEP_OUTPUT;
else if (bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
present_dep_type = REG_DEP_ANTI;
+ else if (bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
+ present_dep_type = REG_DEP_CONTROL;
else
/* There is no existing dep so it should be created. */
return DEP_CREATED;
@@ -949,6 +986,8 @@ ask_dependency_caches (dep_t dep)
present_dep_types |= DEP_OUTPUT;
if (bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
present_dep_types |= DEP_ANTI;
+ if (bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
+ present_dep_types |= DEP_CONTROL;
if (present_dep_types == 0)
/* There is no existing dep so it should be created. */
@@ -1002,6 +1041,10 @@ set_dependency_caches (dep_t dep)
bitmap_set_bit (&anti_dependency_cache[insn_luid], elem_luid);
break;
+ case REG_DEP_CONTROL:
+ bitmap_set_bit (&control_dependency_cache[insn_luid], elem_luid);
+ break;
+
default:
gcc_unreachable ();
}
@@ -1016,6 +1059,8 @@ set_dependency_caches (dep_t dep)
bitmap_set_bit (&output_dependency_cache[insn_luid], elem_luid);
if (ds & DEP_ANTI)
bitmap_set_bit (&anti_dependency_cache[insn_luid], elem_luid);
+ if (ds & DEP_CONTROL)
+ bitmap_set_bit (&control_dependency_cache[insn_luid], elem_luid);
if (ds & SPECULATIVE)
{
@@ -1047,6 +1092,10 @@ update_dependency_caches (dep_t dep, enum reg_note old_type)
bitmap_clear_bit (&anti_dependency_cache[insn_luid], elem_luid);
break;
+ case REG_DEP_CONTROL:
+ bitmap_clear_bit (&control_dependency_cache[insn_luid], elem_luid);
+ break;
+
default:
gcc_unreachable ();
}
@@ -1330,8 +1379,7 @@ sd_unresolve_dep (sd_iterator_def sd_it)
rtx pro = DEP_PRO (dep);
rtx con = DEP_CON (dep);
- if ((current_sched_info->flags & DO_SPECULATION)
- && (DEP_STATUS (dep) & SPECULATIVE))
+ if (dep_spec_p (dep))
move_dep_link (DEP_NODE_BACK (node), INSN_RESOLVED_BACK_DEPS (con),
INSN_SPEC_BACK_DEPS (con));
else
@@ -1382,6 +1430,7 @@ sd_delete_dep (sd_iterator_def sd_it)
bitmap_clear_bit (&true_dependency_cache[insn_luid], elem_luid);
bitmap_clear_bit (&anti_dependency_cache[insn_luid], elem_luid);
+ bitmap_clear_bit (&control_dependency_cache[insn_luid], elem_luid);
bitmap_clear_bit (&output_dependency_cache[insn_luid], elem_luid);
if (current_sched_info->flags & DO_SPECULATION)
@@ -1447,6 +1496,57 @@ sd_debug_lists (rtx insn, sd_list_types_def types)
fprintf (stderr, "\n");
}
+/* A wrapper around add_dependence_1, to add a dependence of CON on
+ PRO, with type DEP_TYPE. This function implements special handling
+ for REG_DEP_CONTROL dependencies. For these, we optionally promote
+ the type to REG_DEP_ANTI if we can determine that predication is
+ impossible; otherwise we add additional true dependencies on the
+ INSN_COND_DEPS list of the jump (which PRO must be). */
+void
+add_dependence (rtx con, rtx pro, enum reg_note dep_type)
+{
+ if (dep_type == REG_DEP_CONTROL
+ && !(current_sched_info->flags & DO_PREDICATION))
+ dep_type = REG_DEP_ANTI;
+
+ /* A REG_DEP_CONTROL dependence may be eliminated through predication,
+ so we must also make the insn dependent on the setter of the
+ condition. */
+ if (dep_type == REG_DEP_CONTROL)
+ {
+ rtx real_pro = pro;
+ rtx other = real_insn_for_shadow (real_pro);
+ rtx cond;
+
+ if (other != NULL_RTX)
+ real_pro = other;
+ cond = sched_get_reverse_condition_uncached (real_pro);
+ /* Verify that the insn does not use a different value in
+ the condition register than the one that was present at
+ the jump. */
+ if (cond == NULL_RTX)
+ dep_type = REG_DEP_ANTI;
+ else if (INSN_CACHED_COND (real_pro) == const_true_rtx)
+ {
+ HARD_REG_SET uses;
+ CLEAR_HARD_REG_SET (uses);
+ note_uses (&PATTERN (con), record_hard_reg_uses, &uses);
+ if (TEST_HARD_REG_BIT (uses, REGNO (XEXP (cond, 0))))
+ dep_type = REG_DEP_ANTI;
+ }
+ if (dep_type == REG_DEP_CONTROL)
+ {
+ if (sched_verbose >= 5)
+ fprintf (sched_dump, "making DEP_CONTROL for %d\n",
+ INSN_UID (real_pro));
+ add_dependence_list (con, INSN_COND_DEPS (real_pro), 0,
+ REG_DEP_TRUE);
+ }
+ }
+
+ add_dependence_1 (con, pro, dep_type);
+}
+
/* A convenience wrapper to operate on an entire list. */
static void
@@ -1662,6 +1762,10 @@ flush_pending_lists (struct deps_desc *deps, rtx insn, int for_read,
add_dependence_list_and_free (deps, insn,
&deps->last_pending_memory_flush, 1,
for_read ? REG_DEP_ANTI : REG_DEP_OUTPUT);
+
+ add_dependence_list_and_free (deps, insn, &deps->pending_jump_insns, 1,
+ REG_DEP_ANTI);
+
if (!deps->readonly)
{
free_EXPR_LIST_list (&deps->pending_write_mems);
@@ -1783,10 +1887,12 @@ ds_to_dt (ds_t ds)
return REG_DEP_TRUE;
else if (ds & DEP_OUTPUT)
return REG_DEP_OUTPUT;
+ else if (ds & DEP_ANTI)
+ return REG_DEP_ANTI;
else
{
- gcc_assert (ds & DEP_ANTI);
- return REG_DEP_ANTI;
+ gcc_assert (ds & DEP_CONTROL);
+ return REG_DEP_CONTROL;
}
}
@@ -2394,6 +2500,8 @@ sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
add_dependence_list (insn, deps->last_pending_memory_flush, 1,
REG_DEP_ANTI);
+ add_dependence_list (insn, deps->pending_jump_insns, 1,
+ REG_DEP_CONTROL);
if (!deps->readonly)
add_insn_mem_dependence (deps, false, insn, dest);
@@ -2541,23 +2649,22 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
}
for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
- {
- if (! NON_FLUSH_JUMP_P (u))
- add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
- else if (deps_may_trap_p (x))
- {
- if ((sched_deps_info->generate_spec_deps)
- && sel_sched_p () && (spec_info->mask & BEGIN_CONTROL))
- {
- ds_t ds = set_dep_weak (DEP_ANTI, BEGIN_CONTROL,
- MAX_DEP_WEAK);
-
- note_dep (XEXP (u, 0), ds);
- }
- else
- add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
- }
- }
+ add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
+
+ for (u = deps->pending_jump_insns; u; u = XEXP (u, 1))
+ if (deps_may_trap_p (x))
+ {
+ if ((sched_deps_info->generate_spec_deps)
+ && sel_sched_p () && (spec_info->mask & BEGIN_CONTROL))
+ {
+ ds_t ds = set_dep_weak (DEP_ANTI, BEGIN_CONTROL,
+ MAX_DEP_WEAK);
+
+ note_dep (XEXP (u, 0), ds);
+ }
+ else
+ add_dependence (insn, XEXP (u, 0), REG_DEP_CONTROL);
+ }
}
/* Always add these dependencies to pending_reads, since
@@ -2776,13 +2883,11 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
if (sched_deps_info->compute_jump_reg_dependencies)
{
- regset_head tmp;
- INIT_REG_SET (&tmp);
-
- (*sched_deps_info->compute_jump_reg_dependencies) (insn, &tmp);
+ (*sched_deps_info->compute_jump_reg_dependencies)
+ (insn, reg_pending_control_uses);
/* Make latency of jump equal to 0 by using anti-dependence. */
- EXECUTE_IF_SET_IN_REG_SET (&tmp, 0, i, rsi)
+ EXECUTE_IF_SET_IN_REG_SET (reg_pending_control_uses, 0, i, rsi)
{
struct deps_reg *reg_last = &deps->reg_last[i];
add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI);
@@ -2790,15 +2895,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
0, REG_DEP_ANTI);
add_dependence_list (insn, reg_last->clobbers, 0,
REG_DEP_ANTI);
-
- if (!deps->readonly)
- {
- reg_last->uses_length++;
- reg_last->uses = alloc_INSN_LIST (insn, reg_last->uses);
- }
}
-
- CLEAR_REG_SET (&tmp);
}
/* All memory writes and volatile reads must happen before the
@@ -2828,6 +2925,8 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
add_dependence_list (insn, deps->last_pending_memory_flush, 1,
REG_DEP_ANTI);
+ add_dependence_list (insn, deps->pending_jump_insns, 1,
+ REG_DEP_ANTI);
}
}
@@ -2863,13 +2962,15 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
REG_DEP_ANTI);
for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
- if (! NON_FLUSH_JUMP_P (u) || !sel_sched_p ())
+ if (!sel_sched_p ())
add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
EXECUTE_IF_SET_IN_REG_SET (reg_pending_uses, 0, i, rsi)
{
struct deps_reg *reg_last = &deps->reg_last[i];
add_dependence_list (insn, reg_last->sets, 1, REG_DEP_ANTI);
+ /* There's no point in making REG_DEP_CONTROL dependencies for
+ debug insns. */
add_dependence_list (insn, reg_last->clobbers, 1, REG_DEP_ANTI);
if (!deps->readonly)
@@ -2953,6 +3054,8 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
add_dependence_list (insn, reg_last->implicit_sets, 0,
REG_DEP_ANTI);
add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+ add_dependence_list (insn, reg_last->control_uses, 0,
+ REG_DEP_CONTROL);
if (!deps->readonly)
{
@@ -2969,6 +3072,8 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
REG_DEP_ANTI);
add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_OUTPUT);
add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+ add_dependence_list (insn, reg_last->control_uses, 0,
+ REG_DEP_CONTROL);
if (!deps->readonly)
reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
@@ -2989,6 +3094,9 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
REG_DEP_ANTI);
add_dependence_list_and_free (deps, insn, &reg_last->uses, 0,
REG_DEP_ANTI);
+ add_dependence_list_and_free (deps, insn,
+ &reg_last->control_uses, 0,
+ REG_DEP_ANTI);
add_dependence_list_and_free
(deps, insn, &reg_last->clobbers, 0, REG_DEP_OUTPUT);
@@ -3005,6 +3113,8 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
add_dependence_list (insn, reg_last->implicit_sets, 0,
REG_DEP_ANTI);
add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+ add_dependence_list (insn, reg_last->control_uses, 0,
+ REG_DEP_CONTROL);
}
if (!deps->readonly)
@@ -3027,6 +3137,8 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
REG_DEP_OUTPUT);
add_dependence_list_and_free (deps, insn, &reg_last->uses, 0,
REG_DEP_ANTI);
+ add_dependence_list (insn, reg_last->control_uses, 0,
+ REG_DEP_CONTROL);
if (!deps->readonly)
{
@@ -3036,6 +3148,15 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
}
}
}
+ if (!deps->readonly)
+ {
+ EXECUTE_IF_SET_IN_REG_SET (reg_pending_control_uses, 0, i, rsi)
+ {
+ struct deps_reg *reg_last = &deps->reg_last[i];
+ reg_last->control_uses
+ = alloc_INSN_LIST (insn, reg_last->control_uses);
+ }
+ }
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -3045,6 +3166,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI);
add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_ANTI);
add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+ add_dependence_list (insn, reg_last->control_uses, 0, REG_DEP_ANTI);
if (!deps->readonly)
reg_last->implicit_sets
@@ -3068,6 +3190,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
CLEAR_REG_SET (reg_pending_uses);
CLEAR_REG_SET (reg_pending_clobbers);
CLEAR_REG_SET (reg_pending_sets);
+ CLEAR_REG_SET (reg_pending_control_uses);
CLEAR_HARD_REG_SET (implicit_reg_pending_clobbers);
CLEAR_HARD_REG_SET (implicit_reg_pending_uses);
@@ -3099,6 +3222,9 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
struct deps_reg *reg_last = &deps->reg_last[i];
add_dependence_list_and_free (deps, insn, &reg_last->uses, 0,
REG_DEP_ANTI);
+ add_dependence_list_and_free (deps, insn,
+ &reg_last->control_uses, 0,
+ REG_DEP_CONTROL);
add_dependence_list_and_free (deps, insn, &reg_last->sets, 0,
reg_pending_barrier == TRUE_BARRIER
? REG_DEP_TRUE : REG_DEP_ANTI);
@@ -3312,7 +3438,33 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
/* Record the condition for this insn. */
if (NONDEBUG_INSN_P (insn))
- sched_get_condition_with_rev (insn, NULL);
+ {
+ rtx t;
+ sched_get_condition_with_rev (insn, NULL);
+ t = INSN_CACHED_COND (insn);
+ INSN_COND_DEPS (insn) = NULL_RTX;
+ if (reload_completed
+ && (current_sched_info->flags & DO_PREDICATION)
+ && COMPARISON_P (t)
+ && REG_P (XEXP (t, 0))
+ && CONSTANT_P (XEXP (t, 1)))
+ {
+ unsigned int regno;
+ int nregs;
+ t = XEXP (t, 0);
+ regno = REGNO (t);
+ nregs = hard_regno_nregs[regno][GET_MODE (t)];
+ t = NULL_RTX;
+ while (nregs-- > 0)
+ {
+ struct deps_reg *reg_last = &deps->reg_last[regno + nregs];
+ t = concat_INSN_LIST (reg_last->sets, t);
+ t = concat_INSN_LIST (reg_last->clobbers, t);
+ t = concat_INSN_LIST (reg_last->implicit_sets, t);
+ }
+ INSN_COND_DEPS (insn) = t;
+ }
+ }
if (JUMP_P (insn))
{
@@ -3326,15 +3478,8 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
if (deps->pending_flush_length++ > MAX_PENDING_LIST_LENGTH)
flush_pending_lists (deps, insn, true, true);
else
- {
- deps->last_pending_memory_flush
- = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
- /* Signal to sched_analyze_insn that this jump stands
- just for its own, not any other pending memory
- reads/writes flush_pending_lists had to flush. */
- PUT_REG_NOTE_KIND (deps->last_pending_memory_flush,
- NON_FLUSH_JUMP_KIND);
- }
+ deps->pending_jump_insns
+ = alloc_INSN_LIST (insn, deps->pending_jump_insns);
}
/* For each insn which shouldn't cross a jump, add a dependence. */
@@ -3584,6 +3729,7 @@ init_deps (struct deps_desc *deps, bool lazy_reg_last)
deps->pending_read_mems = 0;
deps->pending_write_insns = 0;
deps->pending_write_mems = 0;
+ deps->pending_jump_insns = 0;
deps->pending_read_list_length = 0;
deps->pending_write_list_length = 0;
deps->pending_flush_length = 0;
@@ -3644,6 +3790,8 @@ free_deps (struct deps_desc *deps)
free_INSN_LIST_list (&reg_last->sets);
if (reg_last->implicit_sets)
free_INSN_LIST_list (&reg_last->implicit_sets);
+ if (reg_last->control_uses)
+ free_INSN_LIST_list (&reg_last->control_uses);
if (reg_last->clobbers)
free_INSN_LIST_list (&reg_last->clobbers);
}
@@ -3672,6 +3820,9 @@ remove_from_deps (struct deps_desc *deps, rtx insn)
removed = remove_from_both_dependence_lists (insn, &deps->pending_write_insns,
&deps->pending_write_mems);
deps->pending_write_list_length -= removed;
+
+ removed = remove_from_dependence_list (insn, &deps->pending_jump_insns);
+ deps->pending_flush_length -= removed;
removed = remove_from_dependence_list (insn, &deps->last_pending_memory_flush);
deps->pending_flush_length -= removed;
@@ -3766,6 +3917,8 @@ extend_dependency_caches (int n, bool create_p)
output_dependency_cache, luid);
anti_dependency_cache = XRESIZEVEC (bitmap_head, anti_dependency_cache,
luid);
+ control_dependency_cache = XRESIZEVEC (bitmap_head, control_dependency_cache,
+ luid);
if (current_sched_info->flags & DO_SPECULATION)
spec_dependency_cache = XRESIZEVEC (bitmap_head, spec_dependency_cache,
@@ -3776,6 +3929,7 @@ extend_dependency_caches (int n, bool create_p)
bitmap_initialize (&true_dependency_cache[i], 0);
bitmap_initialize (&output_dependency_cache[i], 0);
bitmap_initialize (&anti_dependency_cache[i], 0);
+ bitmap_initialize (&control_dependency_cache[i], 0);
if (current_sched_info->flags & DO_SPECULATION)
bitmap_initialize (&spec_dependency_cache[i], 0);
@@ -3805,6 +3959,7 @@ sched_deps_finish (void)
bitmap_clear (&true_dependency_cache[i]);
bitmap_clear (&output_dependency_cache[i]);
bitmap_clear (&anti_dependency_cache[i]);
+ bitmap_clear (&control_dependency_cache[i]);
if (sched_deps_info->generate_spec_deps)
bitmap_clear (&spec_dependency_cache[i]);
@@ -3815,6 +3970,8 @@ sched_deps_finish (void)
output_dependency_cache = NULL;
free (anti_dependency_cache);
anti_dependency_cache = NULL;
+ free (control_dependency_cache);
+ control_dependency_cache = NULL;
if (sched_deps_info->generate_spec_deps)
{
@@ -3836,6 +3993,7 @@ init_deps_global (void)
reg_pending_sets = ALLOC_REG_SET (&reg_obstack);
reg_pending_clobbers = ALLOC_REG_SET (&reg_obstack);
reg_pending_uses = ALLOC_REG_SET (&reg_obstack);
+ reg_pending_control_uses = ALLOC_REG_SET (&reg_obstack);
reg_pending_barrier = NOT_A_BARRIER;
if (!sel_sched_p () || sched_emulate_haifa_p)
@@ -3860,6 +4018,7 @@ finish_deps_global (void)
FREE_REG_SET (reg_pending_sets);
FREE_REG_SET (reg_pending_clobbers);
FREE_REG_SET (reg_pending_uses);
+ FREE_REG_SET (reg_pending_control_uses);
}
/* Estimate the weakness of dependence between MEM1 and MEM2. */
@@ -3893,8 +4052,8 @@ estimate_dep_weak (rtx mem1, rtx mem2)
/* Add or update backward dependence between INSN and ELEM with type DEP_TYPE.
This function can handle same INSN and ELEM (INSN == ELEM).
It is a convenience wrapper. */
-void
-add_dependence (rtx insn, rtx elem, enum reg_note dep_type)
+static void
+add_dependence_1 (rtx insn, rtx elem, enum reg_note dep_type)
{
ds_t ds;
bool internal;
@@ -3903,6 +4062,8 @@ add_dependence (rtx insn, rtx elem, enum reg_note dep_type)
ds = DEP_TRUE;
else if (dep_type == REG_DEP_OUTPUT)
ds = DEP_OUTPUT;
+ else if (dep_type == REG_DEP_CONTROL)
+ ds = DEP_CONTROL;
else
{
gcc_assert (dep_type == REG_DEP_ANTI);
@@ -4169,10 +4330,12 @@ dump_ds (FILE *f, ds_t s)
if (s & DEP_TRUE)
fprintf (f, "DEP_TRUE; ");
- if (s & DEP_ANTI)
- fprintf (f, "DEP_ANTI; ");
if (s & DEP_OUTPUT)
fprintf (f, "DEP_OUTPUT; ");
+ if (s & DEP_ANTI)
+ fprintf (f, "DEP_ANTI; ");
+ if (s & DEP_CONTROL)
+ fprintf (f, "DEP_CONTROL; ");
fprintf (f, "}");
}
@@ -4207,10 +4370,13 @@ check_dep (dep_t dep, bool relaxed_p)
else if (dt == REG_DEP_OUTPUT)
gcc_assert ((ds & DEP_OUTPUT)
&& !(ds & DEP_TRUE));
- else
- gcc_assert ((dt == REG_DEP_ANTI)
- && (ds & DEP_ANTI)
+ else if (dt == REG_DEP_ANTI)
+ gcc_assert ((ds & DEP_ANTI)
&& !(ds & (DEP_OUTPUT | DEP_TRUE)));
+ else
+ gcc_assert (dt == REG_DEP_CONTROL
+ && (ds & DEP_CONTROL)
+ && !(ds & (DEP_OUTPUT | DEP_ANTI | DEP_TRUE)));
/* HARD_DEP can not appear in dep_status of a link. */
gcc_assert (!(ds & HARD_DEP));
diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c
index 5ec1de017b4..9a28e2bfc4b 100644
--- a/gcc/sched-ebb.c
+++ b/gcc/sched-ebb.c
@@ -431,32 +431,23 @@ add_deps_for_risky_insns (rtx head, rtx tail)
rank. */
if (! sched_insns_conditions_mutex_p (insn, prev))
{
- dep_def _dep, *dep = &_dep;
-
- init_dep (dep, prev, insn, REG_DEP_ANTI);
-
- if (!(current_sched_info->flags & USE_DEPS_LIST))
+ if ((current_sched_info->flags & DO_SPECULATION)
+ && (spec_info->mask & BEGIN_CONTROL))
{
- enum DEPS_ADJUST_RESULT res;
+ dep_def _dep, *dep = &_dep;
- res = sd_add_or_update_dep (dep, false);
+ init_dep (dep, prev, insn, REG_DEP_ANTI);
- /* We can't change an existing dependency with
- DEP_ANTI. */
- gcc_assert (res != DEP_CHANGED);
- }
- else
- {
- if ((current_sched_info->flags & DO_SPECULATION)
- && (spec_info->mask & BEGIN_CONTROL))
- DEP_STATUS (dep) = set_dep_weak (DEP_ANTI, BEGIN_CONTROL,
- MAX_DEP_WEAK);
+ if (current_sched_info->flags & USE_DEPS_LIST)
+ {
+ DEP_STATUS (dep) = set_dep_weak (DEP_ANTI, BEGIN_CONTROL,
+ MAX_DEP_WEAK);
+ }
sd_add_or_update_dep (dep, false);
-
- /* Dep_status could have been changed.
- No assertion here. */
}
+ else
+ add_dependence (insn, prev, REG_DEP_CONTROL);
}
break;
diff --git a/gcc/sched-int.h b/gcc/sched-int.h
index 02e8c6055eb..9b29ea158cb 100644
--- a/gcc/sched-int.h
+++ b/gcc/sched-int.h
@@ -424,6 +424,7 @@ struct deps_reg
rtx uses;
rtx sets;
rtx implicit_sets;
+ rtx control_uses;
rtx clobbers;
int uses_length;
int clobbers_length;
@@ -453,6 +454,9 @@ struct deps_desc
/* An EXPR_LIST containing all MEM rtx's which are pending writes. */
rtx pending_write_mems;
+ /* An INSN_LIST containing all jump insns. */
+ rtx pending_jump_insns;
+
/* We must prevent the above lists from ever growing too large since
the number of dependencies produced is at least O(N*N),
and execution time is at least O(4*N*N), as a function of the
@@ -464,8 +468,9 @@ struct deps_desc
/* Indicates the length of the pending_write list. */
int pending_write_list_length;
- /* Length of the pending memory flush list. Large functions with no
- calls may build up extremely large lists. */
+ /* Length of the pending memory flush list plus the length of the pending
+ jump insn list. Large functions with no calls may build up extremely
+ large lists. */
int pending_flush_length;
/* The last insn upon which all memory references must depend.
@@ -699,6 +704,10 @@ struct _haifa_deps_insn_data
condition that has been clobbered by a subsequent insn. */
rtx cond;
+ /* For a conditional insn, a list of insns that could set the condition
+ register. Used when generating control dependencies. */
+ rtx cond_deps;
+
/* True if the condition in 'cond' should be reversed to get the actual
condition. */
unsigned int reverse_cond : 1;
@@ -799,6 +808,10 @@ struct _haifa_insn_data
real insns following them. */
unsigned int shadow_p : 1;
+ /* Used internally in unschedule_insns_until to mark insns that must have
+ their TODO_SPEC recomputed. */
+ unsigned int must_recompute_spec : 1;
+
/* '> 0' if priority is valid,
'== 0' if priority was not yet computed,
'< 0' if priority in invalid and should be recomputed. */
@@ -819,6 +832,10 @@ struct _haifa_insn_data
/* Original pattern of the instruction. */
rtx orig_pat;
+ /* For insns with DEP_CONTROL dependencies, the predicated pattern if it
+ was ever successfully constructed. */
+ rtx predicated_pat;
+
/* The following array contains info how the insn increases register
pressure. There is an element for each cover class of pseudos
referenced in insns. */
@@ -880,6 +897,7 @@ extern VEC(haifa_deps_insn_data_def, heap) *h_d_i_d;
#define INSN_SPEC_BACK_DEPS(INSN) (HDID (INSN)->spec_back_deps)
#define INSN_CACHED_COND(INSN) (HDID (INSN)->cond)
#define INSN_REVERSE_COND(INSN) (HDID (INSN)->reverse_cond)
+#define INSN_COND_DEPS(INSN) (HDID (INSN)->cond_deps)
#define CANT_MOVE(INSN) (HDID (INSN)->cant_move)
#define CANT_MOVE_BY_LUID(LUID) (VEC_index (haifa_deps_insn_data_def, h_d_i_d, \
LUID)->cant_move)
@@ -893,6 +911,7 @@ extern VEC(haifa_deps_insn_data_def, heap) *h_d_i_d;
#define CHECK_SPEC(INSN) (HID (INSN)->check_spec)
#define RECOVERY_BLOCK(INSN) (HID (INSN)->recovery_block)
#define ORIG_PAT(INSN) (HID (INSN)->orig_pat)
+#define PREDICATED_PAT(INSN) (HID (INSN)->predicated_pat)
/* INSN is either a simple or a branchy speculation check. */
#define IS_SPECULATION_CHECK_P(INSN) \
@@ -932,10 +951,11 @@ extern VEC(haifa_deps_insn_data_def, heap) *h_d_i_d;
/* We exclude sign bit. */
#define BITS_PER_DEP_STATUS (HOST_BITS_PER_INT - 1)
-/* First '4' stands for 3 dep type bits and HARD_DEP bit.
+/* First '6' stands for 4 dep type bits and the HARD_DEP and DEP_CANCELLED
+ bits.
Second '4' stands for BEGIN_{DATA, CONTROL}, BE_IN_{DATA, CONTROL}
dep weakness. */
-#define BITS_PER_DEP_WEAK ((BITS_PER_DEP_STATUS - 4) / 4)
+#define BITS_PER_DEP_WEAK ((BITS_PER_DEP_STATUS - 6) / 4)
/* Mask of speculative weakness in dep_status. */
#define DEP_WEAK_MASK ((1 << BITS_PER_DEP_WEAK) - 1)
@@ -1009,13 +1029,16 @@ enum SPEC_TYPES_OFFSETS {
#define DEP_TRUE (((ds_t) 1) << (BE_IN_CONTROL_BITS_OFFSET + BITS_PER_DEP_WEAK))
#define DEP_OUTPUT (DEP_TRUE << 1)
#define DEP_ANTI (DEP_OUTPUT << 1)
+#define DEP_CONTROL (DEP_ANTI << 1)
-#define DEP_TYPES (DEP_TRUE | DEP_OUTPUT | DEP_ANTI)
+#define DEP_TYPES (DEP_TRUE | DEP_OUTPUT | DEP_ANTI | DEP_CONTROL)
/* Instruction has non-speculative dependence. This bit represents the
property of an instruction - not the one of a dependence.
Therefore, it can appear only in TODO_SPEC field of an instruction. */
-#define HARD_DEP (DEP_ANTI << 1)
+#define HARD_DEP (DEP_CONTROL << 1)
+
+#define DEP_CANCELLED (HARD_DEP << 1)
/* This represents the results of calling sched-deps.c functions,
which modify dependencies. */
@@ -1041,7 +1064,8 @@ enum SCHED_FLAGS {
Requires USE_DEPS_LIST set. */
DO_SPECULATION = USE_DEPS_LIST << 1,
DO_BACKTRACKING = DO_SPECULATION << 1,
- SCHED_RGN = DO_BACKTRACKING << 1,
+ DO_PREDICATION = DO_BACKTRACKING << 1,
+ SCHED_RGN = DO_PREDICATION << 1,
SCHED_EBB = SCHED_RGN << 1,
/* Scheduler can possibly create new basic blocks. Used for assertions. */
NEW_BBS = SCHED_EBB << 1,
@@ -1202,6 +1226,7 @@ extern struct sched_deps_info_def *sched_deps_info;
/* Functions in sched-deps.c. */
+extern rtx sched_get_reverse_condition_uncached (const_rtx);
extern bool sched_insns_conditions_mutex_p (const_rtx, const_rtx);
extern bool sched_insn_is_legitimate_for_speculation_p (const_rtx, ds_t);
extern void add_dependence (rtx, rtx, enum reg_note);
@@ -1337,6 +1362,7 @@ extern bool sched_no_dce;
extern void set_modulo_params (int, int, int, int);
extern void record_delay_slot_pair (rtx, rtx, int, int);
+extern rtx real_insn_for_shadow (rtx);
extern void discard_delay_pairs_above (int);
extern void free_delay_pairs (void);
extern void add_delay_dependencies (rtx);
@@ -1527,3 +1553,4 @@ extern void print_pattern (char *, const_rtx, int);
extern void print_value (char *, const_rtx, int);
#endif /* GCC_SCHED_INT_H */
+
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index 9208ef28ae6..8e948880999 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -234,7 +234,6 @@ static void add_branch_dependences (rtx, rtx);
static void compute_block_dependences (int);
static void schedule_region (int);
-static rtx concat_INSN_LIST (rtx, rtx);
static void concat_insn_mem_list (rtx, rtx, rtx *, rtx *);
static void propagate_deps (int, struct deps_desc *);
static void free_pending_lists (void);
@@ -2552,20 +2551,6 @@ add_branch_dependences (rtx head, rtx tail)
static struct deps_desc *bb_deps;
-/* Duplicate the INSN_LIST elements of COPY and prepend them to OLD. */
-
-static rtx
-concat_INSN_LIST (rtx copy, rtx old)
-{
- rtx new_rtx = old;
- for (; copy ; copy = XEXP (copy, 1))
- {
- new_rtx = alloc_INSN_LIST (XEXP (copy, 0), new_rtx);
- PUT_REG_NOTE_KIND (new_rtx, REG_NOTE_KIND (copy));
- }
- return new_rtx;
-}
-
static void
concat_insn_mem_list (rtx copy_insns, rtx copy_mems, rtx *old_insns_p,
rtx *old_mems_p)
@@ -2619,6 +2604,9 @@ deps_join (struct deps_desc *succ_deps, struct deps_desc *pred_deps)
&succ_deps->pending_write_insns,
&succ_deps->pending_write_mems);
+ succ_deps->pending_jump_insns
+ = concat_INSN_LIST (pred_deps->pending_jump_insns,
+ succ_deps->pending_jump_insns);
succ_deps->last_pending_memory_flush
= concat_INSN_LIST (pred_deps->last_pending_memory_flush,
succ_deps->last_pending_memory_flush);
@@ -2670,12 +2658,14 @@ propagate_deps (int bb, struct deps_desc *pred_deps)
bb_deps[bb].pending_read_mems = pred_deps->pending_read_mems;
bb_deps[bb].pending_write_insns = pred_deps->pending_write_insns;
bb_deps[bb].pending_write_mems = pred_deps->pending_write_mems;
+ bb_deps[bb].pending_jump_insns = pred_deps->pending_jump_insns;
/* Can't allow these to be freed twice. */
pred_deps->pending_read_insns = 0;
pred_deps->pending_read_mems = 0;
pred_deps->pending_write_insns = 0;
pred_deps->pending_write_mems = 0;
+ pred_deps->pending_jump_insns = 0;
}
/* Compute dependences inside bb. In a multiple blocks region:
@@ -2754,6 +2744,7 @@ free_pending_lists (void)
free_INSN_LIST_list (&bb_deps[bb].pending_write_insns);
free_EXPR_LIST_list (&bb_deps[bb].pending_read_mems);
free_EXPR_LIST_list (&bb_deps[bb].pending_write_mems);
+ free_INSN_LIST_list (&bb_deps[bb].pending_jump_insns);
}
}
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index 4878460f882..dacee0b9e9b 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -1745,6 +1745,11 @@ update_target_availability (expr_t to, expr_t from, insn_t split_point)
else
EXPR_TARGET_AVAILABLE (to) = -1;
}
+ else if (EXPR_TARGET_AVAILABLE (from) == 0
+ && EXPR_LHS (from)
+ && REG_P (EXPR_LHS (from))
+ && REGNO (EXPR_LHS (to)) != REGNO (EXPR_LHS (from)))
+ EXPR_TARGET_AVAILABLE (to) = -1;
else
EXPR_TARGET_AVAILABLE (to) &= EXPR_TARGET_AVAILABLE (from);
}
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index f11faca740a..2af01aea99e 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -813,18 +813,12 @@ count_occurrences_1 (rtx *cur_rtx, void *arg)
{
rtx_search_arg_p p = (rtx_search_arg_p) arg;
- /* The last param FOR_GCSE is true, because otherwise it performs excessive
- substitutions like
- r8 = r33
- r16 = r33
- for the last insn it presumes r33 equivalent to r8, so it changes it to
- r33. Actually, there's no change, but it spoils debugging. */
- if (exp_equiv_p (*cur_rtx, p->x, 0, true))
- {
- /* Bail out if we occupy more than one register. */
- if (REG_P (*cur_rtx)
- && HARD_REGISTER_P (*cur_rtx)
- && hard_regno_nregs[REGNO(*cur_rtx)][GET_MODE (*cur_rtx)] > 1)
+ if (REG_P (*cur_rtx) && REGNO (*cur_rtx) == REGNO (p->x))
+ {
+ /* Bail out if mode is different or more than one register is used. */
+ if (GET_MODE (*cur_rtx) != GET_MODE (p->x)
+ || (HARD_REGISTER_P (*cur_rtx)
+ && hard_regno_nregs[REGNO(*cur_rtx)][GET_MODE (*cur_rtx)] > 1))
{
p->n = 0;
return 1;
@@ -837,7 +831,6 @@ count_occurrences_1 (rtx *cur_rtx, void *arg)
}
if (GET_CODE (*cur_rtx) == SUBREG
- && REG_P (p->x)
&& (!REG_P (SUBREG_REG (*cur_rtx))
|| REGNO (SUBREG_REG (*cur_rtx)) == REGNO (p->x)))
{
@@ -859,6 +852,7 @@ count_occurrences_equiv (rtx what, rtx where)
{
struct rtx_search_arg arg;
+ gcc_assert (REG_P (what));
arg.x = what;
arg.n = 0;
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 13016169859..ab888a96db8 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -4352,10 +4352,20 @@ simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode,
{
rtx x = XEXP (op0, 0);
rtx c = XEXP (op0, 1);
+ enum rtx_code invcode = op0code == PLUS ? MINUS : PLUS;
+ rtx tem = simplify_gen_binary (invcode, cmp_mode, op1, c);
+
+ /* Detect an infinite recursive condition, where we oscillate at this
+ simplification case between:
+ A + B == C <---> C - B == A,
+ where A, B, and C are all constants with non-simplifiable expressions,
+ usually SYMBOL_REFs. */
+ if (GET_CODE (tem) == invcode
+ && CONSTANT_P (x)
+ && rtx_equal_p (c, XEXP (tem, 1)))
+ return NULL_RTX;
- c = simplify_gen_binary (op0code == PLUS ? MINUS : PLUS,
- cmp_mode, op1, c);
- return simplify_gen_relational (code, mode, cmp_mode, x, c);
+ return simplify_gen_relational (code, mode, cmp_mode, x, tem);
}
/* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is
diff --git a/gcc/streamer-hooks.h b/gcc/streamer-hooks.h
index b4c65629e47..0c1d483ac6a 100644
--- a/gcc/streamer-hooks.h
+++ b/gcc/streamer-hooks.h
@@ -51,6 +51,16 @@ struct streamer_hooks {
and descriptors needed by the unpickling routines. It returns the
tree instantiated from the stream. */
tree (*read_tree) (struct lto_input_block *, struct data_in *);
+
+ /* [OPT] Called by lto_input_location to retrieve the source location of the
+ tree currently being read. If this hook returns NULL, lto_input_location
+ defaults to calling lto_input_location_bitpack. */
+ location_t (*input_location) (struct lto_input_block *, struct data_in *);
+
+ /* [OPT] Called by lto_output_location to write the source_location of the
+ tree currently being written. If this hook returns NULL,
+ lto_output_location defaults to calling lto_output_location_bitpack. */
+ void (*output_location) (struct output_block *, location_t);
};
#define stream_write_tree(OB, EXPR, REF_P) \
diff --git a/gcc/system.h b/gcc/system.h
index e86f7ba7a4f..7c7d07ea3ee 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -868,7 +868,8 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
FUNCTION_INCOMING_ARG IRA_COVER_CLASSES TARGET_VERSION \
MACHINE_TYPE TARGET_HAS_TARGETCM ASM_OUTPUT_BSS \
SETJMP_VIA_SAVE_AREA FORBIDDEN_INC_DEC_CLASSES \
- PREFERRED_OUTPUT_RELOAD_CLASS
+ PREFERRED_OUTPUT_RELOAD_CLASS SYSTEM_INCLUDE_DIR \
+ STANDARD_INCLUDE_DIR STANDARD_INCLUDE_COMPONENT
/* Hooks that are no longer used. */
#pragma GCC poison LANG_HOOKS_FUNCTION_MARK LANG_HOOKS_FUNCTION_FREE \
diff --git a/gcc/target.def b/gcc/target.def
index c3bec0e0391..f89bb519369 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -985,18 +985,13 @@ DEFHOOK
bool, (const_tree type, bool is_packed),
default_builtin_vector_alignment_reachable)
-/* Target builtin that implements vector permute. */
+/* Return true if a vector created for vec_perm_const is valid.
+ A NULL indicates that all constants are valid permutations. */
DEFHOOK
-(builtin_vec_perm,
+(vec_perm_const_ok,
"",
- tree, (tree type, tree *mask_element_type), NULL)
-
-/* Return true if a vector created for builtin_vec_perm is valid. */
-DEFHOOK
-(builtin_vec_perm_ok,
- "",
- bool, (tree vec_type, tree mask),
- hook_bool_tree_tree_true)
+ bool, (enum machine_mode, const unsigned char *sel),
+ NULL)
/* Return true if the target supports misaligned store/load of a
specific factor denoted in the third parameter. The last parameter
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 827aa2dced8..92b5bef129b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,1060 @@
+2011-11-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.target/sparc/20111102-1.c: New test.
+
+2011-11-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50956
+ * g++.dg/warn/Wcast-qual2.C: New.
+
+2011-11-02 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50763
+ * g++.dg/pr50763-3.C: New test.
+
+2011-11-02 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50672
+ * g++.dg/pr50672.C: New test.
+
+2011-11-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/avx-cvt-2.c (dg-options): Add -mtune=generic.
+ * gcc.target/i386/avx2-cvt-2.c (dg-options): Ditto.
+ * gcc.target/i386/sse2-cvt-2.c (dg-options): Ditto.
+
+ * gcc.target/i386/vectorize4-avx.c (scan-assembler): Remove xfail.
+
+2011-11-02 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50902
+ * gcc.dg/torture/pr50902.c: New testcase.
+
+2010-11-02 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50890
+ * gcc.dg/torture/pr50890.c: New testcase.
+
+2011-11-01 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/44277
+ * g++.dg/warn/Wzero-as-null-pointer-constant-1.C: New.
+ * g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C: Likewise.
+
+2011-11-01 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50908
+ * gcc.dg/pr50908.c: New test.
+ * gcc.dg/pr50908-2.c: Same.
+ * gcc.dg/pr50908-3.c: Same.
+
+2011-11-01 Ira Rosen <ira.rosen@linaro.org>
+
+ * gcc.dg/vect/no-scevccp-outer-6-global.c: Expect to vectorize
+ the outer loop. Remove comment. Don't check for widen-mult.
+
+2011-10-31 Martin Jambor <mjambor@suse.cz>
+
+ * gcc.dg/ipa/ipcp-4.c: New test.
+
+2011-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/vshift-3.c: New test.
+ * gcc.dg/vshift-4.c: New test.
+ * gcc.dg/vshift-5.c: New test.
+
+2011-10-31 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * gfortran.dg/inquire_5.f90: Update testcase to match the standard
+ and current implementation.
+
+2011-10-31 Paul Brook <paul@codesourcery.com>
+
+ * gcc.dg/constructor-1.c: New test.
+
+2011-10-30 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/50753
+ * gfortran.dg/dshift_3.f90: New test.
+
+2011-10-30 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
+
+ * gcc.dg/scal-to-vec2.c (dg-options): Add -fno-common to options on
+ hppa*-*-hpux*.
+ * gcc.dg/torture/vshuf-v8hi.c: Likewise.
+ * gcc.dg/torture/vshuf-v4si.c: Likewise.
+ * gcc.dg/torture/vshuf-v8si.c: Likewise.
+ * gcc.dg/torture/vshuf-v32qi.c: Likewise.
+ * gcc.dg/torture/vshuf-v4di.c: Likewise.
+ * gcc.dg/torture/vshuf-v2df.c: Likewise.
+ * gcc.dg/torture/vshuf-v16qi.c: Likewise.
+ * gcc.dg/torture/vshuf-v4sf.c: Likewise.
+ * gcc.dg/torture/vshuf-v8sf.c: Likewise.
+ * gcc.dg/torture/vshuf-v2di.c: Likewise.
+ * gcc.dg/torture/vshuf-v16hi.c: Likewise.
+ * gcc.dg/torture/vshuf-v4df.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-fre-31.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-fre-33.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-fre-34.c: Likewise.
+ * gcc.dg/vector-compare-2.c: Likewise.
+
+2011-10-29 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50901
+ * g++.dg/cpp0x/pr50901.C: New.
+
+2011-10-29 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/fma-check.h (main): Use return 0 instead of exit (0).
+ * gcc.target/i386/fma4-check.h (main): Ditto.
+ * gcc.target/i386/xop-check.h (main): Ditto.
+
+2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ Revert:
+ 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50864
+ * g++.dg/template/crash109.C: New.
+
+2011-10-28 Jason Merrill <jason@redhat.com>
+
+ * c-c++-common/dfp/pr33466.c: Adjust for user-defined literals.
+
+2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50864
+ * g++.dg/template/crash109.C: New.
+
+2011-10-28 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * gfortran.dg/nearest_5.f90: New test.
+
+2011-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/vshift-1.c: New test.
+ * gcc.dg/vshift-2.c: New test.
+ * gcc.target/i386/xop-vshift-1.c: New test.
+ * gcc.target/i386/xop-vshift-2.c: New test.
+ * gcc.target/i386/avx2-vshift-1.c: New test.
+
+2011-10-28 Chung-Lin Tang <cltang@codesourcery.com>
+
+ PR rtl-optimization/49720
+ * g++.dg/torture/pr49720.C: New test.
+
+2011-10-27 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/setcc-3.c: New test.
+
+2011-10-27 Roberto Agostino Vitillo <ravitillo@lbl.gov>
+
+ PR c++/30066
+ * g++.dg/ext/visibility/fvisibility-inlines-hidden-4.C: New test.
+
+2011-10-27 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/sse2-cvt-1.c: New test.
+ * gcc.target/i386/sse2-cvt-2.c: New test.
+ * gcc.target/i386/avx-cvt-1.c: New test.
+ * gcc.target/i386/avx-cvt-2.c: New test.
+ * gcc.target/i386/avx2-cvt-1.c: New test.
+ * gcc.target/i386/avx2-cvt-2.c: New test.
+
+2011-10-27 Martin Jambor <mjambor@suse.cz>
+
+ * g++.dg/tree-ssa/pr45605.C: Scan fre1 dump and unxfail.
+
+2011-10-27 Uros Bizjak <ubizjak@gmail.com>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR target/50875
+ * gfortran.dg/pr50875.f90: New test.
+
+2011-10-26 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/fmaf-1.c: New test.
+
+ * gcc.target/sparc/setcc-1.c: New test.
+ * gcc.target/sparc/setcc-2.c: New test.
+
+2011-10-26 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/tls/thr-cse-1.c: For i?86-*-mingw*, check for multiple calls.
+
+2011-10-26 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/graphite/run-id-1.c: Pass -Wl,--stack,12582912 option for
+ Windows targets.
+
+2011-10-26 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.target/i386/pr37843-4.c: Allow for leading underscores on
+ symbol names.
+
+2011-10-26 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.target/i386/pad-4.c: Skip for Windows targets.
+
+2011-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/discr1.ads: New test.
+ * gnat.dg/specs/discr1_pkg.ads: New helper.
+
+2011-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/unchecked_union.ads: Rename to...
+ * gnat.dg/specs/unchecked_union1.ads: ...this.
+ * gnat.dg/specs/unchecked_union2.ads: New test.
+
+2011-10-26 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/atomic1.ads: New test.
+
+2011-10-26 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++11 user-defined literals.
+ * g++.dg/cpp0x/udlit-addr.C: New.
+ * g++.dg/cpp0x/udlit-args.C: New.
+ * g++.dg/cpp0x/udlit-args-neg.C: New.
+ * g++.dg/cpp0x/udlit-clink-neg.C: New.
+ * g++.dg/cpp0x/udlit-concat.C: New.
+ * g++.dg/cpp0x/udlit-concat-neg.C: New.
+ * g++.dg/cpp0x/udlit-constexpr.C: New.
+ * g++.dg/cpp0x/udlit-cpp98-neg.C: New.
+ * g++.dg/cpp0x/udlit-declare-neg.C: New.
+ * g++.dg/cpp0x/udlit-friend.C: New.
+ * g++.dg/cpp0x/udlit-general.C: New.
+ * g++.dg/cpp0x/udlit-inline.C: New.
+ * g++.dg/cpp0x/udlit-linkage-neg.C: New.
+ * g++.dg/cpp0x/udlit-member-neg.C: New.
+ * g++.dg/cpp0x/udlit-namespace.C: New.
+ * g++.dg/cpp0x/udlit-nofunc-neg.C: New.
+ * g++.dg/cpp0x/udlit-nonempty-str-neg.C: New.
+ * g++.dg/cpp0x/udlit-nospace-neg.C: New.
+ * g++.dg/cpp0x/udlit-nosuffix-neg.C: New.
+ * g++.dg/cpp0x/udlit-nounder-neg.C: New.
+ * g++.dg/cpp0x/udlit-operator-neg.C: New.
+ * g++.dg/cpp0x/udlit-raw-str.C: New.
+ * g++.dg/cpp0x/udlit-shadow-neg.C: New.
+ * g++.dg/cpp0x/udlit-suffix-neg.C: New.
+ * g++.dg/cpp0x/udlit-systemheader.C: New.
+ * g++.dg/cpp0x/udlit-template.C: New.
+ * g++.dg/cpp0x/udlit-tmpl-arg.C: New.
+ * g++.dg/cpp0x/udlit-tmpl-arg-neg.C: New.
+ * g++.dg/cpp0x/udlit-tmpl-parms.C: New.
+ * g++.dg/cpp0x/udlit-tmpl-parms-neg.C: New.
+ * g++.dg/cpp0x/udlit_system_header: New.
+
+2011-10-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50870
+ * g++.dg/cpp0x/decltype34.C: New.
+
+2011-10-26 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.c-torture/unsorted/HIcmp.c: Fix unaligned pointer.
+ * gcc.c-torture/unsorted/HIset.c: Same.
+ * gcc.c-torture/unsorted/SIcmp.c: Same.
+ * gcc.c-torture/unsorted/SIset.c: Same.
+ * gcc.c-torture/unsorted/SFset.c: Same.
+ * gcc.c-torture/unsorted/UHIcmp.c: Same.
+ * gcc.c-torture/unsorted/USIcmp.c: Same.
+ * gcc.c-torture/unsorted/DFcmp.c: Same.
+
+2011-10-26 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/avx2-i32gatherd-1.c: Adjust scan-assembler regex
+ to work also with -masm=intel and additionally test the xmm vs. ymm
+ register type combination on mask/dest and in vsib.
+ * gcc.target/i386/avx2-i32gatherd256-1.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherd256-3.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherd-3.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherpd-1.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherpd256-1.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherpd256-3.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherpd-3.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherps-1.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherps256-1.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherps256-3.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherps-3.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherq-1.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherq256-1.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherq256-3.c: Likewise.
+ * gcc.target/i386/avx2-i32gatherq-3.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherd-1.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherd256-1.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherd256-3.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherd-3.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherpd-1.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherpd256-1.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherpd256-3.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherpd-3.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherps-1.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherps256-1.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherps256-3.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherps-3.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherq-1.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherq256-1.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherq256-3.c: Likewise.
+ * gcc.target/i386/avx2-i64gatherq-3.c: Likewise.
+
+2011-10-26 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50763
+ * gcc.dg/pr50763-2.c: New test.
+
+2011-10-25 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/format/ms_c90-printf-1.c, gcc.dg/format/ms_c90-scanf-1.c:
+ Update expected messages.
+
+2011-10-25 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/vect/slp-multitypes-2.c: Do not XFAIL on SPARC 32-bit.
+
+2011-10-25 Jason Merrill <jason@redhat.com>
+
+ PR c++/50866
+ * g++.dg/init/aggr7.C: New.
+
+ PR c++/49996
+ * g++.dg/cpp0x/initlist59.C: New.
+
+2011-10-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50858
+ * g++.dg/overload/operator5.C: New.
+
+2011-10-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50861
+ * g++.dg/template/crash108.C: New.
+
+2011-10-25 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50596
+ * gcc.dg/vect/vect-cond-10.c: New test.
+
+2011-10-24 Joey Ye <joey.ye@arm.com>
+
+ * gcc.target/arm/pr42575.c: Remove architecture option.
+
+2011-10-24 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/vis3move-1.c: New test.
+ * gcc.target/sparc/vis3move-2.c: New test.
+ * gcc.target/sparc/vis3move-3.c: New test.
+
+2011-10-24 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
+
+ * gcc.dg/strlenopt-22.c: New testcase.
+ * gcc.dg/strlenopt-4.c: Change scan value for s390(x).
+
+2011-10-24 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/sse-5.c (dg-options): Add -mno-sse.
+ Remove -march=i386.
+ (dg-skip-if): Remove.
+ * gcc.target/i386/funcspec-1.c: Ditto.
+ * gcc.target/i386/funcspec-3.c (dg-options): Add -mno-sse3.
+
+2011-10-24 Richard Guenther <rguenther@suse.de>
+
+ * gcc.dg/vect/vect-bool-1.c: New testcase.
+
+2011-10-24 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50838
+ * gcc.dg/torture/pr50838.c: New testcase.
+
+2011-10-24 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50730
+ * gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c: New test.
+ * gcc.dg/vect/vect.exp: Run no-tree-sra-bb-slp* tests with
+ -fno-tree-sra and SLP flags.
+
+2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50841
+ Revert:
+ 2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50810
+ * g++.dg/cpp0x/warn_cxx0x2.C: New.
+ * g++.dg/cpp0x/warn_cxx0x3.C: Likewise.
+
+2011-10-23 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50810
+ * g++.dg/cpp0x/warn_cxx0x2.C: New.
+ * g++.dg/cpp0x/warn_cxx0x3.C: Likewise.
+
+2011-10-23 Tom de Vries <tom@codesourcery.com>
+
+ PR tree-optimization/50763
+ * gcc.dg/pr50763.c: New test.
+
+2011-10-23 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/50788
+ * gcc.target/i386/pr50788.c: New test.
+
+2011-10-23 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50819
+ * g++.dg/vect/vect.exp: Set target dependent flags for slp-* tests.
+ * g++.dg/vect/slp-pr50819.cc: New test.
+
+2011-10-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/45385
+ * g++.dg/warn/Wconversion4.C: New.
+
+2011-10-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/50813
+ * gcc.dg/torture/vshuf-32.inc: Add broadcast permutation
+ from element other than first and reverse permutation.
+ * gcc.dg/torture/vshuf-16.inc: Likewise.
+ * gcc.dg/torture/vshuf-8.inc: Likewise.
+ * gcc.dg/torture/vshuf-4.inc: Likewise.
+
+2011-10-21 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/31423
+ * g++.dg/parse/error43.C: New.
+ * g++.dg/parse/error44.C: Likewise.
+
+2011-10-21 H.J. Lu <hongjiu.lu@intel.com>
+ Kirill Yukhin <kirill.yukhin@intel.com>
+
+ PR target/50740
+ * gcc.target/i386/avx2-check.h (main): Check CPUID level correctly.
+ * gcc.target/i386/bmi2-check.h: Ditto.
+
+2011-10-21 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ PR c++/50811
+ * g++.dg/cpp0x/override2.C: Add test.
+
+2011-10-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * lib/gcc-dg.exp (GCC_UNDER_TEST): Set before calling
+ check_linker_plugin_available.
+
+2011-10-21 Kai Tietz <ktietz@redhat.com>
+
+ * gcc.target/i386/branch-cost1.c: New test.
+ * gcc.target/i386/branch-cost2.c: New test.
+ * gcc.target/i386/branch-cost3.c: New test.
+ * gcc.target/i386/branch-cost4.c: New test.
+
+2011-10-20 Steve Ellcey <sje@cup.hp.com>
+
+ * gcc.dg/vect/vect-120.c: Add vect_floatint_cvt requirement.
+
+2011-10-20 Steve Ellcey <sje@cup.hp.com>
+
+ PR testsuite/50722
+ * gcc.dg/pr49994-3.c: Skip on HP-UX.
+
+2011-10-20 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/lto/pr46940_0.c (ASMNAME, ASMNAME2, STRING): Define.
+ (_moz_foo, EXT__foo): Use ASMNAME.
+
+2011-10-20 Joseph Myers <joseph@codesourcery.com>
+
+ * lib/lto.exp (lto-execute): Use .exe suffix for test executable
+ names.
+
+2011-10-20 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ PR target/50766
+ * gcc.target/i386/pr50766.c: New test.
+
+2011-10-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/41449
+ * g++.dg/eh/partial1.C: New.
+
+2011-10-20 Richard Henderson <rth@redhat.com>
+
+ * gcc.target/i386/vperm-v2df.c, gcc.target/i386/vperm-v2di.c,
+ gcc.target/i386/vperm-v4sf-1.c, gcc.target/i386/vperm-v4sf-2.c,
+ gcc.target/i386/vperm-v4si-1.c, gcc.target/i386/vperm-v4si-2.c:
+ Use __builtin_shuffle.
+
+2011-10-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/50514
+ * gfortran.dg/ishft_3.f90: Update test.
+
+2011-10-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/50524
+ * gfortran.dg/substring_integer_index.f90: New test.
+
+2011-10-20 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ * gfortran.dg/format_string.f: New test.
+
+2011-10-20 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.dg/ipa/ipa-sra-2.c: Add dg-require-effective-target
+ non_strict_align.
+ * gcc.dg/ipa/ipa-sra-6.c: Ditto.
+
+2011-10-20 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.target/i386/pr40906-1.c, gcc.target/i386/pr40906-2.c,
+ gcc.target/i386/pr46226.c: Do not use
+ -mno-accumulate-outgoing-args.
+
+2011-10-20 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/tree-prof/val-prof-7.c: Declare bzero instead of
+ including <strings.h>.
+
+2011-10-19 Jan Hubicka <jh@suse.cz>
+
+ * lib/lto.exp (lto_init): Test slim lto and no-linker-plugin path.
+ * lib/gcc-dg.exp (check_effective_target_lto): Likewise.
+ * lib/c-torture.exp: Likewise.
+ * gcc.c-torture/execute/builtins/strstr-asm.c: Force fat LTO.
+ * gcc.c-torture/compile/sync-1.c: Likewise.
+ * gcc.c-torture/compile/sync-1.c: Likewise.
+ * gcc.c-torture/compile/sync-3.c: Likewise.
+ * gcc.dg/noncompile/invalid_asm.c: Likewise.
+ * gcc.dg/noncompile/920507-1.c: Likewise.
+ * gcc.dg/torture/pr36400.c: Likewise.
+ * g++.dg/torture/pr34850.C: Likewise.
+
+2011-10-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/source_ref1.adb: New test.
+ * gnat.dg/source_ref2.adb: Likewise.
+
+2011-10-19 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/13657
+ * g++.dg/parse/error42.C: New.
+ * g++.old-deja/g++.other/ptrmem7.C: Tweak dg-errors.
+
+2011-10-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/50793
+ * g++.dg/init/value9.C: New.
+
+2011-10-19 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.dg/torture/vshuf-32.inc: Add interleave permutations.
+ * gcc.dg/torture/vshuf-16.inc: Likewise.
+ * gcc.dg/torture/vshuf-8.inc: Likewise.
+ * gcc.dg/torture/vshuf-4.inc: Likewise.
+
+2011-10-19 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * gfortran.dg/sizeof_proc.f90: New.
+
+2011-10-19 Joseph Myers <joseph@codesourcery.com>
+
+ * g++.dg/compat/struct-layout-1_generate.c: Also pass -mno-mmx
+ -Wno-abi for i?86-*-mingw32* x86_64-*-mingw32* i?86-*-cygwin*.
+
+2011-10-19 Uros Bizjak <ubizjak@gmail.com>
+
+ PR testsuite/50796
+ * gcc.dg/plugin/plugindir?.c Update dg-prune-output.
+
+2011-10-19 Jason Merrill <jason@redhat.com>
+
+ PR c++/50787
+ * g++.dg/init/ref20.C: New.
+
+2011-10-19 Kai Tietz <ktietz@redhat.com>
+
+ PR middle-end/50795
+ * gcc.dg/tree-ssa/builtin-expect-1.c: Adjust test.
+ * gcc.dg/tree-ssa/builtin-expect-2.c: Adjust test.
+ * gcc.dg/tree-ssa/builtin-expect-3.c: Adjust test.
+ * gcc.dg/tree-ssa/builtin-expect-4.c: Adjust test.
+ * gcc.dg/tree-ssa/builtin-expect-5.c: Adjust test.
+
+2011-10-19 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/50768
+ * gcc.dg/torture/pr50768.c: New testcase.
+
+2011-10-19 Alexander Monakov <amonakov@ispras.ru>
+
+ PR rtl-optimization/50340
+ * gcc.dg/pr50340.c: New.
+
+2011-10-18 Andrew Stubbs <ams@codesourcery.com>
+
+ PR tree-optimization/50717
+
+ * gcc.dg/pr50717-1.c: New file.
+ * gcc.target/arm/wmul-12.c: Correct types.
+ * gcc.target/arm/wmul-8.c: Correct types.
+
+2011-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/50531
+ * g++.dg/cpp0x/defaulted32.C: New.
+
+ PR c++/50742
+ * g++.dg/lookup/using23.C: New.
+
+ PR c++/50500
+ * g++.dg/cpp0x/implicit12.C: New.
+ * g++.dg/cpp0x/defaulted20.C: Adjust.
+ * g++.dg/cpp0x/defaulted21.C: Adjust.
+ * g++.dg/cpp0x/implicit-copy.C: Adjust.
+ * g++.dg/cpp0x/implicit4.C: Adjust.
+ * g++.dg/cpp0x/implicit5.C: Adjust.
+ * g++.dg/cpp0x/implicit8.C: Adjust.
+ * g++.dg/cpp0x/lambda/lambda-ice2.C: Adjust.
+ * g++.dg/cpp0x/not_special.C: Adjust.
+ * g++.dg/cpp0x/rv-trivial-bug.C: Adjust.
+ * g++.dg/cpp0x/rv1n.C: Adjust.
+ * g++.dg/cpp0x/rv2n.C: Adjust.
+ * g++.dg/cpp0x/rv3n.C: Adjust.
+ * g++.dg/cpp0x/rv4n.C: Adjust.
+ * g++.dg/cpp0x/rv5n.C: Adjust.
+ * g++.dg/cpp0x/rv6n.C: Adjust.
+ * g++.dg/cpp0x/rv7n.C: Adjust.
+
+2011-10-18 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ * gcc.target/i386/avx2-vpop-check.h: New header.
+ * gcc.target/i386/avx2-vpaddd-3.c: New test.
+ * gcc.target/i386/avx2-vpaddw-3.c: Ditto.
+ * gcc.target/i386/avx2-vpaddb-3.c: Ditto.
+ * gcc.target/i386/avx2-vpaddq-3.c: Ditto.
+ * gcc.target/i386/avx2-vpand-3.c: Ditto.
+ * gcc.target/i386/avx2-vpmulld-3.c: Ditto.
+ * gcc.target/i386/avx2-vpmullw-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsrad-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsraw-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsrld-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsrlw-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsubb-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsubd-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsubq-3.c: Ditto.
+ * gcc.target/i386/avx2-vpsubw-3.c: Ditto.
+
+2011-10-18 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/50420
+ * gfortran.dg/coarray_subobject_1.f90: New test.
+ * gfortran.dg/coarray/subobject_1.f90: New test.
+
+2011-10-18 Alexander Monakov <amonakov@ispras.ru>
+
+ PR rtl-optimization/50205
+ * gcc.dg/pr50205.c: New.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50767
+ * gcc.dg/torture/pr50767.c: New testcase.
+
+2011-10-18 Julian Brown <julian@codesourcery.com>
+
+ * lib/target-supports.exp (check_effective_target_arm_unaligned): New.
+ * gcc.target/arm/unaligned-memcpy-1.c: New.
+ * gcc.target/arm/unaligned-memcpy-2.c: New.
+ * gcc.target/arm/unaligned-memcpy-3.c: New.
+ * gcc.target/arm/unaligned-memcpy-4.c: New.
+
+2011-10-18 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * gfortran.dg/iso_c_binding_class.f03: New.
+
+2011-10-18 Ira Rosen <ira.rosen@linaro.org>
+
+ * testsuite/lib/target-supports.exp
+ (check_effective_target_vect_widen_shift): New.
+ * gcc.dg/vect/vect-widen-shift-s16.c: New.
+ * gcc.dg/vect/vect-widen-shift-s8.c: New.
+ * gcc.dg/vect/vect-widen-shift-u16.c: New.
+ * gcc.dg/vect/vect-widen-shift-u8.c: New.
+
+2011-10-18 Richard Guenther <rguenther@suse.de>
+
+ * gcc.dg/torture/restrict-1.c: New testcase.
+
+2011-10-17 Michael Spertus <mike_spertus@symantec.com>
+
+ * g++.dg/ext/bases.C: New test.
+
+2011-10-17 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/fand.c: Remove __LP64__ ifdefs and expect
+ all operations to emit VIS instructions.
+ * gcc.target/sparc/fandnot.c: Likewise.
+ * gcc.target/sparc/fnot.c: Likewise.
+ * gcc.target/sparc/for.c: Likewise.
+ * gcc.target/sparc/fornot.c: Likewise.
+ * gcc.target/sparc/fxnor.c: Likewise.
+ * gcc.target/sparc/fxor.c: Likewise.
+ * gcc.target/sparc/combined-1.c: Revert change to use -O2, no longer
+ needed.
+
+2011-10-17 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.c-torture/execute/vshuf-v16hi.c: New test.
+ * gcc.dg/torture/vshuf-16.inc: New file.
+ * gcc.dg/torture/vshuf-2.inc: New file.
+ * gcc.dg/torture/vshuf-32.inc: New file.
+ * gcc.dg/torture/vshuf-4.inc: New file.
+ * gcc.dg/torture/vshuf-8.inc: New file.
+ * gcc.dg/torture/vshuf-main.inc: New file.
+ * gcc.dg/torture/vshuf-v16hi.c: New test.
+ * gcc.dg/torture/vshuf-v16qi.c: New test.
+ * gcc.dg/torture/vshuf-v2df.c: New test.
+ * gcc.dg/torture/vshuf-v2di.c: New test.
+ * gcc.dg/torture/vshuf-v2sf.c: New test.
+ * gcc.dg/torture/vshuf-v2si.c: New test.
+ * gcc.dg/torture/vshuf-v32qi.c: New test.
+ * gcc.dg/torture/vshuf-v4df.c: New test.
+ * gcc.dg/torture/vshuf-v4di.c: New test.
+ * gcc.dg/torture/vshuf-v4hi.c: New test.
+ * gcc.dg/torture/vshuf-v4sf.c: New test.
+ * gcc.dg/torture/vshuf-v4si.c: New test.
+ * gcc.dg/torture/vshuf-v8hi.c: New test.
+ * gcc.dg/torture/vshuf-v8qi.c: New test.
+ * gcc.dg/torture/vshuf-v8sf.c: New test.
+ * gcc.dg/torture/vshuf-v8si.c: New test.
+
+2011-10-17 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50746
+ * gcc.dg/vect/vect-114.c: Remove vect_hw_misalign.
+
+2011-10-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/50736
+ * g++.dg/cpp0x/lambda/lambda-capture-neg.C: New.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/44524
+ * g++.dg/parse/error41.C: New.
+ * g++.dg/parse/error20.C: Adjust.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50757
+ * g++.dg/warn/format7.C: New.
+ * obj-c++.dg/warn7.mm: Likewise.
+
+2011-10-17 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50729
+ * gcc.dg/torture/pr50729.c: New testcase.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * lib/prune.exp (prune_gcc_output): Prune output referring to
+ included files.
+ * gcc.dg/cpp/macro-exp-tracking-1.c: New test.
+ * gcc.dg/cpp/macro-exp-tracking-2.c: Likewise.
+ * gcc.dg/cpp/macro-exp-tracking-3.c: Likewise.
+ * gcc.dg/cpp/pragma-diagnostic-2.c: Likewise.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * gcc.dg/cpp/pragma-diagnostic-1.c: New test.
+
+2011-10-17 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/48489
+ * g++.dg/inherit/error5.C: New.
+
+2011-10-17 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ PR fortran/50752
+ * gfortran.dg/kind_tests_4.f90: New.
+
+2011-10-17 Ira Rosen <ira.rosen@linaro.org>
+
+ * gcc.dg/vect/vect-21.c: Expect the loops to get vectorized on
+ targets that support vector condition.
+
+2011-10-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/47023
+ * gfortran.dg/c_kind_tests_3.f03: New.
+
+2011-10-16 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50547
+ * gfortran.dg/elemental_args_check_4.f90: New.
+
+2011-10-16 Ira Rosen <ira.rosen@linaro.org>
+
+ PR tree-optimization/50727
+ * gcc.dg/vect/pr50727.c: New test.
+
+2011-10-16 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/vla-23.c: New test.
+
+2011-10-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/50596
+ * gcc.dg/vect/vect-cond-9.c: New test.
+
+2011-10-16 Ira Rosen <ira.rosen@linaro.org>
+
+ * gcc.dg/vect/bb-slp-29.c: New test.
+
+2011-10-15 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50732
+ * g++.dg/ext/is_base_of_incomplete.C: New.
+ * g++.dg/ext/is_base_of_diagnostic.C: Adjust dg-errors.
+ * g++.dg/ext/unary_trait_incomplete.C: Likewise.
+
+2011-10-15 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.target/sparc/combined-1.c: Compile at -O2.
+
+2011-10-15 Uros Bizjak <ubizjak@gmail.com>
+
+ * gcc.target/i386/fma_float_?.c (dg-prune_output): Remove.
+ (dg-options): Add -Wno-attributes.
+ * gcc.target/i386/fma_double_?.c: Ditto.
+ * gcc.target/i386/fma_run_float_?.c: Ditto.
+ * gcc.target/i386/fma_run_double_?.c: Ditto.
+ * gcc.target/i386/l_fma_float_?.c: Dtto.
+ * gcc.target/i386/l_fma_double_?.c: Ditto.
+ * gcc.target/i386/l_fma_run_float_?.c: Ditto.
+ * gcc.target/i386/l_fma_run_double_?.c: Ditto.
+
+2011-10-15 Tobias Burnus <burnus@net-b.de>
+
+ * gfortran.dg/bind_c_usage_23.f90: Change TR 29113 to TS 29113 in
+ the comments.
+ * gfortran.dg/bind_c_usage_24.f90: Ditto.
+ * gfortran.dg/rank_3.f90: Ditto.
+ * gfortran.dg/bind_c_usage_22.f90: Ditto, change -std=f2008tr to
+ -std=f2008ts in dg-options.
+ * gfortran.dg/rank_4.f90: Ditto.
+
+2011-10-15 Oleg Endo <oleg.endo@t-online.de>
+
+ PR target/49263
+ * gcc.target/sh/pr49263.c: New.
+
+2011-10-14 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/debug1.ads: Tweak.
+
+2011-10-14 Kai Tietz <ktietz@redhat.com>
+
+ * gfortran.fortran-torture/compile/logical-2.f90: New test.
+
+2011-10-14 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/sse2-mul-1.c: New test.
+ * gcc.target/i386/sse4_1-mul-1.c: New test.
+ * gcc.target/i386/avx-mul-1.c: New test.
+ * gcc.target/i386/xop-mul-1.c: New test.
+ * gcc.target/i386/avx2-mul-1.c: New test.
+
+2011-10-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/50563
+ * g++.dg/cpp0x/nsdmi-list1.C: New.
+
+ PR c++/50707
+ * g++.dg/cpp0x/nsdmi-const1.C: New.
+
+2011-10-14 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/50570
+ * gfortran.dg/pointer_intent_5.f90: New.
+
+2011-10-14 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
+
+ * gcc.target/i386/warn-vect-op-3.c: Exclude 32-bit architectures.
+ * gcc.target/i386/warn-vect-op-1.c: Ditto.
+ * gcc.target/i386/warn-vect-op-2.c: Ditto.
+
+2011-10-14 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/50718
+ * gfortran.dg/pointer_check_11.f90: New.
+ * gfortran.dg/pointer_check_12.f90: New.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/38174
+ * g++.dg/overload/operator4.C: New.
+
+2011-10-14 David Alan Gilbert <david.gilbert@linaro.org>
+
+ * gcc.dg/di-longlong64-sync-1.c: New test.
+ * gcc.dg/di-sync-multithread.c: New test.
+ * gcc.target/arm/di-longlong64-sync-withhelpers.c: New test.
+ * gcc.target/arm/di-longlong64-sync-withldrexd.c: New test.
+ * lib/target-supports.exp: (arm_arch_*_ok): Series of effective-target
+ tests for v5, v6, v6k, and v7-a, and add-options helpers.
+ (check_effective_target_arm_arm_ok): New helper.
+ (check_effective_target_sync_longlong): New helper.
+
+2011-10-14 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50723
+ * gcc.dg/torture/pr50723.c: New testcase.
+
+2011-10-14 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/17212
+ * g++.dg/warn/format6.C: New.
+ * obj-c++.dg/warn6.mm: Likewise.
+
+2011-10-13 Richard Henderson <rth@redhat.com>
+
+ * lib/target-supports.exp (check_effective_target_vect_shift_scalar):
+ Delete.
+ * gcc.dg/vect/vec-scal-opt.c: Don't test vect_shift_scalar.
+ * gcc.dg/vect/vec-scal-opt1.c: Likewise.
+ * gcc.dg/vect/vec-scal-opt2.c: Likewise.
+
+2011-10-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/50614
+ * g++.dg/cpp0x/nsdmi-template2.C: New.
+
+ PR c++/50437
+ * g++.dg/cpp0x/lambda/lambda-auto1.C: New.
+
+ PR c++/50618
+ * g++.dg/init/vbase1.C: New.
+
+2011-10-13 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.target/i386/sse4_1-phminposuw-2.c: New test.
+ * gcc.target/i386/sse4_1-phminposuw-3.c: New test.
+ * gcc.target/i386/avx-vphminposuw-2.c: New test.
+ * gcc.target/i386/avx-vphminposuw-3.c: New test.
+
+2011-10-13 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/pr50712.c: Check ia32 instead of ilp32.
+
+2011-10-13 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.dg/builtins-67.c: Guard iround and irint with HAVE_C99_RUNTIME.
+
+2011-10-13 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50712
+ * gcc.target/i386/pr50712.c: New testcase.
+
+2011-10-13 Tom de Vries <tom@codesourcery.com>
+
+ * gcc.dg/memcpy-4.c: New test.
+
+2011-10-13 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/50698
+ * g++.dg/vect/pr50698.cc: New testcase.
+
+2011-10-12 Janis Johnson <janisjo@codesourcery.com>
+
+ * gcc.target/powerpc/warn-1.c: Skip if not powerpc_vsx_ok.
+ * gcc.target/powerpc/warn-2.c: Ditto.
+
+ * gcc.target/powerpc/ppc-fma-3.c: Require powerpc_fprs.
+ * gcc.target/powerpc/ppc-fma-4.c: Likewise.
+ * gcc.target/powerpc/ppc-fma-5.c: Likewise.
+ * gcc.target/powerpc/ppc-fma-7.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-11.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-3.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-7.c: Likewise.
+ * gcc.target/powerpc/ppc-fpconv-8.c: Likewise.
+ * gcc.target/powerpc/ppc-pow.c: Likewise.
+ * gcc.target/powerpc/recip-1.c: Likewise.
+ * gcc.target/powerpc/recip-2.c: Likewise.
+ * gcc.target/powerpc/recip-3.c: Likewise.
+ * gcc.target/powerpc/recip-4.c: Likewise.
+ * gcc.target/powerpc/recip-5.c: Likewise.
+
+2011-10-12 David S. Miller <davem@davemloft.net>
+
+ * gcc.target/sparc/cmask.c: Remove 'vis3' target check and specify
+ '-mvis3' instead of 'mcpu=niagara3' in options.
+ * gcc.target/sparc/fhalve.c: Likewise.
+ * gcc.target/sparc/fnegop.c: Likewise.
+ * gcc.target/sparc/fpadds.c: Likewise.
+ * gcc.target/sparc/fshift.c: Likewise.
+ * gcc.target/sparc/fucmp.c: Likewise.
+ * gcc.target/sparc/lzd.c: Likewise.
+ * gcc.target/sparc/vis3misc.c: Likewise.
+ * gcc.target/sparc/xmul.c: Likewise.
+
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/vect1.ad[sb]: New test.
+ * gnat.dg/vect1_pkg.ads: New helper.
+ * gnat.dg/vect2.ad[sb]: New test.
+ * gnat.dg/vect2_pkg.ads: New helper.
+ * gnat.dg/vect3.ad[sb]: New test.
+ * gnat.dg/vect3_pkg.ads: New helper.
+ * gnat.dg/vect4.ad[sb]: New test.
+ * gnat.dg/vect4_pkg.ads: New helper.
+ * gnat.dg/vect5.ad[sb]: New test.
+ * gnat.dg/vect5_pkg.ads: New helper.
+ * gnat.dg/vect6.ad[sb]: New test.
+ * gnat.dg/vect6_pkg.ads: New helper.
+
+2011-10-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/fma_run_double_1.c: Add -mfpmath=sse.
+ * gcc.target/i386/fma_run_double_2.c: Likewise.
+ * gcc.target/i386/fma_run_double_3.c: Likewise.
+ * gcc.target/i386/fma_run_double_4.c: Likewise.
+ * gcc.target/i386/fma_run_double_5.c: Likewise.
+ * gcc.target/i386/fma_run_double_6.c: Likewise.
+ * gcc.target/i386/fma_run_float_1.c: Likewise.
+ * gcc.target/i386/fma_run_float_2.c: Likewise.
+ * gcc.target/i386/fma_run_float_3.c: Likewise.
+ * gcc.target/i386/fma_run_float_4.c: Likewise.
+ * gcc.target/i386/fma_run_float_5.c: Likewise.
+ * gcc.target/i386/fma_run_float_6.c: Likewise.
+
+ * gcc.target/i386/l_fma_double_1.c: Add -mtune=generic and
+ remove the extra dg-options.
+ * gcc.target/i386/l_fma_double_2.c: Likewise.
+ * gcc.target/i386/l_fma_double_3.c: Likewise.
+ * gcc.target/i386/l_fma_double_4.c: Likewise.
+ * gcc.target/i386/l_fma_double_5.c: Likewise.
+ * gcc.target/i386/l_fma_double_6.c: Likewise.
+ * gcc.target/i386/l_fma_float_1.c: Likewise.
+ * gcc.target/i386/l_fma_float_2.c: Likewise.
+ * gcc.target/i386/l_fma_float_3.c: Likewise.
+ * gcc.target/i386/l_fma_float_4.c: Likewise.
+ * gcc.target/i386/l_fma_float_5.c: Likewise.
+ * gcc.target/i386/l_fma_float_6.c: Likewise.
+
+2011-10-12 Paul Koning <pkoning@gcc.gnu.org>
+
+ PR tree-optimization/50189
+ * g++.dg/torture/pr50189.C: New testcase.
+
2011-10-12 Richard Guenther <rguenther@suse.de>
PR tree-optimization/50700
@@ -7637,6 +8694,11 @@
* gfortran.dg/char4_iunit_2.f03: Adjust test.
* gfortran.dg/real_const_3.f90: Adjust test.
+2011-04-29 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/tree-ssa/inline-10.c: New testcase.
+ * gcc.dg/tree-ssa/inline-9.c: Disable partial inlining.
+
2011-04-28 Xinliang David Li <davidxl@google.com>
* gcc.dg/tree-prof/prof-robust-1.c: New test.
diff --git a/gcc/testsuite/c-c++-common/dfp/pr33466.c b/gcc/testsuite/c-c++-common/dfp/pr33466.c
index e1cd76b74ff..8c73cef4856 100644
--- a/gcc/testsuite/c-c++-common/dfp/pr33466.c
+++ b/gcc/testsuite/c-c++-common/dfp/pr33466.c
@@ -5,9 +5,9 @@
These are invalid for all targets, not just those that support
decimal float. */
-long double dF = 4.5dF; /* { dg-error "invalid suffix" } */
-long double Df = 4.5Df; /* { dg-error "invalid suffix" } */
-long double dD = 4.5dD; /* { dg-error "invalid suffix" } */
-long double Dd = 4.5Dd; /* { dg-error "invalid suffix" } */
-long double dL = 4.5dL; /* { dg-error "invalid suffix" } */
-long double Dl = 4.5Dl; /* { dg-error "invalid suffix" } */
+long double dF = 4.5dF; /* { dg-error "invalid suffix|user-defined" } */
+long double Df = 4.5Df; /* { dg-error "invalid suffix|user-defined" } */
+long double dD = 4.5dD; /* { dg-error "invalid suffix|user-defined" } */
+long double Dd = 4.5Dd; /* { dg-error "invalid suffix|user-defined" } */
+long double dL = 4.5dL; /* { dg-error "invalid suffix|user-defined" } */
+long double Dl = 4.5Dl; /* { dg-error "invalid suffix|user-defined" } */
diff --git a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
index db0e973a7a0..5ad3f4409f6 100644
--- a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
+++ b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
@@ -47,7 +47,7 @@ const char *dg_options[] = {
"/* { dg-options \"%s-I%s\" } */\n",
"/* { dg-options \"%s-I%s -mno-mmx -Wno-abi\" { target i?86-*-* x86_64-*-* } } */\n",
"/* { dg-options \"%s-I%s -fno-common\" { target alpha*-dec-osf* hppa*-*-hpux* powerpc*-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n",
-"/* { dg-options \"%s-I%s -mno-mmx -fno-common -Wno-abi\" { target i?86-*-darwin* x86_64-*-darwin* } } */\n",
+"/* { dg-options \"%s-I%s -mno-mmx -fno-common -Wno-abi\" { target i?86-*-darwin* x86_64-*-darwin* i?86-*-mingw32* x86_64-*-mingw32* i?86-*-cygwin* } } */\n",
"/* { dg-options \"%s-I%s -mno-base-addresses\" { target mmix-*-* } } */\n",
"/* { dg-options \"%s-I%s -mlongcalls -mtext-section-literals\" { target xtensa*-*-* } } */\n"
#define NDG_OPTIONS (sizeof (dg_options) / sizeof (dg_options[0]))
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C
new file mode 100644
index 00000000000..aad273792ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C
@@ -0,0 +1,161 @@
+// { dg-options "-std=c++0x -Wzero-as-null-pointer-constant" }
+
+struct A;
+
+typedef int (A::*pointmemfun) (int);
+typedef int (A::*pointdmem);
+typedef int (*pointfun) (int);
+
+pointmemfun pmfs;
+pointdmem pdms;
+pointfun pfs;
+int* ps;
+
+void f()
+{
+ pointmemfun pmf(0); // { dg-warning "zero as null pointer" }
+ pointdmem pdm(0); // { dg-warning "zero as null pointer" }
+ pointfun pf(0); // { dg-warning "zero as null pointer" }
+ int* p(0); // { dg-warning "zero as null pointer" }
+
+ pointmemfun pmfn(nullptr);
+ pointdmem pdmn(nullptr);
+ pointfun pfn(nullptr);
+ int* pn(nullptr);
+
+ pmf = 0; // { dg-warning "zero as null pointer" }
+
+ pdm = 0; // { dg-warning "zero as null pointer" }
+
+ pf = 0; // { dg-warning "zero as null pointer" }
+
+ p = 0; // { dg-warning "zero as null pointer" }
+
+ pmf = nullptr;
+
+ pdm = nullptr;
+
+ pf = nullptr;
+
+ p = nullptr;
+
+ if (pmf)
+ ;
+
+ if (pdm)
+ ;
+
+ if (pf)
+ ;
+
+ if (p)
+ ;
+
+ if (!pmf)
+ ;
+
+ if (!pdm)
+ ;
+
+ if (!pf)
+ ;
+
+ if (!p)
+ ;
+
+ if (pmf == 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pdm == 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pf == 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (p == 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 == pmf) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 == pdm) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 == pf) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 == p) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pmf != 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pdm != 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pf != 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (p != 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 != pmf) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 != pdm) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 != pf) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 != p) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pmf == nullptr)
+ ;
+
+ if (pdm == nullptr)
+ ;
+
+ if (pf == nullptr)
+ ;
+
+ if (p == nullptr)
+ ;
+
+ if (nullptr == pmf)
+ ;
+
+ if (nullptr == pdm)
+ ;
+
+ if (nullptr == pf)
+ ;
+
+ if (nullptr == p)
+ ;
+
+ if (pmf != nullptr)
+ ;
+
+ if (pdm != nullptr)
+ ;
+
+ if (pf != nullptr)
+ ;
+
+ if (p != nullptr)
+ ;
+
+ if (nullptr != pmf)
+ ;
+
+ if (nullptr != pdm)
+ ;
+
+ if (nullptr != pf)
+ ;
+
+ if (nullptr != p)
+ ;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-98.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-98.C
index 4ae3944c34d..1a0189b56e2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-98.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-98.C
@@ -1,4 +1,4 @@
// { dg-options "-std=c++98" }
-constexpr int i = 42; // { dg-message "std=c\\+\\+0x" }
+constexpr int i = 42; // { dg-message "std=c\\+\\+11" }
// { dg-error "constexpr" "" { target *-*-* } 3 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C
new file mode 100644
index 00000000000..a14d611cee8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+ int i;
+ mutable int j;
+};
+
+constexpr A a = { 0, 1 };
+constexpr A b = a; // { dg-error "mutable" }
+constexpr int i = a.i;
+constexpr int j = a.j; // { dg-error "mutable" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype34.C b/gcc/testsuite/g++.dg/cpp0x/decltype34.C
new file mode 100644
index 00000000000..fbd15c2797d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype34.C
@@ -0,0 +1,19 @@
+// PR c++/50870
+// { dg-options "-std=gnu++0x" }
+
+struct impl
+{
+ template <class T> static T create();
+};
+
+template<class T, class U,
+ class = decltype(impl::create<T>()->impl::create<U>())>
+struct tester{};
+
+tester<impl*, int> ti;
+
+template<class T, class U,
+ class = decltype(impl::create<T>()->impl::create<U>())>
+int test() { return 0; }
+
+int i = test<impl*, int>();
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
index 5d536a97eff..9b8c697abad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C
@@ -2,13 +2,12 @@
// { dg-options -std=c++0x }
struct A {
- A(A&&) = default; // { dg-message "A::A|no known conversion" }
+ A(A&&) = default;
};
struct B {
const A a;
B(const B&) = default;
- B(B&&) = default; // { dg-error "implicitly deleted|no match" }
- // { dg-message "candidate" "candidate note" { target *-*-* } 10 }
+ B(B&&) = default; // { dg-error "implicitly deleted|use of deleted" }
};
void g(B); // { dg-error "argument 1" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
index 3e740331d8a..30a4a7c7d01 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C
@@ -12,7 +12,7 @@ struct X {
X(X&&);
};
-X::X(X&&)=default; // { dg-error "implicitly deleted" }
+X::X(X&&)=default; // { dg-message "implicitly deleted" }
// { dg-error "does not have a move constructor" "" { target *-*-* } 15 }
X f() {
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted32.C b/gcc/testsuite/g++.dg/cpp0x/defaulted32.C
new file mode 100644
index 00000000000..351cdae1102
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted32.C
@@ -0,0 +1,21 @@
+// PR c++/50531
+// { dg-options -std=c++0x }
+
+template <typename T>
+class DataFilter
+{
+ public:
+ inline virtual ~DataFilter();
+};
+
+template<typename T>
+inline DataFilter<T>::~DataFilter() = default;
+
+class ARCalculator : public DataFilter<ARCalculator>
+{
+ public:
+ virtual void dataStart(int, int);
+};
+
+void ARCalculator::dataStart(int, int)
+{}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C b/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
index 861fe201f10..c3f6b85e247 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C
@@ -3,13 +3,13 @@ struct S
{
S();
private:
- S(S const &&); // { dg-error "" }
- S & operator=(S const &&); // { dg-error "" }
+ S(S const &&);
+ S & operator=(S const &&);
};
void f()
{
S a;
- S b(a); // { dg-error "" }
- a = b; // { dg-error "" }
+ S b(a); // { dg-error "deleted" }
+ a = b; // { dg-error "deleted" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit12.C b/gcc/testsuite/g++.dg/cpp0x/implicit12.C
new file mode 100644
index 00000000000..da806e006a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit12.C
@@ -0,0 +1,54 @@
+// PR c++/50500
+// { dg-options "-std=c++0x" }
+
+// If a class declares move operations, the implicitly declared copy
+// operations are deleted.
+struct A
+{
+ A();
+ A(A&&);
+ A& operator=(A&&);
+};
+
+// But they can still be explicitly defaulted.
+struct B
+{
+ B();
+ B(B&&);
+ B(const B&) = default;
+ B& operator=(B&&);
+ B& operator=(const B&) = default;
+};
+
+struct C
+{
+ C();
+ C(C&&);
+};
+
+struct D
+{
+ D();
+ D& operator=(D&&);
+};
+
+int main()
+{
+ A a;
+ A a2 (a); // { dg-error "deleted" }
+ a2 = a; // { dg-error "deleted" }
+
+ B b;
+ B b2 (b);
+ b2 = b;
+
+ C c;
+ C c2(c); // { dg-error "deleted" }
+ c2 = c; // { dg-error "deleted" }
+
+ D d;
+ D d2(d); // { dg-error "deleted" }
+ d2 = d; // { dg-error "deleted" }
+}
+
+// { dg-prune-output "because" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit4.C b/gcc/testsuite/g++.dg/cpp0x/implicit4.C
index f97eb7549f9..47fd56a5252 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit4.C
@@ -2,14 +2,13 @@
// constructor to be deleted.
// { dg-options "-std=c++0x" }
-struct A
+struct A // { dg-message "declares a move" }
{
- A(); // { dg-message "A::A|candidate expects" }
- A(A&&); // { dg-message "A::A|no known conversion" }
+ A();
+ A(A&&);
};
-struct B: A // { dg-error "implicit|no match" }
-// { dg-message "candidate" "candidate note" { target *-*-* } 11 }
+struct B: A // { dg-error "use of deleted" }
{
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit5.C b/gcc/testsuite/g++.dg/cpp0x/implicit5.C
index f25c08530db..d25294831e3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit5.C
@@ -1,19 +1,19 @@
-// Test that the default B copy constructor calls the A member template
-// constructor.
+// Test that the default B copy constructor calls the deleted A
+// copy constructor.
// { dg-options -std=c++0x }
-struct A
+struct A // { dg-message "declares a move" }
{
A() = default;
A(A&&) = default;
template <class T>
- A(const T& t) { t.i; } // { dg-error "no member" }
+ A(const T& t) { t.i; }
};
-struct B: A { };
+struct B: A { }; // { dg-error "implicitly|use of deleted" }
int main()
{
B b;
- B b2(b);
+ B b2(b); // { dg-error "deleted" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit8.C b/gcc/testsuite/g++.dg/cpp0x/implicit8.C
index 2f3febae8b2..c949af21050 100644
--- a/gcc/testsuite/g++.dg/cpp0x/implicit8.C
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit8.C
@@ -1,9 +1,6 @@
// The hack for PR c++/44909 breaks this testcase. We need feedback
// from the C++ committee to know how to proceed.
// { dg-options -std=c++0x }
-// { dg-prune-output "implicitly deleted" }
-// { dg-prune-output "cannot bind" }
-// { dg-prune-output "initializing argument" }
struct A
{
@@ -28,7 +25,8 @@ struct B
// subobject of C should use B(const BP&). But we ignore that constructor
// in order to break the cycle in 44909. Perhaps the move ctor shouldn't
// suppress the copy ctor?
-struct C: A, B { };
+// As of DR 1082, it doesn't suppress it.
+struct C: A, B { }; // { dg-error "use of deleted" }
C c;
-C c2(c); // { dg-bogus "deleted" "" { xfail *-*-* } }
+C c2(c); // { dg-error "deleted" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C
index e422132afc3..373044f765a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C
@@ -2,7 +2,7 @@
// supported by the working draft, but is necessary for perfect forwarding
// of initializer-lists to things that can take a std::initializer_list.
-// { dg-options -std=c++0x }
+// { dg-options "-std=c++0x -fdeduce-init-list" }
// { dg-do run }
#include <initializer_list>
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist59.C b/gcc/testsuite/g++.dg/cpp0x/initlist59.C
new file mode 100644
index 00000000000..2cc015d1fee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist59.C
@@ -0,0 +1,18 @@
+// PR c++/49996
+// { dg-options -std=c++0x }
+
+struct A
+{
+ ~A()
+ { }
+};
+
+struct B
+{
+ const A& ref;
+};
+
+int main()
+{
+ B* p = new B{A()};
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C
new file mode 100644
index 00000000000..b5ba0663754
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-auto1.C
@@ -0,0 +1,14 @@
+// PR c++/50437
+// { dg-options -std=c++0x }
+
+template <typename T>
+void f()
+{
+ auto g = [](T t){ return t == 0; };
+ g(T());
+}
+
+int main()
+{
+ f<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-neg.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-neg.C
new file mode 100644
index 00000000000..82cc98423ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-capture-neg.C
@@ -0,0 +1,15 @@
+// PR c++/50736
+// { dg-options "-std=c++0x -pedantic-errors" }
+
+int i;
+void f();
+typedef int T;
+
+int main()
+{
+ [i]{}; // { dg-error "non-automatic" }
+ [f]{}; // { dg-error "non-variable" }
+ [T]{}; // { dg-error "non-variable" }
+}
+
+struct A { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
index 8d7d093dc40..6468f18a0ac 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-ice2.C
@@ -9,7 +9,7 @@ decltype(F()) run(F f) // { dg-message "note" }
int main()
{
- auto l = []() { return 5; }; // { dg-error "lambda closure type" }
+ auto l = []() { return 5; }; // { dg-message "lambda closure type" }
run(l); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 14 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/not_special.C b/gcc/testsuite/g++.dg/cpp0x/not_special.C
index 6d73bd086ca..2b510bb9a1b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/not_special.C
+++ b/gcc/testsuite/g++.dg/cpp0x/not_special.C
@@ -1,8 +1,8 @@
// I, Howard Hinnant, hereby place this code in the public domain.
// Test that move constructor and move assignement are special.
-// That is, their presence should inhibit compiler generated
-// copy ctor or assignment.
+// That is, their presence should cause compiler declared
+// copy ctor or assignment to be deleted.
// { dg-options "-std=c++0x" }
@@ -24,12 +24,12 @@ struct base
base& operator=(const base&) {++assign; return *this;}
};
-struct derived
+struct derived // { dg-message "declares a move" }
: base
{
derived() {}
- derived(derived&&) {} // { dg-error "argument 1" }
- derived& operator=(derived&&) {return *this;} // { dg-error "argument 1" }
+ derived(derived&&) {}
+ derived& operator=(derived&&) {return *this;}
};
int test1()
@@ -37,11 +37,11 @@ int test1()
derived d;
derived d2(static_cast<derived&&>(d)); // should not call base::(const base&)
assert(copy == 0);
- derived d3(d); // { dg-error "lvalue" }
+ derived d3(d); // { dg-error "deleted" }
assert(copy == 1);
d2 = static_cast<derived&&>(d); // should not call base::operator=
assert(assign == 0);
- d3 = d; // { dg-error "lvalue" }
+ d3 = d; // { dg-error "deleted" }
assert(assign == 1);
return 0;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C
new file mode 100644
index 00000000000..ddf9f04c580
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C
@@ -0,0 +1,10 @@
+// PR c++/50707
+// { dg-options -std=c++0x }
+
+int g;
+
+struct S {
+ int const v=g;
+};
+
+S s;
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C
new file mode 100644
index 00000000000..526f29ae285
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C
@@ -0,0 +1,14 @@
+// PR c++/50563
+// { dg-options -std=c++0x }
+
+struct S1 {
+ int a{10}, b{20}; // OK
+};
+
+struct S2 {
+ int a, b = 20; // OK
+};
+
+struct S3 {
+ int a = 10, b = 20;
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C
new file mode 100644
index 00000000000..27b0aa5f9da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C
@@ -0,0 +1,14 @@
+// PR c++/50614
+// { dg-options "-std=c++0x -fcompare-debug" }
+
+struct A
+{
+ int f ();
+};
+
+template <int> struct B : A
+{
+ int i = this->f ();
+};
+
+B<0> b;
diff --git a/gcc/testsuite/g++.dg/cpp0x/override2.C b/gcc/testsuite/g++.dg/cpp0x/override2.C
index 7f17504fae2..0d8871d6ae2 100644
--- a/gcc/testsuite/g++.dg/cpp0x/override2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/override2.C
@@ -28,6 +28,13 @@ struct B6 final final {}; // { dg-error "duplicate virt-specifier" }
struct B7 override {}; // { dg-error "cannot specify 'override' for a class" }
+namespace N
+{
+ struct C;
+}
+
+struct N::C final{};
+
int main()
{
D3<B1> d;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr50901.C b/gcc/testsuite/g++.dg/cpp0x/pr50901.C
new file mode 100644
index 00000000000..439c15cc1cd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr50901.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+template<class T> int foo(int a)
+{
+ const unsigned b = a < 0 ? -a : a;
+ return 0;
+}
+
+int i = foo<float>(1);
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
index 2765b5f3c30..cbce7c4ddd7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C
@@ -5,22 +5,22 @@
int move_construct = 0;
int move_assign = 0;
-struct base2
+struct base2 // { dg-message "declares a move" }
{
base2() {}
- base2(base2&&) {++move_construct;} // { dg-error "argument 1" }
- base2& operator=(base2&&) {++move_assign; return *this;} // { dg-error "argument 1" }
+ base2(base2&&) {++move_construct;}
+ base2& operator=(base2&&) {++move_assign; return *this;}
};
int test2()
{
base2 b;
- base2 b2(b); // { dg-error "lvalue" }
+ base2 b2(b); // { dg-error "deleted" }
assert(move_construct == 0);
base2 b3(static_cast<base2&&>(b));
base2 b4 = static_cast<base2&&>(b);
assert(move_construct == 2);
- b = b2; // { dg-error "lvalue" }
+ b = b2; // { dg-error "deleted" }
assert(move_assign == 0);
b = static_cast<base2&&>(b2);
assert(move_assign == 1);
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv1n.C b/gcc/testsuite/g++.dg/cpp0x/rv1n.C
index 5224d3eb70e..68305ebc9b4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv1n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv1n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -35,9 +35,9 @@ one sink_1_1( A&); // { dg-error "" }
int test1_1()
{
A a;
- const A ca = a; // { dg-error "cannot bind" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "cannot bind" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_1(ca); // { dg-error "invalid initialization" }
sink_1_1(va); // { dg-error "invalid initialization" }
sink_1_1(cva); // { dg-error "invalid initialization" }
@@ -53,9 +53,9 @@ two sink_1_2(const A&); // { dg-error "" }
int test1_2()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_2(va); // { dg-error "invalid initialization" }
sink_1_2(cva); // { dg-error "invalid initialization" }
sink_1_2(v_source()); // { dg-error "invalid initialization" }
@@ -68,9 +68,9 @@ three sink_1_3(volatile A&); // { dg-error "" }
int test1_3()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_3(ca); // { dg-error "invalid initialization" }
sink_1_3(cva); // { dg-error "invalid initialization" }
sink_1_3(source()); // { dg-error "invalid initialization" }
@@ -85,9 +85,9 @@ four sink_1_4(const volatile A&); // { dg-error "" }
int test1_4()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_4(source()); // { dg-error "invalid initialization" }
sink_1_4(c_source()); // { dg-error "invalid initialization" }
sink_1_4(v_source()); // { dg-error "invalid initialization" }
@@ -100,9 +100,9 @@ five sink_1_5( A&&); // { dg-error "" }
int test1_5()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_5(a); // { dg-error "lvalue" }
sink_1_5(ca); // { dg-error "invalid initialization" }
sink_1_5(va); // { dg-error "invalid initialization" }
@@ -118,9 +118,9 @@ six sink_1_6(const A&&); // { dg-error "" }
int test1_6()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_6(a); // { dg-error "lvalue" }
sink_1_6(ca); // { dg-error "lvalue" }
sink_1_6(va); // { dg-error "invalid initialization" }
@@ -135,9 +135,9 @@ seven sink_1_7(volatile A&&); // { dg-error "" }
int test1_7()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_7(a); // { dg-error "lvalue" }
sink_1_7(ca); // { dg-error "invalid initialization" }
sink_1_7(va); // { dg-error "lvalue" }
@@ -152,9 +152,9 @@ eight sink_1_8(const volatile A&&); // { dg-error "" }
int test1_8()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_1_8(a); // { dg-error "lvalue" }
sink_1_8(ca); // { dg-error "lvalue" }
sink_1_8(va); // { dg-error "lvalue" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv2n.C b/gcc/testsuite/g++.dg/cpp0x/rv2n.C
index 2b3a9c06ae9..a9d37415e07 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv2n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv2n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -36,9 +36,9 @@ two sink_2_12(const A&); // { dg-message "note|argument" }
int test2_12()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_12(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 42 }
sink_2_12(cva); // { dg-error "no match" }
@@ -56,9 +56,9 @@ three sink_2_13(volatile A&); // { dg-message "note|argument" }
int test2_13()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_13(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 62 }
sink_2_13(cva); // { dg-error "no match" }
@@ -80,9 +80,9 @@ four sink_2_14(const volatile A&); // { dg-message "note|argument" }
int test2_14()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_14(source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 86 }
sink_2_14(c_source()); // { dg-error "no match" }
@@ -100,9 +100,9 @@ five sink_2_15( A&&); // { dg-message "note|argument" }
int test2_15()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_15(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 106 }
sink_2_15(va); // { dg-error "no match" }
@@ -124,9 +124,9 @@ six sink_2_16(const A&&); // { dg-message "note|argument" }
int test2_16()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_16(ca); // { dg-error "lvalue" }
sink_2_16(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 131 }
@@ -145,9 +145,9 @@ seven sink_2_17(volatile A&&); // { dg-message "note|argument" }
int test2_17()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_17(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 151 }
sink_2_17(va); // { dg-error "lvalue" }
@@ -166,9 +166,9 @@ eight sink_2_18(const volatile A&&); // { dg-error "argument" }
int test2_18()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_18(ca); // { dg-error "lvalue" }
sink_2_18(va); // { dg-error "lvalue" }
sink_2_18(cva); // { dg-error "lvalue" }
@@ -180,9 +180,9 @@ three sink_2_23(volatile A&); // { dg-message "note|argument" }
int test2_23()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_23(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 186 }
sink_2_23(cva); // { dg-error "no match" }
@@ -200,9 +200,9 @@ four sink_2_24(const volatile A&); // { dg-message "note|argument" }
int test2_24()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_24(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 206 }
sink_2_24(cv_source()); // { dg-error "no match" }
@@ -216,9 +216,9 @@ four sink_2_34(const volatile A&); // { dg-message "note|argument" }
int test2_34()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_34(source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 222 }
sink_2_34(c_source()); // { dg-error "no match" }
@@ -236,9 +236,9 @@ five sink_2_25( A&&); // { dg-message "note|argument" }
int test2_25()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_25(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 242 }
sink_2_25(cva); // { dg-error "no match" }
@@ -256,9 +256,9 @@ six sink_2_26(const A&&); // { dg-message "note|argument" }
int test2_26()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_26(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 262 }
sink_2_26(cva); // { dg-error "no match" }
@@ -276,9 +276,9 @@ seven sink_2_27(volatile A&&); // { dg-message "note|argument" }
int test2_27()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_27(va); // { dg-error "lvalue" }
sink_2_27(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 283 }
@@ -293,9 +293,9 @@ eight sink_2_28(const volatile A&&); // { dg-error "argument" }
int test2_28()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_28(va); // { dg-error "lvalue" }
sink_2_28(cva); // { dg-error "lvalue" }
}
@@ -306,9 +306,9 @@ five sink_2_35( A&&); // { dg-message "note|argument" }
int test2_35()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_35(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 312 }
sink_2_35(cva); // { dg-error "no match" }
@@ -328,9 +328,9 @@ six sink_2_36(const A&&); // { dg-message "note|argument" }
int test2_36()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_36(ca); // { dg-error "lvalue" }
sink_2_36(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 335 }
@@ -347,9 +347,9 @@ seven sink_2_37(volatile A&&); // { dg-message "note|argument" }
int test2_37()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_37(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 353 }
sink_2_37(cva); // { dg-error "no match" }
@@ -367,9 +367,9 @@ eight sink_2_38(const volatile A&&); // { dg-error "argument" }
int test2_38()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_38(ca); // { dg-error "lvalue" }
sink_2_38(cva); // { dg-error "lvalue" }
}
@@ -380,9 +380,9 @@ five sink_2_45( A&&); // { dg-message "note|argument" }
int test2_45()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_45(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 386 }
sink_2_45(v_source()); // { dg-error "no match" }
@@ -398,9 +398,9 @@ six sink_2_46(const A&&); // { dg-message "note|argument" }
int test2_46()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_46(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 404 }
sink_2_46(cv_source()); // { dg-error "no match" }
@@ -414,9 +414,9 @@ seven sink_2_47(volatile A&&); // { dg-message "note|argument" }
int test2_47()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_47(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 420 }
sink_2_47(cv_source()); // { dg-error "no match" }
@@ -430,9 +430,9 @@ six sink_2_56(const A&&); // { dg-message "note|argument" }
int test2_56()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_56(a); // { dg-error "lvalue" }
sink_2_56(ca); // { dg-error "lvalue" }
sink_2_56(va); // { dg-error "no match" }
@@ -452,9 +452,9 @@ seven sink_2_57(volatile A&&); // { dg-message "note|argument" }
int test2_57()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_57(a); // { dg-error "lvalue" }
sink_2_57(va); // { dg-error "lvalue" }
sink_2_57(ca); // { dg-error "no match" }
@@ -474,9 +474,9 @@ eight sink_2_58(const volatile A&&); // { dg-error "argument" }
int test2_58()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_58(a); // { dg-error "lvalue" }
sink_2_58(ca); // { dg-error "lvalue" }
sink_2_58(va); // { dg-error "lvalue" }
@@ -489,9 +489,9 @@ seven sink_2_67(volatile A&&); // { dg-message "note|argument" }
int test2_67()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_67(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 495 }
sink_2_67(ca); // { dg-error "lvalue" }
@@ -511,9 +511,9 @@ eight sink_2_68(const volatile A&&); // { dg-error "argument" }
int test2_68()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_68(a); // { dg-error "lvalue" }
sink_2_68(ca); // { dg-error "lvalue" }
sink_2_68(va); // { dg-error "lvalue" }
@@ -526,9 +526,9 @@ eight sink_2_78(const volatile A&&); // { dg-error "argument" }
int test2_78()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_2_78(a); // { dg-error "lvalue" }
sink_2_78(ca); // { dg-error "lvalue" }
sink_2_78(va); // { dg-error "lvalue" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv3n.C b/gcc/testsuite/g++.dg/cpp0x/rv3n.C
index 637716f9b44..14b810ae68d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv3n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv3n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -37,9 +37,9 @@ three sink_3_123(volatile A&); // { dg-message "three sink_3_123|no known
int test3_123()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_123(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 43 }
sink_3_123(v_source()); // { dg-error "no match" }
@@ -60,9 +60,9 @@ four sink_3_124(const volatile A&); // { dg-message "four sink_3_124|no known
int test3_124()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_124(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 66 }
sink_3_124(cv_source()); // { dg-error "no match" }
@@ -73,9 +73,9 @@ int test3_124()
int test3_125()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_125(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 79 }
sink_3_125(cva); // { dg-error "no match" }
@@ -94,9 +94,9 @@ six sink_3_126(const A&&); // { dg-message "six sink_3_126|no known
int test3_126()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_126(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 100 }
sink_3_126(cva); // { dg-error "no match" }
@@ -115,9 +115,9 @@ seven sink_3_127(volatile A&&); // { dg-message "seven sink_3_127|no know
int test3_127()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_127(va); // { dg-error "lvalue" }
sink_3_127(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 122 }
@@ -133,9 +133,9 @@ eight sink_3_128(const volatile A&&); // { dg-message "" }
int test3_128()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_128(va); // { dg-error "lvalue" }
sink_3_128(cva); // { dg-error "lvalue" }
@@ -148,9 +148,9 @@ four sink_3_134(const volatile A&); // { dg-message "four sink_3_134|no known
int test3_134()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_134(source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 154 }
sink_3_134(c_source()); // { dg-error "no match" }
@@ -169,9 +169,9 @@ five sink_3_135( A&&); // { dg-message "five sink_3_135|no known
int test3_135()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_135(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 175 }
sink_3_135(cva); // { dg-error "no match" }
@@ -192,9 +192,9 @@ six sink_3_136(const A&&); // { dg-message "" }
int test3_136()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_136(ca); // { dg-error "lvalue" }
sink_3_136(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 199 }
@@ -212,9 +212,9 @@ seven sink_3_137(volatile A&&); // { dg-message "note" }
int test3_137()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_137(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 218 }
sink_3_137(cva); // { dg-error "no match" }
@@ -233,9 +233,9 @@ eight sink_3_138(const volatile A&&); // { dg-message "" }
int test3_138()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_138(ca); // { dg-error "lvalue" }
sink_3_138(cva); // { dg-error "lvalue" }
return 0;
@@ -248,9 +248,9 @@ five sink_3_145( A&&); // { dg-message "note" }
int test3_145()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_145(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 254 }
sink_3_145(v_source()); // { dg-error "no match" }
@@ -267,9 +267,9 @@ six sink_3_146(const A&&); // { dg-message "note" }
int test3_146()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_146(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 273 }
sink_3_146(cv_source()); // { dg-error "no match" }
@@ -284,9 +284,9 @@ seven sink_3_147(volatile A&&); // { dg-message "note" }
int test3_147()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_147(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 290 }
sink_3_147(cv_source()); // { dg-error "no match" }
@@ -301,9 +301,9 @@ six sink_3_156(const A&&); // { dg-message "" }
int test3_156()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_156(ca); // { dg-error "lvalue" }
sink_3_156(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 308 }
@@ -323,9 +323,9 @@ seven sink_3_157(volatile A&&); // { dg-message "" }
int test3_157()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_157(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 329 }
sink_3_157(va); // { dg-error "lvalue" }
@@ -345,9 +345,9 @@ eight sink_3_158(const volatile A&&); // { dg-message "" }
int test3_158()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_158(ca); // { dg-error "lvalue" }
sink_3_158(va); // { dg-error "lvalue" }
sink_3_158(cva); // { dg-error "lvalue" }
@@ -361,9 +361,9 @@ seven sink_3_167(volatile A&&); // { dg-message "" }
int test3_167()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_167(ca); // { dg-error "lvalue" }
sink_3_167(va); // { dg-error "lvalue" }
sink_3_167(cva); // { dg-error "no match" }
@@ -382,9 +382,9 @@ eight sink_3_168(const volatile A&&); // { dg-message "" }
int test3_168()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_168(ca); // { dg-error "lvalue" }
sink_3_168(va); // { dg-error "lvalue" }
sink_3_168(cva); // { dg-error "lvalue" }
@@ -398,9 +398,9 @@ eight sink_3_178(const volatile A&&); // { dg-message "" }
int test3_178()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_178(ca); // { dg-error "lvalue" }
sink_3_178(va); // { dg-error "lvalue" }
sink_3_178(cva); // { dg-error "lvalue" }
@@ -414,9 +414,9 @@ four sink_3_234(const volatile A&); // { dg-message "note" }
int test3_234()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_234(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 420 }
sink_3_234(v_source()); // { dg-error "no match" }
@@ -433,9 +433,9 @@ five sink_3_235( A&&); // { dg-message "note" }
int test3_235()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_235(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 439 }
sink_3_235(cva); // { dg-error "no match" }
@@ -454,9 +454,9 @@ six sink_3_236(const A&&); // { dg-message "note" }
int test3_236()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_236(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 460 }
sink_3_236(cva); // { dg-error "no match" }
@@ -475,9 +475,9 @@ seven sink_3_237(volatile A&&); // { dg-message "note" }
int test3_237()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_237(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 481 }
sink_3_237(cva); // { dg-error "no match" }
@@ -494,9 +494,9 @@ eight sink_3_238(const volatile A&&); // { dg-message "eight sink_3_238|no know
int test3_238()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_238(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 500 }
sink_3_238(cva); // { dg-error "lvalue" }
@@ -510,9 +510,9 @@ five sink_3_245( A&&); // { dg-message "five sink_3_245|no known
int test3_245()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_245(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 516 }
sink_3_245(cv_source()); // { dg-error "no match" }
@@ -527,9 +527,9 @@ six sink_3_246(const A&&); // { dg-message "six sink_3_246|no known
int test3_246()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_246(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 533 }
sink_3_246(cv_source()); // { dg-error "no match" }
@@ -544,9 +544,9 @@ seven sink_3_247(volatile A&&); // { dg-message "seven sink_3_247|no know
int test3_247()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_247(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 550 }
return 0;
@@ -559,9 +559,9 @@ six sink_3_256(const A&&); // { dg-message "six sink_3_256|no known
int test3_256()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_256(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 565 }
sink_3_256(cva); // { dg-error "no match" }
@@ -580,9 +580,9 @@ seven sink_3_257(volatile A&&); // { dg-message "seven sink_3_257|no know
int test3_257()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_257(va); // { dg-error "lvalue" }
sink_3_257(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 587 }
@@ -598,9 +598,9 @@ eight sink_3_258(const volatile A&&); // { dg-message "" }
int test3_258()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_258(va); // { dg-error "lvalue" }
sink_3_258(cva); // { dg-error "lvalue" }
return 0;
@@ -613,9 +613,9 @@ seven sink_3_267(volatile A&&); // { dg-message "seven sink_3_267|no know
int test3_267()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_267(va); // { dg-error "lvalue" }
sink_3_267(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 620 }
@@ -633,9 +633,9 @@ eight sink_3_268(const volatile A&&); // { dg-message "" }
int test3_268()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_268(va); // { dg-error "lvalue" }
sink_3_268(cva); // { dg-error "lvalue" }
return 0;
@@ -648,9 +648,9 @@ eight sink_3_278(const volatile A&&); // { dg-message "" }
int test3_278()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_278(va); // { dg-error "lvalue" }
sink_3_278(cva); // { dg-error "lvalue" }
return 0;
@@ -663,9 +663,9 @@ five sink_3_345( A&&); // { dg-message "five sink_3_345|no known
int test3_345()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_345(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 669 }
sink_3_345(v_source()); // { dg-error "no match" }
@@ -682,9 +682,9 @@ six sink_3_346(const A&&); // { dg-message "six sink_3_346|no known
int test3_346()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_346(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 688 }
sink_3_346(cv_source()); // { dg-error "no match" }
@@ -699,9 +699,9 @@ seven sink_3_347(volatile A&&); // { dg-message "seven sink_3_347|no know
int test3_347()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_347(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 705 }
sink_3_347(cv_source()); // { dg-error "no match" }
@@ -716,9 +716,9 @@ six sink_3_356(const A&&); // { dg-message "six sink_3_356|no known
int test3_356()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_356(ca); // { dg-error "lvalue" }
sink_3_356(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 723 }
@@ -736,9 +736,9 @@ seven sink_3_357(volatile A&&); // { dg-message "seven sink_3_357|no know
int test3_357()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_357(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 742 }
sink_3_357(cva); // { dg-error "no match" }
@@ -757,9 +757,9 @@ eight sink_3_358(const volatile A&&); // { dg-message "" }
int test3_358()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_358(ca); // { dg-error "lvalue" }
sink_3_358(cva); // { dg-error "lvalue" }
return 0;
@@ -772,9 +772,9 @@ seven sink_3_367(volatile A&&); // { dg-message "seven sink_3_367|no know
int test3_367()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_367(ca); // { dg-error "lvalue" }
sink_3_367(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 779 }
@@ -792,9 +792,9 @@ eight sink_3_368(const volatile A&&); // { dg-message "" }
int test3_368()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_368(ca); // { dg-error "lvalue" }
sink_3_368(cva); // { dg-error "lvalue" }
return 0;
@@ -807,9 +807,9 @@ eight sink_3_378(const volatile A&&); // { dg-message "" }
int test3_378()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_378(ca); // { dg-error "lvalue" }
sink_3_378(cva); // { dg-error "lvalue" }
return 0;
@@ -822,9 +822,9 @@ six sink_3_456(const A&&); // { dg-message "note" }
int test3_456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 828 }
sink_3_456(cv_source()); // { dg-error "no match" }
@@ -839,9 +839,9 @@ seven sink_3_457(volatile A&&); // { dg-message "note" }
int test3_457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_457(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 845 }
sink_3_457(cv_source()); // { dg-error "no match" }
@@ -856,9 +856,9 @@ seven sink_3_467(volatile A&&); // { dg-message "note" }
int test3_467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 862 }
sink_3_467(cv_source()); // { dg-error "no match" }
@@ -873,9 +873,9 @@ seven sink_3_567(volatile A&&); // { dg-message "seven sink_3_567|no know
int test3_567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_567(a); // { dg-error "lvalue" }
sink_3_567(ca); // { dg-error "lvalue" }
sink_3_567(va); // { dg-error "lvalue" }
@@ -893,9 +893,9 @@ eight sink_3_568(const volatile A&&); // { dg-message "" }
int test3_568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_568(a); // { dg-error "lvalue" }
sink_3_568(ca); // { dg-error "lvalue" }
sink_3_568(va); // { dg-error "lvalue" }
@@ -910,9 +910,9 @@ eight sink_3_578(const volatile A&&); // { dg-message "" }
int test3_578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_578(a); // { dg-error "lvalue" }
sink_3_578(ca); // { dg-error "lvalue" }
sink_3_578(va); // { dg-error "lvalue" }
@@ -927,9 +927,9 @@ eight sink_3_678(const volatile A&&); // { dg-message "eight sink_3_678|no know
int test3_678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_3_678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 933 }
sink_3_678(ca); // { dg-error "lvalue" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv4n.C b/gcc/testsuite/g++.dg/cpp0x/rv4n.C
index daff3079851..076e9a0488e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv4n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv4n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -38,9 +38,9 @@ four sink_4_1234(const volatile A&); // { dg-message "note" }
int test4_1234()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1234(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 44 }
sink_4_1234(cv_source()); // { dg-error "no match" }
@@ -56,9 +56,9 @@ five sink_4_1235( A&&); // { dg-message "note" }
int test4_1235()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1235(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 62 }
sink_4_1235(v_source()); // { dg-error "no match" }
@@ -76,9 +76,9 @@ six sink_4_1236(const A&&); // { dg-message "note" }
int test4_1236()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1236(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 82 }
sink_4_1236(v_source()); // { dg-error "no match" }
@@ -96,9 +96,9 @@ seven sink_4_1237(volatile A&&); // { dg-message "note" }
int test4_1237()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1237(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 102 }
sink_4_1237(cv_source()); // { dg-error "no match" }
@@ -114,9 +114,9 @@ eight sink_4_1238(const volatile A&&); // { dg-message "" }
int test4_1238()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1238(cva); // { dg-error "lvalue" }
return 0;
}
@@ -129,9 +129,9 @@ five sink_4_1245( A&&); // { dg-message "note" }
int test4_1245()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1245(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 135 }
sink_4_1245(cv_source()); // { dg-error "no match" }
@@ -147,9 +147,9 @@ six sink_4_1246(const A&&); // { dg-message "note" }
int test4_1246()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1246(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 153 }
sink_4_1246(cv_source()); // { dg-error "no match" }
@@ -165,9 +165,9 @@ seven sink_4_1247(volatile A&&); // { dg-message "note" }
int test4_1247()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1247(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 171 }
return 0;
@@ -181,9 +181,9 @@ six sink_4_1256(const A&&); // { dg-message "note" }
int test4_1256()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1256(va); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 187 }
sink_4_1256(cva); // { dg-error "no match" }
@@ -203,9 +203,9 @@ seven sink_4_1257(volatile A&&); // { dg-message "" }
int test4_1257()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1257(va); // { dg-error "lvalue" }
sink_4_1257(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 210 }
@@ -222,9 +222,9 @@ eight sink_4_1258(const volatile A&&); // { dg-message "" }
int test4_1258()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1258(va); // { dg-error "lvalue" }
sink_4_1258(cva); // { dg-error "lvalue" }
return 0;
@@ -238,9 +238,9 @@ seven sink_4_1267(volatile A&&); // { dg-message "" }
int test4_1267()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1267(va); // { dg-error "lvalue" }
sink_4_1267(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 245 }
@@ -259,9 +259,9 @@ eight sink_4_1268(const volatile A&&); // { dg-message "" }
int test4_1268()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1268(va); // { dg-error "lvalue" }
sink_4_1268(cva); // { dg-error "lvalue" }
return 0;
@@ -275,9 +275,9 @@ eight sink_4_1278(const volatile A&&); // { dg-message "" }
int test4_1278()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1278(va); // { dg-error "lvalue" }
sink_4_1278(cva); // { dg-error "lvalue" }
return 0;
@@ -291,9 +291,9 @@ five sink_4_1345( A&&); // { dg-message "note" }
int test4_1345()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1345(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 297 }
sink_4_1345(v_source()); // { dg-error "no match" }
@@ -311,9 +311,9 @@ six sink_4_1346(const A&&); // { dg-message "note" }
int test4_1346()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1346(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 317 }
sink_4_1346(cv_source()); // { dg-error "no match" }
@@ -329,9 +329,9 @@ seven sink_4_1347(volatile A&&); // { dg-message "note" }
int test4_1347()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1347(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 335 }
sink_4_1347(cv_source()); // { dg-error "no match" }
@@ -347,9 +347,9 @@ six sink_4_1356(const A&&); // { dg-message "" }
int test4_1356()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1356(ca); // { dg-error "lvalue" }
sink_4_1356(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 354 }
@@ -368,9 +368,9 @@ seven sink_4_1357(volatile A&&); // { dg-message "note" }
int test4_1357()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1357(ca); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 374 }
sink_4_1357(cva); // { dg-error "no match" }
@@ -390,9 +390,9 @@ eight sink_4_1358(const volatile A&&); // { dg-message "" }
int test4_1358()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1358(ca); // { dg-error "lvalue" }
sink_4_1358(cva); // { dg-error "lvalue" }
return 0;
@@ -406,9 +406,9 @@ seven sink_4_1367(volatile A&&); // { dg-message "note" }
int test4_1367()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1367(ca); // { dg-error "lvalue" }
sink_4_1367(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 413 }
@@ -427,9 +427,9 @@ eight sink_4_1368(const volatile A&&); // { dg-message "" }
int test4_1368()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1368(ca); // { dg-error "lvalue" }
sink_4_1368(cva); // { dg-error "lvalue" }
return 0;
@@ -443,9 +443,9 @@ eight sink_4_1378(const volatile A&&); // { dg-message "" }
int test4_1378()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1378(ca); // { dg-error "lvalue" }
sink_4_1378(cva); // { dg-error "lvalue" }
return 0;
@@ -459,9 +459,9 @@ six sink_4_1456(const A&&); // { dg-message "note" }
int test4_1456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 465 }
sink_4_1456(cv_source()); // { dg-error "no match" }
@@ -477,9 +477,9 @@ seven sink_4_1457(volatile A&&); // { dg-message "note" }
int test4_1457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1457(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 483 }
sink_4_1457(cv_source()); // { dg-error "no match" }
@@ -495,9 +495,9 @@ seven sink_4_1467(volatile A&&); // { dg-message "note" }
int test4_1467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 501 }
sink_4_1467(cv_source()); // { dg-error "no match" }
@@ -513,9 +513,9 @@ seven sink_4_1567(volatile A&&); // { dg-message "" }
int test4_1567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1567(ca); // { dg-error "lvalue" }
sink_4_1567(va); // { dg-error "lvalue" }
sink_4_1567(cva); // { dg-error "no match" }
@@ -533,9 +533,9 @@ eight sink_4_1568(const volatile A&&); // { dg-message "" }
int test4_1568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1568(ca); // { dg-error "lvalue" }
sink_4_1568(va); // { dg-error "lvalue" }
sink_4_1568(cva); // { dg-error "lvalue" }
@@ -550,9 +550,9 @@ eight sink_4_1578(const volatile A&&); // { dg-message "" }
int test4_1578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1578(ca); // { dg-error "lvalue" }
sink_4_1578(va); // { dg-error "lvalue" }
sink_4_1578(cva); // { dg-error "lvalue" }
@@ -567,9 +567,9 @@ eight sink_4_1678(const volatile A&&); // { dg-message "" }
int test4_1678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_1678(ca); // { dg-error "lvalue" }
sink_4_1678(va); // { dg-error "lvalue" }
sink_4_1678(cva); // { dg-error "lvalue" }
@@ -586,9 +586,9 @@ five sink_4_2345( A&&); // { dg-message "note" }
int test4_2345()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2345(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 592 }
sink_4_2345(v_source()); // { dg-error "no match" }
@@ -606,9 +606,9 @@ six sink_4_2346(const A&&); // { dg-message "note" }
int test4_2346()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2346(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 612 }
sink_4_2346(v_source()); // { dg-error "no match" }
@@ -626,9 +626,9 @@ seven sink_4_2347(volatile A&&); // { dg-message "note" }
int test4_2347()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2347(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 632 }
sink_4_2347(cv_source()); // { dg-error "no match" }
@@ -644,9 +644,9 @@ eight sink_4_2348(const volatile A&&); // { dg-message "note" }
int test4_2348()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2348(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 650 }
return 0;
@@ -660,9 +660,9 @@ six sink_4_2356(const A&&); // { dg-message "note" }
int test4_2356()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2356(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 666 }
sink_4_2356(cva); // { dg-error "no match" }
@@ -682,9 +682,9 @@ seven sink_4_2357(volatile A&&); // { dg-message "note" }
int test4_2357()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2357(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 688 }
sink_4_2357(cva); // { dg-error "no match" }
@@ -702,9 +702,9 @@ eight sink_4_2358(const volatile A&&); // { dg-message "" }
int test4_2358()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2358(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 708 }
sink_4_2358(cva); // { dg-error "lvalue" }
@@ -719,9 +719,9 @@ seven sink_4_2367(volatile A&&); // { dg-message "note" }
int test4_2367()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2367(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 725 }
sink_4_2367(cva); // { dg-error "no match" }
@@ -741,9 +741,9 @@ eight sink_4_2368(const volatile A&&); // { dg-message "" }
int test4_2368()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2368(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 747 }
sink_4_2368(cva); // { dg-error "lvalue" }
@@ -758,9 +758,9 @@ eight sink_4_2378(const volatile A&&); // { dg-message "" }
int test4_2378()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2378(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 764 }
sink_4_2378(cva); // { dg-error "lvalue" }
@@ -775,9 +775,9 @@ six sink_4_2456(const A&&); // { dg-message "note" }
int test4_2456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 781 }
sink_4_2456(cv_source()); // { dg-error "no match" }
@@ -793,9 +793,9 @@ seven sink_4_2457(volatile A&&); // { dg-message "note" }
int test4_2457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2457(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 799 }
return 0;
@@ -809,9 +809,9 @@ seven sink_4_2467(volatile A&&); // { dg-message "note" }
int test4_2467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 815 }
sink_4_2467(cv_source()); // { dg-error "no match" }
@@ -827,9 +827,9 @@ seven sink_4_2567(volatile A&&); // { dg-message "" }
int test4_2567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2567(va); // { dg-error "lvalue" }
sink_4_2567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 834 }
@@ -846,9 +846,9 @@ eight sink_4_2568(const volatile A&&); // { dg-message "" }
int test4_2568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2568(va); // { dg-error "lvalue" }
sink_4_2568(cva); // { dg-error "lvalue" }
return 0;
@@ -862,9 +862,9 @@ eight sink_4_2578(const volatile A&&); // { dg-message "" }
int test4_2578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2578(va); // { dg-error "lvalue" }
sink_4_2578(cva); // { dg-error "lvalue" }
return 0;
@@ -878,9 +878,9 @@ eight sink_4_2678(const volatile A&&); // { dg-message "" }
int test4_2678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_2678(va); // { dg-error "lvalue" }
sink_4_2678(cva); // { dg-error "lvalue" }
sink_4_2678(source()); // { dg-error "ambiguous" }
@@ -896,9 +896,9 @@ six sink_4_3456(const A&&); // { dg-message "note" }
int test4_3456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 902 }
sink_4_3456(cv_source()); // { dg-error "no match" }
@@ -914,9 +914,9 @@ seven sink_4_3457(volatile A&&); // { dg-message "note" }
int test4_3457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3457(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 920 }
sink_4_3457(cv_source()); // { dg-error "no match" }
@@ -932,9 +932,9 @@ seven sink_4_3467(volatile A&&); // { dg-message "note" }
int test4_3467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 938 }
sink_4_3467(cv_source()); // { dg-error "no match" }
@@ -950,9 +950,9 @@ seven sink_4_3567(volatile A&&); // { dg-message "note" }
int test4_3567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3567(ca); // { dg-error "lvalue" }
sink_4_3567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 957 }
@@ -969,9 +969,9 @@ eight sink_4_3568(const volatile A&&); // { dg-message "" }
int test4_3568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3568(ca); // { dg-error "lvalue" }
sink_4_3568(cva); // { dg-error "lvalue" }
return 0;
@@ -985,9 +985,9 @@ eight sink_4_3578(const volatile A&&); // { dg-message "" }
int test4_3578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3578(ca); // { dg-error "lvalue" }
sink_4_3578(cva); // { dg-error "lvalue" }
return 0;
@@ -1001,9 +1001,9 @@ eight sink_4_3678(const volatile A&&); // { dg-message "" }
int test4_3678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_3678(ca); // { dg-error "lvalue" }
sink_4_3678(cva); // { dg-error "lvalue" }
sink_4_3678(source()); // { dg-error "ambiguous" }
@@ -1019,9 +1019,9 @@ seven sink_4_4567(volatile A&&); // { dg-message "note" }
int test4_4567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_4567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 1025 }
return 0;
@@ -1035,9 +1035,9 @@ eight sink_4_4678(const volatile A&&); // { dg-message "note" }
int test4_4678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_4678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 1041 }
return 0;
@@ -1051,9 +1051,9 @@ eight sink_4_5678(const volatile A&&); // { dg-message "" }
int test4_5678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_4_5678(a); // { dg-error "lvalue" }
sink_4_5678(ca); // { dg-error "lvalue" }
sink_4_5678(va); // { dg-error "lvalue" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv5n.C b/gcc/testsuite/g++.dg/cpp0x/rv5n.C
index 660a68986a0..d9b8cd23988 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv5n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv5n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -39,9 +39,9 @@ five sink_5_12345( A&&); // { dg-message "note" }
int test5_12345()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12345(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 45 }
sink_5_12345(cv_source()); // { dg-error "no match" }
@@ -58,9 +58,9 @@ six sink_5_12346(const A&&); // { dg-message "note" }
int test5_12346()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12346(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 64 }
sink_5_12346(cv_source()); // { dg-error "no match" }
@@ -77,9 +77,9 @@ seven sink_5_12347(volatile A&&); // { dg-message "note" }
int test5_12347()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12347(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 83 }
return 0;
@@ -94,9 +94,9 @@ six sink_5_12356(const A&&); // { dg-message "note" }
int test5_12356()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12356(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 100 }
sink_5_12356(v_source()); // { dg-error "no match" }
@@ -115,9 +115,9 @@ seven sink_5_12357(volatile A&&); // { dg-message "note" }
int test5_12357()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12357(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 121 }
sink_5_12357(cv_source()); // { dg-error "no match" }
@@ -134,9 +134,9 @@ eight sink_5_12358(const volatile A&&); // { dg-message "" }
int test5_12358()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12358(cva); // { dg-error "lvalue" }
return 0;
}
@@ -150,9 +150,9 @@ seven sink_5_12367(volatile A&&); // { dg-message "note" }
int test5_12367()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12367(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 156 }
sink_5_12367(source()); // { dg-error "ambiguous" }
@@ -171,9 +171,9 @@ eight sink_5_12368(const volatile A&&); // { dg-message "" }
int test5_12368()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12368(cva); // { dg-error "lvalue" }
return 0;
}
@@ -187,9 +187,9 @@ eight sink_5_12378(const volatile A&&); // { dg-message "" }
int test5_12378()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12378(cva); // { dg-error "lvalue" }
return 0;
}
@@ -203,9 +203,9 @@ six sink_5_12456(const A&&); // { dg-message "note" }
int test5_12456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 209 }
sink_5_12456(cv_source()); // { dg-error "no match" }
@@ -222,9 +222,9 @@ seven sink_5_12457(volatile A&&); // { dg-message "note" }
int test5_12457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12457(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 228 }
return 0;
@@ -239,9 +239,9 @@ seven sink_5_12467(volatile A&&); // { dg-message "note" }
int test5_12467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 245 }
sink_5_12467(cv_source()); // { dg-error "no match" }
@@ -258,9 +258,9 @@ seven sink_5_12567(volatile A&&); // { dg-message "" }
int test5_12567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12567(va); // { dg-error "lvalue" }
sink_5_12567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 265 }
@@ -278,9 +278,9 @@ eight sink_5_12568(const volatile A&&); // { dg-message "" }
int test5_12568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12568(va); // { dg-error "lvalue" }
sink_5_12568(cva); // { dg-error "lvalue" }
return 0;
@@ -295,9 +295,9 @@ eight sink_5_12578(const volatile A&&); // { dg-message "" }
int test5_12578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12578(va); // { dg-error "lvalue" }
sink_5_12578(cva); // { dg-error "lvalue" }
return 0;
@@ -312,9 +312,9 @@ eight sink_5_12678(const volatile A&&); // { dg-message "" }
int test5_12678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_12678(va); // { dg-error "lvalue" }
sink_5_12678(cva); // { dg-error "lvalue" }
sink_5_12678(source()); // { dg-error "ambiguous" }
@@ -331,9 +331,9 @@ six sink_5_13456(const A&&); // { dg-message "note" }
int test5_13456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 337 }
sink_5_13456(cv_source()); // { dg-error "no match" }
@@ -350,9 +350,9 @@ seven sink_5_13457(volatile A&&); // { dg-message "note" }
int test5_13457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13457(c_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 356 }
sink_5_13457(cv_source()); // { dg-error "no match" }
@@ -369,9 +369,9 @@ seven sink_5_13467(volatile A&&); // { dg-message "note" }
int test5_13467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 375 }
sink_5_13467(cv_source()); // { dg-error "no match" }
@@ -388,9 +388,9 @@ seven sink_5_13567(volatile A&&); // { dg-message "note" }
int test5_13567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13567(ca); // { dg-error "lvalue" }
sink_5_13567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 395 }
@@ -408,9 +408,9 @@ eight sink_5_13568(const volatile A&&); // { dg-message "" }
int test5_13568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13568(ca); // { dg-error "lvalue" }
sink_5_13568(cva); // { dg-error "lvalue" }
return 0;
@@ -425,9 +425,9 @@ eight sink_5_13578(const volatile A&&); // { dg-message "" }
int test5_13578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13578(ca); // { dg-error "lvalue" }
sink_5_13578(cva); // { dg-error "lvalue" }
return 0;
@@ -442,9 +442,9 @@ eight sink_5_13678(const volatile A&&); // { dg-message "" }
int test5_13678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_13678(ca); // { dg-error "lvalue" }
sink_5_13678(cva); // { dg-error "lvalue" }
sink_5_13678(source()); // { dg-error "ambiguous" }
@@ -461,9 +461,9 @@ seven sink_5_14567(volatile A&&); // { dg-message "note" }
int test5_14567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_14567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 467 }
return 0;
@@ -478,9 +478,9 @@ eight sink_5_14678(const volatile A&&); // { dg-message "note" }
int test5_14678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_14678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 484 }
return 0;
@@ -495,9 +495,9 @@ eight sink_5_15678(const volatile A&&); // { dg-message "" }
int test5_15678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_15678(ca); // { dg-error "lvalue" }
sink_5_15678(va); // { dg-error "lvalue" }
sink_5_15678(cva); // { dg-error "lvalue" }
@@ -513,9 +513,9 @@ six sink_5_23456(const A&&); // { dg-message "note" }
int test5_23456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23456(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 519 }
sink_5_23456(v_source()); // { dg-error "no match" }
@@ -534,9 +534,9 @@ seven sink_5_23457(volatile A&&); // { dg-message "note" }
int test5_23457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23457(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 540 }
sink_5_23457(cv_source()); // { dg-error "no match" }
@@ -553,9 +553,9 @@ eight sink_5_23458(const volatile A&&); // { dg-message "note" }
int test5_23458()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23458(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 559 }
return 0;
@@ -570,9 +570,9 @@ seven sink_5_23467(volatile A&&); // { dg-message "note" }
int test5_23467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23467(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 576 }
sink_5_23467(source()); // { dg-error "ambiguous" }
@@ -591,9 +591,9 @@ eight sink_5_23468(const volatile A&&); // { dg-message "note" }
int test5_23468()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23468(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 597 }
return 0;
@@ -608,9 +608,9 @@ eight sink_5_23478(const volatile A&&); // { dg-message "note" }
int test5_23478()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23478(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 614 }
return 0;
@@ -625,9 +625,9 @@ seven sink_5_23567(volatile A&&); // { dg-message "note" }
int test5_23567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23567(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 631 }
sink_5_23567(cva); // { dg-error "no match" }
@@ -646,9 +646,9 @@ eight sink_5_23568(const volatile A&&); // { dg-message "" }
int test5_23568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23568(cva); // { dg-error "lvalue" }
sink_5_23568(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 653 }
@@ -664,9 +664,9 @@ eight sink_5_23578(const volatile A&&); // { dg-message "" }
int test5_23578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23578(cva); // { dg-error "lvalue" }
sink_5_23578(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 671 }
@@ -682,9 +682,9 @@ eight sink_5_23678(const volatile A&&); // { dg-message "" }
int test5_23678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_23678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 688 }
sink_5_23678(cva); // { dg-error "lvalue" }
@@ -702,9 +702,9 @@ seven sink_5_24567(volatile A&&); // { dg-message "note" }
int test5_24567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_24567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 708 }
return 0;
@@ -719,9 +719,9 @@ eight sink_5_24678(const volatile A&&); // { dg-message "note" }
int test5_24678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_24678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 725 }
return 0;
@@ -736,9 +736,9 @@ eight sink_5_25678(const volatile A&&); // { dg-message "" }
int test5_25678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_25678(va); // { dg-error "lvalue" }
sink_5_25678(cva); // { dg-error "lvalue" }
return 0;
@@ -753,9 +753,9 @@ seven sink_5_34567(volatile A&&); // { dg-message "note" }
int test5_34567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_34567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 759 }
return 0;
@@ -770,9 +770,9 @@ eight sink_5_34678(const volatile A&&); // { dg-message "note" }
int test5_34678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_34678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 776 }
return 0;
@@ -787,9 +787,9 @@ eight sink_5_35678(const volatile A&&); // { dg-message "" }
int test5_35678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_5_35678(ca); // { dg-error "lvalue" }
sink_5_35678(cva); // { dg-error "lvalue" }
return 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv6n.C b/gcc/testsuite/g++.dg/cpp0x/rv6n.C
index d0fdbb7e509..fbc932de1ef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv6n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv6n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -40,9 +40,9 @@ six sink_6_123456(const A&&); // { dg-message "note" }
int test6_123456()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123456(v_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 46 }
sink_6_123456(cv_source()); // { dg-error "no match" }
@@ -60,9 +60,9 @@ seven sink_6_123457(volatile A&&); // { dg-message "note" }
int test6_123457()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123457(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 66 }
return 0;
@@ -78,9 +78,9 @@ eight sink_6_235678(const volatile A&&); // { dg-message "" }
int test6_235678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_235678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 84 }
sink_6_235678(cva); // { dg-error "lvalue" }
@@ -97,9 +97,9 @@ eight sink_6_234678(const volatile A&&); // { dg-message "note" }
int test6_234678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_234678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 103 }
sink_6_234678(source()); // { dg-error "ambiguous" }
@@ -117,9 +117,9 @@ eight sink_6_234578(const volatile A&&); // { dg-message "note" }
int test6_234578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_234578(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 123 }
return 0;
@@ -135,9 +135,9 @@ eight sink_6_234568(const volatile A&&); // { dg-message "note" }
int test6_234568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_234568(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 141 }
return 0;
@@ -153,9 +153,9 @@ seven sink_6_234567(volatile A&&); // { dg-message "note" }
int test6_234567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_234567(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 159 }
sink_6_234567(cv_source()); // { dg-error "no match" }
@@ -173,9 +173,9 @@ eight sink_6_134678(const volatile A&&); // { dg-message "note" }
int test6_134678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_134678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 179 }
return 0;
@@ -191,9 +191,9 @@ eight sink_6_124678(const volatile A&&); // { dg-message "note" }
int test6_124678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_124678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 197 }
return 0;
@@ -209,9 +209,9 @@ eight sink_6_123678(const volatile A&&); // { dg-message "" }
int test6_123678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123678(cva); // { dg-error "lvalue" }
sink_6_123678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 216 }
@@ -228,9 +228,9 @@ seven sink_6_123567(volatile A&&); // { dg-message "note" }
int test6_123567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123567(cva); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 234 }
sink_6_123567(cv_source()); // { dg-error "no match" }
@@ -248,9 +248,9 @@ eight sink_6_123568(const volatile A&&); // { dg-message "" }
int test6_123568()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123568(cva); // { dg-error "lvalue" }
return 0;
}
@@ -265,9 +265,9 @@ eight sink_6_123578(const volatile A&&); // { dg-message "" }
int test6_123578()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123578(cva); // { dg-error "lvalue" }
return 0;
}
@@ -282,9 +282,9 @@ seven sink_6_123467(volatile A&&); // { dg-message "note" }
int test6_123467()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_123467(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 288 }
sink_6_123467(cv_source()); // { dg-error "no match" }
@@ -302,9 +302,9 @@ seven sink_6_124567(volatile A&&); // { dg-message "note" }
int test6_124567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_124567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 308 }
return 0;
@@ -320,9 +320,9 @@ eight sink_6_125678(const volatile A&&); // { dg-message "" }
int test6_125678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_125678(va); // { dg-error "lvalue" }
sink_6_125678(cva); // { dg-error "lvalue" }
return 0;
@@ -338,9 +338,9 @@ seven sink_6_134567(volatile A&&); // { dg-message "note" }
int test6_134567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_134567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 344 }
return 0;
@@ -356,9 +356,9 @@ eight sink_6_135678(const volatile A&&); // { dg-message "" }
int test6_135678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_6_135678(ca); // { dg-error "lvalue" }
sink_6_135678(cva); // { dg-error "lvalue" }
return 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv7n.C b/gcc/testsuite/g++.dg/cpp0x/rv7n.C
index 6071e056813..206cc79bb14 100644
--- a/gcc/testsuite/g++.dg/cpp0x/rv7n.C
+++ b/gcc/testsuite/g++.dg/cpp0x/rv7n.C
@@ -20,7 +20,7 @@ struct eight {char x[8];};
struct A
{
A();
- A(const volatile A&&); // { dg-error "argument 1" }
+ A(const volatile A&&);
};
A source();
@@ -41,9 +41,9 @@ seven sink_7_1234567(volatile A&&); // { dg-message "note" }
int test7_1234567()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_7_1234567(cv_source()); // { dg-error "no match" }
// { dg-message "candidate" "candidate note" { target *-*-* } 47 }
return 0;
@@ -60,9 +60,9 @@ eight sink_7_1235678(const volatile A&&); // { dg-message "" }
int test7_1235678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_7_1235678(cva); // { dg-error "lvalue" }
return 0;
}
@@ -78,9 +78,9 @@ eight sink_7_2345678(const volatile A&&); // { dg-message "note" }
int test7_2345678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_7_2345678(a); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 84 }
return 0;
@@ -97,9 +97,9 @@ eight sink_7_1234678(const volatile A&&); // { dg-message "note" }
int test7_1234678()
{
A a;
- const A ca = a; // { dg-error "lvalue" }
+ const A ca = a; // { dg-error "deleted" }
volatile A va;
- const volatile A cva = a; // { dg-error "lvalue" }
+ const volatile A cva = a; // { dg-error "deleted" }
sink_7_1234678(source()); // { dg-error "ambiguous" }
// { dg-message "candidate" "candidate note" { target *-*-* } 103 }
return 0;
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C b/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C
new file mode 100644
index 00000000000..7d3286e007b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C
@@ -0,0 +1,10 @@
+// { dg-options "-std=c++0x" }
+
+#include <cstddef>
+
+bool operator"" _yn(const char*, size_t);
+
+typedef bool (*pfunk)(const char*, size_t);
+pfunk p = &operator"" _yn;
+
+bool tf = p("Hello,\0 World!", 14);
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
new file mode 100644
index 00000000000..cb924a249bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
@@ -0,0 +1,38 @@
+// { dg-options -std=c++0x }
+
+#include <cstddef>
+
+class Foo { };
+
+Foo
+operator"" _Foo(int *); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(unsigned long int); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(double); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(const float *, std::size_t); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(const wchar_t *, int); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(const char16_t *); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(char...); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(unsigned long long int, char); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(const char *, std::size_t, int); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(long double &); // { dg-error "has invalid argument list" }
+
+Foo
+operator"" _Foo(std::size_t, const char16_t *); // { dg-error "has invalid argument list" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-args.C b/gcc/testsuite/g++.dg/cpp0x/udlit-args.C
new file mode 100644
index 00000000000..ca2039c59d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-args.C
@@ -0,0 +1,38 @@
+// { dg-options -std=c++0x }
+
+#include <cstddef>
+
+class Foo { };
+
+Foo
+operator"" _Foo(const char *);
+
+Foo
+operator"" _Foo(unsigned long long int);
+
+Foo
+operator"" _Foo(long double);
+
+Foo
+operator"" _Foo(char);
+
+Foo
+operator"" _Foo(wchar_t);
+
+Foo
+operator"" _Foo(char16_t);
+
+Foo
+operator"" _Foo(char32_t);
+
+Foo
+operator"" _Foo(const char *, std::size_t);
+
+Foo
+operator"" _Foo(const wchar_t *, std::size_t);
+
+Foo
+operator"" _Foo(const char16_t *, std::size_t);
+
+Foo
+operator"" _Foo(const char32_t *, std::size_t);
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C
new file mode 100644
index 00000000000..a80e7244afd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C
@@ -0,0 +1,8 @@
+// { dg-options -std=c++0x }
+
+extern "C" {
+
+int
+operator"" _badclinkage(unsigned long long); // { dg-error "operator with C linkage" }
+
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C
new file mode 100644
index 00000000000..61dc2ab02c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+#include <string>
+
+std::string operator"" _xxx(const char*, size_t);
+
+std::string operator"" _yyy(const char*, size_t);
+
+std::string concat = "Hello, "_xxx "World!"_yyy; // { dg-error "inconsistent user-defined literal suffixes" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C b/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C
new file mode 100644
index 00000000000..612bc1d1116
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C
@@ -0,0 +1,24 @@
+// { dg-options "-std=c++0x" }
+
+#include <string>
+
+std::string operator"" _www(const char*, size_t);
+
+std::string concat01 = "Hello, " "World!"_www;
+
+std::string concat10 = "Hello, "_www "World!";
+
+std::string concat11 = "Hello, "_www "World!"_www;
+
+
+class Tachyon { };
+
+Tachyon operator"" _fast(const char*, size_t);
+
+int operator"" _fast(const char32_t*, size_t);
+
+int speedy01 = "Hello, " U"World!"_fast;
+
+int speedy10 = "Hello, "_fast U"World!";
+
+int speedy11 = "Hello, "_fast U"World!"_fast;
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C b/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C
new file mode 100644
index 00000000000..40b0dfac531
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C
@@ -0,0 +1,7 @@
+// { dg-options -std=c++0x }
+
+constexpr unsigned long long
+operator"" _grow(unsigned long long n)
+{ return 2 * n; }
+
+double buffer[25_grow];
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-cpp98-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-cpp98-neg.C
new file mode 100644
index 00000000000..cb78a2c9c3e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-cpp98-neg.C
@@ -0,0 +1,17 @@
+// { dg-options "-std=c++98" }
+
+#include <cstddef>
+
+int
+operator"" _mm(long double m) // { dg-warning "user-defined literals only available with" }
+{ return int(1000.0L * m); }
+
+int in = 0.0254_mm; // { dg-error "invalid suffix" }
+
+int
+operator"" _Q(const char *, std::size_t) // { dg-warning "user-defined literals only available with" }
+{ return 42; }
+
+int x = "Hello"_Q; // { dg-error "invalid conversion from" }
+
+// { dg-error "expected" "" { target *-*-* } 15 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
new file mode 100644
index 00000000000..7b50c017f01
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C
@@ -0,0 +1,15 @@
+// { dg-options "-std=c++0x" }
+
+// Check that undeclared literal operator calls and literals give appropriate errors.
+
+int i = operator"" _Bar('x'); // { dg-error "was not declared in this scope" }
+int j = 'x'_Bar; // { dg-error "unable to find user-defined character literal operator" }
+
+int ii = operator"" _BarCharStr("Howdy, Pardner!"); // { dg-error "was not declared in this scope" }
+int jj = "Howdy, Pardner!"_BarCharStr; // { dg-error "unable to find user-defined string literal operator" }
+
+unsigned long long iULL = operator"" _BarULL(666ULL); // { dg-error "was not declared in this scope" }
+unsigned long long jULL = 666_BarULL; // { dg-error "unable to find user-defined numeric literal operator" }
+
+long double iLD = operator"" _BarLD(666.0L); // { dg-error "was not declared in this scope" }
+long double jLD = 666.0_BarLD; // { dg-error "unable to find user-defined numeric literal operator" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C b/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C
new file mode 100644
index 00000000000..48a2a1b171d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C
@@ -0,0 +1,34 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+// Make sure embedded quotes are not a problem for string and char literals.
+
+#include <cstdint>
+#include <cassert>
+
+int operator"" _embedchar(char)
+{ return 41; };
+
+int operator"" _embedstr(const char*, std::size_t len)
+{ return 42 + len; };
+
+void
+test()
+{
+ int i = '\''_embedchar;
+
+ int j = "\""_embedstr;
+ assert(j == 43);
+
+ int k = "foo\""_embedstr;
+ assert(k == 46);
+
+ int l = "\"bar"_embedstr;
+ assert(l == 46);
+}
+
+int
+main()
+{
+ test();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C b/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C
new file mode 100644
index 00000000000..b3f3ef8a604
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C
@@ -0,0 +1,28 @@
+// { dg-options -std=c++0x }
+
+long double
+operator"" _Hertz(long double);
+
+class Foo
+{
+public:
+ Foo() { }
+
+ friend Foo operator"" _Bar(char);
+
+ friend long double
+ operator"" _Hertz(long double omega)
+ { return omega / 6.28318530717958648; }
+};
+
+Foo
+operator"" _Bar(char)
+{ return Foo(); }
+
+Foo f1 = operator"" _Bar('x');
+
+Foo f2 = 'x'_Bar;
+
+long double fm1 = operator"" _Hertz(552.92L);
+
+long double fm2 = 552.92_Hertz;
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-general.C b/gcc/testsuite/g++.dg/cpp0x/udlit-general.C
new file mode 100644
index 00000000000..9e448ac8050
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-general.C
@@ -0,0 +1,52 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+// Test user-defined literals.
+// Test simple operator declaration and definition.
+
+#include <cstring>
+#include <string>
+#include <complex>
+#include <cassert>
+
+long double operator"" _v(long double);
+std::string operator"" _w(const char16_t*, size_t);
+unsigned operator"" _w(const char*);
+
+std::complex<double>
+operator"" _i(long double y)
+{ return std::complex<double>(0.0L, y); }
+
+void
+test1()
+{
+ long double x = operator"" _v(1.2L);
+ assert(x == 2.2L);
+
+ std::string s = operator"" _w(u"one", 3);
+ assert(s == "boo");
+
+ unsigned u = operator"" _w("Hello, World!");
+ assert(u == 13U);
+
+ std::complex<double> i = operator"" _i(2.0);
+ assert(i == std::complex<double>(0.0, 2.0));
+}
+
+int
+main()
+{
+ test1();
+}
+
+long double
+operator"" _v(long double x)
+{ return x + 1.0L; }
+
+std::string
+operator"" _w(const char16_t*, size_t)
+{ return std::string("boo"); }
+
+unsigned
+operator"" _w(const char* str)
+{ return strlen(str); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C b/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C
new file mode 100644
index 00000000000..75032c57679
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C
@@ -0,0 +1,22 @@
+// { dg-options "-std=c++0x" }
+
+// Literal operators can be inline.
+
+inline int
+operator"" _thing1(char cc)
+{ return 42 * cc; }
+
+int operator"" _thing2(char cc);
+
+class Foo
+{
+ int
+ friend operator"" _thing2(char cc)
+ { return 42 * cc; }
+};
+
+int i = operator"" _thing1('x');
+int j = 'x'_thing1;
+
+int iF = operator"" _thing2('x');
+int jF = 'x'_thing2;
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C
new file mode 100644
index 00000000000..c2ecede8d48
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C
@@ -0,0 +1,7 @@
+// { dg-options -std=c++0x }
+
+extern "C"_badlinkage { // { dg-error "expected unqualified-id before" }
+
+int foo();
+
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
new file mode 100644
index 00000000000..809df254c0e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C
@@ -0,0 +1,15 @@
+// { dg-options -std=c++0x }
+
+class Foo
+{
+public:
+ Foo() { }
+ int operator"" _Bar(char32_t); // { dg-error "must be a non-member function" }
+};
+
+int i = operator"" _Bar(U'x'); // { dg-error "was not declared in this scope" }
+int j = U'x'_Bar; // { dg-error "unable to find user-defined character literal operator" }
+
+int
+Foo::operator"" _Bar(char32_t) // { dg-error "must be a non-member function" }
+{ return 42; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C
new file mode 100644
index 00000000000..e5d54e51900
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C
@@ -0,0 +1,43 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+// Test user-defined literals.
+// Test simple operator declaration and definition in namespaces.
+
+#include <cmath>
+#include <limits>
+
+namespace Long
+{
+ long double operator"" _LL(long double);
+}
+
+namespace Short
+{
+ short
+ operator"" _SS(long double x)
+ { return std::fmod(x, static_cast<long double>(std::numeric_limits<short>::max())); }
+}
+
+void
+test1()
+{
+ long double x = Long::operator "" _LL(1.2L);
+
+ using namespace Short;
+ short s = operator"" _SS(1.2L);
+ short s2 = 1.2_SS;
+}
+
+int
+main()
+{
+ test1();
+}
+
+namespace Long
+{
+ long double
+ operator"" _LL(long double x)
+ { return x + 2.0L; }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
new file mode 100644
index 00000000000..6ad79b85b1d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+// Test user-defined literals.
+// Test error on non-function declaration.
+
+double operator"" _baddecl; // { dg-error "as non-function" }
+
+template<char...>
+ int operator"" _badtmpldecl; // { dg-error "as non-function" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C
new file mode 100644
index 00000000000..981865f1526
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C
@@ -0,0 +1,6 @@
+// { dg-options "-std=c++0x" }
+
+// Test user-defined literals.
+// Test error on non-empty string after 'operator' keyword.
+
+double operator"hi" _badword(long double); // { dg-error "expected empty string after" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C
new file mode 100644
index 00000000000..2b57637a916
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C
@@ -0,0 +1,3 @@
+// { dg-options "-std=c++0x" }
+
+float operator ""_abc(const char*); // { dg-error "missing space between|and suffix identifier" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C
new file mode 100644
index 00000000000..b90635cd0fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C
@@ -0,0 +1,5 @@
+// { dg-options -std=c++0x }
+
+char32_t
+operator"" (char32_t C) // { dg-error "expected suffix identifier" }
+{ return C; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C
new file mode 100644
index 00000000000..2067bbe561f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+// Test user-defined literals.
+// Test warning on declaration without leading underscore.
+
+long double operator"" nounder(long double); // { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" }
+
+template<char...>
+ int operator"" nounder(); // { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C
new file mode 100644
index 00000000000..27fdedec766
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C
@@ -0,0 +1,42 @@
+// { dg-options "-std=c++0x" }
+
+// Can't have *both* literal operator template and raw literal operator.
+
+int
+operator"" _abc(const char*)
+ {
+ return 42;
+ }
+
+template<char...>
+ int
+ operator"" _abc() // { dg-error "literal operator template|conflicts with raw literal operator" }
+ {
+ return 13;
+ }
+
+template<char...>
+ int
+ operator"" _def()
+ {
+ return 12;
+ }
+
+int
+operator"" _def(const char*) // { dg-error "raw literal operator|conflicts with literal operator template" }
+ {
+ return 43;
+ }
+
+int
+operator"" _ghi(long double)
+ {
+ return 42;
+ }
+
+template<char...>
+ int
+ operator"" _ghi() // OK
+ {
+ return 13;
+ }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C
new file mode 100644
index 00000000000..23633390cf0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+int
+operator"" _badpreproc(const char *str)
+{ return 0; }
+
+#if 123_badpreproc // { dg-error "user-defined literal in preprocessor expression" }
+# error ("user-defined literal in preprocessor expression") // { dg-error "user-defined literal in preprocessor expression" }
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C
new file mode 100644
index 00000000000..5c399aff599
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+
+// Make sure handing a string to a raw literal generates a sensible error message.
+
+int operator"" _embedraw(const char*)
+{ return 41; };
+
+int k = "Boo!"_embedraw; // { dg-error "unable to find valid user-defined string literal operator" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C
new file mode 100644
index 00000000000..3bbf19cb05c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C
@@ -0,0 +1,21 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+#include <cassert>
+#include <cstring>
+
+int
+operator"" _raw_umber(const char * str)
+{
+ return strlen(str);
+}
+
+int
+main()
+{
+ int i = 0123012301230123012301230123012301230123012301230123012301230123_raw_umber;
+ assert( i == 64 );
+
+ int j = 90123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789_raw_umber;
+ assert( j == 101 );
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C
new file mode 100644
index 00000000000..e94410fd061
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C
@@ -0,0 +1,15 @@
+// { dg-options -std=c++0x }
+
+#include <string>
+
+std::string operator"" _i18n(const char*, std::size_t);
+
+std::string vogon_poem = R"V0G0N(
+ O freddled gruntbuggly thy micturations are to me
+ As plured gabbleblochits on a lurgid bee.
+ Groop, I implore thee my foonting turlingdromes.
+ And hooptiously drangle me with crinkly bindlewurdles,
+ Or I will rend thee in the gobberwarts with my blurlecruncheon, see if I don't.
+
+ (by Prostetnic Vogon Jeltz; see p. 56/57)
+)V0G0N"_i18n;
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
new file mode 100644
index 00000000000..6d38252ff2a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C
@@ -0,0 +1,49 @@
+// { dg-options -std=c++0x }
+
+// Test that the standard suffixes shadow any user-defined suffixes of the same name.
+long double
+operator"" L(long double x) // { dg-warning "floating point suffix|shadowed by implementation" }
+{ return x; }
+
+unsigned long long int
+operator"" ULL(unsigned long long int k) // { dg-warning "integer suffix|shadowed by implementation" }
+{ return k; }
+
+long double
+operator"" l(long double x) // { dg-warning "floating point suffix|shadowed by implementation" }
+{ return x; }
+
+unsigned long long int
+operator"" ull(unsigned long long int k) // { dg-warning "integer suffix|shadowed by implementation" }
+{ return k; }
+
+// Namespaces are no hiding place.
+namespace Long
+{
+
+long double
+operator"" L(long double x) // { dg-warning "integer suffix|shadowed by implementation" }
+{ return x; }
+
+unsigned long long int
+operator"" ULL(unsigned long long int k) // { dg-warning "integer suffix|shadowed by implementation" }
+{ return k; }
+
+long double
+operator"" l(long double x) // { dg-warning "integer suffix|shadowed by implementation" }
+{ return x; }
+
+unsigned long long int
+operator"" ull(unsigned long long int k) // { dg-warning "integer suffix|shadowed by implementation" }
+{ return k; }
+
+}
+
+// { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" "" { target *-*-* } 5 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" "" { target *-*-* } 9 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" "" { target *-*-* } 13 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" "" { target *-*-* } 17 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" "" { target *-*-* } 25 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" "" { target *-*-* } 29 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" "" { target *-*-* } 33 }
+// { dg-warning "literal operator suffixes not preceded by|are reserved for future standardization" "" { target *-*-* } 37 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C
new file mode 100644
index 00000000000..56eab01d736
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C
@@ -0,0 +1,5 @@
+// { dg-options -std=c++0x }
+
+#include <string>
+
+std::string operator"" 5X(const char*, std::size_t); // { dg-error "expected suffix identifier" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C b/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C
new file mode 100644
index 00000000000..599c8652a14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C
@@ -0,0 +1,3 @@
+// { dg-options -std=c++0x }
+
+#include "udlit_system_header"
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-template.C b/gcc/testsuite/g++.dg/cpp0x/udlit-template.C
new file mode 100644
index 00000000000..6a28f74a22b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-template.C
@@ -0,0 +1,51 @@
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+// Test user-defined literals.
+// Test template operator declaration and definition.
+
+#include <cassert>
+
+template<char...>
+ int operator"" _abc();
+
+template<>
+ int
+ operator"" _abc<>()
+ { return -1; }
+
+template<>
+ int
+ operator"" _abc<'L','U','E'>()
+ { return 42; }
+
+template<>
+ int
+ operator"" _abc<'6','6','6'>()
+ { return 21; }
+
+int
+test1()
+{
+ int i = operator"" _abc<'1','2','3'>();
+ assert(i == 45);
+ int universal_meaning = operator"" _abc<'L','U','E'>();
+ assert(universal_meaning == 42);
+ int b = operator"" _abc<'6','6','6'>();
+ int z = operator"" _abc<>();
+ assert(z == -1);
+ int j = 123_abc;
+ assert(j == i);
+ int jb = 666_abc;
+ assert(jb == b);
+}
+
+int
+main()
+{
+ test1();
+}
+
+template<char... Chars>
+ int operator"" _abc()
+ { return 42 + sizeof...(Chars); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C
new file mode 100644
index 00000000000..e8ccb6f545d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C
@@ -0,0 +1,4 @@
+// { dg-options -std=c++0x }
+
+template<char...>
+ int operator"" _xyz(unsigned long long); // { dg-error "has invalid argument list" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C
new file mode 100644
index 00000000000..6324823fabb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C
@@ -0,0 +1,4 @@
+// { dg-options -std=c++0x }
+
+template<char...>
+ int operator"" _abc();
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C
new file mode 100644
index 00000000000..4dab4d2f6f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+class Foo { };
+
+template<wchar_t...>
+ Foo operator"" _Foo(); // { dg-error "literal operator template|has invalid parameter list" }
+
+template<char>
+ Foo operator"" _Bar(); // { dg-error "literal operator template|has invalid parameter list" }
+
+template<typename... Type>
+ Foo operator"" _Bar(); // { dg-error "literal operator template|has invalid parameter list" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C
new file mode 100644
index 00000000000..77456737c70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C
@@ -0,0 +1,6 @@
+// { dg-options -std=c++0x }
+
+class Foo { };
+
+template<char...>
+ Foo operator"" _Foo();
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit_system_header b/gcc/testsuite/g++.dg/cpp0x/udlit_system_header
new file mode 100644
index 00000000000..d541f24f62a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/udlit_system_header
@@ -0,0 +1,6 @@
+
+#pragma GCC system_header
+
+char
+operator"" stdsuffix(char __c)
+{ return __c/2; }
diff --git a/gcc/testsuite/g++.dg/eh/partial1.C b/gcc/testsuite/g++.dg/eh/partial1.C
new file mode 100644
index 00000000000..db731770c2b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/partial1.C
@@ -0,0 +1,37 @@
+// PR c++/41449
+// { dg-do run }
+
+struct A
+{
+ A() {}
+ A(const A&) { throw 1; }
+};
+
+int bs;
+struct B
+{
+ B() { ++bs; }
+ B(const B&) { ++bs; }
+ ~B() { --bs; }
+};
+
+struct C
+{
+ B b1;
+ A a;
+ B b2;
+};
+
+int main()
+{
+ {
+ B b1, b2;
+ A a;
+
+ try {
+ C c = { b1, a, b2 };
+ } catch (...) {}
+ }
+ if (bs != 0)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/bases.C b/gcc/testsuite/g++.dg/ext/bases.C
new file mode 100644
index 00000000000..0582f72eb81
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/bases.C
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++0x -w" }
+// { dg-do run }
+
+#include<typeinfo>
+#include<cassert>
+
+// A simple typelist
+template<typename... _Elements> struct types {};
+
+// Simple bases implementation
+template<typename T> struct b {
+ typedef types<__bases(T)...> type;
+};
+
+// Simple direct_bases implementation
+template<typename T> struct db {
+ typedef types<__direct_bases(T)...> type;
+};
+
+template <class,class> struct assert_same_type;
+template <class T> struct assert_same_type<T,T> {};
+
+struct A {};
+struct C : virtual A {};
+struct D : public C {};
+struct B : D, virtual A {};
+struct E : C, virtual D, B {};
+struct F : A, B, E {};
+
+int main() {
+ assert_same_type<b<F>::type, types<A,C,D,A,C,D,B,C,C,D,B,E>>();
+ assert_same_type<db<F>::type, types<A,B,E>>();
+ assert_same_type<db<int>::type, types<>>();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C b/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
index 8cb1ce38f63..4ccc72b9e94 100644
--- a/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
+++ b/gcc/testsuite/g++.dg/ext/is_base_of_diagnostic.C
@@ -1,7 +1,7 @@
class A
{ };
-class B;
+class B; // { dg-error "forward declaration" }
union C
{ };
diff --git a/gcc/testsuite/g++.dg/ext/is_base_of_incomplete.C b/gcc/testsuite/g++.dg/ext/is_base_of_incomplete.C
new file mode 100644
index 00000000000..4704ff5dee1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_base_of_incomplete.C
@@ -0,0 +1,9 @@
+// PR c++/50732
+
+template <typename T>
+struct non_instantiable
+{
+ typedef typename T::THIS_TYPE_CANNOT_BE_INSTANTIATED type;
+};
+
+int check[__is_base_of(non_instantiable<int>, void) ? -1 : 1];
diff --git a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
index 51cc80cd2ac..ecc5ec224b3 100644
--- a/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
+++ b/gcc/testsuite/g++.dg/ext/unary_trait_incomplete.C
@@ -1,6 +1,6 @@
// PR c++/39475
-struct I;
+struct I; // { dg-error "forward declaration" }
struct C { };
bool nas1 = __has_nothrow_assign(I); // { dg-error "incomplete type" }
diff --git a/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-4.C b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-4.C
new file mode 100644
index 00000000000..ebce2ba5c7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/visibility/fvisibility-inlines-hidden-4.C
@@ -0,0 +1,37 @@
+/* PR c++/30066: Test that -fvisibility-inlines-hidden affects functions. */
+/* { dg-do compile } */
+/* { dg-require-visibility "" } */
+/* { dg-options "-fvisibility-inlines-hidden" } */
+/* { dg-final { scan-hidden "_Z3barv" } } */
+/* { dg-final { scan-not-hidden "_ZZ3barvE1n" } } */
+/* { dg-final { scan-not-hidden "_Z3fooIiEvv" } } */
+/* { dg-final { scan-hidden "_Z3fooIvEvv" } } */
+/* { dg-final { scan-hidden "_ZZN1A5innerEvE1n" } } */
+
+inline int * bar()
+{
+ static int n;
+ return &n;
+}
+
+template <class T>
+inline void foo() { }
+
+template void foo<int>();
+
+namespace A __attribute__ ((visibility ("hidden")))
+{
+ inline int * inner()
+ {
+ static int n;
+ return &n;
+ }
+}
+
+int main(void)
+{
+ bar();
+ foo<void>();
+ A::inner();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/inherit/error5.C b/gcc/testsuite/g++.dg/inherit/error5.C
new file mode 100644
index 00000000000..e38e106b14c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/error5.C
@@ -0,0 +1,14 @@
+// PR c++/48489
+
+struct Base{ };
+
+struct Concrete : Base
+{
+ void setValue();
+};
+
+int main()
+{
+ Concrete d;
+ d.Base::setValue(); // { dg-error "struct Base" }
+}
diff --git a/gcc/testsuite/g++.dg/init/aggr7.C b/gcc/testsuite/g++.dg/init/aggr7.C
new file mode 100644
index 00000000000..bec952c230c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/aggr7.C
@@ -0,0 +1,13 @@
+// PR c++/50866
+
+struct A { A(); ~A(); };
+struct B { B(const char *, const A& = A()); ~B(); };
+struct C {
+ B b1, b2;
+};
+void f()
+{
+ C c = {
+ "a","b"
+ };
+}
diff --git a/gcc/testsuite/g++.dg/init/ref20.C b/gcc/testsuite/g++.dg/init/ref20.C
new file mode 100644
index 00000000000..b64cb57e09d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/ref20.C
@@ -0,0 +1,8 @@
+// PR c++/50787
+// { dg-do run }
+
+int main() {
+ const int Ci = 0;
+ const int &rCi = Ci;
+ if (!(&Ci == &rCi)) __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/init/value9.C b/gcc/testsuite/g++.dg/init/value9.C
new file mode 100644
index 00000000000..4899bd81001
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/value9.C
@@ -0,0 +1,32 @@
+// PR c++/50793
+// { dg-do run }
+
+struct NonTrivial
+{
+ NonTrivial() { }
+};
+
+struct S
+{
+ NonTrivial nt;
+ int i;
+};
+
+int f(S s)
+{
+ s.i = 0xdeadbeef;
+ return s.i;
+}
+
+int g(S s = S())
+{
+ return s.i;
+}
+
+int main()
+{
+ f(S()); // make stack dirty
+
+ if ( g() )
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/init/vbase1.C b/gcc/testsuite/g++.dg/init/vbase1.C
new file mode 100644
index 00000000000..bbfd58f5c34
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/vbase1.C
@@ -0,0 +1,39 @@
+// PR c++/50618
+// { dg-do run }
+
+struct Base
+{
+ const int text;
+ Base():text(1) {}
+ Base(int aText)
+ : text(aText) {}
+};
+struct SubA : public virtual Base
+{
+protected:
+ int x;
+public:
+ SubA(int aX)
+ : x(aX) {}
+};
+class SubB : public virtual Base
+{};
+struct Diamond : public SubA, public SubB
+{
+ Diamond(int text)
+ : Base(text), SubA(5), SubB() {}
+
+ void printText()
+ {
+ if(text != 2)
+ __builtin_abort();
+ if(x!=5)
+ __builtin_abort();
+ }
+};
+
+int main(int, char**)
+{
+ Diamond x(2);
+ x.printText();
+}
diff --git a/gcc/testsuite/g++.dg/lookup/using23.C b/gcc/testsuite/g++.dg/lookup/using23.C
new file mode 100644
index 00000000000..5dd8d8594b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/using23.C
@@ -0,0 +1,13 @@
+// PR c++/50742
+
+typedef int A;
+
+void f(int i)
+{
+ switch (i)
+ {
+ case 0:
+ using ::A;
+ default:;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/overload/operator4.C b/gcc/testsuite/g++.dg/overload/operator4.C
new file mode 100644
index 00000000000..3ec1eb472dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/operator4.C
@@ -0,0 +1,14 @@
+// PR c++/38174
+
+struct VolatileIntPtr {
+ operator int volatile *();
+};
+
+struct ConstIntPtr {
+ operator int const *();
+};
+
+void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip) {
+ bool b1 = (vip == cip);
+ long p1 = vip - cip;
+}
diff --git a/gcc/testsuite/g++.dg/overload/operator5.C b/gcc/testsuite/g++.dg/overload/operator5.C
new file mode 100644
index 00000000000..574defb891b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/operator5.C
@@ -0,0 +1,16 @@
+// PR c++/50858
+
+class String {
+ typedef struct ImplicitConversionFromWTFStringToBoolDisallowedA*
+ (String::*UnspecifiedBoolTypeA);
+ typedef struct ImplicitConversionFromWTFStringToBoolDisallowedB*
+ (String::*UnspecifiedBoolTypeB);
+ operator UnspecifiedBoolTypeA() const;
+ operator UnspecifiedBoolTypeB() const;
+};
+inline bool equalIgnoringCase(const String& a, const String& b) { }
+inline bool equalPossiblyIgnoringCase(const String& a,
+ const String& b,
+ bool ignoreCase) {
+ return ignoreCase ? equalIgnoringCase(a, b) : (a == b); } // { dg-error "ambiguous" }
+// { dg-message "note" { target *-*-* } 15 }
diff --git a/gcc/testsuite/g++.dg/parse/error20.C b/gcc/testsuite/g++.dg/parse/error20.C
index d2f9353a7cc..6119df9b2d1 100644
--- a/gcc/testsuite/g++.dg/parse/error20.C
+++ b/gcc/testsuite/g++.dg/parse/error20.C
@@ -12,7 +12,7 @@ struct C {
};
int main() {
C c;
- A(c.p.i); // { dg-error "9:request for member 'i' in 'c.C::p', which is of non-class type 'B" }
+ A(c.p.i); // { dg-error "9:request for member 'i' in 'c.C::p', which is of pointer type 'B" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/parse/error41.C b/gcc/testsuite/g++.dg/parse/error41.C
new file mode 100644
index 00000000000..621a2e252ed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error41.C
@@ -0,0 +1,11 @@
+// PR c++/44524
+
+template<typename, typename>
+struct map
+{
+ bool empty();
+};
+
+int bar(map<int, float> *X) {
+ return X.empty(); // { dg-error "which is of pointer type 'map" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/error42.C b/gcc/testsuite/g++.dg/parse/error42.C
new file mode 100644
index 00000000000..5e4c5bbdd2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error42.C
@@ -0,0 +1,4 @@
+// PR c++/13657
+
+class C { public: int (*f())(); int bar(); };
+int (*C::f())() { return C::bar; } // { dg-error "cannot convert 'C::bar'" }
diff --git a/gcc/testsuite/g++.dg/parse/error43.C b/gcc/testsuite/g++.dg/parse/error43.C
new file mode 100644
index 00000000000..e352fa5c70d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error43.C
@@ -0,0 +1,5 @@
+// PR c++/31423
+// { dg-options "" }
+
+class C { public: C* f(); int get(); };
+int f(C* p) { return p->f->get(); } // { dg-error "forget the '\\(\\)'|base operand" }
diff --git a/gcc/testsuite/g++.dg/parse/error44.C b/gcc/testsuite/g++.dg/parse/error44.C
new file mode 100644
index 00000000000..2ebbe710c7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error44.C
@@ -0,0 +1,11 @@
+// PR c++/31423
+// { dg-options "-fms-extensions" }
+
+struct C {
+ int f() { return 1; }
+ int g() { return 2; }
+};
+
+int f(C& c) {
+ return c.g == &c.f; // { dg-error "forget the '&'" }
+}
diff --git a/gcc/testsuite/g++.dg/pr50672.C b/gcc/testsuite/g++.dg/pr50672.C
new file mode 100644
index 00000000000..fb310082edc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr50672.C
@@ -0,0 +1,101 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-tail-merge" } */
+typedef int BoxCoordinate;
+typedef int BoxDimension;
+const BoxDimension X = 0;
+const BoxDimension Y = 1;
+const BoxDimension NDimensions = 2;
+class BoxPoint {
+ BoxCoordinate point[NDimensions];
+public:
+ bool isValid() const;
+ void operator += (const BoxPoint& p) {
+ if (isValid() && p.isValid()) {
+ point[X] += p.point[X];
+ }
+ }
+ const BoxCoordinate& operator [] (const BoxDimension& dimension) const {
+ return point[dimension];
+ }
+};
+class BoxRegion {
+public:
+ BoxCoordinate& origin(BoxDimension d) const;
+ BoxCoordinate& space(BoxDimension d) const;
+};
+inline bool operator <= (const BoxPoint& p, const BoxRegion& r) {
+ for (BoxDimension d = X;
+ d <= Y;
+ d++) if (p[d] < r.origin(d) || p[d] >= r.origin(d) + r.space(d))
+return false;
+ return true;
+}
+typedef struct _WidgetRec *Widget;
+struct GraphGC {
+ BoxPoint offsetIfSelected;
+};
+class GraphNode;
+class GraphEdge {
+public:
+ GraphNode *from() const;
+ GraphNode *to() const;
+};
+class LineGraphEdge: public GraphEdge {
+protected:
+ virtual void drawLine(Widget w, const GraphGC& gc) const;
+ void _print(const GraphGC &gc) const;
+};
+class ArcGraphEdge: public LineGraphEdge {
+ static bool center(const BoxPoint& p1, const BoxPoint& p2,
+ const BoxPoint& p3, double& x, double& y);
+ void makeLine(Widget w, const GraphGC& gc) const;
+};
+class GraphNode {
+public:
+ bool& selected();
+ GraphEdge *firstTo() const;
+ GraphEdge *nextTo(GraphEdge *ref) const;
+ virtual const BoxPoint& pos() const = 0;
+ virtual const BoxRegion& region(const GraphGC& gc) const = 0;
+ virtual bool isHint() const;
+};
+class PosGraphNode: public GraphNode { };
+class RegionGraphNode: public PosGraphNode { };
+class HintGraphNode: public RegionGraphNode { };
+void ArcGraphEdge::makeLine(Widget w, const GraphGC& gc) const {
+ HintGraphNode *arc_hint = 0;
+ RegionGraphNode *arc_from = 0;
+ RegionGraphNode *arc_to = 0;
+ bool make_arc = true;
+ if (from()->isHint() && to()->isHint()) {
+ make_arc = false;
+ }
+ else if (from()->isHint() && from()->firstTo() != 0) {
+ if (arc_hint == 0 || arc_from == 0 || arc_to == 0
+ || arc_hint->nextTo(arc_hint->firstTo()) != 0) {
+ make_arc = false;
+ }
+ }
+ if (!make_arc) {
+ if (w != 0) LineGraphEdge::drawLine(w, gc);
+ else LineGraphEdge::_print(gc);
+ return;
+ }
+ BoxPoint pos_from = arc_from->pos();
+ BoxRegion region_from = arc_from->region(gc);
+ BoxPoint pos_to = arc_to->pos();
+ BoxRegion region_to = arc_to->region(gc);
+ BoxPoint pos_hint = arc_hint->pos();
+ if (arc_hint->selected()) {
+ pos_hint += gc.offsetIfSelected;
+ }
+ if (pos_hint <= region_from || pos_hint <= region_to) {
+ return;
+ }
+ double cx, cy;
+ bool ok = center(pos_from, pos_hint, pos_to, cx, cy);
+ if (!ok) {
+ if (w != 0) LineGraphEdge::drawLine(w, gc);
+ else LineGraphEdge::_print(gc);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/pr50763-3.C b/gcc/testsuite/g++.dg/pr50763-3.C
new file mode 100644
index 00000000000..b66be87b1b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr50763-3.C
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O2 -ftree-tail-merge" } */
+
+class v2d {
+public:
+ double x;
+ double y;
+};
+
+class v3d {
+public:
+ double x;
+ v3d() {}
+ v3d(const v2d & cr2Dv) {}
+};
+
+class e2d {
+protected:
+ v2d _Min;
+ v2d _Max;
+public:
+ int cop2d(const v2d & rPnt) const;
+ v2d clp2d(const v2d & rPnt) const;
+};
+
+inline int e2d::cop2d(const v2d & rPnt) const {
+ int bRet = 1;
+ if (rPnt.x < _Min.x) bRet = 0;
+ else if (rPnt.x > _Max.x) bRet = 0;
+ else if (rPnt.y > _Max.y) bRet = 0;
+ return bRet;
+}
+
+inline v2d e2d::clp2d(const v2d & rPnt) const {
+ v2d sRet = rPnt;
+ if (rPnt.x < _Min.x) sRet.x = _Min.x;
+ if (rPnt.y < _Min.y) sRet.y = _Min.y;
+ if (rPnt.x > _Max.x) sRet.x = _Max.x;
+ if (rPnt.y > _Max.y) sRet.y = _Max.y;
+ return sRet;
+}
+
+class sExt {
+protected:
+ e2d _Dom;
+ long eval() const;
+ long evalPoint(const v2d & crUV, v3d & rPnt) const;
+};
+
+long sExt::evalPoint(const v2d & crUV, v3d & rPnt) const {
+ v3d sUV = crUV;
+ if (!_Dom.cop2d(crUV)) {
+ sUV = _Dom.clp2d(crUV);
+ }
+ eval();
+}
diff --git a/gcc/testsuite/g++.dg/template/crash108.C b/gcc/testsuite/g++.dg/template/crash108.C
new file mode 100644
index 00000000000..0b25fde6e38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash108.C
@@ -0,0 +1,5 @@
+// PR c++/50861
+
+template<class T> struct A {A(int b=k(0));}; // { dg-error "arguments" }
+void f(int k){A<int> a;} // // { dg-error "parameter|declared" }
+// { dg-message "note" { target *-*-* } 3 }
diff --git a/gcc/testsuite/g++.dg/torture/pr34850.C b/gcc/testsuite/g++.dg/torture/pr34850.C
index 5e30f1dab65..c33dbfb5c93 100644
--- a/gcc/testsuite/g++.dg/torture/pr34850.C
+++ b/gcc/testsuite/g++.dg/torture/pr34850.C
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+/* { dg-options "-ffat-lto-objects" } */
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
diff --git a/gcc/testsuite/g++.dg/torture/pr49720.C b/gcc/testsuite/g++.dg/torture/pr49720.C
new file mode 100644
index 00000000000..c5da7ba670f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr49720.C
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+
+extern char t_start[], t_end[], t_size[];
+bool foo (void)
+{
+ long size = reinterpret_cast<long>(t_size);
+ return (size == t_end - t_start);
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr50189.C b/gcc/testsuite/g++.dg/torture/pr50189.C
new file mode 100644
index 00000000000..06f1d3695c1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr50189.C
@@ -0,0 +1,121 @@
+// { dg-do run }
+// { dg-options "-fstrict-enums" }
+
+extern "C" void abort (void);
+class CCUTILS_KeyedScalarLevelPosition
+{
+public:
+
+ typedef enum
+ {
+ UNINITED = 0,
+ AT_BEGIN = 1,
+ AT_END = 2,
+ AT_KEY = 3
+
+ } position_t;
+
+ bool is_init() const
+ { return(m_timestamp != UNINITED); }
+
+ bool is_at_begin() const
+ { return(m_timestamp == AT_BEGIN); }
+
+ position_t get_state() const
+ {
+ return((m_timestamp >= AT_KEY)
+ ? AT_KEY
+ : ((position_t)m_timestamp));
+ }
+
+ void set_at_begin()
+ { m_timestamp = AT_BEGIN; }
+
+ unsigned int get_index() const
+ { return(m_index); }
+
+ void set_pos(unsigned int a_index, unsigned int a_timestmap)
+ {
+ m_index = a_index;
+ m_timestamp = a_timestmap;
+ }
+
+ bool check_pos(unsigned int a_num_entries, unsigned int a_timestamp) const
+ {
+ if (get_state() != AT_KEY)
+ return(false);
+
+ if (m_timestamp != a_timestamp)
+ return(false);
+
+ return(m_index < a_num_entries);
+ }
+
+ void set_not_init()
+ { m_timestamp = 0; }
+
+private:
+
+ unsigned int m_timestamp;
+ unsigned int m_index;
+
+};
+
+class CCUTILS_KeyedScalarPosition
+{
+public:
+
+ CCUTILS_KeyedScalarLevelPosition m_L1;
+ CCUTILS_KeyedScalarLevelPosition m_L2;
+};
+
+class baz
+{
+public:
+ int *n[20];
+ unsigned int m_cur_array_len;
+ unsigned int m_timestamp;
+
+ unsigned int _get_timestamp() const
+ { return(m_timestamp); }
+
+ bool _check_L1_pos(const CCUTILS_KeyedScalarPosition &a_position) const
+ {
+ return(a_position.m_L1.check_pos(
+ m_cur_array_len, _get_timestamp()));
+ }
+
+ void *next (CCUTILS_KeyedScalarPosition &);
+};
+
+void * baz::next (CCUTILS_KeyedScalarPosition &a_position)
+{
+ if (a_position.m_L1.is_at_begin() || (!a_position.m_L1.is_init()))
+ {
+ a_position.m_L1.set_pos(0, _get_timestamp());
+ a_position.m_L2.set_at_begin();
+ }
+ else if (!_check_L1_pos(a_position))
+ return(0);
+
+ return n[a_position.m_L1.get_index ()];
+}
+
+int main (int, char **)
+{
+ baz obj;
+ CCUTILS_KeyedScalarPosition a_pos;
+ void *ret;
+ int n[5];
+
+ obj.n[0] = n;
+ obj.m_cur_array_len = 1;
+ obj.m_timestamp = 42;
+
+ a_pos.m_L1.set_pos (0, 42);
+
+ ret = obj.next (a_pos);
+ if (ret == 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr45605.C b/gcc/testsuite/g++.dg/tree-ssa/pr45605.C
index 861b122e56f..7604fe4929d 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr45605.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr45605.C
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-ssa" } */
+/* { dg-options "-O1 -fdump-tree-fre1" } */
extern "C" void abort();
bool destructor_called = false;
@@ -33,5 +33,5 @@ int main() {
/* We should devirtualize call to D::Run */
-/* { dg-final { scan-tree-dump-times "D::Run \\(" 1 "ssa" { xfail *-*-* } } } */
-/* { dg-final { cleanup-tree-dump "ssa" } } */
+/* { dg-final { scan-tree-dump-times "D::Run \\(" 1 "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/testsuite/g++.dg/vect/pr50698.cc b/gcc/testsuite/g++.dg/vect/pr50698.cc
new file mode 100644
index 00000000000..acb193665ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/pr50698.cc
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-require-effective-target vect_float }
+
+float mem[4096];
+const int N=1024;
+
+struct XYZ {
+ float * mem;
+ int n;
+ float * x() { return mem;}
+ float * y() { return x()+n;}
+ float * z() { return y()+n;}
+};
+
+inline
+void sum(float * x, float * y, float * z, int n) {
+ for (int i=0;i!=n; ++i)
+ x[i]=y[i]+z[i];
+}
+
+void sumS() {
+ XYZ xyz; xyz.mem=mem; xyz.n=N;
+ sum(xyz.x(),xyz.y(),xyz.z(),xyz.n);
+}
+
+// { dg-final { scan-tree-dump-not "run-time aliasing" "vect" } }
+// { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/g++.dg/vect/slp-pr50819.cc b/gcc/testsuite/g++.dg/vect/slp-pr50819.cc
new file mode 100644
index 00000000000..402218bc5b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/slp-pr50819.cc
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+
+typedef float Value;
+
+struct LorentzVector
+{
+
+ LorentzVector(Value x=0, Value y=0, Value z=0, Value t=0) :
+theX(x),theY(y),theZ(z),theT(t){}
+ LorentzVector & operator+=(const LorentzVector & a) {
+ theX += a.theX;
+ theY += a.theY;
+ theZ += a.theZ;
+ theT += a.theT;
+ return *this;
+ }
+
+ Value theX;
+ Value theY;
+ Value theZ;
+ Value theT;
+} __attribute__ ((aligned(16)));
+
+inline LorentzVector
+operator+(LorentzVector const & a, LorentzVector const & b) {
+ return
+LorentzVector(a.theX+b.theX,a.theY+b.theY,a.theZ+b.theZ,a.theT+b.theT);
+}
+
+inline LorentzVector
+operator*(LorentzVector const & a, Value s) {
+ return LorentzVector(a.theX*s,a.theY*s,a.theZ*s,a.theT*s);
+}
+
+inline LorentzVector
+operator*(Value s, LorentzVector const & a) {
+ return a*s;
+}
+
+
+void sum1(LorentzVector & res, Value s, LorentzVector const & v1, LorentzVector
+const & v2) {
+ res += s*(v1+v2);
+}
+
+void sum2(LorentzVector & res, Value s, LorentzVector const & v1, LorentzVector
+const & v2) {
+ res = res + s*(v1+v2);
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 2 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
diff --git a/gcc/testsuite/g++.dg/vect/vect.exp b/gcc/testsuite/g++.dg/vect/vect.exp
index ac22f4b017d..76bd99a9862 100644
--- a/gcc/testsuite/g++.dg/vect/vect.exp
+++ b/gcc/testsuite/g++.dg/vect/vect.exp
@@ -42,12 +42,6 @@ set DEFAULT_VECTCFLAGS ""
# These flags are used for all targets.
lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fno-vect-cost-model"
-set VECT_SLP_CFLAGS $DEFAULT_VECTCFLAGS
-
-lappend DEFAULT_VECTCFLAGS "-fdump-tree-vect-details"
-lappend VECT_SLP_CFLAGS "-fdump-tree-slp-details"
-
-
# Skip these tests for targets that do not support generating vector
# code. Set additional target-dependent vector flags, which can be
# overridden by using dg-options in individual tests.
@@ -55,6 +49,11 @@ if ![check_vect_support_and_set_flags] {
return
}
+set VECT_SLP_CFLAGS $DEFAULT_VECTCFLAGS
+
+lappend DEFAULT_VECTCFLAGS "-fdump-tree-vect-details"
+lappend VECT_SLP_CFLAGS "-fdump-tree-slp-details"
+
# Initialize `dg'.
dg-init
diff --git a/gcc/testsuite/g++.dg/warn/Wcast-qual2.C b/gcc/testsuite/g++.dg/warn/Wcast-qual2.C
new file mode 100644
index 00000000000..23dbb4d39b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wcast-qual2.C
@@ -0,0 +1,4 @@
+// PR c++/50956
+// { dg-options "-Wcast-qual" }
+
+void* p = (void*)"txt"; // { dg-warning "cast" }
diff --git a/gcc/testsuite/g++.dg/warn/Wconversion4.C b/gcc/testsuite/g++.dg/warn/Wconversion4.C
new file mode 100644
index 00000000000..83daaa06928
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wconversion4.C
@@ -0,0 +1,17 @@
+// PR c++/45385
+// { dg-options "-Wconversion" }
+
+void foo(unsigned char);
+
+class Test
+{
+ void eval()
+ {
+ foo(bar()); // { dg-warning "may alter its value" }
+ }
+
+ unsigned int bar() const
+ {
+ return __INT_MAX__ * 2U + 1;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-1.C b/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-1.C
new file mode 100644
index 00000000000..d0f62b212ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wzero-as-null-pointer-constant-1.C
@@ -0,0 +1,100 @@
+// { dg-options "-Wzero-as-null-pointer-constant" }
+
+struct A;
+
+typedef int (A::*pointmemfun) (int);
+typedef int (A::*pointdmem);
+typedef int (*pointfun) (int);
+
+pointmemfun pmfs;
+pointdmem pdms;
+pointfun pfs;
+int* ps;
+
+void f()
+{
+ pointmemfun pmf(0); // { dg-warning "zero as null pointer" }
+ pointdmem pdm(0); // { dg-warning "zero as null pointer" }
+ pointfun pf(0); // { dg-warning "zero as null pointer" }
+ int* p(0); // { dg-warning "zero as null pointer" }
+
+ pmf = 0; // { dg-warning "zero as null pointer" }
+
+ pdm = 0; // { dg-warning "zero as null pointer" }
+
+ pf = 0; // { dg-warning "zero as null pointer" }
+
+ p = 0; // { dg-warning "zero as null pointer" }
+
+ if (pmf)
+ ;
+
+ if (pdm)
+ ;
+
+ if (pf)
+ ;
+
+ if (p)
+ ;
+
+ if (!pmf)
+ ;
+
+ if (!pdm)
+ ;
+
+ if (!pf)
+ ;
+
+ if (!p)
+ ;
+
+ if (pmf == 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pdm == 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pf == 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (p == 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 == pmf) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 == pdm) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 == pf) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 == p) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pmf != 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pdm != 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (pf != 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (p != 0) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 != pmf) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 != pdm) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 != pf) // { dg-warning "zero as null pointer" }
+ ;
+
+ if (0 != p) // { dg-warning "zero as null pointer" }
+ ;
+}
diff --git a/gcc/testsuite/g++.dg/warn/format6.C b/gcc/testsuite/g++.dg/warn/format6.C
new file mode 100644
index 00000000000..a74f8025d0e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/format6.C
@@ -0,0 +1,7 @@
+// PR c++/17212
+// { dg-options "-Wformat -Wno-format-zero-length" }
+
+void f()
+{
+ __builtin_printf("");
+}
diff --git a/gcc/testsuite/g++.dg/warn/format7.C b/gcc/testsuite/g++.dg/warn/format7.C
new file mode 100644
index 00000000000..6e84069eec5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/format7.C
@@ -0,0 +1,10 @@
+// PR c++/50757
+// { dg-options "-Wformat -Wno-nonnull" }
+
+extern void *f (void *__s) __attribute__ ((__nonnull__ (1)));
+
+int main()
+{
+ void* const s = 0;
+ f(s);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C b/gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C
index b04f7e2657c..987c0445a67 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/ptrmem7.C
@@ -31,9 +31,9 @@ void A::foo ()
int (*ptr8) (short) = ns;
int (A::*ptr11) (int) = &A::single;
- int (A::*ptr12) (int) = A::single; // { dg-error "match" }
+ int (A::*ptr12) (int) = A::single; // { dg-error "cannot convert" }
int (A::*ptr13) (int) = &single; // { dg-error "pointer to member" }
- int (A::*ptr14) (int) = single; // { dg-error "match" }
+ int (A::*ptr14) (int) = single; // { dg-error "cannot convert" }
int (A::*ptr20) (int) = &(A::ns); // { dg-error "pointer to member" }
int (A::*ptr21) (int) = &(A::single); // { dg-error "pointer to member" }
diff --git a/gcc/testsuite/gcc.c-torture/compile/sync-1.c b/gcc/testsuite/gcc.c-torture/compile/sync-1.c
index 0354923d2dd..1a6a096ad41 100644
--- a/gcc/testsuite/gcc.c-torture/compile/sync-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/sync-1.c
@@ -1,5 +1,6 @@
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-options "-ffat-lto-objects" } */
/* Validate that each of the __sync builtins compiles. This won't
necessarily link, since the target might not support the builtin,
diff --git a/gcc/testsuite/gcc.c-torture/compile/sync-2.c b/gcc/testsuite/gcc.c-torture/compile/sync-2.c
index bdc84ef0ae6..4ca0bb58345 100644
--- a/gcc/testsuite/gcc.c-torture/compile/sync-2.c
+++ b/gcc/testsuite/gcc.c-torture/compile/sync-2.c
@@ -1,4 +1,5 @@
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-options "-ffat-lto-objects" } */
/* Validate that each of the __sync builtins compiles. This won't
necessarily link, since the target might not support the builtin,
diff --git a/gcc/testsuite/gcc.c-torture/compile/sync-3.c b/gcc/testsuite/gcc.c-torture/compile/sync-3.c
index 9689eea5bb0..d717ef22913 100644
--- a/gcc/testsuite/gcc.c-torture/compile/sync-3.c
+++ b/gcc/testsuite/gcc.c-torture/compile/sync-3.c
@@ -1,4 +1,5 @@
/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-options "-ffat-lto-objects" } */
/* Validate that each of the __sync builtins compiles. This won't
necessarily link, since the target might not support the builtin,
diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c
index 3c3e45dfa5d..41678412b63 100644
--- a/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c
+++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strstr-asm.c
@@ -2,6 +2,7 @@
Ensure all expected transformations of builtin strstr occur and
perform correctly in presence of redirect. */
+/* { dg-options "-ffat-lto-objects" } */
#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
#define ASMNAME2(prefix, cname) STRING (prefix) cname
diff --git a/gcc/testsuite/gcc.c-torture/execute/vshuf-v16hi.c b/gcc/testsuite/gcc.c-torture/execute/vshuf-v16hi.c
new file mode 100644
index 00000000000..98b329dbf91
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/vshuf-v16hi.c
@@ -0,0 +1,5 @@
+typedef unsigned short V __attribute__((vector_size(32)));
+typedef V VI;
+
+#include "vshuf-16.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/DFcmp.c b/gcc/testsuite/gcc.c-torture/unsorted/DFcmp.c
index b32b0ecc6ab..18b20e6f6ca 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/DFcmp.c
+++ b/gcc/testsuite/gcc.c-torture/unsorted/DFcmp.c
@@ -12,7 +12,7 @@ type glob0, glob1;
#define adrx0 (E0[x0])
#define regx0 (p0[x0])
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(__alignof__ (type) - 1)))
#define reg1 r1
#define indreg1 (*p1)
#define imm1 33
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/HIcmp.c b/gcc/testsuite/gcc.c-torture/unsorted/HIcmp.c
index eea39841b95..77b47886ed1 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/HIcmp.c
+++ b/gcc/testsuite/gcc.c-torture/unsorted/HIcmp.c
@@ -12,7 +12,7 @@ type glob0, glob1;
#define adrx0 (E0[x0])
#define regx0 (p0[x0])
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(__alignof__ (type) - 1)))
#define reg1 r1
#define indreg1 (*p1)
#define imm1 33
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/HIset.c b/gcc/testsuite/gcc.c-torture/unsorted/HIset.c
index 8108fbb27c4..163cb7cbe32 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/HIset.c
+++ b/gcc/testsuite/gcc.c-torture/unsorted/HIset.c
@@ -8,7 +8,7 @@
#define adrx0 (E0[x0])
#define regx0 (p0[x0])
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(__alignof__ (type) - 1)))
#define reg1 r1
#define indreg1 (*p1)
#define imm1 33
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/SFset.c b/gcc/testsuite/gcc.c-torture/unsorted/SFset.c
index ad3e41b834b..61e1bfa4b18 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/SFset.c
+++ b/gcc/testsuite/gcc.c-torture/unsorted/SFset.c
@@ -8,7 +8,7 @@
#define adrx0 (E0[x0])
#define regx0 (p0[x0])
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(__alignof__ (type) - 1)))
#define reg1 r1
#define indreg1 (*p1)
#define imm1 33
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/SIcmp.c b/gcc/testsuite/gcc.c-torture/unsorted/SIcmp.c
index 30e07392467..4a9e0d57fd7 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/SIcmp.c
+++ b/gcc/testsuite/gcc.c-torture/unsorted/SIcmp.c
@@ -12,7 +12,7 @@ type glob0, glob1;
#define adrx0 (E0[x0])
#define regx0 (p0[x0])
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(__alignof__ (type) - 1)))
#define reg1 r1
#define indreg1 (*p1)
#define imm1 33
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/SIset.c b/gcc/testsuite/gcc.c-torture/unsorted/SIset.c
index 74a51cd0fb4..5fb93579f4b 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/SIset.c
+++ b/gcc/testsuite/gcc.c-torture/unsorted/SIset.c
@@ -8,7 +8,7 @@
#define adrx0 (E0[x0])
#define regx0 (p0[x0])
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(__alignof__ (type) - 1)))
#define reg1 r1
#define indreg1 (*p1)
#define imm1 33
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/UHIcmp.c b/gcc/testsuite/gcc.c-torture/unsorted/UHIcmp.c
index 1e969e7103a..529e3a33fd3 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/UHIcmp.c
+++ b/gcc/testsuite/gcc.c-torture/unsorted/UHIcmp.c
@@ -12,7 +12,7 @@ type glob0, glob1;
#define adrx0 (E0[x0])
#define regx0 (p0[x0])
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(__alignof__ (type) - 1)))
#define reg1 r1
#define indreg1 (*p1)
#define imm1 33
diff --git a/gcc/testsuite/gcc.c-torture/unsorted/USIcmp.c b/gcc/testsuite/gcc.c-torture/unsorted/USIcmp.c
index e2175262a42..69788a45b2e 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/USIcmp.c
+++ b/gcc/testsuite/gcc.c-torture/unsorted/USIcmp.c
@@ -12,7 +12,7 @@ type glob0, glob1;
#define adrx0 (E0[x0])
#define regx0 (p0[x0])
-#define E1 ((type *)11111111)
+#define E1 ((type *)(11111111 & ~(__alignof__ (type) - 1)))
#define reg1 r1
#define indreg1 (*p1)
#define imm1 33
diff --git a/gcc/testsuite/gcc.dg/builtins-67.c b/gcc/testsuite/gcc.dg/builtins-67.c
index 5c61391cc92..22267bd31b9 100644
--- a/gcc/testsuite/gcc.dg/builtins-67.c
+++ b/gcc/testsuite/gcc.dg/builtins-67.c
@@ -58,14 +58,14 @@ long long llceilf (float a) { return (long long) ceilf (a); }
long long llceill (long double a) { return (long long) ceill (a); }
#endif
-int iround (double a) { return (int) round (a); }
#ifdef HAVE_C99_RUNTIME
+int iround (double a) { return (int) round (a); }
int iroundf (float a) { return (int) roundf (a); }
int iroundl (long double a) { return (int) roundl (a); }
#endif
-int irint (double a) { return (int) rint (a); }
#ifdef HAVE_C99_RUNTIME
+int irint (double a) { return (int) rint (a); }
int irintf (float a) { return (int) rintf (a); }
int irintl (long double a) { return (int) rintl (a); }
#endif
diff --git a/gcc/testsuite/gcc.dg/constructor-1.c b/gcc/testsuite/gcc.dg/constructor-1.c
new file mode 100644
index 00000000000..1095a455cfa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/constructor-1.c
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+/* The ipa-split pass pulls the body of the if(!x) block
+ into a separate function to make foo a better inlining
+ candidate. Make sure this new function isn't also run
+ as a static constructor. */
+
+#include <stdlib.h>
+
+int x, y;
+
+void __attribute__((noinline))
+bar(void)
+{
+ y++;
+}
+
+void __attribute__((constructor))
+foo(void)
+{
+ if (!x)
+ {
+ bar();
+ y++;
+ }
+}
+
+int main()
+{
+ x = 1;
+ foo();
+ foo();
+ if (y != 2)
+ abort();
+ exit(0);
+}
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c
new file mode 100644
index 00000000000..d975c8cee97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-1.c
@@ -0,0 +1,21 @@
+/*
+ { dg-options "-ftrack-macro-expansion=1" }
+ { dg-do compile }
+*/
+
+#define OPERATE(OPRD1, OPRT, OPRD2) \
+do \
+{ \
+ OPRD1 OPRT OPRD2; /* { dg-message "expansion" }*/ \
+} while (0)
+
+#define SHIFTL(A,B) \
+ OPERATE (A,<<,B) /* { dg-message "expanded|expansion" } */
+
+void
+foo ()
+{
+ SHIFTL (0.1,0.2); /* { dg-message "expanded" } */
+}
+
+/* { dg-error "invalid operands" "" { target *-*-* } 13 } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c
new file mode 100644
index 00000000000..684af4c7507
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-2.c
@@ -0,0 +1,21 @@
+/*
+ { dg-options "-ftrack-macro-expansion=1" }
+ { dg-do compile }
+*/
+
+#define OPERATE(OPRD1, OPRT, OPRD2) \
+ OPRD1 OPRT OPRD2; /* { dg-message "expansion" } */
+
+#define SHIFTL(A,B) \
+ OPERATE (A,<<,B) /* { dg-message "expanded|expansion" } */
+
+#define MULT(A) \
+ SHIFTL (A,1) /* { dg-message "expanded|expansion" } */
+
+void
+foo ()
+{
+ MULT (1.0); /* { dg-message "expanded" } */
+}
+
+/* { dg-error "invalid operands to binary <<" "" { target *-*-* } { 10 } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c
new file mode 100644
index 00000000000..119053ef9fb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-3.c
@@ -0,0 +1,14 @@
+/*
+ { dg-options "-fshow-column -ftrack-macro-expansion=1" }
+ { dg-do compile }
+ */
+
+#define SQUARE(A) A * A /* { dg-message "expansion" } */
+
+void
+foo()
+{
+ SQUARE (1 << 0.1); /* { dg-message "expanded" } */
+}
+
+/* { dg-error "16:invalid operands to binary <<" "" {target *-*-* } { 11 } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c
new file mode 100644
index 00000000000..1f9fe6ad26c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/macro-exp-tracking-4.c
@@ -0,0 +1,14 @@
+/*
+ { dg-options "-fshow-column -ftrack-macro-expansion=2" }
+ { dg-do compile }
+ */
+
+#define SQUARE(A) A * A /* { dg-message "expansion" } */
+
+void
+foo()
+{
+ SQUARE (1 << 0.1); /* { dg-message "expanded" } */
+}
+
+/* { dg-error "13:invalid operands to binary <<" "" { target *-*-* } { 11 } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c
new file mode 100644
index 00000000000..3a2f9da1fce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-1.c
@@ -0,0 +1,32 @@
+/*
+ { dg-options "-Wuninitialized" }
+ { dg-do compile }
+*/
+
+void f (unsigned);
+
+#define CODE_WITH_WARNING \
+ int a; \
+ f (a)
+
+#pragma GCC diagnostic ignored "-Wuninitialized"
+
+void
+g (void)
+{
+ CODE_WITH_WARNING;
+}
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic error "-Wuninitialized"
+
+void
+h (void)
+{
+ CODE_WITH_WARNING; /* { dg-error "uninitialized" } */
+}
+
+/*
+ { dg-message "some warnings being treated as errors" "" {target *-*-*} 0 }
+*/
diff --git a/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c
new file mode 100644
index 00000000000..7ab95b0c63b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/pragma-diagnostic-2.c
@@ -0,0 +1,34 @@
+/*
+ { dg-options "-Wuninitialized -ftrack-macro-expansion=2" }
+ { dg-do compile }
+*/
+
+void f (unsigned);
+
+#define CODE_WITH_WARNING \
+ int a; /* { dg-message "expansion|declared here" } */ \
+ f (a) /* { dg-message "expansion" } */
+
+#pragma GCC diagnostic ignored "-Wuninitialized"
+
+void
+g (void)
+{
+ CODE_WITH_WARNING;
+}
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic error "-Wuninitialized"
+
+void
+h (void)
+{
+ CODE_WITH_WARNING; /* { dg-message "expanded" } */
+}
+
+/*
+ { dg-message "some warnings being treated as errors" "" {target *-*-*} 0 }
+*/
+
+/* { dg-error "uninitialized" "" { target *-*-* } { 10 } } */
diff --git a/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c b/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c
new file mode 100644
index 00000000000..82a4ea24617
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/di-longlong64-sync-1.c
@@ -0,0 +1,164 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_longlong } */
+/* { dg-options "-std=gnu99" } */
+/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+
+
+/* Test basic functionality of the intrinsics. The operations should
+ not be optimized away if no one checks the return values. */
+
+/* Based on ia64-sync-[12].c, but 1) long on ARM is 32 bit so use long long
+ (an explicit 64bit type maybe a better bet) and 2) Use values that cross
+ the 32bit boundary and cause carries since the actual maths are done as
+ pairs of 32 bit instructions. */
+
+/* Note: This file is #included by some of the ARM tests. */
+
+__extension__ typedef __SIZE_TYPE__ size_t;
+
+extern void abort (void);
+extern void *memcpy (void *, const void *, size_t);
+extern int memcmp (const void *, const void *, size_t);
+
+/* Temporary space where the work actually gets done. */
+static long long AL[24];
+/* Values copied into AL before we start. */
+static long long init_di[24] = { 0x100000002ll, 0x200000003ll, 0, 1,
+
+ 0x100000002ll, 0x100000002ll,
+ 0x100000002ll, 0x100000002ll,
+
+ 0, 0x1000e0de0000ll,
+ 42 , 0xc001c0de0000ll,
+
+ -1ll, 0, 0xff00ff0000ll, -1ll,
+
+ 0, 0x1000e0de0000ll,
+ 42 , 0xc001c0de0000ll,
+
+ -1ll, 0, 0xff00ff0000ll, -1ll};
+/* This is what should be in AL at the end. */
+static long long test_di[24] = { 0x1234567890ll, 0x1234567890ll, 1, 0,
+
+ 0x100000002ll, 0x100000002ll,
+ 0x100000002ll, 0x100000002ll,
+
+ 1, 0xc001c0de0000ll,
+ 20, 0x1000e0de0000ll,
+
+ 0x300000007ll , 0x500000009ll,
+ 0xf100ff0001ll, ~0xa00000007ll,
+
+ 1, 0xc001c0de0000ll,
+ 20, 0x1000e0de0000ll,
+
+ 0x300000007ll , 0x500000009ll,
+ 0xf100ff0001ll, ~0xa00000007ll };
+
+/* First check they work in terms of what they do to memory. */
+static void
+do_noret_di (void)
+{
+ __sync_val_compare_and_swap (AL+0, 0x100000002ll, 0x1234567890ll);
+ __sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll);
+ __sync_lock_test_and_set (AL+2, 1);
+ __sync_lock_release (AL+3);
+
+ /* The following tests should not change the value since the
+ original does NOT match. */
+ __sync_val_compare_and_swap (AL+4, 0x000000002ll, 0x1234567890ll);
+ __sync_val_compare_and_swap (AL+5, 0x100000000ll, 0x1234567890ll);
+ __sync_bool_compare_and_swap (AL+6, 0x000000002ll, 0x1234567890ll);
+ __sync_bool_compare_and_swap (AL+7, 0x100000000ll, 0x1234567890ll);
+
+ __sync_fetch_and_add (AL+8, 1);
+ __sync_fetch_and_add (AL+9, 0xb000e0000000ll); /* + to both halves & carry. */
+ __sync_fetch_and_sub (AL+10, 22);
+ __sync_fetch_and_sub (AL+11, 0xb000e0000000ll);
+
+ __sync_fetch_and_and (AL+12, 0x300000007ll);
+ __sync_fetch_and_or (AL+13, 0x500000009ll);
+ __sync_fetch_and_xor (AL+14, 0xe00000001ll);
+ __sync_fetch_and_nand (AL+15, 0xa00000007ll);
+
+ /* These should be the same as the fetch_and_* cases except for
+ return value. */
+ __sync_add_and_fetch (AL+16, 1);
+ /* add to both halves & carry. */
+ __sync_add_and_fetch (AL+17, 0xb000e0000000ll);
+ __sync_sub_and_fetch (AL+18, 22);
+ __sync_sub_and_fetch (AL+19, 0xb000e0000000ll);
+
+ __sync_and_and_fetch (AL+20, 0x300000007ll);
+ __sync_or_and_fetch (AL+21, 0x500000009ll);
+ __sync_xor_and_fetch (AL+22, 0xe00000001ll);
+ __sync_nand_and_fetch (AL+23, 0xa00000007ll);
+}
+
+/* Now check return values. */
+static void
+do_ret_di (void)
+{
+ if (__sync_val_compare_and_swap (AL+0, 0x100000002ll, 0x1234567890ll) !=
+ 0x100000002ll) abort ();
+ if (__sync_bool_compare_and_swap (AL+1, 0x200000003ll, 0x1234567890ll) !=
+ 1) abort ();
+ if (__sync_lock_test_and_set (AL+2, 1) != 0) abort ();
+ __sync_lock_release (AL+3); /* no return value, but keep to match results. */
+
+ /* The following tests should not change the value since the
+ original does NOT match. */
+ if (__sync_val_compare_and_swap (AL+4, 0x000000002ll, 0x1234567890ll) !=
+ 0x100000002ll) abort ();
+ if (__sync_val_compare_and_swap (AL+5, 0x100000000ll, 0x1234567890ll) !=
+ 0x100000002ll) abort ();
+ if (__sync_bool_compare_and_swap (AL+6, 0x000000002ll, 0x1234567890ll) !=
+ 0) abort ();
+ if (__sync_bool_compare_and_swap (AL+7, 0x100000000ll, 0x1234567890ll) !=
+ 0) abort ();
+
+ if (__sync_fetch_and_add (AL+8, 1) != 0) abort ();
+ if (__sync_fetch_and_add (AL+9, 0xb000e0000000ll) != 0x1000e0de0000ll) abort ();
+ if (__sync_fetch_and_sub (AL+10, 22) != 42) abort ();
+ if (__sync_fetch_and_sub (AL+11, 0xb000e0000000ll) != 0xc001c0de0000ll)
+ abort ();
+
+ if (__sync_fetch_and_and (AL+12, 0x300000007ll) != -1ll) abort ();
+ if (__sync_fetch_and_or (AL+13, 0x500000009ll) != 0) abort ();
+ if (__sync_fetch_and_xor (AL+14, 0xe00000001ll) != 0xff00ff0000ll) abort ();
+ if (__sync_fetch_and_nand (AL+15, 0xa00000007ll) != -1ll) abort ();
+
+ /* These should be the same as the fetch_and_* cases except for
+ return value. */
+ if (__sync_add_and_fetch (AL+16, 1) != 1) abort ();
+ if (__sync_add_and_fetch (AL+17, 0xb000e0000000ll) != 0xc001c0de0000ll)
+ abort ();
+ if (__sync_sub_and_fetch (AL+18, 22) != 20) abort ();
+ if (__sync_sub_and_fetch (AL+19, 0xb000e0000000ll) != 0x1000e0de0000ll)
+ abort ();
+
+ if (__sync_and_and_fetch (AL+20, 0x300000007ll) != 0x300000007ll) abort ();
+ if (__sync_or_and_fetch (AL+21, 0x500000009ll) != 0x500000009ll) abort ();
+ if (__sync_xor_and_fetch (AL+22, 0xe00000001ll) != 0xf100ff0001ll) abort ();
+ if (__sync_nand_and_fetch (AL+23, 0xa00000007ll) != ~0xa00000007ll) abort ();
+}
+
+int main ()
+{
+ memcpy (AL, init_di, sizeof (init_di));
+
+ do_noret_di ();
+
+ if (memcmp (AL, test_di, sizeof (test_di)))
+ abort ();
+
+ memcpy (AL, init_di, sizeof (init_di));
+
+ do_ret_di ();
+
+ if (memcmp (AL, test_di, sizeof (test_di)))
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/di-sync-multithread.c b/gcc/testsuite/gcc.dg/di-sync-multithread.c
new file mode 100644
index 00000000000..c99878ea129
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/di-sync-multithread.c
@@ -0,0 +1,205 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sync_longlong } */
+/* { dg-require-effective-target pthread_h } */
+/* { dg-require-effective-target pthread } */
+/* { dg-options "-pthread -std=gnu99" } */
+
+/* test of long long atomic ops performed in parallel in 3 pthreads
+ david.gilbert@linaro.org */
+
+#include <pthread.h>
+#include <unistd.h>
+
+/*#define DEBUGIT 1 */
+
+#ifdef DEBUGIT
+#include <stdio.h>
+
+#define DOABORT(x,...) {\
+ fprintf (stderr, x, __VA_ARGS__); fflush (stderr); abort ();\
+ }
+
+#else
+
+#define DOABORT(x,...) abort ();
+
+#endif
+
+/* Passed to each thread to describe which bits it is going to work on. */
+struct threadwork {
+ unsigned long long count; /* incremented each time the worker loops. */
+ unsigned int thread; /* ID */
+ unsigned int addlsb; /* 8 bit */
+ unsigned int logic1lsb; /* 5 bit */
+ unsigned int logic2lsb; /* 8 bit */
+};
+
+/* The shared word where all the atomic work is done. */
+static volatile long long workspace;
+
+/* A shared word to tell the workers to quit when non-0. */
+static long long doquit;
+
+extern void abort (void);
+
+/* Note this test doesn't test the return values much. */
+void*
+worker (void* data)
+{
+ struct threadwork *tw = (struct threadwork*)data;
+ long long add1bit = 1ll << tw->addlsb;
+ long long logic1bit = 1ll << tw->logic1lsb;
+ long long logic2bit = 1ll << tw->logic2lsb;
+
+ /* Clear the bits we use. */
+ __sync_and_and_fetch (&workspace, ~(0xffll * add1bit));
+ __sync_fetch_and_and (&workspace, ~(0x1fll * logic1bit));
+ __sync_fetch_and_and (&workspace, ~(0xffll * logic2bit));
+
+ do
+ {
+ long long tmp1, tmp2, tmp3;
+ /* OK, lets try and do some stuff to the workspace - by the end
+ of the main loop our area should be the same as it is now - i.e. 0. */
+
+ /* Push the arithmetic section upto 128 - one of the threads will
+ case this to carry accross the 32bit boundary. */
+ for (tmp2 = 0; tmp2 < 64; tmp2++)
+ {
+ /* Add 2 using the two different adds. */
+ tmp1 = __sync_add_and_fetch (&workspace, add1bit);
+ tmp3 = __sync_fetch_and_add (&workspace, add1bit);
+
+ /* The value should be the intermediate add value in both cases. */
+ if ((tmp1 & (add1bit * 0xff)) != (tmp3 & (add1bit * 0xff)))
+ DOABORT ("Mismatch of add intermediates on thread %d "
+ "workspace=0x%llx tmp1=0x%llx "
+ "tmp2=0x%llx tmp3=0x%llx\n",
+ tw->thread, workspace, tmp1, tmp2, tmp3);
+ }
+
+ /* Set the logic bits. */
+ tmp2=__sync_or_and_fetch (&workspace,
+ 0x1fll * logic1bit | 0xffll * logic2bit);
+
+ /* Check the logic bits are set and the arithmetic value is correct. */
+ if ((tmp2 & (0x1fll * logic1bit | 0xffll * logic2bit
+ | 0xffll * add1bit))
+ != (0x1fll * logic1bit | 0xffll * logic2bit | 0x80ll * add1bit))
+ DOABORT ("Midloop check failed on thread %d "
+ "workspace=0x%llx tmp2=0x%llx "
+ "masktmp2=0x%llx expected=0x%llx\n",
+ tw->thread, workspace, tmp2,
+ tmp2 & (0x1fll * logic1bit | 0xffll * logic2bit |
+ 0xffll * add1bit),
+ (0x1fll * logic1bit | 0xffll * logic2bit | 0x80ll * add1bit));
+
+ /* Pull the arithmetic set back down to 0 - again this should cause a
+ carry across the 32bit boundary in one thread. */
+
+ for (tmp2 = 0; tmp2 < 64; tmp2++)
+ {
+ /* Subtract 2 using the two different subs. */
+ tmp1=__sync_sub_and_fetch (&workspace, add1bit);
+ tmp3=__sync_fetch_and_sub (&workspace, add1bit);
+
+ /* The value should be the intermediate sub value in both cases. */
+ if ((tmp1 & (add1bit * 0xff)) != (tmp3 & (add1bit * 0xff)))
+ DOABORT ("Mismatch of sub intermediates on thread %d "
+ "workspace=0x%llx tmp1=0x%llx "
+ "tmp2=0x%llx tmp3=0x%llx\n",
+ tw->thread, workspace, tmp1, tmp2, tmp3);
+ }
+
+
+ /* Clear the logic bits. */
+ __sync_fetch_and_xor (&workspace, 0x1fll * logic1bit);
+ tmp3=__sync_and_and_fetch (&workspace, ~(0xffll * logic2bit));
+
+ /* The logic bits and the arithmetic bits should be zero again. */
+ if (tmp3 & (0x1fll * logic1bit | 0xffll * logic2bit | 0xffll * add1bit))
+ DOABORT ("End of worker loop; bits none 0 on thread %d "
+ "workspace=0x%llx tmp3=0x%llx "
+ "mask=0x%llx maskedtmp3=0x%llx\n",
+ tw->thread, workspace, tmp3, (0x1fll * logic1bit |
+ 0xffll * logic2bit | 0xffll * add1bit),
+ tmp3 & (0x1fll * logic1bit | 0xffll * logic2bit | 0xffll * add1bit));
+
+ __sync_add_and_fetch (&tw->count, 1);
+ }
+ while (!__sync_bool_compare_and_swap (&doquit, 1, 1));
+
+ pthread_exit (0);
+}
+
+int
+main ()
+{
+ /* We have 3 threads doing three sets of operations, an 8 bit
+ arithmetic field, a 5 bit logic field and an 8 bit logic
+ field (just to pack them all in).
+
+ 6 5 4 4 3 2 1
+ 3 6 8 0 2 4 6 8 0
+ |...,...|...,...|...,...|...,...|...,...|...,...|...,...|...,...
+ - T0 -- T1 -- T2 --T2 -- T0 -*- T2-- T1-- T1 -***- T0-
+ logic2 logic2 arith log2 arith log1 log1 arith log1
+
+ */
+ unsigned int t;
+ long long tmp;
+ int err;
+
+ struct threadwork tw[3]={
+ { 0ll, 0, 27, 0, 56 },
+ { 0ll, 1, 8,16, 48 },
+ { 0ll, 2, 40,21, 35 }
+ };
+
+ pthread_t threads[3];
+
+ __sync_lock_release (&doquit);
+
+ /* Get the work space into a known value - All 1's. */
+ __sync_lock_release (&workspace); /* Now all 0. */
+ tmp = __sync_val_compare_and_swap (&workspace, 0, -1ll);
+ if (tmp!=0)
+ DOABORT ("Initial __sync_val_compare_and_swap wasn't 0 workspace=0x%llx "
+ "tmp=0x%llx\n", workspace,tmp);
+
+ for (t = 0; t < 3; t++)
+ {
+ err=pthread_create (&threads[t], NULL , worker, &tw[t]);
+ if (err) DOABORT ("pthread_create failed on thread %d with error %d\n",
+ t, err);
+ };
+
+ sleep (5);
+
+ /* Stop please. */
+ __sync_lock_test_and_set (&doquit, 1ll);
+
+ for (t = 0; t < 3; t++)
+ {
+ err=pthread_join (threads[t], NULL);
+ if (err)
+ DOABORT ("pthread_join failed on thread %d with error %d\n", t, err);
+ };
+
+ __sync_synchronize ();
+
+ /* OK, so all the workers have finished -
+ the workers should have zero'd their workspace, the unused areas
+ should still be 1. */
+ if (!__sync_bool_compare_and_swap (&workspace, 0x040000e0ll, 0))
+ DOABORT ("End of run workspace mismatch, got %llx\n", workspace);
+
+ /* All the workers should have done some work. */
+ for (t = 0; t < 3; t++)
+ {
+ if (tw[t].count == 0) DOABORT ("Worker %d gave 0 count\n", t);
+ };
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/format/ms_c90-printf-1.c b/gcc/testsuite/gcc.dg/format/ms_c90-printf-1.c
index f99d4c49db9..cce2342a565 100644
--- a/gcc/testsuite/gcc.dg/format/ms_c90-printf-1.c
+++ b/gcc/testsuite/gcc.dg/format/ms_c90-printf-1.c
@@ -167,7 +167,7 @@ foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
*/
printf ("%d", u);
/* Wrong number of arguments. */
- printf ("%d%d", i); /* { dg-warning "arguments" "wrong number of args" } */
+ printf ("%d%d", i); /* { dg-warning "matching" "wrong number of args" } */
printf ("%d", i, i); /* { dg-warning "arguments" "wrong number of args" } */
/* Miscellaneous bogus constructions. */
printf (""); /* { dg-warning "zero-length" "warning for empty format" } */
diff --git a/gcc/testsuite/gcc.dg/format/ms_c90-scanf-1.c b/gcc/testsuite/gcc.dg/format/ms_c90-scanf-1.c
index 6e2cb10063b..f52ed20ea36 100644
--- a/gcc/testsuite/gcc.dg/format/ms_c90-scanf-1.c
+++ b/gcc/testsuite/gcc.dg/format/ms_c90-scanf-1.c
@@ -106,7 +106,7 @@ foo (int *ip, unsigned int *uip, short int *hp, unsigned short int *uhp,
scanf ("%s", cs); /* { dg-warning "constant" "%s writing into const" } */
scanf ("%p", pcp); /* { dg-warning "constant" "%p writing into const" } */
/* Wrong number of arguments. */
- scanf ("%d%d", ip); /* { dg-warning "arguments" "wrong number of args" } */
+ scanf ("%d%d", ip); /* { dg-warning "matching" "wrong number of args" } */
scanf ("%d", ip, ip); /* { dg-warning "arguments" "wrong number of args" } */
/* Miscellaneous bogus constructions. */
scanf (""); /* { dg-warning "zero-length" "warning for empty format" } */
diff --git a/gcc/testsuite/gcc.dg/graphite/run-id-1.c b/gcc/testsuite/gcc.dg/graphite/run-id-1.c
index 776600835b9..a58c090e8fd 100644
--- a/gcc/testsuite/gcc.dg/graphite/run-id-1.c
+++ b/gcc/testsuite/gcc.dg/graphite/run-id-1.c
@@ -1,3 +1,4 @@
+/* { dg-options "-Wl,--stack,12582912" { target *-*-mingw* *-*-cygwin* } } */
/* { dg-require-effective-target size32plus } */
void abort (void);
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-2.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-2.c
index 3437a81aa2c..c6b4d63aa78 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-2.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fipa-sra -fdump-tree-eipa_sra-details" } */
+/* { dg-require-effective-target non_strict_align } */
struct bovid
{
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-sra-6.c b/gcc/testsuite/gcc.dg/ipa/ipa-sra-6.c
index 60382949175..487e72ef4ca 100644
--- a/gcc/testsuite/gcc.dg/ipa/ipa-sra-6.c
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-sra-6.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fipa-sra -fdump-tree-eipa_sra-slim" } */
+/* { dg-require-effective-target non_strict_align } */
struct bovid
{
diff --git a/gcc/testsuite/gcc.dg/ipa/ipcp-4.c b/gcc/testsuite/gcc.dg/ipa/ipcp-4.c
new file mode 100644
index 00000000000..59018ca6b1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipcp-4.c
@@ -0,0 +1,68 @@
+/* Test that IPA-CP is able to produce a pass-through jump function for the
+ call of g1 and g2 even though a is addressable. Also test that h is not
+ cloned. */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -fipa-cp -fipa-cp-clone -fdump-ipa-cp -fno-early-inlining" } */
+/* { dg-add-options bind_pic_locally } */
+
+extern void use_stuff (int);
+extern void use_pointer (int *);
+
+static int
+h (int a, int b)
+{
+ int i;
+
+ for (i = 8; i <= b; i++)
+ use_stuff (a+8);
+}
+
+static int
+g1 (int a, int b)
+{
+ int i;
+
+ for (i = 0; i <= b; i++)
+ use_pointer (&a);
+ h (a, b);
+}
+
+static int
+g2 (int a, int b)
+{
+ int i;
+
+ for (i = 4; i <= b; i += 2)
+ use_stuff (a);
+}
+
+
+static void
+f (int a, int z)
+{
+ if (z > 1)
+ g1 (a, z);
+ else
+ g2 (a + 4, z);
+ use_pointer (&a);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+ for (i = 0; i < 100; i++)
+ f (7, argc);
+ return 0;
+}
+
+
+/* { dg-final { scan-ipa-dump "Creating a specialized node of g1.*for all known contexts" "cp" } } */
+/* { dg-final { scan-ipa-dump "Creating a specialized node of g2.*for all known contexts" "cp" } } */
+/* { dg-final { scan-ipa-dump-not "Creating a specialized node of h.*for all known contexts" "cp" } } */
+/* { dg-final { scan-ipa-dump-times "replacing param a with const 7" 2 "cp" } } */
+/* { dg-final { scan-ipa-dump "replacing param a with const 11" "cp" } } */
+/* { dg-final { cleanup-ipa-dump "cp" } } */
+
+
diff --git a/gcc/testsuite/gcc.dg/lto/pr46940_0.c b/gcc/testsuite/gcc.dg/lto/pr46940_0.c
index 5283495e8bb..89cb828fbac 100644
--- a/gcc/testsuite/gcc.dg/lto/pr46940_0.c
+++ b/gcc/testsuite/gcc.dg/lto/pr46940_0.c
@@ -2,10 +2,14 @@
/* { dg-extra-ld-options "-fuse-linker-plugin" } */
#include <stdio.h>
+#define ASMNAME(cname) ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+#define ASMNAME2(prefix, cname) STRING (prefix) cname
+#define STRING(x) #x
+
extern __attribute__((visibility("hidden"))) void _moz_foo (void);
-extern __typeof (_moz_foo) _moz_foo __asm__ ("" "INT__foo") __attribute__((__visibility__("hidden"))) ;
+extern __typeof (_moz_foo) _moz_foo __asm__ (ASMNAME ("INT__foo")) __attribute__((__visibility__("hidden"))) ;
void _moz_foo(void)
{
printf ("blah\n");
}
-extern __typeof (_moz_foo) EXT__foo __asm__("" "_moz_foo") __attribute__((__alias__("" "INT__foo")));
+extern __typeof (_moz_foo) EXT__foo __asm__(ASMNAME ("_moz_foo")) __attribute__((__alias__("" "INT__foo")));
diff --git a/gcc/testsuite/gcc.dg/memcpy-4.c b/gcc/testsuite/gcc.dg/memcpy-4.c
new file mode 100644
index 00000000000..4fe72ec5b89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/memcpy-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-expand" } */
+
+void
+f1 (char *p)
+{
+ __builtin_memcpy (p, "123", 3);
+}
+
+/* { dg-final { scan-rtl-dump-times "mem/s/u" 3 "expand" { target mips*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "expand" } } */
diff --git a/gcc/testsuite/gcc.dg/noncompile/920507-1.c b/gcc/testsuite/gcc.dg/noncompile/920507-1.c
index 7024a5b03a0..22b7b0a8b6b 100644
--- a/gcc/testsuite/gcc.dg/noncompile/920507-1.c
+++ b/gcc/testsuite/gcc.dg/noncompile/920507-1.c
@@ -1,3 +1,4 @@
+/* { dg-options "-ffat-lto-objects" } */
int *
x(void)
{
diff --git a/gcc/testsuite/gcc.dg/noncompile/invalid_asm.c b/gcc/testsuite/gcc.dg/noncompile/invalid_asm.c
index 0cb14799f34..d1d4b364b8e 100644
--- a/gcc/testsuite/gcc.dg/noncompile/invalid_asm.c
+++ b/gcc/testsuite/gcc.dg/noncompile/invalid_asm.c
@@ -1,3 +1,4 @@
+/* { dg-options "-ffat-lto-objects" } */
asm_invalid_register_name()
{
asm("":::"this_is_an_invalid_register_name"); /* { dg-error "unknown register" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugindir1.c b/gcc/testsuite/gcc.dg/plugin/plugindir1.c
index a973ec0c54c..72821ac9852 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugindir1.c
+++ b/gcc/testsuite/gcc.dg/plugin/plugindir1.c
@@ -1,4 +1,4 @@
/* { dg-do compile } */
/* { dg-options "-c -fplugin=foo" } */
-/* { dg-prune-output ".*inacessible plugin file.*foo\.so expanded from short plugin name.*" } */
+/* { dg-prune-output ".*inaccessible plugin file.*foo\.so expanded from short plugin name.*" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugindir2.c b/gcc/testsuite/gcc.dg/plugin/plugindir2.c
index 58c1505501a..063b9d9e594 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugindir2.c
+++ b/gcc/testsuite/gcc.dg/plugin/plugindir2.c
@@ -1,4 +1,4 @@
/* { dg-do compile } */
/* { dg-options "-save-temps -c -fplugin=foo" } */
-/* { dg-prune-output ".*inacessible plugin file.*foo\.so expanded from short plugin name.*" } */
+/* { dg-prune-output ".*inaccessible plugin file.*foo\.so expanded from short plugin name.*" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugindir3.c b/gcc/testsuite/gcc.dg/plugin/plugindir3.c
index 41037534a26..9b1c004cfd1 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugindir3.c
+++ b/gcc/testsuite/gcc.dg/plugin/plugindir3.c
@@ -1,4 +1,4 @@
/* { dg-do preprocess } */
/* { dg-options "-fplugin=foo" } */
-/* { dg-prune-output ".*inacessible plugin file.*foo\.so expanded from short plugin name.*" } */
+/* { dg-prune-output ".*inaccessible plugin file.*foo\.so expanded from short plugin name.*" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/plugindir4.c b/gcc/testsuite/gcc.dg/plugin/plugindir4.c
index 27b2f24aaf9..8f1cb801621 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugindir4.c
+++ b/gcc/testsuite/gcc.dg/plugin/plugindir4.c
@@ -1,4 +1,4 @@
/* { dg-do preprocess } */
/* { dg-options "-iplugindir=my-plugindir -fplugin=foo" } */
-/* { dg-prune-output ".*inacessible plugin file.*my-plugindir/foo\.so expanded from short plugin name.*" } */
+/* { dg-prune-output ".*inaccessible plugin file.*my-plugindir/foo\.so expanded from short plugin name.*" } */
diff --git a/gcc/testsuite/gcc.dg/pr49994-3.c b/gcc/testsuite/gcc.dg/pr49994-3.c
index c24aa8ffbdc..ef079d78b4b 100644
--- a/gcc/testsuite/gcc.dg/pr49994-3.c
+++ b/gcc/testsuite/gcc.dg/pr49994-3.c
@@ -2,6 +2,7 @@
/* { dg-options "-O2 -fsched2-use-superblocks -g" } */
/* { dg-options "-O2 -fsched2-use-superblocks -g -mbackchain" { target s390*-*-* } } */
/* { dg-require-effective-target scheduling } */
+/* { dg-skip-if "PR testsuite/50722" { *-*-hpux* } } */
void *
foo (int offset)
diff --git a/gcc/testsuite/gcc.dg/pr50205.c b/gcc/testsuite/gcc.dg/pr50205.c
new file mode 100644
index 00000000000..ff523d07f37
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50205.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target powerpc*-*-* ia64-*-* i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -fno-cprop-registers -fno-dce -fno-forward-propagate -fselective-scheduling2 -funroll-loops -fno-web" } */
+extern int a[];
+
+void foo (void)
+{
+ int i;
+ for (i = 0; i < 199; i++)
+ {
+ if (a[i] != i)
+ __builtin_abort ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr50340.c b/gcc/testsuite/gcc.dg/pr50340.c
new file mode 100644
index 00000000000..18430366fe1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50340.c
@@ -0,0 +1,46 @@
+/* { dg-do compile { target powerpc*-*-* ia64-*-* i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O3 -fselective-scheduling2 -funroll-loops" } */
+extern int mode_size[];
+typedef unsigned HARD_REG_SET[ ((64 + 32 - 1) / 32) ];
+enum reload_type {
+ RELOAD_FOR_INPUT,
+ RELOAD_FOR_OUTPUT,
+ RELOAD_FOR_INSN,
+ RELOAD_FOR_INPUT_ADDRESS,
+ RELOAD_FOR_OUTPUT_ADDRESS,
+ RELOAD_FOR_OPERAND_ADDRESS,
+ RELOAD_FOR_OPADDR_ADDR,
+ RELOAD_OTHER,
+ RELOAD_FOR_OTHER_ADDRESS
+};
+static HARD_REG_SET reload_reg_used;
+static HARD_REG_SET reload_reg_used_in_input_addr[10];
+static HARD_REG_SET reload_reg_used_in_output_addr[10];
+static HARD_REG_SET reload_reg_used_in_input[10];
+static HARD_REG_SET reload_reg_used_in_output[10];
+static HARD_REG_SET reload_reg_used_in_op_addr;
+static HARD_REG_SET reload_reg_used_in_op_addr_reload;
+static HARD_REG_SET reload_reg_used_in_insn;
+static HARD_REG_SET reload_reg_used_in_other_addr;
+static HARD_REG_SET reload_reg_used_at_all;
+void __attribute__((cold)) mark_reload_reg_in_use (regno, opnum, type, mode)
+{
+ int nregs = regno ? 1 : mode_size[mode];
+ int i;
+ for (i = regno; i < nregs + regno; i++)
+ {
+ switch (type)
+ {
+ case RELOAD_OTHER: reload_reg_used[i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_INPUT_ADDRESS: reload_reg_used_in_input_addr[opnum][i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OUTPUT_ADDRESS: reload_reg_used_in_output_addr[opnum][i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OPERAND_ADDRESS: reload_reg_used_in_op_addr[i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OPADDR_ADDR: reload_reg_used_in_op_addr_reload[i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OTHER_ADDRESS: reload_reg_used_in_other_addr[i / 32u] |= 1; break;
+ case RELOAD_FOR_INPUT: reload_reg_used_in_input[opnum][i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_OUTPUT: reload_reg_used_in_output[opnum][i / 32u] |= 1 << i % 32u; break;
+ case RELOAD_FOR_INSN: reload_reg_used_in_insn[i / 32u] |= 1 << i % 32u;
+ }
+ reload_reg_used_at_all[i / 32u] |= 1 << i;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr50717-1.c b/gcc/testsuite/gcc.dg/pr50717-1.c
new file mode 100644
index 00000000000..afbe542a2be
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50717-1.c
@@ -0,0 +1,26 @@
+/* PR tree-optimization/50717 */
+/* Ensure that widening multiply-and-accumulate is not used where integer
+ type promotion or users' casts should prevent it. */
+
+/* { dg-options "-O2 -fdump-tree-widening_mul" } */
+
+long long
+f (unsigned int a, char b, long long c)
+{
+ return (a * b) + c;
+}
+
+int
+g (short a, short b, int c)
+{
+ return (short)(a * b) + c;
+}
+
+int
+h (char a, char b, int c)
+{
+ return (char)(a * b) + c;
+}
+
+/* { dg-final { scan-tree-dump-times "WIDEN_MULT_PLUS_EXPR" 0 "widening_mul" } } */
+/* { dg-final { cleanup-tree-dump "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/pr50763-2.c b/gcc/testsuite/gcc.dg/pr50763-2.c
new file mode 100644
index 00000000000..a9d12e8f543
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50763-2.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef union tree_node *tree;
+
+struct tree_base
+{
+ int code;
+};
+
+struct tree_typed
+{
+ struct tree_base base;
+ tree type;
+};
+
+struct tree_common
+{
+ struct tree_typed typed;
+};
+
+struct tree_type_common
+{
+ tree main_variant;
+};
+
+union tree_node
+{
+ struct tree_base base;
+ struct tree_typed typed;
+ struct tree_type_common type_common;
+};
+
+int std_canonical_va_list_type (tree type)
+{
+ if (type->base.code)
+ type = type->typed.type;
+ else
+ if (type->typed.type->base.code)
+ type = type->typed.type;
+
+ if (type->type_common.main_variant)
+ return 1;
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr50763.c b/gcc/testsuite/gcc.dg/pr50763.c
new file mode 100644
index 00000000000..60025e30a27
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50763.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-pre" } */
+
+int bar (int i);
+
+void
+foo (int c, int d)
+{
+ if (bar (c))
+ bar (c);
+ d = 33;
+ while (c == d);
+}
+
+/* { dg-final { scan-tree-dump-times "== 33" 1 "pre"} } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/testsuite/gcc.dg/pr50908-2.c b/gcc/testsuite/gcc.dg/pr50908-2.c
new file mode 100644
index 00000000000..bffea335a70
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50908-2.c
@@ -0,0 +1,80 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-tail-merge" } */
+
+typedef struct rtx_def *rtx;
+enum debug_info_levels
+{
+ ARM_FLOAT_ABI_SOFT, ARM_FLOAT_ABI_SOFTFP, ARM_FLOAT_ABI_HARD
+};
+struct gcc_options
+{
+ int x_target_flags;
+};
+extern struct gcc_options global_options;
+extern int arm_arch_thumb2;
+enum rtx_code
+{
+ UNSPEC, UNSPEC_VOLATILE, ADDR_VEC, SET, CLOBBER, CALL, RETURN,
+ SIMPLE_RETURN, EH_RETURN, TRAP_IF, CONST_INT, CONST_FIXED, CONST_DOUBLE,
+ CONST_VECTOR, CONST_STRING, CONST, PC, REG, SCRATCH, SUBREG,
+ STRICT_LOW_PART, CONCAT, CONCATN, MEM, LABEL_REF, SYMBOL_REF, CC0,
+ IF_THEN_ELSE, COMPARE, PLUS, MINUS, NEG, MULT, SS_MULT, US_MULT, DIV,
+ SS_DIV, US_DIV, MOD, UDIV, UMOD, AND, IOR, XOR, NOT, ASHIFT, ROTATE,
+ ASHIFTRT, LSHIFTRT, ROTATERT, PRE_DEC, PRE_INC, POST_DEC, POST_INC,
+ PRE_MODIFY, POST_MODIFY, NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU,
+ UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE, UNLT, LTGT, SIGN_EXTEND,
+ ZERO_EXTEND, TRUNCATE, FLOAT_EXTEND, FLOAT_TRUNCATE, FLOAT, FIX,
+ UNSIGNED_FLOAT, UNSIGNED_FIX, SIGN_EXTRACT, ZERO_EXTRACT, HIGH, LO_SUM,
+ VEC_MERGE, VEC_SELECT, VEC_CONCAT, VEC_DUPLICATE, SS_PLUS, US_PLUS,
+ SS_MINUS, SS_NEG, US_NEG, SS_ABS, SS_ASHIFT, US_ASHIFT, US_MINUS,
+ SS_TRUNCATE, US_TRUNCATE, FMA, VAR_LOCATION, DEBUG_IMPLICIT_PTR,
+ ENTRY_VALUE, DEBUG_PARAMETER_REF, LAST_AND_UNUSED_RTX_CODE
+};
+union rtunion_def
+{
+};
+struct rtx_def
+{
+ enum rtx_code code:16;
+}
+builtin_info_type;
+enum constraint_num
+{
+ CONSTRAINT__UNKNOWN =
+ 0, CONSTRAINT_f, CONSTRAINT_t, CONSTRAINT_v, CONSTRAINT_w, CONSTRAINT_x,
+ CONSTRAINT_y, CONSTRAINT_z, CONSTRAINT_l, CONSTRAINT_h, CONSTRAINT_j,
+ CONSTRAINT_Pj, CONSTRAINT_PJ, CONSTRAINT_k, CONSTRAINT_b, CONSTRAINT_c,
+ CONSTRAINT_I, CONSTRAINT_J, CONSTRAINT_K, CONSTRAINT_L, CONSTRAINT_M,
+ CONSTRAINT_N, CONSTRAINT_O, CONSTRAINT_Pa, CONSTRAINT_Pb, CONSTRAINT_Pc,
+ CONSTRAINT_Pd, CONSTRAINT_Ps, CONSTRAINT_Pt, CONSTRAINT_Pu, CONSTRAINT_Pv,
+ CONSTRAINT_Pw, CONSTRAINT_Px, CONSTRAINT_Py, CONSTRAINT_G, CONSTRAINT_H,
+ CONSTRAINT_Dz, CONSTRAINT_Da, CONSTRAINT_Db, CONSTRAINT_Dc, CONSTRAINT_Di,
+ CONSTRAINT_Dn, CONSTRAINT_Dl, CONSTRAINT_DL, CONSTRAINT_Dv, CONSTRAINT_Dy,
+ CONSTRAINT_Ut, CONSTRAINT_Uv, CONSTRAINT_Uy, CONSTRAINT_Un, CONSTRAINT_Um,
+ CONSTRAINT_Us, CONSTRAINT_Uq, CONSTRAINT_Q, CONSTRAINT_Uu, CONSTRAINT_Uw,
+ CONSTRAINT__LIMIT
+};
+typedef struct VEC_char_base
+{
+}
+VEC_int_heap;
+static inline int
+satisfies_constraint_j (rtx op)
+{
+ long long ival = 0;
+ return ((((!((global_options.x_target_flags & (1 << 14)) != 0))
+ || arm_arch_thumb2) && arm_arch_thumb2))
+ && ((((enum rtx_code) (op)->code) == HIGH)
+ || ((((enum rtx_code) (op)->code) == CONST_INT)
+ && (((ival & 0xffff0000) == 0))));
+}
+
+int
+constraint_satisfied_p (rtx op, enum constraint_num c)
+{
+ switch (c)
+ {
+ case CONSTRAINT_j:
+ return satisfies_constraint_j (op);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr50908-3.c b/gcc/testsuite/gcc.dg/pr50908-3.c
new file mode 100644
index 00000000000..60db03dae85
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50908-3.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-tail-merge" } */
+
+extern int v1;
+extern int v2;
+
+void
+f ()
+{
+ if (v2 || v1)
+ (!(v1)) ? (void) 0 : (void) g ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr50908.c b/gcc/testsuite/gcc.dg/pr50908.c
new file mode 100644
index 00000000000..75341f8f105
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr50908.c
@@ -0,0 +1,175 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O2 -ftree-tail-merge" } */
+
+enum Lisp_Type
+{
+ Lisp_Int0 = 0, Lisp_Int1 = 4, Lisp_Symbol = 2, Lisp_Misc = 3, Lisp_String =
+ 1, Lisp_Vectorlike = 5, Lisp_Cons = 6, Lisp_Float = 7,
+};
+typedef long Lisp_Object;
+enum pvec_type
+{
+ PVEC_NORMAL_VECTOR = 0, PVEC_PROCESS = 0x200, PVEC_FRAME =
+ 0x400, PVEC_COMPILED = 0x800, PVEC_WINDOW =
+ 0x1000, PVEC_WINDOW_CONFIGURATION = 0x2000, PVEC_SUBR =
+ 0x4000, PVEC_CHAR_TABLE = 0x8000, PVEC_BOOL_VECTOR =
+ 0x10000, PVEC_BUFFER = 0x20000, PVEC_HASH_TABLE = 0x40000, PVEC_TERMINAL =
+ 0x80000, PVEC_SUB_CHAR_TABLE = 0x100000, PVEC_FONT =
+ 0x200000, PVEC_OTHER = 0x400000, PVEC_TYPE_MASK = 0x7ffe00
+};
+struct Lisp_Vector
+{
+ unsigned long size;
+};
+struct Lisp_Char_Table
+{
+ Lisp_Object defalt;
+ Lisp_Object ascii;
+};
+struct Lisp_Sub_Char_Table
+{
+ Lisp_Object contents[1];
+};
+extern Lisp_Object Qnil, Qt, Qquote, Qlambda, Qsubr, Qunbound;
+struct buffer_text
+{
+ unsigned char *beg;
+ long gpt_byte;
+ long gap_size;
+};
+struct buffer
+{
+ struct buffer_text *text;
+ struct region_cache *width_run_cache;
+ Lisp_Object tab_width;
+ Lisp_Object ctl_arrow;
+};
+extern struct buffer *current_buffer;
+extern Lisp_Object Vchar_width_table;
+struct frame
+{
+ long text_lines, text_cols;
+};
+struct window
+{
+ Lisp_Object frame;
+};
+extern Lisp_Object Vtruncate_partial_width_windows;
+extern struct Lisp_Char_Table *window_display_table (struct window *);
+struct position *
+compute_motion (from, fromvpos, fromhpos, did_motion, to, tovpos, tohpos,
+ width, hscroll, tab_offset, win)
+ long from, fromvpos, fromhpos, to, tovpos, tohpos;
+ struct window *win;
+{
+ register long hpos = fromhpos;
+ register long pos;
+ long pos_byte;
+ register int c = 0;
+ register struct Lisp_Char_Table *dp = window_display_table (win);
+ long wide_column_end_hpos = 0;
+ long continuation_glyph_width;
+ while (1)
+ {
+ if (hpos > width)
+ {
+ int total_width = width + continuation_glyph_width;
+ if (!((Vtruncate_partial_width_windows) == (Qnil))
+ && (total_width <
+ (((void) 0,
+ (struct frame
+ *) ((long) (((win)->frame) & ~((((long) 1) << 3) -
+ 1)))))->text_cols))
+ {
+ if (pos <= to)
+ {
+ pos = find_before_next_newline (pos, to, 1);
+ }
+ if (wide_column_end_hpos > width)
+ {
+ hpos -= width;
+ }
+ }
+ }
+ else
+ {
+ Lisp_Object charvec;
+ c =
+ *(((((pos_byte)) >=
+ (current_buffer->text->gpt_byte) ? (current_buffer->text->
+ gap_size) : 0) +
+ ((pos_byte)) + (current_buffer->text->beg) - ((1))));
+ if (current_buffer->width_run_cache)
+ {
+ if (((((enum Lisp_Type) (((unsigned long) ((charvec))) &
+ ((((long) 1) << 3) - 1))) ==
+ Lisp_Vectorlike)
+ &&
+ !(((void) 0,
+ (struct Lisp_Vector
+ *) ((long) ((charvec) & ~((((long) 1) << 3) - 1))))->
+ size & ((((unsigned long) 1 << (64 - 1)) >> 1)))))
+ {
+ unsigned char *ptr;
+ int bytes, width, wide_column;
+ do
+ {
+ if ((!((*ptr) & 0x80) ? 1 : !((*ptr) & 0x20) ? 2 :
+ !((*ptr) & 0x10) ? 3 : !((*ptr) & 0x08) ? 4 : 5) !=
+ bytes)
+ width = bytes * 4;
+ else
+ {
+ if (dp != 0
+ &&
+ ((((enum
+ Lisp_Type) (((unsigned
+ long) (((((unsigned) (c) <
+ 0x80)
+ ? ((((dp)->ascii) ==
+ (Qnil)) ? (dp)->
+ defalt
+ : (((((enum
+ Lisp_Type)
+ (((unsigned
+ long) (((dp)->ascii))) & ((((long) 1) << 3) - 1))) == Lisp_Vectorlike) && (((((void) 0, (struct Lisp_Vector *) ((long) (((dp)->ascii) & ~((((long) 1) << 3) - 1))))->size & (((((unsigned long) 1 << (64 - 1)) >> 1)) | (PVEC_SUB_CHAR_TABLE)))) == (((((unsigned long) 1 << (64 - 1)) >> 1)) | (PVEC_SUB_CHAR_TABLE)))) ? ((void) 0, (struct Lisp_Sub_Char_Table *) ((long) (((dp)->ascii) & ~((((long) 1) << 3) - 1))))->contents[c] : (dp)->ascii)) : disp_char_vector ((dp), (c)))))) & ((((long) 1) << 3) - 1))) == Lisp_Vectorlike) && !(((void) 0, (struct Lisp_Vector *) ((long) (((((unsigned) (c) < 0x80) ? ((((dp)->ascii) == (Qnil)) ? (dp)->defalt : (((((enum Lisp_Type) (((unsigned long) (((dp)->ascii))) & ((((long) 1) << 3) - 1))) == Lisp_Vectorlike) && (((((void) 0, (struct Lisp_Vector *) ((long) (((dp)->ascii) & ~((((long) 1) << 3) - 1))))->size & (((((unsigned long) 1 << (64 - 1)) >> 1)) | (PVEC_SUB_CHAR_TABLE)))) == (((((unsigned long) 1 << (64 - 1)) >> 1)) | (PVEC_SUB_CHAR_TABLE)))) ? ((void) 0, (struct Lisp_Sub_Char_Table *) ((long) (((dp)->ascii) & ~((((long) 1) << 3) - 1))))->contents[c] : (dp)->ascii)) : disp_char_vector ((dp), (c)))) & ~((((long) 1) << 3) - 1))))->size & ((((unsigned long) 1 << (64 - 1)) >> 1)))))
+ width =
+ ((void) 0,
+ (struct Lisp_Vector
+ *) ((long) (((((unsigned) (c) <
+ 0x80) ? ((((dp)->ascii) ==
+ (Qnil)) ? (dp)->
+ defalt
+ : (((((enum
+ Lisp_Type) (((unsigned long) (((dp)->ascii))) & ((((long) 1) << 3) - 1))) == Lisp_Vectorlike) && (((((void) 0, (struct Lisp_Vector *) ((long) (((dp)->ascii) & ~((((long) 1) << 3) - 1))))->size & (((((unsigned long) 1 << (64 - 1)) >> 1)) | (PVEC_SUB_CHAR_TABLE)))) == (((((unsigned long) 1 << (64 - 1)) >> 1)) | (PVEC_SUB_CHAR_TABLE)))) ? ((void) 0, (struct Lisp_Sub_Char_Table *) ((long) (((dp)->ascii) & ~((((long) 1) << 3) - 1))))->contents[c] : (dp)->ascii)) : disp_char_vector ((dp), (c)))) & ~((((long) 1) << 3) - 1))))->size;
+ else
+ width =
+ (((unsigned) (c) < 0x80) ? (c <
+ 0x20 ? (c ==
+ '\t'
+ ? ((((long)
+ (current_buffer->
+ tab_width))
+ >> (3 -
+ 1)))
+ : (c ==
+ '\n' ? 0
+ : (((current_buffer->ctl_arrow) == (Qnil)) ? 4 : 2))) : (c < 0x7f ? 1 : ((((current_buffer->ctl_arrow) == (Qnil)) ? 4 : 2)))) : (((long) ((((unsigned) (c) < 0x80) ? (
+ {
+ Lisp_Object
+ _val;
+ _val;}
+ ): char_table_ref ((Vchar_width_table), (c))))) >> (3 - 1)));
+ if (width > 1)
+ wide_column = width;
+ }
+ }
+ while (0);
+ if (wide_column)
+ wide_column_end_hpos = hpos + wide_column;
+ }
+ }
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/scal-to-vec2.c b/gcc/testsuite/gcc.dg/scal-to-vec2.c
index 1354aa55b3d..9ff8c059e56 100644
--- a/gcc/testsuite/gcc.dg/scal-to-vec2.c
+++ b/gcc/testsuite/gcc.dg/scal-to-vec2.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
/* Test for C_MAYBE_CONST are folded correctly when
expanding an expression to vector. */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-22.c b/gcc/testsuite/gcc.dg/strlenopt-22.c
new file mode 100644
index 00000000000..541bfdce467
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-22.c
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-strlen" } */
+
+#define USE_GNU
+#include "strlenopt.h"
+
+__attribute__((noinline, noclone)) size_t
+bar (char *p, char *q)
+{
+ size_t l1, l2, l3;
+ char *r = strchr (p, '\0');
+ strcpy (r, "abcde");
+ char *s = strchr (r, '\0');
+ strcpy (s, q);
+ l1 = strlen (p);
+ l2 = strlen (r);
+ l3 = strlen (s);
+ return l1 + l2 + l3;
+}
+
+int
+main ()
+{
+ char buf[16] = "01234";
+
+ if (bar (buf, "56789") != 30)
+ abort ();
+
+ if (memcmp (buf, "01234abcde56789", 16) != 0)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */
+/* { dg-final { cleanup-tree-dump "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-4.c b/gcc/testsuite/gcc.dg/strlenopt-4.c
index beea4959245..5997d31985f 100644
--- a/gcc/testsuite/gcc.dg/strlenopt-4.c
+++ b/gcc/testsuite/gcc.dg/strlenopt-4.c
@@ -66,10 +66,16 @@ main ()
return 0;
}
-/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */
+/* For targets providing a movstr pattern strcat is already decomposed
+ into strlen + strcpy by fold_builtin_strcat. */
+
+/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "strlen \\(" 6 "strlen" { target s390*-*-* } } } */
/* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "strcpy \\(" 3 "strlen" } } */
-/* { dg-final { scan-tree-dump-times "strcat \\(" 3 "strlen" } } */
+/* { dg-final { scan-tree-dump-times "strcpy \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "strcpy \\(" 6 "strlen" { target s390*-*-* } } } */
+/* { dg-final { scan-tree-dump-times "strcat \\(" 3 "strlen" { target { ! s390*-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" { target s390*-*-* } } } */
/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */
/* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */
diff --git a/gcc/testsuite/gcc.dg/tls/thr-cse-1.c b/gcc/testsuite/gcc.dg/tls/thr-cse-1.c
index 95d3b4580cc..7542350d8da 100644
--- a/gcc/testsuite/gcc.dg/tls/thr-cse-1.c
+++ b/gcc/testsuite/gcc.dg/tls/thr-cse-1.c
@@ -15,9 +15,10 @@ int foo (int b, int c, int d)
return a;
}
-/* { dg-final { scan-assembler-not "emutls_get_address.*emutls_get_address.*" { target { ! { "*-wrs-vxworks" "*-*-darwin8" "hppa*-*-hpux*" "spu-*-*" } } } } } */
+/* { dg-final { scan-assembler-not "emutls_get_address.*emutls_get_address.*" { target { ! { "*-wrs-vxworks" "*-*-darwin8" "hppa*-*-hpux*" "spu-*-*" "i?86-*-mingw*" } } } } } */
/* { dg-final { scan-assembler-not "call\tL___emutls_get_address.stub.*call\tL___emutls_get_address.stub.*" { target "*-*-darwin8" } } } */
/* { dg-final { scan-assembler-not "(b,l|bl) __emutls_get_address.*(b,l|bl) __emutls_get_address.*" { target "hppa*-*-hpux*" } } } */
/* { dg-final { scan-assembler-not "(brsl|brasl)\t__emutls_get_address.*(brsl|brasl)\t__emutls_get_address.*" { target spu-*-* } } } */
/* { dg-final { scan-assembler-not "tls_lookup.*tls_lookup.*" { target *-wrs-vxworks } } } */
+/* { dg-final { scan-assembler-not "call\t___emutls_get_address.*call\t___emutls_get_address" { target "i?86-*-mingw*" } } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr36400.c b/gcc/testsuite/gcc.dg/torture/pr36400.c
index bd9f35a5f76..1dedc0aa1ca 100644
--- a/gcc/testsuite/gcc.dg/torture/pr36400.c
+++ b/gcc/testsuite/gcc.dg/torture/pr36400.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-options "-ffat-lto-objects" } */
struct barstruct { char const* some_string; };
diff --git a/gcc/testsuite/gcc.dg/torture/pr50723.c b/gcc/testsuite/gcc.dg/torture/pr50723.c
new file mode 100644
index 00000000000..24e490fc618
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50723.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+typedef short unsigned int wchar_t;
+typedef unsigned int size_t;
+int* _errno(void);
+int WideCharToMultiByte (wchar_t *);
+int __attribute__ ((__nonnull__ (1)))
+__wcrtomb_cp (char *dst, wchar_t wc, const unsigned int cp,
+ const unsigned int mb_max)
+{
+ if (cp == 0) {
+ if (wc > 255)
+ (*_errno()) = 42;
+ return 1;
+ }
+ else
+ return WideCharToMultiByte (&wc);
+}
+void wcsrtombs (char *dst, const wchar_t *pwc, unsigned int cp,
+ unsigned int mb_max)
+{
+ if ((__wcrtomb_cp (dst, *pwc, cp, mb_max)) <= 0)
+ return;
+ if ((__wcrtomb_cp (dst, *pwc, cp, mb_max)) <= 0)
+ return;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50729.c b/gcc/testsuite/gcc.dg/torture/pr50729.c
new file mode 100644
index 00000000000..a1daa7b851f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50729.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-require-effective-target int32plus } */
+
+extern void abort (void);
+unsigned short __attribute__((noinline))
+foo (int i)
+{
+ if (i >= 0
+ && i <= 0x400000)
+ return (unsigned short)(signed char)i;
+ return i;
+}
+int main()
+{
+ int i;
+ for (i = 0; i < 0xffff; ++i)
+ if (foo(i) != (unsigned short)(signed char) i)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50767.c b/gcc/testsuite/gcc.dg/torture/pr50767.c
new file mode 100644
index 00000000000..96ab72ebd7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50767.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fno-tree-copy-prop -fno-tree-dominator-opts" } */
+
+struct S
+{
+ struct S *s;
+};
+
+static struct S *ss;
+struct S *s;
+
+void bar(void);
+
+void foo(void)
+{
+ for (;;)
+ {
+ s->s = ss;
+ bar ();
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50768.c b/gcc/testsuite/gcc.dg/torture/pr50768.c
new file mode 100644
index 00000000000..351b2f96618
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50768.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-ftracer" } */
+
+char data[8];
+int l1;
+
+void
+test1 (void)
+{
+ char buf[8];
+ __builtin___mempcpy_chk (buf, data, l1 ? sizeof (buf) : 4,
+ __builtin_object_size (buf, 0));
+ if (__builtin___memmove_chk
+ (buf, data, l1 ? sizeof (buf) : 4,
+ __builtin_object_size (buf, 0)) != buf)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50838.c b/gcc/testsuite/gcc.dg/torture/pr50838.c
new file mode 100644
index 00000000000..a3911c9752a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50838.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+
+typedef void * gcv_object_t;
+typedef gcv_object_t object;
+typedef const void * Pseudofun;
+extern struct pseudocode_tab_ {
+ Pseudofun pseudo_eql;
+ Pseudofun pseudo_iconv_wcslen;
+ Pseudofun pseudo_iconv_wcstombs;
+ Pseudofun pseudo_iconv_range;
+}
+pseudocode_tab;
+extern struct symbol_tab_ {
+ object pointer[1024];
+} pseudofun_tab;
+int
+init_memory (void)
+{
+ object* ptr2 = &pseudofun_tab.pointer[0];
+ const Pseudofun* ptr1 = (const Pseudofun*)&pseudocode_tab;
+ unsigned int count = (sizeof(pseudocode_tab)/sizeof(Pseudofun));
+ while (count--)
+ {
+ *ptr2++ = (gcv_object_t)(((unsigned char *)((*ptr1))));
+ ptr1++;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr50890.c b/gcc/testsuite/gcc.dg/torture/pr50890.c
new file mode 100644
index 00000000000..17240d4fb82
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50890.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+static float make_insn_raw (void)
+{
+ return 0;
+}
+
+static int emit_pattern_after_noloc (int (make_raw) ())
+{
+ return make_raw ();
+}
+
+void emit_insn_after_noloc (void)
+{
+ emit_pattern_after_noloc ((void *) make_insn_raw);
+}
+
diff --git a/gcc/testsuite/gcc.dg/torture/pr50902.c b/gcc/testsuite/gcc.dg/torture/pr50902.c
new file mode 100644
index 00000000000..5b7275b839d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr50902.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+_Bool data[128];
+void foo (_Bool *init)
+{
+ int i;
+ for (i = 0; i < 128; i++)
+ data[i] = *init;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/restrict-1.c b/gcc/testsuite/gcc.dg/torture/restrict-1.c
new file mode 100644
index 00000000000..e7af4f538ce
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/restrict-1.c
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+
+extern void abort (void);
+void __attribute__((noinline,noclone))
+foo (int ** __restrict__ p, int ** __restrict__ q)
+{
+ **p = **q;
+}
+int main()
+{
+ int x = 0, y = 1, *i = &x, *j = &y;
+ foo (&i, &j);
+ if (x != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-16.inc b/gcc/testsuite/gcc.dg/torture/vshuf-16.inc
new file mode 100644
index 00000000000..89ef544a11a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-16.inc
@@ -0,0 +1,135 @@
+#define N 16
+#define TESTS \
+T (0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) \
+T (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+T (2, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7) \
+T (3, 0, 18, 7, 16, 23, 5, 4, 22, 1, 6, 21, 20, 19, 3, 17, 2) \
+T (4, 0, 1, 2, 3, 4, 5, 6, 7, 7, 1, 2, 0, 4, 5, 6, 3) \
+T (5, 0, 19, 16, 3, 2, 17, 18, 1, 24, 8, 11, 10, 27, 26, 25, 9) \
+T (6, 4, 23, 20, 7, 6, 21, 22, 5, 28, 12, 15, 14, 31, 30, 29, 13) \
+T (7, 7, 1, 2, 0, 4, 5, 6, 3, 7, 1, 2, 0, 4, 5, 6, 3) \
+T (8, 7, 3, 0, 5, 4, 1, 6, 2, 31, 27, 24, 29, 28, 25, 30, 26) \
+T (9, 7, 1, 2, 0, 4, 5, 6, 3, 15, 9, 14, 10, 8, 12, 13, 11) \
+T (10, 15, 0, 3, 12, 14, 2, 1, 13, 4, 11, 9, 6, 5, 10, 7, 8) \
+T (11, 15, 9, 14, 10, 8, 12, 13, 11, 7, 1, 2, 0, 4, 5, 6, 3) \
+T (12, 2, 5, 24, 23, 17, 22, 20, 21, 12, 14, 13, 8, 6, 20, 10, 18) \
+T (13, 23, 11, 15, 9, 0, 14, 8, 12, 10, 13, 19, 11, 2, 26, 24, 30) \
+T (14, 25, 5, 17, 1, 9, 15, 21, 7, 28, 2, 18, 13, 30, 14, 10, 4) \
+T (15, 1, 30, 27, 31, 9, 18, 25, 12, 7, 4, 2, 16, 25, 20, 10, 3) \
+T (16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30) \
+T (17, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31) \
+T (18, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3) \
+T (19, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+#define EXPTESTS \
+T (116, 28, 13, 27, 11, 21, 1, 5, 22, 29, 14, 15, 6, 3, 10, 16, 30) \
+T (117, 22, 26, 1, 13, 29, 3, 18, 18, 11, 21, 12, 28, 19, 5, 7, 4) \
+T (118, 1, 28, 26, 11, 4, 27, 30, 12, 10, 19, 6, 7, 13, 31, 0, 24) \
+T (119, 7, 30, 17, 27, 0, 10, 13, 21, 3, 29, 24, 21, 12, 6, 15, 18) \
+T (120, 28, 13, 26, 24, 21, 16, 29, 9, 10, 2, 27, 19, 20, 17, 18, 14) \
+T (121, 22, 21, 1, 8, 14, 15, 0, 28, 25, 30, 10, 17, 19, 27, 26, 13) \
+T (122, 28, 13, 27, 2, 21, 29, 22, 4, 8, 0, 18, 1, 31, 7, 19, 14) \
+T (123, 15, 0, 9, 2, 31, 3, 17, 24, 1, 8, 26, 20, 30, 11, 22, 5) \
+T (124, 28, 14, 5, 7, 9, 10, 21, 31, 2, 11, 22, 27, 7, 27, 30, 2) \
+T (125, 17, 13, 1, 7, 20, 22, 8, 15, 4, 25, 10, 28, 23, 24, 9, 21) \
+T (126, 17, 5, 3, 4, 0, 7, 19, 13, 29, 25, 26, 1, 15, 8, 2, 7) \
+T (127, 16, 6, 3, 22, 31, 15, 13, 21, 14, 20, 29, 17, 18, 2, 23, 25) \
+T (128, 18, 22, 21, 28, 10, 13, 6, 17, 29, 20, 7, 16, 2, 9, 1, 11) \
+T (129, 30, 11, 11, 22, 21, 10, 3, 18, 15, 26, 20, 16, 17, 13, 29, 7) \
+T (130, 5, 9, 21, 16, 29, 11, 4, 2, 17, 28, 3, 19, 9, 10, 13, 20) \
+T (131, 13, 3, 19, 25, 1, 28, 31, 30, 10, 12, 21, 26, 27, 14, 5, 17) \
+T (132, 8, 28, 26, 31, 5, 14, 4, 13, 6, 15, 3, 17, 6, 20, 27, 29) \
+T (133, 7, 26, 8, 17, 31, 11, 25, 16, 19, 4, 0, 27, 7, 20, 19, 13) \
+T (134, 14, 23, 19, 4, 9, 11, 16, 6, 7, 3, 27, 20, 24, 18, 26, 31) \
+T (135, 7, 25, 14, 2, 16, 5, 29, 3, 4, 24, 21, 9, 20, 19, 27, 1) \
+T (136, 5, 14, 29, 12, 3, 3, 1, 4, 8, 7, 9, 13, 10, 4, 12, 23) \
+T (137, 2, 6, 21, 28, 5, 23, 16, 24, 22, 18, 30, 12, 31, 16, 4, 1) \
+T (138, 4, 31, 11, 26, 16, 23, 5, 12, 15, 14, 19, 3, 18, 21, 27, 6) \
+T (139, 29, 14, 19, 18, 23, 27, 16, 7, 8, 26, 0, 12, 15, 17, 9, 1) \
+T (140, 18, 27, 20, 31, 8, 10, 9, 17, 13, 19, 12, 15, 28, 3, 25, 5) \
+T (141, 28, 13, 23, 20, 10, 5, 22, 17, 27, 0, 21, 27, 11, 25, 24, 30) \
+T (142, 24, 17, 31, 22, 9, 15, 28, 6, 12, 23, 30, 1, 21, 5, 27, 29) \
+T (143, 12, 19, 16, 0, 8, 15, 13, 22, 17, 4, 31, 20, 2, 9, 21, 30) \
+T (144, 5, 13, 26, 12, 27, 0, 17, 1, 25, 8, 10, 25, 18, 11, 29, 4) \
+T (145, 6, 18, 13, 29, 14, 31, 16, 10, 2, 12, 20, 25, 23, 28, 24, 10) \
+T (146, 17, 0, 21, 0, 12, 13, 16, 5, 19, 29, 30, 27, 4, 9, 1, 20) \
+T (147, 14, 26, 28, 17, 31, 10, 6, 3, 29, 22, 18, 1, 6, 5, 30, 8) \
+T (148, 10, 17, 12, 18, 26, 16, 5, 24, 2, 7, 20, 15, 30, 2, 29, 25) \
+T (149, 30, 27, 15, 23, 8, 12, 29, 2, 4, 9, 25, 13, 21, 7, 16, 20) \
+T (150, 7, 13, 4, 22, 24, 0, 31, 28, 18, 5, 2, 16, 17, 1, 1, 6) \
+T (151, 24, 27, 17, 25, 27, 6, 14, 30, 21, 19, 23, 29, 12, 19, 15, 9) \
+T (152, 1, 16, 24, 19, 29, 27, 17, 9, 8, 23, 22, 12, 11, 2, 26, 25) \
+T (153, 2, 25, 22, 8, 11, 16, 20, 26, 29, 15, 6, 15, 30, 10, 21, 24) \
+T (154, 19, 20, 23, 11, 20, 1, 18, 29, 21, 24, 6, 8, 19, 2, 4, 9) \
+T (155, 30, 12, 29, 21, 7, 8, 31, 15, 3, 1, 10, 4, 2, 9, 19, 2) \
+T (156, 14, 27, 5, 23, 15, 22, 4, 26, 30, 19, 29, 18, 16, 24, 21, 7) \
+T (157, 14, 15, 26, 17, 30, 16, 6, 0, 10, 8, 2, 23, 20, 13, 3, 27) \
+T (158, 2, 14, 13, 22, 24, 26, 17, 16, 4, 27, 7, 31, 9, 1, 28, 3) \
+T (159, 13, 15, 19, 12, 31, 23, 16, 8, 0, 2, 17, 27, 30, 14, 18, 1) \
+T (160, 3, 9, 30, 28, 31, 24, 5, 1, 23, 0, 13, 24, 20, 18, 3, 26) \
+T (161, 6, 10, 28, 8, 15, 14, 17, 26, 9, 0, 11, 2, 16, 2, 27, 24) \
+T (162, 20, 29, 7, 11, 5, 21, 0, 8, 12, 28, 13, 4, 26, 10, 28, 23) \
+T (163, 31, 25, 24, 10, 18, 3, 5, 12, 18, 2, 17, 22, 30, 16, 8, 6) \
+T (164, 0, 5, 22, 3, 21, 28, 31, 20, 12, 14, 18, 4, 13, 2, 0, 29) \
+T (165, 26, 18, 25, 20, 2, 0, 10, 30, 27, 11, 9, 3, 31, 4, 29, 21) \
+T (166, 15, 21, 3, 9, 22, 6, 29, 13, 24, 30, 31, 5, 26, 17, 0, 12) \
+T (167, 3, 28, 19, 27, 26, 14, 5, 10, 16, 24, 12, 30, 23, 13, 18, 26) \
+T (168, 0, 13, 10, 16, 23, 17, 8, 24, 20, 25, 21, 3, 12, 22, 6, 1) \
+T (169, 11, 18, 7, 26, 23, 6, 24, 21, 29, 18, 7, 19, 12, 31, 15, 28) \
+T (170, 14, 5, 21, 6, 9, 11, 12, 4, 0, 8, 30, 10, 24, 19, 18, 3) \
+T (171, 6, 3, 5, 13, 10, 2, 24, 31, 23, 2, 29, 4, 22, 7, 19, 20) \
+T (172, 12, 26, 13, 18, 19, 9, 1, 27, 14, 7, 20, 31, 11, 8, 30, 4) \
+T (173, 1, 23, 10, 31, 12, 26, 6, 13, 7, 30, 18, 4, 0, 27, 21, 19) \
+T (174, 20, 15, 13, 22, 10, 14, 5, 3, 31, 8, 0, 11, 4, 9, 1, 0) \
+T (175, 12, 29, 23, 28, 8, 20, 19, 7, 20, 24, 6, 26, 11, 17, 2, 5) \
+T (176, 19, 0, 31, 26, 30, 16, 17, 14, 5, 7, 3, 27, 1, 22, 29, 9) \
+T (177, 17, 15, 4, 1, 7, 13, 23, 28, 2, 8, 26, 12, 21, 24, 3, 19) \
+T (178, 17, 23, 21, 2, 12, 27, 8, 15, 6, 25, 7, 28, 4, 26, 1, 23) \
+T (179, 17, 25, 19, 4, 7, 20, 13, 30, 18, 3, 25, 21, 24, 26, 16, 31) \
+T (180, 7, 20, 18, 9, 3, 16, 12, 22, 0, 30, 10, 25, 17, 29, 19, 5) \
+T (181, 4, 17, 23, 1, 16, 22, 12, 31, 25, 9, 8, 21, 26, 15, 29, 29) \
+T (182, 31, 25, 14, 17, 8, 24, 4, 29, 27, 0, 20, 5, 13, 12, 5, 30) \
+T (183, 29, 26, 3, 22, 24, 30, 0, 15, 19, 7, 18, 6, 25, 14, 3, 3) \
+T (184, 23, 22, 7, 18, 10, 30, 29, 6, 16, 13, 11, 28, 5, 26, 4, 24) \
+T (185, 27, 15, 8, 29, 21, 23, 12, 11, 26, 22, 21, 6, 10, 23, 20, 27) \
+T (186, 19, 23, 20, 7, 8, 14, 6, 17, 20, 1, 5, 12, 25, 18, 10, 29) \
+T (187, 12, 14, 2, 5, 31, 21, 30, 18, 2, 6, 17, 22, 22, 28, 0, 18) \
+T (188, 10, 8, 13, 29, 20, 18, 8, 5, 4, 3, 26, 19, 24, 29, 6, 30) \
+T (189, 23, 19, 8, 2, 21, 18, 26, 1, 27, 12, 10, 4, 3, 20, 10, 17) \
+T (190, 31, 30, 21, 8, 15, 9, 3, 22, 7, 17, 25, 5, 13, 6, 1, 11) \
+T (191, 0, 5, 26, 6, 18, 1, 9, 31, 11, 3, 10, 23, 30, 27, 17, 14) \
+T (192, 19, 7, 29, 27, 8, 17, 22, 20, 10, 22, 2, 11, 9, 14, 31, 23) \
+T (193, 3, 23, 10, 18, 14, 9, 4, 24, 8, 30, 9, 13, 16, 17, 4, 22) \
+T (194, 13, 22, 8, 3, 9, 24, 9, 7, 15, 17, 26, 19, 11, 5, 18, 24) \
+T (195, 1, 18, 17, 13, 14, 0, 6, 15, 31, 22, 9, 2, 23, 19, 20, 3) \
+T (196, 9, 8, 17, 4, 28, 20, 6, 1, 11, 12, 23, 0, 15, 27, 31, 18) \
+T (197, 11, 2, 16, 1, 29, 21, 14, 9, 23, 30, 22, 8, 27, 9, 18, 10) \
+T (198, 10, 6, 26, 22, 13, 28, 18, 31, 4, 17, 27, 5, 7, 25, 20, 21) \
+T (199, 9, 8, 0, 0, 10, 7, 4, 24, 16, 3, 20, 1, 31, 11, 17, 26) \
+T (200, 19, 24, 31, 25, 7, 4, 14, 4, 9, 21, 29, 30, 10, 16, 6, 13) \
+T (201, 27, 4, 25, 12, 11, 3, 29, 1, 16, 6, 12, 5, 26, 25, 10, 15) \
+T (202, 11, 28, 9, 3, 20, 30, 18, 6, 13, 12, 25, 24, 5, 26, 0, 31) \
+T (203, 7, 23, 14, 16, 1, 31, 3, 0, 18, 6, 4, 10, 11, 15, 13, 29) \
+T (204, 28, 15, 6, 4, 21, 18, 22, 29, 13, 3, 18, 27, 21, 7, 31, 26) \
+T (205, 2, 13, 7, 22, 21, 9, 24, 15, 6, 20, 14, 29, 16, 27, 31, 0) \
+T (206, 23, 3, 13, 0, 18, 19, 10, 29, 16, 22, 21, 30, 17, 5, 6, 31) \
+T (207, 0, 3, 6, 29, 7, 10, 20, 17, 5, 8, 27, 18, 12, 4, 30, 28) \
+T (208, 5, 31, 20, 6, 14, 11, 28, 19, 7, 25, 27, 26, 10, 8, 22, 4) \
+T (209, 26, 22, 12, 9, 25, 0, 21, 14, 4, 7, 17, 30, 29, 24, 13, 31) \
+T (210, 15, 1, 6, 10, 26, 12, 8, 25, 3, 31, 23, 5, 30, 2, 0, 27) \
+T (211, 2, 11, 1, 27, 4, 17, 28, 22, 5, 28, 16, 20, 6, 3, 0, 15) \
+T (212, 25, 2, 6, 18, 16, 12, 4, 27, 1, 29, 7, 3, 21, 20, 17, 19) \
+T (213, 16, 0, 19, 21, 29, 23, 18, 31, 24, 12, 4, 20, 2, 8, 27, 30) \
+T (214, 20, 28, 9, 28, 22, 13, 2, 0, 8, 26, 10, 23, 24, 12, 31, 11) \
+T (215, 27, 22, 12, 15, 10, 20, 4, 25, 29, 9, 17, 3, 28, 21, 31, 23) \
+T (216, 16, 29, 20, 19, 16, 6, 18, 28, 3, 15, 29, 30, 1, 22, 10, 0) \
+T (217, 24, 14, 27, 3, 16, 30, 6, 0, 13, 12, 19, 7, 11, 20, 5, 26) \
+T (218, 19, 30, 26, 17, 13, 5, 10, 15, 16, 28, 24, 20, 0, 25, 9, 14) \
+T (219, 11, 0, 29, 5, 16, 30, 22, 19, 25, 4, 17, 7, 18, 2, 14, 13) \
+T (220, 27, 9, 16, 10, 19, 23, 12, 21, 3, 30, 18, 4, 15, 6, 29, 13) \
+T (221, 26, 12, 25, 22, 11, 18, 1, 7, 0, 19, 29, 31, 8, 4, 9, 15) \
+T (222, 18, 23, 31, 7, 26, 5, 15, 11, 25, 4, 22, 21, 14, 10, 20, 8) \
+T (223, 2, 18, 4, 24, 6, 20, 9, 25, 16, 3, 5, 22, 10, 7, 23, 30) \
+T (224, 4, 13, 6, 8, 22, 2, 12, 24, 31, 29, 20, 23, 0, 10, 1, 3) \
+T (225, 26, 3, 30, 18, 4, 19, 22, 31, 28, 24, 15, 14, 1, 23, 27, 7) \
+T (226, 18, 6, 23, 16, 25, 26, 17, 5, 28, 10, 30, 24, 12, 14, 15, 20) \
+T (227, 5, 19, 23, 22, 1, 7, 26, 12, 30, 17, 0, 0, 10, 6, 18, 4)
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-2.inc b/gcc/testsuite/gcc.dg/torture/vshuf-2.inc
new file mode 100644
index 00000000000..70b2e5c139a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-2.inc
@@ -0,0 +1,19 @@
+#define N 2
+#define TESTS \
+T (0, 0, 0) \
+T (1, 0, 1) \
+T (2, 0, 2) \
+T (3, 0, 3) \
+T (4, 1, 0) \
+T (5, 1, 1) \
+T (6, 1, 2) \
+T (7, 1, 3) \
+T (8, 2, 0) \
+T (9, 2, 1) \
+T (10, 2, 2) \
+T (11, 2, 3) \
+T (12, 3, 0) \
+T (13, 3, 1) \
+T (14, 3, 2) \
+T (15, 3, 3)
+#define EXPTESTS
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-32.inc b/gcc/testsuite/gcc.dg/torture/vshuf-32.inc
new file mode 100644
index 00000000000..bbeebaabeeb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-32.inc
@@ -0,0 +1,135 @@
+#define N 32
+#define TESTS \
+T (0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31) \
+T (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) \
+T (2, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) \
+T (3, 26, 60, 14, 40, 44, 51, 12, 45, 9, 37, 4, 47, 35, 63, 54, 30, 28, 10, 48, 32, 5, 59, 7, 52, 11, 6, 62, 49, 25, 25, 20, 55) \
+T (4, 32, 16, 54, 20, 62, 60, 56, 9, 38, 26, 42, 12, 17, 51, 4, 58, 59, 25, 50, 27, 41, 37, 8, 30, 18, 24, 40, 36, 25, 7, 37, 63) \
+T (5, 0, 4, 60, 9, 23, 19, 45, 6, 5, 12, 38, 60, 34, 36, 26, 11, 47, 52, 63, 39, 7, 56, 17, 54, 53, 39, 18, 2, 37, 55, 22, 21) \
+T (6, 2, 44, 46, 13, 40, 38, 52, 10, 50, 55, 11, 15, 9, 0, 12, 42, 45, 19, 11, 34, 26, 24, 62, 25, 5, 17, 1, 47, 21, 7, 60, 41) \
+T (7, 50, 13, 37, 62, 9, 49, 14, 53, 15, 42, 36, 1, 33, 27, 63, 41, 57, 12, 7, 2, 44, 48, 16, 39, 25, 31, 20, 10, 3, 60, 43, 21) \
+T (8, 1, 37, 22, 61, 5, 14, 46, 47, 6, 35, 10, 48, 30, 26, 33, 13, 18, 18, 11, 21, 44, 29, 60, 45, 19, 37, 7, 43, 36, 1, 28, 59) \
+T (9, 30, 44, 42, 51, 6, 7, 38, 13, 43, 31, 58, 0, 56, 17, 27, 32, 10, 53, 3, 29, 21, 12, 15, 50, 28, 24, 16, 61, 9, 34, 59, 19) \
+T (10, 20, 49, 50, 14, 54, 53, 33, 40, 46, 15, 0, 28, 25, 30, 10, 17, 51, 59, 26, 13, 45, 27, 2, 61, 4, 36, 8, 0, 18, 33, 22, 63) \
+T (11, 13, 40, 7, 33, 51, 21, 59, 46, 47, 32, 9, 34, 63, 35, 41, 17, 24, 1, 8, 26, 52, 62, 11, 22, 37, 28, 5, 39, 10, 53, 60, 2) \
+T (12, 39, 43, 54, 27, 53, 39, 27, 30, 2, 17, 13, 33, 7, 52, 40, 15, 36, 57, 10, 28, 22, 23, 25, 24, 41, 47, 8, 20, 5, 3, 4, 0) \
+T (13, 7, 51, 13, 61, 25, 4, 19, 58, 35, 33, 29, 15, 40, 2, 39, 16, 38, 3, 54, 63, 15, 6, 48, 21, 14, 52, 17, 50, 34, 55, 57, 50) \
+T (14, 22, 53, 28, 42, 45, 38, 49, 13, 54, 61, 21, 52, 7, 16, 34, 9, 1, 43, 62, 43, 35, 50, 47, 58, 20, 3, 30, 15, 37, 53, 43, 36) \
+T (15, 2, 43, 49, 34, 28, 35, 29, 36, 51, 9, 17, 48, 10, 37, 45, 21, 52, 19, 25, 33, 60, 31, 30, 42, 12, 26, 27, 46, 5, 40, 14, 36) \
+T (16, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62) \
+T (17, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63) \
+T (18, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3) \
+T (19, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
+#define EXPTESTS \
+T (116, 13, 38, 47, 3, 17, 8, 38, 20, 59, 61, 39, 26, 7, 49, 63, 43, 57, 16, 40, 19, 4, 32, 27, 7, 52, 19, 46, 55, 36, 41, 48, 6) \
+T (117, 39, 35, 59, 20, 56, 18, 58, 63, 57, 14, 2, 16, 5, 61, 35, 4, 53, 9, 52, 51, 27, 33, 61, 12, 3, 35, 36, 40, 37, 7, 45, 42) \
+T (118, 4, 5, 8, 14, 35, 12, 55, 34, 6, 53, 60, 5, 48, 56, 22, 18, 62, 44, 38, 31, 28, 16, 33, 36, 43, 26, 16, 23, 37, 47, 51, 3) \
+T (119, 26, 50, 53, 27, 6, 29, 14, 19, 23, 48, 39, 8, 58, 0, 12, 15, 17, 41, 33, 18, 52, 31, 10, 9, 49, 13, 51, 45, 47, 60, 35, 57) \
+T (120, 37, 60, 13, 55, 52, 42, 5, 22, 17, 59, 0, 21, 59, 11, 25, 56, 62, 56, 31, 54, 9, 47, 28, 6, 44, 33, 61, 12, 19, 16, 8, 40) \
+T (121, 47, 45, 44, 40, 22, 17, 4, 31, 8, 52, 34, 32, 41, 21, 62, 37, 5, 13, 58, 27, 0, 17, 33, 57, 42, 57, 18, 43, 61, 36, 38, 14) \
+T (122, 31, 16, 42, 6, 34, 2, 12, 20, 57, 29, 23, 60, 24, 10, 17, 0, 21, 32, 45, 5, 19, 30, 59, 4, 9, 1, 46, 14, 26, 63, 3, 22) \
+T (123, 46, 61, 50, 1, 38, 37, 62, 40, 10, 49, 44, 26, 16, 24, 5, 2, 39, 20, 15, 30, 34, 29, 57, 27, 47, 55, 8, 44, 36, 4, 9, 25) \
+T (124, 45, 53, 7, 48, 23, 21, 20, 7, 13, 4, 22, 24, 39, 0, 63, 60, 18, 37, 34, 36, 54, 49, 1, 1, 38, 27, 17, 57, 27, 14, 59, 62) \
+T (125, 30, 57, 46, 21, 51, 23, 25, 62, 29, 12, 51, 15, 41, 33, 16, 56, 19, 61, 27, 49, 41, 40, 55, 54, 44, 43, 2, 26, 34, 22, 11, 20) \
+T (126, 26, 29, 15, 57, 6, 15, 30, 10, 53, 24, 19, 52, 23, 43, 20, 1, 18, 29, 56, 51, 38, 8, 51, 2, 4, 41, 62, 12, 7, 63, 3, 33) \
+T (127, 42, 10, 36, 2, 41, 34, 19, 2, 46, 27, 5, 55, 15, 22, 36, 26, 30, 58, 51, 61, 18, 48, 24, 21, 56, 7, 14, 47, 17, 6, 0, 8) \
+T (128, 34, 23, 16, 20, 15, 13, 3, 30, 59, 46, 54, 24, 26, 45, 17, 48, 4, 27, 7, 31, 2, 41, 1, 28, 51, 12, 63, 8, 32, 19, 18, 33) \
+T (129, 3, 41, 62, 28, 30, 63, 24, 5, 33, 60, 55, 32, 37, 45, 56, 52, 50, 35, 26, 38, 10, 40, 15, 14, 17, 58, 46, 41, 11, 34, 48, 2) \
+T (130, 59, 60, 24, 20, 61, 39, 43, 37, 53, 32, 8, 44, 28, 13, 36, 58, 0, 42, 60, 55, 31, 57, 56, 10, 18, 3, 5, 12, 18, 34, 49, 54) \
+T (131, 3, 62, 16, 40, 38, 32, 5, 54, 53, 28, 63, 20, 12, 14, 50, 4, 13, 34, 32, 29, 26, 18, 25, 52, 2, 42, 30, 59, 43, 41, 27, 10) \
+T (132, 35, 31, 57, 52, 4, 0, 61, 21, 15, 3, 9, 54, 38, 13, 24, 30, 37, 58, 41, 6, 49, 32, 12, 28, 19, 59, 14, 42, 16, 48, 56, 23) \
+T (133, 62, 12, 13, 50, 26, 32, 45, 10, 48, 55, 49, 8, 24, 42, 52, 57, 53, 3, 54, 38, 33, 43, 7, 26, 23, 6, 21, 61, 18, 7, 51, 44) \
+T (134, 31, 15, 38, 39, 60, 14, 5, 21, 53, 6, 9, 43, 12, 36, 32, 40, 30, 10, 56, 51, 50, 35, 38, 3, 37, 13, 2, 24, 63, 34, 55, 34) \
+T (135, 29, 36, 22, 7, 63, 23, 19, 20, 12, 58, 13, 50, 41, 1, 59, 33, 46, 39, 52, 11, 8, 51, 62, 42, 31, 10, 58, 38, 45, 4, 32, 53) \
+T (136, 19, 20, 47, 13, 22, 10, 14, 37, 35, 31, 8, 15, 32, 54, 43, 40, 4, 9, 1, 32, 12, 29, 23, 60, 52, 51, 39, 52, 56, 6, 26, 11) \
+T (137, 39, 11, 49, 34, 37, 51, 32, 63, 26, 62, 16, 49, 14, 5, 7, 3, 59, 33, 54, 58, 61, 9, 47, 36, 13, 23, 28, 2, 40, 4, 44, 1) \
+T (138, 53, 24, 33, 35, 19, 49, 55, 34, 44, 27, 40, 47, 38, 17, 25, 39, 60, 4, 26, 15, 7, 36, 55, 51, 39, 20, 45, 62, 57, 50, 57, 21) \
+T (139, 24, 58, 16, 63, 7, 20, 18, 9, 35, 48, 12, 54, 0, 62, 41, 42, 25, 50, 17, 61, 51, 37, 4, 55, 33, 22, 12, 40, 53, 26, 47, 29) \
+T (140, 55, 53, 40, 61, 63, 57, 46, 17, 8, 56, 4, 29, 27, 32, 24, 52, 5, 13, 12, 5, 44, 30, 26, 3, 22, 0, 47, 19, 39, 50, 38, 15) \
+T (141, 15, 46, 3, 18, 3, 55, 22, 39, 10, 62, 61, 38, 48, 16, 6, 45, 11, 60, 5, 26, 4, 50, 24, 59, 47, 8, 29, 53, 12, 21, 43, 58) \
+T (142, 22, 8, 21, 6, 55, 10, 55, 20, 59, 19, 55, 23, 52, 39, 46, 49, 20, 1, 40, 5, 12, 14, 57, 50, 29, 2, 37, 31, 62, 18, 34, 54) \
+T (143, 54, 28, 50, 0, 62, 18, 10, 8, 13, 29, 52, 8, 5, 36, 35, 4, 58, 19, 56, 29, 38, 30, 55, 51, 40, 34, 53, 26, 33, 59, 12, 27) \
+T (144, 42, 4, 35, 20, 52, 3, 10, 21, 17, 63, 62, 40, 15, 41, 54, 39, 8, 57, 5, 45, 37, 38, 1, 43, 32, 58, 6, 50, 33, 3, 55, 9) \
+T (145, 27, 62, 49, 14, 19, 39, 61, 40, 22, 20, 10, 22, 34, 43, 9, 46, 31, 42, 54, 23, 35, 50, 4, 3, 41, 24, 8, 30, 9, 45, 48, 17) \
+T (146, 4, 40, 22, 45, 8, 35, 9, 24, 9, 41, 7, 47, 49, 58, 51, 43, 54, 37, 18, 39, 56, 1, 46, 0, 33, 38, 15, 13, 17, 31, 54, 2) \
+T (147, 55, 19, 20, 3, 41, 8, 49, 36, 28, 38, 1, 11, 44, 55, 32, 15, 59, 0, 63, 50, 2, 16, 61, 21, 14, 23, 30, 22, 33, 46, 48, 62) \
+T (148, 30, 40, 59, 11, 9, 8, 50, 42, 10, 6, 58, 22, 45, 60, 63, 4, 49, 31, 5, 7, 25, 18, 52, 13, 53, 0, 0, 39, 24, 48, 3, 20) \
+T (149, 41, 1, 63, 11, 49, 24, 26, 51, 31, 57, 7, 36, 46, 4, 53, 19, 29, 21, 30, 14, 10, 48, 38, 13, 59, 25, 44, 43, 35, 61, 33, 16) \
+T (150, 38, 44, 5, 26, 25, 42, 16, 15, 43, 28, 41, 3, 52, 62, 50, 11, 6, 35, 13, 12, 57, 24, 32, 31, 39, 55, 46, 33, 0, 18, 4, 47) \
+T (151, 45, 29, 60, 15, 6, 36, 53, 18, 54, 47, 61, 13, 3, 50, 21, 27, 28, 21, 7, 63, 26, 34, 9, 24, 52, 46, 38, 56, 48, 59, 31, 2) \
+T (152, 32, 23, 3, 13, 35, 55, 18, 19, 42, 29, 48, 54, 53, 30, 17, 62, 37, 38, 31, 32, 6, 61, 7, 10, 52, 8, 27, 12, 59, 50, 36, 28) \
+T (153, 37, 63, 52, 6, 46, 43, 28, 51, 7, 25, 59, 26, 42, 40, 22, 5, 4, 58, 54, 44, 41, 32, 53, 14, 39, 17, 30, 61, 24, 45, 31, 47) \
+T (154, 33, 38, 42, 58, 12, 10, 8, 25, 3, 63, 55, 37, 31, 30, 2, 0, 59, 34, 43, 11, 36, 27, 49, 28, 22, 60, 48, 20, 1, 6, 35, 47) \
+T (155, 57, 2, 6, 50, 16, 12, 36, 59, 1, 61, 39, 35, 21, 20, 17, 51, 48, 32, 19, 53, 29, 23, 18, 31, 24, 4, 52, 8, 27, 62, 60, 9) \
+T (156, 60, 54, 13, 2, 32, 8, 58, 42, 23, 24, 12, 63, 43, 59, 22, 44, 15, 20, 4, 57, 61, 27, 47, 9, 49, 35, 28, 21, 48, 52, 19, 48) \
+T (157, 61, 38, 50, 28, 35, 15, 29, 51, 30, 20, 1, 54, 10, 0, 24, 46, 59, 3, 16, 32, 45, 12, 7, 11, 48, 37, 26, 19, 62, 49, 13, 5) \
+T (158, 10, 15, 16, 60, 24, 52, 19, 0, 25, 41, 46, 11, 29, 5, 62, 22, 43, 36, 17, 7, 18, 34, 49, 45, 59, 9, 42, 51, 55, 44, 21, 3) \
+T (159, 30, 18, 51, 36, 21, 15, 6, 61, 13, 58, 44, 25, 57, 22, 11, 54, 33, 39, 43, 0, 26, 19, 29, 63, 8, 4, 41, 23, 31, 58, 5, 47) \
+T (160, 43, 57, 36, 22, 21, 46, 53, 50, 63, 10, 20, 52, 8, 34, 18, 4, 56, 38, 41, 48, 35, 5, 39, 23, 54, 30, 4, 13, 40, 45, 2, 12) \
+T (161, 24, 31, 61, 52, 55, 36, 32, 10, 33, 3, 58, 35, 62, 50, 51, 54, 63, 30, 28, 4, 26, 47, 14, 56, 23, 59, 39, 38, 16, 25, 17, 37) \
+T (162, 60, 17, 42, 30, 56, 12, 14, 47, 6, 20, 5, 19, 55, 54, 33, 39, 58, 30, 22, 32, 0, 7, 18, 4, 63, 48, 36, 10, 3, 21, 28, 35) \
+T (163, 11, 12, 21, 42, 0, 50, 48, 35, 20, 48, 38, 46, 52, 36, 43, 31, 28, 52, 48, 27, 1, 13, 60, 58, 39, 16, 32, 37, 57, 53, 24, 41) \
+T (164, 10, 17, 45, 30, 36, 24, 55, 59, 5, 50, 15, 56, 13, 38, 25, 29, 53, 20, 6, 1, 26, 51, 36, 32, 23, 35, 62, 3, 34, 10, 12, 52) \
+T (165, 15, 0, 34, 40, 12, 13, 28, 39, 39, 20, 48, 14, 22, 27, 51, 34, 11, 18, 16, 38, 62, 58, 6, 41, 44, 42, 36, 7, 33, 37, 37, 5) \
+T (166, 35, 44, 35, 56, 39, 57, 11, 35, 1, 0, 61, 31, 52, 32, 33, 24, 37, 49, 18, 29, 24, 12, 5, 43, 55, 25, 60, 40, 4, 30, 38, 3) \
+T (167, 25, 2, 53, 19, 62, 59, 49, 43, 15, 12, 15, 28, 22, 35, 40, 31, 47, 11, 16, 10, 41, 5, 7, 23, 48, 24, 60, 52, 30, 50, 55, 7) \
+T (168, 49, 27, 41, 40, 42, 20, 39, 50, 17, 58, 9, 54, 2, 38, 48, 16, 62, 43, 18, 59, 22, 63, 29, 61, 60, 6, 33, 24, 14, 57, 4, 28) \
+T (169, 13, 41, 9, 55, 51, 0, 46, 18, 42, 53, 37, 5, 7, 39, 15, 36, 30, 50, 11, 20, 52, 47, 1, 44, 63, 43, 6, 60, 2, 34, 31, 54) \
+T (170, 49, 35, 62, 17, 55, 14, 30, 11, 8, 29, 2, 54, 31, 44, 36, 46, 37, 21, 15, 28, 27, 23, 57, 53, 51, 37, 34, 19, 47, 16, 43, 59) \
+T (171, 50, 37, 40, 26, 46, 58, 54, 59, 17, 30, 23, 11, 43, 61, 31, 8, 60, 34, 25, 63, 4, 41, 39, 48, 51, 13, 49, 22, 52, 57, 29, 13) \
+T (172, 42, 47, 27, 36, 47, 41, 45, 24, 8, 20, 35, 22, 38, 50, 57, 52, 28, 46, 53, 54, 37, 2, 48, 33, 32, 5, 60, 17, 19, 34, 55, 43) \
+T (173, 19, 12, 42, 37, 36, 13, 0, 1, 62, 53, 54, 50, 44, 0, 24, 59, 2, 6, 10, 29, 3, 63, 34, 28, 13, 61, 46, 33, 7, 26, 27, 5) \
+T (174, 32, 5, 30, 54, 15, 26, 25, 28, 1, 51, 11, 39, 2, 30, 27, 13, 43, 6, 7, 25, 31, 8, 3, 16, 41, 29, 26, 5, 19, 58, 42, 59) \
+T (175, 48, 5, 7, 28, 40, 56, 49, 42, 47, 61, 24, 13, 44, 18, 38, 53, 30, 10, 21, 6, 29, 2, 33, 22, 14, 59, 42, 21, 45, 31, 27, 54) \
+T (176, 56, 39, 62, 32, 46, 48, 36, 27, 3, 53, 22, 42, 31, 9, 40, 0, 19, 58, 16, 26, 1, 10, 16, 21, 63, 54, 23, 2, 15, 6, 7, 47) \
+T (177, 31, 18, 57, 52, 5, 32, 56, 7, 11, 6, 9, 20, 30, 56, 46, 23, 42, 38, 3, 34, 19, 45, 21, 55, 0, 8, 53, 24, 29, 60, 25, 49) \
+T (178, 32, 2, 48, 34, 7, 57, 1, 58, 39, 16, 53, 33, 31, 12, 21, 6, 4, 62, 50, 46, 61, 23, 5, 40, 44, 9, 28, 11, 11, 37, 25, 13) \
+T (179, 47, 40, 12, 47, 26, 3, 33, 30, 46, 61, 33, 10, 19, 1, 20, 5, 37, 9, 28, 27, 25, 63, 15, 23, 43, 54, 11, 30, 6, 24, 57, 18) \
+T (180, 16, 27, 2, 62, 63, 52, 26, 21, 37, 18, 41, 45, 15, 9, 51, 46, 28, 38, 60, 30, 35, 20, 7, 52, 53, 24, 42, 56, 33, 22, 48, 31) \
+T (181, 0, 40, 54, 27, 2, 3, 21, 10, 32, 31, 55, 31, 34, 53, 36, 22, 59, 41, 1, 20, 13, 42, 46, 17, 52, 49, 28, 41, 37, 40, 4, 43) \
+T (182, 35, 7, 38, 12, 27, 41, 8, 17, 1, 23, 46, 3, 28, 24, 61, 60, 21, 19, 48, 33, 26, 29, 45, 51, 48, 56, 34, 22, 10, 62, 25, 39) \
+T (183, 61, 14, 56, 62, 44, 59, 54, 26, 61, 27, 52, 24, 3, 33, 12, 16, 48, 47, 28, 9, 21, 38, 23, 0, 55, 5, 22, 39, 9, 35, 59, 63) \
+T (184, 41, 27, 35, 53, 49, 26, 12, 14, 3, 39, 19, 2, 16, 46, 47, 52, 24, 59, 6, 51, 52, 34, 4, 50, 32, 13, 63, 20, 45, 10, 28, 40) \
+T (185, 14, 7, 4, 53, 23, 11, 9, 41, 26, 20, 46, 51, 3, 8, 18, 56, 31, 48, 38, 15, 12, 46, 42, 59, 40, 57, 16, 2, 21, 33, 37, 11) \
+T (186, 46, 10, 6, 33, 7, 2, 37, 4, 11, 32, 59, 60, 2, 4, 12, 47, 26, 39, 27, 52, 5, 58, 30, 24, 36, 55, 63, 28, 62, 25, 43, 25) \
+T (187, 6, 60, 15, 13, 18, 56, 39, 43, 61, 20, 63, 26, 37, 53, 23, 33, 44, 10, 14, 58, 35, 2, 17, 37, 41, 12, 1, 22, 10, 16, 5, 55) \
+T (188, 31, 62, 49, 57, 22, 42, 61, 6, 34, 35, 3, 13, 16, 56, 2, 28, 38, 49, 22, 49, 0, 29, 17, 57, 59, 27, 5, 22, 26, 24, 40, 30) \
+T (189, 3, 24, 42, 30, 19, 13, 9, 57, 6, 46, 36, 52, 16, 55, 60, 4, 2, 50, 32, 33, 58, 15, 22, 33, 21, 39, 20, 37, 27, 0, 1, 53) \
+T (190, 19, 62, 32, 12, 18, 61, 31, 60, 14, 6, 15, 17, 22, 39, 30, 56, 49, 48, 16, 63, 42, 43, 1, 11, 20, 59, 27, 25, 63, 29, 37, 2) \
+T (191, 0, 15, 16, 7, 56, 54, 8, 63, 39, 18, 32, 46, 12, 35, 17, 38, 41, 34, 36, 40, 51, 21, 61, 26, 43, 57, 53, 4, 45, 6, 57, 2) \
+T (192, 52, 12, 62, 8, 60, 56, 29, 5, 6, 7, 9, 21, 44, 47, 48, 53, 58, 54, 45, 40, 15, 17, 1, 28, 4, 55, 22, 57, 32, 19, 33, 10) \
+T (193, 14, 48, 58, 51, 60, 30, 42, 4, 3, 17, 44, 36, 34, 9, 8, 16, 46, 43, 32, 24, 47, 21, 2, 49, 59, 55, 10, 62, 11, 25, 29, 57) \
+T (194, 35, 0, 38, 57, 14, 16, 12, 7, 10, 40, 20, 44, 42, 40, 22, 47, 31, 5, 54, 8, 13, 26, 62, 28, 32, 37, 48, 34, 41, 39, 60, 4) \
+T (195, 30, 15, 1, 38, 55, 58, 7, 14, 13, 12, 11, 35, 17, 22, 39, 32, 50, 13, 5, 62, 51, 63, 46, 10, 8, 61, 9, 49, 59, 4, 0, 34) \
+T (196, 37, 31, 6, 15, 23, 0, 30, 35, 4, 54, 56, 63, 3, 20, 44, 27, 43, 25, 4, 41, 5, 1, 38, 51, 59, 26, 42, 48, 58, 50, 5, 2) \
+T (197, 3, 21, 28, 5, 22, 62, 16, 17, 56, 45, 46, 33, 41, 24, 25, 31, 10, 54, 19, 14, 0, 59, 42, 34, 12, 23, 53, 35, 55, 30, 18, 8) \
+T (198, 3, 56, 16, 31, 45, 6, 37, 26, 34, 41, 36, 52, 21, 48, 13, 27, 22, 51, 62, 60, 59, 0, 25, 62, 44, 9, 23, 42, 11, 33, 39, 57) \
+T (199, 59, 20, 31, 41, 24, 27, 26, 54, 7, 42, 30, 5, 25, 37, 53, 11, 21, 42, 39, 3, 2, 28, 47, 59, 32, 10, 57, 61, 52, 22, 19, 15) \
+T (200, 3, 57, 34, 47, 8, 31, 63, 39, 34, 19, 52, 42, 51, 28, 50, 44, 59, 27, 21, 24, 30, 61, 28, 20, 56, 20, 37, 32, 12, 22, 14, 4) \
+T (201, 1, 61, 23, 43, 21, 38, 13, 42, 45, 40, 24, 16, 59, 4, 46, 11, 43, 10, 30, 55, 20, 5, 49, 62, 22, 31, 54, 21, 53, 36, 17, 8) \
+T (202, 49, 56, 60, 30, 24, 23, 40, 15, 32, 61, 37, 13, 56, 5, 57, 0, 28, 39, 27, 59, 60, 42, 3, 6, 51, 36, 8, 53, 34, 22, 35, 10) \
+T (203, 27, 13, 16, 12, 30, 31, 15, 47, 23, 22, 37, 29, 40, 55, 6, 44, 11, 4, 49, 9, 50, 1, 25, 38, 59, 61, 2, 18, 28, 8, 17, 57) \
+T (204, 5, 62, 5, 37, 27, 2, 31, 25, 9, 40, 58, 34, 60, 17, 14, 0, 8, 47, 44, 43, 21, 54, 15, 20, 57, 35, 30, 61, 36, 7, 16, 32) \
+T (205, 55, 22, 9, 29, 54, 52, 0, 13, 39, 36, 63, 12, 43, 56, 58, 0, 10, 18, 48, 1, 20, 60, 4, 62, 2, 51, 41, 61, 1, 26, 24, 21) \
+T (206, 29, 14, 52, 20, 49, 59, 31, 55, 61, 15, 20, 11, 1, 16, 39, 43, 53, 13, 35, 7, 38, 28, 41, 10, 63, 56, 2, 23, 0, 57, 30, 26) \
+T (207, 31, 45, 56, 4, 19, 1, 32, 44, 20, 50, 8, 39, 58, 33, 59, 29, 62, 3, 55, 11, 28, 6, 32, 29, 43, 41, 7, 5, 18, 15, 21, 14) \
+T (208, 29, 1, 31, 17, 10, 58, 27, 5, 63, 27, 23, 49, 60, 4, 33, 3, 9, 51, 28, 37, 35, 61, 42, 19, 18, 39, 34, 15, 21, 14, 7, 36) \
+T (209, 47, 2, 8, 51, 56, 61, 12, 0, 37, 49, 24, 29, 44, 60, 30, 63, 33, 55, 5, 4, 27, 45, 50, 13, 59, 14, 39, 46, 40, 28, 19, 11) \
+T (210, 50, 2, 52, 36, 3, 59, 4, 24, 20, 41, 8, 49, 48, 5, 28, 37, 22, 18, 26, 16, 61, 38, 43, 33, 30, 16, 6, 42, 55, 54, 14, 32) \
+T (211, 56, 57, 33, 0, 47, 43, 50, 22, 15, 53, 1, 17, 60, 20, 63, 2, 27, 18, 51, 45, 23, 7, 31, 47, 4, 38, 34, 35, 49, 10, 9, 32) \
+T (212, 42, 54, 63, 4, 20, 3, 48, 34, 28, 10, 6, 60, 33, 29, 37, 14, 35, 13, 11, 57, 43, 44, 24, 39, 7, 56, 37, 22, 41, 31, 49, 32) \
+T (213, 40, 25, 61, 33, 60, 4, 1, 28, 29, 63, 47, 56, 9, 6, 22, 39, 7, 16, 38, 55, 18, 10, 34, 3, 24, 59, 9, 51, 44, 35, 14, 47) \
+T (214, 14, 11, 0, 4, 25, 6, 13, 60, 2, 26, 11, 27, 31, 30, 41, 58, 48, 24, 35, 44, 32, 49, 17, 8, 3, 1, 54, 16, 61, 15, 10, 18) \
+T (215, 7, 30, 38, 10, 26, 20, 54, 1, 28, 41, 0, 0, 5, 32, 56, 61, 48, 42, 14, 4, 34, 55, 39, 53, 46, 13, 62, 31, 53, 37, 24, 11) \
+T (216, 43, 36, 2, 21, 0, 28, 16, 53, 23, 7, 47, 30, 37, 28, 6, 35, 40, 60, 50, 32, 60, 9, 32, 46, 55, 49, 29, 13, 22, 14, 8, 62) \
+T (217, 15, 53, 9, 63, 0, 6, 29, 26, 35, 55, 38, 23, 50, 45, 2, 25, 16, 7, 53, 48, 47, 4, 18, 34, 28, 22, 43, 8, 60, 61, 21, 1) \
+T (218, 60, 32, 56, 46, 28, 61, 35, 57, 2, 11, 44, 34, 13, 23, 39, 50, 18, 5, 1, 40, 59, 3, 51, 49, 43, 14, 12, 27, 43, 31, 1, 25) \
+T (219, 4, 10, 19, 21, 46, 37, 30, 61, 45, 45, 40, 59, 39, 18, 42, 50, 2, 3, 23, 15, 32, 26, 52, 31, 35, 38, 48, 53, 20, 6, 12, 57) \
+T (220, 37, 43, 11, 32, 25, 41, 42, 54, 19, 27, 46, 12, 35, 16, 58, 48, 38, 21, 52, 56, 13, 22, 24, 1, 30, 24, 51, 50, 59, 20, 15, 31) \
+T (221, 31, 52, 23, 52, 42, 57, 3, 59, 56, 34, 35, 50, 25, 2, 45, 8, 11, 16, 62, 21, 25, 0, 15, 28, 18, 7, 24, 33, 1, 4, 20, 48) \
+T (222, 2, 37, 10, 34, 16, 28, 56, 57, 42, 11, 0, 27, 60, 25, 23, 61, 44, 36, 55, 53, 62, 41, 13, 27, 24, 20, 14, 39, 19, 8, 50, 56) \
+T (223, 47, 23, 30, 12, 48, 20, 63, 38, 60, 46, 43, 54, 1, 53, 6, 62, 2, 0, 37, 55, 39, 33, 19, 28, 26, 5, 41, 35, 44, 31, 9, 33) \
+T (224, 8, 3, 25, 48, 57, 1, 24, 23, 32, 22, 12, 10, 5, 43, 46, 39, 56, 19, 33, 27, 0, 56, 13, 2, 38, 51, 60, 35, 15, 59, 23, 28) \
+T (225, 15, 40, 34, 53, 58, 22, 7, 47, 54, 5, 33, 13, 60, 17, 52, 45, 24, 20, 36, 16, 61, 21, 46, 56, 23, 2, 42, 63, 43, 59, 57, 9) \
+T (226, 43, 21, 31, 3, 24, 2, 53, 41, 25, 12, 47, 19, 48, 28, 36, 45, 29, 23, 9, 50, 63, 20, 1, 61, 7, 6, 37, 26, 10, 55, 60, 58) \
+T (227, 59, 13, 48, 58, 52, 5, 16, 39, 7, 36, 37, 41, 47, 26, 40, 42, 25, 54, 6, 51, 63, 27, 12, 56, 28, 19, 49, 62, 38, 44, 61, 9)
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-4.inc b/gcc/testsuite/gcc.dg/torture/vshuf-4.inc
new file mode 100644
index 00000000000..94bdb777dfe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-4.inc
@@ -0,0 +1,135 @@
+#define N 4
+#define TESTS \
+T (0, 0, 1, 2, 3) \
+T (1, 0, 0, 0, 0) \
+T (2, 6, 3, 1, 5) \
+T (3, 1, 3, 5, 0) \
+T (4, 6, 3, 5, 4) \
+T (5, 6, 4, 1, 0) \
+T (6, 6, 1, 4, 2) \
+T (7, 3, 7, 4, 4) \
+T (8, 3, 2, 4, 4) \
+T (9, 3, 2, 6, 1) \
+T (10, 5, 4, 5, 6) \
+T (11, 1, 4, 0, 7) \
+T (12, 1, 5, 7, 2) \
+T (13, 2, 3, 0, 4) \
+T (14, 7, 6, 4, 2) \
+T (15, 6, 1, 3, 4) \
+T (16, 0, 2, 4, 6) \
+T (17, 1, 3, 5, 7) \
+T (18, 3, 3, 3, 3) \
+T (19, 3, 2, 1, 0)
+#define EXPTESTS \
+T (116, 1, 2, 4, 3) \
+T (117, 7, 3, 3, 0) \
+T (118, 5, 3, 2, 7) \
+T (119, 0, 3, 5, 6) \
+T (120, 0, 0, 1, 5) \
+T (121, 4, 6, 2, 1) \
+T (122, 2, 5, 6, 3) \
+T (123, 4, 6, 3, 2) \
+T (124, 4, 7, 5, 6) \
+T (125, 0, 4, 2, 4) \
+T (126, 2, 4, 6, 0) \
+T (127, 4, 3, 5, 1) \
+T (128, 5, 4, 7, 3) \
+T (129, 7, 5, 6, 4) \
+T (130, 2, 0, 5, 3) \
+T (131, 7, 4, 3, 0) \
+T (132, 6, 1, 3, 1) \
+T (133, 3, 4, 1, 7) \
+T (134, 0, 0, 6, 4) \
+T (135, 6, 4, 0, 1) \
+T (136, 6, 0, 2, 4) \
+T (137, 1, 3, 4, 2) \
+T (138, 3, 1, 2, 4) \
+T (139, 3, 1, 5, 0) \
+T (140, 1, 6, 0, 2) \
+T (141, 0, 2, 6, 4) \
+T (142, 1, 7, 5, 2) \
+T (143, 7, 0, 4, 1) \
+T (144, 7, 3, 5, 6) \
+T (145, 0, 7, 5, 4) \
+T (146, 6, 4, 2, 3) \
+T (147, 1, 5, 7, 6) \
+T (148, 5, 7, 4, 7) \
+T (149, 5, 2, 2, 0) \
+T (150, 7, 1, 6, 4) \
+T (151, 5, 2, 4, 6) \
+T (152, 5, 0, 4, 6) \
+T (153, 4, 2, 7, 3) \
+T (154, 7, 1, 0, 6) \
+T (155, 0, 4, 2, 5) \
+T (156, 3, 4, 3, 2) \
+T (157, 2, 0, 6, 1) \
+T (158, 5, 1, 7, 4) \
+T (159, 2, 1, 5, 6) \
+T (160, 1, 6, 5, 7) \
+T (161, 2, 4, 1, 6) \
+T (162, 3, 7, 1, 6) \
+T (163, 2, 1, 4, 7) \
+T (164, 4, 2, 1, 0) \
+T (165, 0, 7, 1, 3) \
+T (166, 7, 4, 2, 3) \
+T (167, 4, 5, 3, 5) \
+T (168, 1, 5, 6, 7) \
+T (169, 6, 3, 2, 0) \
+T (170, 6, 2, 1, 5) \
+T (171, 5, 6, 1, 3) \
+T (172, 2, 2, 3, 1) \
+T (173, 5, 4, 3, 5) \
+T (174, 7, 3, 4, 1) \
+T (175, 4, 2, 3, 6) \
+T (176, 7, 6, 5, 3) \
+T (177, 7, 2, 0, 6) \
+T (178, 1, 3, 0, 2) \
+T (179, 5, 3, 0, 5) \
+T (180, 4, 6, 7, 2) \
+T (181, 4, 5, 2, 0) \
+T (182, 5, 0, 1, 2) \
+T (183, 2, 3, 4, 1) \
+T (184, 2, 6, 5, 1) \
+T (185, 0, 6, 7, 4) \
+T (186, 4, 1, 6, 2) \
+T (187, 1, 3, 2, 3) \
+T (188, 2, 5, 4, 3) \
+T (189, 2, 5, 6, 4) \
+T (190, 4, 0, 5, 0) \
+T (191, 2, 1, 6, 0) \
+T (192, 7, 5, 0, 1) \
+T (193, 3, 5, 6, 7) \
+T (194, 0, 1, 2, 7) \
+T (195, 3, 1, 0, 2) \
+T (196, 2, 4, 6, 3) \
+T (197, 6, 0, 5, 4) \
+T (198, 6, 5, 7, 1) \
+T (199, 2, 5, 4, 6) \
+T (200, 7, 2, 3, 6) \
+T (201, 3, 5, 7, 3) \
+T (202, 1, 7, 4, 6) \
+T (203, 4, 0, 7, 1) \
+T (204, 7, 1, 0, 4) \
+T (205, 5, 1, 3, 4) \
+T (206, 0, 7, 3, 5) \
+T (207, 3, 2, 1, 5) \
+T (208, 7, 5, 0, 2) \
+T (209, 7, 0, 6, 3) \
+T (210, 6, 6, 7, 7) \
+T (211, 5, 6, 0, 4) \
+T (212, 5, 1, 2, 2) \
+T (213, 7, 1, 2, 6) \
+T (214, 5, 4, 2, 6) \
+T (215, 1, 5, 6, 4) \
+T (216, 7, 0, 2, 1) \
+T (217, 1, 5, 3, 6) \
+T (218, 3, 3, 6, 5) \
+T (219, 2, 3, 5, 7) \
+T (220, 2, 4, 3, 0) \
+T (221, 1, 5, 6, 3) \
+T (222, 7, 5, 1, 5) \
+T (223, 0, 5, 3, 4) \
+T (224, 2, 3, 1, 4) \
+T (225, 2, 3, 5, 1) \
+T (226, 4, 3, 1, 0) \
+T (227, 2, 3, 5, 5)
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-8.inc b/gcc/testsuite/gcc.dg/torture/vshuf-8.inc
new file mode 100644
index 00000000000..66586fabe73
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-8.inc
@@ -0,0 +1,135 @@
+#define N 8
+#define TESTS \
+T (0, 0, 1, 2, 3, 4, 5, 6, 7) \
+T (1, 0, 0, 0, 0, 0, 0, 0, 0) \
+T (2, 0, 1, 2, 3, 0, 1, 2, 3) \
+T (3, 0, 10, 3, 8, 1, 11, 10, 2) \
+T (4, 0, 1, 2, 3, 3, 0, 2, 1) \
+T (5, 12, 5, 14, 9, 8, 15, 1, 7) \
+T (6, 9, 10, 11, 8, 4, 15, 14, 12) \
+T (7, 4, 10, 14, 9, 11, 1, 12, 11) \
+T (8, 15, 3, 3, 8, 5, 11, 2, 10) \
+T (9, 13, 11, 10, 15, 8, 5, 14, 8) \
+T (10, 9, 13, 12, 14, 10, 1, 5, 14) \
+T (11, 5, 11, 12, 6, 3, 2, 4, 15) \
+T (12, 5, 13, 14, 8, 4, 10, 4, 12) \
+T (13, 14, 8, 12, 3, 13, 9, 5, 4) \
+T (14, 15, 3, 13, 6, 14, 12, 10, 0) \
+T (15, 0, 5, 11, 7, 4, 6, 14, 1) \
+T (16, 0, 2, 4, 6, 8, 10, 12, 14) \
+T (17, 1, 3, 5, 7, 9, 11, 13, 15) \
+T (18, 3, 3, 3, 3, 3, 3, 3, 3) \
+T (19, 7, 6, 5, 4, 3, 2, 1, 0)
+#define EXPTESTS \
+T (116, 9, 3, 9, 4, 7, 0, 0, 6) \
+T (117, 4, 14, 12, 8, 9, 6, 0, 10) \
+T (118, 10, 12, 1, 3, 4, 11, 9, 2) \
+T (119, 4, 11, 9, 5, 8, 14, 0, 2) \
+T (120, 0, 10, 8, 6, 4, 9, 7, 5) \
+T (121, 10, 15, 0, 4, 12, 9, 7, 3) \
+T (122, 13, 6, 0, 7, 5, 12, 12, 2) \
+T (123, 4, 10, 11, 15, 12, 7, 3, 8) \
+T (124, 1, 13, 15, 9, 6, 5, 7, 4) \
+T (125, 7, 13, 2, 5, 2, 8, 1, 6) \
+T (126, 4, 5, 2, 12, 14, 13, 8, 6) \
+T (127, 4, 10, 2, 7, 11, 15, 9, 0) \
+T (128, 14, 8, 12, 10, 13, 3, 11, 2) \
+T (129, 10, 8, 14, 9, 5, 1, 15, 7) \
+T (130, 12, 2, 9, 13, 5, 14, 1, 15) \
+T (131, 10, 4, 1, 14, 11, 15, 9, 2) \
+T (132, 9, 12, 7, 4, 2, 1, 0, 9) \
+T (133, 11, 15, 4, 10, 3, 12, 13, 5) \
+T (134, 1, 5, 6, 13, 14, 15, 3, 10) \
+T (135, 0, 14, 6, 10, 1, 13, 3, 2) \
+T (136, 2, 11, 1, 5, 12, 13, 3, 5) \
+T (137, 7, 11, 4, 1, 12, 10, 14, 10) \
+T (138, 3, 6, 7, 13, 11, 15, 10, 0) \
+T (139, 10, 8, 7, 14, 1, 11, 0, 13) \
+T (140, 5, 3, 13, 11, 8, 5, 12, 6) \
+T (141, 15, 2, 12, 13, 10, 8, 5, 0) \
+T (142, 13, 9, 10, 2, 11, 3, 4, 1) \
+T (143, 2, 14, 6, 5, 1, 8, 15, 0) \
+T (144, 12, 9, 14, 10, 1, 3, 11, 13) \
+T (145, 12, 13, 11, 2, 5, 6, 4, 8) \
+T (146, 5, 0, 2, 1, 6, 8, 15, 13) \
+T (147, 8, 7, 1, 3, 5, 11, 14, 15) \
+T (148, 0, 9, 2, 15, 3, 1, 8, 10) \
+T (149, 4, 14, 11, 6, 8, 5, 12, 7) \
+T (150, 5, 9, 10, 12, 14, 15, 2, 7) \
+T (151, 11, 6, 5, 7, 11, 14, 2, 1) \
+T (152, 13, 1, 7, 4, 6, 8, 15, 9) \
+T (153, 10, 12, 9, 1, 6, 7, 8, 15) \
+T (154, 8, 4, 5, 1, 3, 0, 7, 13) \
+T (155, 13, 9, 3, 4, 10, 1, 15, 7) \
+T (156, 13, 8, 2, 7, 0, 6, 3, 6) \
+T (157, 15, 15, 13, 6, 0, 5, 14, 4) \
+T (158, 13, 1, 2, 2, 7, 9, 2, 6) \
+T (159, 5, 12, 10, 13, 6, 1, 4, 7) \
+T (160, 0, 2, 9, 1, 5, 11, 14, 11) \
+T (161, 14, 6, 5, 10, 3, 2, 15, 4) \
+T (162, 3, 10, 0, 1, 13, 14, 11, 15) \
+T (163, 13, 7, 5, 9, 5, 0, 11, 4) \
+T (164, 2, 11, 1, 12, 3, 13, 4, 9) \
+T (165, 1, 0, 10, 11, 5, 13, 4, 3) \
+T (166, 3, 9, 1, 12, 15, 14, 10, 5) \
+T (167, 3, 10, 11, 14, 5, 1, 8, 12) \
+T (168, 10, 15, 5, 14, 4, 13, 6, 3) \
+T (169, 1, 8, 6, 4, 11, 13, 7, 10) \
+T (170, 8, 7, 1, 15, 11, 9, 0, 3) \
+T (171, 4, 0, 11, 7, 1, 15, 3, 13) \
+T (172, 14, 7, 3, 4, 9, 11, 0, 6) \
+T (173, 7, 3, 11, 4, 8, 2, 10, 15) \
+T (174, 7, 9, 14, 2, 0, 5, 13, 3) \
+T (175, 4, 8, 5, 9, 3, 11, 1, 14) \
+T (176, 13, 12, 3, 3, 1, 4, 8, 5) \
+T (177, 7, 12, 9, 13, 10, 4, 5, 8) \
+T (178, 14, 3, 12, 7, 2, 6, 5, 5) \
+T (179, 7, 0, 8, 6, 2, 14, 12, 15) \
+T (180, 2, 12, 0, 4, 1, 15, 11, 10) \
+T (181, 0, 7, 5, 12, 15, 10, 14, 3) \
+T (182, 3, 10, 2, 5, 11, 6, 13, 14) \
+T (183, 3, 2, 7, 11, 0, 13, 8, 10) \
+T (184, 0, 12, 15, 1, 9, 2, 11, 4) \
+T (185, 11, 15, 8, 10, 9, 1, 13, 3) \
+T (186, 12, 13, 15, 12, 3, 9, 5, 7) \
+T (187, 4, 10, 5, 6, 1, 11, 0, 11) \
+T (188, 11, 6, 7, 9, 0, 8, 14, 8) \
+T (189, 1, 15, 6, 9, 12, 6, 7, 14) \
+T (190, 1, 5, 6, 11, 12, 13, 3, 0) \
+T (191, 0, 8, 15, 13, 12, 6, 1, 4) \
+T (192, 12, 15, 8, 4, 2, 0, 9, 5) \
+T (193, 14, 5, 13, 10, 12, 11, 0, 1) \
+T (194, 12, 1, 9, 8, 10, 9, 0, 2) \
+T (195, 11, 0, 13, 4, 6, 2, 14, 15) \
+T (196, 0, 10, 6, 2, 12, 4, 9, 13) \
+T (197, 7, 12, 8, 10, 1, 0, 5, 0) \
+T (198, 12, 13, 0, 5, 3, 14, 11, 4) \
+T (199, 9, 1, 4, 14, 10, 12, 15, 6) \
+T (200, 3, 12, 13, 6, 14, 2, 1, 6) \
+T (201, 5, 14, 8, 10, 1, 12, 2, 0) \
+T (202, 5, 8, 2, 7, 4, 15, 14, 2) \
+T (203, 14, 13, 10, 9, 11, 15, 7, 8) \
+T (204, 12, 13, 14, 2, 4, 9, 5, 7) \
+T (205, 0, 7, 5, 4, 7, 13, 6, 8) \
+T (206, 7, 0, 15, 6, 12, 2, 5, 4) \
+T (207, 8, 6, 0, 1, 1, 11, 1, 9) \
+T (208, 11, 6, 14, 9, 5, 3, 7, 13) \
+T (209, 12, 3, 15, 9, 1, 0, 8, 13) \
+T (210, 11, 1, 9, 8, 7, 6, 12, 2) \
+T (211, 10, 9, 2, 6, 8, 11, 0, 4) \
+T (212, 10, 13, 15, 9, 6, 15, 14, 10) \
+T (213, 9, 5, 8, 3, 4, 7, 11, 4) \
+T (214, 1, 2, 13, 5, 8, 4, 3, 6) \
+T (215, 8, 3, 2, 4, 9, 14, 12, 13) \
+T (216, 5, 7, 8, 15, 3, 1, 10, 4) \
+T (217, 2, 9, 3, 2, 14, 11, 5, 7) \
+T (218, 15, 6, 4, 10, 14, 3, 13, 2) \
+T (219, 0, 8, 14, 5, 15, 7, 10, 1) \
+T (220, 14, 0, 6, 10, 8, 2, 7, 4) \
+T (221, 15, 13, 3, 14, 11, 2, 14, 6) \
+T (222, 8, 2, 10, 13, 1, 0, 4, 11) \
+T (223, 7, 15, 2, 9, 1, 12, 11, 3) \
+T (224, 13, 15, 3, 12, 15, 7, 0, 8) \
+T (225, 0, 2, 1, 11, 14, 3, 9, 14) \
+T (226, 12, 14, 3, 15, 8, 5, 1, 7) \
+T (227, 0, 5, 13, 8, 4, 2, 1, 3)
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-main.inc b/gcc/testsuite/gcc.dg/torture/vshuf-main.inc
new file mode 100644
index 00000000000..52b75ee7365
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-main.inc
@@ -0,0 +1,55 @@
+/* Driver fragment for __builtin_shuffle of any vector shape. */
+
+extern void abort (void);
+
+#ifndef UNSUPPORTED
+V a, b, c, d;
+
+#define T(num, msk...) \
+__attribute__((noinline, noclone)) void \
+test_##num (void) \
+{ \
+ VI mask = { msk }; \
+ int i; \
+ c = __builtin_shuffle (a, mask); \
+ d = __builtin_shuffle (a, b, mask); \
+ __asm ("" : : "r" (&c), "r" (&d) : "memory"); \
+ for (i = 0; i < N; ++i) \
+ if (c[i] != a[mask[i] & (N - 1)]) \
+ abort (); \
+ else if ((mask[i] & N)) \
+ { \
+ if (d[i] != b[mask[i] & (N - 1)]) \
+ abort (); \
+ } \
+ else if (d[i] != a[mask[i] & (N - 1)]) \
+ abort (); \
+}
+TESTS
+#ifdef EXPENSIVE
+EXPTESTS
+#endif
+#endif
+
+int
+main ()
+{
+#ifndef UNSUPPORTED
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ a[i] = i + 2;
+ b[i] = N + i + 2;
+ }
+
+#undef T
+#define T(num, msk...) \
+ test_##num ();
+ TESTS
+#ifdef EXPENSIVE
+ EXPTESTS
+#endif
+#endif
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v16hi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v16hi.c
new file mode 100644
index 00000000000..9ff3ebbfa3d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v16hi.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned short V __attribute__((vector_size(32)));
+typedef V VI;
+
+#include "vshuf-16.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v16qi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v16qi.c
new file mode 100644
index 00000000000..062324d7bb9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v16qi.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned char V __attribute__((vector_size(16)));
+typedef V VI;
+
+#include "vshuf-16.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v2df.c b/gcc/testsuite/gcc.dg/torture/vshuf-v2df.c
new file mode 100644
index 00000000000..8e33d1d0411
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v2df.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_DOUBLE__ == 8 && __SIZEOF_LONG_LONG__ == 8
+typedef double V __attribute__((vector_size(16)));
+typedef unsigned long long VI __attribute__((vector_size(16)));
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v2di.c b/gcc/testsuite/gcc.dg/torture/vshuf-v2di.c
new file mode 100644
index 00000000000..d498c28f0f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v2di.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_LONG_LONG__ == 8
+typedef unsigned long long V __attribute__((vector_size(16)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v2sf.c b/gcc/testsuite/gcc.dg/torture/vshuf-v2sf.c
new file mode 100644
index 00000000000..22bcaa98d57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v2sf.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_FLOAT__ == 4
+typedef float V __attribute__((vector_size(8)));
+# if __SIZEOF_INT__ == 4
+typedef unsigned int VI __attribute__((vector_size(8)));
+# elif __SIZEOF_LONG__ == 4
+typedef unsigned long VI __attribute__((vector_size(8)));
+# else
+# define UNSUPPORTED
+# endif
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v2si.c b/gcc/testsuite/gcc.dg/torture/vshuf-v2si.c
new file mode 100644
index 00000000000..2138c6ca6f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v2si.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(8)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(8)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-2.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v32qi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v32qi.c
new file mode 100644
index 00000000000..0179006870c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v32qi.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned char V __attribute__((vector_size(32)));
+typedef V VI;
+
+#include "vshuf-32.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4df.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4df.c
new file mode 100644
index 00000000000..c11d6396dfd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4df.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_DOUBLE__ == 8 && __SIZEOF_LONG_LONG__ == 8
+typedef double V __attribute__((vector_size(32)));
+typedef unsigned long long VI __attribute__((vector_size(32)));
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4di.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4di.c
new file mode 100644
index 00000000000..494cb78260e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4di.c
@@ -0,0 +1,15 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_LONG_LONG__ == 8
+typedef unsigned long long V __attribute__((vector_size(32)));
+typedef V VI;
+#else
+#define UNSUPPORTED
+#endif
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4hi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4hi.c
new file mode 100644
index 00000000000..cfd56a613ef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4hi.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned short V __attribute__((vector_size(8)));
+typedef V VI;
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4sf.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4sf.c
new file mode 100644
index 00000000000..4db59f9da14
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4sf.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_FLOAT__ == 4
+typedef float V __attribute__((vector_size(16)));
+# if __SIZEOF_INT__ == 4
+typedef unsigned int VI __attribute__((vector_size(16)));
+# elif __SIZEOF_LONG__ == 4
+typedef unsigned long VI __attribute__((vector_size(16)));
+# else
+# define UNSUPPORTED
+# endif
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v4si.c b/gcc/testsuite/gcc.dg/torture/vshuf-v4si.c
new file mode 100644
index 00000000000..3ae86acd3c6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v4si.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(16)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(16)));
+typedef V VI;
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-4.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v8hi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v8hi.c
new file mode 100644
index 00000000000..f4639880fb6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v8hi.c
@@ -0,0 +1,11 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned short V __attribute__((vector_size(16)));
+typedef V VI;
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v8qi.c b/gcc/testsuite/gcc.dg/torture/vshuf-v8qi.c
new file mode 100644
index 00000000000..4bc96bedc46
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v8qi.c
@@ -0,0 +1,10 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+typedef unsigned char V __attribute__((vector_size(8)));
+typedef V VI;
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v8sf.c b/gcc/testsuite/gcc.dg/torture/vshuf-v8sf.c
new file mode 100644
index 00000000000..d11aa0c950a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v8sf.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_FLOAT__ == 4
+typedef float V __attribute__((vector_size(32)));
+# if __SIZEOF_INT__ == 4
+typedef unsigned int VI __attribute__((vector_size(32)));
+# elif __SIZEOF_LONG__ == 4
+typedef unsigned long VI __attribute__((vector_size(32)));
+# else
+# define UNSUPPORTED
+# endif
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/torture/vshuf-v8si.c b/gcc/testsuite/gcc.dg/torture/vshuf-v8si.c
new file mode 100644
index 00000000000..64d97164d65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/vshuf-v8si.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-DEXPENSIVE" { target run_expensive_tests } } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __SIZEOF_INT__ == 4
+typedef unsigned int V __attribute__((vector_size(32)));
+typedef V VI;
+#elif __SIZEOF_LONG__ == 4
+typedef unsigned long V __attribute__((vector_size(32)));
+typedef V VI;
+#else
+# define UNSUPPORTED
+#endif
+
+#include "vshuf-8.inc"
+#include "vshuf-main.inc"
diff --git a/gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c b/gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c
index 5f532638445..6c64d0795a3 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/val-prof-7.c
@@ -1,7 +1,7 @@
/* { dg-options "-O2 -fdump-ipa-profile -mtune=core2" } */
/* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } { "*" } { "" } } */
-#include <strings.h>
+extern void bzero (void *, __SIZE_TYPE__);
int foo(int len)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c
index 42d4b0dd874..4c3888fd237 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 && j, 0))
+ if (__builtin_expect ((i * i2) > 0 && (j * j2), 0))
g ();
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c
index ff175b975a9..d8f344f7826 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 || j, 0))
+ if (__builtin_expect ((i * i2) > 0 || (j * j2), 0))
;
else
g ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c
index 8fcc4e2bd40..b9e6cfb8ff9 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 && j, 0))
+ if (__builtin_expect ((i * i2) > 0 && (j * j2), 0))
a ();
else
b ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c
index 1fecf1b980c..2d2b206683b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-gimple" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 || j, 0))
+ if (__builtin_expect ((i * i2) > 0 || (j * j2), 0))
a ();
else
b ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c
index ed53b287b2a..d0b251db17b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c
@@ -1,9 +1,9 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-forwprop" } */
-f (int i, float j)
+f (int i, float j, int i2, float j2)
{
- if (__builtin_expect (i > 0 && __builtin_expect (j != 0, 1), 0))
+ if (__builtin_expect ((i * i2) > 0 && __builtin_expect ((j * j2) != 0, 1), 0))
a ();
else
b ();
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c
index 42257cca5ad..235bd7e4a8c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-31.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-fre1-details" } */
+/* { dg-options "-O -fdump-tree-fre1-details -fno-common" { target hppa*-*-hpux* } } */
typedef double d128 __attribute__((vector_size(16)));
typedef float f128 __attribute__((vector_size(16)));
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c
index daba77d9822..7f19e652929 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-fre1-details" } */
+/* { dg-options "-O -fdump-tree-fre1-details -fno-common" { target hppa*-*-hpux* } } */
#define vector __attribute__((vector_size(16) ))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c
index b0b54a22865..e92be29351b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-fre1-details" } */
+/* { dg-options "-O -fdump-tree-fre1-details -fno-common" { target hppa*-*-hpux* } } */
#define vector __attribute__((vector_size(16) ))
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-29.c b/gcc/testsuite/gcc.dg/vect/bb-slp-29.c
new file mode 100644
index 00000000000..e37b96d14d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-29.c
@@ -0,0 +1,59 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define A 3
+#define B 4
+#define N 256
+
+short src[N], dst[N];
+
+void foo (short * __restrict__ dst, short * __restrict__ src, int h, int stride, int dummy)
+{
+ int i;
+ h /= 16;
+ for (i = 0; i < h; i++)
+ {
+ dst[0] = A*src[0] + B*src[1];
+ dst[1] = A*src[1] + B*src[2];
+ dst[2] = A*src[2] + B*src[3];
+ dst[3] = A*src[3] + B*src[4];
+ dst[4] = A*src[4] + B*src[5];
+ dst[5] = A*src[5] + B*src[6];
+ dst[6] = A*src[6] + B*src[7];
+ dst[7] = A*src[7] + B*src[8];
+ dst += stride;
+ src += stride;
+ if (dummy == 32)
+ abort ();
+ }
+}
+
+
+int main (void)
+{
+ int i;
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ dst[i] = 0;
+ src[i] = i;
+ }
+
+ foo (dst, src, N, 8, 0);
+
+ for (i = 0; i < N/2; i++)
+ {
+ if (dst[i] != A * src[i] + B * src[i+1])
+ abort ();
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target { vect_int_mult && vect_element_align } } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-6-global.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-6-global.c
index a87367b3b08..9447524e817 100644
--- a/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-6-global.c
+++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-6-global.c
@@ -52,7 +52,5 @@ int main (void)
return 0;
}
-/* "Too many BBs in loop" */
-/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_widen_mult_pattern: detected" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { xfail vect_no_align } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c b/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c
new file mode 100644
index 00000000000..90dcd844334
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/no-tree-sra-bb-slp-pr50730.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+
+typedef __complex__ float Value;
+typedef struct {
+ Value a[16 / sizeof (Value)];
+} A;
+
+A sum(A a,A b)
+{
+ a.a[0]+=b.a[0];
+ a.a[1]+=b.a[1];
+ return a;
+}
+
+/* { dg-final { scan-tree-dump-times "not vectorized: more than one data ref in stmt" 0 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr50727.c b/gcc/testsuite/gcc.dg/vect/pr50727.c
new file mode 100644
index 00000000000..896b614b9b8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr50727.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+typedef unsigned char uint8_t;
+typedef unsigned long uint32_t;
+void
+f0a (uint32_t * __restrict__ result, uint32_t * arg2,
+ uint8_t * __restrict__ arg4)
+{
+ int idx;
+ for (idx = 0; idx < 429; idx += 1)
+ {
+ uint32_t temp_9;
+ uint32_t temp_11;
+ temp_9 = ((-19 | arg4[idx]) >> arg2[idx]);
+ temp_11 = (((-19 ^ arg4[idx]) & arg2[idx]) ^ temp_9);
+ result[idx] = temp_11;
+ }
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/slp-multitypes-2.c b/gcc/testsuite/gcc.dg/vect/slp-multitypes-2.c
index 3c04b6d21c5..ab2ed69d4cd 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-multitypes-2.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-multitypes-2.c
@@ -1,5 +1,4 @@
/* { dg-require-effective-target vect_int } */
-/* { dg-xfail-run-if "PR rtl-optimization/46603" { sparc*-*-* && { ilp32 && gas } } } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/vec-scal-opt.c b/gcc/testsuite/gcc.dg/vect/vec-scal-opt.c
index 6514f057a3a..f53e66d4cee 100644
--- a/gcc/testsuite/gcc.dg/vect/vec-scal-opt.c
+++ b/gcc/testsuite/gcc.dg/vect/vec-scal-opt.c
@@ -19,5 +19,5 @@ int main (int argc, char *argv[]) {
return vidx(short, r1, 0);
}
-/* { dg-final { scan-tree-dump-times ">> k.\[0-9_\]*" 1 "veclower2" { target vect_shift_scalar } } } */
+/* { dg-final { scan-tree-dump-times ">> k.\[0-9_\]*" 1 "veclower2" } } */
/* { dg-final { cleanup-tree-dump "veclower2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c b/gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c
index acab40764cc..4025f6717ae 100644
--- a/gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c
+++ b/gcc/testsuite/gcc.dg/vect/vec-scal-opt1.c
@@ -17,5 +17,5 @@ int main (int argc, char *argv[]) {
return vidx(short, r1, 0);
}
-/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower2" { target vect_shift_scalar } } } */
+/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower2" } } */
/* { dg-final { cleanup-tree-dump "veclower2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c b/gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c
index cfaf5e0f1e6..677836da90d 100644
--- a/gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c
+++ b/gcc/testsuite/gcc.dg/vect/vec-scal-opt2.c
@@ -16,5 +16,5 @@ int main (int argc, char *argv[]) {
return vidx(short, r1, 0);
}
-/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower2" { target vect_shift_scalar } } } */
+/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower2" } } */
/* { dg-final { cleanup-tree-dump "veclower2" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-114.c b/gcc/testsuite/gcc.dg/vect/vect-114.c
index 4bc78627815..3d43a7cd4b6 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-114.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-114.c
@@ -34,7 +34,7 @@ int main (void)
return main1 ();
}
-/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_perm && vect_hw_misalign } } } } } */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_perm && vect_hw_misalign } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { target { ! { vect_perm } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_perm } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-120.c b/gcc/testsuite/gcc.dg/vect/vect-120.c
index b9a2f5004ee..1b3c5d49cdc 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-120.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-120.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_float } */
/* { dg-require-effective-target vect_shift } */
+/* { dg-require-effective-target vect_floatint_cvt } */
static inline float
i2f(int x)
diff --git a/gcc/testsuite/gcc.dg/vect/vect-21.c b/gcc/testsuite/gcc.dg/vect/vect-21.c
index 7a57506a208..28fc72ae737 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-21.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-21.c
@@ -123,7 +123,7 @@ int main (void)
return main1 ();
}
-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { target vect_condition } } } */
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bool-1.c b/gcc/testsuite/gcc.dg/vect/vect-bool-1.c
new file mode 100644
index 00000000000..fd12f5c77a3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-bool-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+_Bool a[1024];
+_Bool b[1024];
+_Bool c[1024];
+void foo (void)
+{
+ unsigned i;
+ for (i = 0; i < 1024; ++i)
+ a[i] = b[i] | c[i];
+}
+
+/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-10.c b/gcc/testsuite/gcc.dg/vect/vect-cond-10.c
new file mode 100644
index 00000000000..687d42f0591
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cond-10.c
@@ -0,0 +1,165 @@
+/* { dg-require-effective-target vect_cond_mixed } */
+
+#include "tree-vect.h"
+
+#define N 1024
+float a[N], b[N], c[N], d[N];
+_Bool k[N];
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ k[i] = x & y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = (a[i] < b[i]) & (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ k[i] = x | y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = (a[i] < b[i]) | (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f5 (_Bool *p)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ p[i] = x & y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f6 (_Bool *p)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ p[i] = (a[i] < b[i]) & (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f7 (_Bool *p)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ p[i] = x | y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f8 (_Bool *p)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ p[i] = (a[i] < b[i]) | (c[i] < d[i]);
+}
+
+int
+main ()
+{
+ int i;
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ switch (i % 9)
+ {
+ case 0: asm (""); a[i] = - i - 1; b[i] = i + 1; break;
+ case 1: a[i] = 0; b[i] = 0; break;
+ case 2: a[i] = i + 1; b[i] = - i - 1; break;
+ case 3: a[i] = i; b[i] = i + 7; break;
+ case 4: a[i] = i; b[i] = i; break;
+ case 5: a[i] = i + 16; b[i] = i + 3; break;
+ case 6: a[i] = - i - 5; b[i] = - i; break;
+ case 7: a[i] = - i; b[i] = - i; break;
+ case 8: a[i] = - i; b[i] = - i - 7; break;
+ }
+ }
+ for (i = 0; i < N; i++)
+ {
+ switch ((i / 9) % 3)
+ {
+ case 0: c[i] = a[i / 9]; d[i] = b[i / 9]; break;
+ case 1: c[i] = a[i / 9 + 3]; d[i] = b[i / 9 + 3]; break;
+ case 2: c[i] = a[i / 9 + 6]; d[i] = b[i / 9 + 6]; break;
+ }
+ }
+ f1 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, 0, sizeof (k));
+ f2 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, 0, sizeof (k));
+ f3 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, 0, sizeof (k));
+ f4 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, 0, sizeof (k));
+ f5 (k);
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, 0, sizeof (k));
+ f6 (k);
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, 0, sizeof (k));
+ f7 (k);
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, 0, sizeof (k));
+ f8 (k);
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, 0, sizeof (k));
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops" 8 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-9.c b/gcc/testsuite/gcc.dg/vect/vect-cond-9.c
new file mode 100644
index 00000000000..cfa0363b2fe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-cond-9.c
@@ -0,0 +1,200 @@
+/* { dg-require-effective-target vect_cond_mixed } */
+
+#include "tree-vect.h"
+
+#define N 1024
+float a[N], b[N], c[N], d[N];
+int j[N];
+unsigned char k[N];
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ unsigned int x = a[i] < b[i] ? -1 : 0;
+ unsigned int y = c[i] < d[i] ? -1 : 0;
+ j[i] = (x & y) >> 31;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ j[i] = x & y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ j[i] = (a[i] < b[i]) & (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ k[i] = x & y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = (a[i] < b[i]) & (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f6 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ unsigned int x = a[i] < b[i] ? -1 : 0;
+ unsigned int y = c[i] < d[i] ? -1 : 0;
+ j[i] = (x | y) >> 31;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f7 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ j[i] = x | y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f8 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ j[i] = (a[i] < b[i]) | (c[i] < d[i]);
+}
+
+__attribute__((noinline, noclone)) void
+f9 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ int x = a[i] < b[i];
+ int y = c[i] < d[i];
+ k[i] = x | y;
+ }
+}
+
+__attribute__((noinline, noclone)) void
+f10 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ k[i] = (a[i] < b[i]) | (c[i] < d[i]);
+}
+
+int
+main ()
+{
+ int i;
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ switch (i % 9)
+ {
+ case 0: asm (""); a[i] = - i - 1; b[i] = i + 1; break;
+ case 1: a[i] = 0; b[i] = 0; break;
+ case 2: a[i] = i + 1; b[i] = - i - 1; break;
+ case 3: a[i] = i; b[i] = i + 7; break;
+ case 4: a[i] = i; b[i] = i; break;
+ case 5: a[i] = i + 16; b[i] = i + 3; break;
+ case 6: a[i] = - i - 5; b[i] = - i; break;
+ case 7: a[i] = - i; b[i] = - i; break;
+ case 8: a[i] = - i; b[i] = - i - 7; break;
+ }
+ }
+ for (i = 0; i < N; i++)
+ {
+ switch ((i / 9) % 3)
+ {
+ case 0: c[i] = a[i / 9]; d[i] = b[i / 9]; break;
+ case 1: c[i] = a[i / 9 + 3]; d[i] = b[i / 9 + 3]; break;
+ case 2: c[i] = a[i / 9 + 6]; d[i] = b[i / 9 + 6]; break;
+ }
+ }
+ f1 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f2 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f3 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f4 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, -6, sizeof (k));
+ f5 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 && ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, -6, sizeof (k));
+ f6 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f7 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f8 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (j, -6, sizeof (j));
+ f9 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, -6, sizeof (k));
+ f10 ();
+ for (i = 0; i < N; i++)
+ if (k[i] != ((i % 3) == 0 || ((i / 9) % 3) == 0))
+ abort ();
+ __builtin_memset (k, -6, sizeof (k));
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops" 10 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c
new file mode 100644
index 00000000000..efee6043707
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s16.c
@@ -0,0 +1,107 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define C 16
+
+__attribute__ ((noinline)) void
+foo (short *src, int *dst)
+{
+ int i;
+ short b, b0, b1, b2, b3, *s = src;
+ int *d = dst;
+
+ for (i = 0; i < N/4; i++)
+ {
+ b0 = *s++;
+ b1 = *s++;
+ b2 = *s++;
+ b3 = *s++;
+ *d = b0 << C;
+ d++;
+ *d = b1 << C;
+ d++;
+ *d = b2 << C;
+ d++;
+ *d = b3 << C;
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N/4; i++)
+ {
+ b0 = *s++;
+ b1 = *s++;
+ b2 = *s++;
+ b3 = *s++;
+ *d = b0 << C;
+ d++;
+ *d = b1 << C;
+ d++;
+ *d = b2 << C;
+ d++;
+ *d = b3 << 6;
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N/4; i++)
+ {
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ b = *s++;
+ if (*d != b << 6)
+ abort ();
+ d++;
+ }
+}
+
+int main (void)
+{
+ int i;
+ short in[N];
+ int out[N];
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ in[i] = i;
+ out[i] = 255;
+ __asm__ volatile ("");
+ }
+
+ foo (in, out);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 8 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c
new file mode 100644
index 00000000000..e829a799568
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-s8.c
@@ -0,0 +1,58 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define C 12
+
+__attribute__ ((noinline)) void
+foo (char *src, int *dst)
+{
+ int i;
+ char b, *s = src;
+ int *d = dst;
+
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ *d = b << C;
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ }
+}
+
+int main (void)
+{
+ int i;
+ char in[N];
+ int out[N];
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ in[i] = i;
+ out[i] = 255;
+ __asm__ volatile ("");
+ }
+
+ foo (in, out);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c
new file mode 100644
index 00000000000..75834d481cb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u16.c
@@ -0,0 +1,58 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define C 7
+
+__attribute__ ((noinline)) void
+foo (unsigned short *src, unsigned int *dst)
+{
+ int i;
+ unsigned short b, *s = src;
+ unsigned int *d = dst;
+
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ *d = b << C;
+ d++;
+ }
+
+ s = src;
+ d = dst;
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ if (*d != b << C)
+ abort ();
+ d++;
+ }
+}
+
+int main (void)
+{
+ int i;
+ unsigned short in[N];
+ unsigned int out[N];
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ in[i] = i;
+ out[i] = 255;
+ __asm__ volatile ("");
+ }
+
+ foo (in, out);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c
new file mode 100644
index 00000000000..b87a277c2f7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-widen-shift-u8.c
@@ -0,0 +1,65 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_shift } */
+
+#include <stdarg.h>
+#include "tree-vect.h"
+
+#define N 64
+#define C1 10
+#define C2 5
+
+__attribute__ ((noinline)) void
+foo (unsigned char *src, unsigned int *dst1, unsigned int *dst2)
+{
+ int i;
+ unsigned char b, *s = src;
+ unsigned int *d1 = dst1, *d2 = dst2;
+
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ *d1 = b << C1;
+ d1++;
+ *d2 = b << C2;
+ d2++;
+ }
+
+ s = src;
+ d1 = dst1;
+ d2 = dst2;
+ for (i = 0; i < N; i++)
+ {
+ b = *s++;
+ if (*d1 != b << C1 || *d2 != b << C2)
+ abort ();
+ d1++;
+ d2++;
+ }
+}
+
+int main (void)
+{
+ int i;
+ unsigned char in[N];
+ unsigned int out1[N];
+ unsigned int out2[N];
+
+ check_vect ();
+
+ for (i = 0; i < N; i++)
+ {
+ in[i] = i;
+ out1[i] = 255;
+ out2[i] = 255;
+ __asm__ volatile ("");
+ }
+
+ foo (in, out1, out2);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 1 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp
index b8a41cc16f9..65d74d62823 100644
--- a/gcc/testsuite/gcc.dg/vect/vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/vect.exp
@@ -269,6 +269,13 @@ lappend DEFAULT_VECTCFLAGS "-fno-tree-fre" "-fno-tree-pre"
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-fre-pre*.\[cS\]]] \
"" $DEFAULT_VECTCFLAGS
+# -fno-tree-sra
+set VECT_SLP_CFLAGS $SAVED_VECT_SLP_CFLAGS
+lappend VECT_SLP_CFLAGS "-fno-tree-sra"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-tree-sra-bb-slp-*.\[cS\]]] \
+ "" $VECT_SLP_CFLAGS
+
+
# Clean up.
set dg-do-what-default ${save-dg-do-what-default}
diff --git a/gcc/testsuite/gcc.dg/vector-compare-2.c b/gcc/testsuite/gcc.dg/vector-compare-2.c
index e672dd1d9c4..f42986fdcb5 100644
--- a/gcc/testsuite/gcc.dg/vector-compare-2.c
+++ b/gcc/testsuite/gcc.dg/vector-compare-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile } */
+/* { dg-options "-fno-common" { target hppa*-*-hpux* } } */
/* Test if C_MAYBE_CONST are folded correctly when
creating VEC_COND_EXPR. */
diff --git a/gcc/testsuite/gcc.dg/vla-23.c b/gcc/testsuite/gcc.dg/vla-23.c
new file mode 100644
index 00000000000..47be4123301
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-23.c
@@ -0,0 +1,17 @@
+/* PR rtl-optimization/50615 */
+/* Testcase by Zdenek Sojka <zsojka@seznam.cz> */
+
+/* { dg-do compile } */
+/* { dg-options "-O --param max-cse-insns=1" } */
+
+int
+foo (int a)
+{
+ if (!a)
+ return 1;
+
+ {
+ int s[a];
+ return 0;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vshift-1.c b/gcc/testsuite/gcc.dg/vshift-1.c
new file mode 100644
index 00000000000..2a237aa2bbe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vshift-1.c
@@ -0,0 +1,132 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+#include <stdlib.h>
+
+#define N 64
+
+#ifndef TYPE1
+#define TYPE1 int
+#define TYPE2 long long
+#endif
+
+signed TYPE1 a[N], b[N], g[N];
+unsigned TYPE1 c[N], h[N];
+signed TYPE2 d[N], e[N], j[N];
+unsigned TYPE2 f[N], k[N];
+
+__attribute__((noinline)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ g[i] = a[i] << b[i];
+}
+
+__attribute__((noinline)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ g[i] = a[i] >> b[i];
+}
+
+__attribute__((noinline)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ h[i] = c[i] >> b[i];
+}
+
+__attribute__((noinline)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] << e[i];
+}
+
+__attribute__((noinline)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] >> e[i];
+}
+
+__attribute__((noinline)) void
+f6 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ k[i] = f[i] >> e[i];
+}
+
+__attribute__((noinline)) void
+f7 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] << b[i];
+}
+
+__attribute__((noinline)) void
+f8 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] >> b[i];
+}
+
+__attribute__((noinline)) void
+f9 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ k[i] = f[i] >> b[i];
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < N; i++)
+ {
+ asm ("");
+ c[i] = (random () << 1) | (random () & 1);
+ b[i] = (i * 85) & (sizeof (TYPE1) * __CHAR_BIT__ - 1);
+ a[i] = c[i];
+ d[i] = (random () << 1) | (random () & 1);
+ d[i] |= (unsigned long long) c[i] << 32;
+ e[i] = (i * 85) & (sizeof (TYPE2) * __CHAR_BIT__ - 1);
+ f[i] = d[i];
+ }
+ f1 ();
+ f3 ();
+ f4 ();
+ f6 ();
+ for (i = 0; i < N; i++)
+ if (g[i] != (signed TYPE1) (a[i] << b[i])
+ || h[i] != (unsigned TYPE1) (c[i] >> b[i])
+ || j[i] != (signed TYPE2) (d[i] << e[i])
+ || k[i] != (unsigned TYPE2) (f[i] >> e[i]))
+ abort ();
+ f2 ();
+ f5 ();
+ f9 ();
+ for (i = 0; i < N; i++)
+ if (g[i] != (signed TYPE1) (a[i] >> b[i])
+ || j[i] != (signed TYPE2) (d[i] >> e[i])
+ || k[i] != (unsigned TYPE2) (f[i] >> b[i]))
+ abort ();
+ f7 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != (signed TYPE2) (d[i] << b[i]))
+ abort ();
+ f8 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != (signed TYPE2) (d[i] >> b[i]))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vshift-2.c b/gcc/testsuite/gcc.dg/vshift-2.c
new file mode 100644
index 00000000000..8f490d209db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vshift-2.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+#define TYPE1 char
+#define TYPE2 short
+
+#include "vshift-1.c"
diff --git a/gcc/testsuite/gcc.dg/vshift-3.c b/gcc/testsuite/gcc.dg/vshift-3.c
new file mode 100644
index 00000000000..e62c76b469f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vshift-3.c
@@ -0,0 +1,136 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+#include <stdlib.h>
+
+#define N 64
+
+#ifndef TYPE1
+#define TYPE1 int
+#define TYPE2 long long
+#endif
+
+signed TYPE1 a[N], b, g[N];
+unsigned TYPE1 c[N], h[N];
+signed TYPE2 d[N], e, j[N];
+unsigned TYPE2 f[N], k[N];
+
+#ifndef S
+#define S(x) x
+#endif
+
+__attribute__((noinline)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ g[i] = a[i] << S (b);
+}
+
+__attribute__((noinline)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ g[i] = a[i] >> S (b);
+}
+
+__attribute__((noinline)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ h[i] = c[i] >> S (b);
+}
+
+__attribute__((noinline)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] << S (e);
+}
+
+__attribute__((noinline)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] >> S (e);
+}
+
+__attribute__((noinline)) void
+f6 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ k[i] = f[i] >> S (e);
+}
+
+__attribute__((noinline)) void
+f7 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] << S (b);
+}
+
+__attribute__((noinline)) void
+f8 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] >> S (b);
+}
+
+__attribute__((noinline)) void
+f9 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ k[i] = f[i] >> S (b);
+}
+
+int
+main ()
+{
+ int i;
+ b = 7;
+ e = 12;
+ for (i = 0; i < N; i++)
+ {
+ asm ("");
+ c[i] = (random () << 1) | (random () & 1);
+ a[i] = c[i];
+ d[i] = (random () << 1) | (random () & 1);
+ d[i] |= (unsigned long long) c[i] << 32;
+ f[i] = d[i];
+ }
+ f1 ();
+ f3 ();
+ f4 ();
+ f6 ();
+ for (i = 0; i < N; i++)
+ if (g[i] != (signed TYPE1) (a[i] << S (b))
+ || h[i] != (unsigned TYPE1) (c[i] >> S (b))
+ || j[i] != (signed TYPE2) (d[i] << S (e))
+ || k[i] != (unsigned TYPE2) (f[i] >> S (e)))
+ abort ();
+ f2 ();
+ f5 ();
+ f9 ();
+ for (i = 0; i < N; i++)
+ if (g[i] != (signed TYPE1) (a[i] >> S (b))
+ || j[i] != (signed TYPE2) (d[i] >> S (e))
+ || k[i] != (unsigned TYPE2) (f[i] >> S (b)))
+ abort ();
+ f7 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != (signed TYPE2) (d[i] << S (b)))
+ abort ();
+ f8 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != (signed TYPE2) (d[i] >> S (b)))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vshift-4.c b/gcc/testsuite/gcc.dg/vshift-4.c
new file mode 100644
index 00000000000..c43fbcc196e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vshift-4.c
@@ -0,0 +1,6 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+#define S(x) 3
+
+#include "vshift-3.c"
diff --git a/gcc/testsuite/gcc.dg/vshift-5.c b/gcc/testsuite/gcc.dg/vshift-5.c
new file mode 100644
index 00000000000..daa5f1c5cd8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vshift-5.c
@@ -0,0 +1,81 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+extern void abort (void);
+long long a[16];
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+ long long a0, a1, a2, a3;
+ a0 = a[0];
+ a1 = a[1];
+ a2 = a[2];
+ a3 = a[3];
+ a0 = a0 << 2;
+ a1 = a1 << 3;
+ a2 = a2 << 4;
+ a3 = a3 << 5;
+ a[0] = a0;
+ a[1] = a1;
+ a[2] = a2;
+ a[3] = a3;
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+ long long a0, a1, a2, a3;
+ a0 = a[0];
+ a1 = a[1];
+ a2 = a[2];
+ a3 = a[3];
+ a0 = a0 << 2;
+ a1 = a1 << 2;
+ a2 = a2 << 2;
+ a3 = a3 << 2;
+ a[0] = a0;
+ a[1] = a1;
+ a[2] = a2;
+ a[3] = a3;
+}
+
+__attribute__((noinline, noclone)) void
+f3 (int x)
+{
+ long long a0, a1, a2, a3;
+ a0 = a[0];
+ a1 = a[1];
+ a2 = a[2];
+ a3 = a[3];
+ a0 = a0 << x;
+ a1 = a1 << x;
+ a2 = a2 << x;
+ a3 = a3 << x;
+ a[0] = a0;
+ a[1] = a1;
+ a[2] = a2;
+ a[3] = a3;
+}
+
+int
+main ()
+{
+ a[0] = 4LL;
+ a[1] = 3LL;
+ a[2] = 2LL;
+ a[3] = 1LL;
+ f1 ();
+ if (a[0] != (4LL << 2) || a[1] != (3LL << 3)
+ || a[2] != (2LL << 4) || a[3] != (1LL << 5))
+ abort ();
+ f2 ();
+ if (a[0] != (4LL << 4) || a[1] != (3LL << 5)
+ || a[2] != (2LL << 6) || a[3] != (1LL << 7))
+ abort ();
+ f3 (3);
+ if (a[0] != (4LL << 7) || a[1] != (3LL << 8)
+ || a[2] != (2LL << 9) || a[3] != (1LL << 10))
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withhelpers.c b/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withhelpers.c
new file mode 100644
index 00000000000..19342bf80dd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withhelpers.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v5_ok } */
+/* { dg-options "-std=gnu99" } */
+/* { dg-add-options arm_arch_v5 } */
+/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
+
+#include "../../gcc.dg/di-longlong64-sync-1.c"
+
+/* On an old ARM we have no ldrexd or strexd so we have to use helpers. */
+/* { dg-final { scan-assembler-not "ldrexd" } } */
+/* { dg-final { scan-assembler-not "strexd" } } */
+/* { dg-final { scan-assembler "__sync_" } } */
diff --git a/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c b/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c
new file mode 100644
index 00000000000..dab69405ef4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/di-longlong64-sync-withldrexd.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arm_ok } */
+/* { dg-options "-marm -std=gnu99" } */
+/* { dg-require-effective-target arm_arch_v6k_ok } */
+/* { dg-add-options arm_arch_v6k } */
+/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "note: '__sync_nand_and_fetch' changed semantics in GCC 4.4" "" { target *-*-* } 0 } */
+/* { dg-message "file included" "In file included" { target *-*-* } 0 } */
+
+#include "../../gcc.dg/di-longlong64-sync-1.c"
+
+/* We should be using ldrexd, strexd and no helpers or shorter ldrex. */
+/* { dg-final { scan-assembler-times "\tldrexd" 46 } } */
+/* { dg-final { scan-assembler-times "\tstrexd" 46 } } */
+/* { dg-final { scan-assembler-not "__sync_" } } */
+/* { dg-final { scan-assembler-not "ldrex\t" } } */
+/* { dg-final { scan-assembler-not "strex\t" } } */
diff --git a/gcc/testsuite/gcc.target/arm/pr42575.c b/gcc/testsuite/gcc.target/arm/pr42575.c
index 474bf6cf60b..1998e323df1 100644
--- a/gcc/testsuite/gcc.target/arm/pr42575.c
+++ b/gcc/testsuite/gcc.target/arm/pr42575.c
@@ -1,4 +1,4 @@
-/* { dg-options "-O2 -march=armv7-a" } */
+/* { dg-options "-O2" } */
/* Make sure RA does good job allocating registers and avoids
unnecessary moves. */
/* { dg-final { scan-assembler-not "mov" } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-1.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-1.c
new file mode 100644
index 00000000000..c4f56404225
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-1.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_unaligned } */
+/* { dg-options "-O2" } */
+
+#include <string.h>
+
+void unknown_alignment (char *dest, char *src)
+{
+ memcpy (dest, src, 15);
+}
+
+/* We should see three unaligned word loads and store pairs, one unaligned
+ ldrh/strh pair, and an ldrb/strb pair. Sanity check that. */
+
+/* { dg-final { scan-assembler-times "@ unaligned" 8 } } */
+/* { dg-final { scan-assembler-times "ldrh" 1 } } */
+/* { dg-final { scan-assembler-times "strh" 1 } } */
+/* { dg-final { scan-assembler-times "ldrb" 1 } } */
+/* { dg-final { scan-assembler-times "strb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-2.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-2.c
new file mode 100644
index 00000000000..c7d24c9c5c3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_unaligned } */
+/* { dg-options "-O2" } */
+
+#include <string.h>
+
+char dest[16];
+
+void aligned_dest (char *src)
+{
+ memcpy (dest, src, 15);
+}
+
+/* Expect a multi-word store for the main part of the copy, but subword
+ loads/stores for the remainder. */
+
+/* { dg-final { scan-assembler-times "stmia" 1 } } */
+/* { dg-final { scan-assembler-times "ldrh" 1 } } */
+/* { dg-final { scan-assembler-times "strh" 1 } } */
+/* { dg-final { scan-assembler-times "ldrb" 1 } } */
+/* { dg-final { scan-assembler-times "strb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-3.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-3.c
new file mode 100644
index 00000000000..5f0413738c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-3.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_unaligned } */
+/* { dg-options "-O2" } */
+
+#include <string.h>
+
+char src[16];
+
+void aligned_src (char *dest)
+{
+ memcpy (dest, src, 15);
+}
+
+/* Expect a multi-word load for the main part of the copy, but subword
+ loads/stores for the remainder. */
+
+/* { dg-final { scan-assembler-times "ldmia" 1 } } */
+/* { dg-final { scan-assembler-times "ldrh" 1 } } */
+/* { dg-final { scan-assembler-times "strh" 1 } } */
+/* { dg-final { scan-assembler-times "ldrb" 1 } } */
+/* { dg-final { scan-assembler-times "strb" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c
new file mode 100644
index 00000000000..99957086e7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/unaligned-memcpy-4.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_unaligned } */
+/* { dg-options "-O2" } */
+
+#include <string.h>
+
+char src[16];
+char dest[16];
+
+void aligned_both (void)
+{
+ memcpy (dest, src, 15);
+}
+
+/* We know both src and dest to be aligned: expect multiword loads/stores. */
+
+/* { dg-final { scan-assembler-times "ldmia" 1 } } */
+/* { dg-final { scan-assembler-times "stmia" 1 } } */
diff --git a/gcc/testsuite/gcc.target/arm/wmul-12.c b/gcc/testsuite/gcc.target/arm/wmul-12.c
index 556e53f8e44..5c6b5b9882c 100644
--- a/gcc/testsuite/gcc.target/arm/wmul-12.c
+++ b/gcc/testsuite/gcc.target/arm/wmul-12.c
@@ -5,8 +5,8 @@
long long
foo (int *b, int *c)
{
- int tmp = *b * *c;
- return 10 + (long long)tmp;
+ long long tmp = (long long)*b * *c;
+ return 10 + tmp;
}
/* { dg-final { scan-assembler "smlal" } } */
diff --git a/gcc/testsuite/gcc.target/arm/wmul-8.c b/gcc/testsuite/gcc.target/arm/wmul-8.c
index 3de065d0a62..5ae110d3c49 100644
--- a/gcc/testsuite/gcc.target/arm/wmul-8.c
+++ b/gcc/testsuite/gcc.target/arm/wmul-8.c
@@ -5,7 +5,7 @@
long long
foo (long long a, int *b, int *c)
{
- return a + *b * *c;
+ return a + (long long)*b * *c;
}
/* { dg-final { scan-assembler "smlal" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-cvt-1.c b/gcc/testsuite/gcc.target/i386/avx-cvt-1.c
new file mode 100644
index 00000000000..ce651649d64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-cvt-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mavx -mno-avx2" } */
+/* { dg-require-effective-target avx_runtime } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include "sse2-cvt-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-cvt-2.c b/gcc/testsuite/gcc.target/i386/avx-cvt-2.c
new file mode 100644
index 00000000000..68206f5a0e7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-cvt-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx -mno-avx2 -mtune=generic -fdump-tree-vect-details" } */
+
+#include "avx-cvt-1.c"
+
+/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops in function" 6 "vect" } } */
+/* { dg-final { scan-assembler "vcvttpd2dq(y\[^\n\r\]*%xmm|\[^\n\r\]*xmm\[^\n\r\]*YMMWORD PTR)" } } */
+/* { dg-final { scan-assembler "vcvtdq2ps\[^\n\r\]*xmm" } } */
+/* { dg-final { scan-assembler "vcvtps2pd\[^\n\r\]*(%xmm\[^\n\r\]*%ymm|ymm\[^\n\r\]*xmm)" } } */
+/* { dg-final { scan-assembler "vcvttps2dq\[^\n\r\]*ymm" } } */
+/* { dg-final { scan-assembler "vcvtdq2pd\[^\n\r\]*xmm\[^\n\r\]*xmm" } } */
+/* { dg-final { scan-assembler "vcvtpd2ps(y\[^\n\r\]*%xmm|\[^\n\r\]*xmm\[^\n\r\]*YMMWORD PTR)" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx-mul-1.c b/gcc/testsuite/gcc.target/i386/avx-mul-1.c
new file mode 100644
index 00000000000..0d511c95cb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-mul-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx } */
+/* { dg-options "-O3 -mavx" } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx_test
+#endif
+
+#include "sse2-mul-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-vphminposuw-2.c b/gcc/testsuite/gcc.target/i386/avx-vphminposuw-2.c
new file mode 100644
index 00000000000..3ae122c7e88
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vphminposuw-2.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx } */
+/* { dg-options "-O3 -mavx -mno-avx2" } */
+
+#define CHECK_H "avx-check.h"
+#define TEST avx_test
+
+#include "sse4_1-phminposuw-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx-vphminposuw-3.c b/gcc/testsuite/gcc.target/i386/avx-vphminposuw-3.c
new file mode 100644
index 00000000000..4a37ba542ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx-vphminposuw-3.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx -mno-avx2" } */
+
+#include "avx-vphminposuw-2.c"
+
+/* { dg-final { scan-assembler "vphminposuw\[^\n\r\]*xmm" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-check.h b/gcc/testsuite/gcc.target/i386/avx2-check.h
index 22c9b39da45..424335dbb5e 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-check.h
+++ b/gcc/testsuite/gcc.target/i386/avx2-check.h
@@ -21,6 +21,9 @@ main ()
/* Run AVX2 test only if host has AVX2 support. */
if ((ecx & bit_OSXSAVE) == (bit_OSXSAVE))
{
+ if (__get_cpuid_max (0, NULL) < 7)
+ return 0;
+
__cpuid_count (7, 0, eax, ebx, ecx, edx);
if ((avx_os_support ()) && ((ebx & bit_AVX2) == bit_AVX2))
diff --git a/gcc/testsuite/gcc.target/i386/avx2-cvt-1.c b/gcc/testsuite/gcc.target/i386/avx2-cvt-1.c
new file mode 100644
index 00000000000..9626a0666d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-cvt-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mavx2" } */
+/* { dg-require-effective-target avx2 } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx2_test
+#endif
+
+#include "sse2-cvt-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx2-cvt-2.c b/gcc/testsuite/gcc.target/i386/avx2-cvt-2.c
new file mode 100644
index 00000000000..4826e9b6d05
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-cvt-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx2 -mtune=generic -fdump-tree-vect-details" } */
+
+#include "avx2-cvt-1.c"
+
+/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops in function" 6 "vect" } } */
+/* { dg-final { scan-assembler "vcvttpd2dq(y\[^\n\r\]*%xmm|\[^\n\r\]*xmm\[^\n\r\]*YMMWORD PTR)" } } */
+/* { dg-final { scan-assembler "vcvtdq2ps\[^\n\r\]*ymm" } } */
+/* { dg-final { scan-assembler "vcvtps2pd\[^\n\r\]*(%xmm\[^\n\r\]*%ymm|ymm\[^\n\r\]*xmm)" } } */
+/* { dg-final { scan-assembler "vcvttps2dq\[^\n\r\]*ymm" } } */
+/* { dg-final { scan-assembler "vcvtdq2pd\[^\n\r\]*(%xmm\[^\n\r\]*%ymm|ymm\[^\n\r\]*xmm)" } } */
+/* { dg-final { scan-assembler "vcvtpd2ps(y\[^\n\r\]*%xmm|\[^\n\r\]*xmm\[^\n\r\]*YMMWORD PTR)" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherd-1.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherd-1.c
index 8adddcfdc46..ae3b1d577b4 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherd-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherdd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherdd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherd-3.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherd-3.c
index f84c4a56463..fc8fedea076 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherd-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherd-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherdd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherdd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-1.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-1.c
index a4bbb1d3878..afc73b9b18b 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherdd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherdd\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-3.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-3.c
index 36df1f80cc1..d0c86429449 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherd256-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherdd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherdd\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-1.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-1.c
index e9a3a0ecedd..860cac448d7 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherdpd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherdpd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-3.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-3.c
index 08d0de29b96..5e1d4864bdf 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherdpd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherdpd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-1.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-1.c
index 82edc5c5526..00b6a35c59d 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherdpd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherdpd\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-3.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-3.c
index bc22fae9f5a..336fb299b0f 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherpd256-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherdpd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherdpd\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherps-1.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherps-1.c
index 5559cb198d2..c43687c4d01 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherps-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherps-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherdps\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherdps\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherps-3.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherps-3.c
index 0423d2c2345..76b46fb23ab 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherps-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherps-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherdps\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherdps\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-1.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-1.c
index ce77a398699..f09a0ff32f6 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherdps\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherdps\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-3.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-3.c
index 63879e09f93..34b7b8d72fe 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherps256-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherdps\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherdps\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherq-1.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherq-1.c
index a31e07c3ada..0b250e5dd2c 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherq-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherq-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherdq\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherdq\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherq-3.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherq-3.c
index b3cd6099544..d87400c77db 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherq-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherq-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherdq\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherdq\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-1.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-1.c
index 140036f921f..e8651438a9b 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherdq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherdq\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-3.c b/gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-3.c
index 345917cc2ea..7b6f4491aa0 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i32gatherq256-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherdq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherdq\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherd-1.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherd-1.c
index 333a7f84881..f2ade8415d3 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherd-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherqd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherqd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherd-3.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherd-3.c
index 2c04422331f..265713da504 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherd-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherd-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherqd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherqd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-1.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-1.c
index d338d1bcd86..ccc16e523c8 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherqd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherqd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-3.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-3.c
index 50fbbf2eb74..815e7082824 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherd256-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherqd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherqd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-1.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-1.c
index a8cc464f42d..895b248c722 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherqpd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherqpd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-3.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-3.c
index 8cf10f3e7e7..436ffe90a90 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherqpd\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherqpd\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-1.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-1.c
index 39e2370b2ff..bc22f02e56b 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherqpd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherqpd\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-3.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-3.c
index 83b31544c7b..505722a8a79 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherpd256-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherqpd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherqpd\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherps-1.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherps-1.c
index 2dccde6462d..c7d7c0787b2 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherps-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherps-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherqps\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherqps\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherps-3.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherps-3.c
index f69cc2636bf..ca7162ad92b 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherps-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherps-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherqps\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherqps\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-1.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-1.c
index 59dd47d9113..6612e994005 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherqps\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherqps\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-3.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-3.c
index 4ccc10a2b95..f05e4a208c1 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherps256-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vgatherqps\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vgatherqps\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherq-1.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherq-1.c
index 7db1d924cf8..8f9752d2c84 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherq-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherq-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherqq\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherqq\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherq-3.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherq-3.c
index 16e4fb8ce0e..c1c31c7288e 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherq-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherq-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherqq\[ \\t\]+\[^\n\]*%xmm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherqq\[ \\t\]+\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]\[^\n\]*xmm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-1.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-1.c
index a9b09210070..c873cb95487 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-1.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-1.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherqq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherqq\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-3.c b/gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-3.c
index fd96648fab1..f60ad22746a 100644
--- a/gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-3.c
+++ b/gcc/testsuite/gcc.target/i386/avx2-i64gatherq256-3.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mavx2 -O2" } */
-/* { dg-final { scan-assembler "vpgatherqq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" } } */
+/* { dg-final { scan-assembler "vpgatherqq\[ \\t\]+\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]\[^\n\]*ymm\[0-9\]" } } */
#include <immintrin.h>
diff --git a/gcc/testsuite/gcc.target/i386/avx2-mul-1.c b/gcc/testsuite/gcc.target/i386/avx2-mul-1.c
new file mode 100644
index 00000000000..0351fbb7c3d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-mul-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target avx2 } */
+/* { dg-options "-O3 -mavx2" } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx2_test
+#endif
+
+#include "sse2-mul-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpaddb-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpaddb-3.c
new file mode 100644
index 00000000000..238f0209218
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpaddb-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE char
+#define BIN_OP(a, b) ((a) + (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpaddb\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpaddd-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpaddd-3.c
new file mode 100644
index 00000000000..c57ef8fea30
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpaddd-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE int
+#define BIN_OP(a, b) ((a) + (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpaddd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpaddq-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpaddq-3.c
new file mode 100644
index 00000000000..801bd39d82f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpaddq-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE long long int
+#define BIN_OP(a, b) ((a) + (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpaddq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpaddw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpaddw-3.c
new file mode 100644
index 00000000000..facee9f2d57
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpaddw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE short
+#define BIN_OP(a, b) ((a) + (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpaddw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpand-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpand-3.c
new file mode 100644
index 00000000000..67ca4a7cda1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpand-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE unsigned
+#define BIN_OP(a, b) ((a) & (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpand\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpmulld-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpmulld-3.c
new file mode 100644
index 00000000000..b2d539ba49a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpmulld-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE int
+#define BIN_OP(a, b) ((a) * (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpmulld\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpmullw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpmullw-3.c
new file mode 100644
index 00000000000..46d173fc371
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpmullw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE short
+#define BIN_OP(a, b) ((a) * (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpmullw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpop-check.h b/gcc/testsuite/gcc.target/i386/avx2-vpop-check.h
new file mode 100644
index 00000000000..143b54dae03
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpop-check.h
@@ -0,0 +1,53 @@
+#include "avx2-check.h"
+
+#define SIZE 256
+
+TYPE a[SIZE];
+TYPE b[SIZE];
+TYPE c[SIZE];
+volatile TYPE c_ref[SIZE];
+
+__attribute__ ((__noinline__))
+void
+gen_pop ()
+{
+ int i;
+ for (i = 0; i < SIZE; ++i)
+#ifdef BIN_OP
+ c[i] = BIN_OP (a[i], b[i]);
+#else /* Must be UN_OP */
+ c[i] = UN_OP (a[i]);
+#endif /* BIN_OP */
+}
+
+void
+check_pop ()
+{
+ int i;
+ for (i = 0; i < SIZE; ++i)
+#ifdef BIN_OP
+ c_ref[i] = BIN_OP (a[i], b[i]);
+#else /* Must be UN_OP */
+ c_ref[i] = UN_OP (a[i]);
+#endif /* BIN_OP */
+}
+
+void static
+avx2_test (void)
+{
+ int i, j;
+ for (i = 0; i < 4; ++i )
+ {
+ for ( j = 0; j < SIZE; ++j )
+ {
+ a[i] = i * i + i;
+ b[i] = i * i * i;
+ }
+
+ gen_pop ();
+ check_pop ();
+
+ if (memcmp (c, c_ref, SIZE * sizeof (TYPE)))
+ abort();
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsrad-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsrad-3.c
new file mode 100644
index 00000000000..97affb4bb7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsrad-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE unsigned
+#define UN_OP(a) ((a) >> (5))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsrld\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsraw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsraw-3.c
new file mode 100644
index 00000000000..e7112565b3a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsraw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE short
+#define UN_OP(a) ((a) >> (5))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsraw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsrld-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsrld-3.c
new file mode 100644
index 00000000000..97affb4bb7e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsrld-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE unsigned
+#define UN_OP(a) ((a) >> (5))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsrld\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsrlw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsrlw-3.c
new file mode 100644
index 00000000000..67f3afc4131
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsrlw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE unsigned short
+#define UN_OP(a) ((a) >> (5))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsrlw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsubb-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsubb-3.c
new file mode 100644
index 00000000000..843128b4f27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsubb-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE char
+#define BIN_OP(a, b) ((a) - (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsubb\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsubd-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsubd-3.c
new file mode 100644
index 00000000000..f8f399f6b00
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsubd-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE int
+#define BIN_OP(a, b) ((a) - (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsubd\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsubq-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsubq-3.c
new file mode 100644
index 00000000000..0a23a280e52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsubq-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE long long int
+#define BIN_OP(a, b) ((a) - (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsubq\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vpsubw-3.c b/gcc/testsuite/gcc.target/i386/avx2-vpsubw-3.c
new file mode 100644
index 00000000000..1cb90b5a8e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vpsubw-3.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-mavx2 -O2 -ftree-vectorize -save-temps" } */
+/* { dg-require-effective-target avx2 } */
+
+
+#define TYPE short
+#define BIN_OP(a, b) ((a) - (b))
+
+#include "avx2-vpop-check.h"
+
+/* { dg-final { scan-assembler-times "vpsubw\[ \\t\]+\[^\n\]*%ymm\[0-9\]" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
diff --git a/gcc/testsuite/gcc.target/i386/avx2-vshift-1.c b/gcc/testsuite/gcc.target/i386/avx2-vshift-1.c
new file mode 100644
index 00000000000..15f20c83658
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/avx2-vshift-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mavx2" } */
+/* { dg-require-effective-target avx2 } */
+
+#ifndef CHECK_H
+#define CHECK_H "avx2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST avx2_test
+#endif
+
+#include "xop-vshift-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/bmi2-check.h b/gcc/testsuite/gcc.target/i386/bmi2-check.h
index 5ffce44fc6e..c933a49f281 100644
--- a/gcc/testsuite/gcc.target/i386/bmi2-check.h
+++ b/gcc/testsuite/gcc.target/i386/bmi2-check.h
@@ -17,6 +17,9 @@ main ()
{
unsigned int eax, ebx, ecx, edx;
+ if (__get_cpuid_max (0, NULL) < 7)
+ return 0;
+
__cpuid_count (7, 0, eax, ebx, ecx, edx);
/* Run BMI2 test only if host has BMI2 support. */
diff --git a/gcc/testsuite/gcc.target/i386/branch-cost1.c b/gcc/testsuite/gcc.target/i386/branch-cost1.c
new file mode 100644
index 00000000000..ed873fa7136
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/branch-cost1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-gimple -mbranch-cost=0" } */
+
+extern int doo (void);
+
+int
+foo (int a, int b)
+{
+ if (a && b)
+ return doo ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "if " 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-not " & " "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/gcc.target/i386/branch-cost2.c b/gcc/testsuite/gcc.target/i386/branch-cost2.c
new file mode 100644
index 00000000000..4d754d57b96
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/branch-cost2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-gimple -mbranch-cost=2" } */
+
+extern int doo (void);
+
+int
+foo (int a, int b)
+{
+ if (a && b)
+ return doo ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "if " 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times " & " 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/gcc.target/i386/branch-cost3.c b/gcc/testsuite/gcc.target/i386/branch-cost3.c
new file mode 100644
index 00000000000..3b69f503fcc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/branch-cost3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-gimple -mbranch-cost=2" } */
+
+extern int doo (void);
+
+int
+foo (_Bool a, _Bool b)
+{
+ if (a && b)
+ return doo ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "if " 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times " & " 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/gcc.target/i386/branch-cost4.c b/gcc/testsuite/gcc.target/i386/branch-cost4.c
new file mode 100644
index 00000000000..5904b0da2b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/branch-cost4.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-gimple -mbranch-cost=0" } */
+
+extern int doo (void);
+
+int
+foo (_Bool a, _Bool b)
+{
+ if (a && b)
+ return doo ();
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "if " 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-not " & " "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
diff --git a/gcc/testsuite/gcc.target/i386/fma-check.h b/gcc/testsuite/gcc.target/i386/fma-check.h
index 696c4a00fb4..8390f5088bd 100644
--- a/gcc/testsuite/gcc.target/i386/fma-check.h
+++ b/gcc/testsuite/gcc.target/i386/fma-check.h
@@ -21,5 +21,5 @@ main ()
if (ecx & bit_FMA)
do_test ();
- exit (0);
+ return 0;
}
diff --git a/gcc/testsuite/gcc.target/i386/fma4-check.h b/gcc/testsuite/gcc.target/i386/fma4-check.h
index dc7ee574878..33cd9628c04 100644
--- a/gcc/testsuite/gcc.target/i386/fma4-check.h
+++ b/gcc/testsuite/gcc.target/i386/fma4-check.h
@@ -23,5 +23,5 @@ main ()
if (ecx & bit_FMA4)
do_test ();
- exit (0);
+ return 0;
}
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_1.c b/gcc/testsuite/gcc.target/i386/fma_double_1.c
index 86bd754a281..c3aa3e83c02 100644
--- a/gcc/testsuite/gcc.target/i386/fma_double_1.c
+++ b/gcc/testsuite/gcc.target/i386/fma_double_1.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_2.c b/gcc/testsuite/gcc.target/i386/fma_double_2.c
index e30d689e017..843eff0a158 100644
--- a/gcc/testsuite/gcc.target/i386/fma_double_2.c
+++ b/gcc/testsuite/gcc.target/i386/fma_double_2.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_3.c b/gcc/testsuite/gcc.target/i386/fma_double_3.c
index c66078d4e4c..ac69684fee0 100644
--- a/gcc/testsuite/gcc.target/i386/fma_double_3.c
+++ b/gcc/testsuite/gcc.target/i386/fma_double_3.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_4.c b/gcc/testsuite/gcc.target/i386/fma_double_4.c
index 5df702086ca..51fc111adb2 100644
--- a/gcc/testsuite/gcc.target/i386/fma_double_4.c
+++ b/gcc/testsuite/gcc.target/i386/fma_double_4.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_5.c b/gcc/testsuite/gcc.target/i386/fma_double_5.c
index 68b785f2627..3eca38c1494 100644
--- a/gcc/testsuite/gcc.target/i386/fma_double_5.c
+++ b/gcc/testsuite/gcc.target/i386/fma_double_5.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_double_6.c b/gcc/testsuite/gcc.target/i386/fma_double_6.c
index 5078601b73d..7b75a224f11 100644
--- a/gcc/testsuite/gcc.target/i386/fma_double_6.c
+++ b/gcc/testsuite/gcc.target/i386/fma_double_6.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_1.c b/gcc/testsuite/gcc.target/i386/fma_float_1.c
index a8a2706860e..67b1f3fe7cb 100644
--- a/gcc/testsuite/gcc.target/i386/fma_float_1.c
+++ b/gcc/testsuite/gcc.target/i386/fma_float_1.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_2.c b/gcc/testsuite/gcc.target/i386/fma_float_2.c
index 81836be16d3..a54644d0c70 100644
--- a/gcc/testsuite/gcc.target/i386/fma_float_2.c
+++ b/gcc/testsuite/gcc.target/i386/fma_float_2.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_3.c b/gcc/testsuite/gcc.target/i386/fma_float_3.c
index 354da87adb8..afb88b60745 100644
--- a/gcc/testsuite/gcc.target/i386/fma_float_3.c
+++ b/gcc/testsuite/gcc.target/i386/fma_float_3.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_4.c b/gcc/testsuite/gcc.target/i386/fma_float_4.c
index ed1e44948a4..d9689d9a7af 100644
--- a/gcc/testsuite/gcc.target/i386/fma_float_4.c
+++ b/gcc/testsuite/gcc.target/i386/fma_float_4.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_5.c b/gcc/testsuite/gcc.target/i386/fma_float_5.c
index ed563dad2ba..cb067ca4a91 100644
--- a/gcc/testsuite/gcc.target/i386/fma_float_5.c
+++ b/gcc/testsuite/gcc.target/i386/fma_float_5.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_float_6.c b/gcc/testsuite/gcc.target/i386/fma_float_6.c
index 50ca455eb98..c7580736834 100644
--- a/gcc/testsuite/gcc.target/i386/fma_float_6.c
+++ b/gcc/testsuite/gcc.target/i386/fma_float_6.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfpmath=sse -mfma" } */
+/* { dg-options "-O2 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_1.c b/gcc/testsuite/gcc.target/i386/fma_run_double_1.c
index d46327d23ee..a2f2aae9e14 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_double_1.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_1.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_2.c b/gcc/testsuite/gcc.target/i386/fma_run_double_2.c
index 14d325c3af4..a389473a894 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_double_2.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_2.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_3.c b/gcc/testsuite/gcc.target/i386/fma_run_double_3.c
index f61f3bf7664..7b9d6273bac 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_double_3.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_3.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_4.c b/gcc/testsuite/gcc.target/i386/fma_run_double_4.c
index 36d89ed979f..1c0456dbad8 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_double_4.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_4.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_5.c b/gcc/testsuite/gcc.target/i386/fma_run_double_5.c
index a43af769c03..6c09f0bb8a9 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_double_5.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_5.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_double_6.c b/gcc/testsuite/gcc.target/i386/fma_run_double_6.c
index b72c87d13cb..32e51bf3197 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_double_6.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_double_6.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_1.c b/gcc/testsuite/gcc.target/i386/fma_run_float_1.c
index 1ca34af62fe..eccf60a88cd 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_float_1.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_1.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_2.c b/gcc/testsuite/gcc.target/i386/fma_run_float_2.c
index 380fd3bd742..18177520ac9 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_float_2.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_2.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_3.c b/gcc/testsuite/gcc.target/i386/fma_run_float_3.c
index 0b09056cd36..b206a0775d2 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_float_3.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_3.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_4.c b/gcc/testsuite/gcc.target/i386/fma_run_float_4.c
index e44a62cb92f..31c5a4dbbf6 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_float_4.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_4.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_5.c b/gcc/testsuite/gcc.target/i386/fma_run_float_5.c
index 10c4f2beab1..615886cedbd 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_float_5.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_5.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/fma_run_float_6.c b/gcc/testsuite/gcc.target/i386/fma_run_float_6.c
index 95c44a1ca13..ca6cf5b1c1c 100644
--- a/gcc/testsuite/gcc.target/i386/fma_run_float_6.c
+++ b/gcc/testsuite/gcc.target/i386/fma_run_float_6.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/funcspec-1.c b/gcc/testsuite/gcc.target/i386/funcspec-1.c
index 6eceac2a5a7..742e3a19e23 100644
--- a/gcc/testsuite/gcc.target/i386/funcspec-1.c
+++ b/gcc/testsuite/gcc.target/i386/funcspec-1.c
@@ -3,10 +3,7 @@
for a function that doesn't use attribute((option)). */
/* { dg-do compile } */
/* { dg-require-effective-target ia32 } */
-/* { dg-skip-if "" { i?86-*-* x86_64-*-* } { "-march=*" } { "-march=i386" } } */
-/* { dg-options "-O3 -ftree-vectorize -march=i386" } */
-/* { dg-final { scan-assembler "addps\[ \t\]" } } */
-/* { dg-final { scan-assembler "fsubs\[ \t\]" } } */
+/* { dg-options "-O3 -ftree-vectorize -mno-sse" } */
#ifndef SIZE
#define SIZE 1024
@@ -33,3 +30,6 @@ i387_subnums (void)
for (; i < SIZE; ++i)
a[i] = b[i] - c[i];
}
+
+/* { dg-final { scan-assembler "addps\[ \t\]" } } */
+/* { dg-final { scan-assembler "fsubs\[ \t\]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/funcspec-3.c b/gcc/testsuite/gcc.target/i386/funcspec-3.c
index 01c7e4ca05e..f3f4db76a84 100644
--- a/gcc/testsuite/gcc.target/i386/funcspec-3.c
+++ b/gcc/testsuite/gcc.target/i386/funcspec-3.c
@@ -2,7 +2,7 @@
setting the architecture. */
/* { dg-do compile } */
/* { dg-require-effective-target lp64 } */
-/* { dg-options "-O2 -march=k8" } */
+/* { dg-options "-O2 -march=k8 -mno-sse3" } */
extern void exit (int);
extern void abort (void);
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_1.c b/gcc/testsuite/gcc.target/i386/l_fma_double_1.c
index 81f6111f98e..3451227b2c3 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_1.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_1.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE double
#include "l_fma_1.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_2.c b/gcc/testsuite/gcc.target/i386/l_fma_double_2.c
index cb100f6b2bc..e69bd7fe3de 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_2.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_2.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE double
#include "l_fma_2.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_3.c b/gcc/testsuite/gcc.target/i386/l_fma_double_3.c
index 3aa11399588..00ed16dad2e 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_3.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_3.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE double
#include "l_fma_3.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_4.c b/gcc/testsuite/gcc.target/i386/l_fma_double_4.c
index 97b3a18244d..dbab6430c20 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_4.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_4.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE double
#include "l_fma_4.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_5.c b/gcc/testsuite/gcc.target/i386/l_fma_double_5.c
index 743d5a738a2..210d5670c6c 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_5.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_5.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE double
#include "l_fma_5.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_6.c b/gcc/testsuite/gcc.target/i386/l_fma_double_6.c
index 4f433d5b479..68164818fbc 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_double_6.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_double_6.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE double
#include "l_fma_6.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_1.c b/gcc/testsuite/gcc.target/i386/l_fma_float_1.c
index bc44d15b564..c98ba1169f0 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_1.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_1.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE float
#include "l_fma_1.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_2.c b/gcc/testsuite/gcc.target/i386/l_fma_float_2.c
index 8e4db8a324f..1dafed94e0f 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_2.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_2.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE float
#include "l_fma_2.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_3.c b/gcc/testsuite/gcc.target/i386/l_fma_float_3.c
index 397618a48f4..dbea8fe2714 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_3.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_3.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE float
#include "l_fma_3.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_4.c b/gcc/testsuite/gcc.target/i386/l_fma_float_4.c
index 6ba667ae2c9..5ff5dcb6da9 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_4.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_4.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE float
#include "l_fma_4.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_5.c b/gcc/testsuite/gcc.target/i386/l_fma_float_5.c
index 0f7b3aa3958..d83ebcc094e 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_5.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_5.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE float
#include "l_fma_5.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_6.c b/gcc/testsuite/gcc.target/i386/l_fma_float_6.c
index f53f0c0c576..942ed7d9e3b 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_float_6.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_float_6.c
@@ -1,13 +1,9 @@
/* { dg-do compile } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
-/* { dg-options "-O2 -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma -mtune=generic" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
-
-
#define TYPE float
#include "l_fma_6.h"
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c
index f7aaf25a780..f1d3c3a6b44 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_1.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c
index 9bd3a5b3ea8..db85598c106 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_2.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c
index eac0e5ba9b5..8043f6fbfbb 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_3.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c
index eca6c0abab8..eef05f58ca9 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_4.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c
index 830574bed5f..95b4b66d02b 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_5.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c b/gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c
index cd869dd0e68..24c1a78cdf7 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_double_6.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c
index 55c9bcff71d..8a046131d0c 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_1.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c
index e0a9274f648..ea6df76f173 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_2.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c
index 4beac3c3ab8..5789867d350 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_3.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c
index f85dba450e9..377370b8904 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_4.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c
index 4de24ea2f03..8b0cf3f0fdb 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_5.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c b/gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c
index daaf01763fe..1300618dac1 100644
--- a/gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c
+++ b/gcc/testsuite/gcc.target/i386/l_fma_run_float_6.c
@@ -1,7 +1,6 @@
/* { dg-do run } */
-/* { dg-prune-output ".*warning: 'sseregparm' attribute ignored.*" } */
/* { dg-require-effective-target fma } */
-/* { dg-options "-O3 -mfpmath=sse -mfma" } */
+/* { dg-options "-O3 -Wno-attributes -mfpmath=sse -mfma" } */
/* Test that the compiler properly optimizes floating point multiply
and add instructions into FMA3 instructions. */
diff --git a/gcc/testsuite/gcc.target/i386/pad-4.c b/gcc/testsuite/gcc.target/i386/pad-4.c
index c742310a34c..7b198a63d52 100644
--- a/gcc/testsuite/gcc.target/i386/pad-4.c
+++ b/gcc/testsuite/gcc.target/i386/pad-4.c
@@ -2,6 +2,7 @@
/* { dg-require-effective-target ia32 } */
/* { dg-require-effective-target fpic } */
/* { dg-skip-if "" { i?86-*-* x86_64-*-* } { "-march=*" } { "-march=atom" } } */
+/* { dg-skip-if "No Windows PIC" { *-*-mingw* *-*-cygwin } { "*" } { "" } } */
/* { dg-options "-O2 -fomit-frame-pointer -march=atom -fPIC" } */
/* { dg-final { scan-assembler-times "nop" 8 } } */
/* { dg-final { scan-assembler-not "rep" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr37843-4.c b/gcc/testsuite/gcc.target/i386/pr37843-4.c
index f70692f0e4e..cd56bae4154 100644
--- a/gcc/testsuite/gcc.target/i386/pr37843-4.c
+++ b/gcc/testsuite/gcc.target/i386/pr37843-4.c
@@ -3,8 +3,8 @@
/* { dg-options "-O2 -msse2 -mpreferred-stack-boundary=4 -mstackrealign" } */
/* { dg-require-effective-target sse2 } */
/* { dg-final { scan-assembler-not "andl\[\\t \]*\\$-16,\[\\t \]*%\[re\]?sp" } } */
-/* { dg-final { scan-assembler-not "call\[\\t \]*foo" } } */
-/* { dg-final { scan-assembler "jmp\[\\t \]*foo" } } */
+/* { dg-final { scan-assembler-not "call\[\\t \]*_?foo" } } */
+/* { dg-final { scan-assembler "jmp\[\\t \]*_?foo" } } */
extern int foo (void);
diff --git a/gcc/testsuite/gcc.target/i386/pr40906-1.c b/gcc/testsuite/gcc.target/i386/pr40906-1.c
index e1c3771bb16..233d8fdcb0e 100644
--- a/gcc/testsuite/gcc.target/i386/pr40906-1.c
+++ b/gcc/testsuite/gcc.target/i386/pr40906-1.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-require-effective-target ia32 } */
/* { dg-options "-O2 -fomit-frame-pointer -fno-asynchronous-unwind-tables -mpush-args -mno-accumulate-outgoing-args" } */
+/* { dg-options "-O2 -fomit-frame-pointer -fno-asynchronous-unwind-tables -mpush-args" { target *-*-mingw* *-*-cygwin* } } */
void abort (void);
diff --git a/gcc/testsuite/gcc.target/i386/pr40906-2.c b/gcc/testsuite/gcc.target/i386/pr40906-2.c
index 5a7bd6c270f..58b076e1f5b 100644
--- a/gcc/testsuite/gcc.target/i386/pr40906-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr40906-2.c
@@ -1,6 +1,7 @@
/* { dg-do run } */
/* { dg-require-effective-target ia32 } */
/* { dg-options "-O2 -Wno-psabi -fomit-frame-pointer -fno-asynchronous-unwind-tables -mpush-args -mno-accumulate-outgoing-args -m128bit-long-double" } */
+/* { dg-options "-O2 -Wno-psabi -fomit-frame-pointer -fno-asynchronous-unwind-tables -mpush-args -m128bit-long-double" { target *-*-mingw* *-*-cygwin* } } */
void abort (void);
diff --git a/gcc/testsuite/gcc.target/i386/pr46226.c b/gcc/testsuite/gcc.target/i386/pr46226.c
index 389158a03ee..168d80e2be4 100644
--- a/gcc/testsuite/gcc.target/i386/pr46226.c
+++ b/gcc/testsuite/gcc.target/i386/pr46226.c
@@ -1,5 +1,6 @@
/* { dg-do run } */
/* { dg-options "-Os -fomit-frame-pointer -mno-accumulate-outgoing-args -fno-asynchronous-unwind-tables" } */
+/* { dg-options "-Os -fomit-frame-pointer -fno-asynchronous-unwind-tables" { target *-*-mingw* *-*-cygwin* } } */
extern void abort(void);
diff --git a/gcc/testsuite/gcc.target/i386/pr50712.c b/gcc/testsuite/gcc.target/i386/pr50712.c
new file mode 100644
index 00000000000..90cc75db346
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr50712.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ia32 } */
+/* { dg-options "-O2" } */
+
+typedef __builtin_va_list __va_list;
+typedef __va_list __gnuc_va_list;
+typedef __gnuc_va_list va_list;
+struct MSVCRT__iobuf { };
+typedef struct MSVCRT__iobuf MSVCRT_FILE;
+typedef union _printf_arg { } printf_arg;
+MSVCRT_FILE MSVCRT__iob[20];
+int pf_print_a (va_list *);
+int __attribute__((__cdecl__))
+MSVCRT_vfprintf_s(MSVCRT_FILE* file, const char *format, va_list valist)
+{
+ if(!((file != ((void *)0))
+ || (MSVCRT__invalid_parameter(((void *)0), ((void *)0),
+ ((void *)0), 0, 0),0)))
+ return -1;
+ return pf_printf_a(&valist);
+}
+int __attribute__((__cdecl__))
+MSVCRT_vprintf_s(const char *format, va_list valist)
+{
+ return MSVCRT_vfprintf_s((MSVCRT__iob+1),format,valist);
+}
+int __attribute__((__cdecl__))
+MSVCRT_fprintf_s(MSVCRT_FILE* file, const char *format, ...)
+{
+ va_list valist;
+ va_start (valist, format);
+ return MSVCRT_vfprintf_s(file, format, valist);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr50766.c b/gcc/testsuite/gcc.target/i386/pr50766.c
new file mode 100644
index 00000000000..9923de4248e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr50766.c
@@ -0,0 +1,17 @@
+/* PR target/50766 */
+/* { dg-do assemble } */
+/* { dg-options "-mbmi2" } */
+/* { dg-require-effective-target bmi2 } */
+
+#include <x86intrin.h>
+
+unsigned z;
+
+void
+foo ()
+{
+ unsigned x = 0x23593464;
+ unsigned y = 0xF9494302;
+ z = _pext_u32(x, y);
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/pr50788.c b/gcc/testsuite/gcc.target/i386/pr50788.c
new file mode 100644
index 00000000000..29a19634cc0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr50788.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx -fpeel-loops -fstack-protector-all" } */
+
+typedef long long __m256i __attribute__ ((__vector_size__ (32)));
+typedef double __m256d __attribute__ ((__vector_size__ (32)));
+
+__m256d foo (__m256d *__P, __m256i __M)
+{
+ return __builtin_ia32_maskloadpd256 ( __P, __M);
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse-5.c b/gcc/testsuite/gcc.target/i386/sse-5.c
index 6d84f17c2ee..af935c2f005 100644
--- a/gcc/testsuite/gcc.target/i386/sse-5.c
+++ b/gcc/testsuite/gcc.target/i386/sse-5.c
@@ -1,7 +1,6 @@
/* { dg-do compile } */
/* { dg-require-effective-target ia32 } */
-/* { dg-skip-if "" { i?86-*-* x86_64-*-* } { "-march=*" } { "-march=i386" } } */
-/* { dg-options "-Winline -Wno-psabi -O2 -march=i386" } */
+/* { dg-options "-Winline -Wno-psabi -O2 -mno-sse" } */
typedef double v2df __attribute__ ((vector_size (16)));
v2df p;
diff --git a/gcc/testsuite/gcc.target/i386/sse2-cvt-1.c b/gcc/testsuite/gcc.target/i386/sse2-cvt-1.c
new file mode 100644
index 00000000000..4d5683108dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-cvt-1.c
@@ -0,0 +1,111 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -msse2 -mno-avx" } */
+/* { dg-require-effective-target sse2 } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse2_test
+#endif
+
+#include CHECK_H
+
+#define N 16
+float f[N];
+double d[N];
+int n[N];
+
+__attribute__((noinline)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ n[i] = d[i];
+}
+
+__attribute__((noinline)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ f[i] = n[i];
+}
+
+__attribute__((noinline)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ d[i] = f[i];
+}
+
+__attribute__((noinline)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ n[i] = f[i];
+}
+
+__attribute__((noinline)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ d[i] = n[i];
+}
+
+__attribute__((noinline)) void
+f6 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ f[i] = d[i];
+}
+
+static void
+TEST ()
+{
+ int i;
+ for (i = 0; i < N; i++)
+ {
+ asm ("");
+ d[i] = i + 2.5;
+ }
+ f1 ();
+ for (i = 0; i < N; i++)
+ if (n[i] != i + 2)
+ abort ();
+ else
+ n[i] = i + 7;
+ f2 ();
+ for (i = 0; i < N; i++)
+ if (f[i] != i + 7)
+ abort ();
+ else
+ f[i] = i - 2.25f;
+ f3 ();
+ for (i = 0; i < N; i++)
+ if (d[i] != i - 2.25)
+ abort ();
+ else
+ f[i] = i + 3.5;
+ f4 ();
+ for (i = 0; i < N; i++)
+ if (n[i] != i + 3)
+ abort ();
+ else
+ n[i] = i + 9;
+ f5 ();
+ for (i = 0; i < N; i++)
+ if (d[i] != i + 9)
+ abort ();
+ else
+ d[i] = i - 7.25;
+ f6 ();
+ for (i = 0; i < N; i++)
+ if (f[i] != i - 7.25)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse2-cvt-2.c b/gcc/testsuite/gcc.target/i386/sse2-cvt-2.c
new file mode 100644
index 00000000000..00f13254c22
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-cvt-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -msse2 -mno-sse3 -mtune=generic -fdump-tree-vect-details" } */
+
+#include "sse2-cvt-1.c"
+
+/* { dg-final { scan-tree-dump-times "note: vectorized 1 loops in function" 6 "vect" } } */
+/* { dg-final { scan-assembler "cvttpd2dq" } } */
+/* { dg-final { scan-assembler "cvtdq2ps" } } */
+/* { dg-final { scan-assembler "cvtps2pd" } } */
+/* { dg-final { scan-assembler "cvttps2dq" } } */
+/* { dg-final { scan-assembler "cvtdq2pd" } } */
+/* { dg-final { scan-assembler "cvtpd2ps" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse2-mul-1.c b/gcc/testsuite/gcc.target/i386/sse2-mul-1.c
new file mode 100644
index 00000000000..5c792e8a4aa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse2-mul-1.c
@@ -0,0 +1,209 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-options "-O3 -msse2" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse2-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse2_test
+#endif
+
+#include CHECK_H
+
+#include <stdlib.h>
+
+#define N 512
+static short a1[N], a2[N], a3[N];
+static unsigned short b1[N], b2[N], b3[N];
+static int c1[N], c2[N], c3[N];
+static unsigned int d1[N], d2[N], d3[N];
+static long long e1[N], e2[N], e3[N];
+static unsigned long long g1[N], g2[N], g3[N];
+
+__attribute__((noinline, noclone)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ a1[i] = a2[i] * a3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ b1[i] = b2[i] * b3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ c1[i] = c2[i] * c3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ d1[i] = d2[i] * d3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ e1[i] = e2[i] * e3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f6 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ g1[i] = g2[i] * g3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f7 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ c1[i] = a2[i] * a3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f8 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ d1[i] = (unsigned int) b2[i] * b3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f9 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ e1[i] = (long long) c2[i] * (long long) c3[i];
+}
+
+__attribute__((noinline, noclone)) void
+f10 (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ g1[i] = (unsigned long long) d2[i] * (unsigned long long) d3[i];
+}
+
+__attribute__((noinline, noclone)) int
+f11 (void)
+{
+ int i, r = 0;
+ for (i = 0; i < N; ++i)
+ r += a2[i] * a3[i];
+ return r;
+}
+
+__attribute__((noinline, noclone)) unsigned int
+f12 (void)
+{
+ int i;
+ unsigned r = 0;
+ for (i = 0; i < N; ++i)
+ r += (unsigned int) b2[i] * b3[i];
+ return r;
+}
+
+__attribute__((noinline, noclone)) long long
+f13 (void)
+{
+ int i;
+ long long r = 0;
+ for (i = 0; i < N; ++i)
+ r += (long long) c2[i] * (long long) c3[i];
+ return r;
+}
+
+__attribute__((noinline, noclone)) unsigned long long
+f14 (void)
+{
+ int i;
+ unsigned long long r = 0;
+ for (i = 0; i < N; ++i)
+ r += (unsigned long long) d2[i] * (unsigned long long) d3[i];
+ return r;
+}
+
+static void
+TEST (void)
+{
+ int i;
+ int s1 = 0;
+ unsigned int s2 = 0;
+ long long s3 = 0;
+ unsigned long long s4 = 0;
+ for (i = 0; i < N; ++i)
+ {
+ asm volatile ("" : : "r" (&s1) : "memory");
+ asm volatile ("" : : "r" (&s2) : "memory");
+ asm volatile ("" : : "r" (&s3) : "memory");
+ asm volatile ("" : : "r" (&s4) : "memory");
+ b2[i] = (int) random ();
+ b3[i] = (int) random ();
+ a2[i] = b2[i];
+ a3[i] = b3[i];
+ d2[i] = (((int) random ()) << 16) | b2[i];
+ d3[i] = (((int) random ()) << 16) | b3[i];
+ c2[i] = d2[i];
+ c3[i] = d3[i];
+ s1 += a2[i] * a3[i];
+ s2 += (unsigned int) b2[i] * b3[i];
+ s3 += (long long) c2[i] * (long long) c3[i];
+ s4 += (unsigned long long) d2[i] * (unsigned long long) d3[i];
+ }
+ f1 ();
+ f2 ();
+ f3 ();
+ f4 ();
+ f5 ();
+ f6 ();
+ for (i = 0; i < N; ++i)
+ {
+ if (a1[i] != (short) (a2[i] * a3[i]))
+ abort ();
+ if (b1[i] != (unsigned short) (b2[i] * b3[i]))
+ abort ();
+ if (c1[i] != c2[i] * c3[i])
+ abort ();
+ if (d1[i] != d2[i] * d3[i])
+ abort ();
+ if (e1[i] != e2[i] * e3[i])
+ abort ();
+ if (g1[i] != g2[i] * g3[i])
+ abort ();
+ }
+ f7 ();
+ f8 ();
+ f9 ();
+ f10 ();
+ for (i = 0; i < N; ++i)
+ {
+ if (c1[i] != a2[i] * a3[i])
+ abort ();
+ if (d1[i] != b2[i] * b3[i])
+ abort ();
+ if (e1[i] != (long long) c2[i] * (long long) c3[i])
+ abort ();
+ if (g1[i] != (unsigned long long) d2[i] * (unsigned long long) d3[i])
+ abort ();
+ }
+ if (f11 () != s1 || f12 () != s2 || f13 () != s3 || f14 () != s4)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-mul-1.c b/gcc/testsuite/gcc.target/i386/sse4_1-mul-1.c
new file mode 100644
index 00000000000..20d03a515d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-mul-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-options "-O3 -msse4.1" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include "sse2-mul-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-2.c b/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-2.c
new file mode 100644
index 00000000000..c9f9c1cdf34
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-2.c
@@ -0,0 +1,78 @@
+/* { dg-do run } */
+/* { dg-require-effective-target sse4 } */
+/* { dg-options "-O3 -msse4.1 -mno-avx2" } */
+
+#ifndef CHECK_H
+#define CHECK_H "sse4_1-check.h"
+#endif
+
+#ifndef TEST
+#define TEST sse4_1_test
+#endif
+
+#include CHECK_H
+
+extern void abort (void);
+
+#define N 1024
+short a[N], c, e;
+unsigned short b[N], d, f;
+
+__attribute__((noinline)) short
+vecsmax (void)
+{
+ int i;
+ short r = -32768;
+ for (i = 0; i < N; ++i)
+ if (r < a[i]) r = a[i];
+ return r;
+}
+
+__attribute__((noinline)) unsigned short
+vecumax (void)
+{
+ int i;
+ unsigned short r = 0;
+ for (i = 0; i < N; ++i)
+ if (r < b[i]) r = b[i];
+ return r;
+}
+
+__attribute__((noinline)) short
+vecsmin (void)
+{
+ int i;
+ short r = 32767;
+ for (i = 0; i < N; ++i)
+ if (r > a[i]) r = a[i];
+ return r;
+}
+
+__attribute__((noinline)) unsigned short
+vecumin (void)
+{
+ int i;
+ unsigned short r = 65535;
+ for (i = 0; i < N; ++i)
+ if (r > b[i]) r = b[i];
+ return r;
+}
+
+static void
+TEST (void)
+{
+ int i;
+ for (i = 0; i < N; ++i)
+ {
+ a[i] = i - N / 2;
+ b[i] = i + 32768 - N / 2;
+ }
+ a[N / 3] = N;
+ a[2 * N / 3] = -N;
+ b[N / 5] = 32768 + N;
+ b[4 * N / 5] = 32768 - N;
+ if (vecsmax () != N || vecsmin () != -N)
+ abort ();
+ if (vecumax () != 32768 + N || vecumin () != 32768 - N)
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-3.c b/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-3.c
new file mode 100644
index 00000000000..95c5f059d97
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/sse4_1-phminposuw-3.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -msse4.1 -mno-avx2" } */
+
+#include "sse4_1-phminposuw-2.c"
+
+/* { dg-final { scan-assembler "phminposuw\[^\n\r\]*xmm" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vectorize4-avx.c b/gcc/testsuite/gcc.target/i386/vectorize4-avx.c
index 8e4a747a64b..33e99189373 100644
--- a/gcc/testsuite/gcc.target/i386/vectorize4-avx.c
+++ b/gcc/testsuite/gcc.target/i386/vectorize4-avx.c
@@ -11,4 +11,4 @@ calc_freq (int *dest)
dest[i] = sqrt (tmp_out[i]);
}
-/* { dg-final { scan-assembler "vsqrtpd\[ \\t\]+\[^\n\]*%ymm" { xfail *-*-* } } } */
+/* { dg-final { scan-assembler "vsqrtpd\[ \\t\]+\[^\n\]*%ymm" } } */
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v2df.c b/gcc/testsuite/gcc.target/i386/vperm-v2df.c
index 40a51306fdc..5aefc05f474 100644
--- a/gcc/testsuite/gcc.target/i386/vperm-v2df.c
+++ b/gcc/testsuite/gcc.target/i386/vperm-v2df.c
@@ -16,7 +16,7 @@ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
#define assert(T) ((T) || (__builtin_trap (), 0))
#define TEST(E0, E1) \
- b.v = __builtin_ia32_vec_perm_v2df (i[0].v, i[1].v, (IV){E0, E1}); \
+ b.v = __builtin_shuffle (i[0].v, i[1].v, (IV){E0, E1}); \
c.s[0] = i[0].s[E0]; \
c.s[1] = i[0].s[E1]; \
__asm__("" : : : "memory"); \
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v2di.c b/gcc/testsuite/gcc.target/i386/vperm-v2di.c
index 8e300837da8..282cce6e9b9 100644
--- a/gcc/testsuite/gcc.target/i386/vperm-v2di.c
+++ b/gcc/testsuite/gcc.target/i386/vperm-v2di.c
@@ -16,7 +16,7 @@ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
#define assert(T) ((T) || (__builtin_trap (), 0))
#define TEST(E0, E1) \
- b.v = __builtin_ia32_vec_perm_v2di (i[0].v, i[1].v, (IV){E0, E1}); \
+ b.v = __builtin_shuffle (i[0].v, i[1].v, (IV){E0, E1}); \
c.s[0] = i[0].s[E0]; \
c.s[1] = i[0].s[E1]; \
__asm__("" : : : "memory"); \
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4sf-1.c b/gcc/testsuite/gcc.target/i386/vperm-v4sf-1.c
index 23608b3cf0a..f16c34bc2bc 100644
--- a/gcc/testsuite/gcc.target/i386/vperm-v4sf-1.c
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4sf-1.c
@@ -16,7 +16,7 @@ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
#define assert(T) ((T) || (__builtin_trap (), 0))
#define TEST(E0, E1, E2, E3) \
- b.v = __builtin_ia32_vec_perm_v4sf (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
+ b.v = __builtin_shuffle (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
c.s[0] = i[0].s[E0]; \
c.s[1] = i[0].s[E1]; \
c.s[2] = i[0].s[E2]; \
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4sf-2.c b/gcc/testsuite/gcc.target/i386/vperm-v4sf-2.c
index a0d49874f99..12a4623700b 100644
--- a/gcc/testsuite/gcc.target/i386/vperm-v4sf-2.c
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4sf-2.c
@@ -15,7 +15,7 @@ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
#define assert(T) ((T) || (__builtin_trap (), 0))
#define TEST(E0, E1, E2, E3) \
- b.v = __builtin_ia32_vec_perm_v4sf (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
+ b.v = __builtin_shuffle (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
c.s[0] = i[0].s[E0]; \
c.s[1] = i[0].s[E1]; \
c.s[2] = i[0].s[E2]; \
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4si-1.c b/gcc/testsuite/gcc.target/i386/vperm-v4si-1.c
index 01b7c6fdab6..4667f9556bf 100644
--- a/gcc/testsuite/gcc.target/i386/vperm-v4si-1.c
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4si-1.c
@@ -16,7 +16,7 @@ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
#define assert(T) ((T) || (__builtin_trap (), 0))
#define TEST(E0, E1, E2, E3) \
- b.v = __builtin_ia32_vec_perm_v4si (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
+ b.v = __builtin_shuffle (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
c.s[0] = i[0].s[E0]; \
c.s[1] = i[0].s[E1]; \
c.s[2] = i[0].s[E2]; \
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4si-2.c b/gcc/testsuite/gcc.target/i386/vperm-v4si-2.c
index 43f88ee0935..9304345559d 100644
--- a/gcc/testsuite/gcc.target/i386/vperm-v4si-2.c
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4si-2.c
@@ -15,7 +15,7 @@ extern int memcmp (const void *, const void *, __SIZE_TYPE__);
#define assert(T) ((T) || (__builtin_trap (), 0))
#define TEST(E0, E1, E2, E3) \
- b.v = __builtin_ia32_vec_perm_v4si (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
+ b.v = __builtin_shuffle (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
c.s[0] = i[0].s[E0]; \
c.s[1] = i[0].s[E1]; \
c.s[2] = i[0].s[E2]; \
diff --git a/gcc/testsuite/gcc.target/i386/warn-vect-op-1.c b/gcc/testsuite/gcc.target/i386/warn-vect-op-1.c
index f87cf5996fa..6fecf926208 100644
--- a/gcc/testsuite/gcc.target/i386/warn-vect-op-1.c
+++ b/gcc/testsuite/gcc.target/i386/warn-vect-op-1.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { ! { ia32 } } } } */
/* { dg-options "-mno-sse -Wvector-operation-performance" } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
diff --git a/gcc/testsuite/gcc.target/i386/warn-vect-op-2.c b/gcc/testsuite/gcc.target/i386/warn-vect-op-2.c
index f081d8a9dbe..6e631192445 100644
--- a/gcc/testsuite/gcc.target/i386/warn-vect-op-2.c
+++ b/gcc/testsuite/gcc.target/i386/warn-vect-op-2.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { ! { ia32 } } } } */
/* { dg-options "-mno-sse -Wvector-operation-performance" } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
diff --git a/gcc/testsuite/gcc.target/i386/warn-vect-op-3.c b/gcc/testsuite/gcc.target/i386/warn-vect-op-3.c
index ccb9e988451..bdbd8b520b7 100644
--- a/gcc/testsuite/gcc.target/i386/warn-vect-op-3.c
+++ b/gcc/testsuite/gcc.target/i386/warn-vect-op-3.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { ! { ia32 } } } } */
/* { dg-options "-mno-sse -Wvector-operation-performance" } */
#define vector(elcount, type) \
__attribute__((vector_size((elcount)*sizeof(type)))) type
diff --git a/gcc/testsuite/gcc.target/i386/xop-check.h b/gcc/testsuite/gcc.target/i386/xop-check.h
index 7e8e665c79f..395abe8766d 100644
--- a/gcc/testsuite/gcc.target/i386/xop-check.h
+++ b/gcc/testsuite/gcc.target/i386/xop-check.h
@@ -24,5 +24,5 @@ main ()
if (ecx & bit_XOP)
do_test ();
- exit (0);
+ return 0;
}
diff --git a/gcc/testsuite/gcc.target/i386/xop-mul-1.c b/gcc/testsuite/gcc.target/i386/xop-mul-1.c
new file mode 100644
index 00000000000..47ef1bc02bb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xop-mul-1.c
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+/* { dg-require-effective-target xop } */
+/* { dg-options "-O3 -mxop" } */
+
+#ifndef CHECK_H
+#define CHECK_H "xop-check.h"
+#endif
+
+#ifndef TEST
+#define TEST xop_test
+#endif
+
+#include "sse2-mul-1.c"
diff --git a/gcc/testsuite/gcc.target/i386/xop-vshift-1.c b/gcc/testsuite/gcc.target/i386/xop-vshift-1.c
new file mode 100644
index 00000000000..01198e88a42
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xop-vshift-1.c
@@ -0,0 +1,140 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mxop" } */
+/* { dg-require-effective-target xop } */
+
+#ifndef CHECK_H
+#define CHECK_H "xop-check.h"
+#endif
+
+#ifndef TEST
+#define TEST xop_test
+#endif
+
+#include CHECK_H
+
+#define N 64
+
+#ifndef TYPE1
+#define TYPE1 int
+#define TYPE2 long long
+#endif
+
+signed TYPE1 a[N], b[N], g[N];
+unsigned TYPE1 c[N], h[N];
+signed TYPE2 d[N], e[N], j[N];
+unsigned TYPE2 f[N], k[N];
+
+__attribute__((noinline)) void
+f1 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ g[i] = a[i] << b[i];
+}
+
+__attribute__((noinline)) void
+f2 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ g[i] = a[i] >> b[i];
+}
+
+__attribute__((noinline)) void
+f3 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ h[i] = c[i] >> b[i];
+}
+
+__attribute__((noinline)) void
+f4 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] << e[i];
+}
+
+__attribute__((noinline)) void
+f5 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] >> e[i];
+}
+
+__attribute__((noinline)) void
+f6 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ k[i] = f[i] >> e[i];
+}
+
+__attribute__((noinline)) void
+f7 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] << b[i];
+}
+
+__attribute__((noinline)) void
+f8 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ j[i] = d[i] >> b[i];
+}
+
+__attribute__((noinline)) void
+f9 (void)
+{
+ int i;
+ for (i = 0; i < N; i++)
+ k[i] = f[i] >> b[i];
+}
+
+static void
+TEST ()
+{
+ int i;
+ for (i = 0; i < N; i++)
+ {
+ asm ("");
+ c[i] = (random () << 1) | (random () & 1);
+ b[i] = (i * 85) & (sizeof (TYPE1) * __CHAR_BIT__ - 1);
+ a[i] = c[i];
+ d[i] = (random () << 1) | (random () & 1);
+ d[i] |= (unsigned long long) c[i] << 32;
+ e[i] = (i * 85) & (sizeof (TYPE2) * __CHAR_BIT__ - 1);
+ f[i] = d[i];
+ }
+ f1 ();
+ f3 ();
+ f4 ();
+ f6 ();
+ for (i = 0; i < N; i++)
+ if (g[i] != (signed TYPE1) (a[i] << b[i])
+ || h[i] != (unsigned TYPE1) (c[i] >> b[i])
+ || j[i] != (signed TYPE2) (d[i] << e[i])
+ || k[i] != (unsigned TYPE2) (f[i] >> e[i]))
+ abort ();
+ f2 ();
+ f5 ();
+ f9 ();
+ for (i = 0; i < N; i++)
+ if (g[i] != (signed TYPE1) (a[i] >> b[i])
+ || j[i] != (signed TYPE2) (d[i] >> e[i])
+ || k[i] != (unsigned TYPE2) (f[i] >> b[i]))
+ abort ();
+ f7 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != (signed TYPE2) (d[i] << b[i]))
+ abort ();
+ f8 ();
+ for (i = 0; i < N; i++)
+ if (j[i] != (signed TYPE2) (d[i] >> b[i]))
+ abort ();
+}
diff --git a/gcc/testsuite/gcc.target/i386/xop-vshift-2.c b/gcc/testsuite/gcc.target/i386/xop-vshift-2.c
new file mode 100644
index 00000000000..81e86d098e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/xop-vshift-2.c
@@ -0,0 +1,8 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mxop" } */
+/* { dg-require-effective-target xop } */
+
+#define TYPE1 char
+#define TYPE2 short
+
+#include "xop-vshift-1.c"
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c b/gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c
index c83c58298bd..3203704be7c 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fma-3.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mcpu=power6 -maltivec -ffast-math" } */
/* { dg-final { scan-assembler-times "vmaddfp" 2 } } */
/* { dg-final { scan-assembler-times "fmadd " 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c b/gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c
index 44da6e76bc4..35836eec234 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fma-4.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mcpu=power6 -maltivec -ffast-math -ffp-contract=off" } */
/* { dg-final { scan-assembler-times "vmaddfp" 1 } } */
/* { dg-final { scan-assembler-times "fmadd " 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c b/gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c
index 97243afb7c4..e5ba874e7ea 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fma-5.c
@@ -1,5 +1,6 @@
/* { dg-do run { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mcpu=power5 -std=c99" } */
#ifndef __FP_FAST_FMA
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c b/gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c
index ec0c3d74075..f6e7e4ce561 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fma-7.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mcpu=power6 -ffast-math" } */
/* { dg-final { scan-assembler-times "fmadd" 1 } } */
/* { dg-final { scan-assembler-times "fmsub " 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c
index 2eebbb42cdd..23b3d1e15e8 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-11.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mcpu=power5+ -ffast-math" } */
/* { dg-final { scan-assembler-not "xsrdpiz" } } */
/* { dg-final { scan-assembler "friz" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c
index 6196162a2ff..bf12113d28c 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-3.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mcpu=power5 -ffast-math" } */
/* { dg-final { scan-assembler-not "lfiwax" } } */
/* { dg-final { scan-assembler-not "lfiwzx" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c
index 007c8644a0c..808cbc39078 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -mcpu=power5 -ffast-math" } */
/* { dg-final { scan-assembler-times "fctiwz" 2 } } */
/* { dg-final { scan-assembler-not "fctiwuz" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c
index b5410f60ea5..f841d7ee073 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c
@@ -1,6 +1,7 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
/* { dg-require-effective-target ilp32 } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -mcpu=750 -ffast-math" } */
/* { dg-final { scan-assembler-times "fctiwz" 6 } } */
/* { dg-final { scan-assembler-not "fctiwuz" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-pow.c b/gcc/testsuite/gcc.target/powerpc/ppc-pow.c
index e88125c1d98..ee09d690f50 100644
--- a/gcc/testsuite/gcc.target/powerpc/ppc-pow.c
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-pow.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -ffast-math -mcpu=power6" } */
/* { dg-final { scan-assembler-times "fsqrt" 3 } } */
/* { dg-final { scan-assembler-times "fmul" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-1.c b/gcc/testsuite/gcc.target/powerpc/recip-1.c
index 590881bb892..4ae0c4f119f 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-1.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power6" } */
/* { dg-final { scan-assembler-times "frsqrte" 2 } } */
/* { dg-final { scan-assembler-times "fmsub" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-2.c b/gcc/testsuite/gcc.target/powerpc/recip-2.c
index 3e64c07578f..5c9fbbda510 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-2.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power5" } */
/* { dg-final { scan-assembler-times "frsqrtes" 1 } } */
/* { dg-final { scan-assembler-times "fmsubs" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-3.c b/gcc/testsuite/gcc.target/powerpc/recip-3.c
index 40658818047..905e793952e 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-3.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { { powerpc*-*-* } && { ! powerpc*-apple-darwin* } } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O2 -mrecip -ffast-math -mcpu=power7" } */
/* { dg-final { scan-assembler-times "xsrsqrtedp" 1 } } */
/* { dg-final { scan-assembler-times "xsmsub.dp\|fmsub\ " 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-4.c b/gcc/testsuite/gcc.target/powerpc/recip-4.c
index bd496d70e25..35eef6f0f0f 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-4.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-4.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mrecip -ffast-math -mcpu=power7 -fno-unroll-loops" } */
/* { dg-final { scan-assembler-times "xvrsqrtedp" 1 } } */
/* { dg-final { scan-assembler-times "xvmsub.dp" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/recip-5.c b/gcc/testsuite/gcc.target/powerpc/recip-5.c
index 4a9c496201a..0b3823cfa51 100644
--- a/gcc/testsuite/gcc.target/powerpc/recip-5.c
+++ b/gcc/testsuite/gcc.target/powerpc/recip-5.c
@@ -1,4 +1,5 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target powerpc_fprs } */
/* { dg-options "-O3 -ftree-vectorize -mrecip=all -ffast-math -mcpu=power7 -fno-unroll-loops" } */
/* { dg-final { scan-assembler-times "xvredp" 4 } } */
/* { dg-final { scan-assembler-times "xvresp" 5 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/warn-1.c b/gcc/testsuite/gcc.target/powerpc/warn-1.c
index c00aff08c6e..f4cb4372fdb 100644
--- a/gcc/testsuite/gcc.target/powerpc/warn-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/warn-1.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O -mvsx -mno-altivec" } */
/* { dg-warning "-mvsx and -mno-altivec are incompatible" "" { target *-*-* } 1 } */
diff --git a/gcc/testsuite/gcc.target/powerpc/warn-2.c b/gcc/testsuite/gcc.target/powerpc/warn-2.c
index 0a9fa1e3ff3..e8c9096f774 100644
--- a/gcc/testsuite/gcc.target/powerpc/warn-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/warn-2.c
@@ -1,5 +1,6 @@
/* { dg-do compile { target { powerpc*-*-* } } } */
/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
/* { dg-options "-O -mcpu=power7 -mno-altivec" } */
/* { dg-warning "-mno-altivec disables vsx" "" { target *-*-* } 1 } */
diff --git a/gcc/testsuite/gcc.target/sparc/20111102-1.c b/gcc/testsuite/gcc.target/sparc/20111102-1.c
new file mode 100644
index 00000000000..d33f103e377
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/20111102-1.c
@@ -0,0 +1,17 @@
+/* PR target/50945 */
+/* { dg-do compile } */
+/* { dg-options "-O -msoft-float" } */
+
+double
+__powidf2 (double x, int m)
+{
+ unsigned int n = m < 0 ? -m : m;
+ double y = n % 2 ? x : 1;
+ while (n >>= 1)
+ {
+ x = x * x;
+ if (n % 2)
+ y = y * x;
+ }
+ return m < 0 ? 1/y : y;
+}
diff --git a/gcc/testsuite/gcc.target/sparc/cmask.c b/gcc/testsuite/gcc.target/sparc/cmask.c
index 989274c6858..d1be910f5e0 100644
--- a/gcc/testsuite/gcc.target/sparc/cmask.c
+++ b/gcc/testsuite/gcc.target/sparc/cmask.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
void test_cm8 (long x)
{
diff --git a/gcc/testsuite/gcc.target/sparc/fand.c b/gcc/testsuite/gcc.target/sparc/fand.c
index 3194c921ccd..b0589bdbb3c 100644
--- a/gcc/testsuite/gcc.target/sparc/fand.c
+++ b/gcc/testsuite/gcc.target/sparc/fand.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return foo1_8 () & foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return a & b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return foo1_16 () & foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return a & b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,12 +38,9 @@ vec32 fun32(void)
return foo1_32 () & foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return a & b;
}
-#endif
-/* { dg-final { scan-assembler-times "fand\t%" 3 } } */
+/* { dg-final { scan-assembler-times "fand\t%" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fandnot.c b/gcc/testsuite/gcc.target/sparc/fandnot.c
index 41db849c239..005486385fa 100644
--- a/gcc/testsuite/gcc.target/sparc/fandnot.c
+++ b/gcc/testsuite/gcc.target/sparc/fandnot.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return ~foo1_8 () & foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return ~a & b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return ~foo1_16 () & foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return ~a & b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,13 +38,10 @@ vec32 fun32(void)
return ~foo1_32 () & foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return ~a & b;
}
-#endif
/* This should be transformed into ~b & a. */
@@ -59,38 +50,29 @@ vec8 fun8b(void)
return foo1_8 () & ~foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2b(vec8 a, vec8 b)
{
return a & ~b;
}
-#endif
vec16 fun16b(void)
{
return foo1_16 () & ~foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2b(vec16 a, vec16 b)
{
return a & ~b;
}
-#endif
vec32 fun32b(void)
{
return foo1_32 () & ~foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2b(vec32 a, vec32 b)
{
return a & ~b;
}
-#endif
-/* { dg-final { scan-assembler-times "fandnot1\t%" 6 } } */
+/* { dg-final { scan-assembler-times "fandnot1\t%" 12 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fhalve.c b/gcc/testsuite/gcc.target/sparc/fhalve.c
index 737fc71bbcf..b8f0745afc9 100644
--- a/gcc/testsuite/gcc.target/sparc/fhalve.c
+++ b/gcc/testsuite/gcc.target/sparc/fhalve.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
float test_fhadds (float x, float y)
{
diff --git a/gcc/testsuite/gcc.target/sparc/fmaf-1.c b/gcc/testsuite/gcc.target/sparc/fmaf-1.c
new file mode 100644
index 00000000000..948b9269e69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/fmaf-1.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mfmaf" } */
+
+float fmadds (float a, float b, float c)
+{
+ return a * b + c;
+}
+
+float fmsubs (float a, float b, float c)
+{
+ return a * b - c;
+}
+
+float fnmadds (float a, float b, float c)
+{
+ return -(a * b + c);
+}
+
+float fnmsubs (float a, float b, float c)
+{
+ return -(a * b - c);
+}
+
+double fmaddd (double a, double b, double c)
+{
+ return a * b + c;
+}
+
+double fmsubd (double a, double b, double c)
+{
+ return a * b - c;
+}
+
+double fnmaddd (double a, double b, double c)
+{
+ return -(a * b + c);
+}
+
+double fnmsubd (double a, double b, double c)
+{
+ return -(a * b - c);
+}
+
+/* { dg-final { scan-assembler "fmadds\t%" } } */
+/* { dg-final { scan-assembler "fmsubs\t%" } } */
+/* { dg-final { scan-assembler "fnmadds\t%" } } */
+/* { dg-final { scan-assembler "fnmsubs\t%" } } */
+/* { dg-final { scan-assembler "fmaddd\t%" } } */
+/* { dg-final { scan-assembler "fmsubd\t%" } } */
+/* { dg-final { scan-assembler "fnmaddd\t%" } } */
+/* { dg-final { scan-assembler "fnmsubd\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fnegop.c b/gcc/testsuite/gcc.target/sparc/fnegop.c
index 3e3e72c820c..cbdf28f4c60 100644
--- a/gcc/testsuite/gcc.target/sparc/fnegop.c
+++ b/gcc/testsuite/gcc.target/sparc/fnegop.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-O2 -mcpu=niagara3 -mvis" } */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mvis3" } */
float test_fnadds(float x, float y)
{
diff --git a/gcc/testsuite/gcc.target/sparc/fnot.c b/gcc/testsuite/gcc.target/sparc/fnot.c
index dceee52f7da..c0ddc931fbb 100644
--- a/gcc/testsuite/gcc.target/sparc/fnot.c
+++ b/gcc/testsuite/gcc.target/sparc/fnot.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return ~foo1_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a)
{
foo2_8 (~a);
}
-#endif
extern vec16 foo1_16(void);
extern void foo2_16(vec16);
@@ -29,13 +26,10 @@ vec16 fun16(void)
return ~foo1_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a)
{
foo2_16 (~a);
}
-#endif
extern vec32 foo1_32(void);
extern void foo2_32(vec32);
@@ -45,12 +39,9 @@ vec32 fun32(void)
return ~foo1_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a)
{
foo2_32 (~a);
}
-#endif
-/* { dg-final { scan-assembler-times "fnot1\t%" 3 } } */
+/* { dg-final { scan-assembler-times "fnot1\t%" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/for.c b/gcc/testsuite/gcc.target/sparc/for.c
index 7348dce2035..3da4bc23771 100644
--- a/gcc/testsuite/gcc.target/sparc/for.c
+++ b/gcc/testsuite/gcc.target/sparc/for.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return foo1_8 () | foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return a | b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return foo1_16 () | foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return a | b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,12 +38,9 @@ vec32 fun32(void)
return foo1_32 () | foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return a | b;
}
-#endif
-/* { dg-final { scan-assembler-times "for\t%" 3 } } */
+/* { dg-final { scan-assembler-times "for\t%" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fornot.c b/gcc/testsuite/gcc.target/sparc/fornot.c
index 09fdb4f98f3..2daa96e0a09 100644
--- a/gcc/testsuite/gcc.target/sparc/fornot.c
+++ b/gcc/testsuite/gcc.target/sparc/fornot.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return ~foo1_8 () | foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return ~a | b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return ~foo1_16 () | foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return ~a | b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,14 +38,10 @@ vec32 fun32(void)
return ~foo1_32 () | foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return ~a | b;
}
-#endif
-
/* This should be transformed into ~b | a. */
vec8 fun8b(void)
@@ -59,38 +49,29 @@ vec8 fun8b(void)
return foo1_8 () | ~foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2b(vec8 a, vec8 b)
{
return a | ~b;
}
-#endif
vec16 fun16b(void)
{
return foo1_16 () | ~foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2b(vec16 a, vec16 b)
{
return a | ~b;
}
-#endif
vec32 fun32b(void)
{
return foo1_32 () | ~foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2b(vec32 a, vec32 b)
{
return a | ~b;
}
-#endif
-/* { dg-final { scan-assembler-times "fornot1\t%" 6 } } */
+/* { dg-final { scan-assembler-times "fornot1\t%" 12 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fpadds.c b/gcc/testsuite/gcc.target/sparc/fpadds.c
index f55cb057a2a..9b1027d5fca 100644
--- a/gcc/testsuite/gcc.target/sparc/fpadds.c
+++ b/gcc/testsuite/gcc.target/sparc/fpadds.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
typedef int __v2si __attribute__((vector_size(8)));
typedef int __v1si __attribute__((vector_size(4)));
typedef short __v4hi __attribute__((vector_size(8)));
diff --git a/gcc/testsuite/gcc.target/sparc/fshift.c b/gcc/testsuite/gcc.target/sparc/fshift.c
index 6adbed69171..1f032151c16 100644
--- a/gcc/testsuite/gcc.target/sparc/fshift.c
+++ b/gcc/testsuite/gcc.target/sparc/fshift.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
typedef int __v2si __attribute__((vector_size(8)));
typedef short __v4hi __attribute__((vector_size(8)));
diff --git a/gcc/testsuite/gcc.target/sparc/fucmp.c b/gcc/testsuite/gcc.target/sparc/fucmp.c
index 4e7ecadcd4a..6e8f1b3418e 100644
--- a/gcc/testsuite/gcc.target/sparc/fucmp.c
+++ b/gcc/testsuite/gcc.target/sparc/fucmp.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
typedef unsigned char vec8 __attribute__((vector_size(8)));
long test_fucmple8 (vec8 a, vec8 b)
diff --git a/gcc/testsuite/gcc.target/sparc/fxnor.c b/gcc/testsuite/gcc.target/sparc/fxnor.c
index a685e08e04c..e635d65fdc4 100644
--- a/gcc/testsuite/gcc.target/sparc/fxnor.c
+++ b/gcc/testsuite/gcc.target/sparc/fxnor.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return ~(foo1_8 () ^ foo2_8 ());
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return ~(a ^ b);
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return ~(foo1_16 () ^ foo2_16 ());
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return ~(a ^ b);
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,13 +38,10 @@ vec32 fun32(void)
return ~(foo1_32 () ^ foo2_32 ());
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return ~(a ^ b);
}
-#endif
/* This should be transformed into ~(b ^ a). */
@@ -59,38 +50,29 @@ vec8 fun8b(void)
return foo1_8 () ^ ~foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2b(vec8 a, vec8 b)
{
return a ^ ~b;
}
-#endif
vec16 fun16b(void)
{
return foo1_16 () ^ ~foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2b(vec16 a, vec16 b)
{
return a ^ ~b;
}
-#endif
vec32 fun32b(void)
{
return foo1_32 () ^ ~foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2b(vec32 a, vec32 b)
{
return a ^ ~b;
}
-#endif
-/* { dg-final { scan-assembler-times "fxnor\t%" 6 } } */
+/* { dg-final { scan-assembler-times "fxnor\t%" 12 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/fxor.c b/gcc/testsuite/gcc.target/sparc/fxor.c
index 581b37b54fb..6ca2f76a1eb 100644
--- a/gcc/testsuite/gcc.target/sparc/fxor.c
+++ b/gcc/testsuite/gcc.target/sparc/fxor.c
@@ -12,13 +12,10 @@ vec8 fun8(void)
return foo1_8 () ^ foo2_8 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec8 fun8_2(vec8 a, vec8 b)
{
return a ^ b;
}
-#endif
extern vec16 foo1_16(void);
extern vec16 foo2_16(void);
@@ -28,13 +25,10 @@ vec16 fun16(void)
return foo1_16 () ^ foo2_16 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec16 fun16_2(vec16 a, vec16 b)
{
return a ^ b;
}
-#endif
extern vec32 foo1_32(void);
extern vec32 foo2_32(void);
@@ -44,12 +38,9 @@ vec32 fun32(void)
return foo1_32 () ^ foo2_32 ();
}
-#ifndef __LP64__
-/* Test the 32-bit splitter. */
vec32 fun32_2(vec32 a, vec32 b)
{
return a ^ b;
}
-#endif
-/* { dg-final { scan-assembler-times "fxor\t%" 3 } } */
+/* { dg-final { scan-assembler-times "fxor\t%" 6 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/lzd.c b/gcc/testsuite/gcc.target/sparc/lzd.c
index 5ffaf56e558..bc2b8522be8 100644
--- a/gcc/testsuite/gcc.target/sparc/lzd.c
+++ b/gcc/testsuite/gcc.target/sparc/lzd.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-mcpu=niagara3" } */
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
int test_clz(int a)
{
return __builtin_clz(a);
diff --git a/gcc/testsuite/gcc.target/sparc/setcc-1.c b/gcc/testsuite/gcc.target/sparc/setcc-1.c
new file mode 100644
index 00000000000..6065bbb1326
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/setcc-1.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+int neq (int a, int b)
+{
+ return a != b;
+}
+
+int eq (int a, int b)
+{
+ return a == b;
+}
+
+int lt (unsigned int a, unsigned int b)
+{
+ return a < b;
+}
+
+int leq (unsigned int a, unsigned int b)
+{
+ return a <= b;
+}
+
+int geq (unsigned int a, unsigned int b)
+{
+ return a >= b;
+}
+
+int gt (unsigned int a, unsigned int b)
+{
+ return a > b;
+}
+
+/* { dg-final { scan-assembler-times "xor\t%" 2 } } */
+/* { dg-final { scan-assembler-times "subcc\t%" 2 } } */
+/* { dg-final { scan-assembler-times "addx\t%" 3 } } */
+/* { dg-final { scan-assembler-times "subx\t%" 3 } } */
+/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */
+/* { dg-final { scan-assembler-not "sra\t%" { target lp64 } } } */
diff --git a/gcc/testsuite/gcc.target/sparc/setcc-2.c b/gcc/testsuite/gcc.target/sparc/setcc-2.c
new file mode 100644
index 00000000000..cc17c65f0d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/setcc-2.c
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+
+int neq (int a, int b)
+{
+ return -(a != b);
+}
+
+int eq (int a, int b)
+{
+ return -(a == b);
+}
+
+int lt (unsigned int a, unsigned int b)
+{
+ return -(a < b);
+}
+
+int leq (unsigned int a, unsigned int b)
+{
+ return -(a <= b);
+}
+
+int geq (unsigned int a, unsigned int b)
+{
+ return -(a >= b);
+}
+
+int gt (unsigned int a, unsigned int b)
+{
+ return -(a > b);
+}
+
+/* { dg-final { scan-assembler-times "xor\t%" 2 } } */
+/* { dg-final { scan-assembler-times "subcc\t%" 2 } } */
+/* { dg-final { scan-assembler-times "addx\t%" 3 } } */
+/* { dg-final { scan-assembler-times "subx\t%" 3 } } */
+/* { dg-final { scan-assembler-times "cmp\t%" 4 } } */
+/* { dg-final { scan-assembler-not "sra\t%" { target lp64 } } } */
diff --git a/gcc/testsuite/gcc.target/sparc/setcc-3.c b/gcc/testsuite/gcc.target/sparc/setcc-3.c
new file mode 100644
index 00000000000..8a26b675b63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/setcc-3.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O1 -mvis3" } */
+
+int neq (long a, long b)
+{
+ return a != b;
+}
+
+int lt (unsigned long a, unsigned long b)
+{
+ return a < b;
+}
+
+int gt (unsigned long a, unsigned long b)
+{
+ return a > b;
+}
+
+/* { dg-final { scan-assembler "xor\t%" } } */
+/* { dg-final { scan-assembler "subcc\t%" } } */
+/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */
+/* { dg-final { scan-assembler-times "cmp\t%" 2 } } */
+/* { dg-final { scan-assembler-not "sra\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/vis3misc.c b/gcc/testsuite/gcc.target/sparc/vis3misc.c
index e3ef49e210d..7286d705dd5 100644
--- a/gcc/testsuite/gcc.target/sparc/vis3misc.c
+++ b/gcc/testsuite/gcc.target/sparc/vis3misc.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
typedef int __v2si __attribute__((vector_size(8)));
typedef short __v4hi __attribute__((vector_size(8)));
typedef unsigned char __v8qi __attribute__((vector_size(8)));
diff --git a/gcc/testsuite/gcc.target/sparc/vis3move-1.c b/gcc/testsuite/gcc.target/sparc/vis3move-1.c
new file mode 100644
index 00000000000..1265d886689
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/vis3move-1.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O1 -mvis3" } */
+
+double d;
+float f;
+
+int test_convert_from_float(void)
+{
+ return f;
+}
+
+int test_convert_from_double(void)
+{
+ return d;
+}
+
+float test_convert_to_float(int x)
+{
+ return x;
+}
+
+double test_convert_to_double(int x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "movstouw\t%" 2 } } */
+/* { dg-final { scan-assembler-times "movwtos\t%" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/vis3move-2.c b/gcc/testsuite/gcc.target/sparc/vis3move-2.c
new file mode 100644
index 00000000000..de793076516
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/vis3move-2.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-O1 -mvis3" } */
+
+double d;
+float f;
+
+long test_convert_from_float(void)
+{
+ return f;
+}
+
+long test_convert_from_double(void)
+{
+ return d;
+}
+
+float test_convert_to_float(long x)
+{
+ return x;
+}
+
+double test_convert_to_double(long x)
+{
+ return x;
+}
+
+/* { dg-final { scan-assembler-times "movdtox\t%" 2 } } */
+/* { dg-final { scan-assembler-times "movxtod\t%" 2 } } */
diff --git a/gcc/testsuite/gcc.target/sparc/vis3move-3.c b/gcc/testsuite/gcc.target/sparc/vis3move-3.c
new file mode 100644
index 00000000000..3b2116eec0c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/vis3move-3.c
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target ilp32 } */
+/* { dg-options "-O1 -mvis3" } */
+
+float fnegs (float a)
+{
+ return -a;
+}
+
+double fnegd (double a)
+{
+ return -a;
+}
+
+float fmuls (float a, float b)
+{
+ return a * b;
+}
+
+double fmuld (double a, double b)
+{
+ return a * b;
+}
+
+double fsmuld (float a, float b)
+{
+ return (double)a * (double)b;
+}
+
+double fnsmuld (float a, float b)
+{
+ return -((double)a * (double)b);
+}
+
+/* { dg-final { scan-assembler-times "movwtos\t%" 13 } } */
+/* { dg-final { scan-assembler "fnegs\t%" } } */
+/* { dg-final { scan-assembler "fnegd\t%" } } */
+/* { dg-final { scan-assembler "fmuls\t%" } } */
+/* { dg-final { scan-assembler "fmuld\t%" } } */
+/* { dg-final { scan-assembler "fsmuld\t%" } } */
+/* { dg-final { scan-assembler "fnsmuld\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/xmul.c b/gcc/testsuite/gcc.target/sparc/xmul.c
index 5d249d092db..a432ee1fec1 100644
--- a/gcc/testsuite/gcc.target/sparc/xmul.c
+++ b/gcc/testsuite/gcc.target/sparc/xmul.c
@@ -1,5 +1,5 @@
-/* { dg-do compile { target { vis3 } } } */
-/* { dg-options "-mcpu=niagara3 -mvis" } */
+/* { dg-do compile } */
+/* { dg-options "-mvis3" } */
typedef long long int64_t;
int64_t test_umulxhi (int64_t x, int64_t y)
diff --git a/gcc/testsuite/gfortran.dg/bind_c_usage_22.f90 b/gcc/testsuite/gfortran.dg/bind_c_usage_22.f90
index 861f8c7cfd8..5a5771c7a0f 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_usage_22.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_usage_22.f90
@@ -1,10 +1,10 @@
! { dg-do compile }
-! { dg-options "-std=f2008tr" }
+! { dg-options "-std=f2008ts" }
!
! PR fortran/48858
! PR fortran/48820
!
-! OPTIONAL + BIND(C) is allowed since TR 29113
+! OPTIONAL + BIND(C) is allowed since TS 29113
!
! VALID
@@ -13,20 +13,20 @@ subroutine sub(z) bind(C)
integer(c_int), value :: z
end subroutine sub
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2(z) bind(C)
use iso_c_binding
integer(c_int), optional :: z
end subroutine sub2
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2a(z) bind(C)
use iso_c_binding
integer(c_int) :: z
optional :: z
end subroutine sub2a
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2b(z) bind(C)
use iso_c_binding
optional :: z
diff --git a/gcc/testsuite/gfortran.dg/bind_c_usage_23.f90 b/gcc/testsuite/gfortran.dg/bind_c_usage_23.f90
index 374f8129136..3917b9d3001 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_usage_23.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_usage_23.f90
@@ -4,7 +4,7 @@
! PR fortran/48858
! PR fortran/48820
!
-! OPTIONAL + BIND(C) is allowed since TR 29113
+! OPTIONAL + BIND(C) is allowed since TS 29113
!
! VALID
@@ -13,20 +13,20 @@ subroutine sub(z) bind(C)
integer(c_int), value :: z
end subroutine sub
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2(z) bind(C) ! { dg-error "with OPTIONAL attribute in procedure" }
use iso_c_binding
integer(c_int), optional :: z
end subroutine sub2
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2a(z) bind(C) ! { dg-error "with OPTIONAL attribute in procedure" }
use iso_c_binding
integer(c_int) :: z
optional :: z
end subroutine sub2a
-! VALID since TR29113
+! VALID since TS29113
subroutine sub2b(z) bind(C) ! { dg-error "with OPTIONAL attribute in procedure" }
use iso_c_binding
optional :: z
diff --git a/gcc/testsuite/gfortran.dg/bind_c_usage_24.f90 b/gcc/testsuite/gfortran.dg/bind_c_usage_24.f90
index 703ab5f19fa..a6ebd5833c1 100644
--- a/gcc/testsuite/gfortran.dg/bind_c_usage_24.f90
+++ b/gcc/testsuite/gfortran.dg/bind_c_usage_24.f90
@@ -4,7 +4,7 @@
! PR fortran/48858
! PR fortran/48820
!
-! TR 29113: BIND(C) with OPTIONAL
+! TS 29113: BIND(C) with OPTIONAL
!
module m
use iso_c_binding
diff --git a/gcc/testsuite/gfortran.dg/c_kind_tests_3.f03 b/gcc/testsuite/gfortran.dg/c_kind_tests_3.f03
new file mode 100644
index 00000000000..5d5f3ab195f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_kind_tests_3.f03
@@ -0,0 +1,11 @@
+! { dg-do compile }
+!
+! PR 47023: [4.6/4.7 regression] C_Sizeof: Rejects valid code
+!
+! Contributed by <florian.rathgeber@gmail.com>
+
+ use iso_c_binding
+ real(c_double) x
+ print *, c_sizeof(x)
+ print *, c_sizeof(0.0_c_double)
+end
diff --git a/gcc/testsuite/gfortran.dg/coarray/subobject_1.f90 b/gcc/testsuite/gfortran.dg/coarray/subobject_1.f90
new file mode 100644
index 00000000000..02536866b4d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/subobject_1.f90
@@ -0,0 +1,43 @@
+! { dg-do run }
+!
+! PR fortran/50420
+! Coarray subobjects were not accepted as valid coarrays
+
+ integer :: i
+ integer, parameter :: la = 4, lb = 5, lc = 8
+ integer, parameter :: init(la) = -4 + (/ (i, i=1,la) /)
+
+ type t
+ integer :: i
+ end type t
+ type t2
+ type(t), allocatable :: a[:]
+ end type t2
+ type t3
+ type(t), allocatable :: a(:)[:]
+ end type t3
+
+ type(t2) :: b
+ type(t3) :: c
+
+ allocate(b%a[lb:*])
+ b%a%i = 7
+ if (b%a%i /= 7) call abort
+ if (any (lcobound(b%a) /= (/ lb /))) call abort
+ if (ucobound(b%a, dim=1) /= this_image() + lb - 1) call abort
+ if (any (lcobound(b%a%i) /= (/ lb /))) call abort
+ if (ucobound(b%a%i, dim=1) /= this_image() + lb - 1) call abort
+ allocate(c%a(la)[lc:*])
+ c%a%i = init
+ if (any(c%a%i /= init)) call abort
+ if (any (lcobound(c%a) /= (/ lc /))) call abort
+ if (ucobound(c%a, dim=1) /= this_image() + lc - 1) call abort
+ if (any (lcobound(c%a%i) /= (/ lc /))) call abort
+ if (ucobound(c%a%i, dim=1) /= this_image() + lc - 1) call abort
+ if (c%a(2)%i /= init(2)) call abort
+ if (any (lcobound(c%a(2)) /= (/ lc /))) call abort
+ if (ucobound(c%a(2), dim=1) /= this_image() + lc - 1) call abort
+ if (any (lcobound(c%a(2)%i) /= (/ lc /))) call abort
+ if (ucobound(c%a(2)%i, dim=1) /= this_image() + lc - 1) call abort
+ deallocate(b%a, c%a)
+end
diff --git a/gcc/testsuite/gfortran.dg/coarray_subobject_1.f90 b/gcc/testsuite/gfortran.dg/coarray_subobject_1.f90
new file mode 100644
index 00000000000..52c65e149b5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray_subobject_1.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+! { dg-options "-fcoarray=single" }
+!
+! PR fortran/50420
+! Coarray subobjects were not accepted as valid coarrays
+! They should still be rejected if one of the component reference is allocatable
+! or pointer
+
+type t
+ integer :: i
+end type t
+type t2
+ type(t), allocatable :: a
+ type(t), pointer :: c
+end type t2
+type(t2) :: b[5:*]
+allocate(b%a)
+allocate(b%c)
+b%a%i = 7
+b%c%i = 13
+if (b%a%i /= 7) call abort
+if (any (lcobound(b%a) /= (/ 5 /))) call abort ! { dg-error "Expected coarray variable" }
+if (ucobound(b%a, dim=1) /= this_image() + 4) call abort ! { dg-error "Expected coarray variable" }
+if (any (lcobound(b%a%i) /= (/ 5 /))) call abort ! { dg-error "Expected coarray variable" }
+if (ucobound(b%a%i, dim=1) /= this_image() + 4) call abort ! { dg-error "Expected coarray variable" }
+if (b%c%i /= 13) call abort
+if (any (lcobound(b%c) /= (/ 5 /))) call abort ! { dg-error "Expected coarray variable" }
+if (ucobound(b%c, dim=1) /= this_image() + 4) call abort ! { dg-error "Expected coarray variable" }
+if (any (lcobound(b%c%i) /= (/ 5 /))) call abort ! { dg-error "Expected coarray variable" }
+if (ucobound(b%c%i, dim=1) /= this_image() + 4) call abort ! { dg-error "Expected coarray variable" }
+end
diff --git a/gcc/testsuite/gfortran.dg/dshift_3.f90 b/gcc/testsuite/gfortran.dg/dshift_3.f90
new file mode 100644
index 00000000000..1f214c7d1c7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dshift_3.f90
@@ -0,0 +1,34 @@
+! { dg-do compile }
+! PR fortran/50753
+subroutine foo(i, j, k)
+
+ implicit none
+
+ integer(4), intent(in) :: i, j
+ integer(8), intent(in) :: k
+
+ print *, dshiftl(i, j, 134) ! { dg-error "must be less than or equal" }
+ print *, dshiftl(z'FFF', j, 134) ! { dg-error "must be less than or equal" }
+ print *, dshiftl(i, j, -10) ! { dg-error "must be nonnegative" }
+ print *, dshiftl(z'FFF', z'EEE', 10) ! { dg-error "cannot both be" }
+ print *, dshiftl(z'FFF', j, 10)
+ print *, dshiftl(i, z'EEE', 10)
+ print *, dshiftl(i, j, 10)
+ print *, dshiftl(i, k, 10) ! { dg-error "must be the same type and kind" }
+ print *, dshiftl(k, j, 10) ! { dg-error "must be the same type and kind" }
+ print *, dshiftl(i, j, k)
+ print *, dshiftl(i, j, z'd')
+
+ print *, dshiftr(i, j, 134) ! { dg-error "must be less than or equal" }
+ print *, dshiftr(z'FFF', j, 134) ! { dg-error "must be less than or equal" }
+ print *, dshiftr(i, j, -10) ! { dg-error "must be nonnegative" }
+ print *, dshiftr(z'FFF', z'EEE', 10) ! { dg-error "cannot both be" }
+ print *, dshiftr(z'FFF', j, 10)
+ print *, dshiftr(i, z'EEE', 10)
+ print *, dshiftr(i, j, 10)
+ print *, dshiftr(i, k, 10) ! { dg-error "must be the same type and kind" }
+ print *, dshiftr(k, j, 10) ! { dg-error "must be the same type and kind" }
+ print *, dshiftr(i, j, k)
+ print *, dshiftr(i, j, z'd')
+
+end subroutine foo
diff --git a/gcc/testsuite/gfortran.dg/elemental_args_check_4.f90 b/gcc/testsuite/gfortran.dg/elemental_args_check_4.f90
new file mode 100644
index 00000000000..2c50f58de2d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/elemental_args_check_4.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+!
+! PR 50547: dummy procedure argument of PURE shall be PURE
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+elemental function fun (sub)
+ interface
+ pure subroutine sub ! { dg-error "not allowed in elemental procedure" }
+ end subroutine
+ end interface
+end function
diff --git a/gcc/testsuite/gfortran.dg/format_string.f b/gcc/testsuite/gfortran.dg/format_string.f
new file mode 100644
index 00000000000..ff0b5388ce9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/format_string.f
@@ -0,0 +1,31 @@
+c { dg-do compile }
+c PR fortran/50407
+c
+ program bar
+
+ interface operator (.ip.)
+ function mul (i1, i2)
+ character(20) mul
+ intent(in) :: i1,i2
+ end function
+ end interface
+
+ character(20) foo
+ i=3
+ j=4
+ print 2.ip.8 ! compiles fine
+ print i.ip.2 ! compiles fine
+ print i.ip.j ! compiles fine
+ foo = 1_'(I0,I4.4)'
+ print foo, i,j
+ print 1_'(I0,1X,I4.4)', i, j
+ end
+
+ function mul (i1, i2)
+ character(20) mul
+ intent(in) :: i1,i2
+ integer prod
+ prod=i1*i2
+ write(mul,100) prod
+100 format("('ok ",i2,"')")
+ end function
diff --git a/gcc/testsuite/gfortran.dg/inquire_5.f90 b/gcc/testsuite/gfortran.dg/inquire_5.f90
index fe107a19863..2be3a34c3f3 100644
--- a/gcc/testsuite/gfortran.dg/inquire_5.f90
+++ b/gcc/testsuite/gfortran.dg/inquire_5.f90
@@ -1,11 +1,10 @@
! { dg-do run { target fd_truncate } }
-! { dg-options "-std=legacy" }
!
! pr19314 inquire(..position=..) segfaults
! test by Thomas.Koenig@online.de
! bdavis9659@comcast.net
implicit none
- character*20 chr
+ character(len=20) chr
open(7,STATUS='SCRATCH')
inquire(7,position=chr)
if (chr.NE.'ASIS') CALL ABORT
@@ -31,7 +30,7 @@
write(7,*)'this is another record'
backspace(7)
inquire(7,position=chr)
- if (chr.NE.'ASIS') CALL ABORT
+ if (chr .NE. 'UNSPECIFIED') CALL ABORT
rewind(7)
inquire(7,position=chr)
if (chr.NE.'REWIND') CALL ABORT
diff --git a/gcc/testsuite/gfortran.dg/ishft_3.f90 b/gcc/testsuite/gfortran.dg/ishft_3.f90
index fa3938ef9f0..626e71ce44e 100644
--- a/gcc/testsuite/gfortran.dg/ishft_3.f90
+++ b/gcc/testsuite/gfortran.dg/ishft_3.f90
@@ -1,11 +1,38 @@
! { dg-do compile }
+! PR fortran/50514
program ishft_3
- integer i, j
- write(*,*) ishftc( 3, 2, 3 )
- write(*,*) ishftc( 3, 2, i )
- write(*,*) ishftc( 3, i, j )
- write(*,*) ishftc( 3, 128 ) ! { dg-error "exceeds BIT_SIZE of first" }
- write(*,*) ishftc( 3, 0, 128 ) ! { dg-error "exceeds BIT_SIZE of first" }
- write(*,*) ishftc( 3, 0, 0 ) ! { dg-error "Invalid third argument" }
- write(*,*) ishftc( 3, 3, 2 ) ! { dg-error "exceeds third argument" }
+
+ implicit none
+
+ integer j, m
+
+ m = 42
+ !
+ ! These should compile.
+ !
+ j = ishft(m, 16)
+ j = ishft(m, -16)
+ j = ishftc(m, 16)
+ j = ishftc(m, -16)
+ !
+ ! These should issue an error.
+ !
+ j = ishft(m, 640) ! { dg-error "absolute value of SHIFT" }
+ j = ishftc(m, 640) ! { dg-error "absolute value of SHIFT" }
+ j = ishft(m, -640) ! { dg-error "absolute value of SHIFT" }
+ j = ishftc(m, -640) ! { dg-error "absolute value of SHIFT" }
+
+ ! abs(SHIFT) must be <= SIZE
+
+ j = ishftc(m, 1, 2)
+ j = ishftc(m, 1, 2)
+ j = ishftc(m, -1, 2)
+ j = ishftc(m, -1, 2)
+
+ j = ishftc(m, 10, 2)! { dg-error "absolute value of SHIFT" }
+ j = ishftc(m, 10, 2)! { dg-error "absolute value of SHIFT" }
+ j = ishftc(m, -10, 2)! { dg-error "absolute value of SHIFT" }
+ j = ishftc(m, -10, 2)! { dg-error "absolute value of SHIFT" }
+
+ j = ishftc(m, 1, -2) ! { dg-error "must be positive" }
end program
diff --git a/gcc/testsuite/gfortran.dg/iso_c_binding_class.f03 b/gcc/testsuite/gfortran.dg/iso_c_binding_class.f03
new file mode 100644
index 00000000000..bfb05bcc89b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/iso_c_binding_class.f03
@@ -0,0 +1,15 @@
+! { dg-do compile }
+!
+! PR 47023: C_Sizeof: Rejects valid code
+!
+! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
+
+ use iso_c_binding
+ type t
+ integer(c_int) :: i
+ end type t
+contains
+ subroutine test(a) bind(c) ! { dg-error "is not C interoperable" }
+ class(t) :: a
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/kind_tests_4.f90 b/gcc/testsuite/gfortran.dg/kind_tests_4.f90
new file mode 100644
index 00000000000..050c15a282b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/kind_tests_4.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+!
+! PR 50752: [4.7 Regression] ICE in match_kind_param
+!
+! Contributed by Joost VandeVondele <Joost.VandeVondele@pci.uzh.ch>
+
+rPos=0.0_dp ! { dg-error "Missing kind-parameter" }
+end
diff --git a/gcc/testsuite/gfortran.dg/nearest_5.f90 b/gcc/testsuite/gfortran.dg/nearest_5.f90
new file mode 100644
index 00000000000..dbb0b7209af
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/nearest_5.f90
@@ -0,0 +1,10 @@
+! { dg-do compile }
+program a
+ real x, y(2)
+ x = 1./3.
+ y = [1, 2] / 3.
+ print *, nearest(x, 0.) ! { dg-error "shall not be zero" }
+ print *, nearest(y, 0.) ! { dg-error "shall not be zero" }
+ print *, nearest([1., 2.] / 3., 0.) ! { dg-error "shall not be zero" }
+ print *, nearest(1., 0.) ! { dg-error "shall not be zero" }
+end program a
diff --git a/gcc/testsuite/gfortran.dg/pointer_check_11.f90 b/gcc/testsuite/gfortran.dg/pointer_check_11.f90
new file mode 100644
index 00000000000..b6aa79ae260
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_check_11.f90
@@ -0,0 +1,24 @@
+! { dg-do run }
+! { dg-options "-fcheck=all" }
+!
+! { dg-shouldfail "Pointer check" }
+! { dg-output "Fortran runtime error: Pointer actual argument 'y' is not associated" }
+!
+!
+! PR fortran/50718
+!
+! Was failing (ICE) with -fcheck=pointer if the dummy had the value attribute.
+
+type t
+ integer :: p
+end type t
+
+type(t), pointer :: y => null()
+
+call sub(y) ! Invalid: Nonassociated pointer
+
+contains
+ subroutine sub (x)
+ type(t), value :: x
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/pointer_check_12.f90 b/gcc/testsuite/gfortran.dg/pointer_check_12.f90
new file mode 100644
index 00000000000..cfef70e5999
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_check_12.f90
@@ -0,0 +1,22 @@
+! { dg-do run }
+! { dg-options "-fcheck=all" }
+!
+! { dg-shouldfail "Pointer check" }
+! { dg-output "Fortran runtime error: Pointer actual argument 'p' is not associated" }
+!
+! PR fortran/50718
+!
+! Was failing with -fcheck=pointer: Segfault at run time
+
+integer, pointer :: p => null()
+
+call sub2(%val(p)) ! Invalid: Nonassociated pointer
+end
+
+! Not quite correct dummy, but if one uses VALUE, gfortran
+! complains about a missing interface - which we cannot use
+! if we want to use %VAL().
+
+subroutine sub2(p)
+ integer :: p
+end subroutine sub2
diff --git a/gcc/testsuite/gfortran.dg/pointer_intent_5.f90 b/gcc/testsuite/gfortran.dg/pointer_intent_5.f90
new file mode 100644
index 00000000000..c4e3c7a3c1d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pointer_intent_5.f90
@@ -0,0 +1,24 @@
+! { dg-do run }
+!
+! PR 50570: [4.6/4.7 Regression] Incorrect error for assignment to intent(in) pointer
+!
+! Contributed by Bill Long <longb@cray.com>
+
+program bots_sparselu_pointer_intent_in
+
+ implicit none
+ integer, pointer :: array(:)
+
+ allocate(array(4))
+ array = 0
+ call sub(array)
+ if (sum(array)/=1) call abort
+
+contains
+
+ subroutine sub(dummy)
+ integer, pointer, intent(in) :: dummy(:)
+ dummy(1) = 1
+ end subroutine sub
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/pr50875.f90 b/gcc/testsuite/gfortran.dg/pr50875.f90
new file mode 100644
index 00000000000..6b4476c14e4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr50875.f90
@@ -0,0 +1,39 @@
+! { dg-do compile { target { i?86-*-* x86_64-*-* } } }
+! { dg-options "-O3 -mavx" }
+!
+! PR fortran/50875.f90
+
+module test
+
+ implicit none
+
+ integer, parameter :: dp=kind(1.d0)
+
+ integer :: P = 2
+
+ real(kind=dp), allocatable :: real_array_A(:),real_array_B(:,:)
+ complex(kind=dp), allocatable :: cmplx_array_A(:)
+
+contains
+
+ subroutine routine_A
+
+ integer :: i
+
+ allocate(cmplx_array_A(P),real_array_B(P,P),real_array_A(P))
+
+ real_array_A = 1
+ real_array_B = 1
+
+ do i = 1, p
+ cmplx_array_A = cmplx(real_array_B(:,i),0.0_dp,dp)
+ cmplx_array_A = cmplx_array_A * exp(cmplx(0.0_dp,real_array_A+1))
+ end do
+
+ deallocate(cmplx_array_A,real_array_B,real_array_A)
+
+ end subroutine routine_A
+
+end module test
+
+! { dg-final { cleanup-modules "test" } }
diff --git a/gcc/testsuite/gfortran.dg/rank_3.f90 b/gcc/testsuite/gfortran.dg/rank_3.f90
index fac2185a9fe..c8f8fa77508 100644
--- a/gcc/testsuite/gfortran.dg/rank_3.f90
+++ b/gcc/testsuite/gfortran.dg/rank_3.f90
@@ -3,5 +3,5 @@
!
! PR fortran/48820
!
-intrinsic :: rank ! { dg-error "new in TR 29113" }
+intrinsic :: rank ! { dg-error "new in TS 29113" }
end
diff --git a/gcc/testsuite/gfortran.dg/rank_4.f90 b/gcc/testsuite/gfortran.dg/rank_4.f90
index 40b0209da95..a370df01c7d 100644
--- a/gcc/testsuite/gfortran.dg/rank_4.f90
+++ b/gcc/testsuite/gfortran.dg/rank_4.f90
@@ -1,5 +1,5 @@
! { dg-do compile }
-! { dg-options "-std=f2008tr -fdump-tree-original" }
+! { dg-options "-std=f2008ts -fdump-tree-original" }
!
! PR fortran/48820
!
diff --git a/gcc/testsuite/gfortran.dg/sizeof_proc.f90 b/gcc/testsuite/gfortran.dg/sizeof_proc.f90
new file mode 100644
index 00000000000..b4a2d732003
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/sizeof_proc.f90
@@ -0,0 +1,28 @@
+! { dg-do compile }
+!
+! PR 47023: C_Sizeof: Rejects valid code
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+use iso_c_binding
+procedure(real) :: proc
+procedure(real), pointer :: pp
+pp => sin
+
+print *,sizeof(proc) ! { dg-error "may not be a procedure" }
+print *,sizeof(pp) ! { dg-error "may not be a procedure" }
+print *,sizeof(pp(0.))
+print *,sizeof(sub) ! { dg-error "may not be a procedure" }
+print *,sizeof(func) ! { dg-error "may not be a procedure" }
+print *,sizeof(func())
+
+contains
+
+ subroutine sub
+ end subroutine
+
+ real function func()
+ func = 0.
+ end function
+
+end
diff --git a/gcc/testsuite/gfortran.dg/substring_integer_index.f90 b/gcc/testsuite/gfortran.dg/substring_integer_index.f90
new file mode 100644
index 00000000000..a730a75f36b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/substring_integer_index.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! PR fortran/50524
+!
+program foo
+ print *, 'abc'(2.e0:3) ! { dg-error "must be of type INTEGER" }
+ print *,'qwe'(1:1e0) ! { dg-error "must be of type INTEGER" }
+end program foo
+
diff --git a/gcc/testsuite/gfortran.fortran-torture/compile/logical-2.f90 b/gcc/testsuite/gfortran.fortran-torture/compile/logical-2.f90
new file mode 100644
index 00000000000..c31443f9468
--- /dev/null
+++ b/gcc/testsuite/gfortran.fortran-torture/compile/logical-2.f90
@@ -0,0 +1,10 @@
+! Check for operand type validity after gimplification
+
+subroutine whatever()
+logical(kind=1) :: l1
+logical(kind=2) :: l2
+logical(kind=4) :: l3
+if ((l1 .and. l2) .neqv. l3) then
+ l1 = .true.
+endif
+end
diff --git a/gcc/testsuite/gnat.dg/source_ref1.adb b/gcc/testsuite/gnat.dg/source_ref1.adb
new file mode 100644
index 00000000000..fd450cc45db
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/source_ref1.adb
@@ -0,0 +1,6 @@
+pragma Source_Reference (3, "p1.adb");
+
+procedure Source_Ref1 is
+begin
+ null;
+end;
diff --git a/gcc/testsuite/gnat.dg/source_ref2.adb b/gcc/testsuite/gnat.dg/source_ref2.adb
new file mode 100644
index 00000000000..cc2d57655e2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/source_ref2.adb
@@ -0,0 +1,7 @@
+pragma Source_Reference (1, "p2.adb");
+
+procedure Source_Ref2 is
+pragma Source_Reference (2, "p2.adb");
+begin
+ null;
+end;
diff --git a/gcc/testsuite/gnat.dg/specs/atomic1.ads b/gcc/testsuite/gnat.dg/specs/atomic1.ads
new file mode 100644
index 00000000000..500cad787f3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/atomic1.ads
@@ -0,0 +1,16 @@
+-- { dg-do compile }
+
+package Atomic1 is
+
+ type Arr is array (Integer range <>) of Boolean;
+ type UA is access all Arr;
+
+ U : UA;
+ pragma Atomic (U); -- { dg-error "atomic access" }
+
+ type R is record
+ U : UA;
+ pragma Atomic (U); -- { dg-error "atomic access" }
+ end record;
+
+end Atomic1;
diff --git a/gcc/testsuite/gnat.dg/specs/debug1.ads b/gcc/testsuite/gnat.dg/specs/debug1.ads
index ef7a86e3ddb..2fdc6e13e91 100644
--- a/gcc/testsuite/gnat.dg/specs/debug1.ads
+++ b/gcc/testsuite/gnat.dg/specs/debug1.ads
@@ -11,4 +11,4 @@ package Debug1 is
end Debug1;
--- { dg-final { scan-assembler-times "# DW_AT_artificial" 4 } }
+-- { dg-final { scan-assembler-times "DW_AT_artificial" 8 } }
diff --git a/gcc/testsuite/gnat.dg/specs/discr1.ads b/gcc/testsuite/gnat.dg/specs/discr1.ads
new file mode 100644
index 00000000000..2e0207675b8
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/discr1.ads
@@ -0,0 +1,10 @@
+-- { dg-do compile }
+-- { dg-options "-gnatct" }
+
+with Discr1_Pkg; use Discr1_Pkg;
+
+package Discr1 is
+
+ procedure Proc (V : Variable_String_Array);
+
+end Discr1;
diff --git a/gcc/testsuite/gnat.dg/specs/discr1_pkg.ads b/gcc/testsuite/gnat.dg/specs/discr1_pkg.ads
new file mode 100644
index 00000000000..4bb40ada055
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/discr1_pkg.ads
@@ -0,0 +1,14 @@
+package Discr1_Pkg is
+
+ Maximum_Length : Natural := 80 ;
+
+ subtype String_Length is Natural range 0 .. Maximum_Length;
+
+ type Variable_String (Length : String_Length := 0) is
+ record
+ S : String (1 .. Length);
+ end record;
+
+ type Variable_String_Array is array (Natural range <>) of Variable_String;
+
+end Discr1_Pkg;
diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_union.ads b/gcc/testsuite/gnat.dg/specs/unchecked_union.ads
deleted file mode 100644
index 260f781d89d..00000000000
--- a/gcc/testsuite/gnat.dg/specs/unchecked_union.ads
+++ /dev/null
@@ -1,20 +0,0 @@
--- PR ada/28591
--- Reported by Martin Michlmayr <tbm@cyrius.com>
-
--- { dg-do compile }
--- { dg-options "-g" }
-
-with Interfaces; use Interfaces;
-
-package Unchecked_Union is
- type Mode_Type is (Mode_B2);
-
- type Value_Union (Mode : Mode_Type := Mode_B2) is record
- case Mode is
- when Mode_B2 =>
- B2 : Integer_32;
- end case;
- end record;
- pragma Unchecked_Union (Value_Union);
-
-end Unchecked_Union;
diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_union1.ads b/gcc/testsuite/gnat.dg/specs/unchecked_union1.ads
new file mode 100644
index 00000000000..06313ef88c4
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/unchecked_union1.ads
@@ -0,0 +1,20 @@
+-- PR ada/28591
+-- Reported by Martin Michlmayr <tbm@cyrius.com>
+
+-- { dg-do compile }
+-- { dg-options "-g" }
+
+with Interfaces; use Interfaces;
+
+package Unchecked_Union1 is
+ type Mode_Type is (Mode_B2);
+
+ type Value_Union (Mode : Mode_Type := Mode_B2) is record
+ case Mode is
+ when Mode_B2 =>
+ B2 : Integer_32;
+ end case;
+ end record;
+ pragma Unchecked_Union (Value_Union);
+
+end Unchecked_Union1;
diff --git a/gcc/testsuite/gnat.dg/specs/unchecked_union2.ads b/gcc/testsuite/gnat.dg/specs/unchecked_union2.ads
new file mode 100644
index 00000000000..f13421cc474
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/unchecked_union2.ads
@@ -0,0 +1,30 @@
+-- { dg-do compile }
+
+package Unchecked_Union2 is
+
+ type Small_Int is range 0 .. 2**19 - 1;
+
+ type R1 (B : Boolean := True) is record
+ case B is
+ when True => Data1 : Small_Int;
+ when False => Data2 : Small_Int;
+ end case;
+ end record;
+
+ for R1 use record
+ Data1 at 0 range 0 .. 18;
+ Data2 at 0 range 0 .. 18;
+ end record;
+ for R1'Size use 24;
+
+ pragma Unchecked_Union (R1);
+
+ type R2 is record
+ Data : R1;
+ end record;
+
+ for R2 use record
+ Data at 0 range 3 .. 26;
+ end record;
+
+end Unchecked_Union2;
diff --git a/gcc/testsuite/gnat.dg/vect1.adb b/gcc/testsuite/gnat.dg/vect1.adb
new file mode 100644
index 00000000000..0bbd9ee86a7
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect1.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect1 is
+
+ function "+" (X, Y : Varray) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Varray; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Sarray) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray1) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray2) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray3) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+end Vect1;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect1.ads b/gcc/testsuite/gnat.dg/vect1.ads
new file mode 100644
index 00000000000..48343fc0553
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect1.ads
@@ -0,0 +1,42 @@
+with Vect1_Pkg;
+
+package Vect1 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Integer range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X, Y : Varray) return Varray;
+ procedure Add (X, Y : not null access Varray; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (1 .. 4) of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X, Y : Sarray) return Sarray;
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray);
+
+
+ type Darray1 is array (1 .. Vect1_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X, Y : Darray1) return Darray1;
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect1_Pkg.K .. 4) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X, Y : Darray2) return Darray2;
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect1_Pkg.K .. Vect1_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X, Y : Darray3) return Darray3;
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3);
+
+end Vect1;
diff --git a/gcc/testsuite/gnat.dg/vect1_pkg.ads b/gcc/testsuite/gnat.dg/vect1_pkg.ads
new file mode 100644
index 00000000000..b9fab52b1e2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect1_pkg.ads
@@ -0,0 +1,6 @@
+package Vect1_Pkg is
+
+ function K return Integer;
+ function N return Integer;
+
+end Vect1_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect2.adb b/gcc/testsuite/gnat.dg/vect2.adb
new file mode 100644
index 00000000000..54e0403f135
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect2.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect2 is
+
+ function "+" (X, Y : Varray) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Varray; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Sarray) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray1) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray2) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray3) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+end Vect2;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect2.ads b/gcc/testsuite/gnat.dg/vect2.ads
new file mode 100644
index 00000000000..b5111875924
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect2.ads
@@ -0,0 +1,42 @@
+with Vect2_Pkg;
+
+package Vect2 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Positive range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X, Y : Varray) return Varray;
+ procedure Add (X, Y : not null access Varray; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (Positive(1) .. Positive(4)) of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X, Y : Sarray) return Sarray;
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray);
+
+
+ type Darray1 is array (Positive(1) .. Vect2_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X, Y : Darray1) return Darray1;
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect2_Pkg.K .. Positive(4)) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X, Y : Darray2) return Darray2;
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect2_Pkg.K .. Vect2_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X, Y : Darray3) return Darray3;
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3);
+
+end Vect2;
diff --git a/gcc/testsuite/gnat.dg/vect2_pkg.ads b/gcc/testsuite/gnat.dg/vect2_pkg.ads
new file mode 100644
index 00000000000..804e10caebc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect2_pkg.ads
@@ -0,0 +1,6 @@
+package Vect2_Pkg is
+
+ function K return Positive;
+ function N return Positive;
+
+end Vect2_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect3.adb b/gcc/testsuite/gnat.dg/vect3.adb
new file mode 100644
index 00000000000..3baa6388e17
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect3.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect3 is
+
+ function "+" (X, Y : Varray) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Varray; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Sarray) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray1) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray2) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+
+ function "+" (X, Y : Darray3) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y(I);
+ end loop;
+ end;
+
+end Vect3;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect3.ads b/gcc/testsuite/gnat.dg/vect3.ads
new file mode 100644
index 00000000000..d78e3c44cff
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect3.ads
@@ -0,0 +1,43 @@
+with Vect3_Pkg;
+
+package Vect3 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Vect3_Pkg.Index_Type range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X, Y : Varray) return Varray;
+ procedure Add (X, Y : not null access Varray; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (Vect3_Pkg.Index_Type(1) .. Vect3_Pkg.Index_Type(4))
+ of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X, Y : Sarray) return Sarray;
+ procedure Add (X, Y : not null access Sarray; R : not null access Sarray);
+
+
+ type Darray1 is array (Vect3_Pkg.Index_Type(1) .. Vect3_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X, Y : Darray1) return Darray1;
+ procedure Add (X, Y : not null access Darray1; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect3_Pkg.K .. Vect3_Pkg.Index_Type(4)) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X, Y : Darray2) return Darray2;
+ procedure Add (X, Y : not null access Darray2; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect3_Pkg.K .. Vect3_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X, Y : Darray3) return Darray3;
+ procedure Add (X, Y : not null access Darray3; R : not null access Darray3);
+
+end Vect3;
diff --git a/gcc/testsuite/gnat.dg/vect3_pkg.ads b/gcc/testsuite/gnat.dg/vect3_pkg.ads
new file mode 100644
index 00000000000..8c926bbcd6a
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect3_pkg.ads
@@ -0,0 +1,10 @@
+with System;
+
+package Vect3_Pkg is
+
+ type Index_Type is mod System.Memory_Size;
+
+ function K return Index_Type;
+ function N return Index_Type;
+
+end Vect3_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect4.adb b/gcc/testsuite/gnat.dg/vect4.adb
new file mode 100644
index 00000000000..032a7289394
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect4.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect4 is
+
+ function "+" (X : Varray; Y : Long_Float) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+end Vect4;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect4.ads b/gcc/testsuite/gnat.dg/vect4.ads
new file mode 100644
index 00000000000..98df7efeebc
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect4.ads
@@ -0,0 +1,42 @@
+with Vect4_Pkg;
+
+package Vect4 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Integer range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X : Varray; Y : Long_Float) return Varray;
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (1 .. 4) of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray;
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray);
+
+
+ type Darray1 is array (1 .. Vect4_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1;
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect4_Pkg.K .. 4) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2;
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect4_Pkg.K .. Vect4_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3;
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3);
+
+end Vect4;
diff --git a/gcc/testsuite/gnat.dg/vect4_pkg.ads b/gcc/testsuite/gnat.dg/vect4_pkg.ads
new file mode 100644
index 00000000000..2e0008d0a71
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect4_pkg.ads
@@ -0,0 +1,6 @@
+package Vect4_Pkg is
+
+ function K return Integer;
+ function N return Integer;
+
+end Vect4_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect5.adb b/gcc/testsuite/gnat.dg/vect5.adb
new file mode 100644
index 00000000000..98af2c01d54
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect5.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect5 is
+
+ function "+" (X : Varray; Y : Long_Float) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+end Vect5;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect5.ads b/gcc/testsuite/gnat.dg/vect5.ads
new file mode 100644
index 00000000000..09e798aecb2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect5.ads
@@ -0,0 +1,42 @@
+with Vect5_Pkg;
+
+package Vect5 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Positive range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X : Varray; Y : Long_Float) return Varray;
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (Positive (1) .. Positive (4)) of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray;
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray);
+
+
+ type Darray1 is array (Positive(1) .. Vect5_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1;
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect5_Pkg.K .. Positive(4)) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2;
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect5_Pkg.K .. Vect5_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3;
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3);
+
+end Vect5;
diff --git a/gcc/testsuite/gnat.dg/vect5_pkg.ads b/gcc/testsuite/gnat.dg/vect5_pkg.ads
new file mode 100644
index 00000000000..9eb752eedb2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect5_pkg.ads
@@ -0,0 +1,6 @@
+package Vect5_Pkg is
+
+ function K return Positive;
+ function N return Positive;
+
+end Vect5_Pkg;
diff --git a/gcc/testsuite/gnat.dg/vect6.adb b/gcc/testsuite/gnat.dg/vect6.adb
new file mode 100644
index 00000000000..425f2a70362
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect6.adb
@@ -0,0 +1,93 @@
+-- { dg-do compile { target i?86-*-* x86_64-*-* } }
+-- { dg-options "-O3 -msse2 -fdump-tree-vect-details" }
+
+package body Vect6 is
+
+ function "+" (X : Varray; Y : Long_Float) return Varray is
+ R : Varray (X'Range);
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray) is
+ begin
+ for I in X'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray is
+ R : Sarray;
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray) is
+ begin
+ for I in Sarray'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1 is
+ R : Darray1;
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1) is
+ begin
+ for I in Darray1'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2 is
+ R : Darray2;
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2) is
+ begin
+ for I in Darray2'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3 is
+ R : Darray3;
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ return R;
+ end;
+
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3) is
+ begin
+ for I in Darray3'Range loop
+ R(I) := X(I) + Y;
+ end loop;
+ end;
+
+end Vect6;
+
+-- { dg-final { scan-tree-dump-times "vectorized 1 loops" 10 "vect" } }
+-- { dg-final { cleanup-tree-dump "vect" } }
diff --git a/gcc/testsuite/gnat.dg/vect6.ads b/gcc/testsuite/gnat.dg/vect6.ads
new file mode 100644
index 00000000000..013fe13652e
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect6.ads
@@ -0,0 +1,43 @@
+with Vect6_Pkg;
+
+package Vect6 is
+
+ -- Unconstrained array types are vectorizable, possibly with special
+ -- help for the programmer
+ type Varray is array (Vect6_Pkg.Index_Type range <>) of Long_Float;
+ for Varray'Alignment use 16;
+
+ function "+" (X : Varray; Y : Long_Float) return Varray;
+ procedure Add (X : not null access Varray; Y : Long_Float; R : not null access Varray);
+
+
+ -- Constrained array types are vectorizable
+ type Sarray is array (Vect6_Pkg.Index_Type(1) .. Vect6_Pkg.Index_Type(4))
+ of Long_Float;
+ for Sarray'Alignment use 16;
+
+ function "+" (X : Sarray; Y : Long_Float) return Sarray;
+ procedure Add (X : not null access Sarray; Y : Long_Float; R : not null access Sarray);
+
+
+ type Darray1 is array (Vect6_Pkg.Index_Type(1) .. Vect6_Pkg.N) of Long_Float;
+ for Darray1'Alignment use 16;
+
+ function "+" (X : Darray1; Y : Long_Float) return Darray1;
+ procedure Add (X : not null access Darray1; Y : Long_Float; R : not null access Darray1);
+
+
+ type Darray2 is array (Vect6_Pkg.K .. Vect6_Pkg.Index_Type(4)) of Long_Float;
+ for Darray2'Alignment use 16;
+
+ function "+" (X : Darray2; Y : Long_Float) return Darray2;
+ procedure Add (X : not null access Darray2; Y : Long_Float; R : not null access Darray2);
+
+
+ type Darray3 is array (Vect6_Pkg.K .. Vect6_Pkg.N) of Long_Float;
+ for Darray3'Alignment use 16;
+
+ function "+" (X : Darray3; Y : Long_Float) return Darray3;
+ procedure Add (X : not null access Darray3; Y : Long_Float; R : not null access Darray3);
+
+end Vect6;
diff --git a/gcc/testsuite/gnat.dg/vect6_pkg.ads b/gcc/testsuite/gnat.dg/vect6_pkg.ads
new file mode 100644
index 00000000000..7db734a359f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/vect6_pkg.ads
@@ -0,0 +1,10 @@
+with System;
+
+package Vect6_Pkg is
+
+ type Index_Type is mod System.Memory_Size;
+
+ function K return Index_Type;
+ function N return Index_Type;
+
+end Vect6_Pkg;
diff --git a/gcc/testsuite/go.test/test/chan/sieve2.go b/gcc/testsuite/go.test/test/chan/sieve2.go
index 7f2ed915799..9a7ab15406c 100644
--- a/gcc/testsuite/go.test/test/chan/sieve2.go
+++ b/gcc/testsuite/go.test/test/chan/sieve2.go
@@ -13,7 +13,6 @@ package main
import (
"container/heap"
"container/ring"
- "container/vector"
)
// Return a chan of odd numbers, starting from 5.
@@ -47,13 +46,28 @@ type PeekCh struct {
ch chan int
}
-// Heap of PeekCh, sorting by head values.
-type PeekChHeap struct {
- *vector.Vector
-}
+// Heap of PeekCh, sorting by head values, satisfies Heap interface.
+type PeekChHeap []*PeekCh
func (h *PeekChHeap) Less(i, j int) bool {
- return h.At(i).(*PeekCh).head < h.At(j).(*PeekCh).head
+ return (*h)[i].head < (*h)[j].head
+}
+
+func (h *PeekChHeap) Swap(i, j int) {
+ (*h)[i], (*h)[j] = (*h)[j], (*h)[i]
+}
+
+func (h *PeekChHeap) Len() int {
+ return len(*h)
+}
+
+func (h *PeekChHeap) Pop() (v interface{}) {
+ *h, v = (*h)[:h.Len()-1], (*h)[h.Len()-1]
+ return
+}
+
+func (h *PeekChHeap) Push(v interface{}) {
+ *h = append(*h, v.(*PeekCh))
}
// Return a channel to serve as a sending proxy to 'out'.
@@ -108,26 +122,26 @@ func Sieve() chan int {
// Merge channels of multiples of 'primes' into 'composites'.
go func() {
- h := &PeekChHeap{new(vector.Vector)}
+ var h PeekChHeap
min := 15
for {
m := multiples(<-primes)
head := <-m
for min < head {
composites <- min
- minchan := heap.Pop(h).(*PeekCh)
+ minchan := heap.Pop(&h).(*PeekCh)
min = minchan.head
minchan.head = <-minchan.ch
- heap.Push(h, minchan)
+ heap.Push(&h, minchan)
}
for min == head {
- minchan := heap.Pop(h).(*PeekCh)
+ minchan := heap.Pop(&h).(*PeekCh)
min = minchan.head
minchan.head = <-minchan.ch
- heap.Push(h, minchan)
+ heap.Push(&h, minchan)
}
composites <- head
- heap.Push(h, &PeekCh{<-m, m})
+ heap.Push(&h, &PeekCh{<-m, m})
}
}()
diff --git a/gcc/testsuite/go.test/test/interface/fake.go b/gcc/testsuite/go.test/test/interface/fake.go
index bdc5b9072c3..ddb83254278 100644
--- a/gcc/testsuite/go.test/test/interface/fake.go
+++ b/gcc/testsuite/go.test/test/interface/fake.go
@@ -12,20 +12,20 @@ package main
import "reflect"
type T struct {
- f float32
- g float32
+ F float32
+ G float32
- s string
- t string
+ S string
+ T string
- u uint32
- v uint32
+ U uint32
+ V uint32
- w uint32
- x uint32
+ W uint32
+ X uint32
- y uint32
- z uint32
+ Y uint32
+ Z uint32
}
func add(s, t string) string {
@@ -40,16 +40,16 @@ func assert(b bool) {
func main() {
var x T
- x.f = 1.0
- x.g = x.f
- x.s = add("abc", "def")
- x.t = add("abc", "def")
- x.u = 1
- x.v = 2
- x.w = 1 << 28
- x.x = 2 << 28
- x.y = 0x12345678
- x.z = x.y
+ x.F = 1.0
+ x.G = x.F
+ x.S = add("abc", "def")
+ x.T = add("abc", "def")
+ x.U = 1
+ x.V = 2
+ x.W = 1 << 28
+ x.X = 2 << 28
+ x.Y = 0x12345678
+ x.Z = x.Y
// check mem and string
v := reflect.ValueOf(x)
diff --git a/gcc/testsuite/go.test/test/vectors.go b/gcc/testsuite/go.test/test/vectors.go
deleted file mode 100644
index ed5905da30c..00000000000
--- a/gcc/testsuite/go.test/test/vectors.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// $G $F.go && $L $F.$A && ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "container/vector"
-
-
-type S struct {
- val int
-}
-
-
-func (p *S) Init(val int) *S {
- p.val = val
- return p
-}
-
-
-func test0() {
- v := new(vector.Vector)
- if v.Len() != 0 {
- print("len = ", v.Len(), "\n")
- panic("fail")
- }
-}
-
-
-func test1() {
- var a [1000]*S
- for i := 0; i < len(a); i++ {
- a[i] = new(S).Init(i)
- }
-
- v := new(vector.Vector)
- for i := 0; i < len(a); i++ {
- v.Insert(0, a[i])
- if v.Len() != i+1 {
- print("len = ", v.Len(), "\n")
- panic("fail")
- }
- }
-
- for i := 0; i < v.Len(); i++ {
- x := v.At(i).(*S)
- if x.val != v.Len()-i-1 {
- print("expected ", i, ", found ", x.val, "\n")
- panic("fail")
- }
- }
-
- for v.Len() > 10 {
- v.Delete(10)
- }
-}
-
-
-func main() {
- test0()
- test1()
-}
diff --git a/gcc/testsuite/lib/c-torture.exp b/gcc/testsuite/lib/c-torture.exp
index 5274e8b444a..bb92871937a 100644
--- a/gcc/testsuite/lib/c-torture.exp
+++ b/gcc/testsuite/lib/c-torture.exp
@@ -52,10 +52,19 @@ if [info exists ADDITIONAL_TORTURE_OPTIONS] {
set LTO_TORTURE_OPTIONS ""
if [check_effective_target_lto] {
- set LTO_TORTURE_OPTIONS [list \
- { -O2 -flto -flto-partition=none } \
- { -O2 -flto }
- ]
+ # When having plugin test both slim and fat LTO and plugin/nonplugin
+ # path.
+ if [check_linker_plugin_available] {
+ set LTO_TORTURE_OPTIONS [list \
+ { -O2 -flto -fno-use-linker-plugin -flto-partition=none } \
+ { -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects }
+ ]
+ } else {
+ set LTO_TORTURE_OPTIONS [list \
+ { -O2 -flto -flto-partition=none } \
+ { -O2 -flto }
+ ]
+ }
}
global GCC_UNDER_TEST
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 6bac368d43d..caa057f0746 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -41,6 +41,11 @@ if { [ishost "*-*-cygwin*"] } {
setenv LANG C.ASCII
}
+global GCC_UNDER_TEST
+if ![info exists GCC_UNDER_TEST] {
+ set GCC_UNDER_TEST "[find_gcc]"
+}
+
if [info exists TORTURE_OPTIONS] {
set DG_TORTURE_OPTIONS $TORTURE_OPTIONS
} else {
@@ -69,16 +74,19 @@ if [info exists ADDITIONAL_TORTURE_OPTIONS] {
set LTO_TORTURE_OPTIONS ""
if [check_effective_target_lto] {
- set LTO_TORTURE_OPTIONS [list \
- { -O2 -flto -flto-partition=none } \
- { -O2 -flto }
- ]
-}
-
-
-global GCC_UNDER_TEST
-if ![info exists GCC_UNDER_TEST] {
- set GCC_UNDER_TEST "[find_gcc]"
+ # When having plugin test both slim and fat LTO and plugin/nonplugin
+ # path.
+ if [check_linker_plugin_available] {
+ set LTO_TORTURE_OPTIONS [list \
+ { -O2 -flto -fno-use-linker-plugin -flto-partition=none } \
+ { -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects }
+ ]
+ } else {
+ set LTO_TORTURE_OPTIONS [list \
+ { -O2 -flto -flto-partition=none } \
+ { -O2 -flto }
+ ]
+ }
}
global orig_environment_saved
diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp
index f1f3a68631a..4e5d4437dbe 100644
--- a/gcc/testsuite/lib/lto.exp
+++ b/gcc/testsuite/lib/lto.exp
@@ -66,14 +66,25 @@ proc lto_init { args } {
# You can put this in the environment before site.exp is written or
# add it to site.exp directly.
if ![info exists LTO_OPTIONS] {
- set LTO_OPTIONS [list \
- {-O0 -flto -flto-partition=none } \
- {-O2 -flto -flto-partition=none } \
- {-O0 -flto -flto-partition=1to1 } \
- {-O2 -flto -flto-partition=1to1 } \
- {-O0 -flto} \
- {-O2 -flto} \
- ]
+ if [check_linker_plugin_available] {
+ set LTO_OPTIONS [list \
+ {-O0 -flto -flto-partition=none -fuse-linker-plugin} \
+ {-O2 -flto -flto-partition=none -fuse-linker-plugin -fno-fat-lto-objects } \
+ {-O0 -flto -flto-partition=1to1 -fno-use-linker-plugin } \
+ {-O2 -flto -flto-partition=1to1 -fno-use-linker-plugin } \
+ {-O0 -flto -fuse-linker-plugin -fno-fat-lto-objects } \
+ {-O2 -flto -fuse-linker-plugin} \
+ ]
+ } else {
+ set LTO_OPTIONS [list \
+ {-O0 -flto -flto-partition=none } \
+ {-O2 -flto -flto-partition=none } \
+ {-O0 -flto -flto-partition=1to1 } \
+ {-O2 -flto -flto-partition=1to1 } \
+ {-O0 -flto } \
+ {-O2 -flto} \
+ ]
+ }
}
}
@@ -500,7 +511,7 @@ proc lto-execute { src1 sid } {
verbose "Testing $testcase, $option"
# There's a unique name for each executable we generate.
- set execname "${execbase}-${count}1"
+ set execname "${execbase}-${count}1.exe"
incr count
file_on_host delete $execname
diff --git a/gcc/testsuite/lib/prune.exp b/gcc/testsuite/lib/prune.exp
index 4683f931589..09d25811106 100644
--- a/gcc/testsuite/lib/prune.exp
+++ b/gcc/testsuite/lib/prune.exp
@@ -29,6 +29,7 @@ proc prune_gcc_output { text } {
regsub -all "(^|\n)collect: re(compiling|linking)\[^\n\]*" $text "" text
regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" text
regsub -all "(^|\n)\[0-9\]\[0-9\]* errors\." $text "" text
+ regsub -all "(^|\n)(In file included|\[ \]+from)\[^\n\]*" $text "" text
# Ignore informational notes.
regsub -all "(^|\n)\[^\n\]*: note: \[^\n\]*" $text "" text
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 9f7fcc6188b..54bb0b17b21 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1995,6 +1995,18 @@ proc check_effective_target_arm_dsp { } {
}]
}
+# Return 1 if this is an ARM target that supports unaligned word/halfword
+# load/store instructions.
+
+proc check_effective_target_arm_unaligned { } {
+ return [check_no_compiler_messages arm_unaligned assembly {
+ #ifndef __ARM_FEATURE_UNALIGNED
+ #error no unaligned support
+ #endif
+ int i;
+ }]
+}
+
# Add the options needed for NEON. We need either -mfloat-abi=softfp
# or -mfloat-abi=hard, but if one is already specified by the
# multilib, use it. Similarly, if a -mfpu option already enables
@@ -2089,6 +2101,47 @@ proc check_effective_target_arm_fp16_ok { } {
check_effective_target_arm_fp16_ok_nocache]
}
+# Creates a series of routines that return 1 if the given architecture
+# can be selected and a routine to give the flags to select that architecture
+# Note: Extra flags may be added to disable options from newer compilers
+# (Thumb in particular - but others may be added in the future)
+# Usage: /* { dg-require-effective-target arm_arch_v5_ok } */
+# /* { dg-add-options arm_arch_v5 } */
+foreach { armfunc armflag armdef } { v5 "-march=armv5 -marm" __ARM_ARCH_5__
+ v6 "-march=armv6" __ARM_ARCH_6__
+ v6k "-march=armv6k" __ARM_ARCH_6K__
+ v7a "-march=armv7-a" __ARM_ARCH_7A__ } {
+ eval [string map [list FUNC $armfunc FLAG $armflag DEF $armdef ] {
+ proc check_effective_target_arm_arch_FUNC_ok { } {
+ if { [ string match "*-marm*" "FLAG" ] &&
+ ![check_effective_target_arm_arm_ok] } {
+ return 0
+ }
+ return [check_no_compiler_messages arm_arch_FUNC_ok assembly {
+ #if !defined (DEF)
+ #error FOO
+ #endif
+ } "FLAG" ]
+ }
+
+ proc add_options_for_arm_arch_FUNC { flags } {
+ return "$flags FLAG"
+ }
+ }]
+}
+
+# Return 1 if this is an ARM target where -marm causes ARM to be
+# used (not Thumb)
+
+proc check_effective_target_arm_arm_ok { } {
+ return [check_no_compiler_messages arm_arm_ok assembly {
+ #if !defined (__arm__) || defined (__thumb__) || defined (__thumb2__)
+ #error FOO
+ #endif
+ } "-marm"]
+}
+
+
# Return 1 is this is an ARM target where -mthumb causes Thumb-1 to be
# used.
@@ -2443,27 +2496,6 @@ proc check_effective_target_vect_shift { } {
return $et_vect_shift_saved
}
-# Return 1 if the target supports hardware vector shift operation with
-# scalar shift argument.
-
-proc check_effective_target_vect_shift_scalar { } {
- global et_vect_shift_scalar_saved
-
- if [info exists et_vect_shift_scalar_saved] {
- verbose "check_effective_target_vect_shift_scalar: using cached result" 2
- } else {
- set et_vect_shift_scalar_saved 0
- if { [istarget x86_64-*-*]
- || [istarget i?86-*-*] } {
- set et_vect_shift_scalar_saved 1
- }
- }
-
- verbose "check_effective_target_vect_shift_scalar: returning $et_vect_shift_scalar_saved" 2
- return $et_vect_shift_scalar_saved
-}
-
-
# Return 1 if the target supports hardware vector shift operation for char.
proc check_effective_target_vect_shift_char { } {
@@ -2909,6 +2941,26 @@ proc check_effective_target_vect_widen_mult_hi_to_si_pattern { } {
}
# Return 1 if the target plus current options supports a vector
+# widening shift, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_widen_shift { } {
+ global et_vect_widen_shift_saved
+
+ if [info exists et_vect_shift_saved] {
+ verbose "check_effective_target_vect_widen_shift: using cached result" 2
+ } else {
+ set et_vect_widen_shift_saved 0
+ if { ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok]) } {
+ set et_vect_widen_shift_saved 1
+ }
+ }
+ verbose "check_effective_target_vect_widen_shift: returning $et_vect_widen_shift_saved" 2
+ return $et_vect_widen_shift_saved
+}
+
+# Return 1 if the target plus current options supports a vector
# dot-product of signed chars, 0 otherwise.
#
# This won't change for different subtargets so cache the result.
@@ -3538,6 +3590,31 @@ proc check_effective_target_sync_int_long { } {
return $et_sync_int_long_saved
}
+# Return 1 if the target supports atomic operations on "long long" and can
+# execute them
+# So far only put checks in for ARM, others may want to add their own
+proc check_effective_target_sync_longlong { } {
+ return [check_runtime sync_longlong_runtime {
+ #include <stdlib.h>
+ int main ()
+ {
+ long long l1;
+
+ if (sizeof (long long) != 8)
+ exit (1);
+
+ #ifdef __arm__
+ /* Just check for native; checking for kernel fallback is tricky. */
+ asm volatile ("ldrexd r0,r1, [%0]" : : "r" (&l1) : "r0", "r1");
+ #else
+ # error "Add other suitable archs here"
+ #endif
+
+ exit (0);
+ }
+ } "" ]
+}
+
# Return 1 if the target supports atomic operations on "char" and "short".
proc check_effective_target_sync_char_short { } {
diff --git a/gcc/testsuite/obj-c++.dg/warn6.mm b/gcc/testsuite/obj-c++.dg/warn6.mm
new file mode 100644
index 00000000000..a74f8025d0e
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/warn6.mm
@@ -0,0 +1,7 @@
+// PR c++/17212
+// { dg-options "-Wformat -Wno-format-zero-length" }
+
+void f()
+{
+ __builtin_printf("");
+}
diff --git a/gcc/testsuite/obj-c++.dg/warn7.mm b/gcc/testsuite/obj-c++.dg/warn7.mm
new file mode 100644
index 00000000000..6e84069eec5
--- /dev/null
+++ b/gcc/testsuite/obj-c++.dg/warn7.mm
@@ -0,0 +1,10 @@
+// PR c++/50757
+// { dg-options "-Wformat -Wno-nonnull" }
+
+extern void *f (void *__s) __attribute__ ((__nonnull__ (1)));
+
+int main()
+{
+ void* const s = 0;
+ f(s);
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index ab6b5a41837..86eed5d63a8 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -651,13 +651,13 @@ compile_file (void)
{
#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, NULL_TREE,
- "__gnu_slim_lto",
+ "__gnu_lto_slim",
(unsigned HOST_WIDE_INT) 1, 8);
#elif defined ASM_OUTPUT_ALIGNED_COMMON
- ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_slim_lto",
+ ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, "__gnu_lto_slim",
(unsigned HOST_WIDE_INT) 1, 8);
#else
- ASM_OUTPUT_COMMON (asm_out_file, "__gnu_slim_lto",
+ ASM_OUTPUT_COMMON (asm_out_file, "__gnu_lto_slim",
(unsigned HOST_WIDE_INT) 1,
(unsigned HOST_WIDE_INT) 1);
#endif
@@ -1171,6 +1171,9 @@ general_init (const char *argv0)
can give warnings and errors. */
diagnostic_initialize (global_dc, N_OPTS);
diagnostic_starter (global_dc) = default_tree_diagnostic_starter;
+ /* By default print macro expansion contexts in the diagnostic
+ finalizer -- for tokens resulting from macro macro expansion. */
+ diagnostic_finalizer (global_dc) = virt_loc_aware_diagnostic_finalizer;
/* Set a default printer. Language specific initializations will
override it later. */
pp_format_decoder (global_dc->printer) = &default_tree_printer;
@@ -1213,6 +1216,7 @@ general_init (const char *argv0)
line_table = ggc_alloc_line_maps ();
linemap_init (line_table);
line_table->reallocator = realloc_for_line_map;
+ line_table->round_alloc_size = ggc_round_alloc_size;
init_ttree ();
/* Initialize register usage now so switches may override. */
@@ -1824,6 +1828,7 @@ target_reinit (void)
void
dump_memory_report (bool final)
{
+ dump_line_table_statistics ();
ggc_print_statistics ();
stringpool_statistics ();
dump_tree_statistics ();
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index bcf71b99bbb..2819e7b2fc6 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -3342,7 +3342,9 @@ verify_gimple_assign_unary (gimple stmt)
case FLOAT_EXPR:
{
- if (!INTEGRAL_TYPE_P (rhs1_type) || !SCALAR_FLOAT_TYPE_P (lhs_type))
+ if ((!INTEGRAL_TYPE_P (rhs1_type) || !SCALAR_FLOAT_TYPE_P (lhs_type))
+ && (!VECTOR_INTEGER_TYPE_P (rhs1_type)
+ || !VECTOR_FLOAT_TYPE_P(lhs_type)))
{
error ("invalid types in conversion to floating point");
debug_generic_expr (lhs_type);
@@ -3355,7 +3357,9 @@ verify_gimple_assign_unary (gimple stmt)
case FIX_TRUNC_EXPR:
{
- if (!INTEGRAL_TYPE_P (lhs_type) || !SCALAR_FLOAT_TYPE_P (rhs1_type))
+ if ((!INTEGRAL_TYPE_P (lhs_type) || !SCALAR_FLOAT_TYPE_P (rhs1_type))
+ && (!VECTOR_INTEGER_TYPE_P (lhs_type)
+ || !VECTOR_FLOAT_TYPE_P(rhs1_type)))
{
error ("invalid types in conversion to integer");
debug_generic_expr (lhs_type);
@@ -3510,6 +3514,44 @@ verify_gimple_assign_binary (gimple stmt)
return false;
}
+ case WIDEN_LSHIFT_EXPR:
+ {
+ if (!INTEGRAL_TYPE_P (lhs_type)
+ || !INTEGRAL_TYPE_P (rhs1_type)
+ || TREE_CODE (rhs2) != INTEGER_CST
+ || (2 * TYPE_PRECISION (rhs1_type) > TYPE_PRECISION (lhs_type)))
+ {
+ error ("type mismatch in widening vector shift expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ return true;
+ }
+
+ return false;
+ }
+
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ {
+ if (TREE_CODE (rhs1_type) != VECTOR_TYPE
+ || TREE_CODE (lhs_type) != VECTOR_TYPE
+ || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))
+ || !INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))
+ || TREE_CODE (rhs2) != INTEGER_CST
+ || (2 * TYPE_PRECISION (TREE_TYPE (rhs1_type))
+ > TYPE_PRECISION (TREE_TYPE (lhs_type))))
+ {
+ error ("type mismatch in widening vector shift expression");
+ debug_generic_expr (lhs_type);
+ debug_generic_expr (rhs1_type);
+ debug_generic_expr (rhs2_type);
+ return true;
+ }
+
+ return false;
+ }
+
case PLUS_EXPR:
case MINUS_EXPR:
{
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index a4c9367d9c6..4e0de052c15 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -589,9 +589,6 @@ split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
int punsignedp, pvolatilep;
op0 = TREE_OPERAND (op0, 0);
- if (!handled_component_p (op0))
- return false;
-
base = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset,
&pmode, &punsignedp, &pvolatilep, false);
@@ -858,7 +855,7 @@ static void
dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop)
{
VEC (tree, heap) *access_fns = NULL;
- tree ref, aref, op;
+ tree ref, *aref, op;
tree base, off, access_fn;
basic_block before_loop;
@@ -889,50 +886,58 @@ dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop)
}
/* Analyze access functions of dimensions we know to be independent. */
- aref = ref;
- while (handled_component_p (aref))
+ aref = &ref;
+ while (handled_component_p (*aref))
{
- if (TREE_CODE (aref) == ARRAY_REF)
+ if (TREE_CODE (*aref) == ARRAY_REF)
{
- op = TREE_OPERAND (aref, 1);
+ op = TREE_OPERAND (*aref, 1);
access_fn = analyze_scalar_evolution (loop, op);
access_fn = instantiate_scev (before_loop, loop, access_fn);
VEC_safe_push (tree, heap, access_fns, access_fn);
/* For ARRAY_REFs the base is the reference with the index replaced
by zero if we can not strip it as the outermost component. */
- if (aref == ref)
- ref = TREE_OPERAND (ref, 0);
+ if (*aref == ref)
+ {
+ *aref = TREE_OPERAND (*aref, 0);
+ continue;
+ }
else
- TREE_OPERAND (aref, 1) = build_int_cst (TREE_TYPE (op), 0);
+ TREE_OPERAND (*aref, 1) = build_int_cst (TREE_TYPE (op), 0);
}
- aref = TREE_OPERAND (aref, 0);
+ aref = &TREE_OPERAND (*aref, 0);
}
/* If the address operand of a MEM_REF base has an evolution in the
analyzed nest, add it as an additional independent access-function. */
- if (TREE_CODE (aref) == MEM_REF)
+ if (TREE_CODE (*aref) == MEM_REF)
{
- op = TREE_OPERAND (aref, 0);
+ op = TREE_OPERAND (*aref, 0);
access_fn = analyze_scalar_evolution (loop, op);
access_fn = instantiate_scev (before_loop, loop, access_fn);
if (TREE_CODE (access_fn) == POLYNOMIAL_CHREC)
{
+ tree orig_type;
base = initial_condition (access_fn);
+ orig_type = TREE_TYPE (base);
+ STRIP_USELESS_TYPE_CONVERSION (base);
split_constant_offset (base, &base, &off);
/* Fold the MEM_REF offset into the evolutions initial
value to make more bases comparable. */
- if (!integer_zerop (TREE_OPERAND (aref, 1)))
+ if (!integer_zerop (TREE_OPERAND (*aref, 1)))
{
off = size_binop (PLUS_EXPR, off,
fold_convert (ssizetype,
- TREE_OPERAND (aref, 1)));
- TREE_OPERAND (aref, 1)
- = build_int_cst (TREE_TYPE (TREE_OPERAND (aref, 1)), 0);
+ TREE_OPERAND (*aref, 1)));
+ TREE_OPERAND (*aref, 1)
+ = build_int_cst (TREE_TYPE (TREE_OPERAND (*aref, 1)), 0);
}
access_fn = chrec_replace_initial_condition
- (access_fn, fold_convert (TREE_TYPE (base), off));
- TREE_OPERAND (aref, 0) = base;
+ (access_fn, fold_convert (orig_type, off));
+ *aref = fold_build2_loc (EXPR_LOCATION (*aref),
+ MEM_REF, TREE_TYPE (*aref),
+ base, TREE_OPERAND (*aref, 1));
VEC_safe_push (tree, heap, access_fns, access_fn);
}
}
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index b456a2a5fbf..53b350b5418 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-diagnostic.h"
#include "langhooks.h"
#include "langhooks-def.h"
+#include "vec.h"
/* Prints out, if necessary, the name of the current function
that caused an error. Called from all error and warning functions. */
@@ -35,7 +36,7 @@ void
diagnostic_report_current_function (diagnostic_context *context,
diagnostic_info *diagnostic)
{
- diagnostic_report_current_module (context);
+ diagnostic_report_current_module (context, diagnostic->location);
lang_hooks.print_error_function (context, input_filename, diagnostic);
}
@@ -47,3 +48,182 @@ default_tree_diagnostic_starter (diagnostic_context *context,
pp_set_prefix (context->printer, diagnostic_build_prefix (context,
diagnostic));
}
+
+/* This is a pair made of a location and the line map it originated
+ from. It's used in the maybe_unwind_expanded_macro_loc function
+ below. */
+typedef struct
+{
+ const struct line_map *map;
+ source_location where;
+} loc_t;
+
+DEF_VEC_O (loc_t);
+DEF_VEC_ALLOC_O (loc_t, heap);
+
+/* Unwind the different macro expansions that lead to the token which
+ location is WHERE and emit diagnostics showing the resulting
+ unwound macro expansion trace. Let's look at an example to see how
+ the trace looks like. Suppose we have this piece of code,
+ artificially annotated with the line numbers to increase
+ legibility:
+
+ $ cat -n test.c
+ 1 #define OPERATE(OPRD1, OPRT, OPRD2) \
+ 2 OPRD1 OPRT OPRD2;
+ 3
+ 4 #define SHIFTL(A,B) \
+ 5 OPERATE (A,<<,B)
+ 6
+ 7 #define MULT(A) \
+ 8 SHIFTL (A,1)
+ 9
+ 10 void
+ 11 g ()
+ 12 {
+ 13 MULT (1.0);// 1.0 << 1; <-- so this is an error.
+ 14 }
+
+ Here is the diagnostic that we want the compiler to generate:
+
+ test.c: In function 'g':
+ test.c:5:14: error: invalid operands to binary << (have 'double' and 'int')
+ test.c:2:9: note: in expansion of macro 'OPERATE'
+ test.c:5:3: note: expanded from here
+ test.c:5:14: note: in expansion of macro 'SHIFTL'
+ test.c:8:3: note: expanded from here
+ test.c:8:3: note: in expansion of macro 'MULT2'
+ test.c:13:3: note: expanded from here
+
+ The part that goes from the third to the eighth line of this
+ diagnostic (the lines containing the 'note:' string) is called the
+ unwound macro expansion trace. That's the part generated by this
+ function.
+
+ If FIRST_EXP_POINT_MAP is non-null, *FIRST_EXP_POINT_MAP is set to
+ the map of the location in the source that first triggered the
+ macro expansion. This must be an ordinary map. */
+
+static void
+maybe_unwind_expanded_macro_loc (diagnostic_context *context,
+ diagnostic_info *diagnostic,
+ source_location where,
+ const struct line_map **first_exp_point_map)
+{
+ const struct line_map *map;
+ VEC(loc_t,heap) *loc_vec = NULL;
+ unsigned ix;
+ loc_t loc, *iter;
+
+ map = linemap_lookup (line_table, where);
+ if (!linemap_macro_expansion_map_p (map))
+ return;
+
+ /* Let's unwind the macros that got expanded and led to the token
+ which location is WHERE. We are going to store these macros into
+ LOC_VEC, so that we can later walk it at our convenience to
+ display a somewhat meaningful trace of the macro expansion
+ history to the user. Note that the first macro of the trace
+ (which is OPERATE in the example above) is going to be stored at
+ the beginning of LOC_VEC. */
+
+ do
+ {
+ loc.where = where;
+ loc.map = map;
+
+ VEC_safe_push (loc_t, heap, loc_vec, &loc);
+
+ /* WHERE is the location of a token inside the expansion of a
+ macro. MAP is the map holding the locations of that macro
+ expansion. Let's get the location of the token inside the
+ context that triggered the expansion of this macro.
+ This is basically how we go "down" in the trace of macro
+ expansions that led to WHERE. */
+ where = linemap_unwind_toward_expansion (line_table, where, &map);
+ } while (linemap_macro_expansion_map_p (map));
+
+ if (first_exp_point_map)
+ *first_exp_point_map = map;
+
+ /* Walk LOC_VEC and print the macro expansion trace, unless the
+ first macro which expansion triggered this trace was expanded
+ inside a system header. */
+ if (!LINEMAP_SYSP (map))
+ FOR_EACH_VEC_ELT (loc_t, loc_vec, ix, iter)
+ {
+ source_location resolved_def_loc = 0, resolved_exp_loc = 0;
+ diagnostic_t saved_kind;
+ const char *saved_prefix;
+ source_location saved_location;
+
+ /* Okay, now here is what we want. For each token resulting
+ from macro expansion we want to show: 1/ where in the
+ definition of the macro the token comes from; 2/ where the
+ macro got expanded. */
+
+ /* Resolve the location iter->where into the locus 1/ of the
+ comment above. */
+ resolved_def_loc =
+ linemap_resolve_location (line_table, iter->where,
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+
+ /* Resolve the location of the expansion point of the macro
+ which expansion gave the token represented by def_loc.
+ This is the locus 2/ of the earlier comment. */
+ resolved_exp_loc =
+ linemap_resolve_location (line_table,
+ MACRO_MAP_EXPANSION_POINT_LOCATION (iter->map),
+ LRK_MACRO_DEFINITION_LOCATION, NULL);
+
+ saved_kind = diagnostic->kind;
+ saved_prefix = context->printer->prefix;
+ saved_location = diagnostic->location;
+
+ diagnostic->kind = DK_NOTE;
+ diagnostic->location = resolved_def_loc;
+ pp_base_set_prefix (context->printer,
+ diagnostic_build_prefix (context,
+ diagnostic));
+ pp_newline (context->printer);
+ pp_printf (context->printer, "in expansion of macro '%s'",
+ linemap_map_get_macro_name (iter->map));
+ pp_destroy_prefix (context->printer);
+
+ diagnostic->location = resolved_exp_loc;
+ pp_base_set_prefix (context->printer,
+ diagnostic_build_prefix (context,
+ diagnostic));
+ pp_newline (context->printer);
+ pp_printf (context->printer, "expanded from here");
+ pp_destroy_prefix (context->printer);
+
+ diagnostic->kind = saved_kind;
+ diagnostic->location = saved_location;
+ context->printer->prefix = saved_prefix;
+ }
+
+ VEC_free (loc_t, heap, loc_vec);
+}
+
+/* This is a diagnostic finalizer implementation that is aware of
+ virtual locations produced by libcpp.
+
+ It has to be called by the diagnostic finalizer of front ends that
+ uses libcpp and wish to get diagnostics involving tokens resulting
+ from macro expansion.
+
+ For a given location, if said location belongs to a token
+ resulting from a macro expansion, this starter prints the context
+ of the token. E.g, for multiply nested macro expansion, it
+ unwinds the nested macro expansions and prints them in a manner
+ that is similar to what is done for function call stacks, or
+ template instantiation contexts. */
+void
+virt_loc_aware_diagnostic_finalizer (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ maybe_unwind_expanded_macro_loc (context, diagnostic,
+ diagnostic->location,
+ NULL);
+}
diff --git a/gcc/tree-diagnostic.h b/gcc/tree-diagnostic.h
index 7d88089069f..6b8e8e6e437 100644
--- a/gcc/tree-diagnostic.h
+++ b/gcc/tree-diagnostic.h
@@ -52,5 +52,6 @@ along with GCC; see the file COPYING3. If not see
void default_tree_diagnostic_starter (diagnostic_context *, diagnostic_info *);
extern void diagnostic_report_current_function (diagnostic_context *,
diagnostic_info *);
-
+void virt_loc_aware_diagnostic_finalizer (diagnostic_context *,
+ diagnostic_info *);
#endif /* ! GCC_TREE_DIAGNOSTIC_H */
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index f751d8d98a2..fbc444ca716 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -711,66 +711,35 @@ verify_norecord_switch_expr (struct leh_state *state, gimple switch_expr)
#define verify_norecord_switch_expr(state, switch_expr)
#endif
-/* Redirect a RETURN_EXPR pointed to by STMT_P to FINLAB. Place in CONT_P
- whatever is needed to finish the return. If MOD is non-null, insert it
- before the new branch. RETURN_VALUE_P is a cache containing a temporary
- variable to be used in manipulating the value returned from the function. */
+/* Redirect a RETURN_EXPR pointed to by Q to FINLAB. If MOD is
+ non-null, insert it before the new branch. */
static void
-do_return_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod,
- tree *return_value_p)
+do_return_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod)
{
- tree ret_expr;
gimple x;
- /* In the case of a return, the queue node must be a gimple statement. */
+ /* In the case of a return, the queue node must be a gimple statement. */
gcc_assert (!q->is_label);
- ret_expr = gimple_return_retval (q->stmt.g);
+ /* Note that the return value may have already been computed, e.g.,
- if (ret_expr)
- {
- if (!*return_value_p)
- *return_value_p = ret_expr;
- else
- gcc_assert (*return_value_p == ret_expr);
- q->cont_stmt = q->stmt.g;
- /* The nasty part about redirecting the return value is that the
- return value itself is to be computed before the FINALLY block
- is executed. e.g.
-
- int x;
- int foo (void)
- {
- x = 0;
- try {
- return x;
- } finally {
- x++;
- }
- }
-
- should return 0, not 1. Arrange for this to happen by copying
- computed the return value into a local temporary. This also
- allows us to redirect multiple return statements through the
- same destination block; whether this is a net win or not really
- depends, I guess, but it does make generation of the switch in
- lower_try_finally_switch easier. */
-
- if (TREE_CODE (ret_expr) == RESULT_DECL)
+ int x;
+ int foo (void)
{
- if (!*return_value_p)
- *return_value_p = ret_expr;
- else
- gcc_assert (*return_value_p == ret_expr);
- q->cont_stmt = q->stmt.g;
+ x = 0;
+ try {
+ return x;
+ } finally {
+ x++;
+ }
}
- else
- gcc_unreachable ();
- }
- else
- /* If we don't return a value, all return statements are the same. */
- q->cont_stmt = q->stmt.g;
+
+ should return 0, not 1. We don't have to do anything to make
+ this happens because the return value has been placed in the
+ RESULT_DECL already. */
+
+ q->cont_stmt = q->stmt.g;
if (!q->repl_stmt)
q->repl_stmt = gimple_seq_alloc ();
@@ -1041,7 +1010,7 @@ static void
lower_try_finally_nofallthru (struct leh_state *state,
struct leh_tf_state *tf)
{
- tree lab, return_val;
+ tree lab;
gimple x;
gimple_seq finally;
struct goto_queue_node *q, *qe;
@@ -1055,12 +1024,11 @@ lower_try_finally_nofallthru (struct leh_state *state,
x = gimple_build_label (lab);
gimple_seq_add_stmt (&tf->top_p_seq, x);
- return_val = NULL;
q = tf->goto_queue;
qe = q + tf->goto_queue_active;
for (; q < qe; ++q)
if (q->index < 0)
- do_return_redirection (q, lab, NULL, &return_val);
+ do_return_redirection (q, lab, NULL);
else
do_goto_redirection (q, lab, NULL, tf);
@@ -1126,9 +1094,8 @@ lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
if (tf->may_return)
{
/* Reachable by return expressions only. Redirect them. */
- tree return_val = NULL;
for (; q < qe; ++q)
- do_return_redirection (q, finally_label, NULL, &return_val);
+ do_return_redirection (q, finally_label, NULL);
replace_goto_queue (tf);
}
else
@@ -1197,7 +1164,6 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
if (tf->goto_queue)
{
struct goto_queue_node *q, *qe;
- tree return_val = NULL;
int return_index, index;
struct labels_s
{
@@ -1230,7 +1196,7 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
= create_artificial_label (tf_loc);
if (index == return_index)
- do_return_redirection (q, lab, NULL, &return_val);
+ do_return_redirection (q, lab, NULL);
else
do_goto_redirection (q, lab, NULL, tf);
@@ -1257,7 +1223,7 @@ lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
lab = labels[index].label;
if (index == return_index)
- do_return_redirection (q, lab, NULL, &return_val);
+ do_return_redirection (q, lab, NULL);
else
do_goto_redirection (q, lab, NULL, tf);
}
@@ -1280,7 +1246,6 @@ static void
lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
{
struct goto_queue_node *q, *qe;
- tree return_val = NULL;
tree finally_tmp, finally_label;
int return_index, eh_index, fallthru_index;
int nlabels, ndests, j, last_case_index;
@@ -1401,7 +1366,7 @@ lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
build_int_cst (integer_type_node,
return_index));
gimple_seq_add_stmt (&mod, x);
- do_return_redirection (q, finally_label, mod, &return_val);
+ do_return_redirection (q, finally_label, mod);
switch_id = return_index;
}
else
@@ -2512,7 +2477,13 @@ stmt_could_throw_1_p (gimple stmt)
|| TREE_CODE_CLASS (code) == tcc_unary
|| TREE_CODE_CLASS (code) == tcc_binary)
{
- t = gimple_expr_type (stmt);
+ if (is_gimple_assign (stmt)
+ && TREE_CODE_CLASS (code) == tcc_comparison)
+ t = TREE_TYPE (gimple_assign_rhs1 (stmt));
+ else if (gimple_code (stmt) == GIMPLE_COND)
+ t = TREE_TYPE (gimple_cond_lhs (stmt));
+ else
+ t = gimple_expr_type (stmt);
fp_operation = FLOAT_TYPE_P (t);
if (fp_operation)
{
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 1152b7d0de4..dcfbb9da628 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -715,6 +715,7 @@ bool stmt_dominates_stmt_p (gimple, gimple);
void mark_virtual_ops_for_renaming (gimple);
/* In tree-ssa-dce.c */
+void mark_virtual_operand_for_renaming (tree);
void mark_virtual_phi_result_for_renaming (gimple);
/* In tree-ssa-threadedge.c */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index e2f76e1c608..11be8d0791f 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -3355,6 +3355,7 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
case DOT_PROD_EXPR:
case WIDEN_MULT_PLUS_EXPR:
case WIDEN_MULT_MINUS_EXPR:
+ case WIDEN_LSHIFT_EXPR:
case VEC_WIDEN_MULT_HI_EXPR:
case VEC_WIDEN_MULT_LO_EXPR:
@@ -3369,6 +3370,8 @@ estimate_operator_cost (enum tree_code code, eni_weights *weights,
case VEC_EXTRACT_ODD_EXPR:
case VEC_INTERLEAVE_HIGH_EXPR:
case VEC_INTERLEAVE_LOW_EXPR:
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
return 1;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 8acabb16e16..24d70c3ff38 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1599,6 +1599,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
case RROTATE_EXPR:
case VEC_LSHIFT_EXPR:
case VEC_RSHIFT_EXPR:
+ case WIDEN_LSHIFT_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case BIT_AND_EXPR:
@@ -2297,6 +2298,22 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_string (buffer, " > ");
break;
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ pp_string (buffer, " VEC_WIDEN_LSHIFT_HI_EXPR < ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+ pp_string (buffer, " > ");
+ break;
+
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ pp_string (buffer, " VEC_WIDEN_LSHIFT_HI_EXPR < ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+ pp_string (buffer, ", ");
+ dump_generic_node (buffer, TREE_OPERAND (node, 1), spc, flags, false);
+ pp_string (buffer, " > ");
+ break;
+
case VEC_UNPACK_HI_EXPR:
pp_string (buffer, " VEC_UNPACK_HI_EXPR < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
@@ -2619,6 +2636,9 @@ op_code_prio (enum tree_code code)
case RSHIFT_EXPR:
case LROTATE_EXPR:
case RROTATE_EXPR:
+ case VEC_WIDEN_LSHIFT_HI_EXPR:
+ case VEC_WIDEN_LSHIFT_LO_EXPR:
+ case WIDEN_LSHIFT_EXPR:
return 11;
case WIDEN_SUM_EXPR:
@@ -2794,6 +2814,9 @@ op_symbol_code (enum tree_code code)
case VEC_RSHIFT_EXPR:
return "v>>";
+ case WIDEN_LSHIFT_EXPR:
+ return "w<<";
+
case POINTER_PLUS_EXPR:
return "+";
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index c63b5a817b2..57fc7341c54 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -219,13 +219,6 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
if (!pi)
return true;
- /* If the decl can be used as a restrict tag and we have a restrict
- pointer and that pointers points-to set doesn't contain this decl
- then they can't alias. */
- if (DECL_RESTRICTED_P (decl)
- && pi->pt.vars_contains_restrict)
- return bitmap_bit_p (pi->pt.vars, DECL_PT_UID (decl));
-
return pt_solution_includes (&pi->pt, decl);
}
@@ -316,11 +309,6 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
if (!pi1 || !pi2)
return true;
- /* If both pointers are restrict-qualified try to disambiguate
- with restrict information. */
- if (!pt_solutions_same_restrict_base (&pi1->pt, &pi2->pt))
- return false;
-
/* ??? This does not use TBAA to prune decls from the intersection
that not both pointers may access. */
return pt_solutions_intersect (&pi1->pt, &pi2->pt);
@@ -426,8 +414,6 @@ dump_points_to_solution (FILE *file, struct pt_solution *pt)
dump_decl_set (file, pt->vars);
if (pt->vars_contains_global)
fprintf (file, " (includes global vars)");
- if (pt->vars_contains_restrict)
- fprintf (file, " (includes restrict tags)");
}
}
@@ -1846,6 +1832,8 @@ static bool
maybe_skip_until (gimple phi, tree target, ao_ref *ref,
tree vuse, bitmap *visited)
{
+ basic_block bb = gimple_bb (phi);
+
if (!*visited)
*visited = BITMAP_ALLOC (NULL);
@@ -1870,6 +1858,14 @@ maybe_skip_until (gimple phi, tree target, ao_ref *ref,
else if (gimple_nop_p (def_stmt)
|| stmt_may_clobber_ref_p_1 (def_stmt, ref))
return false;
+ /* If we reach a new basic-block see if we already skipped it
+ in a previous walk that ended successfully. */
+ if (gimple_bb (def_stmt) != bb)
+ {
+ if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (vuse)))
+ return true;
+ bb = gimple_bb (def_stmt);
+ }
vuse = gimple_vuse (def_stmt);
}
return true;
@@ -1948,18 +1944,35 @@ get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
until we hit the phi argument definition that dominates the other one. */
else if (nargs >= 2)
{
- tree arg0 = PHI_ARG_DEF (phi, 0);
- tree arg1;
- unsigned i = 1;
- do
+ tree arg0, arg1;
+ unsigned i;
+
+ /* Find a candidate for the virtual operand which definition
+ dominates those of all others. */
+ arg0 = PHI_ARG_DEF (phi, 0);
+ if (!SSA_NAME_IS_DEFAULT_DEF (arg0))
+ for (i = 1; i < nargs; ++i)
+ {
+ arg1 = PHI_ARG_DEF (phi, i);
+ if (SSA_NAME_IS_DEFAULT_DEF (arg1))
+ {
+ arg0 = arg1;
+ break;
+ }
+ if (dominated_by_p (CDI_DOMINATORS,
+ gimple_bb (SSA_NAME_DEF_STMT (arg0)),
+ gimple_bb (SSA_NAME_DEF_STMT (arg1))))
+ arg0 = arg1;
+ }
+
+ /* Then pairwise reduce against the found candidate. */
+ for (i = 0; i < nargs; ++i)
{
arg1 = PHI_ARG_DEF (phi, i);
arg0 = get_continuation_for_phi_1 (phi, arg0, arg1, ref, visited);
if (!arg0)
return NULL_TREE;
-
}
- while (++i < nargs);
return arg0;
}
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index c2ab2113c1e..74921231045 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -54,8 +54,6 @@ struct GTY(()) pt_solution
/* Nonzero if the pt_vars bitmap includes a global variable. */
unsigned int vars_contains_global : 1;
- /* Nonzero if the pt_vars bitmap includes a restrict tag variable. */
- unsigned int vars_contains_restrict : 1;
/* Set of variables that this pointer may point to. */
bitmap vars;
@@ -130,10 +128,8 @@ extern bool pt_solution_singleton_p (struct pt_solution *, unsigned *);
extern bool pt_solution_includes_global (struct pt_solution *);
extern bool pt_solution_includes (struct pt_solution *, const_tree);
extern bool pt_solutions_intersect (struct pt_solution *, struct pt_solution *);
-extern bool pt_solutions_same_restrict_base (struct pt_solution *,
- struct pt_solution *);
extern void pt_solution_reset (struct pt_solution *);
-extern void pt_solution_set (struct pt_solution *, bitmap, bool, bool);
+extern void pt_solution_set (struct pt_solution *, bitmap, bool);
extern void pt_solution_set_var (struct pt_solution *, tree);
extern void dump_pta_stats (FILE *);
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index b84b6f9a99e..5a6a38e63e9 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -982,18 +982,36 @@ propagate_necessity (struct edge_list *el)
}
}
-/* Replace all uses of result of PHI by underlying variable and mark it
+/* Replace all uses of NAME by underlying variable and mark it
for renaming. */
void
-mark_virtual_phi_result_for_renaming (gimple phi)
+mark_virtual_operand_for_renaming (tree name)
{
bool used = false;
imm_use_iterator iter;
use_operand_p use_p;
gimple stmt;
- tree result_ssa, result_var;
+ tree name_var;
+
+ name_var = SSA_NAME_VAR (name);
+ FOR_EACH_IMM_USE_STMT (stmt, iter, name)
+ {
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, name_var);
+ update_stmt (stmt);
+ used = true;
+ }
+ if (used)
+ mark_sym_for_renaming (name_var);
+}
+/* Replace all uses of result of PHI by underlying variable and mark it
+ for renaming. */
+
+void
+mark_virtual_phi_result_for_renaming (gimple phi)
+{
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Marking result for renaming : ");
@@ -1001,19 +1019,10 @@ mark_virtual_phi_result_for_renaming (gimple phi)
fprintf (dump_file, "\n");
}
- result_ssa = gimple_phi_result (phi);
- result_var = SSA_NAME_VAR (result_ssa);
- FOR_EACH_IMM_USE_STMT (stmt, iter, result_ssa)
- {
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, result_var);
- update_stmt (stmt);
- used = true;
- }
- if (used)
- mark_sym_for_renaming (result_var);
+ mark_virtual_operand_for_renaming (gimple_phi_result (phi));
}
+
/* Remove dead PHI nodes from block BB. */
static bool
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 8bfc91aae4f..949acf1d168 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -1610,12 +1610,15 @@ record_edge_info (basic_block bb)
{
tree cond = build2 (code, boolean_type_node, op0, op1);
tree inverted = invert_truthvalue_loc (loc, cond);
+ bool can_infer_simple_equiv
+ = !(HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op0)))
+ && real_zerop (op0));
struct edge_info *edge_info;
edge_info = allocate_edge_info (true_edge);
record_conditions (edge_info, cond, inverted);
- if (code == EQ_EXPR)
+ if (can_infer_simple_equiv && code == EQ_EXPR)
{
edge_info->lhs = op1;
edge_info->rhs = op0;
@@ -1624,7 +1627,7 @@ record_edge_info (basic_block bb)
edge_info = allocate_edge_info (false_edge);
record_conditions (edge_info, inverted, cond);
- if (TREE_CODE (inverted) == EQ_EXPR)
+ if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR)
{
edge_info->lhs = op1;
edge_info->rhs = op0;
@@ -1632,17 +1635,20 @@ record_edge_info (basic_block bb)
}
else if (TREE_CODE (op0) == SSA_NAME
- && (is_gimple_min_invariant (op1)
- || TREE_CODE (op1) == SSA_NAME))
+ && (TREE_CODE (op1) == SSA_NAME
+ || is_gimple_min_invariant (op1)))
{
tree cond = build2 (code, boolean_type_node, op0, op1);
tree inverted = invert_truthvalue_loc (loc, cond);
+ bool can_infer_simple_equiv
+ = !(HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op1)))
+ && (TREE_CODE (op1) == SSA_NAME || real_zerop (op1)));
struct edge_info *edge_info;
edge_info = allocate_edge_info (true_edge);
record_conditions (edge_info, cond, inverted);
- if (code == EQ_EXPR)
+ if (can_infer_simple_equiv && code == EQ_EXPR)
{
edge_info->lhs = op0;
edge_info->rhs = op1;
@@ -1651,7 +1657,7 @@ record_edge_info (basic_block bb)
edge_info = allocate_edge_info (false_edge);
record_conditions (edge_info, inverted, cond);
- if (TREE_CODE (inverted) == EQ_EXPR)
+ if (can_infer_simple_equiv && TREE_CODE (inverted) == EQ_EXPR)
{
edge_info->lhs = op0;
edge_info->rhs = op1;
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 1db93a65a65..d707db520e3 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -597,7 +597,8 @@ forward_propagate_into_cond (gimple_stmt_iterator *gsi_p)
}
}
- if (tmp)
+ if (tmp
+ && is_gimple_condexpr (tmp))
{
if (dump_file && tmp)
{
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index cb527913d4f..4bc9ffd0eff 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -549,6 +549,11 @@ stmt_cost (gimple stmt)
switch (gimple_assign_rhs_code (stmt))
{
case MULT_EXPR:
+ case WIDEN_MULT_EXPR:
+ case WIDEN_MULT_PLUS_EXPR:
+ case WIDEN_MULT_MINUS_EXPR:
+ case DOT_PROD_EXPR:
+ case FMA_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
@@ -565,6 +570,9 @@ stmt_cost (gimple stmt)
case LSHIFT_EXPR:
case RSHIFT_EXPR:
+ case WIDEN_LSHIFT_EXPR:
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
cost += 20;
break;
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 02d91ca8bbd..75abb3369a1 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -2039,10 +2039,12 @@ is_widening_mult_rhs_p (tree type, tree rhs, tree *type_out,
and *TYPE2_OUT would give the operands of the multiplication. */
static bool
-is_widening_mult_p (tree type, gimple stmt,
+is_widening_mult_p (gimple stmt,
tree *type1_out, tree *rhs1_out,
tree *type2_out, tree *rhs2_out)
{
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+
if (TREE_CODE (type) != INTEGER_TYPE
&& TREE_CODE (type) != FIXED_POINT_TYPE)
return false;
@@ -2104,7 +2106,7 @@ convert_mult_to_widen (gimple stmt, gimple_stmt_iterator *gsi)
if (TREE_CODE (type) != INTEGER_TYPE)
return false;
- if (!is_widening_mult_p (type, stmt, &type1, &rhs1, &type2, &rhs2))
+ if (!is_widening_mult_p (stmt, &type1, &rhs1, &type2, &rhs2))
return false;
to_mode = TYPE_MODE (type);
@@ -2281,7 +2283,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
if (code == PLUS_EXPR
&& (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR))
{
- if (!is_widening_mult_p (type, rhs1_stmt, &type1, &mult_rhs1,
+ if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1,
&type2, &mult_rhs2))
return false;
add_rhs = rhs2;
@@ -2289,7 +2291,7 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt,
}
else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR)
{
- if (!is_widening_mult_p (type, rhs2_stmt, &type1, &mult_rhs1,
+ if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1,
&type2, &mult_rhs2))
return false;
add_rhs = rhs1;
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index a7f6cee35d8..60ae35cef73 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -3188,7 +3188,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
/* Fold the last statement. */
gsi = gsi_last (*stmts);
- fold_stmt_inplace (&gsi);
+ if (fold_stmt_inplace (&gsi))
+ update_stmt (gsi_stmt (gsi));
/* Add a value number to the temporary.
The value may already exist in either NEW_SETS, or AVAIL_OUT, because
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index 5107238093d..d42b46a1801 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see
#include "bitmap.h"
#include "langhooks.h"
#include "cfgloop.h"
+#include "params.h"
/* TODO:
1. Sinking store only using scalar promotion (IE without moving the RHS):
@@ -258,6 +259,71 @@ nearest_common_dominator_of_uses (gimple stmt, bool *debug_stmts)
return commondom;
}
+/* Given EARLY_BB and LATE_BB, two blocks in a path through the dominator
+ tree, return the best basic block between them (inclusive) to place
+ statements.
+
+ We want the most control dependent block in the shallowest loop nest.
+
+ If the resulting block is in a shallower loop nest, then use it. Else
+ only use the resulting block if it has significantly lower execution
+ frequency than EARLY_BB to avoid gratutious statement movement. We
+ consider statements with VOPS more desirable to move.
+
+ This pass would obviously benefit from PDO as it utilizes block
+ frequencies. It would also benefit from recomputing frequencies
+ if profile data is not available since frequencies often get out
+ of sync with reality. */
+
+static basic_block
+select_best_block (basic_block early_bb,
+ basic_block late_bb,
+ gimple stmt)
+{
+ basic_block best_bb = late_bb;
+ basic_block temp_bb = late_bb;
+ int threshold;
+
+ while (temp_bb != early_bb)
+ {
+ /* If we've moved into a lower loop nest, then that becomes
+ our best block. */
+ if (temp_bb->loop_depth < best_bb->loop_depth)
+ best_bb = temp_bb;
+
+ /* Walk up the dominator tree, hopefully we'll find a shallower
+ loop nest. */
+ temp_bb = get_immediate_dominator (CDI_DOMINATORS, temp_bb);
+ }
+
+ /* If we found a shallower loop nest, then we always consider that
+ a win. This will always give us the most control dependent block
+ within that loop nest. */
+ if (best_bb->loop_depth < early_bb->loop_depth)
+ return best_bb;
+
+ /* Get the sinking threshold. If the statement to be moved has memory
+ operands, then increase the threshold by 7% as those are even more
+ profitable to avoid, clamping at 100%. */
+ threshold = PARAM_VALUE (PARAM_SINK_FREQUENCY_THRESHOLD);
+ if (gimple_vuse (stmt) || gimple_vdef (stmt))
+ {
+ threshold += 7;
+ if (threshold > 100)
+ threshold = 100;
+ }
+
+ /* If BEST_BB is at the same nesting level, then require it to have
+ significantly lower execution frequency to avoid gratutious movement. */
+ if (best_bb->loop_depth == early_bb->loop_depth
+ && best_bb->frequency < (early_bb->frequency * threshold / 100.0))
+ return best_bb;
+
+ /* No better block found, so return EARLY_BB, which happens to be the
+ statement's original block. */
+ return early_bb;
+}
+
/* Given a statement (STMT) and the basic block it is currently in (FROMBB),
determine the location to sink the statement to, if any.
Returns true if there is such location; in that case, TOGSI points to the
@@ -379,24 +445,10 @@ statement_sink_location (gimple stmt, basic_block frombb,
if (!dominated_by_p (CDI_DOMINATORS, commondom, frombb))
return false;
- /* It doesn't make sense to move to a dominator that post-dominates
- frombb, because it means we've just moved it into a path that always
- executes if frombb executes, instead of reducing the number of
- executions . */
- if (dominated_by_p (CDI_POST_DOMINATORS, frombb, commondom))
- {
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "Not moving store, common dominator post-dominates from block.\n");
- return false;
- }
+ commondom = select_best_block (frombb, commondom, stmt);
- if (commondom == frombb || commondom->loop_depth > frombb->loop_depth)
- return false;
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Common dominator of all uses is %d\n",
- commondom->index);
- }
+ if (commondom == frombb)
+ return false;
*togsi = gsi_after_labels (commondom);
@@ -415,13 +467,9 @@ statement_sink_location (gimple stmt, basic_block frombb,
if (gimple_code (use) != GIMPLE_PHI)
{
sinkbb = gimple_bb (use);
- if (sinkbb == frombb || sinkbb->loop_depth > frombb->loop_depth
- || sinkbb->loop_father != frombb->loop_father)
- return false;
+ sinkbb = select_best_block (frombb, gimple_bb (use), stmt);
- /* Move the expression to a post dominator can't reduce the number of
- executions. */
- if (dominated_by_p (CDI_POST_DOMINATORS, frombb, sinkbb))
+ if (sinkbb == frombb)
return false;
*togsi = gsi_for_stmt (use);
@@ -431,21 +479,13 @@ statement_sink_location (gimple stmt, basic_block frombb,
}
sinkbb = find_bb_for_arg (use, DEF_FROM_PTR (def_p));
- if (!sinkbb)
- return false;
-
- /* This will happen when you have
- a_3 = PHI <a_13, a_26>
-
- a_26 = VDEF <a_3>
-
- If the use is a phi, and is in the same bb as the def,
- we can't sink it. */
- if (gimple_bb (use) == frombb)
+ /* This can happen if there are multiple uses in a PHI. */
+ if (!sinkbb)
return false;
- if (sinkbb == frombb || sinkbb->loop_depth > frombb->loop_depth
- || sinkbb->loop_father != frombb->loop_father)
+
+ sinkbb = select_best_block (frombb, sinkbb, stmt);
+ if (!sinkbb || sinkbb == frombb)
return false;
/* If the latch block is empty, don't make it non-empty by sinking
@@ -454,11 +494,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
&& empty_block_p (sinkbb))
return false;
- /* Move the expression to a post dominator can't reduce the number of
- executions. */
- if (dominated_by_p (CDI_POST_DOMINATORS, frombb, sinkbb))
- return false;
-
*togsi = gsi_after_labels (sinkbb);
return true;
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 697340f535a..a37633a920f 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-propagate.h"
#include "gimple-pretty-print.h"
#include "params.h"
+#include "expr.h"
/* A vector indexed by SSA_NAME_VERSION. 0 means unknown, positive value
is an index into strinfo vector, negative value stands for
@@ -176,7 +177,7 @@ get_addr_stridx (tree exp)
static int
get_stridx (tree exp)
{
- tree l;
+ tree s, o;
if (TREE_CODE (exp) == SSA_NAME)
return VEC_index (int, ssa_ver_to_stridx, SSA_NAME_VERSION (exp));
@@ -188,14 +189,17 @@ get_stridx (tree exp)
return idx;
}
- l = c_strlen (exp, 0);
- if (l != NULL_TREE
- && host_integerp (l, 1))
+ s = string_constant (exp, &o);
+ if (s != NULL_TREE
+ && (o == NULL_TREE || host_integerp (o, 0))
+ && TREE_STRING_LENGTH (s) > 0)
{
- unsigned HOST_WIDE_INT len = tree_low_cst (l, 1);
- if (len == (unsigned int) len
- && (int) len >= 0)
- return ~(int) len;
+ HOST_WIDE_INT offset = o ? tree_low_cst (o, 0) : 0;
+ const char *p = TREE_STRING_POINTER (s);
+ int max = TREE_STRING_LENGTH (s) - 1;
+
+ if (p[max] == '\0' && offset >= 0 && offset <= max)
+ return ~(int) strlen (p + offset);
}
return 0;
}
@@ -397,7 +401,7 @@ get_string_length (strinfo si)
callee = gimple_call_fndecl (stmt);
gcc_assert (callee && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL);
lhs = gimple_call_lhs (stmt);
- gcc_assert (builtin_decl_implicit_p (BUILT_IN_STRCPY));
+ gcc_assert (builtin_decl_implicit_p (BUILT_IN_STPCPY));
/* unshare_strinfo is intentionally not called here. The (delayed)
transformation of strcpy or strcat into stpcpy is done at the place
of the former strcpy/strcat call and so can affect all the strinfos
@@ -588,13 +592,13 @@ zero_length_string (tree ptr, strinfo chainsi)
|| si->prev != chainsi->idx)
break;
}
- gcc_assert (chainsi->length);
+ gcc_assert (chainsi->length || chainsi->stmt);
if (chainsi->endptr == NULL_TREE)
{
chainsi = unshare_strinfo (chainsi);
chainsi->endptr = ptr;
}
- if (integer_zerop (chainsi->length))
+ if (chainsi->length && integer_zerop (chainsi->length))
{
if (chainsi->next)
{
@@ -626,6 +630,8 @@ zero_length_string (tree ptr, strinfo chainsi)
if (chainsi->first == 0)
chainsi->first = chainsi->idx;
chainsi->next = idx;
+ if (chainsi->endptr == NULL_TREE)
+ chainsi->endptr = ptr;
si->prev = chainsi->idx;
si->first = chainsi->first;
si->writable = chainsi->writable;
@@ -654,11 +660,19 @@ adjust_related_strinfos (location_t loc, strinfo origsi, tree adj)
tree tem;
si = unshare_strinfo (si);
- gcc_assert (si->length);
- tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
- si->length = fold_build2_loc (loc, PLUS_EXPR,
- TREE_TYPE (si->length), si->length,
- tem);
+ if (si->length)
+ {
+ tem = fold_convert_loc (loc, TREE_TYPE (si->length), adj);
+ si->length = fold_build2_loc (loc, PLUS_EXPR,
+ TREE_TYPE (si->length), si->length,
+ tem);
+ }
+ else if (si->stmt != NULL)
+ /* Delayed length computation is unaffected. */
+ ;
+ else
+ gcc_unreachable ();
+
si->endptr = NULL_TREE;
si->dont_invalidate = true;
}
@@ -1117,10 +1131,30 @@ handle_builtin_strcpy (enum built_in_function bcode, gimple_stmt_iterator *gsi)
if (dsi->length == NULL_TREE)
{
+ strinfo chainsi;
+
/* If string length of src is unknown, use delayed length
computation. If string lenth of dst will be needed, it
can be computed by transforming this strcpy call into
stpcpy and subtracting dst from the return value. */
+
+ /* Look for earlier strings whose length could be determined if
+ this strcpy is turned into an stpcpy. */
+
+ if (dsi->prev != 0 && (chainsi = verify_related_strinfos (dsi)) != NULL)
+ {
+ for (; chainsi && chainsi != dsi; chainsi = get_strinfo (chainsi->next))
+ {
+ /* When setting a stmt for delayed length computation
+ prevent all strinfos through dsi from being
+ invalidated. */
+ chainsi = unshare_strinfo (chainsi);
+ chainsi->stmt = stmt;
+ chainsi->length = NULL_TREE;
+ chainsi->endptr = NULL_TREE;
+ chainsi->dont_invalidate = true;
+ }
+ }
dsi->stmt = stmt;
return;
}
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 7de22aabcb3..51f2aa1bf7c 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -261,9 +261,6 @@ struct variable_info
/* True if this is a heap variable. */
unsigned int is_heap_var : 1;
- /* True if this is a variable tracking a restrict pointer source. */
- unsigned int is_restrict_var : 1;
-
/* True if this field may contain pointers. */
unsigned int may_have_pointers : 1;
@@ -350,7 +347,6 @@ new_var_info (tree t, const char *name)
ret->is_unknown_size_var = false;
ret->is_full_var = (t == NULL_TREE);
ret->is_heap_var = false;
- ret->is_restrict_var = false;
ret->may_have_pointers = true;
ret->only_restrict_pointers = false;
ret->is_global_var = (t == NULL_TREE);
@@ -3643,30 +3639,30 @@ make_heapvar (const char *name)
}
/* Create a new artificial heap variable with NAME and make a
- constraint from it to LHS. Return the created variable. */
+ constraint from it to LHS. Set flags according to a tag used
+ for tracking restrict pointers. */
static varinfo_t
-make_constraint_from_heapvar (varinfo_t lhs, const char *name)
+make_constraint_from_restrict (varinfo_t lhs, const char *name)
{
varinfo_t vi = make_heapvar (name);
+ vi->is_global_var = 1;
+ vi->may_have_pointers = 1;
make_constraint_from (lhs, vi->id);
-
return vi;
}
/* Create a new artificial heap variable with NAME and make a
constraint from it to LHS. Set flags according to a tag used
- for tracking restrict pointers. */
+ for tracking restrict pointers and make the artificial heap
+ point to global memory. */
-static void
-make_constraint_from_restrict (varinfo_t lhs, const char *name)
+static varinfo_t
+make_constraint_from_global_restrict (varinfo_t lhs, const char *name)
{
- varinfo_t vi;
- vi = make_constraint_from_heapvar (lhs, name);
- vi->is_restrict_var = 1;
- vi->is_global_var = 0;
- vi->is_special_var = 1;
- vi->may_have_pointers = 0;
+ varinfo_t vi = make_constraint_from_restrict (lhs, name);
+ make_copy_constraint (vi, nonlocal_id);
+ return vi;
}
/* In IPA mode there are varinfos for different aspects of reach
@@ -5504,13 +5500,18 @@ create_variable_info_for (tree decl, const char *name)
if ((POINTER_TYPE_P (TREE_TYPE (decl))
&& TYPE_RESTRICT (TREE_TYPE (decl)))
|| vi->only_restrict_pointers)
- make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
+ {
+ make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
+ continue;
+ }
/* In non-IPA mode the initializer from nonlocal is all we need. */
if (!in_ipa_mode
|| DECL_HARD_REGISTER (decl))
make_copy_constraint (vi, nonlocal_id);
+ /* In IPA mode parse the initializer and generate proper constraints
+ for it. */
else
{
struct varpool_node *vnode = varpool_get_node (decl);
@@ -5595,7 +5596,7 @@ intra_create_variable_infos (void)
passed-by-reference argument. */
for (t = DECL_ARGUMENTS (current_function_decl); t; t = DECL_CHAIN (t))
{
- varinfo_t p;
+ varinfo_t p = get_vi_for_tree (t);
/* For restrict qualified pointers to objects passed by
reference build a real representative for the pointed-to object.
@@ -5610,34 +5611,37 @@ intra_create_variable_infos (void)
DECL_EXTERNAL (heapvar) = 1;
vi = create_variable_info_for_1 (heapvar, "PARM_NOALIAS");
insert_vi_for_tree (heapvar, vi);
- lhsc.var = get_vi_for_tree (t)->id;
+ lhsc.var = p->id;
lhsc.type = SCALAR;
lhsc.offset = 0;
rhsc.var = vi->id;
rhsc.type = ADDRESSOF;
rhsc.offset = 0;
process_constraint (new_constraint (lhsc, rhsc));
- vi->is_restrict_var = 1;
for (; vi; vi = vi->next)
if (vi->may_have_pointers)
{
if (vi->only_restrict_pointers)
- make_constraint_from_restrict (vi, "GLOBAL_RESTRICT");
- make_copy_constraint (vi, nonlocal_id);
+ make_constraint_from_global_restrict (vi, "GLOBAL_RESTRICT");
+ else
+ make_copy_constraint (vi, nonlocal_id);
}
continue;
}
- for (p = get_vi_for_tree (t); p; p = p->next)
- {
- if (p->may_have_pointers)
- make_constraint_from (p, nonlocal_id);
- if (p->only_restrict_pointers)
- make_constraint_from_restrict (p, "PARM_RESTRICT");
- }
if (POINTER_TYPE_P (TREE_TYPE (t))
&& TYPE_RESTRICT (TREE_TYPE (t)))
- make_constraint_from_restrict (get_vi_for_tree (t), "PARM_RESTRICT");
+ make_constraint_from_global_restrict (p, "PARM_RESTRICT");
+ else
+ {
+ for (; p; p = p->next)
+ {
+ if (p->only_restrict_pointers)
+ make_constraint_from_global_restrict (p, "PARM_RESTRICT");
+ else if (p->may_have_pointers)
+ make_constraint_from (p, nonlocal_id);
+ }
+ }
}
/* Add a constraint for a result decl that is passed by reference. */
@@ -5813,15 +5817,11 @@ find_what_var_points_to (varinfo_t orig_vi, struct pt_solution *pt)
|| vi->id == integer_id)
pt->anything = 1;
}
- if (vi->is_restrict_var)
- pt->vars_contains_restrict = true;
}
/* Instead of doing extra work, simply do not create
elaborate points-to information for pt_anything pointers. */
- if (pt->anything
- && (orig_vi->is_artificial_var
- || !pt->vars_contains_restrict))
+ if (pt->anything)
return;
/* Share the final set of variables when possible. */
@@ -5912,13 +5912,11 @@ pt_solution_reset (struct pt_solution *pt)
it contains restrict tag variables. */
void
-pt_solution_set (struct pt_solution *pt, bitmap vars,
- bool vars_contains_global, bool vars_contains_restrict)
+pt_solution_set (struct pt_solution *pt, bitmap vars, bool vars_contains_global)
{
memset (pt, 0, sizeof (struct pt_solution));
pt->vars = vars;
pt->vars_contains_global = vars_contains_global;
- pt->vars_contains_restrict = vars_contains_restrict;
}
/* Set the points-to solution *PT to point only to the variable VAR. */
@@ -5953,7 +5951,6 @@ pt_solution_ior_into (struct pt_solution *dest, struct pt_solution *src)
dest->ipa_escaped |= src->ipa_escaped;
dest->null |= src->null;
dest->vars_contains_global |= src->vars_contains_global;
- dest->vars_contains_restrict |= src->vars_contains_restrict;
if (!src->vars)
return;
@@ -6141,27 +6138,6 @@ pt_solutions_intersect (struct pt_solution *pt1, struct pt_solution *pt2)
return res;
}
-/* Return true if both points-to solutions PT1 and PT2 for two restrict
- qualified pointers are possibly based on the same pointer. */
-
-bool
-pt_solutions_same_restrict_base (struct pt_solution *pt1,
- struct pt_solution *pt2)
-{
- /* If we deal with points-to solutions of two restrict qualified
- pointers solely rely on the pointed-to variable bitmap intersection.
- For two pointers that are based on each other the bitmaps will
- intersect. */
- if (pt1->vars_contains_restrict
- && pt2->vars_contains_restrict)
- {
- gcc_assert (pt1->vars && pt2->vars);
- return bitmap_intersect_p (pt1->vars, pt2->vars);
- }
-
- return true;
-}
-
/* Dump points-to information to OUTFILE. */
@@ -6574,7 +6550,6 @@ compute_points_to_sets (void)
/* Mark escaped HEAP variables as global. */
FOR_EACH_VEC_ELT (varinfo_t, varmap, i, vi)
if (vi->is_heap_var
- && !vi->is_restrict_var
&& !vi->is_global_var)
DECL_EXTERNAL (vi->decl) = vi->is_global_var
= pt_solution_includes (&cfun->gimple_df->escaped, vi->decl);
@@ -6794,7 +6769,7 @@ gate_ipa_pta (void)
/* IPA PTA solutions for ESCAPED. */
struct pt_solution ipa_escaped_pt
- = { true, false, false, false, false, false, false, NULL };
+ = { true, false, false, false, false, false, NULL };
/* Associate node with varinfo DATA. Worker for
cgraph_for_node_and_aliases. */
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index 611a30f23a4..17e7f374b05 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -753,6 +753,19 @@ delete_basic_block_same_succ (basic_block bb)
bitmap_set_bit (deleted_bb_preds, e->src->index);
}
+/* Removes BB from its corresponding same_succ. */
+
+static void
+same_succ_flush_bb (basic_block bb)
+{
+ same_succ same = BB_SAME_SUCC (bb);
+ BB_SAME_SUCC (bb) = NULL;
+ if (bitmap_single_bit_set_p (same->bbs))
+ htab_remove_elt_with_hash (same_succ_htab, same, same->hashval);
+ else
+ bitmap_clear_bit (same->bbs, bb->index);
+}
+
/* Removes all bbs in BBS from their corresponding same_succ. */
static void
@@ -762,15 +775,38 @@ same_succ_flush_bbs (bitmap bbs)
bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (bbs, 0, i, bi)
+ same_succ_flush_bb (BASIC_BLOCK (i));
+}
+
+/* Release the last vdef in BB, either normal or phi result. */
+
+static void
+release_last_vdef (basic_block bb)
+{
+ gimple_stmt_iterator i;
+
+ for (i = gsi_last_bb (bb); !gsi_end_p (i); gsi_prev_nondebug (&i))
{
- basic_block bb = BASIC_BLOCK (i);
- same_succ same = BB_SAME_SUCC (bb);
- BB_SAME_SUCC (bb) = NULL;
- if (bitmap_single_bit_set_p (same->bbs))
- htab_remove_elt_with_hash (same_succ_htab, same, same->hashval);
- else
- bitmap_clear_bit (same->bbs, i);
+ gimple stmt = gsi_stmt (i);
+ if (gimple_vdef (stmt) == NULL_TREE)
+ continue;
+
+ mark_virtual_operand_for_renaming (gimple_vdef (stmt));
+ return;
}
+
+ for (i = gsi_start_phis (bb); !gsi_end_p (i); gsi_next (&i))
+ {
+ gimple phi = gsi_stmt (i);
+ tree res = gimple_phi_result (phi);
+
+ if (is_gimple_reg (res))
+ continue;
+
+ mark_virtual_phi_result_for_renaming (phi);
+ return;
+ }
+
}
/* Delete all deleted_bbs. */
@@ -778,14 +814,6 @@ same_succ_flush_bbs (bitmap bbs)
static void
purge_bbs (void)
{
- unsigned int i;
- bitmap_iterator bi;
-
- same_succ_flush_bbs (deleted_bbs);
-
- EXECUTE_IF_SET_IN_BITMAP (deleted_bbs, 0, i, bi)
- delete_basic_block (BASIC_BLOCK (i));
-
bitmap_and_compl_into (deleted_bb_preds, deleted_bbs);
bitmap_clear (deleted_bbs);
}
@@ -1325,26 +1353,56 @@ find_clusters (void)
}
}
+/* Replace uses of the result of PHI with NAME. */
+
+static void
+unlink_virtual_phi (gimple phi, tree name)
+{
+ use_operand_p use_p;
+ imm_use_iterator iter;
+ gimple use_stmt;
+ tree vdef = gimple_phi_result (phi);
+
+ if (!vdef
+ || TREE_CODE (vdef) != SSA_NAME)
+ return;
+
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, vdef)
+ {
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, name);
+ }
+
+ if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (vdef))
+ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name) = 1;
+}
+
/* Create or update a vop phi in BB2. Use VUSE1 arguments for all the
REDIRECTED_EDGES, or if VUSE1 is NULL_TREE, use BB_VOP_AT_EXIT. If a new
phis is created, use the phi instead of VUSE2 in BB2. */
static void
-update_vuses (tree vuse1, tree vuse2, basic_block bb2,
+update_vuses (bool vuse1_phi_args, tree vuse1, tree vuse2, basic_block bb2,
VEC (edge,heap) *redirected_edges)
{
gimple stmt, phi = NULL;
- tree lhs = NULL_TREE, arg;
+ tree lhs = NULL_TREE, arg, var;
unsigned int i;
- gimple def_stmt2;
+ gimple def_stmt2 = NULL;
imm_use_iterator iter;
use_operand_p use_p;
edge_iterator ei;
edge e;
- def_stmt2 = SSA_NAME_DEF_STMT (vuse2);
+ if (vuse2 != NULL_TREE)
+ {
+ var = SSA_NAME_VAR (vuse2);
+ def_stmt2 = SSA_NAME_DEF_STMT (vuse2);
+ }
+ else
+ var = SSA_NAME_VAR (vuse1);
- if (gimple_bb (def_stmt2) == bb2)
+ if (def_stmt2 && gimple_bb (def_stmt2) == bb2)
/* Update existing phi. */
phi = def_stmt2;
else
@@ -1354,38 +1412,41 @@ update_vuses (tree vuse1, tree vuse2, basic_block bb2,
return;
/* Create a phi. */
- lhs = make_ssa_name (SSA_NAME_VAR (vuse2), NULL);
+ lhs = make_ssa_name (var, NULL);
VN_INFO_GET (lhs);
phi = create_phi_node (lhs, bb2);
SSA_NAME_DEF_STMT (lhs) = phi;
/* Set default argument vuse2 for all preds. */
+ arg = vuse2 == NULL_TREE ? gimple_phi_result (phi): vuse2;
FOR_EACH_EDGE (e, ei, bb2->preds)
- add_phi_arg (phi, vuse2, e, UNKNOWN_LOCATION);
+ add_phi_arg (phi, arg, e, UNKNOWN_LOCATION);
}
/* Update phi. */
for (i = 0; i < EDGE_COUNT (redirected_edges); ++i)
{
e = VEC_index (edge, redirected_edges, i);
- if (vuse1 != NULL_TREE)
- arg = vuse1;
- else
+ if (vuse1_phi_args)
arg = BB_VOP_AT_EXIT (e->src);
+ else
+ arg = vuse1 == NULL_TREE ? gimple_phi_result (phi): vuse1;
+
add_phi_arg (phi, arg, e, UNKNOWN_LOCATION);
}
/* Return if we updated an existing phi. */
- if (gimple_bb (def_stmt2) == bb2)
+ if (def_stmt2 && gimple_bb (def_stmt2) == bb2)
return;
- /* Replace relevant uses of vuse2 with the newly created phi. */
- FOR_EACH_IMM_USE_STMT (stmt, iter, vuse2)
+ /* Replace relevant uses with the newly created phi. */
+ FOR_EACH_IMM_USE_STMT (stmt, iter, vuse2 == NULL_TREE ? vuse1 : vuse2)
{
if (stmt == phi)
continue;
- if (gimple_code (stmt) != GIMPLE_PHI)
- if (gimple_bb (stmt) != bb2)
+
+ if (gimple_code (stmt) != GIMPLE_PHI
+ && !dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), bb2))
continue;
FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
@@ -1394,8 +1455,16 @@ update_vuses (tree vuse1, tree vuse2, basic_block bb2,
{
unsigned int pred_index = PHI_ARG_INDEX_FROM_USE (use_p);
basic_block pred = EDGE_PRED (gimple_bb (stmt), pred_index)->src;
- if (pred != bb2)
+ if (!dominated_by_p (CDI_DOMINATORS, pred, bb2))
continue;
+
+ if (pred == bb2 && EDGE_COUNT (gimple_bb (stmt)->preds) == 1)
+ {
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ unlink_virtual_phi (stmt, lhs);
+ remove_phi_node (&gsi, true);
+ break;
+ }
}
SET_USE (use_p, lhs);
update_stmt (stmt);
@@ -1457,6 +1526,88 @@ vop_at_entry (basic_block bb)
: NULL_TREE);
}
+/* Given that all incoming edges of BB1 have been redirected to BB2, delete BB1
+ and recompute dominator info. */
+
+static void
+delete_block_update_dominator_info (basic_block bb1, basic_block bb2)
+{
+ VEC (basic_block,heap) *fix_dom_bb;
+ unsigned int i;
+ basic_block bb, dom;
+ edge e;
+ edge_iterator ei;
+
+ /* Consider the following cfg, where A is the direct dominator of I:
+
+ A
+ / \
+ B \
+ / \ \
+ C D
+ /| |\
+ E F
+ |\ /|
+ | x |
+ |/ \|
+ G H
+ \ /
+ I
+
+ Say E and F are duplicates, and F is removed. The cfg then looks like
+ this:
+
+ A
+ / \
+ B \
+ / \ \
+ C D
+ / \ / \
+ E
+ / \
+ G H
+ \ /
+ I
+
+ E is now the new direct dominator of I.
+
+ In order to calculate the new dominator info, we take the nearest common
+ dominator (A) of bb1 (F) and bb2 (E), and get the set of bbs immediately
+ dominated by it. Some of this set may now be directly dominated by bb2.
+
+ Ideally we would have a means to determine which bbs in the set are now
+ dominated by bb2, and call set_immediate_dominator for those bbs, but we
+ don't, so instead we let iterate_fix_dominators figure it out. */
+
+ /* Add bbs immediately dominated by the most common dominator. */
+ dom = nearest_common_dominator (CDI_DOMINATORS, bb1, bb2);
+ fix_dom_bb = get_dominated_by (CDI_DOMINATORS, dom);
+
+ if (get_immediate_dominator (CDI_DOMINATORS, bb1) == dom)
+ for (i = 0; VEC_iterate (basic_block, fix_dom_bb, i, bb); ++i)
+ {
+ if (bb != bb1)
+ continue;
+ VEC_unordered_remove (basic_block, fix_dom_bb, i);
+ break;
+ }
+
+ /* Add bb2, but not twice. */
+ if (get_immediate_dominator (CDI_DOMINATORS, bb2) != dom)
+ VEC_safe_push (basic_block, heap, fix_dom_bb, bb2);
+ /* Add succs of bb2, but not twice. */
+ FOR_EACH_EDGE (e, ei, bb2->succs)
+ if (get_immediate_dominator (CDI_DOMINATORS, e->dest) != dom)
+ VEC_safe_push (basic_block, heap, fix_dom_bb, e->dest);
+
+ delete_basic_block (bb1);
+ iterate_fix_dominators (CDI_DOMINATORS, fix_dom_bb, false);
+#if defined (ENABLE_CHECKING)
+ verify_dominators (CDI_DOMINATORS);
+#endif
+ VEC_free (basic_block, heap, fix_dom_bb);
+}
+
/* Redirect all edges from BB1 to BB2, marks BB1 for removal, and if
UPDATE_VOPS, inserts vop phis. */
@@ -1469,18 +1620,28 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
VEC (edge,heap) *redirected_edges = NULL;
edge e;
edge_iterator ei;
+ bool vuse1_phi_args = false;
+
+ phi_vuse2 = vop_at_entry (bb2);
+ if (phi_vuse2 != NULL_TREE && TREE_CODE (phi_vuse2) != SSA_NAME)
+ phi_vuse2 = NULL_TREE;
if (update_vops)
{
/* Find the vops at entry of bb1 and bb2. */
phi_vuse1 = vop_at_entry (bb1);
- phi_vuse2 = vop_at_entry (bb2);
- /* If one of the 2 not found, it means there's no need to update. */
- update_vops = phi_vuse1 != NULL_TREE && phi_vuse2 != NULL_TREE;
+ /* If both are not found, it means there's no need to update. Uses old
+ dominator info. */
+ if (phi_vuse1 == NULL_TREE && phi_vuse2 == NULL_TREE)
+ update_vops = false;
+ else if (phi_vuse1 == NULL_TREE)
+ update_vops = dominated_by_p (CDI_DOMINATORS, bb1, bb2);
+ else if (phi_vuse2 == NULL_TREE)
+ update_vops = dominated_by_p (CDI_DOMINATORS, bb2, bb1);
}
- if (update_vops && gimple_bb (SSA_NAME_DEF_STMT (phi_vuse1)) == bb1)
+ if (phi_vuse1 && gimple_bb (SSA_NAME_DEF_STMT (phi_vuse1)) == bb1)
{
/* If the vop at entry of bb1 is a phi, save the phi alternatives in
BB_VOP_AT_EXIT, before we lose that information by redirecting the
@@ -1490,7 +1651,7 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
arg = PHI_ARG_DEF_FROM_EDGE (SSA_NAME_DEF_STMT (phi_vuse1), e);
BB_VOP_AT_EXIT (e->src) = arg;
}
- phi_vuse1 = NULL;
+ vuse1_phi_args = true;
}
/* Mark the basic block for later deletion. */
@@ -1507,12 +1668,23 @@ replace_block_by (basic_block bb1, basic_block bb2, bool update_vops)
gcc_assert (pred_edge != NULL);
if (update_vops)
VEC_safe_push (edge, heap, redirected_edges, pred_edge);
+ else if (phi_vuse2 && gimple_bb (SSA_NAME_DEF_STMT (phi_vuse2)) == bb2)
+ add_phi_arg (SSA_NAME_DEF_STMT (phi_vuse2), SSA_NAME_VAR (phi_vuse2),
+ pred_edge, UNKNOWN_LOCATION);
}
- /* Update the vops. */
+ /* Do updates that use bb1, before deleting bb1. */
+ if (!update_vops)
+ release_last_vdef (bb1);
+ same_succ_flush_bb (bb1);
+
+ delete_block_update_dominator_info (bb1, bb2);
+
+ /* Update the vops. Uses new dominator info. */
if (update_vops)
{
- update_vuses (phi_vuse1, phi_vuse2, bb2, redirected_edges);
+ update_vuses (vuse1_phi_args, phi_vuse1, phi_vuse2, bb2,
+ redirected_edges);
VEC_free (edge, heap, redirected_edges);
}
}
@@ -1664,13 +1836,11 @@ tail_merge_optimize (unsigned int todo)
if (nr_bbs_removed == 0)
break;
- free_dominance_info (CDI_DOMINATORS);
purge_bbs ();
if (iteration_nr == max_iterations)
break;
- calculate_dominance_info (CDI_DOMINATORS);
update_worklist ();
}
@@ -1680,7 +1850,6 @@ tail_merge_optimize (unsigned int todo)
if (nr_bbs_removed_total > 0)
{
- calculate_dominance_info (CDI_DOMINATORS);
update_debug_stmts ();
if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 258a7444b08..8f73d9176f2 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1963,6 +1963,8 @@ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs)
a non-register. Otherwise we are confused and forget to
add virtual operands for it. */
&& (!is_gimple_reg_type (TREE_TYPE (var))
+ || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE
+ || TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
|| !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
{
TREE_ADDRESSABLE (var) = 0;
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index db2bb376432..86eb9ce20b2 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -130,7 +130,10 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
TREE_PROTECTED (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TYPE_P (expr))
- TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
+ {
+ TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
+ TYPE_ADDR_SPACE (expr) = (unsigned) bp_unpack_value (bp, 8);
+ }
else if (TREE_CODE (expr) == SSA_NAME)
SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
else
diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c
index 58be0a385a0..c46859f1989 100644
--- a/gcc/tree-streamer-out.c
+++ b/gcc/tree-streamer-out.c
@@ -100,7 +100,10 @@ pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, TREE_PROTECTED (expr), 1);
bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
if (TYPE_P (expr))
- bp_pack_value (bp, TYPE_SATURATING (expr), 1);
+ {
+ bp_pack_value (bp, TYPE_SATURATING (expr), 1);
+ bp_pack_value (bp, TYPE_ADDR_SPACE (expr), 8);
+ }
else if (TREE_CODE (expr) == SSA_NAME)
bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
else
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index a9504cd2362..a239216cf2d 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -555,8 +555,7 @@ vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo)
static bool
vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
- loop_vec_info loop_vinfo, int *max_vf,
- bool *data_dependence_in_bb)
+ loop_vec_info loop_vinfo, int *max_vf)
{
unsigned int i;
struct loop *loop = NULL;
@@ -587,6 +586,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
{
+ gimple earlier_stmt;
+
if (loop_vinfo)
{
if (vect_print_dump_info (REPORT_DR_DETAILS))
@@ -624,10 +625,11 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
return true;
- /* We deal with read-write dependencies in basic blocks later (by
- verifying that all the loads in the basic block are before all the
- stores). */
- *data_dependence_in_bb = true;
+ /* Check that it's not a load-after-store dependence. */
+ earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb));
+ if (DR_IS_WRITE (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt))))
+ return true;
+
return false;
}
@@ -753,8 +755,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
bool
vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
- bb_vec_info bb_vinfo, int *max_vf,
- bool *data_dependence_in_bb)
+ bb_vec_info bb_vinfo, int *max_vf)
{
unsigned int i;
VEC (ddr_p, heap) *ddrs = NULL;
@@ -769,8 +770,7 @@ vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
ddrs = BB_VINFO_DDRS (bb_vinfo);
FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr)
- if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf,
- data_dependence_in_bb))
+ if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf))
return false;
return true;
@@ -2524,7 +2524,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
VEC (data_reference_p, heap) *datarefs;
struct data_reference *dr;
tree scalar_type;
- bool res;
+ bool res, stop_bb_analysis = false;
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vect_analyze_data_refs ===\n");
@@ -2579,12 +2579,19 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
fprintf (vect_dump, "not vectorized: unhandled data-ref ");
+
return false;
}
stmt = DR_STMT (dr);
stmt_info = vinfo_for_stmt (stmt);
+ if (stop_bb_analysis)
+ {
+ STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ continue;
+ }
+
/* Check that analysis of the data-ref succeeded. */
if (!DR_BASE_ADDRESS (dr) || !DR_OFFSET (dr) || !DR_INIT (dr)
|| !DR_STEP (dr))
@@ -2595,6 +2602,13 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
+ if (bb_vinfo)
+ {
+ STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ stop_bb_analysis = true;
+ continue;
+ }
+
return false;
}
@@ -2603,7 +2617,15 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
fprintf (vect_dump, "not vectorized: base addr of dr is a "
"constant");
- return false;
+
+ if (bb_vinfo)
+ {
+ STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ stop_bb_analysis = true;
+ continue;
+ }
+
+ return false;
}
if (TREE_THIS_VOLATILE (DR_REF (dr)))
@@ -2613,6 +2635,14 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
fprintf (vect_dump, "not vectorized: volatile type ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
+
+ if (bb_vinfo)
+ {
+ STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ stop_bb_analysis = true;
+ continue;
+ }
+
return false;
}
@@ -2628,6 +2658,14 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
"exception ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
+
+ if (bb_vinfo)
+ {
+ STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ stop_bb_analysis = true;
+ continue;
+ }
+
return false;
}
@@ -2745,6 +2783,14 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
"not vectorized: more than one data ref in stmt: ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
+
+ if (bb_vinfo)
+ {
+ STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ stop_bb_analysis = true;
+ continue;
+ }
+
return false;
}
@@ -2769,6 +2815,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo,
{
/* Mark the statement as not vectorizable. */
STMT_VINFO_VECTORIZABLE (stmt_info) = false;
+ stop_bb_analysis = true;
continue;
}
else
@@ -3420,7 +3467,7 @@ vect_create_destination_var (tree scalar_dest, tree vectype)
bool
vect_strided_store_supported (tree vectype, unsigned HOST_WIDE_INT count)
{
- optab interleave_high_optab, interleave_low_optab;
+ optab ih_optab, il_optab;
enum machine_mode mode;
mode = TYPE_MODE (vectype);
@@ -3435,26 +3482,22 @@ vect_strided_store_supported (tree vectype, unsigned HOST_WIDE_INT count)
}
/* Check that the operation is supported. */
- interleave_high_optab = optab_for_tree_code (VEC_INTERLEAVE_HIGH_EXPR,
- vectype, optab_default);
- interleave_low_optab = optab_for_tree_code (VEC_INTERLEAVE_LOW_EXPR,
- vectype, optab_default);
- if (!interleave_high_optab || !interleave_low_optab)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "no optab for interleave.");
- return false;
- }
+ ih_optab = optab_for_tree_code (VEC_INTERLEAVE_HIGH_EXPR,
+ vectype, optab_default);
+ il_optab = optab_for_tree_code (VEC_INTERLEAVE_LOW_EXPR,
+ vectype, optab_default);
+ if (il_optab && ih_optab
+ && optab_handler (ih_optab, mode) != CODE_FOR_nothing
+ && optab_handler (il_optab, mode) != CODE_FOR_nothing)
+ return true;
- if (optab_handler (interleave_high_optab, mode) == CODE_FOR_nothing
- || optab_handler (interleave_low_optab, mode) == CODE_FOR_nothing)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "interleave op not supported by target.");
- return false;
- }
+ if (can_vec_perm_for_code_p (VEC_INTERLEAVE_HIGH_EXPR, mode, NULL)
+ && can_vec_perm_for_code_p (VEC_INTERLEAVE_LOW_EXPR, mode, NULL))
+ return true;
- return true;
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "interleave op not supported by target.");
+ return false;
}
@@ -3876,7 +3919,7 @@ vect_setup_realignment (gimple stmt, gimple_stmt_iterator *gsi,
bool
vect_strided_load_supported (tree vectype, unsigned HOST_WIDE_INT count)
{
- optab perm_even_optab, perm_odd_optab;
+ optab ee_optab, eo_optab;
enum machine_mode mode;
mode = TYPE_MODE (vectype);
@@ -3890,38 +3933,22 @@ vect_strided_load_supported (tree vectype, unsigned HOST_WIDE_INT count)
return false;
}
- perm_even_optab = optab_for_tree_code (VEC_EXTRACT_EVEN_EXPR, vectype,
- optab_default);
- if (!perm_even_optab)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "no optab for perm_even.");
- return false;
- }
-
- if (optab_handler (perm_even_optab, mode) == CODE_FOR_nothing)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "perm_even op not supported by target.");
- return false;
- }
+ ee_optab = optab_for_tree_code (VEC_EXTRACT_EVEN_EXPR,
+ vectype, optab_default);
+ eo_optab = optab_for_tree_code (VEC_EXTRACT_ODD_EXPR,
+ vectype, optab_default);
+ if (ee_optab && eo_optab
+ && optab_handler (ee_optab, mode) != CODE_FOR_nothing
+ && optab_handler (eo_optab, mode) != CODE_FOR_nothing)
+ return true;
- perm_odd_optab = optab_for_tree_code (VEC_EXTRACT_ODD_EXPR, vectype,
- optab_default);
- if (!perm_odd_optab)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "no optab for perm_odd.");
- return false;
- }
+ if (can_vec_perm_for_code_p (VEC_EXTRACT_EVEN_EXPR, mode, NULL)
+ && can_vec_perm_for_code_p (VEC_EXTRACT_ODD_EXPR, mode, NULL))
+ return true;
- if (optab_handler (perm_odd_optab, mode) == CODE_FOR_nothing)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "perm_odd op not supported by target.");
- return false;
- }
- return true;
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "extract even/odd not supported by target");
+ return false;
}
/* Return TRUE if vec_load_lanes is available for COUNT vectors of
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 4e79b15ce04..6555932a4cc 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -125,8 +125,10 @@ static tree
do_binop (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
tree bitpos, tree bitsize, enum tree_code code)
{
- a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
- b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
+ if (TREE_CODE (TREE_TYPE (a)) == VECTOR_TYPE)
+ a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
+ if (TREE_CODE (TREE_TYPE (b)) == VECTOR_TYPE)
+ b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
return gimplify_build2 (gsi, code, inner_type, a, b);
}
@@ -641,13 +643,23 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
location_t loc = gimple_location (gsi_stmt (*gsi));
unsigned i;
- if (expand_vec_perm_expr_p (TYPE_MODE (vect_type), vec0, vec1, mask))
+ if (TREE_CODE (mask) == VECTOR_CST)
+ {
+ unsigned char *sel_int = XALLOCAVEC (unsigned char, elements);
+ tree vals = TREE_VECTOR_CST_ELTS (mask);
+
+ for (i = 0; i < elements; ++i, vals = TREE_CHAIN (vals))
+ sel_int[i] = TREE_INT_CST_LOW (TREE_VALUE (vals));
+
+ if (can_vec_perm_p (TYPE_MODE (vect_type), false, sel_int))
+ return;
+ }
+ else if (can_vec_perm_p (TYPE_MODE (vect_type), true, NULL))
return;
warning_at (loc, OPT_Wvector_operation_performance,
"vector shuffling operation will be expanded piecewise");
-
v = VEC_alloc (constructor_elt, gc, elements);
for (i = 0; i < elements; i++)
{
@@ -761,6 +773,15 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
|| code == VIEW_CONVERT_EXPR)
return;
+ /* These are only created by the vectorizer, after having queried
+ the target support. It's more than just looking at the optab,
+ and there's no need to do it again. */
+ if (code == VEC_INTERLEAVE_HIGH_EXPR
+ || code == VEC_INTERLEAVE_LOW_EXPR
+ || code == VEC_EXTRACT_EVEN_EXPR
+ || code == VEC_EXTRACT_ODD_EXPR)
+ return;
+
gcc_assert (code != CONVERT_EXPR);
/* The signedness is determined from input argument. */
@@ -775,60 +796,39 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
|| code == LROTATE_EXPR
|| code == RROTATE_EXPR)
{
- bool vector_scalar_shift;
- op = optab_for_tree_code (code, type, optab_scalar);
-
- /* Vector/Scalar shift is supported. */
- vector_scalar_shift = (op && (optab_handler (op, TYPE_MODE (type))
- != CODE_FOR_nothing));
-
- /* If the 2nd argument is vector, we need a vector/vector shift.
- Except all the elements in the second vector are the same. */
+ /* Check whether we have vector <op> {x,x,x,x} where x
+ could be a scalar variable or a constant. Transform
+ vector <op> {x,x,x,x} ==> vector <op> scalar. */
if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
{
tree first;
gimple def_stmt;
- /* Check whether we have vector <op> {x,x,x,x} where x
- could be a scalar variable or a constant. Transform
- vector <op> {x,x,x,x} ==> vector <op> scalar. */
- if (vector_scalar_shift
- && ((TREE_CODE (rhs2) == VECTOR_CST
- && (first = uniform_vector_p (rhs2)) != NULL_TREE)
- || (TREE_CODE (rhs2) == SSA_NAME
- && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
- && gimple_assign_single_p (def_stmt)
- && (first = uniform_vector_p
- (gimple_assign_rhs1 (def_stmt))) != NULL_TREE)))
+ if ((TREE_CODE (rhs2) == VECTOR_CST
+ && (first = uniform_vector_p (rhs2)) != NULL_TREE)
+ || (TREE_CODE (rhs2) == SSA_NAME
+ && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
+ && gimple_assign_single_p (def_stmt)
+ && (first = uniform_vector_p
+ (gimple_assign_rhs1 (def_stmt))) != NULL_TREE))
{
gimple_assign_set_rhs2 (stmt, first);
update_stmt (stmt);
rhs2 = first;
}
- else
- op = optab_for_tree_code (code, type, optab_vector);
}
- /* Try for a vector/scalar shift, and if we don't have one, see if we
- have a vector/vector shift */
- else if (!vector_scalar_shift)
+ if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
+ op = optab_for_tree_code (code, type, optab_vector);
+ else
{
- op = optab_for_tree_code (code, type, optab_vector);
+ op = optab_for_tree_code (code, type, optab_scalar);
- if (op && (optab_handler (op, TYPE_MODE (type))
- != CODE_FOR_nothing))
- {
- /* Transform vector <op> scalar => vector <op> {x,x,x,x}. */
- int n_parts = TYPE_VECTOR_SUBPARTS (type);
- int part_size = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
- tree part_type = lang_hooks.types.type_for_size (part_size, 1);
- tree vect_type = build_vector_type (part_type, n_parts);
-
- rhs2 = fold_convert (part_type, rhs2);
- rhs2 = build_vector_from_val (vect_type, rhs2);
- gimple_assign_set_rhs2 (stmt, rhs2);
- update_stmt (stmt);
- }
+ /* The rtl expander will expand vector/scalar as vector/vector
+ if necessary. Don't bother converting the stmt here. */
+ if (op == NULL
+ || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
+ op = optab_for_tree_code (code, type, optab_vector);
}
}
else
@@ -844,7 +844,9 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
|| code == VEC_UNPACK_LO_EXPR
|| code == VEC_PACK_TRUNC_EXPR
|| code == VEC_PACK_SAT_EXPR
- || code == VEC_PACK_FIX_TRUNC_EXPR)
+ || code == VEC_PACK_FIX_TRUNC_EXPR
+ || code == VEC_WIDEN_LSHIFT_HI_EXPR
+ || code == VEC_WIDEN_LSHIFT_LO_EXPR)
type = TREE_TYPE (rhs1);
/* Optabs will try converting a negation into a subtraction, so
@@ -874,12 +876,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
if (compute_type == type)
{
compute_mode = TYPE_MODE (compute_type);
- if ((GET_MODE_CLASS (compute_mode) == MODE_VECTOR_INT
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FLOAT
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_FRACT
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UFRACT
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_ACCUM
- || GET_MODE_CLASS (compute_mode) == MODE_VECTOR_UACCUM)
+ if (VECTOR_MODE_P (compute_mode)
&& op != NULL
&& optab_handler (op, compute_mode) != CODE_FOR_nothing)
return;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index ba8878a8663..a04099fc06a 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1473,7 +1473,7 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo, bool slp)
static bool
vect_analyze_loop_2 (loop_vec_info loop_vinfo)
{
- bool ok, dummy, slp = false;
+ bool ok, slp = false;
int max_vf = MAX_VECTORIZATION_FACTOR;
int min_vf = 2;
@@ -1514,7 +1514,7 @@ vect_analyze_loop_2 (loop_vec_info loop_vinfo)
the dependences.
FORNOW: fail at the first data dependence that we encounter. */
- ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL, &max_vf, &dummy);
+ ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL, &max_vf);
if (!ok
|| max_vf < min_vf)
{
@@ -4422,6 +4422,11 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
&& !SCALAR_FLOAT_TYPE_P (scalar_type))
return false;
+ /* Do not try to vectorize bit-precision reductions. */
+ if ((TYPE_PRECISION (scalar_type)
+ != GET_MODE_PRECISION (TYPE_MODE (scalar_type))))
+ return false;
+
/* All uses but the last are expected to be defined in the loop.
The last use is the reduction variable. In case of nested cycle this
assumption is not true: we use reduc_index to record the index of the
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 44a37b91e38..19b75e9e465 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -49,16 +49,23 @@ static gimple vect_recog_dot_prod_pattern (VEC (gimple, heap) **, tree *,
static gimple vect_recog_pow_pattern (VEC (gimple, heap) **, tree *, tree *);
static gimple vect_recog_over_widening_pattern (VEC (gimple, heap) **, tree *,
tree *);
+static gimple vect_recog_widen_shift_pattern (VEC (gimple, heap) **,
+ tree *, tree *);
+static gimple vect_recog_vector_vector_shift_pattern (VEC (gimple, heap) **,
+ tree *, tree *);
static gimple vect_recog_mixed_size_cond_pattern (VEC (gimple, heap) **,
tree *, tree *);
+static gimple vect_recog_bool_pattern (VEC (gimple, heap) **, tree *, tree *);
static vect_recog_func_ptr vect_vect_recog_func_ptrs[NUM_PATTERNS] = {
vect_recog_widen_mult_pattern,
vect_recog_widen_sum_pattern,
vect_recog_dot_prod_pattern,
vect_recog_pow_pattern,
vect_recog_over_widening_pattern,
- vect_recog_mixed_size_cond_pattern};
-
+ vect_recog_widen_shift_pattern,
+ vect_recog_vector_vector_shift_pattern,
+ vect_recog_mixed_size_cond_pattern,
+ vect_recog_bool_pattern};
/* Function widened_name_p
@@ -338,27 +345,37 @@ vect_recog_dot_prod_pattern (VEC (gimple, heap) **stmts, tree *type_in,
}
-/* Handle two cases of multiplication by a constant. The first one is when
- the constant, CONST_OPRND, fits the type (HALF_TYPE) of the second
- operand (OPRND). In that case, we can peform widen-mult from HALF_TYPE to
- TYPE.
+/* Handle widening operation by a constant. At the moment we support MULT_EXPR
+ and LSHIFT_EXPR.
+
+ For MULT_EXPR we check that CONST_OPRND fits HALF_TYPE, and for LSHIFT_EXPR
+ we check that CONST_OPRND is less or equal to the size of HALF_TYPE.
Otherwise, if the type of the result (TYPE) is at least 4 times bigger than
- HALF_TYPE, and CONST_OPRND fits an intermediate type (2 times smaller than
- TYPE), we can perform widen-mult from the intermediate type to TYPE and
- replace a_T = (TYPE) a_t; with a_it - (interm_type) a_t; */
+ HALF_TYPE, and there is an intermediate type (2 times smaller than TYPE)
+ that satisfies the above restrictions, we can perform a widening opeartion
+ from the intermediate type to TYPE and replace a_T = (TYPE) a_t;
+ with a_it = (interm_type) a_t; */
static bool
-vect_handle_widen_mult_by_const (gimple stmt, tree const_oprnd, tree *oprnd,
- VEC (gimple, heap) **stmts, tree type,
- tree *half_type, gimple def_stmt)
+vect_handle_widen_op_by_const (gimple stmt, enum tree_code code,
+ tree const_oprnd, tree *oprnd,
+ VEC (gimple, heap) **stmts, tree type,
+ tree *half_type, gimple def_stmt)
{
tree new_type, new_oprnd, tmp;
gimple new_stmt;
loop_vec_info loop_info = STMT_VINFO_LOOP_VINFO (vinfo_for_stmt (stmt));
struct loop *loop = LOOP_VINFO_LOOP (loop_info);
- if (int_fits_type_p (const_oprnd, *half_type))
+ if (code != MULT_EXPR && code != LSHIFT_EXPR)
+ return false;
+
+ if (((code == MULT_EXPR && int_fits_type_p (const_oprnd, *half_type))
+ || (code == LSHIFT_EXPR
+ && compare_tree_int (const_oprnd, TYPE_PRECISION (*half_type))
+ != 1))
+ && TYPE_PRECISION (type) == (TYPE_PRECISION (*half_type) * 2))
{
/* CONST_OPRND is a constant of HALF_TYPE. */
*oprnd = gimple_assign_rhs1 (def_stmt);
@@ -371,14 +388,16 @@ vect_handle_widen_mult_by_const (gimple stmt, tree const_oprnd, tree *oprnd,
|| !vinfo_for_stmt (def_stmt))
return false;
- /* TYPE is 4 times bigger than HALF_TYPE, try widen-mult for
+ /* TYPE is 4 times bigger than HALF_TYPE, try widening operation for
a type 2 times bigger than HALF_TYPE. */
new_type = build_nonstandard_integer_type (TYPE_PRECISION (type) / 2,
TYPE_UNSIGNED (type));
- if (!int_fits_type_p (const_oprnd, new_type))
+ if ((code == MULT_EXPR && !int_fits_type_p (const_oprnd, new_type))
+ || (code == LSHIFT_EXPR
+ && compare_tree_int (const_oprnd, TYPE_PRECISION (new_type)) == 1))
return false;
- /* Use NEW_TYPE for widen_mult. */
+ /* Use NEW_TYPE for widening operation. */
if (STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)))
{
new_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt));
@@ -498,7 +517,7 @@ vect_recog_widen_mult_pattern (VEC (gimple, heap) **stmts,
enum tree_code dummy_code;
int dummy_int;
VEC (tree, heap) *dummy_vec;
- bool op0_ok, op1_ok;
+ bool op1_ok;
if (!is_gimple_assign (last_stmt))
return NULL;
@@ -518,38 +537,23 @@ vect_recog_widen_mult_pattern (VEC (gimple, heap) **stmts,
return NULL;
/* Check argument 0. */
- op0_ok = widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false);
+ if (!widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false))
+ return NULL;
/* Check argument 1. */
op1_ok = widened_name_p (oprnd1, last_stmt, &half_type1, &def_stmt1, false);
- /* In case of multiplication by a constant one of the operands may not match
- the pattern, but not both. */
- if (!op0_ok && !op1_ok)
- return NULL;
-
- if (op0_ok && op1_ok)
+ if (op1_ok)
{
oprnd0 = gimple_assign_rhs1 (def_stmt0);
oprnd1 = gimple_assign_rhs1 (def_stmt1);
}
- else if (!op0_ok)
- {
- if (TREE_CODE (oprnd0) == INTEGER_CST
- && TREE_CODE (half_type1) == INTEGER_TYPE
- && vect_handle_widen_mult_by_const (last_stmt, oprnd0, &oprnd1,
- stmts, type,
- &half_type1, def_stmt1))
- half_type0 = half_type1;
- else
- return NULL;
- }
- else if (!op1_ok)
+ else
{
if (TREE_CODE (oprnd1) == INTEGER_CST
&& TREE_CODE (half_type0) == INTEGER_TYPE
- && vect_handle_widen_mult_by_const (last_stmt, oprnd1, &oprnd0,
- stmts, type,
- &half_type0, def_stmt0))
+ && vect_handle_widen_op_by_const (last_stmt, MULT_EXPR, oprnd1,
+ &oprnd0, stmts, type,
+ &half_type0, def_stmt0))
half_type1 = half_type0;
else
return NULL;
@@ -1001,6 +1005,7 @@ vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type,
|| TREE_TYPE (gimple_assign_lhs (new_stmt)) != interm_type)
return false;
+ VEC_safe_push (gimple, heap, *stmts, def_stmt);
oprnd = gimple_assign_lhs (new_stmt);
}
else
@@ -1068,10 +1073,8 @@ vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type,
constants.
Check if S3 and S4 can be done on a smaller type than 'TYPE', it can either
be 'type' or some intermediate type. For now, we expect S5 to be a type
- demotion operation. We also check that S3 and S4 have only one use.
-.
+ demotion operation. We also check that S3 and S4 have only one use. */
-*/
static gimple
vect_recog_over_widening_pattern (VEC (gimple, heap) **stmts,
tree *type_in, tree *type_out)
@@ -1129,7 +1132,7 @@ vect_recog_over_widening_pattern (VEC (gimple, heap) **stmts,
statetments, except for the case when the last statement in the
sequence doesn't have a corresponding pattern statement. In such
case we associate the last pattern statement with the last statement
- in the sequence. Therefore, we only add an original statetement to
+ in the sequence. Therefore, we only add the original statement to
the list if we know that it is not the last. */
if (prev_stmt)
VEC_safe_push (gimple, heap, *stmts, prev_stmt);
@@ -1214,6 +1217,357 @@ vect_recog_over_widening_pattern (VEC (gimple, heap) **stmts,
return pattern_stmt;
}
+/* Detect widening shift pattern:
+
+ type a_t;
+ TYPE a_T, res_T;
+
+ S1 a_t = ;
+ S2 a_T = (TYPE) a_t;
+ S3 res_T = a_T << CONST;
+
+ where type 'TYPE' is at least double the size of type 'type'.
+
+ Also detect unsigned cases:
+
+ unsigned type a_t;
+ unsigned TYPE u_res_T;
+ TYPE a_T, res_T;
+
+ S1 a_t = ;
+ S2 a_T = (TYPE) a_t;
+ S3 res_T = a_T << CONST;
+ S4 u_res_T = (unsigned TYPE) res_T;
+
+ And a case when 'TYPE' is 4 times bigger than 'type'. In that case we
+ create an additional pattern stmt for S2 to create a variable of an
+ intermediate type, and perform widen-shift on the intermediate type:
+
+ type a_t;
+ interm_type a_it;
+ TYPE a_T, res_T, res_T';
+
+ S1 a_t = ;
+ S2 a_T = (TYPE) a_t;
+ '--> a_it = (interm_type) a_t;
+ S3 res_T = a_T << CONST;
+ '--> res_T' = a_it <<* CONST;
+
+ Input/Output:
+
+ * STMTS: Contains a stmt from which the pattern search begins.
+ In case of unsigned widen-shift, the original stmt (S3) is replaced with S4
+ in STMTS. When an intermediate type is used and a pattern statement is
+ created for S2, we also put S2 here (before S3).
+
+ Output:
+
+ * TYPE_IN: The type of the input arguments to the pattern.
+
+ * TYPE_OUT: The type of the output of this pattern.
+
+ * Return value: A new stmt that will be used to replace the sequence of
+ stmts that constitute the pattern. In this case it will be:
+ WIDEN_LSHIFT_EXPR <a_t, CONST>. */
+
+static gimple
+vect_recog_widen_shift_pattern (VEC (gimple, heap) **stmts,
+ tree *type_in, tree *type_out)
+{
+ gimple last_stmt = VEC_pop (gimple, *stmts);
+ gimple def_stmt0;
+ tree oprnd0, oprnd1;
+ tree type, half_type0;
+ gimple pattern_stmt, orig_stmt = NULL;
+ tree vectype, vectype_out = NULL_TREE;
+ tree dummy;
+ tree var;
+ enum tree_code dummy_code;
+ int dummy_int;
+ VEC (tree, heap) * dummy_vec;
+ gimple use_stmt = NULL;
+ bool over_widen = false;
+
+ if (!is_gimple_assign (last_stmt) || !vinfo_for_stmt (last_stmt))
+ return NULL;
+
+ orig_stmt = last_stmt;
+ if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (last_stmt)))
+ {
+ /* This statement was also detected as over-widening operation (it can't
+ be any other pattern, because only over-widening detects shifts).
+ LAST_STMT is the final type demotion statement, but its related
+ statement is shift. We analyze the related statement to catch cases:
+
+ orig code:
+ type a_t;
+ itype res;
+ TYPE a_T, res_T;
+
+ S1 a_T = (TYPE) a_t;
+ S2 res_T = a_T << CONST;
+ S3 res = (itype)res_T;
+
+ (size of type * 2 <= size of itype
+ and size of itype * 2 <= size of TYPE)
+
+ code after over-widening pattern detection:
+
+ S1 a_T = (TYPE) a_t;
+ --> a_it = (itype) a_t;
+ S2 res_T = a_T << CONST;
+ S3 res = (itype)res_T; <--- LAST_STMT
+ --> res = a_it << CONST;
+
+ after widen_shift:
+
+ S1 a_T = (TYPE) a_t;
+ --> a_it = (itype) a_t; - redundant
+ S2 res_T = a_T << CONST;
+ S3 res = (itype)res_T;
+ --> res = a_t w<< CONST;
+
+ i.e., we replace the three statements with res = a_t w<< CONST. */
+ last_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (last_stmt));
+ over_widen = true;
+ }
+
+ if (gimple_assign_rhs_code (last_stmt) != LSHIFT_EXPR)
+ return NULL;
+
+ oprnd0 = gimple_assign_rhs1 (last_stmt);
+ oprnd1 = gimple_assign_rhs2 (last_stmt);
+ if (TREE_CODE (oprnd0) != SSA_NAME || TREE_CODE (oprnd1) != INTEGER_CST)
+ return NULL;
+
+ /* Check operand 0: it has to be defined by a type promotion. */
+ if (!widened_name_p (oprnd0, last_stmt, &half_type0, &def_stmt0, false))
+ return NULL;
+
+ /* Check operand 1: has to be positive. We check that it fits the type
+ in vect_handle_widen_op_by_const (). */
+ if (tree_int_cst_compare (oprnd1, size_zero_node) <= 0)
+ return NULL;
+
+ oprnd0 = gimple_assign_rhs1 (def_stmt0);
+ type = gimple_expr_type (last_stmt);
+
+ /* Check if this a widening operation. */
+ if (!vect_handle_widen_op_by_const (last_stmt, LSHIFT_EXPR, oprnd1,
+ &oprnd0, stmts,
+ type, &half_type0, def_stmt0))
+ return NULL;
+
+ /* Handle unsigned case. Look for
+ S4 u_res_T = (unsigned TYPE) res_T;
+ Use unsigned TYPE as the type for WIDEN_LSHIFT_EXPR. */
+ if (TYPE_UNSIGNED (type) != TYPE_UNSIGNED (half_type0))
+ {
+ tree lhs = gimple_assign_lhs (last_stmt), use_lhs;
+ imm_use_iterator imm_iter;
+ use_operand_p use_p;
+ int nuses = 0;
+ tree use_type;
+
+ if (over_widen)
+ {
+ /* In case of over-widening pattern, S4 should be ORIG_STMT itself.
+ We check here that TYPE is the correct type for the operation,
+ i.e., it's the type of the original result. */
+ tree orig_type = gimple_expr_type (orig_stmt);
+ if ((TYPE_UNSIGNED (type) != TYPE_UNSIGNED (orig_type))
+ || (TYPE_PRECISION (type) != TYPE_PRECISION (orig_type)))
+ return NULL;
+ }
+ else
+ {
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
+ {
+ if (is_gimple_debug (USE_STMT (use_p)))
+ continue;
+ use_stmt = USE_STMT (use_p);
+ nuses++;
+ }
+
+ if (nuses != 1 || !is_gimple_assign (use_stmt)
+ || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_stmt)))
+ return NULL;
+
+ use_lhs = gimple_assign_lhs (use_stmt);
+ use_type = TREE_TYPE (use_lhs);
+
+ if (!INTEGRAL_TYPE_P (use_type)
+ || (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (use_type))
+ || (TYPE_PRECISION (type) != TYPE_PRECISION (use_type)))
+ return NULL;
+
+ type = use_type;
+ }
+ }
+
+ /* Pattern detected. */
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "vect_recog_widen_shift_pattern: detected: ");
+
+ /* Check target support. */
+ vectype = get_vectype_for_scalar_type (half_type0);
+ vectype_out = get_vectype_for_scalar_type (type);
+
+ if (!vectype
+ || !vectype_out
+ || !supportable_widening_operation (WIDEN_LSHIFT_EXPR, last_stmt,
+ vectype_out, vectype,
+ &dummy, &dummy, &dummy_code,
+ &dummy_code, &dummy_int,
+ &dummy_vec))
+ return NULL;
+
+ *type_in = vectype;
+ *type_out = vectype_out;
+
+ /* Pattern supported. Create a stmt to be used to replace the pattern. */
+ var = vect_recog_temp_ssa_var (type, NULL);
+ pattern_stmt =
+ gimple_build_assign_with_ops (WIDEN_LSHIFT_EXPR, var, oprnd0, oprnd1);
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
+
+ if (use_stmt)
+ last_stmt = use_stmt;
+ else
+ last_stmt = orig_stmt;
+
+ VEC_safe_push (gimple, heap, *stmts, last_stmt);
+ return pattern_stmt;
+}
+
+/* Detect a vector by vector shift pattern that wouldn't be otherwise
+ vectorized:
+
+ type a_t;
+ TYPE b_T, res_T;
+
+ S1 a_t = ;
+ S2 b_T = ;
+ S3 res_T = b_T op a_t;
+
+ where type 'TYPE' is a type with different size than 'type',
+ and op is <<, >> or rotate.
+
+ Also detect cases:
+
+ type a_t;
+ TYPE b_T, c_T, res_T;
+
+ S0 c_T = ;
+ S1 a_t = (type) c_T;
+ S2 b_T = ;
+ S3 res_T = b_T op a_t;
+
+ Input/Output:
+
+ * STMTS: Contains a stmt from which the pattern search begins,
+ i.e. the shift/rotate stmt. The original stmt (S3) is replaced
+ with a shift/rotate which has same type on both operands, in the
+ second case just b_T op c_T, in the first case with added cast
+ from a_t to c_T in STMT_VINFO_PATTERN_DEF_STMT.
+
+ Output:
+
+ * TYPE_IN: The type of the input arguments to the pattern.
+
+ * TYPE_OUT: The type of the output of this pattern.
+
+ * Return value: A new stmt that will be used to replace the shift/rotate
+ S3 stmt. */
+
+static gimple
+vect_recog_vector_vector_shift_pattern (VEC (gimple, heap) **stmts,
+ tree *type_in, tree *type_out)
+{
+ gimple last_stmt = VEC_pop (gimple, *stmts);
+ tree oprnd0, oprnd1, lhs, var;
+ gimple pattern_stmt, def_stmt;
+ enum tree_code rhs_code;
+ stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+ enum vect_def_type dt;
+ tree def;
+
+ if (!is_gimple_assign (last_stmt))
+ return NULL;
+
+ rhs_code = gimple_assign_rhs_code (last_stmt);
+ switch (rhs_code)
+ {
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case LROTATE_EXPR:
+ case RROTATE_EXPR:
+ break;
+ default:
+ return NULL;
+ }
+
+ if (STMT_VINFO_IN_PATTERN_P (stmt_vinfo))
+ return NULL;
+
+ lhs = gimple_assign_lhs (last_stmt);
+ oprnd0 = gimple_assign_rhs1 (last_stmt);
+ oprnd1 = gimple_assign_rhs2 (last_stmt);
+ if (TREE_CODE (oprnd0) != SSA_NAME
+ || TREE_CODE (oprnd1) != SSA_NAME
+ || TYPE_MODE (TREE_TYPE (oprnd0)) == TYPE_MODE (TREE_TYPE (oprnd1))
+ || TYPE_PRECISION (TREE_TYPE (oprnd1))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (oprnd1)))
+ || TYPE_PRECISION (TREE_TYPE (lhs))
+ != TYPE_PRECISION (TREE_TYPE (oprnd0)))
+ return NULL;
+
+ if (!vect_is_simple_use (oprnd1, loop_vinfo, NULL, &def_stmt, &def, &dt))
+ return NULL;
+
+ if (dt != vect_internal_def)
+ return NULL;
+
+ *type_in = get_vectype_for_scalar_type (TREE_TYPE (oprnd0));
+ *type_out = *type_in;
+ if (*type_in == NULL_TREE)
+ return NULL;
+
+ def = NULL_TREE;
+ if (gimple_assign_cast_p (def_stmt))
+ {
+ tree rhs1 = gimple_assign_rhs1 (def_stmt);
+ if (TYPE_MODE (TREE_TYPE (rhs1)) == TYPE_MODE (TREE_TYPE (oprnd0))
+ && TYPE_PRECISION (TREE_TYPE (rhs1))
+ == TYPE_PRECISION (TREE_TYPE (oprnd0)))
+ def = rhs1;
+ }
+
+ if (def == NULL_TREE)
+ {
+ def = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
+ def_stmt = gimple_build_assign_with_ops (NOP_EXPR, def, oprnd1,
+ NULL_TREE);
+ STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo) = def_stmt;
+ }
+
+ /* Pattern detected. */
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "vect_recog_vector_vector_shift_pattern: detected: ");
+
+ /* Pattern supported. Create a stmt to be used to replace the pattern. */
+ var = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL);
+ pattern_stmt = gimple_build_assign_with_ops (rhs_code, var, oprnd0, def);
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ print_gimple_stmt (vect_dump, pattern_stmt, 0, TDF_SLIM);
+
+ VEC_safe_push (gimple, heap, *stmts, last_stmt);
+ return pattern_stmt;
+}
/* Function vect_recog_mixed_size_cond_pattern
@@ -1333,6 +1687,425 @@ vect_recog_mixed_size_cond_pattern (VEC (gimple, heap) **stmts, tree *type_in,
}
+/* Helper function of vect_recog_bool_pattern. Called recursively, return
+ true if bool VAR can be optimized that way. */
+
+static bool
+check_bool_pattern (tree var, loop_vec_info loop_vinfo)
+{
+ gimple def_stmt;
+ enum vect_def_type dt;
+ tree def, rhs1;
+ enum tree_code rhs_code;
+
+ if (!vect_is_simple_use (var, loop_vinfo, NULL, &def_stmt, &def, &dt))
+ return false;
+
+ if (dt != vect_internal_def)
+ return false;
+
+ if (!is_gimple_assign (def_stmt))
+ return false;
+
+ if (!has_single_use (def))
+ return false;
+
+ rhs1 = gimple_assign_rhs1 (def_stmt);
+ rhs_code = gimple_assign_rhs_code (def_stmt);
+ switch (rhs_code)
+ {
+ case SSA_NAME:
+ return check_bool_pattern (rhs1, loop_vinfo);
+
+ CASE_CONVERT:
+ if ((TYPE_PRECISION (TREE_TYPE (rhs1)) != 1
+ || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
+ && TREE_CODE (TREE_TYPE (rhs1)) != BOOLEAN_TYPE)
+ return false;
+ return check_bool_pattern (rhs1, loop_vinfo);
+
+ case BIT_NOT_EXPR:
+ return check_bool_pattern (rhs1, loop_vinfo);
+
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ if (!check_bool_pattern (rhs1, loop_vinfo))
+ return false;
+ return check_bool_pattern (gimple_assign_rhs2 (def_stmt), loop_vinfo);
+
+ default:
+ if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
+ {
+ tree vecitype, comp_vectype;
+
+ comp_vectype = get_vectype_for_scalar_type (TREE_TYPE (rhs1));
+ if (comp_vectype == NULL_TREE)
+ return false;
+
+ if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE)
+ {
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
+ tree itype
+ = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
+ vecitype = get_vectype_for_scalar_type (itype);
+ if (vecitype == NULL_TREE)
+ return false;
+ }
+ else
+ vecitype = comp_vectype;
+ return expand_vec_cond_expr_p (vecitype, comp_vectype);
+ }
+ return false;
+ }
+}
+
+
+/* Helper function of adjust_bool_pattern. Add a cast to TYPE to a previous
+ stmt (SSA_NAME_DEF_STMT of VAR) by moving the COND_EXPR from RELATED_STMT
+ to PATTERN_DEF_STMT and adding a cast as RELATED_STMT. */
+
+static tree
+adjust_bool_pattern_cast (tree type, tree var)
+{
+ stmt_vec_info stmt_vinfo = vinfo_for_stmt (SSA_NAME_DEF_STMT (var));
+ gimple cast_stmt, pattern_stmt;
+
+ gcc_assert (!STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo));
+ pattern_stmt = STMT_VINFO_RELATED_STMT (stmt_vinfo);
+ STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo) = pattern_stmt;
+ cast_stmt
+ = gimple_build_assign_with_ops (NOP_EXPR,
+ vect_recog_temp_ssa_var (type, NULL),
+ gimple_assign_lhs (pattern_stmt),
+ NULL_TREE);
+ STMT_VINFO_RELATED_STMT (stmt_vinfo) = cast_stmt;
+ return gimple_assign_lhs (cast_stmt);
+}
+
+
+/* Helper function of vect_recog_bool_pattern. Do the actual transformations,
+ recursively. VAR is an SSA_NAME that should be transformed from bool
+ to a wider integer type, OUT_TYPE is the desired final integer type of
+ the whole pattern, TRUEVAL should be NULL unless optimizing
+ BIT_AND_EXPR into a COND_EXPR with one integer from one of the operands
+ in the then_clause, STMTS is where statements with added pattern stmts
+ should be pushed to. */
+
+static tree
+adjust_bool_pattern (tree var, tree out_type, tree trueval,
+ VEC (gimple, heap) **stmts)
+{
+ gimple stmt = SSA_NAME_DEF_STMT (var);
+ enum tree_code rhs_code, def_rhs_code;
+ tree itype, cond_expr, rhs1, rhs2, irhs1, irhs2;
+ location_t loc;
+ gimple pattern_stmt, def_stmt;
+
+ rhs1 = gimple_assign_rhs1 (stmt);
+ rhs2 = gimple_assign_rhs2 (stmt);
+ rhs_code = gimple_assign_rhs_code (stmt);
+ loc = gimple_location (stmt);
+ switch (rhs_code)
+ {
+ case SSA_NAME:
+ CASE_CONVERT:
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ itype = TREE_TYPE (irhs1);
+ pattern_stmt
+ = gimple_build_assign_with_ops (SSA_NAME,
+ vect_recog_temp_ssa_var (itype, NULL),
+ irhs1, NULL_TREE);
+ break;
+
+ case BIT_NOT_EXPR:
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ itype = TREE_TYPE (irhs1);
+ pattern_stmt
+ = gimple_build_assign_with_ops (BIT_XOR_EXPR,
+ vect_recog_temp_ssa_var (itype, NULL),
+ irhs1, build_int_cst (itype, 1));
+ break;
+
+ case BIT_AND_EXPR:
+ /* Try to optimize x = y & (a < b ? 1 : 0); into
+ x = (a < b ? y : 0);
+
+ E.g. for:
+ bool a_b, b_b, c_b;
+ TYPE d_T;
+
+ S1 a_b = x1 CMP1 y1;
+ S2 b_b = x2 CMP2 y2;
+ S3 c_b = a_b & b_b;
+ S4 d_T = (TYPE) c_b;
+
+ we would normally emit:
+
+ S1' a_T = x1 CMP1 y1 ? 1 : 0;
+ S2' b_T = x2 CMP2 y2 ? 1 : 0;
+ S3' c_T = a_T & b_T;
+ S4' d_T = c_T;
+
+ but we can save one stmt by using the
+ result of one of the COND_EXPRs in the other COND_EXPR and leave
+ BIT_AND_EXPR stmt out:
+
+ S1' a_T = x1 CMP1 y1 ? 1 : 0;
+ S3' c_T = x2 CMP2 y2 ? a_T : 0;
+ S4' f_T = c_T;
+
+ At least when VEC_COND_EXPR is implemented using masks
+ cond ? 1 : 0 is as expensive as cond ? var : 0, in both cases it
+ computes the comparison masks and ands it, in one case with
+ all ones vector, in the other case with a vector register.
+ Don't do this for BIT_IOR_EXPR, because cond ? 1 : var; is
+ often more expensive. */
+ def_stmt = SSA_NAME_DEF_STMT (rhs2);
+ def_rhs_code = gimple_assign_rhs_code (def_stmt);
+ if (TREE_CODE_CLASS (def_rhs_code) == tcc_comparison)
+ {
+ tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ if (TYPE_PRECISION (TREE_TYPE (irhs1))
+ == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1))))
+ {
+ gimple tstmt;
+ stmt_vec_info stmt_def_vinfo = vinfo_for_stmt (def_stmt);
+ irhs2 = adjust_bool_pattern (rhs2, out_type, irhs1, stmts);
+ tstmt = VEC_pop (gimple, *stmts);
+ gcc_assert (tstmt == def_stmt);
+ VEC_quick_push (gimple, *stmts, stmt);
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt))
+ = STMT_VINFO_RELATED_STMT (stmt_def_vinfo);
+ gcc_assert (!STMT_VINFO_PATTERN_DEF_STMT (stmt_def_vinfo));
+ STMT_VINFO_RELATED_STMT (stmt_def_vinfo) = NULL;
+ return irhs2;
+ }
+ else
+ irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
+ goto and_ior_xor;
+ }
+ def_stmt = SSA_NAME_DEF_STMT (rhs1);
+ def_rhs_code = gimple_assign_rhs_code (def_stmt);
+ if (TREE_CODE_CLASS (def_rhs_code) == tcc_comparison)
+ {
+ tree def_rhs1 = gimple_assign_rhs1 (def_stmt);
+ irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
+ if (TYPE_PRECISION (TREE_TYPE (irhs2))
+ == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (def_rhs1))))
+ {
+ gimple tstmt;
+ stmt_vec_info stmt_def_vinfo = vinfo_for_stmt (def_stmt);
+ irhs1 = adjust_bool_pattern (rhs1, out_type, irhs2, stmts);
+ tstmt = VEC_pop (gimple, *stmts);
+ gcc_assert (tstmt == def_stmt);
+ VEC_quick_push (gimple, *stmts, stmt);
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt))
+ = STMT_VINFO_RELATED_STMT (stmt_def_vinfo);
+ gcc_assert (!STMT_VINFO_PATTERN_DEF_STMT (stmt_def_vinfo));
+ STMT_VINFO_RELATED_STMT (stmt_def_vinfo) = NULL;
+ return irhs1;
+ }
+ else
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ goto and_ior_xor;
+ }
+ /* FALLTHRU */
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ irhs1 = adjust_bool_pattern (rhs1, out_type, NULL_TREE, stmts);
+ irhs2 = adjust_bool_pattern (rhs2, out_type, NULL_TREE, stmts);
+ and_ior_xor:
+ if (TYPE_PRECISION (TREE_TYPE (irhs1))
+ != TYPE_PRECISION (TREE_TYPE (irhs2)))
+ {
+ int prec1 = TYPE_PRECISION (TREE_TYPE (irhs1));
+ int prec2 = TYPE_PRECISION (TREE_TYPE (irhs2));
+ int out_prec = TYPE_PRECISION (out_type);
+ if (absu_hwi (out_prec - prec1) < absu_hwi (out_prec - prec2))
+ irhs2 = adjust_bool_pattern_cast (TREE_TYPE (irhs1), rhs2);
+ else if (absu_hwi (out_prec - prec1) > absu_hwi (out_prec - prec2))
+ irhs1 = adjust_bool_pattern_cast (TREE_TYPE (irhs2), rhs1);
+ else
+ {
+ irhs1 = adjust_bool_pattern_cast (out_type, rhs1);
+ irhs2 = adjust_bool_pattern_cast (out_type, rhs2);
+ }
+ }
+ itype = TREE_TYPE (irhs1);
+ pattern_stmt
+ = gimple_build_assign_with_ops (rhs_code,
+ vect_recog_temp_ssa_var (itype, NULL),
+ irhs1, irhs2);
+ break;
+
+ default:
+ gcc_assert (TREE_CODE_CLASS (rhs_code) == tcc_comparison);
+ if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE
+ || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
+ {
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (rhs1));
+ itype
+ = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
+ }
+ else
+ itype = TREE_TYPE (rhs1);
+ cond_expr = build2_loc (loc, rhs_code, itype, rhs1, rhs2);
+ if (trueval == NULL_TREE)
+ trueval = build_int_cst (itype, 1);
+ else
+ gcc_checking_assert (useless_type_conversion_p (itype,
+ TREE_TYPE (trueval)));
+ pattern_stmt
+ = gimple_build_assign_with_ops3 (COND_EXPR,
+ vect_recog_temp_ssa_var (itype, NULL),
+ cond_expr, trueval,
+ build_int_cst (itype, 0));
+ break;
+ }
+
+ VEC_safe_push (gimple, heap, *stmts, stmt);
+ gimple_set_location (pattern_stmt, loc);
+ STMT_VINFO_RELATED_STMT (vinfo_for_stmt (stmt)) = pattern_stmt;
+ return gimple_assign_lhs (pattern_stmt);
+}
+
+
+/* Function vect_recog_bool_pattern
+
+ Try to find pattern like following:
+
+ bool a_b, b_b, c_b, d_b, e_b;
+ TYPE f_T;
+ loop:
+ S1 a_b = x1 CMP1 y1;
+ S2 b_b = x2 CMP2 y2;
+ S3 c_b = a_b & b_b;
+ S4 d_b = x3 CMP3 y3;
+ S5 e_b = c_b | d_b;
+ S6 f_T = (TYPE) e_b;
+
+ where type 'TYPE' is an integral type.
+
+ Input:
+
+ * LAST_STMT: A stmt at the end from which the pattern
+ search begins, i.e. cast of a bool to
+ an integer type.
+
+ Output:
+
+ * TYPE_IN: The type of the input arguments to the pattern.
+
+ * TYPE_OUT: The type of the output of this pattern.
+
+ * Return value: A new stmt that will be used to replace the pattern.
+
+ Assuming size of TYPE is the same as size of all comparisons
+ (otherwise some casts would be added where needed), the above
+ sequence we create related pattern stmts:
+ S1' a_T = x1 CMP1 y1 ? 1 : 0;
+ S3' c_T = x2 CMP2 y2 ? a_T : 0;
+ S4' d_T = x3 CMP3 y3 ? 1 : 0;
+ S5' e_T = c_T | d_T;
+ S6' f_T = e_T;
+
+ Instead of the above S3' we could emit:
+ S2' b_T = x2 CMP2 y2 ? 1 : 0;
+ S3' c_T = a_T | b_T;
+ but the above is more efficient. */
+
+static gimple
+vect_recog_bool_pattern (VEC (gimple, heap) **stmts, tree *type_in,
+ tree *type_out)
+{
+ gimple last_stmt = VEC_pop (gimple, *stmts);
+ enum tree_code rhs_code;
+ tree var, lhs, rhs, vectype;
+ stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
+ gimple pattern_stmt;
+
+ if (!is_gimple_assign (last_stmt))
+ return NULL;
+
+ var = gimple_assign_rhs1 (last_stmt);
+ lhs = gimple_assign_lhs (last_stmt);
+
+ if ((TYPE_PRECISION (TREE_TYPE (var)) != 1
+ || !TYPE_UNSIGNED (TREE_TYPE (var)))
+ && TREE_CODE (TREE_TYPE (var)) != BOOLEAN_TYPE)
+ return NULL;
+
+ rhs_code = gimple_assign_rhs_code (last_stmt);
+ if (CONVERT_EXPR_CODE_P (rhs_code))
+ {
+ if (TREE_CODE (TREE_TYPE (lhs)) != INTEGER_TYPE)
+ return NULL;
+ vectype = get_vectype_for_scalar_type (TREE_TYPE (lhs));
+ if (vectype == NULL_TREE)
+ return NULL;
+
+ if (!check_bool_pattern (var, loop_vinfo))
+ return NULL;
+
+ rhs = adjust_bool_pattern (var, TREE_TYPE (lhs), NULL_TREE, stmts);
+ lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
+ if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ pattern_stmt
+ = gimple_build_assign_with_ops (SSA_NAME, lhs, rhs, NULL_TREE);
+ else
+ pattern_stmt
+ = gimple_build_assign_with_ops (NOP_EXPR, lhs, rhs, NULL_TREE);
+ *type_out = vectype;
+ *type_in = vectype;
+ VEC_safe_push (gimple, heap, *stmts, last_stmt);
+ return pattern_stmt;
+ }
+ else if (rhs_code == SSA_NAME
+ && STMT_VINFO_DATA_REF (stmt_vinfo))
+ {
+ stmt_vec_info pattern_stmt_info;
+ vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
+ gcc_assert (vectype != NULL_TREE);
+ if (!check_bool_pattern (var, loop_vinfo))
+ return NULL;
+
+ rhs = adjust_bool_pattern (var, TREE_TYPE (vectype), NULL_TREE, stmts);
+ lhs = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (vectype), lhs);
+ if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ {
+ tree rhs2 = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
+ gimple cast_stmt
+ = gimple_build_assign_with_ops (NOP_EXPR, rhs2, rhs, NULL_TREE);
+ STMT_VINFO_PATTERN_DEF_STMT (stmt_vinfo) = cast_stmt;
+ rhs = rhs2;
+ }
+ pattern_stmt
+ = gimple_build_assign_with_ops (SSA_NAME, lhs, rhs, NULL_TREE);
+ pattern_stmt_info = new_stmt_vec_info (pattern_stmt, loop_vinfo, NULL);
+ set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
+ STMT_VINFO_DATA_REF (pattern_stmt_info)
+ = STMT_VINFO_DATA_REF (stmt_vinfo);
+ STMT_VINFO_DR_BASE_ADDRESS (pattern_stmt_info)
+ = STMT_VINFO_DR_BASE_ADDRESS (stmt_vinfo);
+ STMT_VINFO_DR_INIT (pattern_stmt_info) = STMT_VINFO_DR_INIT (stmt_vinfo);
+ STMT_VINFO_DR_OFFSET (pattern_stmt_info)
+ = STMT_VINFO_DR_OFFSET (stmt_vinfo);
+ STMT_VINFO_DR_STEP (pattern_stmt_info) = STMT_VINFO_DR_STEP (stmt_vinfo);
+ STMT_VINFO_DR_ALIGNED_TO (pattern_stmt_info)
+ = STMT_VINFO_DR_ALIGNED_TO (stmt_vinfo);
+ *type_out = vectype;
+ *type_in = vectype;
+ VEC_safe_push (gimple, heap, *stmts, last_stmt);
+ return pattern_stmt;
+ }
+ else
+ return NULL;
+}
+
+
/* Mark statements that are involved in a pattern. */
static inline void
@@ -1344,19 +2117,22 @@ vect_mark_pattern_stmts (gimple orig_stmt, gimple pattern_stmt,
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (orig_stmt_info);
gimple def_stmt;
- set_vinfo_for_stmt (pattern_stmt,
- new_stmt_vec_info (pattern_stmt, loop_vinfo, NULL));
- gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt));
pattern_stmt_info = vinfo_for_stmt (pattern_stmt);
+ if (pattern_stmt_info == NULL)
+ {
+ pattern_stmt_info = new_stmt_vec_info (pattern_stmt, loop_vinfo, NULL);
+ set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info);
+ }
+ gimple_set_bb (pattern_stmt, gimple_bb (orig_stmt));
STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt;
STMT_VINFO_DEF_TYPE (pattern_stmt_info)
- = STMT_VINFO_DEF_TYPE (orig_stmt_info);
+ = STMT_VINFO_DEF_TYPE (orig_stmt_info);
STMT_VINFO_VECTYPE (pattern_stmt_info) = pattern_vectype;
STMT_VINFO_IN_PATTERN_P (orig_stmt_info) = true;
STMT_VINFO_RELATED_STMT (orig_stmt_info) = pattern_stmt;
STMT_VINFO_PATTERN_DEF_STMT (pattern_stmt_info)
- = STMT_VINFO_PATTERN_DEF_STMT (orig_stmt_info);
+ = STMT_VINFO_PATTERN_DEF_STMT (orig_stmt_info);
if (STMT_VINFO_PATTERN_DEF_STMT (pattern_stmt_info))
{
def_stmt = STMT_VINFO_PATTERN_DEF_STMT (pattern_stmt_info);
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 4b205bf332a..790f2dd0a75 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -1,5 +1,5 @@
/* SLP - Basic Block Vectorization
- Copyright (C) 2007, 2008, 2009, 2010
+ Copyright (C) 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Dorit Naishlos <dorit@il.ibm.com>
and Ira Rosen <irar@il.ibm.com>
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "optabs.h"
#include "tree-vectorizer.h"
+#include "langhooks.h"
/* Extract the location of the basic block in the source code.
Return the basic block location if succeed and NULL if not. */
@@ -115,13 +116,15 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
tree oprnd;
unsigned int i, number_of_oprnds;
- tree def;
+ tree def[2];
gimple def_stmt;
enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
stmt_vec_info stmt_info =
vinfo_for_stmt (VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0));
enum gimple_rhs_class rhs_class;
struct loop *loop = NULL;
+ enum tree_code rhs_code;
+ bool different_types = false;
if (loop_vinfo)
loop = LOOP_VINFO_LOOP (loop_vinfo);
@@ -133,7 +136,7 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
oprnd = gimple_op (stmt, i + 1);
- if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def,
+ if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def[i],
&dt[i])
|| (!def_stmt && dt[i] != vect_constant_def))
{
@@ -188,11 +191,11 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
switch (gimple_code (def_stmt))
{
case GIMPLE_PHI:
- def = gimple_phi_result (def_stmt);
+ def[i] = gimple_phi_result (def_stmt);
break;
case GIMPLE_ASSIGN:
- def = gimple_assign_lhs (def_stmt);
+ def[i] = gimple_assign_lhs (def_stmt);
break;
default:
@@ -206,8 +209,8 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
/* op0 of the first stmt of the group - store its info. */
*first_stmt_dt0 = dt[i];
- if (def)
- *first_stmt_def0_type = TREE_TYPE (def);
+ if (def[i])
+ *first_stmt_def0_type = TREE_TYPE (def[i]);
else
*first_stmt_const_oprnd = oprnd;
@@ -227,8 +230,8 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
{
/* op1 of the first stmt of the group - store its info. */
*first_stmt_dt1 = dt[i];
- if (def)
- *first_stmt_def1_type = TREE_TYPE (def);
+ if (def[i])
+ *first_stmt_def1_type = TREE_TYPE (def[i]);
else
{
/* We assume that the stmt contains only one constant
@@ -254,24 +257,56 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
&& ((*first_stmt_dt0 != dt[i]
&& !(*first_stmt_dt0 == vect_reduction_def
&& dt[i] == vect_internal_def))
- || (*first_stmt_def0_type && def
+ || (*first_stmt_def0_type && def[0]
&& !types_compatible_p (*first_stmt_def0_type,
- TREE_TYPE (def)))))
+ TREE_TYPE (def[0])))))
|| (i == 1
&& ((*first_stmt_dt1 != dt[i]
&& !(*first_stmt_dt1 == vect_reduction_def
&& dt[i] == vect_internal_def))
- || (*first_stmt_def1_type && def
+ || (*first_stmt_def1_type && def[1]
&& !types_compatible_p (*first_stmt_def1_type,
- TREE_TYPE (def)))))
- || (!def
+ TREE_TYPE (def[1])))))
+ || (!def[i]
&& !types_compatible_p (TREE_TYPE (*first_stmt_const_oprnd),
- TREE_TYPE (oprnd))))
+ TREE_TYPE (oprnd)))
+ || different_types)
{
- if (vect_print_dump_info (REPORT_SLP))
- fprintf (vect_dump, "Build SLP failed: different types ");
+ if (i != number_of_oprnds - 1)
+ different_types = true;
+ else
+ {
+ if (is_gimple_assign (stmt)
+ && (rhs_code = gimple_assign_rhs_code (stmt))
+ && TREE_CODE_CLASS (rhs_code) == tcc_binary
+ && commutative_tree_code (rhs_code)
+ && *first_stmt_dt0 == dt[1]
+ && *first_stmt_dt1 == dt[0]
+ && def[0] && def[1]
+ && !(*first_stmt_def0_type
+ && !types_compatible_p (*first_stmt_def0_type,
+ TREE_TYPE (def[1])))
+ && !(*first_stmt_def1_type
+ && !types_compatible_p (*first_stmt_def1_type,
+ TREE_TYPE (def[0]))))
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ {
+ fprintf (vect_dump, "Swapping operands of ");
+ print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
+ }
+
+ swap_tree_operands (stmt, gimple_assign_rhs1_ptr (stmt),
+ gimple_assign_rhs2_ptr (stmt));
+ }
+ else
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ fprintf (vect_dump, "Build SLP failed: different types ");
- return false;
+ return false;
+ }
+ }
}
}
}
@@ -285,10 +320,10 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
case vect_internal_def:
case vect_reduction_def:
- if (i == 0)
+ if ((i == 0 && !different_types) || (i == 1 && different_types))
VEC_safe_push (gimple, heap, *def_stmts0, def_stmt);
else
- VEC_safe_push (gimple, heap, *def_stmts1, def_stmt);
+ VEC_safe_push (gimple, heap, *def_stmts1, def_stmt);
break;
default:
@@ -296,7 +331,7 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
if (vect_print_dump_info (REPORT_SLP))
{
fprintf (vect_dump, "Build SLP failed: illegal type of def ");
- print_generic_expr (vect_dump, def, TDF_SLIM);
+ print_generic_expr (vect_dump, def[i], TDF_SLIM);
}
return false;
@@ -319,7 +354,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
int ncopies_for_cost, unsigned int *max_nunits,
VEC (int, heap) **load_permutation,
VEC (slp_tree, heap) **loads,
- unsigned int vectorization_factor)
+ unsigned int vectorization_factor, bool *loads_permuted)
{
VEC (gimple, heap) *def_stmts0 = VEC_alloc (gimple, heap, group_size);
VEC (gimple, heap) *def_stmts1 = VEC_alloc (gimple, heap, group_size);
@@ -454,6 +489,11 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
}
}
}
+ else if (rhs_code == WIDEN_LSHIFT_EXPR)
+ {
+ need_same_oprnds = true;
+ first_op1 = gimple_assign_rhs2 (stmt);
+ }
}
else
{
@@ -530,7 +570,8 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
/* Check that the size of interleaved loads group is not
greater than the SLP group size. */
- if (GROUP_SIZE (vinfo_for_stmt (stmt)) > ncopies * group_size)
+ if (loop_vinfo
+ && GROUP_SIZE (vinfo_for_stmt (stmt)) > ncopies * group_size)
{
if (vect_print_dump_info (REPORT_SLP))
{
@@ -651,19 +692,22 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
/* Strided loads were reached - stop the recursion. */
if (stop_recursion)
{
+ VEC_safe_push (slp_tree, heap, *loads, *node);
if (permutation)
{
- VEC_safe_push (slp_tree, heap, *loads, *node);
+
+ *loads_permuted = true;
*inside_cost
+= targetm.vectorize.builtin_vectorization_cost (vec_perm, NULL, 0)
* group_size;
}
else
- {
- /* We don't check here complex numbers chains, so we keep them in
- LOADS for further check in vect_supported_load_permutation_p. */
+ {
+ /* We don't check here complex numbers chains, so we set
+ LOADS_PERMUTED for further check in
+ vect_supported_load_permutation_p. */
if (rhs_code == REALPART_EXPR || rhs_code == IMAGPART_EXPR)
- VEC_safe_push (slp_tree, heap, *loads, *node);
+ *loads_permuted = true;
}
return true;
@@ -682,7 +726,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
if (!vect_build_slp_tree (loop_vinfo, bb_vinfo, &left_node, group_size,
inside_cost, outside_cost, ncopies_for_cost,
max_nunits, load_permutation, loads,
- vectorization_factor))
+ vectorization_factor, loads_permuted))
return false;
SLP_TREE_LEFT (*node) = left_node;
@@ -700,7 +744,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
if (!vect_build_slp_tree (loop_vinfo, bb_vinfo, &right_node, group_size,
inside_cost, outside_cost, ncopies_for_cost,
max_nunits, load_permutation, loads,
- vectorization_factor))
+ vectorization_factor, loads_permuted))
return false;
SLP_TREE_RIGHT (*node) = right_node;
@@ -886,8 +930,10 @@ vect_supported_load_permutation_p (slp_instance slp_instn, int group_size,
bool supported, bad_permutation = false;
sbitmap load_index;
slp_tree node, other_complex_node;
- gimple stmt, first = NULL, other_node_first;
+ gimple stmt, first = NULL, other_node_first, load, next_load, first_load;
unsigned complex_numbers = 0;
+ struct data_reference *dr;
+ bb_vec_info bb_vinfo;
/* FORNOW: permutations are only supported in SLP. */
if (!slp_instn)
@@ -1049,6 +1095,76 @@ vect_supported_load_permutation_p (slp_instance slp_instn, int group_size,
}
}
+ /* In basic block vectorization we allow any subchain of an interleaving
+ chain.
+ FORNOW: not supported in loop SLP because of realignment compications. */
+ bb_vinfo = STMT_VINFO_BB_VINFO (vinfo_for_stmt (stmt));
+ bad_permutation = false;
+ /* Check that for every node in the instance teh loads form a subchain. */
+ if (bb_vinfo)
+ {
+ FOR_EACH_VEC_ELT (slp_tree, SLP_INSTANCE_LOADS (slp_instn), i, node)
+ {
+ next_load = NULL;
+ first_load = NULL;
+ FOR_EACH_VEC_ELT (gimple, SLP_TREE_SCALAR_STMTS (node), j, load)
+ {
+ if (!first_load)
+ first_load = GROUP_FIRST_ELEMENT (vinfo_for_stmt (load));
+ else if (first_load
+ != GROUP_FIRST_ELEMENT (vinfo_for_stmt (load)))
+ {
+ bad_permutation = true;
+ break;
+ }
+
+ if (j != 0 && next_load != load)
+ {
+ bad_permutation = true;
+ break;
+ }
+
+ next_load = GROUP_NEXT_ELEMENT (vinfo_for_stmt (load));
+ }
+
+ if (bad_permutation)
+ break;
+ }
+
+ /* Check that the alignment of the first load in every subchain, i.e.,
+ the first statement in every load node, is supported. */
+ if (!bad_permutation)
+ {
+ FOR_EACH_VEC_ELT (slp_tree, SLP_INSTANCE_LOADS (slp_instn), i, node)
+ {
+ first_load = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (node), 0);
+ if (first_load
+ != GROUP_FIRST_ELEMENT (vinfo_for_stmt (first_load)))
+ {
+ dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_load));
+ if (vect_supportable_dr_alignment (dr, false)
+ == dr_unaligned_unsupported)
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ {
+ fprintf (vect_dump, "unsupported unaligned load ");
+ print_gimple_stmt (vect_dump, first_load, 0,
+ TDF_SLIM);
+ }
+ bad_permutation = true;
+ break;
+ }
+ }
+ }
+
+ if (!bad_permutation)
+ {
+ VEC_free (int, heap, SLP_INSTANCE_LOAD_PERMUTATION (slp_instn));
+ return true;
+ }
+ }
+ }
+
/* FORNOW: the only supported permutation is 0..01..1.. of length equal to
GROUP_SIZE and where each sequence of same drs is of GROUP_SIZE length as
well (unless it's reduction). */
@@ -1158,6 +1274,7 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
VEC (int, heap) *load_permutation;
VEC (slp_tree, heap) *loads;
struct data_reference *dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt));
+ bool loads_permuted = false;
if (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)))
{
@@ -1249,7 +1366,7 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
if (vect_build_slp_tree (loop_vinfo, bb_vinfo, &node, group_size,
&inside_cost, &outside_cost, ncopies_for_cost,
&max_nunits, &load_permutation, &loads,
- vectorization_factor))
+ vectorization_factor, &loads_permuted))
{
/* Calculate the unrolling factor based on the smallest type. */
if (max_nunits > nunits)
@@ -1274,7 +1391,8 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
SLP_INSTANCE_LOADS (new_instance) = loads;
SLP_INSTANCE_FIRST_LOAD_STMT (new_instance) = NULL;
SLP_INSTANCE_LOAD_PERMUTATION (new_instance) = load_permutation;
- if (VEC_length (slp_tree, loads))
+
+ if (loads_permuted)
{
if (!vect_supported_load_permutation_p (new_instance, group_size,
load_permutation))
@@ -1588,43 +1706,6 @@ vect_slp_analyze_operations (bb_vec_info bb_vinfo)
return true;
}
-/* Check if loads and stores are mixed in the basic block (in that
- case if we are not sure that the accesses differ, we can't vectorize the
- basic block). Also return FALSE in case that there is statement marked as
- not vectorizable. */
-
-static bool
-vect_bb_vectorizable_with_dependencies (bb_vec_info bb_vinfo)
-{
- basic_block bb = BB_VINFO_BB (bb_vinfo);
- gimple_stmt_iterator si;
- bool detected_store = false;
- gimple stmt;
- struct data_reference *dr;
-
- for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
- {
- stmt = gsi_stmt (si);
-
- /* We can't allow not analyzed statements, since they may contain data
- accesses. */
- if (!STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)))
- return false;
-
- if (!STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt)))
- continue;
-
- dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt));
- if (DR_IS_READ (dr) && detected_store)
- return false;
-
- if (!DR_IS_READ (dr))
- detected_store = true;
- }
-
- return true;
-}
-
/* Check if vectorization of the basic block is profitable. */
static bool
@@ -1705,7 +1786,6 @@ vect_slp_analyze_bb_1 (basic_block bb)
int i;
int min_vf = 2;
int max_vf = MAX_VECTORIZATION_FACTOR;
- bool data_dependence_in_bb = false;
bb_vinfo = new_bb_vec_info (bb);
if (!bb_vinfo)
@@ -1732,11 +1812,8 @@ vect_slp_analyze_bb_1 (basic_block bb)
return NULL;
}
- if (!vect_analyze_data_ref_dependences (NULL, bb_vinfo, &max_vf,
- &data_dependence_in_bb)
- || min_vf > max_vf
- || (data_dependence_in_bb
- && !vect_bb_vectorizable_with_dependencies (bb_vinfo)))
+ if (!vect_analyze_data_ref_dependences (NULL, bb_vinfo, &max_vf)
+ || min_vf > max_vf)
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
fprintf (vect_dump, "not vectorized: unhandled data dependence "
@@ -2226,8 +2303,7 @@ static inline void
vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
tree mask, int first_vec_indx, int second_vec_indx,
gimple_stmt_iterator *gsi, slp_tree node,
- tree builtin_decl, tree vectype,
- VEC(tree,heap) *dr_chain,
+ tree vectype, VEC(tree,heap) *dr_chain,
int ncopies, int vect_stmts_counter)
{
tree perm_dest;
@@ -2251,10 +2327,10 @@ vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
second_vec = VEC_index (tree, dr_chain, second_vec_indx);
/* Generate the permute statement. */
- perm_stmt = gimple_build_call (builtin_decl,
- 3, first_vec, second_vec, mask);
+ perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
+ first_vec, second_vec, mask);
data_ref = make_ssa_name (perm_dest, perm_stmt);
- gimple_call_set_lhs (perm_stmt, data_ref);
+ gimple_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
/* Store the vector statement in NODE. */
@@ -2280,7 +2356,7 @@ vect_create_mask_and_perm (gimple stmt, gimple next_scalar_stmt,
static bool
vect_get_mask_element (gimple stmt, int first_mask_element, int m,
int mask_nunits, bool only_one_vec, int index,
- int *mask, int *current_mask_element,
+ unsigned char *mask, int *current_mask_element,
bool *need_next_vector, int *number_of_mask_fixes,
bool *mask_fixed, bool *needs_first_vector)
{
@@ -2361,48 +2437,41 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree mask_element_type = NULL_TREE, mask_type;
- int i, j, k, m, scale, mask_nunits, nunits, vec_index = 0, scalar_index;
+ int i, j, k, nunits, vec_index = 0, scalar_index;
slp_tree node;
- tree vectype = STMT_VINFO_VECTYPE (stmt_info), builtin_decl;
+ tree vectype = STMT_VINFO_VECTYPE (stmt_info);
gimple next_scalar_stmt;
int group_size = SLP_INSTANCE_GROUP_SIZE (slp_node_instance);
int first_mask_element;
- int index, unroll_factor, *mask, current_mask_element, ncopies;
+ int index, unroll_factor, current_mask_element, ncopies;
+ unsigned char *mask;
bool only_one_vec = false, need_next_vector = false;
int first_vec_index, second_vec_index, orig_vec_stmts_num, vect_stmts_counter;
int number_of_mask_fixes = 1;
bool mask_fixed = false;
bool needs_first_vector = false;
+ enum machine_mode mode;
- if (!targetm.vectorize.builtin_vec_perm)
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- {
- fprintf (vect_dump, "no builtin for vect permute for ");
- print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
- }
-
- return false;
- }
+ mode = TYPE_MODE (vectype);
- builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
- &mask_element_type);
- if (!builtin_decl || !mask_element_type)
+ if (!can_vec_perm_p (mode, false, NULL))
{
if (vect_print_dump_info (REPORT_DETAILS))
{
- fprintf (vect_dump, "no builtin for vect permute for ");
+ fprintf (vect_dump, "no vect permute for ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
-
- return false;
+ return false;
}
+ /* The generic VEC_PERM_EXPR code always uses an integral type of the
+ same size as the vector element being permuted. */
+ mask_element_type
+ = lang_hooks.types.type_for_size
+ (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (vectype))), 1);
mask_type = get_vectype_for_scalar_type (mask_element_type);
- mask_nunits = TYPE_VECTOR_SUBPARTS (mask_type);
- mask = (int *) xmalloc (sizeof (int) * mask_nunits);
nunits = TYPE_VECTOR_SUBPARTS (vectype);
- scale = mask_nunits / nunits;
+ mask = XALLOCAVEC (unsigned char, nunits);
unroll_factor = SLP_INSTANCE_UNROLLING_FACTOR (slp_node_instance);
/* The number of vector stmts to generate based only on SLP_NODE_INSTANCE
@@ -2425,8 +2494,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
for b's: b0b0b0b1 b1b1b2b2 b2b3b3b3
...
- The masks for a's should be: {0,0,0,3} {3,3,6,6} {6,9,9,9} (in target
- scpecific type, e.g., in bytes for Altivec.
+ The masks for a's should be: {0,0,0,3} {3,3,6,6} {6,9,9,9}.
The last mask is illegal since we assume two operands for permute
operation, and the mask element values can't be outside that range.
Hence, the last mask must be converted into {2,5,5,5}.
@@ -2451,23 +2519,32 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
{
for (k = 0; k < group_size; k++)
{
- first_mask_element = (i + j * group_size) * scale;
- for (m = 0; m < scale; m++)
- {
- if (!vect_get_mask_element (stmt, first_mask_element, m,
- mask_nunits, only_one_vec, index, mask,
- &current_mask_element, &need_next_vector,
- &number_of_mask_fixes, &mask_fixed,
- &needs_first_vector))
- return false;
-
- mask[index++] = current_mask_element;
- }
+ first_mask_element = i + j * group_size;
+ if (!vect_get_mask_element (stmt, first_mask_element, 0,
+ nunits, only_one_vec, index,
+ mask, &current_mask_element,
+ &need_next_vector,
+ &number_of_mask_fixes, &mask_fixed,
+ &needs_first_vector))
+ return false;
+ mask[index++] = current_mask_element;
- if (index == mask_nunits)
+ if (index == nunits)
{
tree mask_vec = NULL;
+ if (!can_vec_perm_p (mode, false, mask))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ {
+ fprintf (vect_dump, "unsupported vect permute { ");
+ for (i = 0; i < nunits; ++i)
+ fprintf (vect_dump, "%d ", mask[i]);
+ fprintf (vect_dump, "}\n");
+ }
+ return false;
+ }
+
while (--index >= 0)
{
tree t = build_int_cst (mask_element_type, mask[index]);
@@ -2476,18 +2553,6 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
mask_vec = build_vector (mask_type, mask_vec);
index = 0;
- if (!targetm.vectorize.builtin_vec_perm_ok (vectype,
- mask_vec))
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- {
- fprintf (vect_dump, "unsupported vect permute ");
- print_generic_expr (vect_dump, mask_vec, 0);
- }
- free (mask);
- return false;
- }
-
if (!analyze_only)
{
if (need_next_vector)
@@ -2501,7 +2566,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
vect_create_mask_and_perm (stmt, next_scalar_stmt,
mask_vec, first_vec_index, second_vec_index,
- gsi, node, builtin_decl, vectype, dr_chain,
+ gsi, node, vectype, dr_chain,
ncopies, vect_stmts_counter++);
}
}
@@ -2509,7 +2574,6 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
}
}
- free (mask);
return true;
}
@@ -2583,10 +2647,11 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
/* Loads should be inserted before the first load. */
if (SLP_INSTANCE_FIRST_LOAD_STMT (instance)
&& STMT_VINFO_STRIDED_ACCESS (stmt_info)
- && !REFERENCE_CLASS_P (gimple_get_lhs (stmt)))
+ && !REFERENCE_CLASS_P (gimple_get_lhs (stmt))
+ && SLP_INSTANCE_LOAD_PERMUTATION (instance))
si = gsi_for_stmt (SLP_INSTANCE_FIRST_LOAD_STMT (instance));
else if (is_pattern_stmt_p (stmt_info))
- si = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+ si = gsi_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
else
si = gsi_for_stmt (stmt);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index f2ac8c7a616..e91efc96ade 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -159,19 +159,20 @@ vect_mark_relevant (VEC(gimple,heap) **worklist, gimple stmt,
/* This use is out of pattern use, if LHS has other uses that are
pattern uses, we should mark the stmt itself, and not the pattern
stmt. */
- FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
- {
- if (is_gimple_debug (USE_STMT (use_p)))
- continue;
- use_stmt = USE_STMT (use_p);
+ if (TREE_CODE (lhs) == SSA_NAME)
+ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
+ {
+ if (is_gimple_debug (USE_STMT (use_p)))
+ continue;
+ use_stmt = USE_STMT (use_p);
- if (vinfo_for_stmt (use_stmt)
- && STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (use_stmt)))
- {
- found = true;
- break;
- }
- }
+ if (vinfo_for_stmt (use_stmt)
+ && STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (use_stmt)))
+ {
+ found = true;
+ break;
+ }
+ }
}
if (!found)
@@ -1204,7 +1205,9 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "Create vector_cst. nunits = %d", nunits);
- vec_cst = build_vector_from_val (vector_type, op);
+ vec_cst = build_vector_from_val (vector_type,
+ fold_convert (TREE_TYPE (vector_type),
+ op));
return vect_init_vector (stmt, vec_cst, vector_type, NULL);
}
@@ -1821,7 +1824,6 @@ vect_gen_widened_results_half (enum tree_code code,
return new_stmt;
}
-
/* Check if STMT performs a conversion operation, that can be vectorized.
If VEC_STMT is also passed, vectorize the STMT: create a vectorized
stmt to replace it, put it in VEC_STMT, and insert it at BSI.
@@ -1850,7 +1852,6 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
tree vectype_out, vectype_in;
int ncopies, j;
tree rhs_type;
- tree builtin_decl;
enum { NARROW, NONE, WIDEN } modifier;
int i;
VEC(tree,heap) *vec_oprnds0 = NULL;
@@ -1939,7 +1940,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
/* Supportable by target? */
if ((modifier == NONE
- && !targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
+ && !supportable_convert_operation (code, vectype_out, vectype_in, &decl1, &code1))
|| (modifier == WIDEN
&& !supportable_widening_operation (code, stmt,
vectype_out, vectype_in,
@@ -1989,19 +1990,28 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
else
vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, NULL);
- builtin_decl =
- targetm.vectorize.builtin_conversion (code,
- vectype_out, vectype_in);
FOR_EACH_VEC_ELT (tree, vec_oprnds0, i, vop0)
- {
- /* Arguments are ready. create the new vector stmt. */
- new_stmt = gimple_build_call (builtin_decl, 1, vop0);
- new_temp = make_ssa_name (vec_dest, new_stmt);
- gimple_call_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt, new_stmt, gsi);
- if (slp_node)
- VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
- }
+ {
+ /* Arguments are ready, create the new vector stmt. */
+ if (code1 == CALL_EXPR)
+ {
+ new_stmt = gimple_build_call (decl1, 1, vop0);
+ new_temp = make_ssa_name (vec_dest, new_stmt);
+ gimple_call_set_lhs (new_stmt, new_temp);
+ }
+ else
+ {
+ gcc_assert (TREE_CODE_LENGTH (code) == unary_op);
+ new_stmt = gimple_build_assign_with_ops (code, vec_dest, vop0,
+ NULL);
+ new_temp = make_ssa_name (vec_dest, new_stmt);
+ gimple_assign_set_lhs (new_stmt, new_temp);
+ }
+
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ if (slp_node)
+ VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
+ }
if (j == 0)
STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
@@ -2173,6 +2183,25 @@ vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
!= GET_MODE_SIZE (TYPE_MODE (vectype_in)))))
return false;
+ /* We do not handle bit-precision changes. */
+ if ((CONVERT_EXPR_CODE_P (code)
+ || code == VIEW_CONVERT_EXPR)
+ && INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
+ && ((TYPE_PRECISION (TREE_TYPE (scalar_dest))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (scalar_dest))))
+ || ((TYPE_PRECISION (TREE_TYPE (op))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (op))))))
+ /* But a conversion that does not change the bit-pattern is ok. */
+ && !((TYPE_PRECISION (TREE_TYPE (scalar_dest))
+ > TYPE_PRECISION (TREE_TYPE (op)))
+ && TYPE_UNSIGNED (TREE_TYPE (op))))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "type conversion to/from bit-precision "
+ "unsupported.");
+ return false;
+ }
+
if (!vec_stmt) /* transformation not required. */
{
STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
@@ -2296,6 +2325,7 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
int nunits_in;
int nunits_out;
tree vectype_out;
+ tree op1_vectype;
int ncopies;
int j, i;
VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
@@ -2326,6 +2356,13 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
scalar_dest = gimple_assign_lhs (stmt);
vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+ if (TYPE_PRECISION (TREE_TYPE (scalar_dest))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (scalar_dest))))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "bit-precision shifts not supported.");
+ return false;
+ }
op0 = gimple_assign_rhs1 (stmt);
if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
@@ -2358,7 +2395,8 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
return false;
op1 = gimple_assign_rhs2 (stmt);
- if (!vect_is_simple_use (op1, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt[1]))
+ if (!vect_is_simple_use_1 (op1, loop_vinfo, bb_vinfo, &def_stmt, &def,
+ &dt[1], &op1_vectype))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -2415,6 +2453,16 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
optab = optab_for_tree_code (code, vectype, optab_vector);
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "vector/vector shift/rotate found.");
+ if (!op1_vectype)
+ op1_vectype = get_same_sized_vectype (TREE_TYPE (op1), vectype_out);
+ if (op1_vectype == NULL_TREE
+ || TYPE_MODE (op1_vectype) != TYPE_MODE (vectype))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "unusable type for last operand in"
+ " vector/vector shift/rotate.");
+ return false;
+ }
}
/* See if the machine has a vector shifted by scalar insn and if not
then see if it has a vector shifted by vector insn. */
@@ -2442,9 +2490,28 @@ vectorizable_shift (gimple stmt, gimple_stmt_iterator *gsi,
/* Unlike the other binary operators, shifts/rotates have
the rhs being int, instead of the same type as the lhs,
so make sure the scalar is the right type if we are
- dealing with vectors of short/char. */
+ dealing with vectors of long long/long/short/char. */
if (dt[1] == vect_constant_def)
op1 = fold_convert (TREE_TYPE (vectype), op1);
+ else if (!useless_type_conversion_p (TREE_TYPE (vectype),
+ TREE_TYPE (op1)))
+ {
+ if (slp_node
+ && TYPE_MODE (TREE_TYPE (vectype))
+ != TYPE_MODE (TREE_TYPE (op1)))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "unusable type for last operand in"
+ " vector/vector shift/rotate.");
+ return false;
+ }
+ if (vec_stmt && !slp_node)
+ {
+ op1 = fold_convert (TREE_TYPE (vectype), op1);
+ op1 = vect_init_vector (stmt, op1,
+ TREE_TYPE (vectype), NULL);
+ }
+ }
}
}
}
@@ -2660,6 +2727,20 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
scalar_dest = gimple_assign_lhs (stmt);
vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+ /* Most operations cannot handle bit-precision types without extra
+ truncations. */
+ if ((TYPE_PRECISION (TREE_TYPE (scalar_dest))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (scalar_dest))))
+ /* Exception are bitwise binary operations. */
+ && code != BIT_IOR_EXPR
+ && code != BIT_XOR_EXPR
+ && code != BIT_AND_EXPR)
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "bit-precision arithmetic not supported.");
+ return false;
+ }
+
op0 = gimple_assign_rhs1 (stmt);
if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
&def_stmt, &def, &dt[0], &vectype))
@@ -3082,9 +3163,20 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
&& INTEGRAL_TYPE_P (TREE_TYPE (op0)))
|| (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
- && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
- && CONVERT_EXPR_CODE_P (code))))
+ && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0)))))
return false;
+
+ if (INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
+ && ((TYPE_PRECISION (TREE_TYPE (scalar_dest))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (scalar_dest))))
+ || ((TYPE_PRECISION (TREE_TYPE (op0))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (op0)))))))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "type demotion to/from bit-precision unsupported.");
+ return false;
+ }
+
if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
&def_stmt, &def, &dt[0], &vectype_in))
{
@@ -3333,6 +3425,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
VEC (tree, heap) *vec_dsts = NULL, *interm_types = NULL, *tmp_vec_dsts = NULL;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ unsigned int k;
if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false;
@@ -3349,7 +3442,8 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
code = gimple_assign_rhs_code (stmt);
if (!CONVERT_EXPR_CODE_P (code)
- && code != WIDEN_MULT_EXPR)
+ && code != WIDEN_MULT_EXPR
+ && code != WIDEN_LSHIFT_EXPR)
return false;
scalar_dest = gimple_assign_lhs (stmt);
@@ -3363,6 +3457,19 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
&& SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
&& CONVERT_EXPR_CODE_P (code))))
return false;
+
+ if (INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
+ && ((TYPE_PRECISION (TREE_TYPE (scalar_dest))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (scalar_dest))))
+ || ((TYPE_PRECISION (TREE_TYPE (op0))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (op0)))))))
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "type promotion to/from bit-precision "
+ "unsupported.");
+ return false;
+ }
+
if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
&def_stmt, &def, &dt[0], &vectype_in))
{
@@ -3377,7 +3484,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
bool ok;
op1 = gimple_assign_rhs2 (stmt);
- if (code == WIDEN_MULT_EXPR)
+ if (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR)
{
/* For WIDEN_MULT_EXPR, if OP0 is a constant, use the type of
OP1. */
@@ -3454,7 +3561,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
fprintf (vect_dump, "transform type promotion operation. ncopies = %d.",
ncopies);
- if (code == WIDEN_MULT_EXPR)
+ if (code == WIDEN_MULT_EXPR || code == WIDEN_LSHIFT_EXPR)
{
if (CONSTANT_CLASS_P (op0))
op0 = fold_convert (TREE_TYPE (op1), op0);
@@ -3495,6 +3602,8 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
if (op_type == binary_op)
vec_oprnds1 = VEC_alloc (tree, heap, 1);
}
+ else if (code == WIDEN_LSHIFT_EXPR)
+ vec_oprnds1 = VEC_alloc (tree, heap, slp_node->vec_stmts_size);
/* In case the vectorization factor (VF) is bigger than the number
of elements that we can fit in a vectype (nunits), we have to generate
@@ -3508,15 +3617,33 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
if (j == 0)
{
if (slp_node)
- vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0,
- &vec_oprnds1, -1);
- else
+ {
+ if (code == WIDEN_LSHIFT_EXPR)
+ {
+ vec_oprnd1 = op1;
+ /* Store vec_oprnd1 for every vector stmt to be created
+ for SLP_NODE. We check during the analysis that all
+ the shift arguments are the same. */
+ for (k = 0; k < slp_node->vec_stmts_size - 1; k++)
+ VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
+
+ vect_get_slp_defs (op0, NULL_TREE, slp_node, &vec_oprnds0, NULL,
+ -1);
+ }
+ else
+ vect_get_slp_defs (op0, op1, slp_node, &vec_oprnds0,
+ &vec_oprnds1, -1);
+ }
+ else
{
vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
VEC_quick_push (tree, vec_oprnds0, vec_oprnd0);
if (op_type == binary_op)
{
- vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
+ if (code == WIDEN_LSHIFT_EXPR)
+ vec_oprnd1 = op1;
+ else
+ vec_oprnd1 = vect_get_vec_def_for_operand (op1, stmt, NULL);
VEC_quick_push (tree, vec_oprnds1, vec_oprnd1);
}
}
@@ -3527,7 +3654,10 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
VEC_replace (tree, vec_oprnds0, 0, vec_oprnd0);
if (op_type == binary_op)
{
- vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
+ if (code == WIDEN_LSHIFT_EXPR)
+ vec_oprnd1 = op1;
+ else
+ vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt[1], vec_oprnd1);
VEC_replace (tree, vec_oprnds1, 0, vec_oprnd1);
}
}
@@ -3631,6 +3761,9 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
return false;
scalar_dest = gimple_assign_lhs (stmt);
+ if (TREE_CODE (scalar_dest) == VIEW_CONVERT_EXPR
+ && is_pattern_stmt_p (stmt_info))
+ scalar_dest = TREE_OPERAND (scalar_dest, 0);
if (TREE_CODE (scalar_dest) != ARRAY_REF
&& TREE_CODE (scalar_dest) != INDIRECT_REF
&& TREE_CODE (scalar_dest) != COMPONENT_REF
@@ -3648,17 +3781,9 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
return false;
}
- /* The scalar rhs type needs to be trivially convertible to the vector
- component type. This should always be the case. */
elem_type = TREE_TYPE (vectype);
- if (!useless_type_conversion_p (elem_type, TREE_TYPE (op)))
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "??? operands of different types");
- return false;
- }
-
vec_mode = TYPE_MODE (vectype);
+
/* FORNOW. In some cases can vectorize even if data-type not supported
(e.g. - array initialization with 0). */
if (optab_handler (mov_optab, vec_mode) == CODE_FOR_nothing)
@@ -3996,41 +4121,37 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
}
/* Given a vector type VECTYPE returns a builtin DECL to be used
- for vector permutation and stores a mask into *MASK that implements
- reversal of the vector elements. If that is impossible to do
- returns NULL (and *MASK is unchanged). */
+ for vector permutation and returns the mask that implements
+ reversal of the vector elements. If that is impossible to do,
+ returns NULL. */
static tree
-perm_mask_for_reverse (tree vectype, tree *mask)
+perm_mask_for_reverse (tree vectype)
{
- tree builtin_decl;
- tree mask_element_type, mask_type;
- tree mask_vec = NULL;
- int i;
- int nunits;
- if (!targetm.vectorize.builtin_vec_perm)
- return NULL;
+ tree mask_elt_type, mask_type, mask_vec;
+ int i, nunits;
+ unsigned char *sel;
- builtin_decl = targetm.vectorize.builtin_vec_perm (vectype,
- &mask_element_type);
- if (!builtin_decl || !mask_element_type)
- return NULL;
-
- mask_type = get_vectype_for_scalar_type (mask_element_type);
nunits = TYPE_VECTOR_SUBPARTS (vectype);
- if (!mask_type
- || TYPE_VECTOR_SUBPARTS (vectype) != TYPE_VECTOR_SUBPARTS (mask_type))
+ sel = XALLOCAVEC (unsigned char, nunits);
+
+ for (i = 0; i < nunits; ++i)
+ sel[i] = nunits - 1 - i;
+
+ if (!can_vec_perm_p (TYPE_MODE (vectype), false, sel))
return NULL;
+ mask_elt_type
+ = lang_hooks.types.type_for_size
+ (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (vectype))), 1);
+ mask_type = get_vectype_for_scalar_type (mask_elt_type);
+
+ mask_vec = NULL;
for (i = 0; i < nunits; i++)
- mask_vec = tree_cons (NULL, build_int_cst (mask_element_type, i), mask_vec);
+ mask_vec = tree_cons (NULL, build_int_cst (mask_elt_type, i), mask_vec);
mask_vec = build_vector (mask_type, mask_vec);
- if (!targetm.vectorize.builtin_vec_perm_ok (vectype, mask_vec))
- return NULL;
- if (mask)
- *mask = mask_vec;
- return builtin_decl;
+ return mask_vec;
}
/* Given a vector variable X, that was generated for the scalar LHS of
@@ -4041,27 +4162,16 @@ static tree
reverse_vec_elements (tree x, gimple stmt, gimple_stmt_iterator *gsi)
{
tree vectype = TREE_TYPE (x);
- tree mask_vec, builtin_decl;
- tree perm_dest, data_ref;
+ tree mask_vec, perm_dest, data_ref;
gimple perm_stmt;
- builtin_decl = perm_mask_for_reverse (vectype, &mask_vec);
+ mask_vec = perm_mask_for_reverse (vectype);
perm_dest = vect_create_destination_var (gimple_assign_lhs (stmt), vectype);
/* Generate the permute statement. */
- perm_stmt = gimple_build_call (builtin_decl, 3, x, x, mask_vec);
- if (!useless_type_conversion_p (vectype,
- TREE_TYPE (TREE_TYPE (builtin_decl))))
- {
- tree tem = create_tmp_reg (TREE_TYPE (TREE_TYPE (builtin_decl)), NULL);
- tem = make_ssa_name (tem, perm_stmt);
- gimple_call_set_lhs (perm_stmt, tem);
- vect_finish_stmt_generation (stmt, perm_stmt, gsi);
- perm_stmt = gimple_build_assign (NULL_TREE,
- build1 (VIEW_CONVERT_EXPR,
- vectype, tem));
- }
+ perm_stmt = gimple_build_assign_with_ops3 (VEC_PERM_EXPR, perm_dest,
+ x, x, mask_vec);
data_ref = make_ssa_name (perm_dest, perm_stmt);
gimple_set_lhs (perm_stmt, data_ref);
vect_finish_stmt_generation (stmt, perm_stmt, gsi);
@@ -4111,7 +4221,6 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
bool strided_load = false;
bool load_lanes_p = false;
gimple first_stmt;
- tree scalar_type;
bool inv_p;
bool negative;
bool compute_in_loop = false;
@@ -4186,7 +4295,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
return false;
}
- scalar_type = TREE_TYPE (DR_REF (dr));
+ elem_type = TREE_TYPE (vectype);
mode = TYPE_MODE (vectype);
/* FORNOW. In some cases can vectorize even if data-type not supported
@@ -4198,16 +4307,6 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
return false;
}
- /* The vector component type needs to be trivially convertible to the
- scalar lhs. This should always be the case. */
- elem_type = TREE_TYPE (vectype);
- if (!useless_type_conversion_p (TREE_TYPE (scalar_dest), elem_type))
- {
- if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "??? operands of different types");
- return false;
- }
-
/* Check if the load is a part of an interleaving chain. */
if (STMT_VINFO_STRIDED_ACCESS (stmt_info))
{
@@ -4237,7 +4336,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
fprintf (vect_dump, "negative step but alignment required.");
return false;
}
- if (!perm_mask_for_reverse (vectype, NULL))
+ if (!perm_mask_for_reverse (vectype))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "negative step and reversing not supported.");
@@ -4260,6 +4359,11 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
if (strided_load)
{
first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
+ if (slp
+ && !SLP_INSTANCE_LOAD_PERMUTATION (slp_node_instance)
+ && first_stmt != VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0))
+ first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0);
+
/* Check if the chain of loads is already vectorized. */
if (STMT_VINFO_VEC_STMT (vinfo_for_stmt (first_stmt)))
{
@@ -4549,7 +4653,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
msq = new_temp;
bump = size_binop (MULT_EXPR, vs_minus_1,
- TYPE_SIZE_UNIT (scalar_type));
+ TYPE_SIZE_UNIT (elem_type));
ptr = bump_vector_ptr (dataref_ptr, NULL, gsi, stmt, bump);
new_stmt = gimple_build_assign_with_ops
(BIT_AND_EXPR, NULL_TREE, ptr,
@@ -4622,11 +4726,20 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
/* 4. Handle invariant-load. */
if (inv_p && !bb_vinfo)
{
- tree vec_inv;
+ tree tem, vec_inv;
gimple_stmt_iterator gsi2 = *gsi;
gcc_assert (!strided_load);
gsi_next (&gsi2);
- vec_inv = build_vector_from_val (vectype, scalar_dest);
+ tem = scalar_dest;
+ if (!useless_type_conversion_p (TREE_TYPE (vectype),
+ TREE_TYPE (tem)))
+ {
+ tem = fold_convert (TREE_TYPE (vectype), tem);
+ tem = force_gimple_operand_gsi (&gsi2, tem, true,
+ NULL_TREE, true,
+ GSI_SAME_STMT);
+ }
+ vec_inv = build_vector_from_val (vectype, tem);
new_temp = vect_init_vector (stmt, vec_inv,
vectype, &gsi2);
new_stmt = SSA_NAME_DEF_STMT (new_temp);
@@ -5430,13 +5543,14 @@ get_vectype_for_scalar_type_and_size (tree scalar_type, unsigned size)
if (nbytes < TYPE_ALIGN_UNIT (scalar_type))
return NULL_TREE;
- /* If we'd build a vector type of elements whose mode precision doesn't
- match their types precision we'll get mismatched types on vector
- extracts via BIT_FIELD_REFs. This effectively means we disable
- vectorization of bool and/or enum types in some languages. */
+ /* For vector types of elements whose mode precision doesn't
+ match their types precision we use a element type of mode
+ precision. The vectorization routines will have to make sure
+ they support the proper result truncation/extension. */
if (INTEGRAL_TYPE_P (scalar_type)
&& GET_MODE_BITSIZE (inner_mode) != TYPE_PRECISION (scalar_type))
- return NULL_TREE;
+ scalar_type = build_nonstandard_integer_type (GET_MODE_BITSIZE (inner_mode),
+ TYPE_UNSIGNED (scalar_type));
if (GET_MODE_CLASS (inner_mode) != MODE_INT
&& GET_MODE_CLASS (inner_mode) != MODE_FLOAT)
@@ -5803,6 +5917,19 @@ supportable_widening_operation (enum tree_code code, gimple stmt,
}
break;
+ case WIDEN_LSHIFT_EXPR:
+ if (BYTES_BIG_ENDIAN)
+ {
+ c1 = VEC_WIDEN_LSHIFT_HI_EXPR;
+ c2 = VEC_WIDEN_LSHIFT_LO_EXPR;
+ }
+ else
+ {
+ c2 = VEC_WIDEN_LSHIFT_HI_EXPR;
+ c1 = VEC_WIDEN_LSHIFT_LO_EXPR;
+ }
+ break;
+
CASE_CONVERT:
if (BYTES_BIG_ENDIAN)
{
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index f22add6b754..6703edb5ee0 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -832,7 +832,7 @@ extern enum dr_alignment_support vect_supportable_dr_alignment
extern tree vect_get_smallest_scalar_type (gimple, HOST_WIDE_INT *,
HOST_WIDE_INT *);
extern bool vect_analyze_data_ref_dependences (loop_vec_info, bb_vec_info,
- int *, bool *);
+ int *);
extern bool vect_enhance_data_refs_alignment (loop_vec_info);
extern bool vect_analyze_data_refs_alignment (loop_vec_info, bb_vec_info);
extern bool vect_verify_datarefs_alignment (loop_vec_info, bb_vec_info);
@@ -902,7 +902,7 @@ extern void vect_slp_transform_bb (basic_block);
Additional pattern recognition functions can (and will) be added
in the future. */
typedef gimple (* vect_recog_func_ptr) (VEC (gimple, heap) **, tree *, tree *);
-#define NUM_PATTERNS 6
+#define NUM_PATTERNS 9
void vect_pattern_recog (loop_vec_info);
/* In tree-vectorizer.c. */
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 56fc5a20b2b..248bc61926f 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -1519,7 +1519,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
limit = avoid_overflow_infinity (limit);
- type = TREE_TYPE (limit);
+ type = TREE_TYPE (var);
gcc_assert (limit != var);
/* For pointer arithmetic, we only keep track of pointer equality
@@ -1693,8 +1693,8 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
/* For LT_EXPR, we create the range [MIN, MAX - 1]. */
if (cond_code == LT_EXPR)
{
- tree one = build_int_cst (type, 1);
- max = fold_build2 (MINUS_EXPR, type, max, one);
+ tree one = build_int_cst (TREE_TYPE (max), 1);
+ max = fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, one);
if (EXPR_P (max))
TREE_NO_WARNING (max) = 1;
}
@@ -1728,8 +1728,8 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
/* For GT_EXPR, we create the range [MIN + 1, MAX]. */
if (cond_code == GT_EXPR)
{
- tree one = build_int_cst (type, 1);
- min = fold_build2 (PLUS_EXPR, type, min, one);
+ tree one = build_int_cst (TREE_TYPE (min), 1);
+ min = fold_build2 (PLUS_EXPR, TREE_TYPE (min), min, one);
if (EXPR_P (min))
TREE_NO_WARNING (min) = 1;
}
@@ -2913,15 +2913,10 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
determining if it evaluates to NULL [0, 0] or non-NULL (~[0, 0]). */
if (POINTER_TYPE_P (type))
{
- if (CONVERT_EXPR_CODE_P (code))
- {
- if (range_is_nonnull (&vr0))
- set_value_range_to_nonnull (vr, type);
- else if (range_is_null (&vr0))
- set_value_range_to_null (vr, type);
- else
- set_value_range_to_varying (vr);
- }
+ if (range_is_nonnull (&vr0))
+ set_value_range_to_nonnull (vr, type);
+ else if (range_is_null (&vr0))
+ set_value_range_to_null (vr, type);
else
set_value_range_to_varying (vr);
return;
@@ -7288,10 +7283,17 @@ simplify_conversion_using_ranges (gimple stmt)
TYPE_UNSIGNED (TREE_TYPE (middleop)));
middlemax = double_int_ext (innermax, TYPE_PRECISION (TREE_TYPE (middleop)),
TYPE_UNSIGNED (TREE_TYPE (middleop)));
- /* If the middle values do not represent a proper range fail. */
- if (double_int_cmp (middlemin, middlemax,
- TYPE_UNSIGNED (TREE_TYPE (middleop))) > 0)
+ /* If the middle values are not equal to the original values fail.
+ But only if the inner cast truncates (thus we ignore differences
+ in extension to handle the case going from a range to an anti-range
+ and back). */
+ if ((TYPE_PRECISION (TREE_TYPE (innerop))
+ > TYPE_PRECISION (TREE_TYPE (middleop)))
+ && (!double_int_equal_p (innermin, middlemin)
+ || !double_int_equal_p (innermax, middlemax)))
return false;
+ /* Require that the final conversion applied to both the original
+ and the intermediate range produces the same result. */
if (!double_int_equal_p (double_int_ext (middlemin,
TYPE_PRECISION (finaltype),
TYPE_UNSIGNED (finaltype)),
diff --git a/gcc/tree.c b/gcc/tree.c
index 64c49688575..2cbd68b5fd9 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1525,6 +1525,7 @@ build_real_from_int_cst (tree type, const_tree i)
/* Return a newly constructed STRING_CST node whose value is
the LEN characters at STR.
+ Note that for a C string literal, LEN should include the trailing NUL.
The TREE_TYPE is not initialized. */
tree
diff --git a/gcc/tree.def b/gcc/tree.def
index 3e5981947fd..77dc7d7489a 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1125,6 +1125,19 @@ DEFTREECODE (WIDEN_MULT_PLUS_EXPR, "widen_mult_plus_expr", tcc_expression, 3)
is subtracted from t3. */
DEFTREECODE (WIDEN_MULT_MINUS_EXPR, "widen_mult_minus_expr", tcc_expression, 3)
+/* Widening shift left.
+ The first operand is of type t1.
+ The second operand is the number of bits to shift by; it need not be the
+ same type as the first operand and result.
+ Note that the result is undefined if the second operand is larger
+ than or equal to the first operand's type size.
+ The type of the entire expression is t2, such that t2 is at least twice
+ the size of t1.
+ WIDEN_LSHIFT_EXPR is equivalent to first widening (promoting)
+ the first argument from type t1 to type t2, and then shifting it
+ by the second argument. */
+DEFTREECODE (WIDEN_LSHIFT_EXPR, "widen_lshift_expr", tcc_binary, 2)
+
/* Fused multiply-add.
All operands and the result are of the same type. No intermediate
rounding is performed after multiplying operand one with operand two
@@ -1173,12 +1186,22 @@ DEFTREECODE (VEC_PACK_SAT_EXPR, "vec_pack_sat_expr", tcc_binary, 2)
DEFTREECODE (VEC_PACK_FIX_TRUNC_EXPR, "vec_pack_fix_trunc_expr", tcc_binary, 2)
/* Extract even/odd fields from vectors. */
-DEFTREECODE (VEC_EXTRACT_EVEN_EXPR, "vec_extracteven_expr", tcc_binary, 2)
-DEFTREECODE (VEC_EXTRACT_ODD_EXPR, "vec_extractodd_expr", tcc_binary, 2)
+DEFTREECODE (VEC_EXTRACT_EVEN_EXPR, "vec_extract_even_expr", tcc_binary, 2)
+DEFTREECODE (VEC_EXTRACT_ODD_EXPR, "vec_extract_odd_expr", tcc_binary, 2)
/* Merge input vectors interleaving their fields. */
-DEFTREECODE (VEC_INTERLEAVE_HIGH_EXPR, "vec_interleavehigh_expr", tcc_binary, 2)
-DEFTREECODE (VEC_INTERLEAVE_LOW_EXPR, "vec_interleavelow_expr", tcc_binary, 2)
+DEFTREECODE (VEC_INTERLEAVE_HIGH_EXPR, "vec_interleave_high_expr", tcc_binary, 2)
+DEFTREECODE (VEC_INTERLEAVE_LOW_EXPR, "vec_interleave_low_expr", tcc_binary, 2)
+
+/* Widening vector shift left in bits.
+ Operand 0 is a vector to be shifted with N elements of size S.
+ Operand 1 is an integer shift amount in bits.
+ The result of the operation is N elements of size 2*S.
+ VEC_WIDEN_LSHIFT_HI_EXPR computes the N/2 high results.
+ VEC_WIDEN_LSHIFT_LO_EXPR computes the N/2 low results.
+ */
+DEFTREECODE (VEC_WIDEN_LSHIFT_HI_EXPR, "widen_lshift_hi_expr", tcc_binary, 2)
+DEFTREECODE (VEC_WIDEN_LSHIFT_LO_EXPR, "widen_lshift_lo_expr", tcc_binary, 2)
/* PREDICT_EXPR. Specify hint for branch prediction. The
PREDICT_EXPR_PREDICTOR specify predictor and PREDICT_EXPR_OUTCOME the
diff --git a/gcc/tree.h b/gcc/tree.h
index 18fdd07fe4e..4f9970b3c8c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1120,6 +1120,13 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
(TREE_CODE (TYPE) == COMPLEX_TYPE \
&& TREE_CODE (TREE_TYPE (TYPE)) == REAL_TYPE)
+/* Nonzero if TYPE represents a vector integer type. */
+
+#define VECTOR_INTEGER_TYPE_P(TYPE) \
+ (TREE_CODE (TYPE) == VECTOR_TYPE \
+ && TREE_CODE (TREE_TYPE (TYPE)) == INTEGER_TYPE)
+
+
/* Nonzero if TYPE represents a vector floating-point type. */
#define VECTOR_FLOAT_TYPE_P(TYPE) \
@@ -2967,6 +2974,17 @@ extern void decl_value_expr_insert (tree, tree);
/* The DECL_RTL for NODE, if it is set, or NULL, if it is not set. */
#define DECL_RTL_IF_SET(NODE) (DECL_RTL_SET_P (NODE) ? DECL_RTL (NODE) : NULL)
+#if (GCC_VERSION >= 2007)
+#define DECL_RTL_KNOWN_SET(decl) __extension__ \
+({ tree const __d = (decl); \
+ gcc_checking_assert (DECL_RTL_SET_P (__d)); \
+ /* Dereference it so the compiler knows it can't be NULL even \
+ without assertion checking. */ \
+ &*DECL_RTL_IF_SET (__d); })
+#else
+#define DECL_RTL_KNOWN_SET(decl) (&*DECL_RTL_IF_SET (decl))
+#endif
+
/* In VAR_DECL and PARM_DECL nodes, nonzero means declared `register'. */
#define DECL_REGISTER(NODE) (DECL_WRTL_CHECK (NODE)->decl_common.decl_flag_0)
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 214f58a8ac2..11d4efdcdc2 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -301,6 +301,48 @@ typedef struct location_chain_def
enum var_init_status init;
} *location_chain;
+/* A vector of loc_exp_dep holds the active dependencies of a one-part
+ DV on VALUEs, i.e., the VALUEs expanded so as to form the current
+ location of DV. Each entry is also part of VALUE' s linked-list of
+ backlinks back to DV. */
+typedef struct loc_exp_dep_s
+{
+ /* The dependent DV. */
+ decl_or_value dv;
+ /* The dependency VALUE or DECL_DEBUG. */
+ rtx value;
+ /* The next entry in VALUE's backlinks list. */
+ struct loc_exp_dep_s *next;
+ /* A pointer to the pointer to this entry (head or prev's next) in
+ the doubly-linked list. */
+ struct loc_exp_dep_s **pprev;
+} loc_exp_dep;
+
+DEF_VEC_O (loc_exp_dep);
+
+/* This data structure is allocated for one-part variables at the time
+ of emitting notes. */
+struct onepart_aux
+{
+ /* Doubly-linked list of dependent DVs. These are DVs whose cur_loc
+ computation used the expansion of this variable, and that ought
+ to be notified should this variable change. If the DV's cur_loc
+ expanded to NULL, all components of the loc list are regarded as
+ active, so that any changes in them give us a chance to get a
+ location. Otherwise, only components of the loc that expanded to
+ non-NULL are regarded as active dependencies. */
+ loc_exp_dep *backlinks;
+ /* This holds the LOC that was expanded into cur_loc. We need only
+ mark a one-part variable as changed if the FROM loc is removed,
+ or if it has no known location and a loc is added, or if it gets
+ a change notification from any of its active dependencies. */
+ rtx from;
+ /* The depth of the cur_loc expression. */
+ int depth;
+ /* Dependencies actively used when expand FROM into cur_loc. */
+ VEC (loc_exp_dep, none) deps;
+};
+
/* Structure describing one part of variable. */
typedef struct variable_part_def
{
@@ -310,13 +352,33 @@ typedef struct variable_part_def
/* Location which was last emitted to location list. */
rtx cur_loc;
- /* The offset in the variable. */
- HOST_WIDE_INT offset;
+ union variable_aux
+ {
+ /* The offset in the variable, if !var->onepart. */
+ HOST_WIDE_INT offset;
+
+ /* Pointer to auxiliary data, if var->onepart and emit_notes. */
+ struct onepart_aux *onepaux;
+ } aux;
} variable_part;
/* Maximum number of location parts. */
#define MAX_VAR_PARTS 16
+/* Enumeration type used to discriminate various types of one-part
+ variables. */
+typedef enum onepart_enum
+{
+ /* Not a one-part variable. */
+ NOT_ONEPART = 0,
+ /* A one-part DECL that is not a DEBUG_EXPR_DECL. */
+ ONEPART_VDECL = 1,
+ /* A DEBUG_EXPR_DECL. */
+ ONEPART_DEXPR = 2,
+ /* A VALUE. */
+ ONEPART_VALUE = 3
+} onepart_enum_t;
+
/* Structure describing where the variable is located. */
typedef struct variable_def
{
@@ -330,10 +392,8 @@ typedef struct variable_def
/* Number of variable parts. */
char n_var_parts;
- /* True if this variable changed (any of its) cur_loc fields
- during the current emit_notes_for_changes resp.
- emit_notes_for_differences call. */
- bool cur_loc_changed;
+ /* What type of DV this is, according to enum onepart_enum. */
+ ENUM_BITFIELD (onepart_enum) onepart : CHAR_BIT;
/* True if this variable_def struct is currently in the
changed_variables hash table. */
@@ -344,29 +404,48 @@ typedef struct variable_def
} *variable;
typedef const struct variable_def *const_variable;
-/* Structure for chaining backlinks from referenced VALUEs to
- DVs that are referencing them. */
-typedef struct value_chain_def
-{
- /* Next value_chain entry. */
- struct value_chain_def *next;
-
- /* The declaration of the variable, or an RTL value
- being handled like a declaration, whose var_parts[0].loc_chain
- references the VALUE owning this value_chain. */
- decl_or_value dv;
-
- /* Reference count. */
- int refcount;
-} *value_chain;
-typedef const struct value_chain_def *const_value_chain;
-
/* Pointer to the BB's information specific to variable tracking pass. */
#define VTI(BB) ((variable_tracking_info) (BB)->aux)
/* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
#define INT_MEM_OFFSET(mem) (MEM_OFFSET_KNOWN_P (mem) ? MEM_OFFSET (mem) : 0)
+#if ENABLE_CHECKING && (GCC_VERSION >= 2007)
+
+/* Access VAR's Ith part's offset, checking that it's not a one-part
+ variable. */
+#define VAR_PART_OFFSET(var, i) __extension__ \
+(*({ variable const __v = (var); \
+ gcc_checking_assert (!__v->onepart); \
+ &__v->var_part[(i)].aux.offset; }))
+
+/* Access VAR's one-part auxiliary data, checking that it is a
+ one-part variable. */
+#define VAR_LOC_1PAUX(var) __extension__ \
+(*({ variable const __v = (var); \
+ gcc_checking_assert (__v->onepart); \
+ &__v->var_part[0].aux.onepaux; }))
+
+#else
+#define VAR_PART_OFFSET(var, i) ((var)->var_part[(i)].aux.offset)
+#define VAR_LOC_1PAUX(var) ((var)->var_part[0].aux.onepaux)
+#endif
+
+/* These are accessor macros for the one-part auxiliary data. When
+ convenient for users, they're guarded by tests that the data was
+ allocated. */
+#define VAR_LOC_DEP_LST(var) (VAR_LOC_1PAUX (var) \
+ ? VAR_LOC_1PAUX (var)->backlinks \
+ : NULL)
+#define VAR_LOC_DEP_LSTP(var) (VAR_LOC_1PAUX (var) \
+ ? &VAR_LOC_1PAUX (var)->backlinks \
+ : NULL)
+#define VAR_LOC_FROM(var) (VAR_LOC_1PAUX (var)->from)
+#define VAR_LOC_DEPTH(var) (VAR_LOC_1PAUX (var)->depth)
+#define VAR_LOC_DEP_VEC(var) (VAR_LOC_1PAUX (var) \
+ ? &VAR_LOC_1PAUX (var)->deps \
+ : NULL)
+
/* Alloc pool for struct attrs_def. */
static alloc_pool attrs_pool;
@@ -382,24 +461,24 @@ static alloc_pool loc_chain_pool;
/* Alloc pool for struct shared_hash_def. */
static alloc_pool shared_hash_pool;
-/* Alloc pool for struct value_chain_def. */
-static alloc_pool value_chain_pool;
-
/* Changed variables, notes will be emitted for them. */
static htab_t changed_variables;
-/* Links from VALUEs to DVs referencing them in their current loc_chains. */
-static htab_t value_chains;
-
/* Shall notes be emitted? */
static bool emit_notes;
+/* Values whose dynamic location lists have gone empty, but whose
+ cselib location lists are still usable. Use this to hold the
+ current location, the backlinks, etc, during emit_notes. */
+static htab_t dropped_values;
+
/* Empty shared hashtable. */
static shared_hash empty_shared_hash;
/* Scratch register bitmap used by cselib_expand_value_rtx. */
static bitmap scratch_regs = NULL;
+#ifdef HAVE_window_save
typedef struct GTY(()) parm_reg {
rtx outgoing;
rtx incoming;
@@ -410,6 +489,7 @@ DEF_VEC_ALLOC_O(parm_reg_t, gc);
/* Vector of windowed parameter registers, if any. */
static VEC(parm_reg_t, gc) *windowed_parm_regs = NULL;
+#endif
/* Variable used to tell whether cselib_process_insn called our hook. */
static bool cselib_hook_called;
@@ -420,7 +500,6 @@ static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
static void insn_stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
HOST_WIDE_INT *);
static bool vt_stack_adjustments (void);
-static void note_register_arguments (rtx);
static hashval_t variable_htab_hash (const void *);
static int variable_htab_eq (const void *, const void *);
static void variable_htab_free (void *);
@@ -476,6 +555,7 @@ static void dump_vars (htab_t);
static void dump_dataflow_set (dataflow_set *);
static void dump_dataflow_sets (void);
+static void set_dv_changed (decl_or_value, bool);
static void variable_was_changed (variable, dataflow_set *);
static void **set_slot_part (dataflow_set *, rtx, void **,
decl_or_value, HOST_WIDE_INT,
@@ -672,15 +752,11 @@ vt_stack_adjustments (void)
for (insn = BB_HEAD (dest);
insn != NEXT_INSN (BB_END (dest));
insn = NEXT_INSN (insn))
- {
- if (INSN_P (insn))
- {
- insn_stack_adjust_offset_pre_post (insn, &pre, &post);
- offset += pre + post;
- }
- if (CALL_P (insn))
- note_register_arguments (insn);
- }
+ if (INSN_P (insn))
+ {
+ insn_stack_adjust_offset_pre_post (insn, &pre, &post);
+ offset += pre + post;
+ }
VTI (dest)->out.stack_adjust = offset;
@@ -1133,6 +1209,21 @@ dv_as_value (decl_or_value dv)
return (rtx)dv;
}
+/* Return the DEBUG_EXPR of a DEBUG_EXPR_DECL or the VALUE in DV. */
+static inline rtx
+dv_as_rtx (decl_or_value dv)
+{
+ tree decl;
+
+ if (dv_is_value_p (dv))
+ return dv_as_value (dv);
+
+ decl = dv_as_decl (dv);
+
+ gcc_checking_assert (TREE_CODE (decl) == DEBUG_EXPR_DECL);
+ return DECL_RTL_KNOWN_SET (decl);
+}
+
/* Return the opaque pointer in the decl_or_value. */
static inline void *
dv_as_opaque (decl_or_value dv)
@@ -1140,36 +1231,36 @@ dv_as_opaque (decl_or_value dv)
return dv;
}
-/* Return true if a decl_or_value must not have more than one variable
- part. */
-static inline bool
+/* Return nonzero if a decl_or_value must not have more than one
+ variable part. The returned value discriminates among various
+ kinds of one-part DVs ccording to enum onepart_enum. */
+static inline onepart_enum_t
dv_onepart_p (decl_or_value dv)
{
tree decl;
if (!MAY_HAVE_DEBUG_INSNS)
- return false;
+ return NOT_ONEPART;
if (dv_is_value_p (dv))
- return true;
+ return ONEPART_VALUE;
decl = dv_as_decl (dv);
- if (!decl)
- return true;
-
if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
- return true;
+ return ONEPART_DEXPR;
+
+ if (target_for_debug_bind (decl) != NULL_TREE)
+ return ONEPART_VDECL;
- return (target_for_debug_bind (decl) != NULL_TREE);
+ return NOT_ONEPART;
}
-/* Return the variable pool to be used for dv, depending on whether it
- can have multiple parts or not. */
+/* Return the variable pool to be used for a dv of type ONEPART. */
static inline alloc_pool
-dv_pool (decl_or_value dv)
+onepart_pool (onepart_enum_t onepart)
{
- return dv_onepart_p (dv) ? valvar_pool : var_pool;
+ return onepart ? valvar_pool : var_pool;
}
/* Build a decl_or_value out of a decl. */
@@ -1192,6 +1283,30 @@ dv_from_value (rtx value)
return dv;
}
+/* Return a value or the decl of a debug_expr as a decl_or_value. */
+static inline decl_or_value
+dv_from_rtx (rtx x)
+{
+ decl_or_value dv;
+
+ switch (GET_CODE (x))
+ {
+ case DEBUG_EXPR:
+ dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
+ gcc_checking_assert (DECL_RTL_KNOWN_SET (DEBUG_EXPR_TREE_DECL (x)) == x);
+ break;
+
+ case VALUE:
+ dv = dv_from_value (x);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return dv;
+}
+
extern void debug_dv (decl_or_value dv);
DEBUG_FUNCTION void
@@ -1254,6 +1369,8 @@ variable_htab_eq (const void *x, const void *y)
return (dv_as_opaque (v->dv) == dv_as_opaque (dv));
}
+static void loc_exp_dep_clear (variable var);
+
/* Free the element of VARIABLE_HTAB (its type is struct variable_def). */
static void
@@ -1278,29 +1395,18 @@ variable_htab_free (void *elem)
}
var->var_part[i].loc_chain = NULL;
}
- pool_free (dv_pool (var->dv), var);
-}
-
-/* The hash function for value_chains htab, computes the hash value
- from the VALUE. */
-
-static hashval_t
-value_chain_htab_hash (const void *x)
-{
- const_value_chain const v = (const_value_chain) x;
-
- return dv_htab_hash (v->dv);
-}
-
-/* Compare the VALUE X with VALUE Y. */
-
-static int
-value_chain_htab_eq (const void *x, const void *y)
-{
- const_value_chain const v = (const_value_chain) x;
- decl_or_value dv = CONST_CAST2 (decl_or_value, const void *, y);
-
- return dv_as_opaque (v->dv) == dv_as_opaque (dv);
+ if (var->onepart && VAR_LOC_1PAUX (var))
+ {
+ loc_exp_dep_clear (var);
+ if (VAR_LOC_DEP_LST (var))
+ VAR_LOC_DEP_LST (var)->pprev = NULL;
+ XDELETE (VAR_LOC_1PAUX (var));
+ /* These may be reused across functions, so reset
+ e.g. NO_LOC_P. */
+ if (var->onepart == ONEPART_DEXPR)
+ set_dv_changed (var->dv, true);
+ }
+ pool_free (onepart_pool (var->onepart), var);
}
/* Initialize the set (array) SET of attrs to empty lists. */
@@ -1569,13 +1675,12 @@ unshare_variable (dataflow_set *set, void **slot, variable var,
variable new_var;
int i;
- new_var = (variable) pool_alloc (dv_pool (var->dv));
+ new_var = (variable) pool_alloc (onepart_pool (var->onepart));
new_var->dv = var->dv;
new_var->refcount = 1;
var->refcount--;
new_var->n_var_parts = var->n_var_parts;
- new_var->cur_loc_changed = var->cur_loc_changed;
- var->cur_loc_changed = false;
+ new_var->onepart = var->onepart;
new_var->in_changed_variables = false;
if (! flag_var_tracking_uninit)
@@ -1586,7 +1691,18 @@ unshare_variable (dataflow_set *set, void **slot, variable var,
location_chain node;
location_chain *nextp;
- new_var->var_part[i].offset = var->var_part[i].offset;
+ if (i == 0 && var->onepart)
+ {
+ /* One-part auxiliary data is only used while emitting
+ notes, so propagate it to the new variable in the active
+ dataflow set. If we're not emitting notes, this will be
+ a no-op. */
+ gcc_checking_assert (!VAR_LOC_1PAUX (var) || emit_notes);
+ VAR_LOC_1PAUX (new_var) = VAR_LOC_1PAUX (var);
+ VAR_LOC_1PAUX (var) = NULL;
+ }
+ else
+ VAR_PART_OFFSET (new_var, i) = VAR_PART_OFFSET (var, i);
nextp = &new_var->var_part[i].loc_chain;
for (node = var->var_part[i].loc_chain; node; node = node->next)
{
@@ -1891,6 +2007,26 @@ var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
delete_variable_part (set, loc, dv_from_decl (decl), offset);
}
+/* Return true if LOC should not be expanded for location expressions,
+ or used in them. */
+
+static inline bool
+unsuitable_loc (rtx loc)
+{
+ switch (GET_CODE (loc))
+ {
+ case PC:
+ case SCRATCH:
+ case CC0:
+ case ASM_INPUT:
+ case ASM_OPERANDS:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
/* Bind a value to a location it was just stored in. If MODIFIED
holds, assume the location was modified, detaching it from any
values bound to it. */
@@ -1904,10 +2040,10 @@ val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
if (dump_file)
{
- fprintf (dump_file, "%i: ", INSN_UID (insn));
- print_inline_rtx (dump_file, val, 0);
- fprintf (dump_file, " stored in ");
+ fprintf (dump_file, "%i: ", insn ? INSN_UID (insn) : 0);
print_inline_rtx (dump_file, loc, 0);
+ fprintf (dump_file, " evaluates to ");
+ print_inline_rtx (dump_file, val, 0);
if (v->locs)
{
struct elt_loc_list *l;
@@ -1920,6 +2056,8 @@ val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
fprintf (dump_file, "\n");
}
+ gcc_checking_assert (!unsuitable_loc (loc));
+
if (REG_P (loc))
{
if (modified)
@@ -1931,6 +2069,8 @@ val_store (dataflow_set *set, rtx val, rtx loc, rtx insn, bool modified)
var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
dv_from_value (val), 0, NULL_RTX, INSERT);
else
+ /* ??? Ideally we wouldn't get these, and use them from the static
+ cselib loc list. */
set_variable_part (set, loc, dv_from_value (val), 0,
VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
}
@@ -1997,13 +2137,6 @@ val_reset (dataflow_set *set, decl_or_value dv)
delete_variable_part (set, dv_as_value (dv), dv_from_value (cval), 0);
clobber_variable_part (set, NULL, dv, 0, NULL);
-
- /* ??? Should we make sure there aren't other available values or
- variables whose values involve this one other than by
- equivalence? E.g., at the very least we should reset MEMs, those
- shouldn't be too hard to find cselib-looking up the value as an
- address, then locating the resulting value in our own hash
- table. */
}
/* Find the values in a given location and map the val to another
@@ -2029,6 +2162,8 @@ val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
val_reset (set, dv);
+ gcc_checking_assert (!unsuitable_loc (loc));
+
if (REG_P (loc))
{
attrs node, found = NULL;
@@ -2061,6 +2196,8 @@ val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn)
var_mem_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED,
dv_from_value (val), 0, NULL_RTX, INSERT);
else
+ /* ??? Ideally we wouldn't get these, and use them from the static
+ cselib loc list. */
/* ??? Merge equivalent expressions. */
set_variable_part (set, loc, dv_from_value (val), 0,
VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
@@ -2176,10 +2313,11 @@ variable_union (variable src, dataflow_set *set)
dst = (variable) *dstp;
gcc_assert (src->n_var_parts);
+ gcc_checking_assert (src->onepart == dst->onepart);
/* We can combine one-part variables very efficiently, because their
entries are in canonical order. */
- if (dv_onepart_p (src->dv))
+ if (src->onepart)
{
location_chain *nodep, dnode, snode;
@@ -2233,16 +2371,18 @@ variable_union (variable src, dataflow_set *set)
return 1;
}
+ gcc_checking_assert (!src->onepart);
+
/* Count the number of location parts, result is K. */
for (i = 0, j = 0, k = 0;
i < src->n_var_parts && j < dst->n_var_parts; k++)
{
- if (src->var_part[i].offset == dst->var_part[j].offset)
+ if (VAR_PART_OFFSET (src, i) == VAR_PART_OFFSET (dst, j))
{
i++;
j++;
}
- else if (src->var_part[i].offset < dst->var_part[j].offset)
+ else if (VAR_PART_OFFSET (src, i) < VAR_PART_OFFSET (dst, j))
i++;
else
j++;
@@ -2252,7 +2392,7 @@ variable_union (variable src, dataflow_set *set)
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
thus there are at most MAX_VAR_PARTS different offsets. */
- gcc_assert (dv_onepart_p (dst->dv) ? k == 1 : k <= MAX_VAR_PARTS);
+ gcc_checking_assert (dst->onepart ? k == 1 : k <= MAX_VAR_PARTS);
if (dst->n_var_parts != k && shared_var_p (dst, set->vars))
{
@@ -2269,7 +2409,7 @@ variable_union (variable src, dataflow_set *set)
location_chain node, node2;
if (i >= 0 && j >= 0
- && src->var_part[i].offset == dst->var_part[j].offset)
+ && VAR_PART_OFFSET (src, i) == VAR_PART_OFFSET (dst, j))
{
/* Compute the "sorted" union of the chains, i.e. the locations which
are in both chains go first, they are sorted by the sum of
@@ -2317,7 +2457,7 @@ variable_union (variable src, dataflow_set *set)
/* The most common case, much simpler, no qsort is needed. */
location_chain dstnode = dst->var_part[j].loc_chain;
dst->var_part[k].loc_chain = dstnode;
- dst->var_part[k].offset = dst->var_part[j].offset;
+ VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET(dst, j);
node2 = dstnode;
for (node = src->var_part[i].loc_chain; node; node = node->next)
if (!((REG_P (dstnode->loc)
@@ -2455,20 +2595,20 @@ variable_union (variable src, dataflow_set *set)
dst->var_part[k].loc_chain = vui[0].lc;
}
- dst->var_part[k].offset = dst->var_part[j].offset;
+ VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (dst, j);
}
i--;
j--;
}
else if ((i >= 0 && j >= 0
- && src->var_part[i].offset < dst->var_part[j].offset)
+ && VAR_PART_OFFSET (src, i) < VAR_PART_OFFSET (dst, j))
|| i < 0)
{
dst->var_part[k] = dst->var_part[j];
j--;
}
else if ((i >= 0 && j >= 0
- && src->var_part[i].offset > dst->var_part[j].offset)
+ && VAR_PART_OFFSET (src, i) > VAR_PART_OFFSET (dst, j))
|| j < 0)
{
location_chain *nextp;
@@ -2492,7 +2632,7 @@ variable_union (variable src, dataflow_set *set)
nextp = &new_lc->next;
}
- dst->var_part[k].offset = src->var_part[i].offset;
+ VAR_PART_OFFSET (dst, k) = VAR_PART_OFFSET (src, i);
i--;
}
dst->var_part[k].cur_loc = NULL;
@@ -2543,25 +2683,46 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src)
/* Whether the value is currently being expanded. */
#define VALUE_RECURSED_INTO(x) \
(RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
-/* Whether the value is in changed_variables hash table. */
+
+/* Whether no expansion was found, saving useless lookups.
+ It must only be set when VALUE_CHANGED is clear. */
+#define NO_LOC_P(x) \
+ (RTL_FLAG_CHECK2 ("NO_LOC_P", (x), VALUE, DEBUG_EXPR)->return_val)
+
+/* Whether cur_loc in the value needs to be (re)computed. */
#define VALUE_CHANGED(x) \
(RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
-/* Whether the decl is in changed_variables hash table. */
+/* Whether cur_loc in the decl needs to be (re)computed. */
#define DECL_CHANGED(x) TREE_VISITED (x)
-/* Record that DV has been added into resp. removed from changed_variables
- hashtable. */
+/* Record (if NEWV) that DV needs to have its cur_loc recomputed. For
+ user DECLs, this means they're in changed_variables. Values and
+ debug exprs may be left with this flag set if no user variable
+ requires them to be evaluated. */
static inline void
set_dv_changed (decl_or_value dv, bool newv)
{
- if (dv_is_value_p (dv))
- VALUE_CHANGED (dv_as_value (dv)) = newv;
- else
- DECL_CHANGED (dv_as_decl (dv)) = newv;
+ switch (dv_onepart_p (dv))
+ {
+ case ONEPART_VALUE:
+ if (newv)
+ NO_LOC_P (dv_as_value (dv)) = false;
+ VALUE_CHANGED (dv_as_value (dv)) = newv;
+ break;
+
+ case ONEPART_DEXPR:
+ if (newv)
+ NO_LOC_P (DECL_RTL_KNOWN_SET (dv_as_decl (dv))) = false;
+ /* Fall through... */
+
+ default:
+ DECL_CHANGED (dv_as_decl (dv)) = newv;
+ break;
+ }
}
-/* Return true if DV is present in changed_variables hash table. */
+/* Return true if DV needs to have its cur_loc recomputed. */
static inline bool
dv_changed_p (decl_or_value dv)
@@ -2585,12 +2746,11 @@ find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
if (!var)
return NULL;
- gcc_checking_assert (dv_onepart_p (var->dv));
+ gcc_checking_assert (var->onepart);
if (!var->n_var_parts)
return NULL;
- gcc_checking_assert (var->var_part[0].offset == 0);
gcc_checking_assert (loc != dv_as_opaque (var->dv));
loc_code = GET_CODE (loc);
@@ -2639,6 +2799,8 @@ find_loc_in_1pdv (rtx loc, variable var, htab_t vars)
return find_loc_in_1pdv (loc, rvar, vars);
}
+ /* ??? Gotta look in cselib_val locations too. */
+
return NULL;
}
@@ -2683,7 +2845,7 @@ insert_into_intersection (location_chain *nodep, rtx loc,
*nodep = node;
}
-/* Insert in DEST the intersection the locations present in both
+/* Insert in DEST the intersection of the locations present in both
S1NODE and S2VAR, directly or indirectly. S1NODE is from a
variable in DSM->cur, whereas S2VAR is from DSM->src. dvar is in
DSM->dst. */
@@ -2700,11 +2862,10 @@ intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
{
location_chain s2node;
- gcc_checking_assert (dv_onepart_p (s2var->dv));
+ gcc_checking_assert (s2var->onepart);
if (s2var->n_var_parts)
{
- gcc_checking_assert (s2var->var_part[0].offset == 0);
s2node = s2var->var_part[0].loc_chain;
for (; s1node && s2node;
@@ -2750,6 +2911,8 @@ intersect_loc_chains (rtx val, location_chain *dest, struct dfset_merge *dsm,
}
}
+ /* ??? gotta look in cselib_val locations too. */
+
/* ??? if the location is equivalent to any location in src,
searched recursively
@@ -2839,6 +3002,18 @@ loc_cmp (rtx x, rtx y)
if (GET_CODE (y) == VALUE)
return 1;
+ /* Entry value is the least preferable kind of expression. */
+ if (GET_CODE (x) == ENTRY_VALUE)
+ {
+ if (GET_CODE (y) != ENTRY_VALUE)
+ return 1;
+ gcc_assert (GET_MODE (x) == GET_MODE (y));
+ return loc_cmp (XEXP (x, 0), XEXP (y, 0));
+ }
+
+ if (GET_CODE (y) == ENTRY_VALUE)
+ return -1;
+
if (GET_CODE (x) == GET_CODE (y))
/* Compare operands below. */;
else if (GET_CODE (x) < GET_CODE (y))
@@ -2933,186 +3108,23 @@ loc_cmp (rtx x, rtx y)
return 0;
}
-/* If decl or value DVP refers to VALUE from *LOC, add backlinks
- from VALUE to DVP. */
-
-static int
-add_value_chain (rtx *loc, void *dvp)
-{
- decl_or_value dv, ldv;
- value_chain vc, nvc;
- void **slot;
-
- if (GET_CODE (*loc) == VALUE)
- ldv = dv_from_value (*loc);
- else if (GET_CODE (*loc) == DEBUG_EXPR)
- ldv = dv_from_decl (DEBUG_EXPR_TREE_DECL (*loc));
- else
- return 0;
-
- if (dv_as_opaque (ldv) == dvp)
- return 0;
-
- dv = (decl_or_value) dvp;
- slot = htab_find_slot_with_hash (value_chains, ldv, dv_htab_hash (ldv),
- INSERT);
- if (!*slot)
- {
- vc = (value_chain) pool_alloc (value_chain_pool);
- vc->dv = ldv;
- vc->next = NULL;
- vc->refcount = 0;
- *slot = (void *) vc;
- }
- else
- {
- for (vc = ((value_chain) *slot)->next; vc; vc = vc->next)
- if (dv_as_opaque (vc->dv) == dv_as_opaque (dv))
- break;
- if (vc)
- {
- vc->refcount++;
- return 0;
- }
- }
- vc = (value_chain) *slot;
- nvc = (value_chain) pool_alloc (value_chain_pool);
- nvc->dv = dv;
- nvc->next = vc->next;
- nvc->refcount = 1;
- vc->next = nvc;
- return 0;
-}
-
-/* If decl or value DVP refers to VALUEs from within LOC, add backlinks
- from those VALUEs to DVP. */
-
-static void
-add_value_chains (decl_or_value dv, rtx loc)
-{
- if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR)
- {
- add_value_chain (&loc, dv_as_opaque (dv));
- return;
- }
- if (REG_P (loc))
- return;
- if (MEM_P (loc))
- loc = XEXP (loc, 0);
- for_each_rtx (&loc, add_value_chain, dv_as_opaque (dv));
-}
-
-/* If CSELIB_VAL_PTR of value DV refer to VALUEs, add backlinks from those
- VALUEs to DV. Add the same time get rid of ASM_OPERANDS from locs list,
- that is something we never can express in .debug_info and can prevent
- reverse ops from being used. */
-
-static void
-add_cselib_value_chains (decl_or_value dv)
-{
- struct elt_loc_list **l;
-
- for (l = &CSELIB_VAL_PTR (dv_as_value (dv))->locs; *l;)
- if (GET_CODE ((*l)->loc) == ASM_OPERANDS)
- *l = (*l)->next;
- else
- {
- for_each_rtx (&(*l)->loc, add_value_chain, dv_as_opaque (dv));
- l = &(*l)->next;
- }
-}
-
-/* If decl or value DVP refers to VALUE from *LOC, remove backlinks
- from VALUE to DVP. */
-
-static int
-remove_value_chain (rtx *loc, void *dvp)
-{
- decl_or_value dv, ldv;
- value_chain vc;
- void **slot;
-
- if (GET_CODE (*loc) == VALUE)
- ldv = dv_from_value (*loc);
- else if (GET_CODE (*loc) == DEBUG_EXPR)
- ldv = dv_from_decl (DEBUG_EXPR_TREE_DECL (*loc));
- else
- return 0;
-
- if (dv_as_opaque (ldv) == dvp)
- return 0;
-
- dv = (decl_or_value) dvp;
- slot = htab_find_slot_with_hash (value_chains, ldv, dv_htab_hash (ldv),
- NO_INSERT);
- for (vc = (value_chain) *slot; vc->next; vc = vc->next)
- if (dv_as_opaque (vc->next->dv) == dv_as_opaque (dv))
- {
- value_chain dvc = vc->next;
- gcc_assert (dvc->refcount > 0);
- if (--dvc->refcount == 0)
- {
- vc->next = dvc->next;
- pool_free (value_chain_pool, dvc);
- if (vc->next == NULL && vc == (value_chain) *slot)
- {
- pool_free (value_chain_pool, vc);
- htab_clear_slot (value_chains, slot);
- }
- }
- return 0;
- }
- gcc_unreachable ();
-}
-
-/* If decl or value DVP refers to VALUEs from within LOC, remove backlinks
- from those VALUEs to DVP. */
-
-static void
-remove_value_chains (decl_or_value dv, rtx loc)
-{
- if (GET_CODE (loc) == VALUE || GET_CODE (loc) == DEBUG_EXPR)
- {
- remove_value_chain (&loc, dv_as_opaque (dv));
- return;
- }
- if (REG_P (loc))
- return;
- if (MEM_P (loc))
- loc = XEXP (loc, 0);
- for_each_rtx (&loc, remove_value_chain, dv_as_opaque (dv));
-}
-
#if ENABLE_CHECKING
-/* If CSELIB_VAL_PTR of value DV refer to VALUEs, remove backlinks from those
- VALUEs to DV. */
-
-static void
-remove_cselib_value_chains (decl_or_value dv)
-{
- struct elt_loc_list *l;
-
- for (l = CSELIB_VAL_PTR (dv_as_value (dv))->locs; l; l = l->next)
- for_each_rtx (&l->loc, remove_value_chain, dv_as_opaque (dv));
-}
-
/* Check the order of entries in one-part variables. */
static int
canonicalize_loc_order_check (void **slot, void *data ATTRIBUTE_UNUSED)
{
variable var = (variable) *slot;
- decl_or_value dv = var->dv;
location_chain node, next;
#ifdef ENABLE_RTL_CHECKING
int i;
for (i = 0; i < var->n_var_parts; i++)
gcc_assert (var->var_part[0].cur_loc == NULL);
- gcc_assert (!var->cur_loc_changed && !var->in_changed_variables);
+ gcc_assert (!var->in_changed_variables);
#endif
- if (!dv_onepart_p (dv))
+ if (!var->onepart)
return 1;
gcc_assert (var->n_var_parts == 1);
@@ -3186,7 +3198,7 @@ canonicalize_values_star (void **slot, void *data)
bool has_value;
bool has_marks;
- if (!dv_onepart_p (dv))
+ if (!var->onepart)
return 1;
gcc_checking_assert (var->n_var_parts == 1);
@@ -3408,7 +3420,7 @@ canonicalize_vars_star (void **slot, void *data)
variable cvar;
location_chain cnode;
- if (!dv_onepart_p (dv) || dv_is_value_p (dv))
+ if (!var->onepart || var->onepart == ONEPART_VALUE)
return 1;
gcc_assert (var->n_var_parts == 1);
@@ -3461,7 +3473,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
void **dstslot;
variable s2var, dvar = NULL;
decl_or_value dv = s1var->dv;
- bool onepart = dv_onepart_p (dv);
+ onepart_enum_t onepart = s1var->onepart;
rtx val;
hashval_t dvhash;
location_chain node, *nodep;
@@ -3475,8 +3487,7 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
if (!onepart)
return variable_union (s1var, dst);
- gcc_checking_assert (s1var->n_var_parts == 1
- && s1var->var_part[0].offset == 0);
+ gcc_checking_assert (s1var->n_var_parts == 1);
dvhash = dv_htab_hash (dv);
if (dv_is_value_p (dv))
@@ -3493,16 +3504,16 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
dsm->src_onepart_cnt--;
gcc_assert (s2var->var_part[0].loc_chain
- && s2var->n_var_parts == 1
- && s2var->var_part[0].offset == 0);
+ && s2var->onepart == onepart
+ && s2var->n_var_parts == 1);
dstslot = shared_hash_find_slot_noinsert_1 (dst->vars, dv, dvhash);
if (dstslot)
{
dvar = (variable)*dstslot;
gcc_assert (dvar->refcount == 1
- && dvar->n_var_parts == 1
- && dvar->var_part[0].offset == 0);
+ && dvar->onepart == onepart
+ && dvar->n_var_parts == 1);
nodep = &dvar->var_part[0].loc_chain;
}
else
@@ -3529,15 +3540,18 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
{
if (node)
{
- dvar = (variable) pool_alloc (dv_pool (dv));
+ dvar = (variable) pool_alloc (onepart_pool (onepart));
dvar->dv = dv;
dvar->refcount = 1;
dvar->n_var_parts = 1;
- dvar->cur_loc_changed = false;
+ dvar->onepart = onepart;
dvar->in_changed_variables = false;
- dvar->var_part[0].offset = 0;
dvar->var_part[0].loc_chain = node;
dvar->var_part[0].cur_loc = NULL;
+ if (onepart)
+ VAR_LOC_1PAUX (dvar) = NULL;
+ else
+ VAR_PART_OFFSET (dvar, 0) = 0;
dstslot
= shared_hash_find_slot_unshare_1 (&dst->vars, dv, dvhash,
@@ -3662,15 +3676,16 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm)
INSERT);
if (!*slot)
{
- variable var = (variable) pool_alloc (dv_pool (dv));
+ variable var = (variable) pool_alloc (onepart_pool
+ (ONEPART_VALUE));
var->dv = dv;
var->refcount = 1;
var->n_var_parts = 1;
- var->cur_loc_changed = false;
+ var->onepart = ONEPART_VALUE;
var->in_changed_variables = false;
- var->var_part[0].offset = 0;
var->var_part[0].loc_chain = NULL;
var->var_part[0].cur_loc = NULL;
+ VAR_LOC_1PAUX (var) = NULL;
*slot = var;
}
@@ -3717,9 +3732,8 @@ variable_merge_over_src (variable s2var, struct dfset_merge *dsm)
{
dataflow_set *dst = dsm->dst;
decl_or_value dv = s2var->dv;
- bool onepart = dv_onepart_p (dv);
- if (!onepart)
+ if (!s2var->onepart)
{
void **dstp = shared_hash_find_slot (dst->vars, dv);
*dstp = s2var;
@@ -3864,7 +3878,7 @@ remove_duplicate_values (variable var)
{
location_chain node, *nodep;
- gcc_assert (dv_onepart_p (var->dv));
+ gcc_assert (var->onepart);
gcc_assert (var->n_var_parts == 1);
gcc_assert (var->refcount == 1);
@@ -3915,7 +3929,7 @@ variable_post_merge_new_vals (void **slot, void *info)
variable var = (variable)*slot;
location_chain node;
- if (!dv_onepart_p (var->dv) || !var->n_var_parts)
+ if (!var->onepart || !var->n_var_parts)
return 1;
gcc_assert (var->n_var_parts == 1);
@@ -4146,13 +4160,11 @@ find_mem_expr_in_1pdv (tree expr, rtx val, htab_t vars)
if (!var)
return NULL;
- gcc_assert (dv_onepart_p (var->dv));
+ gcc_assert (var->onepart);
if (!var->n_var_parts)
return NULL;
- gcc_assert (var->var_part[0].offset == 0);
-
VALUE_RECURSED_INTO (val) = true;
for (node = var->var_part[0].loc_chain; node; node = node->next)
@@ -4206,7 +4218,7 @@ dataflow_set_preserve_mem_locs (void **slot, void *data)
dataflow_set *set = (dataflow_set *) data;
variable var = (variable) *slot;
- if (dv_is_decl_p (var->dv) && dv_onepart_p (var->dv))
+ if (var->onepart == ONEPART_VDECL || var->onepart == ONEPART_DEXPR)
{
tree decl = dv_as_decl (var->dv);
location_chain loc, *locp;
@@ -4277,10 +4289,7 @@ dataflow_set_preserve_mem_locs (void **slot, void *data)
{
changed = true;
var->var_part[0].cur_loc = NULL;
- var->cur_loc_changed = true;
}
- add_value_chains (var->dv, loc->loc);
- remove_value_chains (var->dv, old_loc);
}
locp = &loc->next;
continue;
@@ -4288,12 +4297,10 @@ dataflow_set_preserve_mem_locs (void **slot, void *data)
if (emit_notes)
{
- remove_value_chains (var->dv, old_loc);
if (old_loc == var->var_part[0].cur_loc)
{
changed = true;
var->var_part[0].cur_loc = NULL;
- var->cur_loc_changed = true;
}
}
*locp = loc->next;
@@ -4321,10 +4328,11 @@ dataflow_set_remove_mem_locs (void **slot, void *data)
dataflow_set *set = (dataflow_set *) data;
variable var = (variable) *slot;
- if (dv_is_value_p (var->dv))
+ if (var->onepart == ONEPART_VALUE)
{
location_chain loc, *locp;
bool changed = false;
+ rtx cur_loc;
gcc_assert (var->n_var_parts == 1);
@@ -4343,6 +4351,11 @@ dataflow_set_remove_mem_locs (void **slot, void *data)
gcc_assert (var->n_var_parts == 1);
}
+ if (VAR_LOC_1PAUX (var))
+ cur_loc = VAR_LOC_FROM (var);
+ else
+ cur_loc = var->var_part[0].cur_loc;
+
for (locp = &var->var_part[0].loc_chain, loc = *locp;
loc; loc = *locp)
{
@@ -4353,17 +4366,16 @@ dataflow_set_remove_mem_locs (void **slot, void *data)
continue;
}
- if (emit_notes)
- remove_value_chains (var->dv, loc->loc);
*locp = loc->next;
/* If we have deleted the location which was last emitted
we have to emit new location so add the variable to set
of changed variables. */
- if (var->var_part[0].cur_loc == loc->loc)
+ if (cur_loc == loc->loc)
{
changed = true;
var->var_part[0].cur_loc = NULL;
- var->cur_loc_changed = true;
+ if (VAR_LOC_1PAUX (var))
+ VAR_LOC_FROM (var) = NULL;
}
pool_free (loc_chain_pool, loc);
}
@@ -4467,20 +4479,24 @@ variable_different_p (variable var1, variable var2)
if (var1 == var2)
return false;
+ if (var1->onepart != var2->onepart)
+ return true;
+
if (var1->n_var_parts != var2->n_var_parts)
return true;
+ if (var1->onepart && var1->n_var_parts)
+ {
+ gcc_checking_assert (dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv)
+ && var1->n_var_parts == 1);
+ /* One-part values have locations in a canonical order. */
+ return onepart_variable_different_p (var1, var2);
+ }
+
for (i = 0; i < var1->n_var_parts; i++)
{
- if (var1->var_part[i].offset != var2->var_part[i].offset)
+ if (VAR_PART_OFFSET (var1, i) != VAR_PART_OFFSET (var2, i))
return true;
- /* One-part values have locations in a canonical order. */
- if (i == 0 && var1->var_part[i].offset == 0 && dv_onepart_p (var1->dv))
- {
- gcc_assert (var1->n_var_parts == 1
- && dv_as_opaque (var1->dv) == dv_as_opaque (var2->dv));
- return onepart_variable_different_p (var1, var2);
- }
if (variable_part_different_p (&var1->var_part[i], &var2->var_part[i]))
return true;
if (variable_part_different_p (&var2->var_part[i], &var1->var_part[i]))
@@ -4891,6 +4907,18 @@ replace_expr_with_values (rtx loc)
return cselib_subst_to_values (loc, VOIDmode);
}
+/* Return true if *X is a DEBUG_EXPR. Usable as an argument to
+ for_each_rtx to tell whether there are any DEBUG_EXPRs within
+ RTX. */
+
+static int
+rtx_debug_expr_p (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+ rtx loc = *x;
+
+ return GET_CODE (loc) == DEBUG_EXPR;
+}
+
/* Determine what kind of micro operation to choose for a USE. Return
MO_CLOBBER if no micro operation is to be generated. */
@@ -4972,7 +5000,13 @@ use_type (rtx loc, struct count_use_info *cui, enum machine_mode *modep)
else if (target_for_debug_bind (var_debug_decl (expr)))
return MO_CLOBBER;
else if (track_loc_p (loc, expr, INT_MEM_OFFSET (loc),
- false, modep, NULL))
+ false, modep, NULL)
+ /* Multi-part variables shouldn't refer to one-part
+ variable names such as VALUEs (never happens) or
+ DEBUG_EXPRs (only happens in the presence of debug
+ insns). */
+ && (!MAY_HAVE_DEBUG_INSNS
+ || !for_each_rtx (&XEXP (loc, 0), rtx_debug_expr_p, NULL)))
return MO_USE;
else
return MO_CLOBBER;
@@ -5020,9 +5054,6 @@ log_op_type (rtx x, basic_block bb, rtx insn,
/* All preserved VALUEs. */
static VEC (rtx, heap) *preserved_values;
-/* Registers used in the current function for passing parameters. */
-static HARD_REG_SET argument_reg_set;
-
/* Ensure VAL is preserved and remember it in a vector for vt_emit_notes. */
static void
@@ -5089,11 +5120,7 @@ add_uses (rtx *ploc, void *data)
if (MEM_P (vloc)
&& !REG_P (XEXP (vloc, 0))
- && !MEM_P (XEXP (vloc, 0))
- && GET_CODE (XEXP (vloc, 0)) != ENTRY_VALUE
- && (GET_CODE (XEXP (vloc, 0)) != PLUS
- || XEXP (XEXP (vloc, 0), 0) != cfa_base_rtx
- || !CONST_INT_P (XEXP (XEXP (vloc, 0), 1))))
+ && !MEM_P (XEXP (vloc, 0)))
{
rtx mloc = vloc;
enum machine_mode address_mode = get_address_mode (mloc);
@@ -5105,16 +5132,24 @@ add_uses (rtx *ploc, void *data)
{
micro_operation moa;
preserve_value (val);
- mloc = cselib_subst_to_values (XEXP (mloc, 0),
- GET_MODE (mloc));
- moa.type = MO_VAL_USE;
- moa.insn = cui->insn;
- moa.u.loc = gen_rtx_CONCAT (address_mode,
- val->val_rtx, mloc);
- if (dump_file && (dump_flags & TDF_DETAILS))
- log_op_type (moa.u.loc, cui->bb, cui->insn,
- moa.type, dump_file);
- VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
+
+ if (GET_CODE (XEXP (mloc, 0)) != ENTRY_VALUE
+ && (GET_CODE (XEXP (mloc, 0)) != PLUS
+ || XEXP (XEXP (mloc, 0), 0) != cfa_base_rtx
+ || !CONST_INT_P (XEXP (XEXP (mloc, 0), 1))))
+ {
+ mloc = cselib_subst_to_values (XEXP (mloc, 0),
+ GET_MODE (mloc));
+ moa.type = MO_VAL_USE;
+ moa.insn = cui->insn;
+ moa.u.loc = gen_rtx_CONCAT (address_mode,
+ val->val_rtx, mloc);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ log_op_type (moa.u.loc, cui->bb, cui->insn,
+ moa.type, dump_file);
+ VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
+ &moa);
+ }
}
}
@@ -5122,7 +5157,7 @@ add_uses (rtx *ploc, void *data)
&& (GET_CODE (vloc) != CONST
|| for_each_rtx (&vloc, non_suitable_const, NULL)))
/* For constants don't look up any value. */;
- else if (!VAR_LOC_UNKNOWN_P (vloc)
+ else if (!VAR_LOC_UNKNOWN_P (vloc) && !unsuitable_loc (vloc)
&& (val = find_use_val (vloc, GET_MODE (oloc), cui)))
{
enum machine_mode mode2;
@@ -5168,32 +5203,36 @@ add_uses (rtx *ploc, void *data)
if (MEM_P (oloc)
&& !REG_P (XEXP (oloc, 0))
- && !MEM_P (XEXP (oloc, 0))
- && GET_CODE (XEXP (oloc, 0)) != ENTRY_VALUE
- && (GET_CODE (XEXP (oloc, 0)) != PLUS
- || XEXP (XEXP (oloc, 0), 0) != cfa_base_rtx
- || !CONST_INT_P (XEXP (XEXP (oloc, 0), 1))))
+ && !MEM_P (XEXP (oloc, 0)))
{
rtx mloc = oloc;
enum machine_mode address_mode = get_address_mode (mloc);
cselib_val *val
= cselib_lookup (XEXP (mloc, 0), address_mode, 0,
- GET_MODE (mloc));
+ GET_MODE (mloc));
if (val && !cselib_preserved_value_p (val))
{
micro_operation moa;
preserve_value (val);
- mloc = cselib_subst_to_values (XEXP (mloc, 0),
- GET_MODE (mloc));
- moa.type = MO_VAL_USE;
- moa.insn = cui->insn;
- moa.u.loc = gen_rtx_CONCAT (address_mode,
- val->val_rtx, mloc);
- if (dump_file && (dump_flags & TDF_DETAILS))
- log_op_type (moa.u.loc, cui->bb, cui->insn,
- moa.type, dump_file);
- VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &moa);
+
+ if (GET_CODE (XEXP (mloc, 0)) != ENTRY_VALUE
+ && (GET_CODE (XEXP (mloc, 0)) != PLUS
+ || XEXP (XEXP (mloc, 0), 0) != cfa_base_rtx
+ || !CONST_INT_P (XEXP (XEXP (mloc, 0), 1))))
+ {
+ mloc = cselib_subst_to_values (XEXP (mloc, 0),
+ GET_MODE (mloc));
+ moa.type = MO_VAL_USE;
+ moa.insn = cui->insn;
+ moa.u.loc = gen_rtx_CONCAT (address_mode,
+ val->val_rtx, mloc);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ log_op_type (moa.u.loc, cui->bb, cui->insn,
+ moa.type, dump_file);
+ VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
+ &moa);
+ }
}
}
@@ -5255,7 +5294,18 @@ add_uses_1 (rtx *x, void *cui)
for_each_rtx (x, add_uses, cui);
}
-#define EXPR_DEPTH (PARAM_VALUE (PARAM_MAX_VARTRACK_EXPR_DEPTH))
+/* This is the value used during expansion of locations. We want it
+ to be unbounded, so that variables expanded deep in a recursion
+ nest are fully evaluated, so that their values are cached
+ correctly. We avoid recursion cycles through other means, and we
+ don't unshare RTL, so excess complexity is not a problem. */
+#define EXPR_DEPTH (INT_MAX)
+/* We use this to keep too-complex expressions from being emitted as
+ location notes, and then to debug information. Users can trade
+ compile time for ridiculously complex expressions, although they're
+ seldom useful, and they may often have to be discarded as not
+ representable anyway. */
+#define EXPR_USE_DEPTH (PARAM_VALUE (PARAM_MAX_VARTRACK_EXPR_DEPTH))
/* Attempt to reverse the EXPR operation in the debug info. Say for
reg1 = reg2 + 6 even when reg2 is no longer live we
@@ -5382,10 +5432,8 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
mo.u.loc = loc;
if (GET_CODE (expr) == SET
&& SET_DEST (expr) == loc
- && REGNO (loc) < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (argument_reg_set, REGNO (loc))
- && find_use_val (loc, mode, cui)
- && GET_CODE (SET_SRC (expr)) != ASM_OPERANDS)
+ && !unsuitable_loc (SET_SRC (expr))
+ && find_use_val (loc, mode, cui))
{
gcc_checking_assert (type == MO_VAL_SET);
mo.u.loc = gen_rtx_SET (VOIDmode, loc, SET_SRC (expr));
@@ -5422,11 +5470,7 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
{
if (MEM_P (loc) && type == MO_VAL_SET
&& !REG_P (XEXP (loc, 0))
- && !MEM_P (XEXP (loc, 0))
- && GET_CODE (XEXP (loc, 0)) != ENTRY_VALUE
- && (GET_CODE (XEXP (loc, 0)) != PLUS
- || XEXP (XEXP (loc, 0), 0) != cfa_base_rtx
- || !CONST_INT_P (XEXP (XEXP (loc, 0), 1))))
+ && !MEM_P (XEXP (loc, 0)))
{
rtx mloc = loc;
enum machine_mode address_mode = get_address_mode (mloc);
@@ -5437,15 +5481,23 @@ add_stores (rtx loc, const_rtx expr, void *cuip)
if (val && !cselib_preserved_value_p (val))
{
preserve_value (val);
- mo.type = MO_VAL_USE;
- mloc = cselib_subst_to_values (XEXP (mloc, 0),
- GET_MODE (mloc));
- mo.u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
- mo.insn = cui->insn;
- if (dump_file && (dump_flags & TDF_DETAILS))
- log_op_type (mo.u.loc, cui->bb, cui->insn,
- mo.type, dump_file);
- VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
+
+ if (GET_CODE (XEXP (mloc, 0)) != ENTRY_VALUE
+ && (GET_CODE (XEXP (mloc, 0)) != PLUS
+ || XEXP (XEXP (mloc, 0), 0) != cfa_base_rtx
+ || !CONST_INT_P (XEXP (XEXP (mloc, 0), 1))))
+ {
+ mloc = cselib_subst_to_values (XEXP (mloc, 0),
+ GET_MODE (mloc));
+ mo.type = MO_VAL_USE;
+ mo.insn = cui->insn;
+ mo.u.loc = gen_rtx_CONCAT (address_mode,
+ val->val_rtx, mloc);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ log_op_type (mo.u.loc, cui->bb, cui->insn,
+ mo.type, dump_file);
+ VEC_safe_push (micro_operation, heap, VTI (bb)->mos, &mo);
+ }
}
}
@@ -5893,7 +5945,7 @@ prepare_call_arguments (basic_block bb, rtx insn)
tree dtemp = VEC_index (tree, *debug_args, ix + 1);
enum machine_mode mode = DECL_MODE (dtemp);
item = gen_rtx_DEBUG_PARAMETER_REF (mode, param);
- item = gen_rtx_CONCAT (mode, item, DECL_RTL (dtemp));
+ item = gen_rtx_CONCAT (mode, item, DECL_RTL_KNOWN_SET (dtemp));
call_arguments = gen_rtx_EXPR_LIST (VOIDmode, item,
call_arguments);
}
@@ -6705,7 +6757,7 @@ dump_var (variable var)
for (i = 0; i < var->n_var_parts; i++)
{
fprintf (dump_file, " offset %ld\n",
- (long) var->var_part[i].offset);
+ (long)(var->onepart ? 0 : VAR_PART_OFFSET (var, i)));
for (node = var->var_part[i].loc_chain; node; node = node->next)
{
fprintf (dump_file, " ");
@@ -6766,6 +6818,73 @@ dump_dataflow_sets (void)
}
}
+/* Return the variable for DV in dropped_values, inserting one if
+ requested with INSERT. */
+
+static inline variable
+variable_from_dropped (decl_or_value dv, enum insert_option insert)
+{
+ void **slot;
+ variable empty_var;
+ onepart_enum_t onepart;
+
+ slot = htab_find_slot_with_hash (dropped_values, dv, dv_htab_hash (dv),
+ insert);
+
+ if (!slot)
+ return NULL;
+
+ if (*slot)
+ return (variable) *slot;
+
+ gcc_checking_assert (insert == INSERT);
+
+ onepart = dv_onepart_p (dv);
+
+ gcc_checking_assert (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR);
+
+ empty_var = (variable) pool_alloc (onepart_pool (onepart));
+ empty_var->dv = dv;
+ empty_var->refcount = 1;
+ empty_var->n_var_parts = 0;
+ empty_var->onepart = onepart;
+ empty_var->in_changed_variables = false;
+ empty_var->var_part[0].loc_chain = NULL;
+ empty_var->var_part[0].cur_loc = NULL;
+ VAR_LOC_1PAUX (empty_var) = NULL;
+ set_dv_changed (dv, true);
+
+ *slot = empty_var;
+
+ return empty_var;
+}
+
+/* Recover the one-part aux from dropped_values. */
+
+static struct onepart_aux *
+recover_dropped_1paux (variable var)
+{
+ variable dvar;
+
+ gcc_checking_assert (var->onepart);
+
+ if (VAR_LOC_1PAUX (var))
+ return VAR_LOC_1PAUX (var);
+
+ if (var->onepart == ONEPART_VDECL)
+ return NULL;
+
+ dvar = variable_from_dropped (var->dv, NO_INSERT);
+
+ if (!dvar)
+ return NULL;
+
+ VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (dvar);
+ VAR_LOC_1PAUX (dvar) = NULL;
+
+ return VAR_LOC_1PAUX (var);
+}
+
/* Add variable VAR to the hash table of changed variables and
if it has no locations delete it from SET's hash table. */
@@ -6777,7 +6896,6 @@ variable_was_changed (variable var, dataflow_set *set)
if (emit_notes)
{
void **slot;
- bool old_cur_loc_changed = false;
/* Remember this decl or VALUE has been added to changed_variables. */
set_dv_changed (var->dv, true);
@@ -6791,30 +6909,76 @@ variable_was_changed (variable var, dataflow_set *set)
variable old_var = (variable) *slot;
gcc_assert (old_var->in_changed_variables);
old_var->in_changed_variables = false;
- old_cur_loc_changed = old_var->cur_loc_changed;
+ if (var != old_var && var->onepart)
+ {
+ /* Restore the auxiliary info from an empty variable
+ previously created for changed_variables, so it is
+ not lost. */
+ gcc_checking_assert (!VAR_LOC_1PAUX (var));
+ VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (old_var);
+ VAR_LOC_1PAUX (old_var) = NULL;
+ }
variable_htab_free (*slot);
}
+
if (set && var->n_var_parts == 0)
{
- variable empty_var;
+ onepart_enum_t onepart = var->onepart;
+ variable empty_var = NULL;
+ void **dslot = NULL;
- empty_var = (variable) pool_alloc (dv_pool (var->dv));
- empty_var->dv = var->dv;
- empty_var->refcount = 1;
- empty_var->n_var_parts = 0;
- empty_var->cur_loc_changed = true;
+ if (onepart == ONEPART_VALUE || onepart == ONEPART_DEXPR)
+ {
+ dslot = htab_find_slot_with_hash (dropped_values, var->dv,
+ dv_htab_hash (var->dv),
+ INSERT);
+ empty_var = (variable) *dslot;
+
+ if (empty_var)
+ {
+ gcc_checking_assert (!empty_var->in_changed_variables);
+ if (!VAR_LOC_1PAUX (var))
+ {
+ VAR_LOC_1PAUX (var) = VAR_LOC_1PAUX (empty_var);
+ VAR_LOC_1PAUX (empty_var) = NULL;
+ }
+ else
+ gcc_checking_assert (!VAR_LOC_1PAUX (empty_var));
+ }
+ }
+
+ if (!empty_var)
+ {
+ empty_var = (variable) pool_alloc (onepart_pool (onepart));
+ empty_var->dv = var->dv;
+ empty_var->refcount = 1;
+ empty_var->n_var_parts = 0;
+ empty_var->onepart = onepart;
+ if (dslot)
+ {
+ empty_var->refcount++;
+ *dslot = empty_var;
+ }
+ }
+ else
+ empty_var->refcount++;
empty_var->in_changed_variables = true;
*slot = empty_var;
+ if (onepart)
+ {
+ empty_var->var_part[0].loc_chain = NULL;
+ empty_var->var_part[0].cur_loc = NULL;
+ VAR_LOC_1PAUX (empty_var) = VAR_LOC_1PAUX (var);
+ VAR_LOC_1PAUX (var) = NULL;
+ }
goto drop_var;
}
else
{
+ if (var->onepart && !VAR_LOC_1PAUX (var))
+ recover_dropped_1paux (var);
var->refcount++;
var->in_changed_variables = true;
- /* If within processing one uop a variable is deleted
- and then readded, we need to assume it has changed. */
- if (old_cur_loc_changed)
- var->cur_loc_changed = true;
*slot = var;
}
}
@@ -6849,13 +7013,24 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset,
{
int pos, low, high;
+ if (var->onepart)
+ {
+ if (offset != 0)
+ return -1;
+
+ if (insertion_point)
+ *insertion_point = 0;
+
+ return var->n_var_parts - 1;
+ }
+
/* Find the location part. */
low = 0;
high = var->n_var_parts;
while (low != high)
{
pos = (low + high) / 2;
- if (var->var_part[pos].offset < offset)
+ if (VAR_PART_OFFSET (var, pos) < offset)
low = pos + 1;
else
high = pos;
@@ -6865,7 +7040,7 @@ find_variable_location_part (variable var, HOST_WIDE_INT offset,
if (insertion_point)
*insertion_point = pos;
- if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
+ if (pos < var->n_var_parts && VAR_PART_OFFSET (var, pos) == offset)
return pos;
return -1;
@@ -6880,26 +7055,34 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
location_chain node, next;
location_chain *nextp;
variable var;
- bool onepart = dv_onepart_p (dv);
-
- gcc_assert (offset == 0 || !onepart);
- gcc_assert (loc != dv_as_opaque (dv));
+ onepart_enum_t onepart;
var = (variable) *slot;
+ if (var)
+ onepart = var->onepart;
+ else
+ onepart = dv_onepart_p (dv);
+
+ gcc_checking_assert (offset == 0 || !onepart);
+ gcc_checking_assert (loc != dv_as_opaque (dv));
+
if (! flag_var_tracking_uninit)
initialized = VAR_INIT_STATUS_INITIALIZED;
if (!var)
{
/* Create new variable information. */
- var = (variable) pool_alloc (dv_pool (dv));
+ var = (variable) pool_alloc (onepart_pool (onepart));
var->dv = dv;
var->refcount = 1;
var->n_var_parts = 1;
- var->cur_loc_changed = false;
+ var->onepart = onepart;
var->in_changed_variables = false;
- var->var_part[0].offset = offset;
+ if (var->onepart)
+ VAR_LOC_1PAUX (var) = NULL;
+ else
+ VAR_PART_OFFSET (var, 0) = offset;
var->var_part[0].loc_chain = NULL;
var->var_part[0].cur_loc = NULL;
*slot = var;
@@ -7054,7 +7237,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
/* We track only variables whose size is <= MAX_VAR_PARTS bytes
thus there are at most MAX_VAR_PARTS different offsets. */
gcc_assert (var->n_var_parts < MAX_VAR_PARTS
- && (!var->n_var_parts || !dv_onepart_p (var->dv)));
+ && (!var->n_var_parts || !onepart));
/* We have to move the elements of array starting at index
inspos to the next position. */
@@ -7062,7 +7245,8 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
var->var_part[pos] = var->var_part[pos - 1];
var->n_var_parts++;
- var->var_part[pos].offset = offset;
+ gcc_checking_assert (!onepart);
+ VAR_PART_OFFSET (var, pos) = offset;
var->var_part[pos].loc_chain = NULL;
var->var_part[pos].cur_loc = NULL;
}
@@ -7083,10 +7267,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
if (node->set_src != NULL && set_src == NULL)
set_src = node->set_src;
if (var->var_part[pos].cur_loc == node->loc)
- {
- var->var_part[pos].cur_loc = NULL;
- var->cur_loc_changed = true;
- }
+ var->var_part[pos].cur_loc = NULL;
pool_free (loc_chain_pool, node);
*nextp = next;
break;
@@ -7106,9 +7287,6 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot,
node->next = *nextp;
*nextp = node;
- if (onepart && emit_notes)
- add_value_chains (var->dv, loc);
-
/* If no location was emitted do so. */
if (var->var_part[pos].cur_loc == NULL)
variable_was_changed (var, set);
@@ -7238,6 +7416,7 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
location_chain node, next;
location_chain *nextp;
bool changed;
+ rtx cur_loc;
if (shared_var_p (var, set->vars))
{
@@ -7258,6 +7437,11 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
}
}
+ if (pos == 0 && var->onepart && VAR_LOC_1PAUX (var))
+ cur_loc = VAR_LOC_FROM (var);
+ else
+ cur_loc = var->var_part[pos].cur_loc;
+
/* Delete the location part. */
changed = false;
nextp = &var->var_part[pos].loc_chain;
@@ -7268,16 +7452,15 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
&& REGNO (node->loc) == REGNO (loc))
|| rtx_equal_p (node->loc, loc))
{
- if (emit_notes && pos == 0 && dv_onepart_p (var->dv))
- remove_value_chains (var->dv, node->loc);
/* If we have deleted the location which was last emitted
we have to emit new location so add the variable to set
of changed variables. */
- if (var->var_part[pos].cur_loc == node->loc)
+ if (cur_loc == node->loc)
{
changed = true;
var->var_part[pos].cur_loc = NULL;
- var->cur_loc_changed = true;
+ if (pos == 0 && var->onepart && VAR_LOC_1PAUX (var))
+ VAR_LOC_FROM (var) = NULL;
}
pool_free (loc_chain_pool, node);
*nextp = next;
@@ -7291,8 +7474,6 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot,
{
changed = true;
var->n_var_parts--;
- if (emit_notes)
- var->cur_loc_changed = true;
while (pos < var->n_var_parts)
{
var->var_part[pos] = var->var_part[pos + 1];
@@ -7321,6 +7502,12 @@ delete_variable_part (dataflow_set *set, rtx loc, decl_or_value dv,
delete_slot_part (set, loc, slot, offset);
}
+DEF_VEC_P (variable);
+DEF_VEC_ALLOC_P (variable, heap);
+
+DEF_VEC_ALLOC_P_STACK (rtx);
+#define VEC_rtx_stack_alloc(alloc) VEC_stack_alloc (rtx, alloc)
+
/* Structure for passing some other parameters to function
vt_expand_loc_callback. */
struct expand_loc_callback_data
@@ -7328,56 +7515,370 @@ struct expand_loc_callback_data
/* The variables and values active at this point. */
htab_t vars;
- /* True in vt_expand_loc_dummy calls, no rtl should be allocated.
- Non-NULL should be returned if vt_expand_loc would return
- non-NULL in that case, NULL otherwise. cur_loc_changed should be
- computed and cur_loc recomputed when possible (but just once
- per emit_notes_for_changes call). */
- bool dummy;
-
- /* True if expansion of subexpressions had to recompute some
- VALUE/DEBUG_EXPR_DECL's cur_loc or used a VALUE/DEBUG_EXPR_DECL
- whose cur_loc has been already recomputed during current
- emit_notes_for_changes call. */
- bool cur_loc_changed;
-
- /* True if cur_loc should be ignored and any possible location
- returned. */
- bool ignore_cur_loc;
+ /* Stack of values and debug_exprs under expansion, and their
+ children. */
+ VEC (rtx, stack) *expanding;
+
+ /* Stack of values and debug_exprs whose expansion hit recursion
+ cycles. They will have VALUE_RECURSED_INTO marked when added to
+ this list. This flag will be cleared if any of its dependencies
+ resolves to a valid location. So, if the flag remains set at the
+ end of the search, we know no valid location for this one can
+ possibly exist. */
+ VEC (rtx, stack) *pending;
+
+ /* The maximum depth among the sub-expressions under expansion.
+ Zero indicates no expansion so far. */
+ int depth;
};
+/* Allocate the one-part auxiliary data structure for VAR, with enough
+ room for COUNT dependencies. */
+
+static void
+loc_exp_dep_alloc (variable var, int count)
+{
+ size_t allocsize;
+
+ gcc_checking_assert (var->onepart);
+
+ /* We can be called with COUNT == 0 to allocate the data structure
+ without any dependencies, e.g. for the backlinks only. However,
+ if we are specifying a COUNT, then the dependency list must have
+ been emptied before. It would be possible to adjust pointers or
+ force it empty here, but this is better done at an earlier point
+ in the algorithm, so we instead leave an assertion to catch
+ errors. */
+ gcc_checking_assert (!count
+ || VEC_empty (loc_exp_dep, VAR_LOC_DEP_VEC (var)));
+
+ if (VAR_LOC_1PAUX (var)
+ && VEC_space (loc_exp_dep, VAR_LOC_DEP_VEC (var), count))
+ return;
+
+ allocsize = offsetof (struct onepart_aux, deps)
+ + VEC_embedded_size (loc_exp_dep, count);
+
+ if (VAR_LOC_1PAUX (var))
+ {
+ VAR_LOC_1PAUX (var) = XRESIZEVAR (struct onepart_aux,
+ VAR_LOC_1PAUX (var), allocsize);
+ /* If the reallocation moves the onepaux structure, the
+ back-pointer to BACKLINKS in the first list member will still
+ point to its old location. Adjust it. */
+ if (VAR_LOC_DEP_LST (var))
+ VAR_LOC_DEP_LST (var)->pprev = VAR_LOC_DEP_LSTP (var);
+ }
+ else
+ {
+ VAR_LOC_1PAUX (var) = XNEWVAR (struct onepart_aux, allocsize);
+ *VAR_LOC_DEP_LSTP (var) = NULL;
+ VAR_LOC_FROM (var) = NULL;
+ VAR_LOC_DEPTH (var) = 0;
+ }
+ VEC_embedded_init (loc_exp_dep, VAR_LOC_DEP_VEC (var), count);
+}
+
+/* Remove all entries from the vector of active dependencies of VAR,
+ removing them from the back-links lists too. */
+
+static void
+loc_exp_dep_clear (variable var)
+{
+ while (!VEC_empty (loc_exp_dep, VAR_LOC_DEP_VEC (var)))
+ {
+ loc_exp_dep *led = VEC_last (loc_exp_dep, VAR_LOC_DEP_VEC (var));
+ if (led->next)
+ led->next->pprev = led->pprev;
+ if (led->pprev)
+ *led->pprev = led->next;
+ VEC_pop (loc_exp_dep, VAR_LOC_DEP_VEC (var));
+ }
+}
+
+/* Insert an active dependency from VAR on X to the vector of
+ dependencies, and add the corresponding back-link to X's list of
+ back-links in VARS. */
+
+static void
+loc_exp_insert_dep (variable var, rtx x, htab_t vars)
+{
+ decl_or_value dv;
+ variable xvar;
+ loc_exp_dep *led;
+
+ dv = dv_from_rtx (x);
+
+ /* ??? Build a vector of variables parallel to EXPANDING, to avoid
+ an additional look up? */
+ xvar = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
+
+ if (!xvar)
+ {
+ xvar = variable_from_dropped (dv, NO_INSERT);
+ gcc_checking_assert (xvar);
+ }
+
+ /* No point in adding the same backlink more than once. This may
+ arise if say the same value appears in two complex expressions in
+ the same loc_list, or even more than once in a single
+ expression. */
+ if (VAR_LOC_DEP_LST (xvar) && VAR_LOC_DEP_LST (xvar)->dv == var->dv)
+ return;
+
+ VEC_quick_push (loc_exp_dep, VAR_LOC_DEP_VEC (var), NULL);
+ led = VEC_last (loc_exp_dep, VAR_LOC_DEP_VEC (var));
+ led->dv = var->dv;
+ led->value = x;
+
+ loc_exp_dep_alloc (xvar, 0);
+ led->pprev = VAR_LOC_DEP_LSTP (xvar);
+ led->next = *led->pprev;
+ if (led->next)
+ led->next->pprev = &led->next;
+ *led->pprev = led;
+}
+
+/* Create active dependencies of VAR on COUNT values starting at
+ VALUE, and corresponding back-links to the entries in VARS. Return
+ true if we found any pending-recursion results. */
+
+static bool
+loc_exp_dep_set (variable var, rtx result, rtx *value, int count, htab_t vars)
+{
+ bool pending_recursion = false;
+
+ gcc_checking_assert (VEC_empty (loc_exp_dep, VAR_LOC_DEP_VEC (var)));
+
+ /* Set up all dependencies from last_child (as set up at the end of
+ the loop above) to the end. */
+ loc_exp_dep_alloc (var, count);
+
+ while (count--)
+ {
+ rtx x = *value++;
+
+ if (!pending_recursion)
+ pending_recursion = !result && VALUE_RECURSED_INTO (x);
+
+ loc_exp_insert_dep (var, x, vars);
+ }
+
+ return pending_recursion;
+}
+
+/* Notify the back-links of IVAR that are pending recursion that we
+ have found a non-NIL value for it, so they are cleared for another
+ attempt to compute a current location. */
+
+static void
+notify_dependents_of_resolved_value (variable ivar, htab_t vars)
+{
+ loc_exp_dep *led, *next;
+
+ for (led = VAR_LOC_DEP_LST (ivar); led; led = next)
+ {
+ decl_or_value dv = led->dv;
+ variable var;
+
+ next = led->next;
+
+ if (dv_is_value_p (dv))
+ {
+ rtx value = dv_as_value (dv);
+
+ /* If we have already resolved it, leave it alone. */
+ if (!VALUE_RECURSED_INTO (value))
+ continue;
+
+ /* Check that VALUE_RECURSED_INTO, true from the test above,
+ implies NO_LOC_P. */
+ gcc_checking_assert (NO_LOC_P (value));
+
+ /* We won't notify variables that are being expanded,
+ because their dependency list is cleared before
+ recursing. */
+ VALUE_RECURSED_INTO (value) = false;
+
+ gcc_checking_assert (dv_changed_p (dv));
+ }
+ else if (!dv_changed_p (dv))
+ continue;
+
+ var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
+
+ if (!var)
+ var = variable_from_dropped (dv, NO_INSERT);
+
+ if (var)
+ notify_dependents_of_resolved_value (var, vars);
+
+ if (next)
+ next->pprev = led->pprev;
+ if (led->pprev)
+ *led->pprev = next;
+ led->next = NULL;
+ led->pprev = NULL;
+ }
+}
+
+static rtx vt_expand_loc_callback (rtx x, bitmap regs,
+ int max_depth, void *data);
+
+/* Return the combined depth, when one sub-expression evaluated to
+ BEST_DEPTH and the previous known depth was SAVED_DEPTH. */
+
+static inline int
+update_depth (int saved_depth, int best_depth)
+{
+ /* If we didn't find anything, stick with what we had. */
+ if (!best_depth)
+ return saved_depth;
+
+ /* If we found hadn't found anything, use the depth of the current
+ expression. Do NOT add one extra level, we want to compute the
+ maximum depth among sub-expressions. We'll increment it later,
+ if appropriate. */
+ if (!saved_depth)
+ return best_depth;
+
+ if (saved_depth < best_depth)
+ return best_depth;
+ else
+ return saved_depth;
+}
+
+/* Expand VAR to a location RTX, updating its cur_loc. Use REGS and
+ DATA for cselib expand callback. If PENDRECP is given, indicate in
+ it whether any sub-expression couldn't be fully evaluated because
+ it is pending recursion resolution. */
+
+static inline rtx
+vt_expand_var_loc_chain (variable var, bitmap regs, void *data, bool *pendrecp)
+{
+ struct expand_loc_callback_data *elcd
+ = (struct expand_loc_callback_data *) data;
+ location_chain loc, next;
+ rtx result = NULL;
+ int first_child, result_first_child, last_child;
+ bool pending_recursion;
+ rtx loc_from = NULL;
+ struct elt_loc_list *cloc = NULL;
+ int depth = 0, saved_depth = elcd->depth;
+
+ /* Clear all backlinks pointing at this, so that we're not notified
+ while we're active. */
+ loc_exp_dep_clear (var);
+
+ if (var->onepart == ONEPART_VALUE)
+ {
+ cselib_val *val = CSELIB_VAL_PTR (dv_as_value (var->dv));
+
+ gcc_checking_assert (cselib_preserved_value_p (val));
+
+ cloc = val->locs;
+ }
+
+ first_child = result_first_child = last_child
+ = VEC_length (rtx, elcd->expanding);
+
+ /* Attempt to expand each available location in turn. */
+ for (next = loc = var->n_var_parts ? var->var_part[0].loc_chain : NULL;
+ loc || cloc; loc = next)
+ {
+ result_first_child = last_child;
+
+ if (!loc || (GET_CODE (loc->loc) == ENTRY_VALUE && cloc))
+ {
+ loc_from = cloc->loc;
+ next = loc;
+ cloc = cloc->next;
+ if (unsuitable_loc (loc_from))
+ continue;
+ }
+ else
+ {
+ loc_from = loc->loc;
+ next = loc->next;
+ }
+
+ gcc_checking_assert (!unsuitable_loc (loc_from));
+
+ elcd->depth = 0;
+ result = cselib_expand_value_rtx_cb (loc_from, regs, EXPR_DEPTH,
+ vt_expand_loc_callback, data);
+ last_child = VEC_length (rtx, elcd->expanding);
+
+ if (result)
+ {
+ depth = elcd->depth;
+
+ gcc_checking_assert (depth || result_first_child == last_child);
+
+ if (last_child - result_first_child != 1)
+ depth++;
+
+ if (depth <= EXPR_USE_DEPTH)
+ break;
+
+ result = NULL;
+ }
+
+ /* Set it up in case we leave the loop. */
+ depth = 0;
+ loc_from = NULL;
+ result_first_child = first_child;
+ }
+
+ /* Register all encountered dependencies as active. */
+ pending_recursion = loc_exp_dep_set
+ (var, result, VEC_address (rtx, elcd->expanding) + result_first_child,
+ last_child - result_first_child, elcd->vars);
+
+ VEC_truncate (rtx, elcd->expanding, first_child);
+
+ /* Record where the expansion came from. */
+ gcc_checking_assert (!result || !pending_recursion);
+ VAR_LOC_FROM (var) = loc_from;
+ VAR_LOC_DEPTH (var) = depth;
+
+ gcc_checking_assert (!depth == !result);
+
+ elcd->depth = update_depth (saved_depth, depth);
+
+ /* Indicate whether any of the dependencies are pending recursion
+ resolution. */
+ if (pendrecp)
+ *pendrecp = pending_recursion;
+
+ if (!pendrecp || !pending_recursion)
+ var->var_part[0].cur_loc = result;
+
+ return result;
+}
+
/* Callback for cselib_expand_value, that looks for expressions
holding the value in the var-tracking hash tables. Return X for
standard processing, anything else is to be used as-is. */
static rtx
-vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
+vt_expand_loc_callback (rtx x, bitmap regs,
+ int max_depth ATTRIBUTE_UNUSED,
+ void *data)
{
struct expand_loc_callback_data *elcd
= (struct expand_loc_callback_data *) data;
- bool dummy = elcd->dummy;
- bool cur_loc_changed = elcd->cur_loc_changed;
- rtx cur_loc;
decl_or_value dv;
variable var;
- location_chain loc;
- rtx result, subreg, xret;
+ rtx result, subreg;
+ bool pending_recursion = false;
+ bool from_empty = false;
switch (GET_CODE (x))
{
case SUBREG:
- if (dummy)
- {
- if (cselib_dummy_expand_value_rtx_cb (SUBREG_REG (x), regs,
- max_depth - 1,
- vt_expand_loc_callback, data))
- return pc_rtx;
- else
- return NULL;
- }
-
subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs,
- max_depth - 1,
+ EXPR_DEPTH,
vt_expand_loc_callback, data);
if (!subreg)
@@ -7395,148 +7896,172 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
return result;
case DEBUG_EXPR:
- dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
- xret = NULL;
- break;
-
case VALUE:
- dv = dv_from_value (x);
- xret = x;
+ dv = dv_from_rtx (x);
break;
default:
return x;
}
- if (VALUE_RECURSED_INTO (x))
+ VEC_safe_push (rtx, stack, elcd->expanding, x);
+
+ /* Check that VALUE_RECURSED_INTO implies NO_LOC_P. */
+ gcc_checking_assert (!VALUE_RECURSED_INTO (x) || NO_LOC_P (x));
+
+ if (NO_LOC_P (x))
return NULL;
var = (variable) htab_find_with_hash (elcd->vars, dv, dv_htab_hash (dv));
if (!var)
{
- if (dummy && dv_changed_p (dv))
- elcd->cur_loc_changed = true;
- return xret;
+ from_empty = true;
+ var = variable_from_dropped (dv, INSERT);
}
- if (var->n_var_parts == 0)
+ gcc_checking_assert (var);
+
+ if (!dv_changed_p (dv))
{
- if (dummy)
- elcd->cur_loc_changed = true;
- return xret;
- }
+ gcc_checking_assert (!NO_LOC_P (x));
+ gcc_checking_assert (var->var_part[0].cur_loc);
+ gcc_checking_assert (VAR_LOC_1PAUX (var));
+ gcc_checking_assert (VAR_LOC_1PAUX (var)->depth);
- gcc_assert (var->n_var_parts == 1);
+ elcd->depth = update_depth (elcd->depth, VAR_LOC_1PAUX (var)->depth);
+
+ return var->var_part[0].cur_loc;
+ }
VALUE_RECURSED_INTO (x) = true;
- result = NULL;
+ /* This is tentative, but it makes some tests simpler. */
+ NO_LOC_P (x) = true;
+
+ gcc_checking_assert (var->n_var_parts == 1 || from_empty);
+
+ result = vt_expand_var_loc_chain (var, regs, data, &pending_recursion);
- if (var->var_part[0].cur_loc && !elcd->ignore_cur_loc)
+ if (pending_recursion)
{
- if (dummy)
- {
- if (cselib_dummy_expand_value_rtx_cb (var->var_part[0].cur_loc, regs,
- max_depth,
- vt_expand_loc_callback, data))
- result = pc_rtx;
- }
- else
- result = cselib_expand_value_rtx_cb (var->var_part[0].cur_loc, regs,
- max_depth,
- vt_expand_loc_callback, data);
- if (result)
- set_dv_changed (dv, false);
- cur_loc = var->var_part[0].cur_loc;
+ gcc_checking_assert (!result);
+ VEC_safe_push (rtx, stack, elcd->pending, x);
}
else
- cur_loc = NULL_RTX;
- if (!result && (dv_changed_p (dv) || elcd->ignore_cur_loc))
{
- if (!elcd->ignore_cur_loc)
- set_dv_changed (dv, false);
- for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
- if (loc->loc == cur_loc)
- continue;
- else if (dummy)
- {
- elcd->cur_loc_changed = cur_loc_changed;
- if (cselib_dummy_expand_value_rtx_cb (loc->loc, regs, max_depth,
- vt_expand_loc_callback,
- data))
- {
- result = pc_rtx;
- break;
- }
- }
- else
- {
- result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth,
- vt_expand_loc_callback, data);
- if (result)
- break;
- }
- if (dummy && (result || var->var_part[0].cur_loc))
- var->cur_loc_changed = true;
- if (!elcd->ignore_cur_loc)
- var->var_part[0].cur_loc = loc ? loc->loc : NULL_RTX;
- }
- if (dummy)
- {
- if (var->cur_loc_changed)
- elcd->cur_loc_changed = true;
- else if (!result && var->var_part[0].cur_loc == NULL_RTX)
- elcd->cur_loc_changed = cur_loc_changed;
+ NO_LOC_P (x) = !result;
+ VALUE_RECURSED_INTO (x) = false;
+ set_dv_changed (dv, false);
+
+ if (result)
+ notify_dependents_of_resolved_value (var, elcd->vars);
}
- VALUE_RECURSED_INTO (x) = false;
- if (result)
- return result;
- else
- return xret;
+ return result;
}
-/* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
- tables. */
+/* While expanding variables, we may encounter recursion cycles
+ because of mutual (possibly indirect) dependencies between two
+ particular variables (or values), say A and B. If we're trying to
+ expand A when we get to B, which in turn attempts to expand A, if
+ we can't find any other expansion for B, we'll add B to this
+ pending-recursion stack, and tentatively return NULL for its
+ location. This tentative value will be used for any other
+ occurrences of B, unless A gets some other location, in which case
+ it will notify B that it is worth another try at computing a
+ location for it, and it will use the location computed for A then.
+ At the end of the expansion, the tentative NULL locations become
+ final for all members of PENDING that didn't get a notification.
+ This function performs this finalization of NULL locations. */
+
+static void
+resolve_expansions_pending_recursion (VEC (rtx, stack) *pending)
+{
+ while (!VEC_empty (rtx, pending))
+ {
+ rtx x = VEC_pop (rtx, pending);
+ decl_or_value dv;
+
+ if (!VALUE_RECURSED_INTO (x))
+ continue;
+
+ gcc_checking_assert (NO_LOC_P (x));
+ VALUE_RECURSED_INTO (x) = false;
+ dv = dv_from_rtx (x);
+ gcc_checking_assert (dv_changed_p (dv));
+ set_dv_changed (dv, false);
+ }
+}
+
+/* Initialize expand_loc_callback_data D with variable hash table V.
+ It must be a macro because of alloca (VEC stack). */
+#define INIT_ELCD(d, v) \
+ do \
+ { \
+ (d).vars = (v); \
+ (d).expanding = VEC_alloc (rtx, stack, 4); \
+ (d).pending = VEC_alloc (rtx, stack, 4); \
+ (d).depth = 0; \
+ } \
+ while (0)
+/* Finalize expand_loc_callback_data D, resolved to location L. */
+#define FINI_ELCD(d, l) \
+ do \
+ { \
+ resolve_expansions_pending_recursion ((d).pending); \
+ VEC_free (rtx, stack, (d).pending); \
+ VEC_free (rtx, stack, (d).expanding); \
+ \
+ if ((l) && MEM_P (l)) \
+ (l) = targetm.delegitimize_address (l); \
+ } \
+ while (0)
+
+/* Expand VALUEs and DEBUG_EXPRs in LOC to a location, using the
+ equivalences in VARS, updating their CUR_LOCs in the process. */
static rtx
-vt_expand_loc (rtx loc, htab_t vars, bool ignore_cur_loc)
+vt_expand_loc (rtx loc, htab_t vars)
{
struct expand_loc_callback_data data;
+ rtx result;
if (!MAY_HAVE_DEBUG_INSNS)
return loc;
- data.vars = vars;
- data.dummy = false;
- data.cur_loc_changed = false;
- data.ignore_cur_loc = ignore_cur_loc;
- loc = cselib_expand_value_rtx_cb (loc, scratch_regs, EXPR_DEPTH,
- vt_expand_loc_callback, &data);
+ INIT_ELCD (data, vars);
- if (loc && MEM_P (loc))
- loc = targetm.delegitimize_address (loc);
- return loc;
+ result = cselib_expand_value_rtx_cb (loc, scratch_regs, EXPR_DEPTH,
+ vt_expand_loc_callback, &data);
+
+ FINI_ELCD (data, result);
+
+ return result;
}
-/* Like vt_expand_loc, but only return true/false (whether vt_expand_loc
- would succeed or not, without actually allocating new rtxes. */
+/* Expand the one-part VARiable to a location, using the equivalences
+ in VARS, updating their CUR_LOCs in the process. */
-static bool
-vt_expand_loc_dummy (rtx loc, htab_t vars, bool *pcur_loc_changed)
+static rtx
+vt_expand_1pvar (variable var, htab_t vars)
{
struct expand_loc_callback_data data;
- bool ret;
-
- gcc_assert (MAY_HAVE_DEBUG_INSNS);
- data.vars = vars;
- data.dummy = true;
- data.cur_loc_changed = false;
- data.ignore_cur_loc = false;
- ret = cselib_dummy_expand_value_rtx_cb (loc, scratch_regs, EXPR_DEPTH,
- vt_expand_loc_callback, &data);
- *pcur_loc_changed = data.cur_loc_changed;
- return ret;
+ rtx loc;
+
+ gcc_checking_assert (var->onepart && var->n_var_parts == 1);
+
+ if (!dv_changed_p (var->dv))
+ return var->var_part[0].cur_loc;
+
+ INIT_ELCD (data, vars);
+
+ loc = vt_expand_var_loc_chain (var, scratch_regs, &data, NULL);
+
+ gcc_checking_assert (VEC_empty (rtx, data.expanding));
+
+ FINI_ELCD (data, loc);
+
+ return loc;
}
/* Emit the NOTE_INSN_VAR_LOCATION for variable *VARP. DATA contains
@@ -7561,49 +8086,57 @@ emit_note_insn_var_location (void **varp, void *data)
tree decl;
location_chain lc;
- if (dv_is_value_p (var->dv))
- goto value_or_debug_decl;
+ gcc_checking_assert (var->onepart == NOT_ONEPART
+ || var->onepart == ONEPART_VDECL);
decl = dv_as_decl (var->dv);
- if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
- goto value_or_debug_decl;
-
complete = true;
last_limit = 0;
n_var_parts = 0;
- if (!MAY_HAVE_DEBUG_INSNS)
- {
- for (i = 0; i < var->n_var_parts; i++)
- if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain)
- {
- var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
- var->cur_loc_changed = true;
- }
- if (var->n_var_parts == 0)
- var->cur_loc_changed = true;
- }
- if (!var->cur_loc_changed)
- goto clear;
+ if (!var->onepart)
+ for (i = 0; i < var->n_var_parts; i++)
+ if (var->var_part[i].cur_loc == NULL && var->var_part[i].loc_chain)
+ var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
for (i = 0; i < var->n_var_parts; i++)
{
enum machine_mode mode, wider_mode;
rtx loc2;
+ HOST_WIDE_INT offset;
- if (last_limit < var->var_part[i].offset)
+ if (i == 0 && var->onepart)
{
- complete = false;
- break;
+ gcc_checking_assert (var->n_var_parts == 1);
+ offset = 0;
+ initialized = VAR_INIT_STATUS_INITIALIZED;
+ loc2 = vt_expand_1pvar (var, vars);
}
- else if (last_limit > var->var_part[i].offset)
- continue;
- offsets[n_var_parts] = var->var_part[i].offset;
- if (!var->var_part[i].cur_loc)
+ else
{
- complete = false;
- continue;
+ if (last_limit < VAR_PART_OFFSET (var, i))
+ {
+ complete = false;
+ break;
+ }
+ else if (last_limit > VAR_PART_OFFSET (var, i))
+ continue;
+ offset = VAR_PART_OFFSET (var, i);
+ if (!var->var_part[i].cur_loc)
+ {
+ complete = false;
+ continue;
+ }
+ for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
+ if (var->var_part[i].cur_loc == lc->loc)
+ {
+ initialized = lc->init;
+ break;
+ }
+ gcc_assert (lc);
+ loc2 = var->var_part[i].cur_loc;
}
- loc2 = vt_expand_loc (var->var_part[i].cur_loc, vars, false);
+
+ offsets[n_var_parts] = offset;
if (!loc2)
{
complete = false;
@@ -7611,29 +8144,22 @@ emit_note_insn_var_location (void **varp, void *data)
}
loc[n_var_parts] = loc2;
mode = GET_MODE (var->var_part[i].cur_loc);
- if (mode == VOIDmode && dv_onepart_p (var->dv))
+ if (mode == VOIDmode && var->onepart)
mode = DECL_MODE (decl);
- for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
- if (var->var_part[i].cur_loc == lc->loc)
- {
- initialized = lc->init;
- break;
- }
- gcc_assert (lc);
last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
/* Attempt to merge adjacent registers or memory. */
wider_mode = GET_MODE_WIDER_MODE (mode);
for (j = i + 1; j < var->n_var_parts; j++)
- if (last_limit <= var->var_part[j].offset)
+ if (last_limit <= VAR_PART_OFFSET (var, j))
break;
if (j < var->n_var_parts
&& wider_mode != VOIDmode
&& var->var_part[j].cur_loc
&& mode == GET_MODE (var->var_part[j].cur_loc)
&& (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
- && last_limit == var->var_part[j].offset
- && (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars, false))
+ && last_limit == (var->onepart ? 0 : VAR_PART_OFFSET (var, j))
+ && (loc2 = vt_expand_loc (var->var_part[j].cur_loc, vars))
&& GET_CODE (loc[n_var_parts]) == GET_CODE (loc2))
{
rtx new_loc = NULL;
@@ -7746,152 +8272,152 @@ emit_note_insn_var_location (void **varp, void *data)
}
NOTE_VAR_LOCATION (note) = note_vl;
- clear:
set_dv_changed (var->dv, false);
- var->cur_loc_changed = false;
gcc_assert (var->in_changed_variables);
var->in_changed_variables = false;
htab_clear_slot (changed_variables, varp);
/* Continue traversing the hash table. */
return 1;
-
- value_or_debug_decl:
- if (dv_changed_p (var->dv) && var->n_var_parts)
- {
- location_chain lc;
- bool cur_loc_changed;
-
- if (var->var_part[0].cur_loc
- && vt_expand_loc_dummy (var->var_part[0].cur_loc, vars,
- &cur_loc_changed))
- goto clear;
- for (lc = var->var_part[0].loc_chain; lc; lc = lc->next)
- if (lc->loc != var->var_part[0].cur_loc
- && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed))
- break;
- var->var_part[0].cur_loc = lc ? lc->loc : NULL_RTX;
- }
- goto clear;
}
-DEF_VEC_P (variable);
-DEF_VEC_ALLOC_P (variable, heap);
-
-/* Stack of variable_def pointers that need processing with
- check_changed_vars_2. */
-
-static VEC (variable, heap) *changed_variables_stack;
+/* While traversing changed_variables, push onto DATA (a stack of RTX
+ values) entries that aren't user variables. */
-/* VALUEs with no variables that need set_dv_changed (val, false)
- called before check_changed_vars_3. */
+static int
+values_to_stack (void **slot, void *data)
+{
+ VEC (rtx, stack) **changed_values_stack = (VEC (rtx, stack) **)data;
+ variable var = (variable) *slot;
-static VEC (rtx, heap) *changed_values_stack;
+ if (var->onepart == ONEPART_VALUE)
+ VEC_safe_push (rtx, stack, *changed_values_stack, dv_as_value (var->dv));
+ else if (var->onepart == ONEPART_DEXPR)
+ VEC_safe_push (rtx, stack, *changed_values_stack,
+ DECL_RTL_KNOWN_SET (dv_as_decl (var->dv)));
-/* Helper function for check_changed_vars_1 and check_changed_vars_2. */
+ return 1;
+}
+/* Remove from changed_variables the entry whose DV corresponds to
+ value or debug_expr VAL. */
static void
-check_changed_vars_0 (decl_or_value dv, htab_t htab)
+remove_value_from_changed_variables (rtx val)
{
- value_chain vc
- = (value_chain) htab_find_with_hash (value_chains, dv, dv_htab_hash (dv));
+ decl_or_value dv = dv_from_rtx (val);
+ void **slot;
+ variable var;
- if (vc == NULL)
- return;
- for (vc = vc->next; vc; vc = vc->next)
- if (!dv_changed_p (vc->dv))
- {
- variable vcvar
- = (variable) htab_find_with_hash (htab, vc->dv,
- dv_htab_hash (vc->dv));
- if (vcvar)
- {
- set_dv_changed (vc->dv, true);
- VEC_safe_push (variable, heap, changed_variables_stack, vcvar);
- }
- else if (dv_is_value_p (vc->dv))
- {
- set_dv_changed (vc->dv, true);
- VEC_safe_push (rtx, heap, changed_values_stack,
- dv_as_value (vc->dv));
- check_changed_vars_0 (vc->dv, htab);
- }
- }
+ slot = htab_find_slot_with_hash (changed_variables,
+ dv, dv_htab_hash (dv), NO_INSERT);
+ var = (variable) *slot;
+ var->in_changed_variables = false;
+ htab_clear_slot (changed_variables, slot);
}
-/* Populate changed_variables_stack with variable_def pointers
- that need variable_was_changed called on them. */
+/* If VAL (a value or debug_expr) has backlinks to variables actively
+ dependent on it in HTAB or in CHANGED_VARIABLES, mark them as
+ changed, adding to CHANGED_VALUES_STACK any dependencies that may
+ have dependencies of their own to notify. */
-static int
-check_changed_vars_1 (void **slot, void *data)
+static void
+notify_dependents_of_changed_value (rtx val, htab_t htab,
+ VEC (rtx, stack) **changed_values_stack)
{
- variable var = (variable) *slot;
- htab_t htab = (htab_t) data;
+ void **slot;
+ variable var;
+ loc_exp_dep *led;
+ decl_or_value dv = dv_from_rtx (val);
- if (dv_is_value_p (var->dv)
- || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
- check_changed_vars_0 (var->dv, htab);
- return 1;
-}
+ slot = htab_find_slot_with_hash (changed_variables,
+ dv, dv_htab_hash (dv), NO_INSERT);
+ if (!slot)
+ slot = htab_find_slot_with_hash (htab,
+ dv, dv_htab_hash (dv), NO_INSERT);
+ if (!slot)
+ slot = htab_find_slot_with_hash (dropped_values,
+ dv, dv_htab_hash (dv), NO_INSERT);
+ var = (variable) *slot;
-/* Add VAR to changed_variables and also for VALUEs add recursively
- all DVs that aren't in changed_variables yet but reference the
- VALUE from its loc_chain. */
+ while ((led = VAR_LOC_DEP_LST (var)))
+ {
+ decl_or_value ldv = led->dv;
+ void **islot;
+ variable ivar;
-static void
-check_changed_vars_2 (variable var, htab_t htab)
-{
- variable_was_changed (var, NULL);
- if (dv_is_value_p (var->dv)
- || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
- check_changed_vars_0 (var->dv, htab);
+ /* Deactivate and remove the backlink, as it was “used upâ€. It
+ makes no sense to attempt to notify the same entity again:
+ either it will be recomputed and re-register an active
+ dependency, or it will still have the changed mark. */
+ if (led->next)
+ led->next->pprev = led->pprev;
+ if (led->pprev)
+ *led->pprev = led->next;
+ led->next = NULL;
+ led->pprev = NULL;
+
+ if (dv_changed_p (ldv))
+ continue;
+
+ switch (dv_onepart_p (ldv))
+ {
+ case ONEPART_VALUE:
+ case ONEPART_DEXPR:
+ set_dv_changed (ldv, true);
+ VEC_safe_push (rtx, stack, *changed_values_stack, dv_as_rtx (ldv));
+ break;
+
+ default:
+ islot = htab_find_slot_with_hash (htab, ldv, dv_htab_hash (ldv),
+ NO_INSERT);
+ ivar = (variable) *islot;
+ gcc_checking_assert (!VAR_LOC_DEP_LST (ivar));
+ variable_was_changed (ivar, NULL);
+ break;
+ }
+ }
}
-/* For each changed decl (except DEBUG_EXPR_DECLs) recompute
- cur_loc if needed (and cur_loc of all VALUEs and DEBUG_EXPR_DECLs
- it needs and are also in changed variables) and track whether
- cur_loc (or anything it uses to compute location) had to change
- during the current emit_notes_for_changes call. */
+/* Take out of changed_variables any entries that don't refer to use
+ variables. Back-propagate change notifications from values and
+ debug_exprs to their active dependencies in HTAB or in
+ CHANGED_VARIABLES. */
-static int
-check_changed_vars_3 (void **slot, void *data)
+static void
+process_changed_values (htab_t htab)
{
- variable var = (variable) *slot;
- htab_t vars = (htab_t) data;
- int i;
- location_chain lc;
- bool cur_loc_changed;
+ int i, n;
+ rtx val;
+ VEC (rtx, stack) *changed_values_stack = VEC_alloc (rtx, stack, 20);
- if (dv_is_value_p (var->dv)
- || TREE_CODE (dv_as_decl (var->dv)) == DEBUG_EXPR_DECL)
- return 1;
+ /* Move values from changed_variables to changed_values_stack. */
+ htab_traverse (changed_variables, values_to_stack, &changed_values_stack);
- for (i = 0; i < var->n_var_parts; i++)
+ /* Back-propagate change notifications in values while popping
+ them from the stack. */
+ for (n = i = VEC_length (rtx, changed_values_stack);
+ i > 0; i = VEC_length (rtx, changed_values_stack))
{
- if (var->var_part[i].cur_loc
- && vt_expand_loc_dummy (var->var_part[i].cur_loc, vars,
- &cur_loc_changed))
+ val = VEC_pop (rtx, changed_values_stack);
+ notify_dependents_of_changed_value (val, htab, &changed_values_stack);
+
+ /* This condition will hold when visiting each of the entries
+ originally in changed_variables. We can't remove them
+ earlier because this could drop the backlinks before we got a
+ chance to use them. */
+ if (i == n)
{
- if (cur_loc_changed)
- var->cur_loc_changed = true;
- continue;
+ remove_value_from_changed_variables (val);
+ n--;
}
- for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
- if (lc->loc != var->var_part[i].cur_loc
- && vt_expand_loc_dummy (lc->loc, vars, &cur_loc_changed))
- break;
- if (lc || var->var_part[i].cur_loc)
- var->cur_loc_changed = true;
- var->var_part[i].cur_loc = lc ? lc->loc : NULL_RTX;
}
- if (var->n_var_parts == 0)
- var->cur_loc_changed = true;
- return 1;
+
+ VEC_free (rtx, stack, changed_values_stack);
}
/* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain
- CHANGED_VARIABLES and delete this chain. WHERE specifies whether the notes
- shall be emitted before of after instruction INSN. */
+ CHANGED_VARIABLES and delete this chain. WHERE specifies whether
+ the notes shall be emitted before of after instruction INSN. */
static void
emit_notes_for_changes (rtx insn, enum emit_note_where where,
@@ -7904,19 +8430,7 @@ emit_notes_for_changes (rtx insn, enum emit_note_where where,
return;
if (MAY_HAVE_DEBUG_INSNS)
- {
- /* Unfortunately this has to be done in two steps, because
- we can't traverse a hashtab into which we are inserting
- through variable_was_changed. */
- htab_traverse (changed_variables, check_changed_vars_1, htab);
- while (VEC_length (variable, changed_variables_stack) > 0)
- check_changed_vars_2 (VEC_pop (variable, changed_variables_stack),
- htab);
- while (VEC_length (rtx, changed_values_stack) > 0)
- set_dv_changed (dv_from_value (VEC_pop (rtx, changed_values_stack)),
- false);
- htab_traverse (changed_variables, check_changed_vars_3, htab);
- }
+ process_changed_values (htab);
data.insn = insn;
data.where = where;
@@ -7941,78 +8455,59 @@ emit_notes_for_differences_1 (void **slot, void *data)
if (!new_var)
{
/* Variable has disappeared. */
- variable empty_var;
-
- empty_var = (variable) pool_alloc (dv_pool (old_var->dv));
- empty_var->dv = old_var->dv;
- empty_var->refcount = 0;
- empty_var->n_var_parts = 0;
- empty_var->cur_loc_changed = false;
- empty_var->in_changed_variables = false;
- if (dv_onepart_p (old_var->dv))
- {
- location_chain lc;
+ variable empty_var = NULL;
- gcc_assert (old_var->n_var_parts == 1);
- for (lc = old_var->var_part[0].loc_chain; lc; lc = lc->next)
- remove_value_chains (old_var->dv, lc->loc);
- }
- variable_was_changed (empty_var, NULL);
- /* Continue traversing the hash table. */
- return 1;
- }
- if (variable_different_p (old_var, new_var))
- {
- if (dv_onepart_p (old_var->dv))
+ if (old_var->onepart == ONEPART_VALUE
+ || old_var->onepart == ONEPART_DEXPR)
{
- location_chain lc1, lc2;
-
- gcc_assert (old_var->n_var_parts == 1
- && new_var->n_var_parts == 1);
- lc1 = old_var->var_part[0].loc_chain;
- lc2 = new_var->var_part[0].loc_chain;
- while (lc1
- && lc2
- && ((REG_P (lc1->loc) && REG_P (lc2->loc))
- || rtx_equal_p (lc1->loc, lc2->loc)))
+ empty_var = variable_from_dropped (old_var->dv, NO_INSERT);
+ if (empty_var)
{
- lc1 = lc1->next;
- lc2 = lc2->next;
+ gcc_checking_assert (!empty_var->in_changed_variables);
+ if (!VAR_LOC_1PAUX (old_var))
+ {
+ VAR_LOC_1PAUX (old_var) = VAR_LOC_1PAUX (empty_var);
+ VAR_LOC_1PAUX (empty_var) = NULL;
+ }
+ else
+ gcc_checking_assert (!VAR_LOC_1PAUX (empty_var));
}
- for (; lc2; lc2 = lc2->next)
- add_value_chains (old_var->dv, lc2->loc);
- for (; lc1; lc1 = lc1->next)
- remove_value_chains (old_var->dv, lc1->loc);
}
- variable_was_changed (new_var, NULL);
- }
- /* Update cur_loc. */
- if (old_var != new_var)
- {
- int i;
- for (i = 0; i < new_var->n_var_parts; i++)
+
+ if (!empty_var)
{
- new_var->var_part[i].cur_loc = NULL;
- if (old_var->n_var_parts != new_var->n_var_parts
- || old_var->var_part[i].offset != new_var->var_part[i].offset)
- new_var->cur_loc_changed = true;
- else if (old_var->var_part[i].cur_loc != NULL)
- {
- location_chain lc;
- rtx cur_loc = old_var->var_part[i].cur_loc;
+ empty_var = (variable) pool_alloc (onepart_pool (old_var->onepart));
+ empty_var->dv = old_var->dv;
+ empty_var->refcount = 0;
+ empty_var->n_var_parts = 0;
+ empty_var->onepart = old_var->onepart;
+ empty_var->in_changed_variables = false;
+ }
- for (lc = new_var->var_part[i].loc_chain; lc; lc = lc->next)
- if (lc->loc == cur_loc
- || rtx_equal_p (cur_loc, lc->loc))
- {
- new_var->var_part[i].cur_loc = lc->loc;
- break;
- }
- if (lc == NULL)
- new_var->cur_loc_changed = true;
- }
+ if (empty_var->onepart)
+ {
+ /* Propagate the auxiliary data to (ultimately)
+ changed_variables. */
+ empty_var->var_part[0].loc_chain = NULL;
+ empty_var->var_part[0].cur_loc = NULL;
+ VAR_LOC_1PAUX (empty_var) = VAR_LOC_1PAUX (old_var);
+ VAR_LOC_1PAUX (old_var) = NULL;
}
+ variable_was_changed (empty_var, NULL);
+ /* Continue traversing the hash table. */
+ return 1;
+ }
+ /* Update cur_loc and one-part auxiliary data, before new_var goes
+ through variable_was_changed. */
+ if (old_var != new_var && new_var->onepart)
+ {
+ gcc_checking_assert (VAR_LOC_1PAUX (new_var) == NULL);
+ VAR_LOC_1PAUX (new_var) = VAR_LOC_1PAUX (old_var);
+ VAR_LOC_1PAUX (old_var) = NULL;
+ new_var->var_part[0].cur_loc = old_var->var_part[0].cur_loc;
}
+ if (variable_different_p (old_var, new_var))
+ variable_was_changed (new_var, NULL);
/* Continue traversing the hash table. */
return 1;
@@ -8033,15 +8528,6 @@ emit_notes_for_differences_2 (void **slot, void *data)
if (!old_var)
{
int i;
- /* Variable has appeared. */
- if (dv_onepart_p (new_var->dv))
- {
- location_chain lc;
-
- gcc_assert (new_var->n_var_parts == 1);
- for (lc = new_var->var_part[0].loc_chain; lc; lc = lc->next)
- add_value_chains (new_var->dv, lc->loc);
- }
for (i = 0; i < new_var->n_var_parts; i++)
new_var->var_part[i].cur_loc = NULL;
variable_was_changed (new_var, NULL);
@@ -8111,7 +8597,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
{
XEXP (XEXP (*p, 0), 1)
= vt_expand_loc (XEXP (XEXP (*p, 0), 1),
- shared_hash_htab (set->vars), true);
+ shared_hash_htab (set->vars));
/* If expansion is successful, keep it in the list. */
if (XEXP (XEXP (*p, 0), 1))
p = &XEXP (*p, 1);
@@ -8412,15 +8898,9 @@ vt_emit_notes (void)
emit_notes = true;
if (MAY_HAVE_DEBUG_INSNS)
- {
- unsigned int i;
- rtx val;
-
- FOR_EACH_VEC_ELT (rtx, preserved_values, i, val)
- add_cselib_value_chains (dv_from_value (val));
- changed_variables_stack = VEC_alloc (variable, heap, 40);
- changed_values_stack = VEC_alloc (rtx, heap, 40);
- }
+ dropped_values = htab_create (cselib_get_next_uid () * 2,
+ variable_htab_hash, variable_htab_eq,
+ variable_htab_free);
dataflow_set_init (&cur);
@@ -8441,23 +8921,11 @@ vt_emit_notes (void)
htab_traverse (shared_hash_htab (cur.vars),
emit_notes_for_differences_1,
shared_hash_htab (empty_shared_hash));
- if (MAY_HAVE_DEBUG_INSNS)
- {
- unsigned int i;
- rtx val;
-
- FOR_EACH_VEC_ELT (rtx, preserved_values, i, val)
- remove_cselib_value_chains (dv_from_value (val));
- gcc_assert (htab_elements (value_chains) == 0);
- }
#endif
dataflow_set_destroy (&cur);
if (MAY_HAVE_DEBUG_INSNS)
- {
- VEC_free (variable, heap, changed_variables_stack);
- VEC_free (rtx, heap, changed_values_stack);
- }
+ htab_delete (dropped_values);
emit_notes = false;
}
@@ -8489,36 +8957,27 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
return false;
}
-/* Helper function for vt_add_function_parameter. RTL is
- the expression and VAL corresponding cselib_val pointer
- for which ENTRY_VALUE should be created. */
+/* Mark the value for the ENTRY_VALUE of RTL as equivalent to EQVAL in
+ OUT. */
static void
-create_entry_value (rtx rtl, cselib_val *val)
-{
- cselib_val *val2;
- struct elt_loc_list *el;
- el = (struct elt_loc_list *) ggc_alloc_cleared_atomic (sizeof (*el));
- el->loc = gen_rtx_ENTRY_VALUE (GET_MODE (rtl));
- ENTRY_VALUE_EXP (el->loc) = rtl;
- val2 = cselib_lookup_from_insn (el->loc, GET_MODE (rtl), true,
- VOIDmode, get_insns ());
- el->next = val->locs;
- el->setting_insn = get_insns ();
- val->locs = el;
- if (val2
- && val2 != val
- && val2->locs
- && rtx_equal_p (val2->locs->loc, el->loc))
- {
- struct elt_loc_list *el2;
-
- preserve_value (val2);
- el2 = (struct elt_loc_list *) ggc_alloc_cleared_atomic (sizeof (*el2));
- el2->next = val2->locs;
- el2->loc = val->val_rtx;
- el2->setting_insn = get_insns ();
- val2->locs = el2;
+create_entry_value (dataflow_set *out, rtx eqval, rtx rtl)
+{
+ rtx ev = gen_rtx_ENTRY_VALUE (GET_MODE (rtl));
+ cselib_val *val;
+
+ ENTRY_VALUE_EXP (ev) = rtl;
+
+ val = cselib_lookup_from_insn (ev, GET_MODE (ev), true,
+ VOIDmode, get_insns ());
+
+ if (val->val_rtx != eqval)
+ {
+ preserve_value (val);
+ set_variable_part (out, val->val_rtx, dv_from_value (eqval), 0,
+ VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
+ set_variable_part (out, eqval, dv_from_value (val->val_rtx), 0,
+ VAR_INIT_STATUS_INITIALIZED, NULL_RTX, INSERT);
}
}
@@ -8678,20 +9137,22 @@ vt_add_function_parameter (tree parm)
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
if (dv_is_value_p (dv))
{
- cselib_val *val = CSELIB_VAL_PTR (dv_as_value (dv));
- create_entry_value (incoming, val);
+ create_entry_value (out, dv_as_value (dv), incoming);
if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
&& INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (parm))))
{
enum machine_mode indmode
= TYPE_MODE (TREE_TYPE (TREE_TYPE (parm)));
rtx mem = gen_rtx_MEM (indmode, incoming);
- val = cselib_lookup_from_insn (mem, indmode, true,
- VOIDmode, get_insns ());
+ cselib_val *val = cselib_lookup_from_insn (mem, indmode, true,
+ VOIDmode,
+ get_insns ());
if (val)
{
preserve_value (val);
- create_entry_value (mem, val);
+ set_variable_part (out, mem, dv_from_value (val->val_rtx), 0,
+ VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
+ create_entry_value (out, val->val_rtx, mem);
}
}
}
@@ -8755,23 +9216,6 @@ fp_setter (rtx insn)
return false;
}
-/* Gather all registers used for passing arguments to other functions
- called from the current routine. */
-
-static void
-note_register_arguments (rtx insn)
-{
- rtx link, x;
-
- for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1))
- if (GET_CODE (XEXP (link, 0)) == USE)
- {
- x = XEXP (XEXP (link, 0), 0);
- if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
- SET_HARD_REG_BIT (argument_reg_set, REGNO (x));
- }
-}
-
/* Initialize cfa_base_rtx, create a preserved VALUE for it and
ensure it isn't flushed during cselib_reset_table.
Can be called only if frame_pointer_rtx resp. arg_pointer_rtx
@@ -8843,14 +9287,6 @@ vt_initialize (void)
variable_htab_free);
changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
variable_htab_free);
- if (MAY_HAVE_DEBUG_INSNS)
- {
- value_chain_pool = create_alloc_pool ("value_chain_def pool",
- sizeof (struct value_chain_def),
- 1024);
- value_chains = htab_create (32, value_chain_htab_hash,
- value_chain_htab_eq, NULL);
- }
/* Init the IN and OUT sets. */
FOR_ALL_BB (bb)
@@ -8876,8 +9312,6 @@ vt_initialize (void)
valvar_pool = NULL;
}
- CLEAR_HARD_REG_SET (argument_reg_set);
-
/* In order to factor out the adjustments made to the stack pointer or to
the hard frame pointer and thus be able to use DW_OP_fbreg operations
instead of individual location lists, we're going to rewrite MEMs based
@@ -8962,14 +9396,6 @@ vt_initialize (void)
}
}
- if (frame_pointer_needed)
- {
- rtx insn;
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (CALL_P (insn))
- note_register_arguments (insn);
- }
-
hard_frame_pointer_adjustment = -1;
vt_add_function_parameters ();
@@ -9155,8 +9581,6 @@ vt_finalize (void)
if (MAY_HAVE_DEBUG_INSNS)
{
- htab_delete (value_chains);
- free_alloc_pool (value_chain_pool);
free_alloc_pool (valvar_pool);
VEC_free (rtx, heap, preserved_values);
cselib_finish ();
@@ -9164,7 +9588,9 @@ vt_finalize (void)
scratch_regs = NULL;
}
+#ifdef HAVE_window_save
VEC_free (parm_reg_t, gc, windowed_parm_regs);
+#endif
if (vui_vec)
XDELETEVEC (vui_vec);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 94e31115d1e..d0de2136bd8 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -3119,7 +3119,7 @@ build_constant_desc (tree exp)
SET_SYMBOL_REF_DECL (symbol, decl);
TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1;
- rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol);
+ rtl = gen_const_mem (TYPE_MODE (TREE_TYPE (exp)), symbol);
set_mem_attributes (rtl, exp, 1);
set_mem_alias_set (rtl, 0);
set_mem_alias_set (rtl, const_alias_set);
diff --git a/gcc/varpool.c b/gcc/varpool.c
index d223779a5c1..e342a9109d9 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -703,9 +703,11 @@ varpool_create_variable_alias (tree alias, tree decl)
gcc_assert (TREE_CODE (alias) == VAR_DECL);
alias_node = varpool_node (alias);
alias_node->alias = 1;
- alias_node->finalized = 1;
+ if (!DECL_EXTERNAL (alias))
+ alias_node->finalized = 1;
alias_node->alias_of = decl;
- if (decide_is_variable_needed (alias_node, alias)
+ if ((!DECL_EXTERNAL (alias)
+ && decide_is_variable_needed (alias_node, alias))
|| alias_node->needed)
varpool_mark_needed_node (alias_node);
return alias_node;
diff --git a/gnattools/ChangeLog b/gnattools/ChangeLog
index 9bcd6213230..e9a7a8be14e 100644
--- a/gnattools/ChangeLog
+++ b/gnattools/ChangeLog
@@ -1,3 +1,13 @@
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.in (LOOSE_WARN): Delete.
+ (GCC_WARN_CFLAGS): Set to -W -Wall.
+ (TOOLS_FLAGS_TO_PASS_1): Delete.
+ (TOOLS_FLAGS_TO_PASS_1re): Rename into...
+ (TOOLS_FLAGS_TO_PASS_RE): ...this.
+ (gnattools-native): Use TOOLS_FLAGS_TO_PASS_NATIVE.
+ (regnattools): Use TOOLS_FLAGS_TO_PASS_RE.
+
2011-07-07 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR target/39150
diff --git a/gnattools/Makefile.in b/gnattools/Makefile.in
index 3718b30593f..794d374e75e 100644
--- a/gnattools/Makefile.in
+++ b/gnattools/Makefile.in
@@ -44,8 +44,7 @@ PWD_COMMAND = $${PWDCMD-pwd}
# The tedious process of getting CFLAGS right.
CFLAGS=-g
-LOOSE_WARN = -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
-GCC_WARN_CFLAGS = $(LOOSE_WARN)
+GCC_WARN_CFLAGS = -W -Wall
WARN_CFLAGS = @warn_cflags@
ADA_CFLAGS=@ADA_CFLAGS@
@@ -64,8 +63,8 @@ INCLUDES_FOR_SUBDIR = -I. -I.. -I../.. -I$(fsrcdir)/ada -I$(fsrcdir)/config \
-I$(fsrcdir)/../include -I$(fsrcdir)
ADA_INCLUDES_FOR_SUBDIR = -I. -I$(fsrcdir)/ada
-# Variables for gnattools1, native
-TOOLS_FLAGS_TO_PASS_1= \
+# Variables for gnattools, native
+TOOLS_FLAGS_TO_PASS_NATIVE= \
"CC=../../xgcc -B../../" \
"CFLAGS=$(CFLAGS) $(WARN_CFLAGS)" \
"LDFLAGS=$(LDFLAGS)" \
@@ -76,11 +75,13 @@ TOOLS_FLAGS_TO_PASS_1= \
"exeext=$(exeext)" \
"fsrcdir=$(fsrcdir)" \
"srcdir=$(fsrcdir)" \
+ "GNATMAKE=../../gnatmake" \
+ "GNATLINK=../../gnatlink" \
"GNATBIND=../../gnatbind" \
"TOOLSCASE=native"
# Variables for regnattools
-TOOLS_FLAGS_TO_PASS_1re= \
+TOOLS_FLAGS_TO_PASS_RE= \
"CC=../../xgcc -B../../" \
"CFLAGS=$(CFLAGS)" \
"ADAFLAGS=$(ADAFLAGS)" \
@@ -93,24 +94,7 @@ TOOLS_FLAGS_TO_PASS_1re= \
"GNATMAKE=../../gnatmake" \
"GNATLINK=../../gnatlink" \
"GNATBIND=../../gnatbind" \
- "TOOLSCASE=cross" \
- "INCLUDES="
-
-# Variables for gnattools2, native
-TOOLS_FLAGS_TO_PASS_NATIVE= \
- "CC=../../xgcc -B../../" \
- "CFLAGS=$(CFLAGS)" \
- "ADAFLAGS=$(ADAFLAGS)" \
- "ADA_CFLAGS=$(ADA_CFLAGS)" \
- "INCLUDES=$(INCLUDES_FOR_SUBDIR)" \
- "ADA_INCLUDES=-I../rts $(ADA_INCLUDES_FOR_SUBDIR)" \
- "exeext=$(exeext)" \
- "fsrcdir=$(fsrcdir)" \
- "srcdir=$(fsrcdir)" \
- "GNATMAKE=../../gnatmake" \
- "GNATLINK=../../gnatlink" \
- "GNATBIND=../../gnatbind" \
- "TOOLSCASE=native"
+ "TOOLSCASE=cross"
# Variables for gnattools, cross
TOOLS_FLAGS_TO_PASS_CROSS= \
@@ -177,7 +161,7 @@ $(GCC_DIR)/stamp-tools:
gnattools-native: $(GCC_DIR)/stamp-tools $(GCC_DIR)/stamp-gnatlib-rts
# gnattools1
$(MAKE) -C $(GCC_DIR)/ada/tools -f ../Makefile \
- $(TOOLS_FLAGS_TO_PASS_1) \
+ $(TOOLS_FLAGS_TO_PASS_NATIVE) \
../../gnatmake$(exeext) ../../gnatlink$(exeext)
# gnattools2
$(MAKE) -C $(GCC_DIR)/ada/tools -f ../Makefile \
@@ -189,7 +173,7 @@ gnattools-native: $(GCC_DIR)/stamp-tools $(GCC_DIR)/stamp-gnatlib-rts
regnattools: $(GCC_DIR)/stamp-gnatlib-rts
# gnattools1-re
$(MAKE) -C $(GCC_DIR)/ada/tools -f ../Makefile \
- $(TOOLS_FLAGS_TO_PASS_1re) \
+ $(TOOLS_FLAGS_TO_PASS_RE) INCLUDES="" \
gnatmake-re gnatlink-re
# gnattools2
$(MAKE) -C $(GCC_DIR)/ada/tools -f ../Makefile \
diff --git a/include/ChangeLog b/include/ChangeLog
index 342ae36e176..d5701f40772 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,11 @@
+2011-10-21 Ulrich Drepper <drepper@gmail.com>
+
+ * obstack.h [!GNUC] (obstack_free): Avoid cast to int.
+
+2011-10-21 Marc Glisse <marc.glisse@inria.fr>
+
+ * ansidecl.h (ENUM_BITFIELD): Always use enum in C++
+
2011-09-28 Doug Evans <dje@google.com>
* timeval-utils.h: New file.
diff --git a/include/ansidecl.h b/include/ansidecl.h
index c39ce2f5d70..23d85bf0e16 100644
--- a/include/ansidecl.h
+++ b/include/ansidecl.h
@@ -416,10 +416,12 @@ So instead we use the macro below and test it against specific values. */
#define EXPORTED_CONST const
#endif
-/* Be conservative and only use enum bitfields with GCC.
+/* Be conservative and only use enum bitfields with C++ or GCC.
FIXME: provide a complete autoconf test for buggy enum bitfields. */
-#if (GCC_VERSION > 2000)
+#ifdef __cplusplus
+#define ENUM_BITFIELD(TYPE) enum TYPE
+#elif (GCC_VERSION > 2000)
#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
#else
#define ENUM_BITFIELD(TYPE) unsigned int
diff --git a/include/obstack.h b/include/obstack.h
index 4aec3a484e2..23487ba4f4a 100644
--- a/include/obstack.h
+++ b/include/obstack.h
@@ -532,9 +532,9 @@ __extension__ \
# define obstack_free(h,obj) \
( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
- ? (int) ((h)->next_free = (h)->object_base \
- = (h)->temp + (char *) (h)->chunk) \
- : (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
+ ? (((h)->next_free = (h)->object_base \
+ = (h)->temp + (char *) (h)->chunk), 0) \
+ : ((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0)))
#endif /* not __GNUC__ or not __STDC__ */
diff --git a/libada/ChangeLog b/libada/ChangeLog
index 689e9fb1a32..fbcff774051 100644
--- a/libada/ChangeLog
+++ b/libada/ChangeLog
@@ -1,3 +1,14 @@
+2011-10-12 Eric Botcazou <ebotcazou@adacore.com>
+
+ * Makefile.in (LOOSE_WARN): Delete.
+ (GCC_WARN_CFLAGS): Likewise.
+ (WARN_CFLAGS): Likewise.
+ (GNATLIBFLAGS): Add -nostdinc.
+ (GNATLIBCFLAGS_FOR_C): Add -W -Wall.
+ (LIBADA_FLAGS_TO_PASS): Remove WARN_CFLAGS.
+ * configure.ac (warn_cflags): Delete.
+ * configure: Regenerate.
+
2011-08-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* configure.ac: Include ../config/picflag.m4.
diff --git a/libada/Makefile.in b/libada/Makefile.in
index 6f3df38c322..86aff529dbd 100644
--- a/libada/Makefile.in
+++ b/libada/Makefile.in
@@ -45,21 +45,17 @@ AWK=@AWK@
# Variables for the user (or the top level) to override.
objext=.o
-GNATLIBFLAGS= -W -Wall -gnatpg
THREAD_KIND=native
TRACE=no
LDFLAGS=
# The tedious process of getting CFLAGS right.
CFLAGS=-g
-LOOSE_WARN = -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
-GCC_WARN_CFLAGS = $(LOOSE_WARN)
-WARN_CFLAGS = @warn_cflags@
-
PICFLAG = @PICFLAG@
+GNATLIBFLAGS= -W -Wall -gnatpg -nostdinc
GNATLIBCFLAGS= -g -O2
-GNATLIBCFLAGS_FOR_C = $(GNATLIBCFLAGS) $(PICFLAG) -fexceptions \
- -DIN_RTS @have_getipinfo@
+GNATLIBCFLAGS_FOR_C = -W -Wall $(GNATLIBCFLAGS) $(PICFLAG) \
+ -fexceptions -DIN_RTS @have_getipinfo@
host_subdir = @host_subdir@
GCC_DIR=$(MULTIBUILDTOP)../../$(host_subdir)/gcc
@@ -91,7 +87,7 @@ LIBADA_FLAGS_TO_PASS = \
"exeext=.exeext.should.not.be.used " \
'CC=the.host.compiler.should.not.be.needed' \
"GCC_FOR_TARGET=$(CC)" \
- "CFLAGS=$(CFLAGS) $(WARN_CFLAGS)"
+ "CFLAGS=$(CFLAGS)"
# Rules to build gnatlib.
.PHONY: gnatlib gnatlib-plain gnatlib-sjlj gnatlib-zcx gnatlib-shared oscons
diff --git a/libada/configure b/libada/configure
index c0a294fdd0c..1e0ceefc86a 100755
--- a/libada/configure
+++ b/libada/configure
@@ -553,7 +553,6 @@ PACKAGE_URL=
ac_unique_file="Makefile.in"
ac_subst_vars='LTLIBOBJS
LIBOBJS
-warn_cflags
have_getipinfo
default_gnatlib_target
LN_S
@@ -3007,12 +3006,6 @@ if test x$have_unwind_getipinfo = xyes; then
fi
-warn_cflags=
-if test "x$GCC" = "xyes"; then
- warn_cflags='$(GCC_WARN_CFLAGS)'
-fi
-
-
# Output: create a Makefile.
ac_config_files="$ac_config_files Makefile"
diff --git a/libada/configure.ac b/libada/configure.ac
index f9b9c5ab3b0..1e3760cbe4c 100644
--- a/libada/configure.ac
+++ b/libada/configure.ac
@@ -144,12 +144,6 @@ if test x$have_unwind_getipinfo = xyes; then
fi
AC_SUBST(have_getipinfo)
-warn_cflags=
-if test "x$GCC" = "xyes"; then
- warn_cflags='$(GCC_WARN_CFLAGS)'
-fi
-AC_SUBST(warn_cflags)
-
# Output: create a Makefile.
AC_CONFIG_FILES([Makefile])
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 4ecda03cfec..64ed4683669 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,302 @@
+2011-10-31 Jason Merrill <jason@redhat.com>
+
+ PR libstdc++/1773
+ * init.c (cpp_init_builtins): Set __cplusplus for C++11.
+
+ PR c++/50920
+ * include/cpplib.h (enum c_lang): Rename CLK_CXX0X to CLK_CXX11,
+ CLK_GNUCXX0X to CLK_GNUCXX11.
+
+2011-10-26 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ Implement C++11 user-defined literals.
+ * expr.c: (cpp_interpret_float_suffix, cpp_interpret_int_suffix,
+ cpp_userdef_string_remove_type, cpp_userdef_string_add_type,
+ cpp_userdef_char_remove_type, cpp_userdef_char_add_type,
+ cpp_userdef_string_p, cpp_userdef_char_p, cpp_get_userdef_suffix): New.
+ (cpp_classify_number): Classify unrecognized tokens as user-defined
+ literals.
+ * include/cpplib.h: Add new tokens for user-defined literals.
+ * init.c: Add new preprocessor flag (cxx11).
+ * lex.c: (lex_string, lex_raw_string): Handle user-defined literals
+ including concatenation and promotion with suffixes.
+
+2011-10-24 Dodji Seketeli <dodji@redhat.com>
+
+ * line-map.c (linemap_macro_map_lookup): Fix logic.
+
+2011-10-24 Dodji Seketeli <dodji@redhat.com>
+
+ * include/line-map.h (linemap_expand_location): Take a line table
+ parameter. Update comment.
+ (linemap_resolve_location): Update comment.
+ (linemap_expand_location_full): Remove.
+ * line-map.c (linemap_resolve_location): Handle reserved
+ locations; return a NULL map in those cases.
+ (linemap_expand_location): If location is reserved, return a
+ zeroed expanded location. Update comment. Take a line table to
+ assert that the function takes non-virtual locations only.
+ (linemap_expand_location_full): remove.
+ (linemap_dump_location): Handle the fact that
+ linemap_resolve_location can return NULL line maps when the
+ location resolves to a reserved location.
+
+ * line-map.c (linemap_macro_map_lookup): Fix logic.
+
+2011-10-22 Dodji Seketeli <dodji@redhat.com>
+
+ PR bootstrap/50778
+ * include/internal.h (_cpp_remaining_tokens_num_in_context): Take the
+ context to act upon.
+ * lex.c (_cpp_remaining_tokens_num_in_context): Likewise. Update
+ comment.
+ (cpp_token_from_context_at): Likewise.
+ (cpp_peek_token): Use the context to peek tokens from.
+
+2011-10-20 Dodji Seketeli <dodji@redhat.com>
+
+ PR bootstrap/50801
+ * lex.c (_cpp_remaining_tokens_num_in_context): Fix computation of
+ number of tokens.
+
+2011-10-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR bootstrap/50760
+ * include/line-map.h (struct linemap_stats): Change the type of
+ the members from size_t to long.
+ * macro.c (macro_arg_token_iter_init): Unconditionally initialize
+ iter->location_ptr.
+
+2011-10-17 Dodji Seketeli <dodji@redhat.com>
+
+ * line-map.c (linemap_macro_map_loc_to_exp_point): Avoid setting a
+ variable without using it if ENABLE_CHECKING is not defined. Mark
+ the LOCATION parameter as being unused.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/line-map.h (struct line_maps::alloced_size_for_request):
+ New member.
+ * line-map.c (new_linemap): Use set->alloced_size_for_request to
+ get the actual allocated size of line maps.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * line-map.h (struct linemap_stats): Declare new struct.
+ (linemap_get_statistics): Declare ...
+ * line-map.c (linemap_get_statistics): ... new function.
+ * macro.c (num_expanded_macros_counter, num_macro_tokens_counter):
+ Declare new counters.
+ (enter_macro_context, replace_args): Update
+ num_macro_tokens_counter.
+ (cpp_get_token_1): Update num_expanded_macros_counter.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/cpplib.h (struct cpp_options)<debug>: New struct member.
+ * include/line-map.h (linemap_dump_location): Declare ...
+ * line-map.c (linemap_dump_location): ... new function.
+
+2011-10-15 Tom Tromey <tromey@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/cpplib.h (struct cpp_options)<track_macro_expansion>:
+ New option.
+ * internal.h (struct macro_context): New struct.
+ (enum context_tokens_kind): New enum.
+ (struct cpp_context)<tokens_kind>: New member of type enum
+ context_tokens_kind.
+ (struct cpp_context)<macro>: Remove this. Replace it with an enum
+ of macro and macro_context.
+ (struct cpp_context)<direct_p>: Remove.
+ (_cpp_remaining_tokens_num_in_context): Declare new function.
+ * directives.c (destringize_and_run): Adjust.
+ * lex.c (_cpp_remaining_tokens_num_in_context)
+ (_cpp_token_from_context_at): Define new functions
+ (cpp_peek_token): Use them.
+ * init.c (cpp_create_reader): Initialize the base context to zero.
+ (_cpp_token_from_context_at): Define new static function.
+ (cpp_peek_token): Use new _cpp_remaining_tokens_num_in_context and
+ _cpp_token_from_context_at.
+ * macro.c (struct macro_arg)<virt_locs, expanded_virt_locs>: New
+ members.
+ (enum macro_arg_token_kind): New enum.
+ (struct macro_arg_token_iter): New struct.
+ (maybe_adjust_loc_for_trad_cpp, push_extended_tokens_context)
+ (alloc_expanded_arg_mem, ensure_expanded_arg_room)
+ (delete_macro_args, set_arg_token, get_arg_token_location)
+ (arg_token_ptr_at, macro_arg_token_iter_init)
+ (macro_arg_token_iter_get_token)
+ (macro_arg_token_iter_get_location, macro_arg_token_iter_forward)
+ (expanded_token_index, tokens_buff_new, tokens_buff_count)
+ (tokens_buff_last_token_ptr, tokens_buff_put_token_to)
+ (tokens_buff_add_token, tokens_buff_remove_last_token)
+ (reached_end_of_context, consume_next_token_from_context): New
+ static functions.
+ (cpp_get_token_1): New static function. Split and extended from
+ cpp_get_token. Use reached_end_of_context and
+ consume_next_token_from_context. Unify its return point. Move
+ the location tweaking from cpp_get_token_with_location in here.
+ (cpp_get_token): Use cpp_get_token_1
+ (stringify_arg): Use the new arg_token_at.
+ (paste_all_tokens): Support tokens coming from extended tokens
+ contexts.
+ (collect_args): Return the number of collected arguments, by
+ parameter. Store virtual locations of tokens that constitute the
+ collected args.
+ (funlike_invocation_p): Return the number of collected arguments,
+ by parameter.
+ (enter_macro_context): Add a parameter for macro expansion point.
+ Pass it to replace_args and to the "used" cpp callback. Get the
+ number of function-like macro arguments from funlike_invocation_p,
+ pass it to the new delete_macro_args to free the memory used by
+ macro args. When -ftrack-macro-expansion is in effect, for macros
+ that have no arguments, create a macro map for the macro expansion
+ and use it to allocate proper virtual locations for tokens
+ resulting from the expansion. Push an extended tokens context
+ containing the tokens resulting from macro expansion and their
+ virtual locations.
+ (replace_args): Rename the different variables named 'count' into
+ variables with more meaningful names. Create a macro map;
+ allocate virtual locations of tokens resulting from this
+ expansion. Use macro_arg_token_iter to iterate over tokens of a
+ given macro. Handle the case of the argument of
+ -ftrack-macro-expansion being < 2. Don't free macro arguments
+ memory resulting from expand_arg here, as these are freed by the
+ caller of replace_arg using delete_macro_args now. Push extended
+ token context.
+ (next_context, push_ptoken_context, _cpp_push_token_context)
+ (_cpp_push_text_context): Properly initialize the context.
+ (expand_arg): Use the new alloc_expanded_arg_mem,
+ push_extended_tokens_context, cpp_get_token_1, and set_arg_token.
+ (_cpp_pop_context): Really free the memory held by the context.
+ Handle freeing memory used by extended tokens contexts.
+ (cpp_get_token_with_location): Use cpp_get_token_1.
+ (cpp_sys_macro_p): Adjust.
+ (_cpp_backup_tokens): Support the new kinds of token contexts.
+ * traditional.c (recursive_macro): Adjust.
+
+2011-10-15 Tom Tromey <tromey@redhat>
+ Dodji Seketeli <dodji@redhat.com>
+
+ * include/line-map.h (enum lc_reason)<LC_ENTER_MACRO>: New enum
+ member.
+ (MAX_SOURCE_LOCATION): New constant.
+ (struct line_map_ordinary, struct line_map_macro): New structs.
+ (struct line_map): Turn this into a union of the two above. Add
+ comments.
+ (struct maps_info): New struct.
+ (struct line_maps)<info_ordinary, info_macro>: Two new fields.
+ These now carry the map information that was previously scattered
+ in struct line_maps.
+ (struct map_info::allocated): Fix comment.
+ (MAP_START_LOCATION, ORDINARY_MAP_FILE_NAME)
+ (ORDINARY_MAP_STARTING_LINE_NUMBER)
+ (ORDINARY_MAP_INCLUDER_FILE_INDEX)
+ (ORDINARY_MAP_IN_SYSTEM_HEADER_P)
+ (ORDINARY_MAP_NUMBER_OF_COLUMN_BITS, MACRO_MAP_MACRO)
+ (MACRO_MAP_NUM_MACRO_TOKENS MACRO_MAP_LOCATIONS)
+ (MACRO_MAP_EXPANSION_POINT_LOCATION)
+ (LOCATION_POSSIBLY_IN_MACRO_MAP_P, LINEMAPS_MAP_INFO)
+ (LINEMAPS_MAPS, LINEMAPS_ALLOCATE, LINEMAPS_USED, LINEMAPS_CACHE)
+ (LINEMAPS_LAST_MAP, LINEMAPS_LAST_ALLOCATED_MAP)
+ (LINEMAPS_ORDINARY_MAPS, LINEMAPS_ORDINARY_ALLOCATED)
+ (LINEMAPS_ORDINARY_USED, LINEMAPS_ORDINARY_CACHE)
+ (LINEMAPS_LAST_ORDINARY_MAP, LINEMAPS_LAST_ALLOCATED_ORDINARY_MAP)
+ (LINEMAPS_MACRO_MAPS, LINEMAPS_MACRO_ALLOCATED)
+ (LINEMAPS_MACRO_USED, LINEMAPS_MACRO_CACHE)
+ (LINEMAPS_LAST_MACRO_MAP, LINEMAPS_LAST_ALLOCATED_MACRO_MAP)
+ (LINEMAPS_MAP_AT, LINEMAPS_ORDINARY_MAP_AT)
+ (LINEMAPS_MACRO_MAP_AT): New accessors for ordinary and macro map
+ information.
+ (linemap_check_ordinary, linemap_assert)
+ (linemap_location_before_p): New macros.
+ (linemap_position_for_line_and_column)
+ (linemap_tracks_macro_expansion_locs_p, linemap_add_macro_token)
+ (linemap_macro_expansion_map_p)
+ (linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_once)
+ (linemap_macro_map_loc_to_exp_point, linemap_step_out_once)
+ (linemap_get_source_line linemap_get_source_column)
+ (linemap_map_get_macro_name, linemap_get_file_path)
+ (linemap_location_in_system_header_p)
+ (linemap_location_from_macro_expansion_p): Declare new functions.
+ (SOURCE_LINE, SOURCE_COLUMN, LAST_SOURCE_LINE_LOCATION)
+ (LINEMAP_FILE, LINEMAP_LINE, LINEMAP_SYSP): Assert that this
+ accessors act on ordinary maps only.
+ (INCLUDED_FROM): Return NULL for main files; use the new
+ accessors.
+ (LINEMAP_POSITION_FOR_COLUMN): Use the new accessors.
+ (struct expanded_location): Move here from gcc/input.h
+ (linemap_resolve_location, linemap_expand_location)
+ (linemap_expand_location_full): Declare new functions.
+ * line-map.c: Include cpplib.h, internal.h
+ (linemap_enter_macro, linemap_add_macro_token)
+ (linemap_get_expansion_line, linemap_get_expansion_filename): New
+ functions that are private to libcpp.
+ (linemap_assert): New macro.
+ (linemap_macro_loc_to_exp_point, linemap_macro_loc_to_exp_point)
+ (linemap_macro_loc_unwind, linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_toward_spelling)
+ (linemap_macro_map_loc_to_exp_point)
+ (first_map_in_common_1, first_map_in_common): New static
+ functions.
+ (new_linemap): Define new static functions. Extracted and
+ enhanced from ...
+ (linemap_add): ... here. Use linemap_assert in lieu of abort
+ previously.
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_add_macro_token, linemap_macro_expansion_map_p)
+ (linemap_check_ordinary, linemap_macro_map_loc_to_exp_point)
+ (linemap_macro_map_loc_to_def_point)
+ (linemap_macro_map_loc_unwind_once)
+ (linemap_step_out_once, linemap_map_get_index)
+ (linemap_get_source_line,linemap_get_source_column)
+ (linemap_get_file_path, linemap_map_get_macro_name)
+ (linemap_location_in_system_header_p)
+ (linemap_location_originated_from_system_header_p)
+ (linemap_location_from_macro_expansion_p)
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_resolve_location, linemap_expand_location)
+ (linemap_expand_location_full)
+ (linemap_tracks_macro_expansion_locs_p)
+ (linemap_position_for_line_and_column, linemap_compare_locations):
+ Define new public functions.
+ (linemap_init): Initialize ordinary and macro maps information in
+ the map set.
+ (linemap_check_files_exited): Use the new accessors.
+ (linemap_free): Remove this dead code.
+ (linemap_line_start): Assert this uses an ordinary map. Adjust to
+ use the new ordinary map accessors and data structures. Don't
+ overflow past the lowest possible macro token's location.
+ (linemap_position_for_column): Assert the ordinary maps of the map
+ set are really ordinary. Use ordinary map accessors.
+ (linemap_lookup): Keep the same logic but generalize to allow
+ lookup of both ordinary and macro maps. Do not crash when called
+ with an empty line table.
+ * directives-only.c (_cpp_preprocess_dir_only): Adjust to use the
+ new API of line-map.h.
+ * directives.c (start_directive, do_line, do_linemarker)
+ (do_linemarker): Likewise.
+ * files.c (_cpp_find_file, _cpp_stack_include, open_file_failed)
+ (make_cpp_dir, cpp_make_system_header): Likewise.
+ * init.c (cpp_read_main_file): Likewise.
+ * internal.h (CPP_INCREMENT_LINE): Likewise.
+ (linemap_enter_macro, linemap_add_macro_token)
+ (linemap_get_expansion_line, linemap_get_expansion_filename): New
+ functions private to libcpp.
+ * lex.c (_cpp_process_line_notes, _cpp_skip_block_comment)
+ (skip_line_comment, skip_whitespace, lex_raw_string)
+ (_cpp_lex_direct): Likewise.
+ * macro.c (_cpp_builtin_macro_text): Likewise.
+ (_cpp_aligned_alloc): Initialize the new name member of the macro.
+ * traditional.c (copy_comment, _cpp_scan_out_logical_line):
+ Likewise.
+ * errors.c (cpp_diagnostic): Adjust to new linemap API.
+
2011-08-28 Dodji Seketeli <dodji@redhat.com>
* line-map.c (linemap_add): Assert that reason must not be
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 83d4a0e8d7f..0510c6e3a8e 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -1,7 +1,7 @@
/* CPP Library. (Directive handling.)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Contributed by Per Bothner, 1994-95.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -884,14 +884,14 @@ static void
do_line (cpp_reader *pfile)
{
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used - 1];
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
/* skip_rest_of_line() may cause line table to be realloc()ed so note down
sysp right now. */
- unsigned char map_sysp = map->sysp;
+ unsigned char map_sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (map);
const cpp_token *token;
- const char *new_file = map->to_file;
+ const char *new_file = ORDINARY_MAP_FILE_NAME (map);
linenum_type new_lineno;
/* C99 raised the minimum limit on #line numbers. */
@@ -946,11 +946,11 @@ static void
do_linemarker (cpp_reader *pfile)
{
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used - 1];
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
const cpp_token *token;
- const char *new_file = map->to_file;
+ const char *new_file = ORDINARY_MAP_FILE_NAME (map);
linenum_type new_lineno;
- unsigned int new_sysp = map->sysp;
+ unsigned int new_sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (map);
enum lc_reason reason = LC_RENAME_VERBATIM;
int flag;
bool wrapped;
@@ -1038,7 +1038,9 @@ _cpp_do_file_change (cpp_reader *pfile, enum lc_reason reason,
const struct line_map *map = linemap_add (pfile->line_table, reason, sysp,
to_file, file_line);
if (map != NULL)
- linemap_line_start (pfile->line_table, map->to_line, 127);
+ linemap_line_start (pfile->line_table,
+ ORDINARY_MAP_STARTING_LINE_NUMBER (map),
+ 127);
if (pfile->cb.file_change)
pfile->cb.file_change (pfile, map);
@@ -1740,7 +1742,7 @@ destringize_and_run (cpp_reader *pfile, const cpp_string *in)
saved_cur_run = pfile->cur_run;
pfile->context = XNEW (cpp_context);
- pfile->context->macro = 0;
+ pfile->context->c.macro = 0;
pfile->context->prev = 0;
pfile->context->next = 0;
diff --git a/libcpp/expr.c b/libcpp/expr.c
index 3c36127b54f..7bbc72d6f26 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -1,6 +1,6 @@
/* Parse C expressions for cpplib.
Copyright (C) 1987, 1992, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
- 2002, 2004, 2008, 2009, 2010 Free Software Foundation.
+ 2002, 2004, 2008, 2009, 2010, 2011 Free Software Foundation.
Contributed by Per Bothner, 1994.
This program is free software; you can redistribute it and/or modify it
@@ -185,6 +185,13 @@ interpret_float_suffix (const uchar *s, size_t len)
q ? CPP_N_MD_Q : CPP_N_DEFAULT));
}
+/* Return the classification flags for a float suffix. */
+unsigned int
+cpp_interpret_float_suffix (const char *s, size_t len)
+{
+ return interpret_float_suffix ((const unsigned char *)s, len);
+}
+
/* 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. */
@@ -219,11 +226,143 @@ interpret_int_suffix (const uchar *s, size_t len)
: (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
}
+/* Return the classification flags for an int suffix. */
+unsigned int
+cpp_interpret_int_suffix (const char *s, size_t len)
+{
+ return interpret_int_suffix ((const unsigned char *)s, len);
+}
+
+/* Return the string type corresponding to the the input user-defined string
+ literal type. If the input type is not a user-defined string literal
+ type return the input type. */
+enum cpp_ttype
+cpp_userdef_string_remove_type (enum cpp_ttype type)
+{
+ if (type == CPP_STRING_USERDEF)
+ return CPP_STRING;
+ else if (type == CPP_WSTRING_USERDEF)
+ return CPP_WSTRING;
+ else if (type == CPP_STRING16_USERDEF)
+ return CPP_STRING16;
+ else if (type == CPP_STRING32_USERDEF)
+ return CPP_STRING32;
+ else if (type == CPP_UTF8STRING_USERDEF)
+ return CPP_UTF8STRING;
+ else
+ return type;
+}
+
+/* Return the user-defined string literal type corresponding to the input
+ string type. If the input type is not a string type return the input
+ type. */
+enum cpp_ttype
+cpp_userdef_string_add_type (enum cpp_ttype type)
+{
+ if (type == CPP_STRING)
+ return CPP_STRING_USERDEF;
+ else if (type == CPP_WSTRING)
+ return CPP_WSTRING_USERDEF;
+ else if (type == CPP_STRING16)
+ return CPP_STRING16_USERDEF;
+ else if (type == CPP_STRING32)
+ return CPP_STRING32_USERDEF;
+ else if (type == CPP_UTF8STRING)
+ return CPP_UTF8STRING_USERDEF;
+ else
+ return type;
+}
+
+/* Return the char type corresponding to the the input user-defined char
+ literal type. If the input type is not a user-defined char literal
+ type return the input type. */
+enum cpp_ttype
+cpp_userdef_char_remove_type (enum cpp_ttype type)
+{
+ if (type == CPP_CHAR_USERDEF)
+ return CPP_CHAR;
+ else if (type == CPP_WCHAR_USERDEF)
+ return CPP_WCHAR;
+ else if (type == CPP_CHAR16_USERDEF)
+ return CPP_STRING16;
+ else if (type == CPP_CHAR32_USERDEF)
+ return CPP_STRING32;
+ else
+ return type;
+}
+
+/* Return the user-defined char literal type corresponding to the input
+ char type. If the input type is not a char type return the input
+ type. */
+enum cpp_ttype
+cpp_userdef_char_add_type (enum cpp_ttype type)
+{
+ if (type == CPP_CHAR)
+ return CPP_CHAR_USERDEF;
+ else if (type == CPP_WCHAR)
+ return CPP_WCHAR_USERDEF;
+ else if (type == CPP_CHAR16)
+ return CPP_CHAR16_USERDEF;
+ else if (type == CPP_CHAR32)
+ return CPP_CHAR32_USERDEF;
+ else
+ return type;
+}
+
+/* Return true if the token type is a user-defined string literal. */
+bool
+cpp_userdef_string_p (enum cpp_ttype type)
+{
+ if (type == CPP_STRING_USERDEF
+ || type == CPP_WSTRING_USERDEF
+ || type == CPP_STRING16_USERDEF
+ || type == CPP_STRING32_USERDEF
+ || type == CPP_UTF8STRING_USERDEF)
+ return true;
+ else
+ return false;
+}
+
+/* Return true if the token type is a user-defined char literal. */
+bool
+cpp_userdef_char_p (enum cpp_ttype type)
+{
+ if (type == CPP_CHAR_USERDEF
+ || type == CPP_WCHAR_USERDEF
+ || type == CPP_CHAR16_USERDEF
+ || type == CPP_CHAR32_USERDEF)
+ return true;
+ else
+ return false;
+}
+
+/* Extract the suffix from a user-defined literal string or char. */
+const char *
+cpp_get_userdef_suffix (const cpp_token *tok)
+{
+ unsigned int len = tok->val.str.len;
+ const char *text = (const char *)tok->val.str.text;
+ char delim;
+ unsigned int i;
+ for (i = 0; i < len; ++i)
+ if (text[i] == '\'' || text[i] == '"')
+ break;
+ if (i == len)
+ return text + len;
+ delim = text[i];
+ for (i = len; i > 0; --i)
+ if (text[i - 1] == delim)
+ break;
+ return text + i;
+}
+
/* Categorize numeric constants according to their field (integer,
floating point, or invalid), radix (decimal, octal, hexadecimal),
- and type suffixes. */
+ and type suffixes. In C++0X if UD_SUFFIX is non null it will be
+ assigned any unrecognized suffix for a user-defined literal. */
unsigned int
-cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
+cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
+ const char **ud_suffix)
{
const uchar *str = token->val.str.text;
const uchar *limit;
@@ -231,6 +370,9 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
bool seen_digit;
+ if (ud_suffix)
+ *ud_suffix = NULL;
+
/* 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)
@@ -361,10 +503,19 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
result = interpret_float_suffix (str, limit - str);
if (result == 0)
{
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" on floating constant",
- (int) (limit - str), str);
- return CPP_N_INVALID;
+ if (CPP_OPTION (pfile, user_literals))
+ {
+ if (ud_suffix)
+ *ud_suffix = (const char *) str;
+ result = CPP_N_LARGE | CPP_N_USERDEF;
+ }
+ else
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "invalid suffix \"%.*s\" on floating constant",
+ (int) (limit - str), str);
+ return CPP_N_INVALID;
+ }
}
/* Traditional C didn't accept any floating suffixes. */
@@ -406,10 +557,19 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token)
result = interpret_int_suffix (str, limit - str);
if (result == 0)
{
- cpp_error (pfile, CPP_DL_ERROR,
- "invalid suffix \"%.*s\" on integer constant",
- (int) (limit - str), str);
- return CPP_N_INVALID;
+ if (CPP_OPTION (pfile, user_literals))
+ {
+ if (ud_suffix)
+ *ud_suffix = (const char *) str;
+ result = CPP_N_UNSIGNED | CPP_N_LARGE | CPP_N_USERDEF;
+ }
+ else
+ {
+ cpp_error (pfile, CPP_DL_ERROR,
+ "invalid suffix \"%.*s\" on integer constant",
+ (int) (limit - str), str);
+ return CPP_N_INVALID;
+ }
}
/* Traditional C only accepted the 'L' suffix.
@@ -539,7 +699,7 @@ cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
}
}
- if (overflow)
+ if (overflow && !(type & CPP_N_USERDEF))
cpp_error (pfile, CPP_DL_PEDWARN,
"integer constant is too large for its type");
/* If too big to be signed, consider it unsigned. Only warn for
@@ -748,7 +908,10 @@ eval_token (cpp_reader *pfile, const cpp_token *token)
switch (token->type)
{
case CPP_NUMBER:
- temp = cpp_classify_number (pfile, token);
+ temp = cpp_classify_number (pfile, token, NULL);
+ if (temp & CPP_N_USERDEF)
+ cpp_error (pfile, CPP_DL_ERROR,
+ "user-defined literal in preprocessor expression");
switch (temp & CPP_N_CATEGORY)
{
case CPP_N_FLOATING:
diff --git a/libcpp/files.c b/libcpp/files.c
index d2c6b8bdecf..fad8b75fe57 100644
--- a/libcpp/files.c
+++ b/libcpp/files.c
@@ -1220,13 +1220,12 @@ cpp_make_system_header (cpp_reader *pfile, int syshdr, int externc)
{
int flags = 0;
const struct line_maps *line_table = pfile->line_table;
- const struct line_map *map = &line_table->maps[line_table->used-1];
-
+ const struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (line_table);
/* 1 = system header, 2 = system header to be treated as C. */
if (syshdr)
flags = 1 + (externc != 0);
pfile->buffer->sysp = flags;
- _cpp_do_file_change (pfile, LC_RENAME, map->to_file,
+ _cpp_do_file_change (pfile, LC_RENAME, ORDINARY_MAP_FILE_NAME (map),
SOURCE_LINE (map, pfile->line_table->highest_line), flags);
}
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 0e90821072f..518fe945ebb 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -131,6 +131,16 @@ struct _cpp_file;
TK(OBJC_STRING, LITERAL) /* @"string" - Objective-C */ \
TK(HEADER_NAME, LITERAL) /* <stdio.h> in #include */ \
\
+ TK(CHAR_USERDEF, LITERAL) /* 'char'_suffix - C++-0x */ \
+ TK(WCHAR_USERDEF, LITERAL) /* L'char'_suffix - C++-0x */ \
+ TK(CHAR16_USERDEF, LITERAL) /* u'char'_suffix - C++-0x */ \
+ TK(CHAR32_USERDEF, LITERAL) /* U'char'_suffix - C++-0x */ \
+ TK(STRING_USERDEF, LITERAL) /* "string"_suffix - C++-0x */ \
+ TK(WSTRING_USERDEF, LITERAL) /* L"string"_suffix - C++-0x */ \
+ TK(STRING16_USERDEF, LITERAL) /* u"string"_suffix - C++-0x */ \
+ TK(STRING32_USERDEF, LITERAL) /* U"string"_suffix - C++-0x */ \
+ TK(UTF8STRING_USERDEF,LITERAL) /* u8"string"_suffix - C++-0x */ \
+ \
TK(COMMENT, LITERAL) /* Only if output comments. */ \
/* SPELL_LITERAL happens to DTRT. */ \
TK(MACRO_ARG, NONE) /* Macro argument. */ \
@@ -157,7 +167,7 @@ enum cpp_ttype
/* C language kind, used when calling cpp_create_reader. */
enum c_lang {CLK_GNUC89 = 0, CLK_GNUC99, CLK_GNUC1X,
CLK_STDC89, CLK_STDC94, CLK_STDC99, CLK_STDC1X,
- CLK_GNUCXX, CLK_CXX98, CLK_GNUCXX0X, CLK_CXX0X, CLK_ASM};
+ CLK_GNUCXX, CLK_CXX98, CLK_GNUCXX11, CLK_CXX11, CLK_ASM};
/* Payload of a NUMBER, STRING, CHAR or COMMENT token. */
struct GTY(()) cpp_string {
@@ -392,6 +402,18 @@ struct cpp_options
/* Nonzero means we're looking at already preprocessed code, so don't
bother trying to do macro expansion and whatnot. */
unsigned char preprocessed;
+
+ /* Nonzero means we are going to emit debugging logs during
+ preprocessing. */
+ unsigned char debug;
+
+ /* Nonzero means we are tracking locations of tokens involved in
+ macro expansion. 1 Means we track the location in degraded mode
+ where we do not track locations of tokens resulting from the
+ expansion of arguments of function-like macro. 2 Means we do
+ track all macro expansions. This last option is the one that
+ consumes the highest amount of memory. */
+ unsigned char track_macro_expansion;
/* Nonzero means handle C++ alternate operator names. */
unsigned char operator_names;
@@ -402,6 +424,9 @@ struct cpp_options
/* True for traditional preprocessing. */
unsigned char traditional;
+ /* Nonzero for C++ 2011 Standard user-defnied literals. */
+ unsigned char user_literals;
+
/* Holds the name of the target (execution) character set. */
const char *narrow_charset;
@@ -817,13 +842,22 @@ struct cpp_num
#define CPP_N_FRACT 0x100000 /* Fract types. */
#define CPP_N_ACCUM 0x200000 /* Accum types. */
+#define CPP_N_USERDEF 0x1000000 /* C++0x user-defined literal. */
+
/* Classify a CPP_NUMBER token. The return value is a combination of
the flags from the above sets. */
-extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *);
+extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *,
+ const char **);
+
+/* Return the classification flags for a float suffix. */
+extern unsigned int cpp_interpret_float_suffix (const char *, size_t);
+
+/* Return the classification flags for an int suffix. */
+extern unsigned int cpp_interpret_int_suffix (const char *, size_t);
/* Evaluate a token classified as category CPP_N_INTEGER. */
extern cpp_num cpp_interpret_integer (cpp_reader *, const cpp_token *,
- unsigned int type);
+ unsigned int);
/* Sign extend a number, with PRECISION significant bits and all
others assumed clear, to fill out a cpp_num structure. */
@@ -993,4 +1027,20 @@ extern int cpp_read_state (cpp_reader *, const char *, FILE *,
extern void cpp_force_token_locations (cpp_reader *, source_location *);
extern void cpp_stop_forcing_token_locations (cpp_reader *);
+/* In expr.c */
+extern enum cpp_ttype cpp_userdef_string_remove_type
+ (enum cpp_ttype type);
+extern enum cpp_ttype cpp_userdef_string_add_type
+ (enum cpp_ttype type);
+extern enum cpp_ttype cpp_userdef_char_remove_type
+ (enum cpp_ttype type);
+extern enum cpp_ttype cpp_userdef_char_add_type
+ (enum cpp_ttype type);
+extern bool cpp_userdef_string_p
+ (enum cpp_ttype type);
+extern bool cpp_userdef_char_p
+ (enum cpp_ttype type);
+extern const char * cpp_get_userdef_suffix
+ (const cpp_token *);
+
#endif /* ! LIBCPP_CPPLIB_H */
diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h
index 3c84035e95f..112bc020309 100644
--- a/libcpp/include/line-map.h
+++ b/libcpp/include/line-map.h
@@ -1,5 +1,5 @@
/* Map logical line numbers to (source file, line number) pairs.
- Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010
+ Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -27,13 +27,22 @@ along with this program; see the file COPYING3. If not see
#define GTY(x) /* nothing */
#endif
-/* Reason for adding a line change with add_line_map (). LC_ENTER is
+/* Reason for creating a new line map with linemap_add. LC_ENTER is
when including a new file, e.g. a #include directive in C.
LC_LEAVE is when reaching a file's end. LC_RENAME is when a file
name or line number changes for neither of the above reasons
(e.g. a #line directive in C); LC_RENAME_VERBATIM is like LC_RENAME
- but a filename of "" is not specially interpreted as standard input. */
-enum lc_reason {LC_ENTER = 0, LC_LEAVE, LC_RENAME, LC_RENAME_VERBATIM};
+ but a filename of "" is not specially interpreted as standard
+ input. LC_ENTER_MACRO is when a macro expansion is about to start. */
+enum lc_reason
+{
+ LC_ENTER = 0,
+ LC_LEAVE,
+ LC_RENAME,
+ LC_RENAME_VERBATIM,
+ LC_ENTER_MACRO
+ /* FIXME: add support for stringize and paste. */
+};
/* The type of line numbers. */
typedef unsigned int linenum_type;
@@ -44,37 +53,218 @@ typedef unsigned int source_location;
/* Memory allocation function typedef. Works like xrealloc. */
typedef void *(*line_map_realloc) (void *, size_t);
-/* Physical source file TO_FILE at line TO_LINE at column 0 is represented
+/* Memory allocator function that returns the actual allocated size,
+ for a given requested allocation. */
+typedef size_t (*line_map_round_alloc_size_func) (size_t);
+
+/* An ordinary line map encodes physical source locations. Those
+ physical source locations are called "spelling locations".
+
+ Physical source file TO_FILE at line TO_LINE at column 0 is represented
by the logical START_LOCATION. TO_LINE+L at column C is represented by
START_LOCATION+(L*(1<<column_bits))+C, as long as C<(1<<column_bits),
and the result_location is less than the next line_map's start_location.
(The top line is line 1 and the leftmost column is column 1; line/column 0
means "entire file/line" or "unknown line/column" or "not applicable".)
- INCLUDED_FROM is an index into the set that gives the line mapping
- at whose end the current one was included. File(s) at the bottom
- of the include stack have this set to -1. REASON is the reason for
- creation of this line map, SYSP is one for a system header, two for
- a C system header file that therefore needs to be extern "C"
- protected in C++, and zero otherwise. */
-struct GTY(()) line_map {
+
+ The highest possible source location is MAX_SOURCE_LOCATION. */
+struct GTY(()) line_map_ordinary {
const char *to_file;
linenum_type to_line;
- source_location start_location;
+
+ /* An index into the set that gives the line mapping at whose end
+ the current one was included. File(s) at the bottom of the
+ include stack have this set to -1. */
int included_from;
- ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
- /* The sysp field isn't really needed now that it's in cpp_buffer. */
+
+ /* SYSP is one for a system header, two for a C system header file
+ that therefore needs to be extern "C" protected in C++, and zero
+ otherwise. This field isn't really needed now that it's in
+ cpp_buffer. */
unsigned char sysp;
+
/* Number of the low-order source_location bits used for a column number. */
unsigned int column_bits : 8;
};
-/* A set of chronological line_map structures. */
-struct GTY(()) line_maps {
+/* This is the highest possible source location encoded within an
+ ordinary or macro map. */
+#define MAX_SOURCE_LOCATION 0xFFFFFFFF
+
+struct cpp_hashnode;
+
+/* A macro line map encodes location of tokens coming from a macro
+ expansion.
+
+ Please note that this struct line_map_macro is a field of struct
+ line_map below, go read the comments of struct line_map below and
+ then come back here.
+
+ The offset from START_LOCATION is used to index into
+ MACRO_LOCATIONS; this holds the original location of the token. */
+struct GTY(()) line_map_macro {
+ /* The cpp macro which expansion gave birth to this macro map. */
+ struct cpp_hashnode * GTY ((nested_ptr (union tree_node,
+ "%h ? CPP_HASHNODE (GCC_IDENT_TO_HT_IDENT (%h)) : NULL",
+ "%h ? HT_IDENT_TO_GCC_IDENT (HT_NODE (%h)) : NULL")))
+ macro;
+
+ /* The number of tokens inside the replacement-list of MACRO. */
+ unsigned int n_tokens;
+
+ /* This array of location is actually an array of pairs of
+ locations. The elements inside it thus look like:
+
+ x0,y0, x1,y1, x2,y2, ...., xn,yn.
+
+ where n == n_tokens;
+
+ Remember that these xI,yI are collected when libcpp is about to
+ expand a given macro.
+
+ yI is the location in the macro definition, either of the token
+ itself or of a macro parameter that it replaces.
+
+ Imagine this:
+
+ #define PLUS(A, B) A + B <--- #1
+
+ int a = PLUS (1,2); <--- #2
+
+ There is a macro map for the expansion of PLUS in #2. PLUS is
+ expanded into its expansion-list. The expansion-list is the
+ replacement-list of PLUS where the macro parameters are replaced
+ with their arguments. So the replacement-list of PLUS is made of
+ the tokens:
+
+ A, +, B
+
+ and the expansion-list is made of the tokens:
+
+ 1, +, 2
+
+ Let's consider the case of token "+". Its y1 [yI for I == 1] is
+ its spelling location in #1.
+
+ y0 (thus for token "1") is the spelling location of A in #1.
+
+ And y2 (of token "2") is the spelling location of B in #1.
+
+ When the token is /not/ an argument for a macro, xI is the same
+ location as yI. Otherwise, xI is the location of the token
+ outside this macro expansion. If this macro was expanded from
+ another macro expansion, xI is a virtual location representing
+ the token in that macro expansion; otherwise, it is the spelling
+ location of the token.
+
+ Note that a virtual location is a location returned by
+ linemap_add_macro_token. It encodes the relevant locations (x,y
+ pairs) of that token accross the macro expansions from which it
+ (the token) might come from.
+
+ In the example above x1 (for token "+") is going to be the same
+ as y1. x0 is the spelling location for the argument token "1",
+ and x2 is the spelling location for the argument token "2". */
+ source_location * GTY((length ("2 * %h.n_tokens"))) macro_locations;
+
+ /* This is the location of the expansion point of the current macro
+ map. It's the location of the macro name. That location is held
+ by the map that was current right before the current one. It
+ could have been either a macro or an ordinary map, depending on
+ if we are in a nested expansion context not. */
+ source_location expansion;
+};
+
+/* A line_map encodes a sequence of locations.
+ There are two kinds of maps. Ordinary maps and macro expansion
+ maps, a.k.a macro maps.
+
+ A macro map encodes source locations of tokens that are part of a
+ macro replacement-list, at a macro expansion point. E.g, in:
+
+ #define PLUS(A,B) A + B
+
+ No macro map is going to be created there, because we are not at a
+ macro expansion point. We are at a macro /definition/ point. So the
+ locations of the tokens of the macro replacement-list (i.e, A + B)
+ will be locations in an ordinary map, not a macro map.
+
+ On the other hand, if we later do:
+
+ int a = PLUS (1,2);
+
+ The invocation of PLUS here is a macro expansion. So we are at a
+ macro expansion point. The preprocessor expands PLUS (1,2) and
+ replaces it with the tokens of its replacement-list: 1 + 2. A macro
+ map is going to be created to hold (or rather to map, haha ...) the
+ locations of the tokens 1, + and 2. The macro map also records the
+ location of the expansion point of PLUS. That location is mapped in
+ the map that is active right before the location of the invocation
+ of PLUS. */
+struct GTY(()) line_map {
+ source_location start_location;
+
+ /* The reason for creation of this line map. */
+ ENUM_BITFIELD (lc_reason) reason : CHAR_BIT;
+
+ union map_u {
+ struct line_map_ordinary GTY((tag ("0"))) ordinary;
+ struct line_map_macro GTY((tag ("1"))) macro;
+ } GTY((desc ("%1.reason == LC_ENTER_MACRO"))) d;
+};
+
+#define MAP_START_LOCATION(MAP) (MAP)->start_location
+
+#define ORDINARY_MAP_FILE_NAME(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.to_file
+
+#define ORDINARY_MAP_STARTING_LINE_NUMBER(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.to_line
+
+#define ORDINARY_MAP_INCLUDER_FILE_INDEX(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.included_from
+
+#define ORDINARY_MAP_IN_SYSTEM_HEADER_P(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.sysp
+
+#define ORDINARY_MAP_NUMBER_OF_COLUMN_BITS(MAP) \
+ linemap_check_ordinary (MAP)->d.ordinary.column_bits
+
+#define MACRO_MAP_MACRO(MAP) (MAP)->d.macro.macro
+
+#define MACRO_MAP_NUM_MACRO_TOKENS(MAP) (MAP)->d.macro.n_tokens
+
+#define MACRO_MAP_LOCATIONS(MAP) (MAP)->d.macro.macro_locations
+
+#define MACRO_MAP_EXPANSION_POINT_LOCATION(MAP) (MAP)->d.macro.expansion
+
+/* The abstraction of a set of location maps. There can be several
+ types of location maps. This abstraction contains the attributes
+ that are independent from the type of the map. */
+struct GTY(()) maps_info {
+ /* This array contains the different line maps.
+ A line map is created for the following events:
+ - when a new preprocessing unit start.
+ - when a preprocessing unit ends.
+ - when a macro expansion occurs. */
struct line_map * GTY ((length ("%h.used"))) maps;
+
+ /* The total number of allocated maps. */
unsigned int allocated;
+
+ /* The number of elements used in maps. This number is smaller
+ or equal to ALLOCATED. */
unsigned int used;
unsigned int cache;
+};
+
+/* A set of chronological line_map structures. */
+struct GTY(()) line_maps {
+
+ struct maps_info info_ordinary;
+
+ struct maps_info info_macro;
/* Depth of the include stack, including the current file. */
unsigned int depth;
@@ -95,14 +285,132 @@ struct GTY(()) line_maps {
/* If non-null, the allocator to use when resizing 'maps'. If null,
xrealloc is used. */
line_map_realloc reallocator;
+
+ /* The allocators' function used to know the actual size it
+ allocated, for a certain allocation size requested. */
+ line_map_round_alloc_size_func round_alloc_size;
};
+/* Returns the pointer to the memory region where information about
+ maps are stored in the line table SET. MACRO_MAP_P is a flag
+ telling if we want macro or ordinary maps. */
+#define LINEMAPS_MAP_INFO(SET, MACRO_MAP_P) \
+ ((MACRO_MAP_P) \
+ ? &((SET)->info_macro) \
+ : &((SET)->info_ordinary))
+
+/* Returns the pointer to the memory region where maps are stored in
+ the line table SET. MAP_KIND shall be TRUE if we are interested in
+ macro maps false otherwise. */
+#define LINEMAPS_MAPS(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->maps
+
+/* Returns the number of allocated maps so far. MAP_KIND shall be TRUE
+ if we are interested in macro maps, FALSE otherwise. */
+#define LINEMAPS_ALLOCATED(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->allocated
+
+/* Returns the number of used maps so far. MAP_KIND shall be TRUE if
+ we are interested in macro maps, FALSE otherwise.*/
+#define LINEMAPS_USED(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->used
+
+/* Returns the index of the last map that was looked up with
+ linemap_lookup. MAP_KIND shall be TRUE if we are interested in
+ macro maps, FALSE otherwise. */
+#define LINEMAPS_CACHE(SET, MAP_KIND) \
+ (LINEMAPS_MAP_INFO (SET, MAP_KIND))->cache
+
+/* Return the map at a given index. */
+#define LINEMAPS_MAP_AT(SET, MAP_KIND, INDEX) \
+ (&((LINEMAPS_MAPS (SET, MAP_KIND))[(INDEX)]))
+
+/* Returns the last map used in the line table SET. MAP_KIND
+ shall be TRUE if we are interested in macro maps, FALSE
+ otherwise.*/
+#define LINEMAPS_LAST_MAP(SET, MAP_KIND) \
+ LINEMAPS_MAP_AT (SET, MAP_KIND, (LINEMAPS_USED (SET, MAP_KIND) - 1))
+
+/* Returns the last map that was allocated in the line table SET.
+ MAP_KIND shall be TRUE if we are interested in macro maps, FALSE
+ otherwise.*/
+#define LINEMAPS_LAST_ALLOCATED_MAP(SET, MAP_KIND) \
+ LINEMAPS_MAP_AT (SET, MAP_KIND, LINEMAPS_ALLOCATED (SET, MAP_KIND) - 1)
+
+/* Returns a pointer to the memory region where ordinary maps are
+ allocated in the line table SET. */
+#define LINEMAPS_ORDINARY_MAPS(SET) \
+ LINEMAPS_MAPS (SET, false)
+
+/* Returns the INDEXth ordinary map. */
+#define LINEMAPS_ORDINARY_MAP_AT(SET, INDEX) \
+ LINEMAPS_MAP_AT (SET, false, INDEX)
+
+/* Return the number of ordinary maps allocated in the line table
+ SET. */
+#define LINEMAPS_ORDINARY_ALLOCATED(SET) \
+ LINEMAPS_ALLOCATED(SET, false)
+
+/* Return the number of ordinary maps used in the line table SET. */
+#define LINEMAPS_ORDINARY_USED(SET) \
+ LINEMAPS_USED(SET, false)
+
+/* Return the index of the last ordinary map that was looked up with
+ linemap_lookup. */
+#define LINEMAPS_ORDINARY_CACHE(SET) \
+ LINEMAPS_CACHE(SET, false)
+
+/* Returns a pointer to the last ordinary map used in the line table
+ SET. */
+#define LINEMAPS_LAST_ORDINARY_MAP(SET) \
+ LINEMAPS_LAST_MAP(SET, false)
+
+/* Returns a pointer to the last ordinary map allocated the line table
+ SET. */
+#define LINEMAPS_LAST_ALLOCATED_ORDINARY_MAP(SET) \
+ LINEMAPS_LAST_ALLOCATED_MAP(SET, false)
+
+/* Returns a pointer to the begining of the region where macro maps
+ are allcoated. */
+#define LINEMAPS_MACRO_MAPS(SET) \
+ LINEMAPS_MAPS(SET, true)
+
+/* Returns the INDEXth macro map. */
+#define LINEMAPS_MACRO_MAP_AT(SET, INDEX) \
+ LINEMAPS_MAP_AT (SET, true, INDEX)
+
+/* Returns the number of macro maps that were allocated in the line
+ table SET. */
+#define LINEMAPS_MACRO_ALLOCATED(SET) \
+ LINEMAPS_ALLOCATED(SET, true)
+
+/* Returns the number of macro maps used in the line table SET. */
+#define LINEMAPS_MACRO_USED(SET) \
+ LINEMAPS_USED(SET, true)
+
+/* Returns the index of the last macro map looked up with
+ linemap_lookup. */
+#define LINEMAPS_MACRO_CACHE(SET) \
+ LINEMAPS_CACHE(SET, true)
+
+/* Returns the lowest location [of a token resulting from macro
+ expansion] encoded in this line table. */
+#define LINEMAPS_MACRO_LOWEST_LOCATION(SET) \
+ (LINEMAPS_MACRO_USED (set) \
+ ? MAP_START_LOCATION (LINEMAPS_LAST_MACRO_MAP (set)) \
+ : MAX_SOURCE_LOCATION)
+
+/* Returns the last macro map used in the line table SET. */
+#define LINEMAPS_LAST_MACRO_MAP(SET) \
+ LINEMAPS_LAST_MAP (SET, true)
+
+/* Returns the last macro map allocated in the line table SET. */
+#define LINEMAPS_LAST_ALLOCATED_MACRO_MAP(SET) \
+ LINEMAPS_LAST_ALLOCATED_MAP (SET, true)
+
/* Initialize a line map set. */
extern void linemap_init (struct line_maps *);
-/* Free a line map set. */
-extern void linemap_free (struct line_maps *);
-
/* Check for and warn about line_maps entered but not exited. */
extern void linemap_check_files_exited (struct line_maps *);
@@ -117,10 +425,12 @@ extern source_location linemap_line_start
(struct line_maps *set, linenum_type to_line, unsigned int max_column_hint);
/* Add a mapping of logical source line to physical source file and
- line number.
+ line number. This function creates an "ordinary map", which is a
+ map that records locations of tokens that are not part of macro
+ replacement-lists present at a macro expansion point.
The text pointed to by TO_FILE must have a lifetime
- at least as long as the final call to lookup_line (). An empty
+ at least as long as the lifetime of SET. An empty
TO_FILE means standard input. If reason is LC_LEAVE, and
TO_FILE is NULL, then TO_FILE, TO_LINE and SYSP are given their
natural values considering the file we are returning to.
@@ -131,41 +441,268 @@ extern const struct line_map *linemap_add
(struct line_maps *, enum lc_reason, unsigned int sysp,
const char *to_file, linenum_type to_line);
-/* Given a logical line, returns the map from which the corresponding
- (source file, line) pair can be deduced. */
+/* Given a logical source location, returns the map which the
+ corresponding (source file, line, column) triplet can be deduced
+ from. Since the set is built chronologically, the logical lines are
+ monotonic increasing, and so the list is sorted and we can use a
+ binary search. If no line map have been allocated yet, this
+ function returns NULL. */
extern const struct line_map *linemap_lookup
(struct line_maps *, source_location);
+/* Returns TRUE if the line table set tracks token locations accross
+ macro expansion, FALSE otherwise. */
+bool linemap_tracks_macro_expansion_locs_p (struct line_maps *);
+
+/* Return TRUE if MAP encodes locations coming from a macro
+ replacement-list at macro expansion point. */
+bool linemap_macro_expansion_map_p (const struct line_map *);
+
+/* Return the name of the macro associated to MACRO_MAP. */
+const char* linemap_map_get_macro_name (const struct line_map*);
+
+/* Return a positive value if LOCATION is the locus of a token that is
+ located in a system header, O otherwise. It returns 1 if LOCATION
+ is the locus of a token that is located in a system header, and 2
+ if LOCATION is the locus of a token located in a C system header
+ that therefore needs to be extern "C" protected in C++.
+
+ Note that this function returns 1 if LOCATION belongs to a token
+ that is part of a macro replacement-list defined in a system
+ header, but expanded in a non-system file. */
+int linemap_location_in_system_header_p (struct line_maps *,
+ source_location);
+
+/* Return TRUE if LOCATION is a source code location of a token coming
+ from a macro replacement-list at a macro expansion point, FALSE
+ otherwise. */
+bool linemap_location_from_macro_expansion_p (struct line_maps *,
+ source_location);
+
/* source_location values from 0 to RESERVED_LOCATION_COUNT-1 will
be reserved for libcpp user as special values, no token from libcpp
will contain any of those locations. */
#define RESERVED_LOCATION_COUNT 2
/* Converts a map and a source_location to source line. */
-#define SOURCE_LINE(MAP, LOC) \
- ((((LOC) - (MAP)->start_location) >> (MAP)->column_bits) + (MAP)->to_line)
-
-#define SOURCE_COLUMN(MAP, LOC) \
- (((LOC) - (MAP)->start_location) & ((1 << (MAP)->column_bits) - 1))
-
-/* Returns the last source line within a map. This is the (last) line
- of the #include, or other directive, that caused a map change. */
+#define SOURCE_LINE(MAP, LOC) \
+ (((((LOC) - linemap_check_ordinary (MAP)->start_location) \
+ >> (MAP)->d.ordinary.column_bits) + (MAP)->d.ordinary.to_line))
+
+/* Convert a map and source_location to source column number. */
+#define SOURCE_COLUMN(MAP, LOC) \
+ ((((LOC) - linemap_check_ordinary (MAP)->start_location) \
+ & ((1 << (MAP)->d.ordinary.column_bits) - 1)))
+
+/* Returns the last source line number within an ordinary map. This
+ is the (last) line of the #include, or other directive, that caused
+ a map change. */
#define LAST_SOURCE_LINE(MAP) \
SOURCE_LINE (MAP, LAST_SOURCE_LINE_LOCATION (MAP))
+
+/* Return the last column number within an ordinary map. */
#define LAST_SOURCE_COLUMN(MAP) \
SOURCE_COLUMN (MAP, LAST_SOURCE_LINE_LOCATION (MAP))
-#define LAST_SOURCE_LINE_LOCATION(MAP) \
- ((((MAP)[1].start_location - 1 - (MAP)->start_location) \
- & ~((1 << (MAP)->column_bits) - 1)) \
- + (MAP)->start_location)
-/* Returns the map a given map was included from. */
-#define INCLUDED_FROM(SET, MAP) (&(SET)->maps[(MAP)->included_from])
+/* Return the location of the last source line within an ordinary
+ map. */
+#define LAST_SOURCE_LINE_LOCATION(MAP) \
+ ((((linemap_check_ordinary (MAP)[1].start_location - 1 \
+ - (MAP)->start_location) \
+ & ~((1 << (MAP)->d.ordinary.column_bits) - 1)) \
+ + (MAP)->start_location))
+
+/* Returns the map a given map was included from, or NULL if the map
+ belongs to the main file, i.e, a file that wasn't included by
+ another one. */
+#define INCLUDED_FROM(SET, MAP) \
+ ((linemap_check_ordinary (MAP)->d.ordinary.included_from == -1) \
+ ? NULL \
+ : (&LINEMAPS_ORDINARY_MAPS (SET)[(MAP)->d.ordinary.included_from]))
/* Nonzero if the map is at the bottom of the include stack. */
-#define MAIN_FILE_P(MAP) ((MAP)->included_from < 0)
+#define MAIN_FILE_P(MAP) \
+ ((linemap_check_ordinary (MAP)->d.ordinary.included_from < 0))
+
+#if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
+
+/* Assertion macro to be used in line-map code. */
+#define linemap_assert(EXPR) \
+ do { \
+ if (! (EXPR)) \
+ abort (); \
+ } while (0)
+
+/* Assert that MAP encodes locations of tokens that are not part of
+ the replacement-list of a macro expansion. */
+#define linemap_check_ordinary(LINE_MAP) __extension__ \
+ ({linemap_assert (!linemap_macro_expansion_map_p (LINE_MAP)); \
+ (LINE_MAP);})
+#else
+#define linemap_assert(EXPR)
+#define linemap_check_ordinary(LINE_MAP) (LINE_MAP)
+#endif
+/* Encode and return a source_location from a column number. The
+ source line considered is the last source line used to call
+ linemap_line_start, i.e, the last source line which a location was
+ encoded from. */
extern source_location
-linemap_position_for_column (struct line_maps *set, unsigned int to_column);
+linemap_position_for_column (struct line_maps *, unsigned int);
+
+/* Encode and return a source location from a given line and
+ column. */
+source_location linemap_position_for_line_and_column (struct line_map *,
+ linenum_type,
+ unsigned int);
+/* Return the file this map is for. */
+#define LINEMAP_FILE(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.to_file)
+
+/* Return the line number this map started encoding location from. */
+#define LINEMAP_LINE(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.to_line)
+
+/* Return a positive value if map encodes locations from a system
+ header, 0 otherwise. Returns 1 if MAP encodes locations in a
+ system header and 2 if it encodes locations in a C system header
+ that therefore needs to be extern "C" protected in C++. */
+#define LINEMAP_SYSP(MAP) \
+ (linemap_check_ordinary (MAP)->d.ordinary.sysp)
+
+/* Return a positive value if PRE denotes the location of a token that
+ comes before the token of POST, 0 if PRE denotes the location of
+ the same token as the token for POST, and a negative value
+ otherwise. */
+int linemap_compare_locations (struct line_maps *set,
+ source_location pre,
+ source_location post);
+
+/* Return TRUE if LOC_A denotes the location a token that comes
+ topogically before the token denoted by location LOC_B, or if they
+ are equal. */
+#define linemap_location_before_p(SET, LOC_A, LOC_B) \
+ (linemap_compare_locations ((SET), (LOC_A), (LOC_B)) >= 0)
+
+typedef struct
+{
+ /* The name of the source file involved. */
+ const char *file;
+
+ /* The line-location in the source file. */
+ int line;
+
+ int column;
+
+ /* In a system header?. */
+ bool sysp;
+} expanded_location;
+
+/* This is enum is used by the function linemap_resolve_location
+ below. The meaning of the values is explained in the comment of
+ that function. */
+enum location_resolution_kind
+{
+ LRK_MACRO_EXPANSION_POINT,
+ LRK_SPELLING_LOCATION,
+ LRK_MACRO_DEFINITION_LOCATION
+};
+
+/* Resolve a virtual location into either a spelling location, an
+ expansion point location or a token argument replacement point
+ location. Return the map that encodes the virtual location as well
+ as the resolved location.
+
+ If LOC is *NOT* the location of a token resulting from the
+ expansion of a macro, then the parameter LRK (which stands for
+ Location Resolution Kind) is ignored and the resulting location
+ just equals the one given in argument.
+
+ Now if LOC *IS* the location of a token resulting from the
+ expansion of a macro, this is what happens.
+
+ * If LRK is set to LRK_MACRO_EXPANSION_POINT
+ -------------------------------
+
+ The virtual location is resolved to the first macro expansion point
+ that led to this macro expansion.
+
+ * If LRK is set to LRK_SPELLING_LOCATION
+ -------------------------------------
+
+ The virtual location is resolved to the locus where the token has
+ been spelled in the source. This can follow through all the macro
+ expansions that led to the token.
+
+ * If LRK is set to LRK_MACRO_DEFINITION_LOCATION
+ --------------------------------------
+
+ The virtual location is resolved to the locus of the token in the
+ context of the macro definition.
+
+ If LOC is the locus of a token that is an argument of a
+ function-like macro [replacing a parameter in the replacement list
+ of the macro] the virtual location is resolved to the locus of the
+ parameter that is replaced, in the context of the definition of the
+ macro.
+
+ If LOC is the locus of a token that is not an argument of a
+ function-like macro, then the function behaves as if LRK was set to
+ LRK_SPELLING_LOCATION.
+
+ If LOC_MAP is not NULL, *LOC_MAP is set to the map encoding the
+ returned location. Note that if the resturned location wasn't originally
+ encoded by a map, the *MAP is set to NULL. This can happen if LOC
+ resolves to a location reserved for the client code, like
+ UNKNOWN_LOCATION or BUILTINS_LOCATION in GCC. */
+
+source_location linemap_resolve_location (struct line_maps *,
+ source_location loc,
+ enum location_resolution_kind lrk,
+ const struct line_map **loc_map);
+
+/* Suppose that LOC is the virtual location of a token coming from the
+ expansion of a macro M. This function then steps up to get the
+ location L of the point where M got expanded. If L is a spelling
+ location inside a macro expansion M', then this function returns
+ the point where M' was expanded. LOC_MAP is an output parameter.
+ When non-NULL, *LOC_MAP is set the the map of the returned
+ location. */
+source_location linemap_unwind_toward_expansion (struct line_maps *,
+ source_location loc,
+ const struct line_map **loc_map);
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC must be a spelling (non-virtual) location. If
+ it's a location < RESERVED_LOCATION_COUNT a zeroed expanded source
+ location is returned. */
+expanded_location linemap_expand_location (struct line_maps *,
+ const struct line_map *,
+ source_location loc);
+
+/* Statistics about maps allocation and usage as returned by
+ linemap_get_statistics. */
+struct linemap_stats
+{
+ long num_ordinary_maps_allocated;
+ long num_ordinary_maps_used;
+ long ordinary_maps_allocated_size;
+ long ordinary_maps_used_size;
+ long num_expanded_macros;
+ long num_macro_tokens;
+ long num_macro_maps_used;
+ long macro_maps_allocated_size;
+ long macro_maps_used_size;
+ long macro_maps_locations_size;
+ long duplicated_macro_maps_locations_size;
+};
+
+/* Compute and return statistics about the memory consumption of some
+ parts of the line table SET. */
+void linemap_get_statistics (struct line_maps *, struct linemap_stats *);
+
+/* Dump debugging information about source location LOC into the file
+ stream STREAM. SET is the line map set LOC comes from. */
+void linemap_dump_location (struct line_maps *, source_location, FILE *);
#endif /* !LIBCPP_LINE_MAP_H */
diff --git a/libcpp/init.c b/libcpp/init.c
index c5c53256d35..9101b34e086 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -80,24 +80,25 @@ struct lang_flags
char digraphs;
char uliterals;
char rliterals;
+ char user_literals;
};
static const struct lang_flags lang_defaults[] =
-{ /* c99 c++ xnum xid std // digr ulit rlit */
- /* GNUC89 */ { 0, 0, 1, 0, 0, 1, 1, 0, 0 },
- /* GNUC99 */ { 1, 0, 1, 0, 0, 1, 1, 1, 1 },
- /* GNUC1X */ { 1, 0, 1, 0, 0, 1, 1, 1, 1 },
- /* STDC89 */ { 0, 0, 0, 0, 1, 0, 0, 0, 0 },
- /* STDC94 */ { 0, 0, 0, 0, 1, 0, 1, 0, 0 },
- /* STDC99 */ { 1, 0, 1, 0, 1, 1, 1, 0, 0 },
- /* STDC1X */ { 1, 0, 1, 0, 1, 1, 1, 1, 0 },
- /* GNUCXX */ { 0, 1, 1, 0, 0, 1, 1, 0, 0 },
- /* CXX98 */ { 0, 1, 1, 0, 1, 1, 1, 0, 0 },
- /* GNUCXX0X */ { 1, 1, 1, 0, 0, 1, 1, 1, 1 },
- /* CXX0X */ { 1, 1, 1, 0, 1, 1, 1, 1, 1 },
- /* ASM */ { 0, 0, 1, 0, 0, 1, 0, 0, 0 }
- /* xid should be 1 for GNUC99, STDC99, GNUCXX, CXX98, GNUCXX0X, and
- CXX0X when no longer experimental (when all uses of identifiers
+{ /* c99 c++ xnum xid std // digr ulit rlit user_literals */
+ /* GNUC89 */ { 0, 0, 1, 0, 0, 1, 1, 0, 0, 0 },
+ /* GNUC99 */ { 1, 0, 1, 0, 0, 1, 1, 1, 1, 0 },
+ /* GNUC1X */ { 1, 0, 1, 0, 0, 1, 1, 1, 1, 0 },
+ /* STDC89 */ { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
+ /* STDC94 */ { 0, 0, 0, 0, 1, 0, 1, 0, 0, 0 },
+ /* STDC99 */ { 1, 0, 1, 0, 1, 1, 1, 0, 0, 0 },
+ /* STDC1X */ { 1, 0, 1, 0, 1, 1, 1, 1, 0, 0 },
+ /* GNUCXX */ { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0 },
+ /* CXX98 */ { 0, 1, 1, 0, 1, 1, 1, 0, 0, 0 },
+ /* GNUCXX11 */ { 1, 1, 1, 0, 0, 1, 1, 1, 1, 1 },
+ /* CXX11 */ { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1 },
+ /* ASM */ { 0, 0, 1, 0, 0, 1, 0, 0, 0, 0 }
+ /* xid should be 1 for GNUC99, STDC99, GNUCXX, CXX98, GNUCXX11, and
+ CXX11 when no longer experimental (when all uses of identifiers
in the compiler have been audited for correct handling of
extended identifiers). */
};
@@ -120,6 +121,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang)
CPP_OPTION (pfile, digraphs) = l->digraphs;
CPP_OPTION (pfile, uliterals) = l->uliterals;
CPP_OPTION (pfile, rliterals) = l->rliterals;
+ CPP_OPTION (pfile, user_literals) = l->user_literals;
}
/* Initialize library global state. */
@@ -154,6 +156,7 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
init_library ();
pfile = XCNEW (cpp_reader);
+ memset (&pfile->base_context, 0, sizeof (pfile->base_context));
cpp_set_lang (pfile, lang);
CPP_OPTION (pfile, warn_multichar) = 1;
@@ -213,7 +216,7 @@ cpp_create_reader (enum c_lang lang, hash_table *table,
/* Initialize the base context. */
pfile->context = &pfile->base_context;
- pfile->base_context.macro = 0;
+ pfile->base_context.c.macro = 0;
pfile->base_context.prev = pfile->base_context.next = 0;
/* Aligned and unaligned storage. */
@@ -458,7 +461,13 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
_cpp_define_builtin (pfile, "__STDC__ 1");
if (CPP_OPTION (pfile, cplusplus))
- _cpp_define_builtin (pfile, "__cplusplus 199711L");
+ {
+ if (CPP_OPTION (pfile, lang) == CLK_CXX11
+ || CPP_OPTION (pfile, lang) == CLK_GNUCXX11)
+ _cpp_define_builtin (pfile, "__cplusplus 201103L");
+ else
+ _cpp_define_builtin (pfile, "__cplusplus 199711L");
+ }
else if (CPP_OPTION (pfile, lang) == CLK_ASM)
_cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
else if (CPP_OPTION (pfile, lang) == CLK_STDC94)
@@ -586,7 +595,9 @@ cpp_read_main_file (cpp_reader *pfile, const char *fname)
if (CPP_OPTION (pfile, preprocessed))
{
read_original_filename (pfile);
- fname = pfile->line_table->maps[pfile->line_table->used-1].to_file;
+ fname =
+ ORDINARY_MAP_FILE_NAME
+ ((LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table)));
}
return fname;
}
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 6c423f056bc..986d167d60e 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -1,6 +1,6 @@
/* Part of CPP library.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
- 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2008, 2009, 2010, 2011 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
@@ -67,7 +67,8 @@ struct cset_converter
#define CPP_INCREMENT_LINE(PFILE, COLS_HINT) do { \
const struct line_maps *line_table = PFILE->line_table; \
- const struct line_map *map = &line_table->maps[line_table->used-1]; \
+ const struct line_map *map = \
+ LINEMAPS_LAST_ORDINARY_MAP (line_table); \
linenum_type line = SOURCE_LINE (map, line_table->highest_line); \
linemap_line_start (PFILE->line_table, line + 1, COLS_HINT); \
} while (0)
@@ -138,6 +139,40 @@ struct tokenrun
#define CUR(c) ((c)->u.trad.cur)
#define RLIMIT(c) ((c)->u.trad.rlimit)
+/* This describes some additional data that is added to the macro
+ token context of type cpp_context, when -ftrack-macro-expansion is
+ on. */
+typedef struct
+{
+ /* The node of the macro we are referring to. */
+ cpp_hashnode *macro_node;
+ /* This buffer contains an array of virtual locations. The virtual
+ location at index 0 is the virtual location of the token at index
+ 0 in the current instance of cpp_context; similarly for all the
+ other virtual locations. */
+ source_location *virt_locs;
+ /* This is a pointer to the current virtual location. This is used
+ to iterate over the virtual locations while we iterate over the
+ tokens they belong to. */
+ source_location *cur_virt_loc;
+} macro_context;
+
+/* The kind of tokens carried by a cpp_context. */
+enum context_tokens_kind {
+ /* This is the value of cpp_context::tokens_kind if u.iso.first
+ contains an instance of cpp_token **. */
+ TOKENS_KIND_INDIRECT,
+ /* This is the value of cpp_context::tokens_kind if u.iso.first
+ contains an instance of cpp_token *. */
+ TOKENS_KIND_DIRECT,
+ /* This is the value of cpp_context::tokens_kind when the token
+ context contains tokens resulting from macro expansion. In that
+ case struct cpp_context::macro points to an instance of struct
+ macro_context. This is used only when the
+ -ftrack-macro-expansion flag is on. */
+ TOKENS_KIND_EXTENDED
+};
+
typedef struct cpp_context cpp_context;
struct cpp_context
{
@@ -167,11 +202,24 @@ struct cpp_context
When the context is popped, the buffer is released. */
_cpp_buff *buff;
- /* For a macro context, the macro node, otherwise NULL. */
- cpp_hashnode *macro;
+ /* If tokens_kind is TOKEN_KIND_EXTENDED, then (as we thus are in a
+ macro context) this is a pointer to an instance of macro_context.
+ Otherwise if tokens_kind is *not* TOKEN_KIND_EXTENDED, then, if
+ we are in a macro context, this is a pointer to an instance of
+ cpp_hashnode, representing the name of the macro this context is
+ for. If we are not in a macro context, then this is just NULL.
+ Note that when tokens_kind is TOKEN_KIND_EXTENDED, the memory
+ used by the instance of macro_context pointed to by this member
+ is de-allocated upon de-allocation of the instance of struct
+ cpp_context. */
+ union
+ {
+ macro_context *mc;
+ cpp_hashnode *macro;
+ } c;
- /* True if utoken element is token, else ptoken. */
- bool direct_p;
+ /* This determines the type of tokens held by this context. */
+ enum context_tokens_kind tokens_kind;
};
struct lexer_state
@@ -604,6 +652,7 @@ extern cpp_token *_cpp_lex_direct (cpp_reader *);
extern int _cpp_equiv_tokens (const cpp_token *, const cpp_token *);
extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
extern cpp_hashnode *_cpp_lex_identifier (cpp_reader *, const char *);
+extern int _cpp_remaining_tokens_num_in_context (cpp_context *);
/* In init.c. */
extern void _cpp_maybe_push_include_file (cpp_reader *);
@@ -690,8 +739,8 @@ static inline int ustrcmp (const unsigned char *, const unsigned char *);
static inline int ustrncmp (const unsigned char *, const unsigned char *,
size_t);
static inline size_t ustrlen (const unsigned char *);
-static inline unsigned char *uxstrdup (const unsigned char *);
-static inline unsigned char *ustrchr (const unsigned char *, int);
+static inline const unsigned char *uxstrdup (const unsigned char *);
+static inline const unsigned char *ustrchr (const unsigned char *, int);
static inline int ufputs (const unsigned char *, FILE *);
/* Use a const char for the second parameter since it is usually a literal. */
@@ -721,16 +770,16 @@ ustrlen (const unsigned char *s1)
return strlen ((const char *)s1);
}
-static inline unsigned char *
+static inline const unsigned char *
uxstrdup (const unsigned char *s1)
{
- return (unsigned char *) xstrdup ((const char *)s1);
+ return (unsigned const char *) xstrdup ((const char *)s1);
}
-static inline unsigned char *
+static inline const unsigned char *
ustrchr (const unsigned char *s1, int c)
{
- return (unsigned char *) strchr ((const char *)s1, c);
+ return (const unsigned char *) strchr ((const char *)s1, c);
}
static inline int
@@ -739,6 +788,76 @@ ufputs (const unsigned char *s, FILE *f)
return fputs ((const char *)s, f);
}
+ /* In line-map.c. */
+
+/* Create a macro map. A macro map encodes source locations of tokens
+ that are part of a macro replacement-list, at a macro expansion
+ point. See the extensive comments of struct line_map and struct
+ line_map_macro, in line-map.h.
+
+ This map shall be created when the macro is expanded. The map
+ encodes the source location of the expansion point of the macro as
+ well as the "original" source location of each token that is part
+ of the macro replacement-list. If a macro is defined but never
+ expanded, it has no macro map. SET is the set of maps the macro
+ map should be part of. MACRO_NODE is the macro which the new macro
+ map should encode source locations for. EXPANSION is the location
+ of the expansion point of MACRO. For function-like macros
+ invocations, it's best to make it point to the closing parenthesis
+ of the macro, rather than the the location of the first character
+ of the macro. NUM_TOKENS is the number of tokens that are part of
+ the replacement-list of MACRO. */
+const struct line_map *linemap_enter_macro (struct line_maps *,
+ struct cpp_hashnode*,
+ source_location,
+ unsigned int);
+
+/* Create and return a virtual location for a token that is part of a
+ macro expansion-list at a macro expansion point. See the comment
+ inside struct line_map_macro to see what an expansion-list exactly
+ is.
+
+ A call to this function must come after a call to
+ linemap_enter_macro.
+
+ MAP is the map into which the source location is created. TOKEN_NO
+ is the index of the token in the macro replacement-list, starting
+ at number 0.
+
+ ORIG_LOC is the location of the token outside of this macro
+ expansion. If the token comes originally from the macro
+ definition, it is the locus in the macro definition; otherwise it
+ is a location in the context of the caller of this macro expansion
+ (which is a virtual location or a source location if the caller is
+ itself a macro expansion or not).
+
+ MACRO_DEFINITION_LOC is the location in the macro definition,
+ either of the token itself or of a macro parameter that it
+ replaces. */
+source_location linemap_add_macro_token (const struct line_map *,
+ unsigned int,
+ source_location,
+ source_location);
+
+/* Return the source line number corresponding to source location
+ LOCATION. SET is the line map set LOCATION comes from. If
+ LOCATION is the location of token that is part of the
+ expansion-list of a macro expansion return the line number of the
+ macro expansion point. */
+int linemap_get_expansion_line (struct line_maps *,
+ source_location);
+
+/* Return the path of the file corresponding to source code location
+ LOCATION.
+
+ If LOCATION is the location of a token that is part of the
+ replacement-list of a macro expansion return the file path of the
+ macro expansion point.
+
+ SET is the line map set LOCATION comes from. */
+const char* linemap_get_expansion_filename (struct line_maps *,
+ source_location);
+
#ifdef __cplusplus
}
#endif
diff --git a/libcpp/lex.c b/libcpp/lex.c
index 75b2b1dc7ff..fcec329d8b4 100644
--- a/libcpp/lex.c
+++ b/libcpp/lex.c
@@ -1478,6 +1478,18 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base,
}
break_outer_loop:
+ if (CPP_OPTION (pfile, user_literals))
+ {
+ /* Grab user defined literal suffix. */
+ if (ISIDST (*cur))
+ {
+ type = cpp_userdef_string_add_type (type);
+ ++cur;
+ }
+ while (ISIDNUM (*cur))
+ ++cur;
+ }
+
pfile->buffer->cur = cur;
if (first_buff == NULL)
create_literal (pfile, token, base, cur - base, type);
@@ -1581,6 +1593,19 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
cpp_error (pfile, CPP_DL_PEDWARN, "missing terminating %c character",
(int) terminator);
+ if (CPP_OPTION (pfile, user_literals))
+ {
+ /* Grab user defined literal suffix. */
+ if (ISIDST (*cur))
+ {
+ type = cpp_userdef_char_add_type (type);
+ type = cpp_userdef_string_add_type (type);
+ ++cur;
+ }
+ while (ISIDNUM (*cur))
+ ++cur;
+ }
+
pfile->buffer->cur = cur;
create_literal (pfile, token, base, cur - base, type);
}
@@ -1703,6 +1728,34 @@ next_tokenrun (tokenrun *run)
return run->next;
}
+/* Return the number of not yet processed token in a given
+ context. */
+int
+_cpp_remaining_tokens_num_in_context (cpp_context *context)
+{
+ if (context->tokens_kind == TOKENS_KIND_DIRECT)
+ return (LAST (context).token - FIRST (context).token);
+ else if (context->tokens_kind == TOKENS_KIND_INDIRECT
+ || context->tokens_kind == TOKENS_KIND_EXTENDED)
+ return (LAST (context).ptoken - FIRST (context).ptoken);
+ else
+ abort ();
+}
+
+/* Returns the token present at index INDEX in a given context. If
+ INDEX is zero, the next token to be processed is returned. */
+static const cpp_token*
+_cpp_token_from_context_at (cpp_context *context, int index)
+{
+ if (context->tokens_kind == TOKENS_KIND_DIRECT)
+ return &(FIRST (context).token[index]);
+ else if (context->tokens_kind == TOKENS_KIND_INDIRECT
+ || context->tokens_kind == TOKENS_KIND_EXTENDED)
+ return FIRST (context).ptoken[index];
+ else
+ abort ();
+}
+
/* Look ahead in the input stream. */
const cpp_token *
cpp_peek_token (cpp_reader *pfile, int index)
@@ -1714,15 +1767,10 @@ cpp_peek_token (cpp_reader *pfile, int index)
/* First, scan through any pending cpp_context objects. */
while (context->prev)
{
- ptrdiff_t sz = (context->direct_p
- ? LAST (context).token - FIRST (context).token
- : LAST (context).ptoken - FIRST (context).ptoken);
+ ptrdiff_t sz = _cpp_remaining_tokens_num_in_context (context);
if (index < (int) sz)
- return (context->direct_p
- ? FIRST (context).token + index
- : *(FIRST (context).ptoken + index));
-
+ return _cpp_token_from_context_at (context, index);
index -= (int) sz;
context = context->prev;
}
diff --git a/libcpp/line-map.c b/libcpp/line-map.c
index 2a0749aad2e..23a0347cb5f 100644
--- a/libcpp/line-map.c
+++ b/libcpp/line-map.c
@@ -1,5 +1,5 @@
/* Map logical line numbers to (source file, line number) pairs.
- Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009
+ Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -23,24 +23,41 @@ along with this program; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "line-map.h"
+#include "cpplib.h"
+#include "internal.h"
static void trace_include (const struct line_maps *, const struct line_map *);
+static const struct line_map * linemap_ordinary_map_lookup (struct line_maps *,
+ source_location);
+static const struct line_map* linemap_macro_map_lookup (struct line_maps *,
+ source_location);
+static source_location linemap_macro_map_loc_to_def_point
+(const struct line_map*, source_location);
+static source_location linemap_macro_map_loc_unwind_toward_spelling
+(const struct line_map*, source_location);
+static source_location linemap_macro_map_loc_to_exp_point
+(const struct line_map*, source_location);
+static source_location linemap_macro_loc_to_spelling_point
+(struct line_maps *, source_location, const struct line_map **);
+static source_location linemap_macro_loc_to_def_point (struct line_maps *,
+ source_location,
+ const struct line_map **);
+static source_location linemap_macro_loc_to_exp_point (struct line_maps *,
+ source_location,
+ const struct line_map **);
+
+/* Counters defined in macro.c. */
+extern unsigned num_expanded_macros_counter;
+extern unsigned num_macro_tokens_counter;
/* Initialize a line map set. */
void
linemap_init (struct line_maps *set)
{
- set->maps = NULL;
- set->allocated = 0;
- set->used = 0;
- set->trace_includes = false;
- set->depth = 0;
- set->cache = 0;
+ memset (set, 0, sizeof (struct line_maps));
set->highest_location = RESERVED_LOCATION_COUNT - 1;
set->highest_line = RESERVED_LOCATION_COUNT - 1;
- set->max_column_hint = 0;
- set->reallocator = 0;
}
/* Check for and warn about line_maps entered but not exited. */
@@ -51,23 +68,82 @@ linemap_check_files_exited (struct line_maps *set)
struct line_map *map;
/* Depending upon whether we are handling preprocessed input or
not, this can be a user error or an ICE. */
- for (map = &set->maps[set->used - 1]; ! MAIN_FILE_P (map);
+ for (map = LINEMAPS_LAST_ORDINARY_MAP (set);
+ ! MAIN_FILE_P (map);
map = INCLUDED_FROM (set, map))
fprintf (stderr, "line-map.c: file \"%s\" entered but not left\n",
- map->to_file);
+ ORDINARY_MAP_FILE_NAME (map));
}
-
-/* Free a line map set. */
-void
-linemap_free (struct line_maps *set)
+/* Create a new line map in the line map set SET, and return it.
+ REASON is the reason of creating the map. It determines the type
+ of map created (ordinary or macro map). Note that ordinary maps and
+ macro maps are allocated in different memory location. */
+
+static struct line_map *
+new_linemap (struct line_maps *set,
+ enum lc_reason reason)
{
- if (set->maps)
+ /* Depending on this variable, a macro map would be allocated in a
+ different memory location than an ordinary map. */
+ bool macro_map_p = (reason == LC_ENTER_MACRO);
+ struct line_map *result;
+
+ if (LINEMAPS_USED (set, macro_map_p) == LINEMAPS_ALLOCATED (set, macro_map_p))
{
- linemap_check_files_exited (set);
+ /* We ran out of allocated line maps. Let's allocate more. */
+ unsigned alloc_size;
+
+ line_map_realloc reallocator
+ = set->reallocator ? set->reallocator : xrealloc;
+ line_map_round_alloc_size_func round_alloc_size =
+ set->round_alloc_size;
+
+ /* We are going to execute some dance to try to reduce the
+ overhead of the memory allocator, in case we are using the
+ ggc-page.c one.
+
+ The actual size of memory we are going to get back from the
+ allocator is the smallest power of 2 that is greater than the
+ size we requested. So let's consider that size then. */
+
+ alloc_size =
+ (2 * LINEMAPS_ALLOCATED (set, macro_map_p) + 256)
+ * sizeof (struct line_map);
- free (set->maps);
+ /* Get the actual size of memory that is going to be allocated
+ by the allocator. */
+ alloc_size = round_alloc_size (alloc_size);
+
+ /* Now alloc_size contains the exact memory size we would get if
+ we have asked for the initial alloc_size amount of memory.
+ Let's get back to the number of macro map that amounts
+ to. */
+ LINEMAPS_ALLOCATED (set, macro_map_p) =
+ alloc_size / (sizeof (struct line_map));
+
+ /* And now let's really do the re-allocation. */
+ LINEMAPS_MAPS (set, macro_map_p) =
+ (struct line_map *) (*reallocator)
+ (LINEMAPS_MAPS (set, macro_map_p),
+ (LINEMAPS_ALLOCATED (set, macro_map_p)
+ * sizeof (struct line_map)));
+
+ result =
+ &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
+ memset (result, 0,
+ ((LINEMAPS_ALLOCATED (set, macro_map_p)
+ - LINEMAPS_USED (set, macro_map_p))
+ * sizeof (struct line_map)));
}
+ else
+ result =
+ &LINEMAPS_MAPS (set, macro_map_p)[LINEMAPS_USED (set, macro_map_p)];
+
+ LINEMAPS_USED (set, macro_map_p)++;
+
+ result->reason = reason;
+ return result;
}
/* Add a mapping of logical source line to physical source file and
@@ -90,23 +166,24 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
struct line_map *map;
source_location start_location = set->highest_location + 1;
- if (set->used && start_location < set->maps[set->used - 1].start_location)
- abort ();
+ linemap_assert (!(LINEMAPS_ORDINARY_USED (set)
+ && (start_location
+ < MAP_START_LOCATION (LINEMAPS_LAST_ORDINARY_MAP (set)))));
- if (set->used == set->allocated)
+ /* When we enter the file for the first time reason cannot be
+ LC_RENAME. */
+ linemap_assert (!(set->depth == 0 && reason == LC_RENAME));
+
+ /* If we are leaving the main file, return a NULL map. */
+ if (reason == LC_LEAVE
+ && MAIN_FILE_P (LINEMAPS_LAST_ORDINARY_MAP (set))
+ && to_file == NULL)
{
- line_map_realloc reallocator
- = set->reallocator ? set->reallocator : xrealloc;
- set->allocated = 2 * set->allocated + 256;
- set->maps
- = (struct line_map *) (*reallocator) (set->maps,
- set->allocated
- * sizeof (struct line_map));
- memset (&set->maps[set->used], 0, ((set->allocated - set->used)
- * sizeof (struct line_map)));
+ set->depth--;
+ return NULL;
}
- map = &set->maps[set->used];
+ map = new_linemap (set, reason);
if (to_file && *to_file == '\0' && reason != LC_RENAME_VERBATIM)
to_file = "<stdin>";
@@ -114,29 +191,35 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
if (reason == LC_RENAME_VERBATIM)
reason = LC_RENAME;
- if (set->depth == 0 && reason == LC_RENAME)
- abort ();
-
if (reason == LC_LEAVE)
{
+ /* When we are just leaving an "included" file, and jump to the next
+ location inside the "includer" right after the #include
+ "included", this variable points the map in use right before the
+ #include "included", inside the same "includer" file. */
struct line_map *from;
bool error;
if (MAIN_FILE_P (map - 1))
{
- if (to_file == NULL)
- {
- set->depth--;
- return NULL;
- }
+ /* So this _should_ means we are leaving the main file --
+ effectively ending the compilation unit. But to_file not
+ being NULL means the caller thinks we are leaving to
+ another file. This is an erroneous behaviour but we'll
+ try to recover from it. Let's pretend we are not leaving
+ the main file. */
error = true;
reason = LC_RENAME;
from = map - 1;
}
else
{
+ /* (MAP - 1) points to the map we are leaving. The
+ map from which (MAP - 1) got included should be the map
+ that comes right before MAP in the same file. */
from = INCLUDED_FROM (set, map - 1);
- error = to_file && filename_cmp (from->to_file, to_file);
+ error = to_file && filename_cmp (ORDINARY_MAP_FILE_NAME (from),
+ to_file);
}
/* Depending upon whether we are handling preprocessed input or
@@ -148,55 +231,176 @@ linemap_add (struct line_maps *set, enum lc_reason reason,
/* A TO_FILE of NULL is special - we use the natural values. */
if (error || to_file == NULL)
{
- to_file = from->to_file;
+ to_file = ORDINARY_MAP_FILE_NAME (from);
to_line = SOURCE_LINE (from, from[1].start_location);
- sysp = from->sysp;
+ sysp = ORDINARY_MAP_IN_SYSTEM_HEADER_P (from);
}
}
- map->reason = reason;
- map->sysp = sysp;
- map->start_location = start_location;
- map->to_file = to_file;
- map->to_line = to_line;
- set->cache = set->used++;
- map->column_bits = 0;
+ linemap_assert (reason != LC_ENTER_MACRO);
+ ORDINARY_MAP_IN_SYSTEM_HEADER_P (map) = sysp;
+ MAP_START_LOCATION (map) = start_location;
+ ORDINARY_MAP_FILE_NAME (map) = to_file;
+ ORDINARY_MAP_STARTING_LINE_NUMBER (map) = to_line;
+ LINEMAPS_ORDINARY_CACHE (set) = LINEMAPS_ORDINARY_USED (set) - 1;
+ ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = 0;
set->highest_location = start_location;
set->highest_line = start_location;
set->max_column_hint = 0;
if (reason == LC_ENTER)
{
- map->included_from = set->depth == 0 ? -1 : (int) (set->used - 2);
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ set->depth == 0 ? -1 : (int) (LINEMAPS_ORDINARY_USED (set) - 2);
set->depth++;
if (set->trace_includes)
trace_include (set, map);
}
else if (reason == LC_RENAME)
- map->included_from = map[-1].included_from;
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (&map[-1]);
else if (reason == LC_LEAVE)
{
set->depth--;
- map->included_from = INCLUDED_FROM (set, map - 1)->included_from;
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (map) =
+ ORDINARY_MAP_INCLUDER_FILE_INDEX (INCLUDED_FROM (set, map - 1));
}
return map;
}
+/* Returns TRUE if the line table set tracks token locations accross
+ macro expansion, FALSE otherwise. */
+
+bool
+linemap_tracks_macro_expansion_locs_p (struct line_maps *set)
+{
+ return LINEMAPS_MACRO_MAPS (set) != NULL;
+}
+
+/* Create a macro map. A macro map encodes source locations of tokens
+ that are part of a macro replacement-list, at a macro expansion
+ point. See the extensive comments of struct line_map and struct
+ line_map_macro, in line-map.h.
+
+ This map shall be created when the macro is expanded. The map
+ encodes the source location of the expansion point of the macro as
+ well as the "original" source location of each token that is part
+ of the macro replacement-list. If a macro is defined but never
+ expanded, it has no macro map. SET is the set of maps the macro
+ map should be part of. MACRO_NODE is the macro which the new macro
+ map should encode source locations for. EXPANSION is the location
+ of the expansion point of MACRO. For function-like macros
+ invocations, it's best to make it point to the closing parenthesis
+ of the macro, rather than the the location of the first character
+ of the macro. NUM_TOKENS is the number of tokens that are part of
+ the replacement-list of MACRO.
+
+ Note that when we run out of the integer space available for source
+ locations, this function returns NULL. In that case, callers of
+ this function cannot encode {line,column} pairs into locations of
+ macro tokens anymore. */
+
+const struct line_map *
+linemap_enter_macro (struct line_maps *set, struct cpp_hashnode *macro_node,
+ source_location expansion, unsigned int num_tokens)
+{
+ struct line_map *map;
+ source_location start_location;
+ line_map_realloc reallocator
+ = set->reallocator ? set->reallocator : xrealloc;
+
+ start_location = LINEMAPS_MACRO_LOWEST_LOCATION (set) - num_tokens;
+
+ if (start_location <= set->highest_line
+ || start_location > LINEMAPS_MACRO_LOWEST_LOCATION (set))
+ /* We ran out of macro map space. */
+ return NULL;
+
+ map = new_linemap (set, LC_ENTER_MACRO);
+
+ MAP_START_LOCATION (map) = start_location;
+ MACRO_MAP_MACRO (map) = macro_node;
+ MACRO_MAP_NUM_MACRO_TOKENS (map) = num_tokens;
+ MACRO_MAP_LOCATIONS (map)
+ = (source_location*) reallocator (NULL,
+ 2 * num_tokens
+ * sizeof (source_location));
+ MACRO_MAP_EXPANSION_POINT_LOCATION (map) = expansion;
+ memset (MACRO_MAP_LOCATIONS (map), 0,
+ num_tokens * sizeof (source_location));
+
+ LINEMAPS_MACRO_CACHE (set) = LINEMAPS_MACRO_USED (set) - 1;
+ set->max_column_hint = 0;
+
+ return map;
+}
+
+/* Create and return a virtual location for a token that is part of a
+ macro expansion-list at a macro expansion point. See the comment
+ inside struct line_map_macro to see what an expansion-list exactly
+ is.
+
+ A call to this function must come after a call to
+ linemap_enter_macro.
+
+ MAP is the map into which the source location is created. TOKEN_NO
+ is the index of the token in the macro replacement-list, starting
+ at number 0.
+
+ ORIG_LOC is the location of the token outside of this macro
+ expansion. If the token comes originally from the macro
+ definition, it is the locus in the macro definition; otherwise it
+ is a location in the context of the caller of this macro expansion
+ (which is a virtual location or a source location if the caller is
+ itself a macro expansion or not).
+
+ MACRO_DEFINITION_LOC is the location in the macro definition,
+ either of the token itself or of a macro parameter that it
+ replaces. */
+
+source_location
+linemap_add_macro_token (const struct line_map *map,
+ unsigned int token_no,
+ source_location orig_loc,
+ source_location orig_parm_replacement_loc)
+{
+ source_location result;
+
+ linemap_assert (linemap_macro_expansion_map_p (map));
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ MACRO_MAP_LOCATIONS (map)[2 * token_no] = orig_loc;
+ MACRO_MAP_LOCATIONS (map)[2 * token_no + 1] = orig_parm_replacement_loc;
+
+ result = MAP_START_LOCATION (map) + token_no;
+ return result;
+}
+
+/* Return a source_location for the start (i.e. column==0) of
+ (physical) line TO_LINE in the current source file (as in the
+ most recent linemap_add). MAX_COLUMN_HINT is the highest column
+ number we expect to use in this line (but it does not change
+ the highest_location). */
+
source_location
linemap_line_start (struct line_maps *set, linenum_type to_line,
unsigned int max_column_hint)
{
- struct line_map *map = &set->maps[set->used - 1];
+ struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (set);
source_location highest = set->highest_location;
source_location r;
- linenum_type last_line = SOURCE_LINE (map, set->highest_line);
+ linenum_type last_line =
+ SOURCE_LINE (map, set->highest_line);
int line_delta = to_line - last_line;
bool add_map = false;
+
if (line_delta < 0
- || (line_delta > 10 && line_delta * map->column_bits > 1000)
- || (max_column_hint >= (1U << map->column_bits))
- || (max_column_hint <= 80 && map->column_bits >= 10))
+ || (line_delta > 10
+ && line_delta * ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) > 1000)
+ || (max_column_hint >= (1U << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)))
+ || (max_column_hint <= 80
+ && ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) >= 10))
{
add_map = true;
}
@@ -224,16 +428,27 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
/* Allocate the new line_map. However, if the current map only has a
single line we can sometimes just increase its column_bits instead. */
if (line_delta < 0
- || last_line != map->to_line
+ || last_line != ORDINARY_MAP_STARTING_LINE_NUMBER (map)
|| SOURCE_COLUMN (map, highest) >= (1U << column_bits))
- map = (struct line_map *) linemap_add (set, LC_RENAME, map->sysp,
- map->to_file, to_line);
- map->column_bits = column_bits;
- r = map->start_location + ((to_line - map->to_line) << column_bits);
+ map = (struct line_map *) linemap_add (set, LC_RENAME,
+ ORDINARY_MAP_IN_SYSTEM_HEADER_P
+ (map),
+ ORDINARY_MAP_FILE_NAME (map),
+ to_line);
+ ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map) = column_bits;
+ r = (MAP_START_LOCATION (map)
+ + ((to_line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
+ << column_bits));
}
else
r = highest - SOURCE_COLUMN (map, highest)
- + (line_delta << map->column_bits);
+ + (line_delta << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map));
+
+ /* Locations of ordinary tokens are always lower than locations of
+ macro tokens. */
+ if (r >= LINEMAPS_MACRO_LOWEST_LOCATION (set))
+ return 0;
+
set->highest_line = r;
if (r > set->highest_location)
set->highest_location = r;
@@ -241,10 +456,19 @@ linemap_line_start (struct line_maps *set, linenum_type to_line,
return r;
}
+/* Encode and return a source_location from a column number. The
+ source line considered is the last source line used to call
+ linemap_line_start, i.e, the last source line which a location was
+ encoded from. */
+
source_location
linemap_position_for_column (struct line_maps *set, unsigned int to_column)
{
source_location r = set->highest_line;
+
+ linemap_assert
+ (!linemap_macro_expansion_map_p (LINEMAPS_LAST_ORDINARY_MAP (set)));
+
if (to_column >= set->max_column_hint)
{
if (r >= 0xC000000 || to_column > 100000)
@@ -254,7 +478,7 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column)
}
else
{
- struct line_map *map = &set->maps[set->used - 1];
+ struct line_map *map = LINEMAPS_LAST_ORDINARY_MAP (set);
r = linemap_line_start (set, SOURCE_LINE (map, r), to_column + 50);
}
}
@@ -264,25 +488,55 @@ linemap_position_for_column (struct line_maps *set, unsigned int to_column)
return r;
}
-/* Given a logical line, returns the map from which the corresponding
- (source file, line) pair can be deduced. Since the set is built
- chronologically, the logical lines are monotonic increasing, and so
- the list is sorted and we can use a binary search. */
+/* Encode and return a source location from a given line and
+ column. */
-const struct line_map *
+source_location
+linemap_position_for_line_and_column (struct line_map *map,
+ linenum_type line,
+ unsigned column)
+{
+ linemap_assert (ORDINARY_MAP_STARTING_LINE_NUMBER (map) <= line);
+
+ return (MAP_START_LOCATION (map)
+ + ((line - ORDINARY_MAP_STARTING_LINE_NUMBER (map))
+ << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map))
+ + (column & ((1 << ORDINARY_MAP_NUMBER_OF_COLUMN_BITS (map)) - 1)));
+}
+
+/* Given a virtual source location yielded by a map (either an
+ ordinary or a macro map), returns that map. */
+
+const struct line_map*
linemap_lookup (struct line_maps *set, source_location line)
{
+ if (linemap_location_from_macro_expansion_p (set, line))
+ return linemap_macro_map_lookup (set, line);
+ return linemap_ordinary_map_lookup (set, line);
+}
+
+/* Given a source location yielded by an ordinary map, returns that
+ map. Since the set is built chronologically, the logical lines are
+ monotonic increasing, and so the list is sorted and we can use a
+ binary search. */
+
+static const struct line_map *
+linemap_ordinary_map_lookup (struct line_maps *set, source_location line)
+{
unsigned int md, mn, mx;
- const struct line_map *cached;
+ const struct line_map *cached, *result;
+
+ if (set == NULL || line < RESERVED_LOCATION_COUNT)
+ return NULL;
- mn = set->cache;
- mx = set->used;
+ mn = LINEMAPS_ORDINARY_CACHE (set);
+ mx = LINEMAPS_ORDINARY_USED (set);
- cached = &set->maps[mn];
+ cached = LINEMAPS_ORDINARY_MAP_AT (set, mn);
/* We should get a segfault if no line_maps have been added yet. */
- if (line >= cached->start_location)
+ if (line >= MAP_START_LOCATION (cached))
{
- if (mn + 1 == mx || line < cached[1].start_location)
+ if (mn + 1 == mx || line < MAP_START_LOCATION (&cached[1]))
return cached;
}
else
@@ -294,14 +548,343 @@ linemap_lookup (struct line_maps *set, source_location line)
while (mx - mn > 1)
{
md = (mn + mx) / 2;
- if (set->maps[md].start_location > line)
+ if (MAP_START_LOCATION (LINEMAPS_ORDINARY_MAP_AT (set, md)) > line)
mx = md;
else
mn = md;
}
- set->cache = mn;
- return &set->maps[mn];
+ LINEMAPS_ORDINARY_CACHE (set) = mn;
+ result = LINEMAPS_ORDINARY_MAP_AT (set, mn);
+ linemap_assert (line >= MAP_START_LOCATION (result));
+ return result;
+}
+
+/* Given a source location yielded by a macro map, returns that map.
+ Since the set is built chronologically, the logical lines are
+ monotonic decreasing, and so the list is sorted and we can use a
+ binary search. */
+
+static const struct line_map*
+linemap_macro_map_lookup (struct line_maps *set, source_location line)
+{
+ unsigned int md, mn, mx;
+ const struct line_map *cached, *result;
+
+ linemap_assert (line >= LINEMAPS_MACRO_LOWEST_LOCATION (set));
+
+ if (set == NULL)
+ return NULL;
+
+ mn = LINEMAPS_MACRO_CACHE (set);
+ mx = LINEMAPS_MACRO_USED (set);
+ cached = LINEMAPS_MACRO_MAP_AT (set, mn);
+
+ if (line >= MAP_START_LOCATION (cached))
+ {
+ if (mn == 0 || line < MAP_START_LOCATION (&cached[-1]))
+ return cached;
+ mx = mn - 1;
+ mn = 0;
+ }
+
+ while (mn < mx)
+ {
+ md = (mx + mn) / 2;
+ if (MAP_START_LOCATION (LINEMAPS_MACRO_MAP_AT (set, md)) > line)
+ mn = md + 1;
+ else
+ mx = md;
+ }
+
+ LINEMAPS_MACRO_CACHE (set) = mx;
+ result = LINEMAPS_MACRO_MAP_AT (set, LINEMAPS_MACRO_CACHE (set));
+ linemap_assert (MAP_START_LOCATION (result) <= line);
+
+ return result;
+}
+
+/* Return TRUE if MAP encodes locations coming from a macro
+ replacement-list at macro expansion point. */
+
+bool
+linemap_macro_expansion_map_p (const struct line_map *map)
+{
+ if (!map)
+ return false;
+ return (map->reason == LC_ENTER_MACRO);
+}
+
+/* If LOCATION is the locus of a token in a replacement-list of a
+ macro expansion return the location of the macro expansion point.
+
+ Read the comments of struct line_map and struct line_map_macro in
+ line-map.h to understand what a macro expansion point is. */
+
+static source_location
+linemap_macro_map_loc_to_exp_point (const struct line_map *map,
+ source_location location ATTRIBUTE_UNUSED)
+{
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+
+ /* Make sure LOCATION is correct. */
+ linemap_assert ((location - MAP_START_LOCATION (map))
+ < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ return MACRO_MAP_EXPANSION_POINT_LOCATION (map);
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- as part of a macro expansion -- then
+ return the location of the token at the definition point of the
+ macro. Otherwise, return LOCATION. SET is the set of maps
+ location come from. ORIGINAL_MAP is an output parm. If non NULL,
+ the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
+ returned location comes from. */
+
+source_location
+linemap_macro_map_loc_to_def_point (const struct line_map *map,
+ source_location location)
+{
+ unsigned token_no;
+
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+ linemap_assert (location >= RESERVED_LOCATION_COUNT);
+
+ token_no = location - MAP_START_LOCATION (map);
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ location = MACRO_MAP_LOCATIONS (map)[2 * token_no + 1];
+
+ return location;
+}
+
+/* If LOCATION is the locus of a token that is an argument of a
+ function-like macro M and appears in the expansion of M, return the
+ locus of that argument in the context of the caller of M.
+
+ In other words, this returns the xI location presented in the
+ comments of line_map_macro above. */
+source_location
+linemap_macro_map_loc_unwind_toward_spelling (const struct line_map* map,
+ source_location location)
+{
+ unsigned token_no;
+
+ linemap_assert (linemap_macro_expansion_map_p (map)
+ && location >= MAP_START_LOCATION (map));
+ linemap_assert (location >= RESERVED_LOCATION_COUNT);
+
+ token_no = location - MAP_START_LOCATION (map);
+ linemap_assert (token_no < MACRO_MAP_NUM_MACRO_TOKENS (map));
+
+ location = MACRO_MAP_LOCATIONS (map)[2 * token_no];
+
+ return location;
+}
+
+/* Return the source line number corresponding to source location
+ LOCATION. SET is the line map set LOCATION comes from. If
+ LOCATION is the source location of token that is part of the
+ replacement-list of a macro expansion return the line number of the
+ macro expansion point. */
+
+int
+linemap_get_expansion_line (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return 0;
+
+ location =
+ linemap_macro_loc_to_exp_point (set, location, &map);
+
+ return SOURCE_LINE (map, location);
+}
+
+/* Return the path of the file corresponding to source code location
+ LOCATION.
+
+ If LOCATION is the source location of token that is part of the
+ replacement-list of a macro expansion return the file path of the
+ macro expansion point.
+
+ SET is the line map set LOCATION comes from. */
+
+const char*
+linemap_get_expansion_filename (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return NULL;
+
+ location =
+ linemap_macro_loc_to_exp_point (set, location, &map);
+
+ return LINEMAP_FILE (map);
+}
+
+/* Return the name of the macro associated to MACRO_MAP. */
+
+const char*
+linemap_map_get_macro_name (const struct line_map* macro_map)
+{
+ linemap_assert (macro_map && linemap_macro_expansion_map_p (macro_map));
+ return (const char*) NODE_NAME (MACRO_MAP_MACRO (macro_map));
+}
+
+/* Return a positive value if LOCATION is the locus of a token that is
+ located in a system header, O otherwise. It returns 1 if LOCATION
+ is the locus of a token that is located in a system header, and 2
+ if LOCATION is the locus of a token located in a C system header
+ that therefore needs to be extern "C" protected in C++.
+
+ Note that this function returns 1 if LOCATION belongs to a token
+ that is part of a macro replacement-list defined in a system
+ header, but expanded in a non-system file. */
+
+int
+linemap_location_in_system_header_p (struct line_maps *set,
+ source_location location)
+{
+ const struct line_map *map = NULL;
+
+ location =
+ linemap_resolve_location (set, location, LRK_SPELLING_LOCATION, &map);
+
+ if (location < RESERVED_LOCATION_COUNT)
+ return false;
+
+ return LINEMAP_SYSP (map);
+}
+
+/* Return TRUE if LOCATION is a source code location of a token coming
+ from a macro replacement-list at a macro expansion point, FALSE
+ otherwise. */
+
+bool
+linemap_location_from_macro_expansion_p (struct line_maps *set,
+ source_location location)
+{
+ linemap_assert (location <= MAX_SOURCE_LOCATION
+ && (set->highest_location
+ < LINEMAPS_MACRO_LOWEST_LOCATION (set)));
+ if (set == NULL)
+ return false;
+ return (location > set->highest_location);
+}
+
+/* Given two virtual locations *LOC0 and *LOC1, return the first
+ common macro map in their macro expansion histories. Return NULL
+ if no common macro was found. *LOC0 (resp. *LOC1) is set to the
+ virtual location of the token inside the resulting macro. */
+
+static const struct line_map*
+first_map_in_common_1 (struct line_maps *set,
+ source_location *loc0,
+ source_location *loc1)
+{
+ source_location l0 = *loc0, l1 = *loc1;
+ const struct line_map *map0 = linemap_lookup (set, l0),
+ *map1 = linemap_lookup (set, l1);
+
+ while (linemap_macro_expansion_map_p (map0)
+ && linemap_macro_expansion_map_p (map1)
+ && (map0 != map1))
+ {
+ if (MAP_START_LOCATION (map0) < MAP_START_LOCATION (map1))
+ {
+ l0 = linemap_macro_map_loc_to_exp_point (map0, l0);
+ map0 = linemap_lookup (set, l0);
+ }
+ else
+ {
+ l1 = linemap_macro_map_loc_to_exp_point (map1, l1);
+ map1 = linemap_lookup (set, l1);
+ }
+ }
+
+ if (map0 == map1)
+ {
+ *loc0 = l0;
+ *loc1 = l1;
+ return map0;
+ }
+ return NULL;
+}
+
+/* Given two virtual locations LOC0 and LOC1, return the first common
+ macro map in their macro expansion histories. Return NULL if no
+ common macro was found. *RES_LOC0 (resp. *RES_LOC1) is set to the
+ virtual location of the token inside the resulting macro, upon
+ return of a non-NULL result. */
+
+static const struct line_map*
+first_map_in_common (struct line_maps *set,
+ source_location loc0,
+ source_location loc1,
+ source_location *res_loc0,
+ source_location *res_loc1)
+{
+ *res_loc0 = loc0;
+ *res_loc1 = loc1;
+
+ return first_map_in_common_1 (set, res_loc0, res_loc1);
+}
+
+/* Return a positive value if PRE denotes the location of a token that
+ comes before the token of POST, 0 if PRE denotes the location of
+ the same token as the token for POST, and a negative value
+ otherwise. */
+
+int
+linemap_compare_locations (struct line_maps *set,
+ source_location pre,
+ source_location post)
+{
+ bool pre_virtual_p, post_virtual_p;
+ source_location l0 = pre, l1 = post;
+
+ if (l0 == l1)
+ return 0;
+
+ if ((pre_virtual_p = linemap_location_from_macro_expansion_p (set, l0)))
+ l0 = linemap_resolve_location (set, l0,
+ LRK_MACRO_EXPANSION_POINT,
+ NULL);
+
+ if ((post_virtual_p = linemap_location_from_macro_expansion_p (set, l1)))
+ l1 = linemap_resolve_location (set, l1,
+ LRK_MACRO_EXPANSION_POINT,
+ NULL);
+
+ if (l0 == l1
+ && pre_virtual_p
+ && post_virtual_p)
+ {
+ /* So pre and post represent two tokens that are present in a
+ same macro expansion. Let's see if the token for pre was
+ before the token for post in that expansion. */
+ unsigned i0, i1;
+ const struct line_map *map =
+ first_map_in_common (set, pre, post, &l0, &l1);
+
+ if (map == NULL)
+ /* This should not be possible. */
+ abort ();
+
+ i0 = l0 - MAP_START_LOCATION (map);
+ i1 = l1 - MAP_START_LOCATION (map);
+ return i1 - i0;
+ }
+
+ return l1 - l0;
}
/* Print an include trace, for e.g. the -H option of the preprocessor. */
@@ -313,5 +896,361 @@ trace_include (const struct line_maps *set, const struct line_map *map)
while (--i)
putc ('.', stderr);
- fprintf (stderr, " %s\n", map->to_file);
+
+ fprintf (stderr, " %s\n", ORDINARY_MAP_FILE_NAME (map));
+}
+
+/* Return the spelling location of the token wherever it comes from,
+ whether part of a macro definition or not.
+
+ This is a subroutine for linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_spelling_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+
+ location =
+ linemap_macro_map_loc_unwind_toward_spelling (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- as part of a macro expansion -- then
+ return the location of the token at the definition point of the
+ macro. Otherwise, return LOCATION. SET is the set of maps
+ location come from. ORIGINAL_MAP is an output parm. If non NULL,
+ the function sets *ORIGINAL_MAP to the ordinary (non-macro) map the
+ returned location comes from.
+
+ This is a subroutine of linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_def_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+
+ location =
+ linemap_macro_map_loc_to_def_point (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* If LOCATION is the source location of a token that belongs to a
+ macro replacement-list -- at a macro expansion point -- then return
+ the location of the topmost expansion point of the macro. We say
+ topmost because if we are in the context of a nested macro
+ expansion, the function returns the source location of the first
+ macro expansion that triggered the nested expansions.
+
+ Otherwise, return LOCATION. SET is the set of maps location come
+ from. ORIGINAL_MAP is an output parm. If non NULL, the function
+ sets *ORIGINAL_MAP to the ordinary (non-macro) map the returned
+ location comes from.
+
+ This is a subroutine of linemap_resolve_location. */
+
+static source_location
+linemap_macro_loc_to_exp_point (struct line_maps *set,
+ source_location location,
+ const struct line_map **original_map)
+{
+ struct line_map *map;
+
+ linemap_assert (set && location >= RESERVED_LOCATION_COUNT);
+
+ while (true)
+ {
+ map = (struct line_map*) linemap_lookup (set, location);
+ if (!linemap_macro_expansion_map_p (map))
+ break;
+ location = linemap_macro_map_loc_to_exp_point (map, location);
+ }
+
+ if (original_map)
+ *original_map = map;
+ return location;
+}
+
+/* Resolve a virtual location into either a spelling location, an
+ expansion point location or a token argument replacement point
+ location. Return the map that encodes the virtual location as well
+ as the resolved location.
+
+ If LOC is *NOT* the location of a token resulting from the
+ expansion of a macro, then the parameter LRK (which stands for
+ Location Resolution Kind) is ignored and the resulting location
+ just equals the one given in argument.
+
+ Now if LOC *IS* the location of a token resulting from the
+ expansion of a macro, this is what happens.
+
+ * If LRK is set to LRK_MACRO_EXPANSION_POINT
+ -------------------------------
+
+ The virtual location is resolved to the location to the locus of
+ the expansion point of the macro.
+
+ * If LRK is set to LRK_SPELLING_LOCATION
+ -------------------------------------
+
+ The virtual location is resolved to the location to the locus where
+ the token has been spelled in the source. This can follow through
+ all the macro expansions that led to the token.
+
+ * If LRK is set to LRK_MACRO_PARM_REPLACEMENT_POINT
+ --------------------------------------
+
+ If LOC is the locus of a token that is an argument of a
+ function-like macro [replacing a parameter in the replacement list
+ of the macro] the virtual location is resolved to the locus of the
+ parameter that is replaced, in the context of the definition of the
+ macro.
+
+ If LOC is the locus of a token that is not an argument of a
+ function-like macro, then the function behaves as if LRK was set to
+ LRK_SPELLING_LOCATION.
+
+ If MAP is non-NULL, *MAP is set to the map of the resolved
+ location. Note that if the resturned location wasn't originally
+ encoded by a map, the *MAP is set to NULL. This can happen if LOC
+ resolves to a location reserved for the client code, like
+ UNKNOWN_LOCATION or BUILTINS_LOCATION in GCC. */
+
+source_location
+linemap_resolve_location (struct line_maps *set,
+ source_location loc,
+ enum location_resolution_kind lrk,
+ const struct line_map **map)
+{
+ if (loc < RESERVED_LOCATION_COUNT)
+ {
+ /* A reserved location wasn't encoded in a map. Let's return a
+ NULL map here, just like what linemap_ordinary_map_lookup
+ does. */
+ if (map)
+ *map = NULL;
+ return loc;
+ }
+
+ switch (lrk)
+ {
+ case LRK_MACRO_EXPANSION_POINT:
+ loc = linemap_macro_loc_to_exp_point (set, loc, map);
+ break;
+ case LRK_SPELLING_LOCATION:
+ loc = linemap_macro_loc_to_spelling_point (set, loc, map);
+ break;
+ case LRK_MACRO_DEFINITION_LOCATION:
+ loc = linemap_macro_loc_to_def_point (set, loc, map);
+ break;
+ default:
+ abort ();
+ }
+ return loc;
+}
+
+/*
+ Suppose that LOC is the virtual location of a token T coming from
+ the expansion of a macro M. This function then steps up to get the
+ location L of the point where M got expanded. If L is a spelling
+ location inside a macro expansion M', then this function returns
+ the locus of the point where M' was expanded. Said otherwise, this
+ function returns the location of T in the context that triggered
+ the expansion of M.
+
+ *LOC_MAP must be set to the map of LOC. This function then sets it
+ to the map of the returned location. */
+
+source_location
+linemap_unwind_toward_expansion (struct line_maps *set,
+ source_location loc,
+ const struct line_map **map)
+{
+ source_location resolved_location;
+ const struct line_map *resolved_map;
+
+ resolved_location =
+ linemap_macro_map_loc_unwind_toward_spelling (*map, loc);
+ resolved_map = linemap_lookup (set, resolved_location);
+
+ if (!linemap_macro_expansion_map_p (resolved_map))
+ {
+ resolved_location = linemap_macro_map_loc_to_exp_point (*map, loc);
+ resolved_map = linemap_lookup (set, resolved_location);
+ }
+
+ *map = resolved_map;
+ return resolved_location;
+}
+
+/* Expand source code location LOC and return a user readable source
+ code location. LOC must be a spelling (non-virtual) location. If
+ it's a location < RESERVED_LOCATION_COUNT a zeroed expanded source
+ location is returned. */
+
+expanded_location
+linemap_expand_location (struct line_maps *set,
+ const struct line_map *map,
+ source_location loc)
+
+{
+ expanded_location xloc;
+
+ memset (&xloc, 0, sizeof (xloc));
+
+ if (loc < RESERVED_LOCATION_COUNT)
+ /* The location for this token wasn't generated from a line map.
+ It was probably a location for a builtin token, chosen by some
+ client code. Let's not try to expand the location in that
+ case. */;
+ else if (map == NULL)
+ /* We shouldn't be getting a NULL map with a location that is not
+ reserved by the client code. */
+ abort ();
+ else
+ {
+ /* MAP must be an ordinary map and LOC must be non-virtual,
+ encoded into this map, obviously; the accessors used on MAP
+ below ensure it is ordinary. Let's just assert the
+ non-virtualness of LOC here. */
+ if (linemap_location_from_macro_expansion_p (set, loc))
+ abort ();
+
+ xloc.file = LINEMAP_FILE (map);
+ xloc.line = SOURCE_LINE (map, loc);
+ xloc.column = SOURCE_COLUMN (map, loc);
+ xloc.sysp = LINEMAP_SYSP (map) != 0;
+ }
+
+ return xloc;
+}
+
+/* Dump debugging information about source location LOC into the file
+ stream STREAM. SET is the line map set LOC comes from. */
+
+void
+linemap_dump_location (struct line_maps *set,
+ source_location loc,
+ FILE *stream)
+{
+ const struct line_map *map;
+ source_location location;
+ const char *path = "", *from = "";
+ int l = -1, c = -1, s = -1, e = -1;
+
+ if (loc == 0)
+ return;
+
+ location =
+ linemap_resolve_location (set, loc, LRK_MACRO_DEFINITION_LOCATION, &map);
+
+ if (map == NULL)
+ /* Only reserved locations can be tolerated in this case. */
+ linemap_assert (location < RESERVED_LOCATION_COUNT);
+ else
+ {
+ path = LINEMAP_FILE (map);
+ l = SOURCE_LINE (map, location);
+ c = SOURCE_COLUMN (map, location);
+ s = LINEMAP_SYSP (map) != 0;
+ e = location != loc;
+ if (e)
+ from = "N/A";
+ else
+ from = (INCLUDED_FROM (set, map))
+ ? LINEMAP_FILE (INCLUDED_FROM (set, map))
+ : "<NULL>";
+ }
+
+ /* P: path, L: line, C: column, S: in-system-header, M: map address,
+ E: macro expansion?, LOC: original location, R: resolved location */
+ fprintf (stream, "{P:%s;F:%s;L:%d;C:%d;S:%d;M:%p;E:%d,LOC:%d,R:%d}",
+ path, from, l, c, s, (void*)map, e, loc, location);
+}
+
+/* Compute and return statistics about the memory consumption of some
+ parts of the line table SET. */
+
+void
+linemap_get_statistics (struct line_maps *set,
+ struct linemap_stats *s)
+{
+ long ordinary_maps_allocated_size, ordinary_maps_used_size,
+ macro_maps_allocated_size, macro_maps_used_size,
+ macro_maps_locations_size = 0, duplicated_macro_maps_locations_size = 0;
+
+ struct line_map *cur_map;
+
+ ordinary_maps_allocated_size =
+ LINEMAPS_ORDINARY_ALLOCATED (set) * sizeof (struct line_map);
+
+ ordinary_maps_used_size =
+ LINEMAPS_ORDINARY_USED (set) * sizeof (struct line_map);
+
+ macro_maps_allocated_size =
+ LINEMAPS_MACRO_ALLOCATED (set) * sizeof (struct line_map);
+
+ for (cur_map = LINEMAPS_MACRO_MAPS (set);
+ cur_map && cur_map <= LINEMAPS_LAST_MACRO_MAP (set);
+ ++cur_map)
+ {
+ unsigned i;
+
+ linemap_assert (linemap_macro_expansion_map_p (cur_map));
+
+ macro_maps_locations_size +=
+ 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map) * sizeof (source_location);
+
+ for (i = 0; i < 2 * MACRO_MAP_NUM_MACRO_TOKENS (cur_map); i += 2)
+ {
+ if (MACRO_MAP_LOCATIONS (cur_map)[i] ==
+ MACRO_MAP_LOCATIONS (cur_map)[i + 1])
+ duplicated_macro_maps_locations_size +=
+ sizeof (source_location);
+ }
+ }
+
+ macro_maps_used_size =
+ LINEMAPS_MACRO_USED (set) * sizeof (struct line_map);
+
+ s->num_ordinary_maps_allocated = LINEMAPS_ORDINARY_ALLOCATED (set);
+ s->num_ordinary_maps_used = LINEMAPS_ORDINARY_USED (set);
+ s->ordinary_maps_allocated_size = ordinary_maps_allocated_size;
+ s->ordinary_maps_used_size = ordinary_maps_used_size;
+ s->num_expanded_macros = num_expanded_macros_counter;
+ s->num_macro_tokens = num_macro_tokens_counter;
+ s->num_macro_maps_used = LINEMAPS_MACRO_USED (set);
+ s->macro_maps_allocated_size = macro_maps_allocated_size;
+ s->macro_maps_locations_size = macro_maps_locations_size;
+ s->macro_maps_used_size = macro_maps_used_size;
+ s->duplicated_macro_maps_locations_size =
+ duplicated_macro_maps_locations_size;
}
diff --git a/libcpp/macro.c b/libcpp/macro.c
index eba2349954a..f3139590d50 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -1,7 +1,7 @@
/* Part of CPP library. (Macro and #define handling.)
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -30,6 +30,10 @@ along with this program; see the file COPYING3. If not see
#include "internal.h"
typedef struct macro_arg macro_arg;
+/* This structure represents the tokens of a macro argument. These
+ tokens can be macro themselves, in which case they can be either
+ expanded or unexpanded. When they are expanded, this data
+ structure keeps both the expanded and unexpanded forms. */
struct macro_arg
{
const cpp_token **first; /* First token in unexpanded argument. */
@@ -37,17 +41,59 @@ struct macro_arg
const cpp_token *stringified; /* Stringified argument. */
unsigned int count; /* # of tokens in argument. */
unsigned int expanded_count; /* # of tokens in expanded argument. */
+ source_location *virt_locs; /* Where virtual locations for
+ unexpanded tokens are stored. */
+ source_location *expanded_virt_locs; /* Where virtual locations for
+ expanded tokens are
+ stored. */
+};
+
+/* The kind of macro tokens which the instance of
+ macro_arg_token_iter is supposed to iterate over. */
+enum macro_arg_token_kind {
+ MACRO_ARG_TOKEN_NORMAL,
+ /* This is a macro argument token that got transformed into a string
+ litteral, e.g. #foo. */
+ MACRO_ARG_TOKEN_STRINGIFIED,
+ /* This is a token resulting from the expansion of a macro
+ argument that was itself a macro. */
+ MACRO_ARG_TOKEN_EXPANDED
+};
+
+/* An iterator over tokens coming from a function-like macro
+ argument. */
+typedef struct macro_arg_token_iter macro_arg_token_iter;
+struct macro_arg_token_iter
+{
+ /* Whether or not -ftrack-macro-expansion is used. */
+ bool track_macro_exp_p;
+ /* The kind of token over which we are supposed to iterate. */
+ enum macro_arg_token_kind kind;
+ /* A pointer to the current token pointed to by the iterator. */
+ const cpp_token **token_ptr;
+ /* A pointer to the "full" location of the current token. If
+ -ftrack-macro-expansion is used this location tracks loci accross
+ macro expansion. */
+ const source_location *location_ptr;
+#ifdef ENABLE_CHECKING
+ /* The number of times the iterator went forward. This useful only
+ when checking is enabled. */
+ size_t num_forwards;
+#endif
};
/* Macro expansion. */
static int enter_macro_context (cpp_reader *, cpp_hashnode *,
- const cpp_token *);
+ const cpp_token *, source_location);
static int builtin_macro (cpp_reader *, cpp_hashnode *);
static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
const cpp_token **, unsigned int);
+static void push_extended_tokens_context (cpp_reader *, cpp_hashnode *,
+ _cpp_buff *, source_location *,
+ const cpp_token **, unsigned int);
static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *,
- _cpp_buff **);
+ _cpp_buff **, unsigned *);
static cpp_context *next_context (cpp_reader *);
static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
static void expand_arg (cpp_reader *, macro_arg *);
@@ -55,10 +101,53 @@ static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int);
static const cpp_token *stringify_arg (cpp_reader *, macro_arg *);
static void paste_all_tokens (cpp_reader *, const cpp_token *);
static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *);
+static void alloc_expanded_arg_mem (cpp_reader *, macro_arg *, size_t);
+static void ensure_expanded_arg_room (cpp_reader *, macro_arg *, size_t, size_t *);
+static void delete_macro_args (_cpp_buff*, unsigned num_args);
+static void set_arg_token (macro_arg *, const cpp_token *,
+ source_location, size_t,
+ enum macro_arg_token_kind,
+ bool);
+static const source_location *get_arg_token_location (const macro_arg *,
+ enum macro_arg_token_kind);
+static const cpp_token **arg_token_ptr_at (const macro_arg *,
+ size_t,
+ enum macro_arg_token_kind,
+ source_location **virt_location);
+
+static void macro_arg_token_iter_init (macro_arg_token_iter *, bool,
+ enum macro_arg_token_kind,
+ const macro_arg *,
+ const cpp_token **);
+static const cpp_token *macro_arg_token_iter_get_token
+(const macro_arg_token_iter *it);
+static source_location macro_arg_token_iter_get_location
+(const macro_arg_token_iter *);
+static void macro_arg_token_iter_forward (macro_arg_token_iter *);
+static _cpp_buff *tokens_buff_new (cpp_reader *, size_t,
+ source_location **);
+static size_t tokens_buff_count (_cpp_buff *);
+static const cpp_token **tokens_buff_last_token_ptr (_cpp_buff *);
+static const cpp_token **tokens_buff_put_token_to (const cpp_token **,
+ source_location *,
+ const cpp_token *,
+ source_location,
+ source_location,
+ const struct line_map *,
+ unsigned int);
+
+static const cpp_token **tokens_buff_add_token (_cpp_buff *,
+ source_location *,
+ const cpp_token *,
+ source_location,
+ source_location,
+ const struct line_map *,
+ unsigned int);
+static void tokens_buff_remove_last_token (_cpp_buff *);
static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *,
- macro_arg *);
+ macro_arg *, source_location);
static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *,
- _cpp_buff **);
+ _cpp_buff **, unsigned *);
static bool create_iso_definition (cpp_reader *, cpp_macro *);
/* #define directive parsing and handling. */
@@ -70,6 +159,18 @@ static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *,
static bool parse_params (cpp_reader *, cpp_macro *);
static void check_trad_stringification (cpp_reader *, const cpp_macro *,
const cpp_string *);
+static bool reached_end_of_context (cpp_context *);
+static void consume_next_token_from_context (cpp_reader *pfile,
+ const cpp_token **,
+ source_location *);
+static const cpp_token* cpp_get_token_1 (cpp_reader *, source_location *);
+
+/* Statistical counter tracking the number of macros that got
+ expanded. */
+unsigned num_expanded_macros_counter = 0;
+/* Statistical counter tracking the total number tokens resulting
+ from macro expansion. */
+unsigned num_macro_tokens_counter = 0;
/* Emits a warning if NODE is a macro defined in the main file that
has not been used. */
@@ -171,13 +272,17 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
unsigned int len;
const char *name;
uchar *buf;
- map = linemap_lookup (pfile->line_table, pfile->line_table->highest_line);
-
- if (node->value.builtin == BT_BASE_FILE)
- while (! MAIN_FILE_P (map))
- map = INCLUDED_FROM (pfile->line_table, map);
-
- name = map->to_file;
+
+ if (node->value.builtin == BT_FILE)
+ name = linemap_get_expansion_filename (pfile->line_table,
+ pfile->line_table->highest_line);
+ else
+ {
+ map = linemap_lookup (pfile->line_table, pfile->line_table->highest_line);
+ while (! MAIN_FILE_P (map))
+ map = INCLUDED_FROM (pfile->line_table, map);
+ name = ORDINARY_MAP_FILE_NAME (map);
+ }
len = strlen (name);
buf = _cpp_unaligned_alloc (pfile, len * 2 + 3);
result = buf;
@@ -196,14 +301,14 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node)
break;
case BT_SPECLINE:
- map = &pfile->line_table->maps[pfile->line_table->used-1];
+ map = LINEMAPS_LAST_ORDINARY_MAP (pfile->line_table);
/* 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. */
- number = SOURCE_LINE (map,
- CPP_OPTION (pfile, traditional)
- ? pfile->line_table->highest_line
- : pfile->cur_token[-1].src_loc);
+ number = linemap_get_expansion_line (pfile->line_table,
+ CPP_OPTION (pfile, traditional)
+ ? pfile->line_table->highest_line
+ : pfile->cur_token[-1].src_loc);
break;
/* __STDC__ has the value 1 under normal circumstances.
@@ -507,7 +612,7 @@ paste_tokens (cpp_reader *pfile, const cpp_token **plhs, const cpp_token *rhs)
static void
paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
{
- const cpp_token *rhs;
+ const cpp_token *rhs = NULL;
cpp_context *context = pfile->context;
do
@@ -517,10 +622,25 @@ paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
object-like macro, or a function-like macro with arguments
inserted. In either case, the constraints to #define
guarantee we have at least one more token. */
- if (context->direct_p)
+ if (context->tokens_kind == TOKENS_KIND_DIRECT)
rhs = FIRST (context).token++;
- else
+ else if (context->tokens_kind == TOKENS_KIND_INDIRECT)
rhs = *FIRST (context).ptoken++;
+ else if (context->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ /* So we are in presence of an extended token context, which
+ means that each token in this context has a virtual
+ location attached to it. So let's not forget to update
+ the pointer to the current virtual location of the
+ current token when we update the pointer to the current
+ token */
+
+ rhs = *FIRST (context).ptoken++;
+ /* context->c.mc must be non-null, as if we were not in a
+ macro context, context->tokens_kind could not be equal to
+ TOKENS_KIND_EXTENDED. */
+ context->c.mc->cur_virt_loc++;
+ }
if (rhs->type == CPP_PADDING)
{
@@ -584,23 +704,37 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node
NULL. Each argument is terminated by a CPP_EOF token, for the
future benefit of expand_arg(). If there are any deferred
#pragma directives among macro arguments, store pointers to the
- CPP_PRAGMA ... CPP_PRAGMA_EOL tokens into *PRAGMA_BUFF buffer. */
+ CPP_PRAGMA ... CPP_PRAGMA_EOL tokens into *PRAGMA_BUFF buffer.
+
+ What is returned is the buffer that contains the memory allocated
+ to hold the macro arguments. NODE is the name of the macro this
+ function is dealing with. If NUM_ARGS is non-NULL, *NUM_ARGS is
+ set to the actual number of macro arguments allocated in the
+ returned buffer. */
static _cpp_buff *
collect_args (cpp_reader *pfile, const cpp_hashnode *node,
- _cpp_buff **pragma_buff)
+ _cpp_buff **pragma_buff, unsigned *num_args)
{
_cpp_buff *buff, *base_buff;
cpp_macro *macro;
macro_arg *args, *arg;
const cpp_token *token;
unsigned int argc;
+ source_location virt_loc;
+ bool track_macro_expansion_p = CPP_OPTION (pfile, track_macro_expansion);
+ unsigned num_args_alloced = 0;
macro = node->value.macro;
if (macro->paramc)
argc = macro->paramc;
else
argc = 1;
- buff = _cpp_get_buff (pfile, argc * (50 * sizeof (cpp_token *)
+
+#define DEFAULT_NUM_TOKENS_PER_MACRO_ARG 50
+#define ARG_TOKENS_EXTENT 1000
+
+ buff = _cpp_get_buff (pfile, argc * (DEFAULT_NUM_TOKENS_PER_MACRO_ARG
+ * sizeof (cpp_token *)
+ sizeof (macro_arg)));
base_buff = buff;
args = (macro_arg *) buff->base;
@@ -615,9 +749,17 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
{
unsigned int paren_depth = 0;
unsigned int ntokens = 0;
+ unsigned virt_locs_capacity = DEFAULT_NUM_TOKENS_PER_MACRO_ARG;
+ num_args_alloced++;
argc++;
arg->first = (const cpp_token **) buff->cur;
+ if (track_macro_expansion_p)
+ {
+ virt_locs_capacity = DEFAULT_NUM_TOKENS_PER_MACRO_ARG;
+ arg->virt_locs = XNEWVEC (source_location,
+ virt_locs_capacity);
+ }
for (;;)
{
@@ -625,11 +767,20 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
if ((unsigned char *) &arg->first[ntokens + 2] > buff->limit)
{
buff = _cpp_append_extend_buff (pfile, buff,
- 1000 * sizeof (cpp_token *));
+ ARG_TOKENS_EXTENT
+ * sizeof (cpp_token *));
arg->first = (const cpp_token **) buff->cur;
}
+ if (track_macro_expansion_p
+ && (ntokens + 2 > virt_locs_capacity))
+ {
+ virt_locs_capacity += ARG_TOKENS_EXTENT;
+ arg->virt_locs = XRESIZEVEC (source_location,
+ arg->virt_locs,
+ virt_locs_capacity);
+ }
- token = cpp_get_token (pfile);
+ token = cpp_get_token_1 (pfile, &virt_loc);
if (token->type == CPP_PADDING)
{
@@ -686,7 +837,7 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
BUFF_FRONT (*pragma_buff) += sizeof (cpp_token *);
if (token->type == CPP_PRAGMA_EOL)
break;
- token = cpp_get_token (pfile);
+ token = cpp_get_token_1 (pfile, &virt_loc);
}
while (token->type != CPP_EOF);
@@ -700,8 +851,10 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
else
continue;
}
-
- arg->first[ntokens++] = token;
+ set_arg_token (arg, token, virt_loc,
+ ntokens, MACRO_ARG_TOKEN_NORMAL,
+ CPP_OPTION (pfile, track_macro_expansion));
+ ntokens++;
}
/* Drop trailing padding. */
@@ -709,7 +862,9 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
ntokens--;
arg->count = ntokens;
- arg->first[ntokens] = &pfile->eof;
+ set_arg_token (arg, &pfile->eof, pfile->eof.src_loc,
+ ntokens, MACRO_ARG_TOKEN_NORMAL,
+ CPP_OPTION (pfile, track_macro_expansion));
/* Terminate the argument. Excess arguments loop back and
overwrite the final legitimate argument, before failing. */
@@ -752,6 +907,8 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
|| (argc == 1 && args[0].count == 0
&& !CPP_OPTION (pfile, std))))
args[macro->paramc - 1].first = NULL;
+ if (num_args)
+ *num_args = num_args_alloced;
return base_buff;
}
}
@@ -765,10 +922,12 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node,
way that, if none is found, we don't lose the information in any
intervening padding tokens. If we find the parenthesis, collect
the arguments and return the buffer containing them. PRAGMA_BUFF
- argument is the same as in collect_args. */
+ argument is the same as in collect_args. If NUM_ARGS is non-NULL,
+ *NUM_ARGS is set to the number of arguments contained in the
+ returned buffer. */
static _cpp_buff *
funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
- _cpp_buff **pragma_buff)
+ _cpp_buff **pragma_buff, unsigned *num_args)
{
const cpp_token *token, *padding = NULL;
@@ -785,7 +944,7 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
if (token->type == CPP_OPEN_PAREN)
{
pfile->state.parsing_args = 2;
- return collect_args (pfile, node, pragma_buff);
+ return collect_args (pfile, node, pragma_buff, num_args);
}
/* CPP_EOF can be the end of macro arguments, or the end of the
@@ -819,13 +978,15 @@ macro_real_token_count (const cpp_macro *macro)
/* Push the context of a macro with hash entry NODE onto the context
stack. If we can successfully expand the macro, we push a context
containing its yet-to-be-rescanned replacement list and return one.
- If there were additionally any unexpanded deferred #pragma directives
- among macro arguments, push another context containing the
- pragma tokens before the yet-to-be-rescanned replacement list
- and return two. Otherwise, we don't push a context and return zero. */
+ If there were additionally any unexpanded deferred #pragma
+ directives among macro arguments, push another context containing
+ the pragma tokens before the yet-to-be-rescanned replacement list
+ and return two. Otherwise, we don't push a context and return
+ zero. LOCATION is the location of the expansion point of the
+ macro. */
static int
enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
- const cpp_token *result)
+ const cpp_token *result, source_location location)
{
/* The presence of a macro invalidates a file's controlling macro. */
pfile->mi_valid = false;
@@ -850,11 +1011,13 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
if (macro->fun_like)
{
_cpp_buff *buff;
+ unsigned num_args = 0;
pfile->state.prevent_expansion++;
pfile->keep_tokens++;
pfile->state.parsing_args = 1;
- buff = funlike_invocation_p (pfile, node, &pragma_buff);
+ buff = funlike_invocation_p (pfile, node, &pragma_buff,
+ &num_args);
pfile->state.parsing_args = 0;
pfile->keep_tokens--;
pfile->state.prevent_expansion--;
@@ -873,8 +1036,13 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
}
if (macro->paramc > 0)
- replace_args (pfile, node, macro, (macro_arg *) buff->base);
- _cpp_release_buff (pfile, buff);
+ replace_args (pfile, node, macro,
+ (macro_arg *) buff->base,
+ location);
+ /* Free the memory used by the arguments of this
+ function-like macro. This memory has been allocated by
+ funlike_invocation_p and by replace_args. */
+ delete_macro_args (buff, num_args);
}
/* Disable the macro within its expansion. */
@@ -888,13 +1056,49 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
}
if (pfile->cb.used)
- pfile->cb.used (pfile, result->src_loc, node);
+ pfile->cb.used (pfile, location, node);
macro->used = 1;
if (macro->paramc == 0)
- _cpp_push_token_context (pfile, node, macro->exp.tokens,
- macro_real_token_count (macro));
+ {
+ if (CPP_OPTION (pfile, track_macro_expansion))
+ {
+ unsigned int i, count = macro->count;
+ const cpp_token *src = macro->exp.tokens;
+ const struct line_map *map;
+ source_location *virt_locs = NULL;
+ _cpp_buff *macro_tokens =
+ tokens_buff_new (pfile, count, &virt_locs);
+
+ /* Create a macro map to record the locations of the
+ tokens that are involved in the expansion. LOCATION
+ is the location of the macro expansion point. */
+ map = linemap_enter_macro (pfile->line_table,
+ node, location, count);
+ for (i = 0; i < count; ++i)
+ {
+ tokens_buff_add_token (macro_tokens, virt_locs,
+ src, src->src_loc,
+ src->src_loc, map, i);
+ ++src;
+ }
+ push_extended_tokens_context (pfile, node,
+ macro_tokens,
+ virt_locs,
+ (const cpp_token **)
+ macro_tokens->base,
+ count);
+ num_macro_tokens_counter += count;
+ }
+ else
+ {
+ unsigned tokens_count = macro_real_token_count (macro);
+ _cpp_push_token_context (pfile, node, macro->exp.tokens,
+ tokens_count);
+ num_macro_tokens_counter += tokens_count;
+ }
+ }
if (pragma_buff)
{
@@ -903,13 +1107,18 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
padding_token (pfile, result), 1);
do
{
+ unsigned tokens_count;
_cpp_buff *tail = pragma_buff->next;
pragma_buff->next = NULL;
+ tokens_count = ((const cpp_token **) BUFF_FRONT (pragma_buff)
+ - (const cpp_token **) pragma_buff->base);
push_ptoken_context (pfile, NULL, pragma_buff,
(const cpp_token **) pragma_buff->base,
- ((const cpp_token **) BUFF_FRONT (pragma_buff)
- - (const cpp_token **) pragma_buff->base));
+ tokens_count);
pragma_buff = tail;
+ if (!CPP_OPTION (pfile, track_macro_expansion))
+ num_macro_tokens_counter += tokens_count;
+
}
while (pragma_buff != NULL);
return 2;
@@ -922,33 +1131,318 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
return builtin_macro (pfile, node);
}
+/* De-allocate the memory used by BUFF which is an array of instances
+ of macro_arg. NUM_ARGS is the number of instances of macro_arg
+ present in BUFF. */
+static void
+delete_macro_args (_cpp_buff *buff, unsigned num_args)
+{
+ macro_arg *macro_args;
+ unsigned i;
+
+ if (buff == NULL)
+ return;
+
+ macro_args = (macro_arg *) buff->base;
+
+ /* Walk instances of macro_arg to free their expanded tokens as well
+ as their macro_arg::virt_locs members. */
+ for (i = 0; i < num_args; ++i)
+ {
+ if (macro_args[i].expanded)
+ {
+ free (macro_args[i].expanded);
+ macro_args[i].expanded = NULL;
+ }
+ if (macro_args[i].virt_locs)
+ {
+ free (macro_args[i].virt_locs);
+ macro_args[i].virt_locs = NULL;
+ }
+ if (macro_args[i].expanded_virt_locs)
+ {
+ free (macro_args[i].expanded_virt_locs);
+ macro_args[i].expanded_virt_locs = NULL;
+ }
+ }
+ _cpp_free_buff (buff);
+}
+
+/* Set the INDEXth token of the macro argument ARG. TOKEN is the token
+ to set, LOCATION is its virtual location. "Virtual" location means
+ the location that encodes loci accross macro expansion. Otherwise
+ it has to be TOKEN->SRC_LOC. KIND is the kind of tokens the
+ argument ARG is supposed to contain. Note that ARG must be
+ tailored so that it has enough room to contain INDEX + 1 numbers of
+ tokens, at least. */
+static void
+set_arg_token (macro_arg *arg, const cpp_token *token,
+ source_location location, size_t index,
+ enum macro_arg_token_kind kind,
+ bool track_macro_exp_p)
+{
+ const cpp_token **token_ptr;
+ source_location *loc = NULL;
+
+ token_ptr =
+ arg_token_ptr_at (arg, index, kind,
+ track_macro_exp_p ? &loc : NULL);
+ *token_ptr = token;
+
+ if (loc != NULL)
+ {
+#ifdef ENABLE_CHECKING
+ if (kind == MACRO_ARG_TOKEN_STRINGIFIED
+ || !track_macro_exp_p)
+ /* We can't set the location of a stringified argument
+ token and we can't set any location if we aren't tracking
+ macro expansion locations. */
+ abort ();
+#endif
+ *loc = location;
+ }
+}
+
+/* Get the pointer to the location of the argument token of the
+ function-like macro argument ARG. This function must be called
+ only when we -ftrack-macro-expansion is on. */
+static const source_location *
+get_arg_token_location (const macro_arg *arg,
+ enum macro_arg_token_kind kind)
+{
+ const source_location *loc = NULL;
+ const cpp_token **token_ptr =
+ arg_token_ptr_at (arg, 0, kind, (source_location **) &loc);
+
+ if (token_ptr == NULL)
+ return NULL;
+
+ return loc;
+}
+
+/* Return the pointer to the INDEXth token of the macro argument ARG.
+ KIND specifies the kind of token the macro argument ARG contains.
+ If VIRT_LOCATION is non NULL, *VIRT_LOCATION is set to the address
+ of the virtual location of the returned token if the
+ -ftrack-macro-expansion flag is on; otherwise, it's set to the
+ spelling location of the returned token. */
+static const cpp_token **
+arg_token_ptr_at (const macro_arg *arg, size_t index,
+ enum macro_arg_token_kind kind,
+ source_location **virt_location)
+{
+ const cpp_token **tokens_ptr = NULL;
+
+ switch (kind)
+ {
+ case MACRO_ARG_TOKEN_NORMAL:
+ tokens_ptr = arg->first;
+ break;
+ case MACRO_ARG_TOKEN_STRINGIFIED:
+ tokens_ptr = (const cpp_token **) &arg->stringified;
+ break;
+ case MACRO_ARG_TOKEN_EXPANDED:
+ tokens_ptr = arg->expanded;
+ break;
+ }
+
+ if (tokens_ptr == NULL)
+ /* This can happen for e.g, an empty token argument to a
+ funtion-like macro. */
+ return tokens_ptr;
+
+ if (virt_location)
+ {
+ if (kind == MACRO_ARG_TOKEN_NORMAL)
+ *virt_location = &arg->virt_locs[index];
+ else if (kind == MACRO_ARG_TOKEN_EXPANDED)
+ *virt_location = &arg->expanded_virt_locs[index];
+ else if (kind == MACRO_ARG_TOKEN_STRINGIFIED)
+ *virt_location =
+ (source_location *) &tokens_ptr[index]->src_loc;
+ }
+ return &tokens_ptr[index];
+}
+
+/* Initialize an iterator so that it iterates over the tokens of a
+ function-like macro argument. KIND is the kind of tokens we want
+ ITER to iterate over. TOKEN_PTR points the first token ITER will
+ iterate over. */
+static void
+macro_arg_token_iter_init (macro_arg_token_iter *iter,
+ bool track_macro_exp_p,
+ enum macro_arg_token_kind kind,
+ const macro_arg *arg,
+ const cpp_token **token_ptr)
+{
+ iter->track_macro_exp_p = track_macro_exp_p;
+ iter->kind = kind;
+ iter->token_ptr = token_ptr;
+ /* Unconditionally initialize this so that the compiler doesn't warn
+ about iter->location_ptr being possibly uninitialized later after
+ this code has been inlined somewhere. */
+ iter->location_ptr = NULL;
+ if (track_macro_exp_p)
+ iter->location_ptr = get_arg_token_location (arg, kind);
+#ifdef ENABLE_CHECKING
+ iter->num_forwards = 0;
+ if (track_macro_exp_p
+ && token_ptr != NULL
+ && iter->location_ptr == NULL)
+ abort ();
+#endif
+}
+
+/* Move the iterator one token forward. Note that if IT was
+ initialized on an argument that has a stringified token, moving it
+ foward doesn't make sense as a stringified token is essentially one
+ string. */
+static void
+macro_arg_token_iter_forward (macro_arg_token_iter *it)
+{
+ switch (it->kind)
+ {
+ case MACRO_ARG_TOKEN_NORMAL:
+ case MACRO_ARG_TOKEN_EXPANDED:
+ it->token_ptr++;
+ if (it->track_macro_exp_p)
+ it->location_ptr++;
+ break;
+ case MACRO_ARG_TOKEN_STRINGIFIED:
+#ifdef ENABLE_CHECKING
+ if (it->num_forwards > 0)
+ abort ();
+#endif
+ break;
+ }
+
+#ifdef ENABLE_CHECKING
+ it->num_forwards++;
+#endif
+}
+
+/* Return the token pointed to by the iterator. */
+static const cpp_token *
+macro_arg_token_iter_get_token (const macro_arg_token_iter *it)
+{
+#ifdef ENABLE_CHECKING
+ if (it->kind == MACRO_ARG_TOKEN_STRINGIFIED
+ && it->num_forwards > 0)
+ abort ();
+#endif
+ if (it->token_ptr == NULL)
+ return NULL;
+ return *it->token_ptr;
+}
+
+/* Return the location of the token pointed to by the iterator.*/
+static source_location
+macro_arg_token_iter_get_location (const macro_arg_token_iter *it)
+{
+#ifdef ENABLE_CHECKING
+ if (it->kind == MACRO_ARG_TOKEN_STRINGIFIED
+ && it->num_forwards > 0)
+ abort ();
+#endif
+ if (it->track_macro_exp_p)
+ return *it->location_ptr;
+ else
+ return (*it->token_ptr)->src_loc;
+}
+
+/* Return the index of a token [resulting from macro expansion] inside
+ the total list of tokens resulting from a given macro
+ expansion. The index can be different depending on whether if we
+ want each tokens resulting from function-like macro arguments
+ expansion to have a different location or not.
+
+ E.g, consider this function-like macro:
+
+ #define M(x) x - 3
+
+ Then consider us "calling" it (and thus expanding it) like:
+
+ M(1+4)
+
+ It will be expanded into:
+
+ 1+4-3
+
+ Let's consider the case of the token '4'.
+
+ Its index can be 2 (it's the third token of the set of tokens
+ resulting from the expansion) or it can be 0 if we consider that
+ all tokens resulting from the expansion of the argument "1+2" have
+ the same index, which is 0. In this later case, the index of token
+ '-' would then be 1 and the index of token '3' would be 2.
+
+ The later case is useful to use less memory e.g, for the case of
+ the user using the option -ftrack-macro-expansion=1.
+
+ ABSOLUTE_TOKEN_INDEX is the index of the macro argument token we
+ are interested in. CUR_REPLACEMENT_TOKEN is the token of the macro
+ parameter (inside the macro replacement list) that corresponds to
+ the macro argument for which ABSOLUTE_TOKEN_INDEX is a token index
+ of.
+
+ If we refer to the example above, for the '4' argument token,
+ ABSOLUTE_TOKEN_INDEX would be set to 2, and CUR_REPLACEMENT_TOKEN
+ would be set to the token 'x', in the replacement list "x - 3" of
+ macro M.
+
+ This is a subroutine of replace_args. */
+inline static unsigned
+expanded_token_index (cpp_reader *pfile, cpp_macro *macro,
+ const cpp_token *cur_replacement_token,
+ unsigned absolute_token_index)
+{
+ if (CPP_OPTION (pfile, track_macro_expansion) > 1)
+ return absolute_token_index;
+ return cur_replacement_token - macro->exp.tokens;
+}
+
/* Replace the parameters in a function-like macro of NODE with the
actual ARGS, and place the result in a newly pushed token context.
Expand each argument before replacing, unless it is operated upon
- by the # or ## operators. */
+ by the # or ## operators. EXPANSION_POINT_LOC is the location of
+ the expansion point of the macro. E.g, the location of the
+ function-like macro invocation. */
static void
-replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg *args)
+replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
+ macro_arg *args, source_location expansion_point_loc)
{
unsigned int i, total;
const cpp_token *src, *limit;
- const cpp_token **dest, **first;
+ const cpp_token **first = NULL;
macro_arg *arg;
- _cpp_buff *buff;
- unsigned int count;
+ _cpp_buff *buff = NULL;
+ source_location *virt_locs = NULL;
+ unsigned int exp_count;
+ const struct line_map *map = NULL;
+ int track_macro_exp;
/* 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. */
- count = macro_real_token_count (macro);
- total = count;
- limit = macro->exp.tokens + count;
+
+ /* EXP_COUNT is the number of tokens in the macro replacement
+ list. TOTAL is the number of tokens /after/ macro parameters
+ have been replaced by their arguments. */
+ exp_count = macro_real_token_count (macro);
+ total = exp_count;
+ limit = macro->exp.tokens + exp_count;
for (src = macro->exp.tokens; src < limit; src++)
if (src->type == CPP_MACRO_ARG)
{
/* Leading and trailing padding tokens. */
total += 2;
+ /* Account for leading and padding tokens in exp_count too.
+ This is going to be important later down this function,
+ when we want to handle the case of (track_macro_exp <
+ 2). */
+ exp_count += 2;
/* We have an argument. If it is not being stringified or
pasted it is macro-replaced before insertion. */
@@ -970,67 +1464,230 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg
}
}
- /* Now allocate space for the expansion, copy the tokens and replace
- the arguments. */
- buff = _cpp_get_buff (pfile, total * sizeof (cpp_token *));
+ /* When the compiler is called with the -ftrack-macro-expansion
+ flag, we need to keep track of the location of each token that
+ results from macro expansion.
+
+ A token resulting from macro expansion is not a new token. It is
+ simply the same token as the token coming from the macro
+ definition. The new things that are allocated are the buffer
+ that holds the tokens resulting from macro expansion and a new
+ location that records many things like the locus of the expansion
+ point as well as the original locus inside the definition of the
+ macro. This location is called a virtual location.
+
+ So the buffer BUFF holds a set of cpp_token*, and the buffer
+ VIRT_LOCS holds the virtual locations of the tokens held by BUFF.
+
+ Both of these two buffers are going to be hung off of the macro
+ context, when the latter is pushed. The memory allocated to
+ store the tokens and their locations is going to be freed once
+ the context of macro expansion is popped.
+
+ As far as tokens are concerned, the memory overhead of
+ -ftrack-macro-expansion is proportional to the number of
+ macros that get expanded multiplied by sizeof (source_location).
+ The good news is that extra memory gets freed when the macro
+ context is freed, i.e shortly after the macro got expanded. */
+
+ /* Is the -ftrack-macro-expansion flag in effect? */
+ track_macro_exp = CPP_OPTION (pfile, track_macro_expansion);
+
+ /* Now allocate memory space for tokens and locations resulting from
+ the macro expansion, copy the tokens and replace the arguments.
+ This memory must be freed when the context of the macro MACRO is
+ popped. */
+ buff = tokens_buff_new (pfile, total, track_macro_exp ? &virt_locs : NULL);
+
first = (const cpp_token **) buff->base;
- dest = first;
+ /* Create a macro map to record the locations of the tokens that are
+ involved in the expansion. Note that the expansion point is set
+ to the location of the closing parenthesis. Otherwise, the
+ subsequent map created for the first token that comes after the
+ macro map might have a wrong line number. That would lead to
+ tokens with wrong line numbers after the macro expansion. This
+ adds up to the memory overhead of the -ftrack-macro-expansion
+ flag; for every macro that is expanded, a "macro map" is
+ created. */
+ if (track_macro_exp)
+ {
+ int num_macro_tokens = total;
+ if (track_macro_exp < 2)
+ /* Then the number of macro tokens won't take in account the
+ fact that function-like macro arguments can expand to
+ multiple tokens. This is to save memory at the expense of
+ accuracy.
+
+ Suppose we have #define SQARE(A) A * A
+
+ And then we do SQARE(2+3)
+
+ Then the tokens 2, +, 3, will have the same location,
+ saying they come from the expansion of the argument A. */
+ num_macro_tokens = exp_count;
+ map = linemap_enter_macro (pfile->line_table, node,
+ expansion_point_loc,
+ num_macro_tokens);
+ }
+ i = 0;
for (src = macro->exp.tokens; src < limit; src++)
{
- unsigned int count;
- const cpp_token **from, **paste_flag;
+ unsigned int arg_tokens_count;
+ macro_arg_token_iter from;
+ const cpp_token **paste_flag = NULL;
+ const cpp_token **tmp_token_ptr;
if (src->type != CPP_MACRO_ARG)
{
- *dest++ = src;
+ /* Allocate a virtual location for token SRC, and add that
+ token and its virtual location into the buffers BUFF and
+ VIRT_LOCS. */
+ unsigned index = expanded_token_index (pfile, macro, src, i);
+ tokens_buff_add_token (buff, virt_locs, src,
+ src->src_loc, src->src_loc,
+ map, index);
+ i += 1;
continue;
}
paste_flag = 0;
arg = &args[src->val.macro_arg.arg_no - 1];
+ /* SRC is a macro parameter that we need to replace with its
+ corresponding argument. So at some point we'll need to
+ iterate over the tokens of the macro argument and copy them
+ into the "place" now holding the correspondig macro
+ parameter. We are going to use the iterator type
+ macro_argo_token_iter to handle that iterating. The 'if'
+ below is to initialize the iterator depending on the type of
+ tokens the macro argument has. It also does some adjustment
+ related to padding tokens and some pasting corner cases. */
if (src->flags & STRINGIFY_ARG)
- count = 1, from = &arg->stringified;
+ {
+ arg_tokens_count = 1;
+ macro_arg_token_iter_init (&from,
+ CPP_OPTION (pfile,
+ track_macro_expansion),
+ MACRO_ARG_TOKEN_STRINGIFIED,
+ arg, &arg->stringified);
+ }
else if (src->flags & PASTE_LEFT)
- count = arg->count, from = arg->first;
+ {
+ arg_tokens_count = arg->count;
+ macro_arg_token_iter_init (&from,
+ CPP_OPTION (pfile,
+ track_macro_expansion),
+ MACRO_ARG_TOKEN_NORMAL,
+ arg, arg->first);
+ }
else if (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT))
{
- count = arg->count, from = arg->first;
- if (dest != first)
+ int num_toks;
+ arg_tokens_count = arg->count;
+ macro_arg_token_iter_init (&from,
+ CPP_OPTION (pfile,
+ track_macro_expansion),
+ MACRO_ARG_TOKEN_NORMAL,
+ arg, arg->first);
+
+ num_toks = tokens_buff_count (buff);
+
+ if (num_toks != 0)
{
- if (dest[-1]->type == CPP_COMMA
+ /* So the current parameter token is pasted to the previous
+ token in the replacement list. Let's look at what
+ we have as previous and current arguments. */
+
+ /* This is the previous argument's token ... */
+ tmp_token_ptr = tokens_buff_last_token_ptr (buff);
+
+ if ((*tmp_token_ptr)->type == CPP_COMMA
&& macro->variadic
&& src->val.macro_arg.arg_no == macro->paramc)
{
- /* Swallow a pasted comma if from == NULL, otherwise
- drop the paste flag. */
- if (from == NULL)
- dest--;
+ /* ... which is a comma; and the current parameter
+ is the last parameter of a variadic function-like
+ macro. If the argument to the current last
+ parameter is NULL, then swallow the comma,
+ otherwise drop the paste flag. */
+ if (macro_arg_token_iter_get_token (&from) == NULL)
+ tokens_buff_remove_last_token (buff);
else
- paste_flag = dest - 1;
+ paste_flag = tmp_token_ptr;
}
/* Remove the paste flag if the RHS is a placemarker. */
- else if (count == 0)
- paste_flag = dest - 1;
+ else if (arg_tokens_count == 0)
+ paste_flag = tmp_token_ptr;
}
}
else
- count = arg->expanded_count, from = arg->expanded;
+ {
+ arg_tokens_count = arg->expanded_count;
+ macro_arg_token_iter_init (&from,
+ CPP_OPTION (pfile,
+ track_macro_expansion),
+ MACRO_ARG_TOKEN_EXPANDED,
+ arg, arg->expanded);
+ }
/* Padding on the left of an argument (unless RHS of ##). */
if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
&& src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT))
- *dest++ = padding_token (pfile, src);
+ {
+ const cpp_token *t = padding_token (pfile, src);
+ unsigned index = expanded_token_index (pfile, macro, src, i);
+ /* Allocate a virtual location for the padding token and
+ append the token and its location to BUFF and
+ VIRT_LOCS. */
+ tokens_buff_add_token (buff, virt_locs, t,
+ t->src_loc, t->src_loc,
+ map, index);
+ }
- if (count)
+ if (arg_tokens_count)
{
- memcpy (dest, from, count * sizeof (cpp_token *));
- dest += count;
+ /* So now we've got the number of tokens that make up the
+ argument that is going to replace the current parameter
+ in the macro's replacement list. */
+ unsigned int j;
+ for (j = 0; j < arg_tokens_count; ++j)
+ {
+ /* So if track_macro_exp is < 2, the user wants to
+ save extra memory while tracking macro expansion
+ locations. So in that case here is what we do:
+
+ Suppose we have #define SQARE(A) A * A
+
+ And then we do SQARE(2+3)
+
+ Then the tokens 2, +, 3, will have the same location,
+ saying they come from the expansion of the argument
+ A.
+
+ So that means we are going to ignore the COUNT tokens
+ resulting from the expansion of the current macro
+ arugment. In other words all the ARG_TOKENS_COUNT tokens
+ resulting from the expansion of the macro argument will
+ have the index I. Normally, each of those token should
+ have index I+J. */
+ unsigned token_index = i;
+ unsigned index;
+ if (track_macro_exp > 1)
+ token_index += j;
+
+ index = expanded_token_index (pfile, macro, src, token_index);
+ tokens_buff_add_token (buff, virt_locs,
+ macro_arg_token_iter_get_token (&from),
+ macro_arg_token_iter_get_location (&from),
+ src->src_loc, map, index);
+ macro_arg_token_iter_forward (&from);
+ }
/* With a non-empty argument on the LHS of ##, the last
token should be flagged PASTE_LEFT. */
if (src->flags & PASTE_LEFT)
- paste_flag = dest - 1;
+ paste_flag =
+ (const cpp_token **) tokens_buff_last_token_ptr (buff);
}
else if (CPP_PEDANTIC (pfile) && ! macro->syshdr
&& ! CPP_OPTION (pfile, c99)
@@ -1046,7 +1703,12 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg
/* Avoid paste on RHS (even case count == 0). */
if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT))
- *dest++ = &pfile->avoid_paste;
+ {
+ const cpp_token *t = &pfile->avoid_paste;
+ tokens_buff_add_token (buff, virt_locs,
+ t, t->src_loc, t->src_loc,
+ NULL, 0);
+ }
/* Add a new paste flag, or remove an unwanted one. */
if (paste_flag)
@@ -1060,13 +1722,18 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, macro_arg
token->flags = (*paste_flag)->flags & ~PASTE_LEFT;
*paste_flag = token;
}
+
+ i += arg_tokens_count;
}
- /* Free the expanded arguments. */
- for (i = 0; i < macro->paramc; i++)
- free (args[i].expanded);
+ if (track_macro_exp)
+ push_extended_tokens_context (pfile, node, buff, virt_locs, first,
+ tokens_buff_count (buff));
+ else
+ push_ptoken_context (pfile, node, buff, first,
+ tokens_buff_count (buff));
- push_ptoken_context (pfile, node, buff, first, dest - first);
+ num_macro_tokens_counter += tokens_buff_count (buff);
}
/* Return a special padding token, with padding inherited from SOURCE. */
@@ -1094,6 +1761,7 @@ next_context (cpp_reader *pfile)
if (result == 0)
{
result = XNEW (cpp_context);
+ memset (result, 0, sizeof (cpp_context));
result->prev = pfile->context;
result->next = 0;
pfile->context->next = result;
@@ -1110,8 +1778,8 @@ push_ptoken_context (cpp_reader *pfile, cpp_hashnode *macro, _cpp_buff *buff,
{
cpp_context *context = next_context (pfile);
- context->direct_p = false;
- context->macro = macro;
+ context->tokens_kind = TOKENS_KIND_INDIRECT;
+ context->c.macro = macro;
context->buff = buff;
FIRST (context).ptoken = first;
LAST (context).ptoken = first + count;
@@ -1122,15 +1790,44 @@ void
_cpp_push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
const cpp_token *first, unsigned int count)
{
- cpp_context *context = next_context (pfile);
-
- context->direct_p = true;
- context->macro = macro;
- context->buff = NULL;
+ cpp_context *context = next_context (pfile);
+
+ context->tokens_kind = TOKENS_KIND_DIRECT;
+ context->c.macro = macro;
+ context->buff = NULL;
FIRST (context).token = first;
LAST (context).token = first + count;
}
+/* Build a context containing a list of tokens as well as their
+ virtual locations and push it. TOKENS_BUFF is the buffer that
+ contains the tokens pointed to by FIRST. If TOKENS_BUFF is
+ non-NULL, it means that the context owns it, meaning that
+ _cpp_pop_context will free it as well as VIRT_LOCS_BUFF that
+ contains the virtual locations. */
+static void
+push_extended_tokens_context (cpp_reader *pfile,
+ cpp_hashnode *macro,
+ _cpp_buff *token_buff,
+ source_location *virt_locs,
+ const cpp_token **first,
+ unsigned int count)
+{
+ cpp_context *context = next_context (pfile);
+ macro_context *m;
+
+ context->tokens_kind = TOKENS_KIND_EXTENDED;
+ context->buff = token_buff;
+
+ m = XNEW (macro_context);
+ m->macro_node = macro;
+ m->virt_locs = virt_locs;
+ m->cur_virt_loc = virt_locs;
+ context->c.mc = m;
+ FIRST (context).ptoken = first;
+ LAST (context).ptoken = first + count;
+}
+
/* Push a traditional macro's replacement text. */
void
_cpp_push_text_context (cpp_reader *pfile, cpp_hashnode *macro,
@@ -1138,14 +1835,200 @@ _cpp_push_text_context (cpp_reader *pfile, cpp_hashnode *macro,
{
cpp_context *context = next_context (pfile);
- context->direct_p = true;
- context->macro = macro;
+ context->tokens_kind = TOKENS_KIND_DIRECT;
+ context->c.macro = macro;
context->buff = NULL;
CUR (context) = start;
RLIMIT (context) = start + len;
macro->flags |= NODE_DISABLED;
}
+/* Creates a buffer that holds tokens a.k.a "token buffer", usually
+ for the purpose of storing them on a cpp_context. If VIRT_LOCS is
+ non-null (which means that -ftrack-macro-expansion is on),
+ *VIRT_LOCS is set to a newly allocated buffer that is supposed to
+ hold the virtual locations of the tokens resulting from macro
+ expansion. */
+static _cpp_buff*
+tokens_buff_new (cpp_reader *pfile, size_t len,
+ source_location **virt_locs)
+{
+ size_t tokens_size = len * sizeof (cpp_token *);
+ size_t locs_size = len * sizeof (source_location);
+
+ if (virt_locs != NULL)
+ *virt_locs = XNEWVEC (source_location, locs_size);
+ return _cpp_get_buff (pfile, tokens_size);
+}
+
+/* Returns the number of tokens contained in a token buffer. The
+ buffer holds a set of cpp_token*. */
+static size_t
+tokens_buff_count (_cpp_buff *buff)
+{
+ return (BUFF_FRONT (buff) - buff->base) / sizeof (cpp_token *);
+}
+
+/* Return a pointer to the last token contained in the token buffer
+ BUFF. */
+static const cpp_token **
+tokens_buff_last_token_ptr (_cpp_buff *buff)
+{
+ return &((const cpp_token **) BUFF_FRONT (buff))[-1];
+}
+
+/* Remove the last token contained in the token buffer TOKENS_BUFF.
+ If VIRT_LOCS_BUFF is non-NULL, it should point at the buffer
+ containing the virtual locations of the tokens in TOKENS_BUFF; in
+ which case the function updates that buffer as well. */
+static inline void
+tokens_buff_remove_last_token (_cpp_buff *tokens_buff)
+
+{
+ if (BUFF_FRONT (tokens_buff) > tokens_buff->base)
+ BUFF_FRONT (tokens_buff) =
+ (unsigned char *) &((cpp_token **) BUFF_FRONT (tokens_buff))[-1];
+}
+
+/* Insert a token into the token buffer at the position pointed to by
+ DEST. Note that the buffer is not enlarged so the previous token
+ that was at *DEST is overwritten. VIRT_LOC_DEST, if non-null,
+ means -ftrack-macro-expansion is effect; it then points to where to
+ insert the virtual location of TOKEN. TOKEN is the token to
+ insert. VIRT_LOC is the virtual location of the token, i.e, the
+ location possibly encoding its locus accross macro expansion. If
+ TOKEN is an argument of a function-like macro (inside a macro
+ replacement list), PARM_DEF_LOC is the spelling location of the
+ macro parameter that TOKEN is replacing, in the replacement list of
+ the macro. If TOKEN is not an argument of a function-like macro or
+ if it doesn't come from a macro expansion, then VIRT_LOC can just
+ be set to the same value as PARM_DEF_LOC. If MAP is non null, it
+ means TOKEN comes from a macro expansion and MAP is the macro map
+ associated to the macro. MACRO_TOKEN_INDEX points to the index of
+ the token in the macro map; it is not considered if MAP is NULL.
+
+ Upon successful completion this function returns the a pointer to
+ the position of the token coming right after the insertion
+ point. */
+static inline const cpp_token **
+tokens_buff_put_token_to (const cpp_token **dest,
+ source_location *virt_loc_dest,
+ const cpp_token *token,
+ source_location virt_loc,
+ source_location parm_def_loc,
+ const struct line_map *map,
+ unsigned int macro_token_index)
+{
+ source_location macro_loc = virt_loc;
+ const cpp_token **result;
+
+ if (virt_loc_dest)
+ {
+ /* -ftrack-macro-expansion is on. */
+ if (map)
+ macro_loc = linemap_add_macro_token (map, macro_token_index,
+ virt_loc, parm_def_loc);
+ *virt_loc_dest = macro_loc;
+ }
+ *dest = token;
+ result = &dest[1];
+
+ return result;
+}
+
+/* Adds a token at the end of the tokens contained in BUFFER. Note
+ that this function doesn't enlarge BUFFER when the number of tokens
+ reaches BUFFER's size; it aborts in that situation.
+
+ TOKEN is the token to append. VIRT_LOC is the virtual location of
+ the token, i.e, the location possibly encoding its locus accross
+ macro expansion. If TOKEN is an argument of a function-like macro
+ (inside a macro replacement list), PARM_DEF_LOC is the location of
+ the macro parameter that TOKEN is replacing. If TOKEN doesn't come
+ from a macro expansion, then VIRT_LOC can just be set to the same
+ value as PARM_DEF_LOC. If MAP is non null, it means TOKEN comes
+ from a macro expansion and MAP is the macro map associated to the
+ macro. MACRO_TOKEN_INDEX points to the index of the token in the
+ macro map; It is not considered if MAP is NULL. If VIRT_LOCS is
+ non-null, it means -ftrack-macro-expansion is on; in which case
+ this function adds the virtual location DEF_LOC to the VIRT_LOCS
+ array, at the same index as the one of TOKEN in BUFFER. Upon
+ successful completion this function returns the a pointer to the
+ position of the token coming right after the insertion point. */
+static const cpp_token **
+tokens_buff_add_token (_cpp_buff *buffer,
+ source_location *virt_locs,
+ const cpp_token *token,
+ source_location virt_loc,
+ source_location parm_def_loc,
+ const struct line_map *map,
+ unsigned int macro_token_index)
+{
+ const cpp_token **result;
+ source_location *virt_loc_dest = NULL;
+ unsigned token_index =
+ (BUFF_FRONT (buffer) - buffer->base) / sizeof (cpp_token *);
+
+ /* Abort if we pass the end the buffer. */
+ if (BUFF_FRONT (buffer) > BUFF_LIMIT (buffer))
+ abort ();
+
+ if (virt_locs != NULL)
+ virt_loc_dest = &virt_locs[token_index];
+
+ result =
+ tokens_buff_put_token_to ((const cpp_token **) BUFF_FRONT (buffer),
+ virt_loc_dest, token, virt_loc, parm_def_loc,
+ map, macro_token_index);
+
+ BUFF_FRONT (buffer) = (unsigned char *) result;
+ return result;
+}
+
+/* Allocate space for the function-like macro argument ARG to store
+ the tokens resulting from the macro-expansion of the tokens that
+ make up ARG itself. That space is allocated in ARG->expanded and
+ needs to be freed using free. */
+static void
+alloc_expanded_arg_mem (cpp_reader *pfile, macro_arg *arg, size_t capacity)
+{
+#ifdef ENABLE_CHECKING
+ if (arg->expanded != NULL
+ || arg->expanded_virt_locs != NULL)
+ abort ();
+#endif
+ arg->expanded = XNEWVEC (const cpp_token *, capacity);
+ if (CPP_OPTION (pfile, track_macro_expansion))
+ arg->expanded_virt_locs = XNEWVEC (source_location, capacity);
+
+}
+
+/* If necessary, enlarge ARG->expanded to so that it can contain SIZE
+ tokens. */
+static void
+ensure_expanded_arg_room (cpp_reader *pfile, macro_arg *arg,
+ size_t size, size_t *expanded_capacity)
+{
+ if (size <= *expanded_capacity)
+ return;
+
+ size *= 2;
+
+ arg->expanded =
+ XRESIZEVEC (const cpp_token *, arg->expanded, size);
+ *expanded_capacity = size;
+
+ if (CPP_OPTION (pfile, track_macro_expansion))
+ {
+ if (arg->expanded_virt_locs == NULL)
+ arg->expanded_virt_locs = XNEWVEC (source_location, size);
+ else
+ arg->expanded_virt_locs = XRESIZEVEC (source_location,
+ arg->expanded_virt_locs,
+ size);
+ }
+}
+
/* Expand an argument ARG before replacing parameters in a
function-like macro. This works by pushing a context with the
argument's tokens, and then expanding that into a temporary buffer
@@ -1155,38 +2038,48 @@ _cpp_push_text_context (cpp_reader *pfile, cpp_hashnode *macro,
static void
expand_arg (cpp_reader *pfile, macro_arg *arg)
{
- unsigned int capacity;
+ size_t capacity;
bool saved_warn_trad;
+ bool track_macro_exp_p = CPP_OPTION (pfile, track_macro_expansion);
- if (arg->count == 0)
+ if (arg->count == 0
+ || arg->expanded != NULL)
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. */
+ /* Loop, reading in the tokens of the argument. */
capacity = 256;
- arg->expanded = XNEWVEC (const cpp_token *, capacity);
+ alloc_expanded_arg_mem (pfile, arg, capacity);
+
+ if (track_macro_exp_p)
+ push_extended_tokens_context (pfile, NULL, NULL,
+ arg->virt_locs,
+ arg->first,
+ arg->count + 1);
+ else
+ push_ptoken_context (pfile, NULL, NULL,
+ arg->first, arg->count + 1);
- push_ptoken_context (pfile, NULL, NULL, arg->first, arg->count + 1);
for (;;)
{
const cpp_token *token;
+ source_location location;
- if (arg->expanded_count + 1 >= capacity)
- {
- capacity *= 2;
- arg->expanded = XRESIZEVEC (const cpp_token *, arg->expanded,
- capacity);
- }
+ ensure_expanded_arg_room (pfile, arg, arg->expanded_count + 1,
+ &capacity);
- token = cpp_get_token (pfile);
+ token = cpp_get_token_1 (pfile, &location);
if (token->type == CPP_EOF)
break;
- arg->expanded[arg->expanded_count++] = token;
+ set_arg_token (arg, token, location,
+ arg->expanded_count, MACRO_ARG_TOKEN_EXPANDED,
+ CPP_OPTION (pfile, track_macro_expansion));
+ arg->expanded_count++;
}
_cpp_pop_context (pfile);
@@ -1195,25 +2088,132 @@ expand_arg (cpp_reader *pfile, macro_arg *arg)
}
/* Pop the current context off the stack, re-enabling the macro if the
- context represented a macro's replacement list. The context
- structure is not freed so that we can re-use it later. */
+ context represented a macro's replacement list. Initially the
+ context structure was not freed so that we can re-use it later, but
+ now we do free it to reduce peak memory consumption. */
void
_cpp_pop_context (cpp_reader *pfile)
{
cpp_context *context = pfile->context;
- if (context->macro)
- context->macro->flags &= ~NODE_DISABLED;
+ if (context->c.macro)
+ {
+ cpp_hashnode *macro;
+ if (context->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ macro_context *mc = context->c.mc;
+ macro = mc->macro_node;
+ /* If context->buff is set, it means the life time of tokens
+ is bound to the life time of this context; so we must
+ free the tokens; that means we must free the virtual
+ locations of these tokens too. */
+ if (context->buff && mc->virt_locs)
+ {
+ free (mc->virt_locs);
+ mc->virt_locs = NULL;
+ }
+ free (mc);
+ context->c.mc = NULL;
+ }
+ else
+ macro = context->c.macro;
+
+ /* Beware that MACRO can be NULL in cases like when we are
+ called from expand_arg. In those cases, a dummy context with
+ tokens is pushed just for the purpose of walking them using
+ cpp_get_token_1. In that case, no 'macro' field is set into
+ the dummy context. */
+ if (macro != NULL)
+ macro->flags &= ~NODE_DISABLED;
+ }
if (context->buff)
- _cpp_release_buff (pfile, context->buff);
+ {
+ /* Decrease memory peak consumption by freeing the memory used
+ by the context. */
+ _cpp_free_buff (context->buff);
+ }
pfile->context = context->prev;
+ /* decrease peak memory consumption by feeing the context. */
+ pfile->context->next = NULL;
+ free (context);
}
-/* External routine to get a token. Also used nearly everywhere
- internally, except for places where we know we can safely call
- _cpp_lex_token directly, such as lexing a directive name.
+/* Return TRUE if we reached the end of the set of tokens stored in
+ CONTEXT, FALSE otherwise. */
+static inline bool
+reached_end_of_context (cpp_context *context)
+{
+ if (context->tokens_kind == TOKENS_KIND_DIRECT)
+ return FIRST (context).token == LAST (context).token;
+ else if (context->tokens_kind == TOKENS_KIND_INDIRECT
+ || context->tokens_kind == TOKENS_KIND_EXTENDED)
+ return FIRST (context).ptoken == LAST (context).ptoken;
+ else
+ abort ();
+}
+
+/* Consume the next token contained in the current context of PFILE,
+ and return it in *TOKEN. It's "full location" is returned in
+ *LOCATION. If -ftrack-macro-location is in effeect, fFull location"
+ means the location encoding the locus of the token accross macro
+ expansion; otherwise it's just is the "normal" location of the
+ token which (*TOKEN)->src_loc. */
+static inline void
+consume_next_token_from_context (cpp_reader *pfile,
+ const cpp_token ** token,
+ source_location *location)
+{
+ cpp_context *c = pfile->context;
+
+ if ((c)->tokens_kind == TOKENS_KIND_DIRECT)
+ {
+ *token = FIRST (c).token;
+ *location = (*token)->src_loc;
+ FIRST (c).token++;
+ }
+ else if ((c)->tokens_kind == TOKENS_KIND_INDIRECT)
+ {
+ *token = *FIRST (c).ptoken;
+ *location = (*token)->src_loc;
+ FIRST (c).ptoken++;
+ }
+ else if ((c)->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ macro_context *m = c->c.mc;
+ *token = *FIRST (c).ptoken;
+ if (m->virt_locs)
+ {
+ *location = *m->cur_virt_loc;
+ m->cur_virt_loc++;
+ }
+ else
+ *location = (*token)->src_loc;
+ FIRST (c).ptoken++;
+ }
+ else
+ abort ();
+}
+
+/* In the traditional mode of the preprocessor, if we are currently in
+ a directive, the location of a token must be the location of the
+ start of the directive line. This function returns the proper
+ location if we are in the traditional mode, and just returns
+ LOCATION otherwise. */
+
+static inline source_location
+maybe_adjust_loc_for_trad_cpp (cpp_reader *pfile, source_location location)
+{
+ if (CPP_OPTION (pfile, traditional))
+ {
+ if (pfile->state.in_directive)
+ return pfile->directive_line;
+ }
+ return location;
+}
+
+/* Routine to get a token as well as its location.
Macro expansions and directives are transparently handled,
including entering included files. Thus tokens are post-macro
@@ -1221,12 +2221,20 @@ _cpp_pop_context (cpp_reader *pfile)
see CPP_EOF only at EOF. Internal callers also see it when meeting
a directive inside a macro call, when at the end of a directive and
state.in_directive is still 1, and at the end of argument
- pre-expansion. */
-const cpp_token *
-cpp_get_token (cpp_reader *pfile)
+ pre-expansion.
+
+ LOC is an out parameter; *LOC is set to the location "as expected
+ by the user". Please read the comment of
+ cpp_get_token_with_location to learn more about the meaning of this
+ location. */
+static const cpp_token*
+cpp_get_token_1 (cpp_reader *pfile, source_location *location)
{
const cpp_token *result;
bool can_set = pfile->set_invocation_location;
+ /* This token is a virtual token that either encodes a location
+ related to macro expansion or a spelling location. */
+ source_location virt_loc = 0;
pfile->set_invocation_location = false;
for (;;)
@@ -1236,28 +2244,32 @@ cpp_get_token (cpp_reader *pfile)
/* Context->prev == 0 <=> base context. */
if (!context->prev)
- result = _cpp_lex_token (pfile);
- else if (FIRST (context).token != LAST (context).token)
{
- if (context->direct_p)
- result = FIRST (context).token++;
- else
- result = *FIRST (context).ptoken++;
-
+ result = _cpp_lex_token (pfile);
+ virt_loc = result->src_loc;
+ }
+ else if (!reached_end_of_context (context))
+ {
+ consume_next_token_from_context (pfile, &result,
+ &virt_loc);
if (result->flags & PASTE_LEFT)
{
paste_all_tokens (pfile, result);
if (pfile->state.in_directive)
continue;
- return padding_token (pfile, result);
+ result = padding_token (pfile, result);
+ goto out;
}
}
else
{
+ if (pfile->context->c.macro)
+ ++num_expanded_macros_counter;
_cpp_pop_context (pfile);
if (pfile->state.in_directive)
continue;
- return &pfile->avoid_paste;
+ result = &pfile->avoid_paste;
+ goto out;
}
if (pfile->state.in_directive && result->type == CPP_COMMENT)
@@ -1276,7 +2288,7 @@ cpp_get_token (cpp_reader *pfile)
int ret = 0;
/* If not in a macro context, and we're going to start an
expansion, record the location. */
- if (can_set && !context->macro)
+ if (can_set && !context->c.macro)
pfile->invocation_location = result->src_loc;
if (pfile->state.prevent_expansion)
break;
@@ -1294,7 +2306,8 @@ cpp_get_token (cpp_reader *pfile)
|| (peek_tok->flags & PREV_WHITE));
node = pfile->cb.macro_to_expand (pfile, result);
if (node)
- ret = enter_macro_context (pfile, node, result);
+ ret = enter_macro_context (pfile, node, result,
+ virt_loc);
else if (whitespace_after)
{
/* If macro_to_expand hook returned NULL and it
@@ -1311,12 +2324,14 @@ cpp_get_token (cpp_reader *pfile)
}
}
else
- ret = enter_macro_context (pfile, node, result);
+ ret = enter_macro_context (pfile, node, result,
+ virt_loc);
if (ret)
{
if (pfile->state.in_directive || ret == 2)
continue;
- return padding_token (pfile, result);
+ result = padding_token (pfile, result);
+ goto out;
}
}
else
@@ -1333,27 +2348,88 @@ cpp_get_token (cpp_reader *pfile)
break;
}
+ out:
+ if (location != NULL)
+ {
+ if (virt_loc == 0)
+ virt_loc = result->src_loc;
+ *location = virt_loc;
+
+ if (!CPP_OPTION (pfile, track_macro_expansion)
+ && can_set
+ && pfile->context->c.macro != NULL)
+ /* We are in a macro expansion context, are not tracking
+ virtual location, but were asked to report the location
+ of the expansion point of the macro being expanded. */
+ *location = pfile->invocation_location;
+
+ *location = maybe_adjust_loc_for_trad_cpp (pfile, *location);
+ }
return result;
}
-/* Like cpp_get_token, but also returns a location separate from the
- one provided by the returned token. LOC is an out parameter; *LOC
- is set to the location "as expected by the user". This matters
- when a token results from macro expansion -- the token's location
- will indicate where the macro is defined, but *LOC will be the
- location of the start of the expansion. */
+/* External routine to get a token. Also used nearly everywhere
+ internally, except for places where we know we can safely call
+ _cpp_lex_token directly, such as lexing a directive name.
+
+ Macro expansions and directives are transparently handled,
+ including entering included files. Thus tokens are post-macro
+ expansion, and after any intervening directives. External callers
+ see CPP_EOF only at EOF. Internal callers also see it when meeting
+ a directive inside a macro call, when at the end of a directive and
+ state.in_directive is still 1, and at the end of argument
+ pre-expansion. */
+const cpp_token *
+cpp_get_token (cpp_reader *pfile)
+{
+ return cpp_get_token_1 (pfile, NULL);
+}
+
+/* Like cpp_get_token, but also returns a virtual token location
+ separate from the spelling location carried by the returned token.
+
+ LOC is an out parameter; *LOC is set to the location "as expected
+ by the user". This matters when a token results from macro
+ expansion; in that case the token's spelling location indicates the
+ locus of the token in the definition of the macro but *LOC
+ virtually encodes all the other meaningful locuses associated to
+ the token.
+
+ What? virtual location? Yes, virtual location.
+
+ If the token results from macro expansion and if macro expansion
+ location tracking is enabled its virtual location encodes (at the
+ same time):
+
+ - the spelling location of the token
+
+ - the locus of the macro expansion point
+
+ - the locus of the point where the token got instantiated as part
+ of the macro expansion process.
+
+ You have to use the linemap API to get the locus you are interested
+ in from a given virtual location.
+
+ Note however that virtual locations are not necessarily ordered for
+ relations '<' and '>'. One must use the function
+ linemap_location_before_p instead of using the relational operator
+ '<'.
+
+ If macro expansion tracking is off and if the token results from
+ macro expansion the virtual location is the expansion point of the
+ macro that got expanded.
+
+ When the token doesn't result from macro expansion, the virtual
+ location is just the same thing as its spelling location. */
+
const cpp_token *
cpp_get_token_with_location (cpp_reader *pfile, source_location *loc)
{
const cpp_token *result;
pfile->set_invocation_location = true;
- result = cpp_get_token (pfile);
- if (pfile->context->macro)
- *loc = pfile->invocation_location;
- else
- *loc = result->src_loc;
-
+ result = cpp_get_token_1 (pfile, loc);
return result;
}
@@ -1363,7 +2439,7 @@ cpp_get_token_with_location (cpp_reader *pfile, source_location *loc)
int
cpp_sys_macro_p (cpp_reader *pfile)
{
- cpp_hashnode *node = pfile->context->macro;
+ cpp_hashnode *node = pfile->context->c.macro;
return node && node->value.macro && node->value.macro->syshdr;
}
@@ -1420,10 +2496,27 @@ _cpp_backup_tokens (cpp_reader *pfile, unsigned int count)
{
if (count != 1)
abort ();
- if (pfile->context->direct_p)
+ if (pfile->context->tokens_kind == TOKENS_KIND_DIRECT)
FIRST (pfile->context).token--;
- else
+ else if (pfile->context->tokens_kind == TOKENS_KIND_INDIRECT)
FIRST (pfile->context).ptoken--;
+ else if (pfile->context->tokens_kind == TOKENS_KIND_EXTENDED)
+ {
+ FIRST (pfile->context).ptoken--;
+ if (pfile->context->c.macro)
+ {
+ macro_context *m = pfile->context->c.mc;
+ m->cur_virt_loc--;
+#ifdef ENABLE_CHECKING
+ if (m->cur_virt_loc < m->virt_locs)
+ abort ();
+#endif
+ }
+ else
+ abort ();
+ }
+ else
+ abort ();
}
}
diff --git a/libcpp/traditional.c b/libcpp/traditional.c
index 7ff11bb205e..4206b6fa768 100644
--- a/libcpp/traditional.c
+++ b/libcpp/traditional.c
@@ -738,7 +738,7 @@ recursive_macro (cpp_reader *pfile, cpp_hashnode *node)
do
{
depth++;
- if (context->macro == node && depth > 20)
+ if (context->c.macro == node && depth > 20)
break;
context = context->prev;
}
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 87ba1ca83b7..1bbe29afd05 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,895 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * gthr-single.h, gthr.h: New files.
+ * config/gthr-lynx.h, config/gthr-posix.h., config/gthr-rtems.h,
+ config/gthr-vxworks.h, config/i386/gthr-win32.h,
+ config/mips/gthr-mipssde.h, config/pa/gthr-dce.h,
+ config/rs6000/gthr-aix.h, config/s390/gthr-tpf.h: New files.
+ * config/i386/gthr-win32.c: Include "gthr-win32.h".
+ * configure.ac (thread_header): New variable.
+ Set it depending on target_thread_file.
+ (gthr-default.h): Link from $thread_header.
+ * configure: Regenerate.
+ * Makefile.in (LIBGCC2_CFLAGS): Remove $(GTHREAD_FLAGS).
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * configure.ac (tm_file_): New variable.
+ Determine from tm_file.
+ (tm_file, tm_defines): Substitute.
+ * configure: Regenerate.
+ * mkheader.sh: New file.
+ * Makefile.in (clean): Remove libgcc_tm.h.
+ ($(objects)): Depend on libgcc_tm.h.
+ (libgcc_tm_defines, libgcc_tm_file): New variables.
+ (libgcc_tm.h, libgcc_tm.stamp): New targets.
+ ($(libgcc-objects), $(libgcc-s-objects), $(libgcc-eh-objects))
+ ($(libgcov-objects), $(libunwind-objects), $(libunwind-s-objects))
+ ($(extra-parts)): Depend on libgcc_tm.h.
+ * config.host (tm_defines, tm_file): New variable.
+ (arm*-*-linux*): Set tm_file for arm*-*-linux-*eabi.
+ (arm*-*-uclinux*): Set tm_file for arm*-*-uclinux*eabi.
+ (arm*-*-eabi*, arm*-*-symbianelf*): Set tm_file.
+ (avr-*-rtems*): Likewise.
+ (avr-*-*): Likewise.
+ (frv-*-elf): Likewise.
+ (frv-*-*linux*): Likewise.
+ (h8300-*-rtems*): Likewise.
+ (h8300-*-elf*): Likewise.
+ (i[34567]86-*-darwin*): Likewise.
+ (x86_64-*-darwin*): Likewise.
+ (rx-*-elf): Likewise.
+ (tic6x-*-uclinux): Likewise.
+ (tic6x-*-elf): Likewise.
+ (i[34567]86-*-linux*, x86_64-*-linux*): Likewise.
+ * config/alpha/gthr-posix.c: Include libgcc_tm.h.
+ * config/i386/cygming-crtbegin.c: Likewise.
+ * config/i386/cygming-crtend.c: Likewise.
+ * config/ia64/fde-vms.c: Likewise.
+ * config/ia64/unwind-ia64.c: Likewise.
+ * config/libbid/bid_gcc_intrinsics.h: Likewise.
+ * config/rs6000/darwin-fallback.c: Likewise.
+ * config/stormy16/lib2funcs.c: Likewise.
+ * config/xtensa/unwind-dw2-xtensa.c: Likewise.
+ * crtstuff.c: Likewise.
+ * dfp-bit.h: Likewise.
+ * emutls.c: Likewise.
+ * fixed-bit.c: Likewise.
+ * fp-bit.c: Likewise.
+ * generic-morestack-thread.c: Likewise.
+ * generic-morestack.c: Likewise.
+ * libgcc2.c: Likewise.
+ * libgcov.c: Likewise.
+ * unwind-dw2-fde-dip.c: Likewise.
+ * unwind-dw2-fde.c: Likewise.
+ * unwind-dw2.c: Likewise.
+ * unwind-sjlj.c: Likewise.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * configure.ac: Include ../config/picflag.m4.
+ (GCC_PICFLAG): Call it.
+ Substitute.
+ * configure: Regenerate.
+ * Makefile.in (gcc_srcdir): Remove.
+ (LIBGCC2_DEBUG_CFLAGS, LIBGCC2_CFLAGS, LIBGCC2_INCLUDES)
+ (HOST_LIBGCC2_CFLAGS, PICFLAG, LIB2FUNCS_ST, LIB2FUNCS_EXCLUDE)
+ (LIB2_DIVMOD_FUNCS, LIB2ADD, LIB2ADD_ST): Set.
+ ($(lib2funcs-o), $(lib2funcs-s-o), $(lib2-divmod-o))
+ ($(lib2-divmod-s-o)): Use $(srcdir) to refer to libgcc2.c.
+ Use $<.
+ Remove comment.
+ * libgcc2.c, libgcc2.h, gbl-ctors.h, longlong.h: New files.
+ * siditi-object.mk ($o$(objext), $(o)_s$(objext)): Use $(srcdir)
+ to refer to libgcc2.c.
+ Use $<.
+ * config/darwin-64.c: New file.
+ * config/darwin-crt3.c: Remove comment.
+ * config/divmod.c, config/floatunsidf.c, config/floatunsisf.c,
+ config/floatunsitf.c, config/floatunsixf.c, config/udivmod.c,
+ config/udivmodsi4.c: New files.
+ * config/memcmp.c, config/memcpy.c, config/memmove.c,
+ config/memset.c: New files.
+ * config/t-crtstuff-pic (CRTSTUFF_T_CFLAGS_S): Use $(PICFLAG).
+ * config/t-darwin (HOST_LIBGCC2_CFLAGS): Set.
+ * config/t-freebsd-thread, config/t-libgcc-pic: New files.
+ * config/t-libunwind (HOST_LIBGCC2_CFLAGS): Set.
+ * config/t-openbsd-thread: New file.
+ * config/t-sol2 (HOST_LIBGCC2_CFLAGS): Remove.
+ * config/t-vxworks, config/vxlib-tls.c, config/vxlib.c: New files.
+ * config/alpha/gthr-posix.c, config/alpha/qrnnd.S: New files.
+ * config/alpha/t-alpha (LIB2ADD): Use $(srcdir) to refer to
+ qrnnd.S.
+ Adapt filename.
+ * config/alpha/t-osf-pthread (LIB2ADD): Use $(srcdir)/config/alpha
+ to refer to gthr-posix.c.
+ * config/alpha/t-vms (LIB2ADD): Set.
+ * config/alpha/vms-gcc_shell_handler.c: New file.
+ * config/arm/bpabi.c, config/arm/fp16.c,
+ config/arm/linux-atomic.c, config/arm/linux-atomic-64bit.c,
+ config/arm/unaligned-funcs.c: New files.
+ * config/arm/t-bpabi (LIB2ADD, LIB2ADD_ST): Set.
+ * config/arm/t-elf (HOST_LIBGCC2_CFLAGS): Set.
+ * config/arm/t-linux: Likewise.
+ * config/arm/t-linux-eabi (LIB2ADD_ST): Add.
+ * config/arm/t-netbsd: New file.
+ * config/arm/t-strongarm-elf (HOST_LIBGCC2_CFLAGS): Set.
+ * config/arm/t-symbian (LIB2ADD_ST): Set.
+ * config/avr/t-avr (LIB2FUNCS_EXCLUDE, HOST_LIBGCC2_CFLAGS): Set.
+ * config/bfin/t-crtstuff (CRTSTUFF_T_CFLAGS): Use $(PICFLAG).
+ * config/bfin/t-elf: New file.
+ * config/c6x/eqd.c, config/c6x/eqf.c, config/c6x/ged.c,
+ config/c6x/gef.c, config/c6x/gtd.c, config/c6x/gtf.c,
+ config/c6x/led.c, config/c6x/lef.c, config/c6x/ltd.c,
+ config/c6x/ltf.c: New files.
+ * config/c6x/t-elf (LIB2FUNCS_EXCLUDE, LIB2ADD)
+ (HOST_LIBGCC2_CFLAGS): Set.
+ * config/c6x/t-uclinux (HOST_LIBGCC2_CFLAGS): Set.
+ (CRTSTUFF_T_CFLAGS): Use $(PICFLAG).
+ * config/cris/arit.c, config/cris/mulsi3.S, config/cris/t-cris:
+ New files.
+ * config/cris/t-elfmulti (LIB2ADD_ST): Set.
+ * config/cris/t-linux (HOST_LIBGCC2_CFLAGS): Remove.
+ * config/frv/cmovd.c, config/frv/cmovh.c, config/frv/cmovw.c,
+ config/frv/modi.c, config/frv/uitod.c, config/frv/uitof.c,
+ config/frv/ulltod.c, config/frv/ulltof.c, config/frv/umodi.c: New
+ files.
+ * config/frv/t-frv (LIB2ADD): Set.
+ * config/frv/t-linux (CRTSTUFF_T_CFLAGS): Use $(PICFLAG).
+ * config/h8300/clzhi2.c, config/h8300/ctzhi2.c,
+ config/h8300/fixunssfsi.c, config/h8300/parityhi2.c,
+ config/h8300/popcounthi2.c: New files.
+ * config/h8300/t-h8300 (LIB2ADD, HOST_LIBGCC2_CFLAGS): Set.
+ * config/i386/gthr-win32.c: New file.
+ * config/i386/t-cygming (LIBGCC2_INCLUDES): Set.
+ * config/i386/t-cygwin: Likewise.
+ * config/i386/t-darwin, config/i386/t-darwin64,
+ config/i386/t-gthr-win32, config/i386/t-interix: New files.
+ * config/i386/t-nto (HOST_LIBGCC2_CFLAGS): Set.
+ (CRTSTUFF_T_CFLAGS): Use $(PICFLAG).
+ * config/i386/t-sol2 (CRTSTUFF_T_CFLAGS): Use $(PICFLAG).
+ * config/ia64/quadlib.c: New file.
+ * config/ia64/t-hpux (LIB2ADD): Set.
+ * config/ia64/t-ia64: Add comment.
+ * config/iq2000/lib2funcs.c, config/iq2000/t-iq2000: New files.
+ * config/lm32/t-uclinux (CRTSTUFF_T_CFLAGS): Use $(PICFLAG).
+ (HOST_LIBGCC2_CFLAGS): Append, remove -fPIC.
+ * config/m32c/lib2funcs.c, config/m32c/trapv.c: New files.
+ * config/m32c/t-m32c (LIB2ADD): Set.
+ * config/m32r/t-linux (HOST_LIBGCC2_CFLAGS): Set.
+ * config/m32r/t-m32r: Likewise.
+ * config/m68k/fpgnulib.c: New file.
+ * config/m68k/t-floatlib (LIB2ADD): Set.
+ (xfgnulib.c): New target.
+ * config/mcore/t-mcore (HOST_LIBGCC2_CFLAGS): Set.
+ * config/mep/lib2funcs.c, config/mep/tramp.c: New files.
+ * config/mep/t-mep (LIB2ADD): Set.
+ * config/microblaze/divsi3.asm: Rename to divsi3.S.
+ * config/microblaze/moddi3.asm: Rename to moddi3.S.
+ * config/microblaze/modsi3.asm: Rename to modsi3.S.
+ * config/microblaze/muldi3_hard.asm: Rename to hard.S.
+ * config/microblaze/mulsi3.asm: Rename to mulsi3.S.
+ * config/microblaze/stack_overflow_exit.asm: Rename to exit.S.
+ * config/microblaze/udivsi3.asm: Rename to udivsi3.S.
+ * config/microblaze/umodsi3.asm: Rename to umodsi3.S.
+ * config/microblaze/t-microblaze (LIB2ADD): Reflect this.
+ * config/mips/t-elf, config/mips/t-vr, config/mips/vr4120-div.S:
+ New files.
+ * config/mips/t-mips (LIB2_SIDITI_CONV_FUNCS): Set.
+ * config/mmix/t-mmix (HOST_LIBGCC2_CFLAGS): Set.
+ * config/pa/fptr.c, config/pa/lib2funcs.S,
+ config/pa/linux-atomic.c, config/pa/quadlib.c: New files.
+ * config/pa/t-linux (HOST_LIBGCC2_CFLAGS): Set.
+ (LIB2ADD, LIB2ADD_ST): Set.
+ * config/pa/t-hpux, config/pa/t-hpux10, config/pa/t-pa64: New files.
+ * config/pa/t-linux (HOST_LIBGCC2_CFLAGS, LIB2ADD, LIB2ADD_ST):
+ Set.
+ * config/pa/t-linux64 (LIB2ADD_ST, HOST_LIBGCC2_CFLAGS): Set.
+ * config/pdp11/t-pdp11: New file.
+ * config/picochip/libgccExtras/adddi3.S,
+ config/picochip/libgccExtras/ashlsi3.S,
+ config/picochip/libgccExtras/ashrsi3.S,
+ config/picochip/libgccExtras/clzsi2.S,
+ config/picochip/libgccExtras/cmpsi2.S,
+ config/picochip/libgccExtras/divmod15.S,
+ config/picochip/libgccExtras/divmodhi4.S,
+ config/picochip/libgccExtras/divmodsi4.S,
+ config/picochip/libgccExtras/lshrsi3.S,
+ config/picochip/libgccExtras/parityhi2.S,
+ config/picochip/libgccExtras/popcounthi2.S,
+ config/picochip/libgccExtras/subdi3.S,
+ config/picochip/libgccExtras/ucmpsi2.S,
+ config/picochip/libgccExtras/udivmodhi4.S,
+ config/picochip/libgccExtras/udivmodsi4.S: New files.
+ * config/picochip/t-picochip (LIB2ADD, HOST_LIBGCC2_CFLAGS)
+ (LIBGCC2_DEBUG_CFLAGS, RANLIB_FOR_TARGET): Set.
+ * config/rs6000/crtresfpr.S, config/rs6000/crtresgpr.S,
+ config/rs6000/crtresxfpr.S, config/rs6000/crtresxgpr.S,
+ config/rs6000/crtsavfpr.S, config/rs6000/crtsavgpr.S)
+ config/rs6000/darwin-asm.h, config/rs6000/darwin-fpsave.S,
+ config/rs6000/darwin-gpsave.S, config/rs6000/darwin-tramp.S,
+ config/rs6000/darwin-vecsave.S, config/rs6000/darwin-world.S: New
+ files.
+ * config/rs6000/t-darwin (LIB2ADD, LIB2ADD_ST)
+ (HOST_LIBGCC2_CFLAGS): Set.
+ * config/rs6000/t-darwin64: New file.
+ * config/rs6000/t-linux64 (HOST_LIBGCC2_CFLAGS): Set.
+ * config/rs6000/t-lynx, config/rs6000/t-netbsd: New files.
+ * config/rs6000/t-ppccomm (LIB2ADD): Add
+ $(srcdir)/config/rs6000/tramp.S.
+ (LIB2ADD_ST): Use $(srcdir)/config/rs6000 to refer to sources.
+ Add $(srcdir)/config/rs6000/eabi.S.
+ (crtsavfpr.S, crtresfpr.S, crtsavgpr.S, crtresgpr.S, crtresxfpr.S)
+ (crtresxgpr.S, e500crtres32gpr.S, e500crtres64gpr.S)
+ (e500crtres64gprctr.S, e500crtrest32gpr.S, e500crtrest64gpr.S)
+ (e500crtresx32gpr.S, e500crtresx64gpr.S, e500crtsav32gpr.S)
+ (e500crtsav64gpr.S, e500crtsav64gprctr.S, e500crtsavg32gpr.S)
+ (e500crtsavg64gpr.S, e500crtsavg64gprctr.S): Remove.
+ * config/rs6000/tramp.S: New file.
+ * config/s390/t-tpf: Remove.
+ * config/sh/linux-atomic.S: New file.
+ * config/sh/t-linux (LIB2ADD): Set.
+ (HOST_LIBGCC2_CFLAGS): Append, remove -fpic.
+ * config/sh/t-netbsd (LIB2ADD, HOST_LIBGCC2_CFLAGS): Set.
+ * config/sh/t-sh (unwind-dw2-Os-4-200.o): Use $(srcdir) to refer
+ to unwind-dw2.c.
+ (HOST_LIBGCC2_CFLAGS): Set.
+ * config/sparc/t-sol2 (CRTSTUFF_T_CFLAGS): Use $(PICFLAG).
+ * config/spu/divmodti4.c, config/spu/divv2df3.c,
+ config/spu/float_disf.c, config/spu/float_unsdidf.c,
+ config/spu/float_unsdisf.c, config/spu/float_unssidf.c,
+ config/spu/mfc_multi_tag_release.c,
+ config/spu/mfc_multi_tag_reserve.c, config/spu/mfc_tag_release.c,
+ config/spu/mfc_tag_reserve.c, config/spu/mfc_tag_table.c,
+ config/spu/multi3.c: New files.
+ * config/spu/t-elf (LIB2ADD, LIB2ADD_ST, LIB2_SIDITI_CONV_FUNCS)
+ (HOST_LIBGCC2_CFLAGS): Set.
+ * config/stormy16/ashlsi3.c, config/stormy16/ashrsi3.c,
+ config/stormy16/clzhi2.c, config/stormy16/cmpsi2.c,
+ config/stormy16/ctzhi2.c, config/stormy16/divsi3.c,
+ config/stormy16/ffshi2.c, config/stormy16/lib2.c,
+ config/stormy16/lshrsi3.c, config/stormy16/modsi3.c,
+ config/stormy16/parityhi2.c, config/stormy16/popcounthi2.c,
+ config/stormy16/t-stormy16, config/stormy16/ucmpsi2.c,
+ config/stormy16/udivmodsi4.c, config/stormy16/udivsi3.c,
+ config/stormy16/umodsi3.c: New files.
+ * config/xtensa/lib2funcs.S: New file.
+ * config/xtensa/t-elf (HOST_LIBGCC2_CFLAGS): Set.
+ * config/xtensa/t-xtensa (LIB2ADD): Set.
+ * config.host (*-*-darwin*): Add t-libgcc-pic to tmake_file.
+ (*-*-freebsd*): Add t-freebsd, t-libgcc-pic to tmake_file.
+ Add t-freebsd-thread to tmake_file for posix threads.
+ (*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu)
+ (*-*-gnu*, *-*-kopensolaris*-gnu): Add t-libgcc-pic to tmake_file.
+ (*-*-lynxos*): Likewise.
+ (*-*-netbsd*): Likewise.
+ (*-*-openbsd*): Likewise.
+ Add t-openbsd-thread to tmake_file for posix threads.
+ (*-*-solaris2*): Add t-libgcc-pic to tmake_file.
+ (*-*-vxworks*): Set tmake_file.
+ (alpha*-*-linux*): Add alpha/t-alpha, alpha/t-ieee to tmake_file.
+ (alpha*-*-freebsd*): Likewise.
+ (alpha*-*-netbsd*): Likewise.
+ (alpha*-*-openbsd*): Likewise.
+ (alpha*-dec-osf5.1*): Remove qrnnd.o, gthr-posix.o from extra_parts.
+ (alpha64-dec-*vms*): Add alpha/t-alpha, alpha/t-ieee to tmake_file.
+ (alpha*-dec-*vms*): Likewise.
+ (arm*-*-netbsdelf*): Add arm/t-netbsd to tmake_file.
+ (bfin*-elf*): Add bfin/t-elf to tmake_file.
+ (bfin*-uclinux*): Likewise.
+ (bfin*-linux-uclibc*): Likewise.
+ (crisv32-*-elf): Add cris/t-cris to tmake_file.
+ (crisv32-*-none): Likewise.
+ (cris-*-elf): Likewise.
+ (cris-*-none): Likewise.
+ (cris-*-linux*, crisv32-*-linux*): Likewise.
+ (hppa[12]*-*-hpux10*): Add pa/t-hpux pa/t-hpux10, t-libgcc-pic to
+ tmake_file.
+ (hppa*64*-*-hpux11*): Add pa/t-hpux, pa/t-pa64, t-libgcc-pic to
+ tmake_file.
+ (hppa[12]*-*-hpux11*): Add pa/t-hpux, t-libgcc-pic to tmake_file.
+ (i[34567]86-*-elf*): Add t-libgcc-pic to tmake_file.
+ (x86_64-*-elf*): Likewise.
+ (i[34567]86-*-nto-qnx*): Likewise.
+ (i[34567]86-*-mingw*): Add i386/t-gthr-win32 to tmake_file for
+ win32 threads.
+ (x86_64-*-mingw*): Likewise.
+ (i[34567]86-*-interix3*): Add i386/t-interix to tmake_file.
+ (lm32-*-uclinux*): Add t-libgcc-pic to tmake_file.
+ (mipsisa32-*-elf*, mipsisa32el-*-elf*, mipsisa32r2-*-elf*)
+ (mipsisa32r2el-*-elf*, mipsisa64-*-elf*, mipsisa64el-*-elf*)
+ (mipsisa64r2-*-elf*, mipsisa64r2el-*-elf*): Add mips/t-elf to
+ tmake_file.
+ (mipsisa64sr71k-*-elf*): Likewise.
+ (mipsisa64sb1-*-elf*, mipsisa64sb1el-*-elf*): Likewise.
+ (mips-*-elf*, mipsel-*-elf*): Likewise.
+ (mips64-*-elf*, mips64el-*-elf*): Likewise.
+ (mips64orion-*-elf*, mips64orionel-*-elf*): Likewise.
+ (mips*-*-rtems*): Likewise.
+ (mips64vr-*-elf*, mips64vrel-*-elf*): Add mips/t-elf, mips/t-vr
+ to tmake_file.
+ (pdp11-*-*): Add pdp11/t-pdp11 to tmake_file.
+ (powerpc64-*-darwin*): Add rs6000/t-darwin64 to tmake_file.
+ (s390x-ibm-tpf*): Add t-libgcc-pic to tmake_file.
+ (spu-*-elf*): Likewise.
+ (tic6x-*-uclinux): Add t-libgcc-pic to tmake_file.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makefile.in ($(lib1asmfuncs-o), $(lib1asmfuncs-s-o)): Use
+ $(srcdir) to refer to $(LIB1ASMSRC).
+ Use $<.
+ * config/arm/bpabi-v6m.S, config/arm/bpabi.S,
+ config/arm/ieee754-df.S, config/arm/ieee754-sf.S,
+ config/arm/lib1funcs.S: New files.
+ * config/arm/libunwind.S [!__symbian__]: Use lib1funcs.S.
+ * config/arm/t-arm: New file.
+ * config/arm/t-bpabi (LIB1ASMFUNCS): Set.
+ * config/arm/t-elf, config/arm/t-linux, config/arm/t-linux-eabi,
+ config/arm/t-strongarm-elf: New files.
+ * config/arm/t-symbian (LIB1ASMFUNCS): Set.
+ * config/arm/t-vxworks, config/arm/t-wince-pe: New files.
+ * config/avr/lib1funcs.S: New file.
+ * config/avr/t-avr (LIB1ASMSRC, LIB1ASMFUNCS): Set.
+ * config/bfin/lib1funcs.S, config/bfin/t-bfin: New files.
+ * config/c6x/lib1funcs.S: New file.
+ * config/c6x/t-elf (LIB1ASMSRC, LIB1ASMFUNCS): Set.
+ * config/fr30/lib1funcs.S, config/fr30/t-fr30: New files.
+ * config/frv/lib1funcs.S: New file.
+ * config/frv/t-frv (LIB1ASMSRC, LIB1ASMFUNCS): Set.
+ * config/h8300/lib1funcs.S, config/h8300/t-h8300: New files.
+ * config/i386/cygwin.S, config/i386/t-chkstk: New files.
+ * config/ia64/__divxf3.asm: Rename to ...
+ * config/ia64/__divxf3.S: ... this.
+ Adapt lib1funcs.asm filename.
+ * config/ia64/_fixtfdi.asm: Rename to ...
+ * config/ia64/_fixtfdi.S: ... this.
+ Adapt lib1funcs.asm filename.
+ * config/ia64/_fixunstfdi.asm: Rename to ...
+ * config/ia64/_fixunstfdi.S: ... this.
+ Adapt lib1funcs.asm filename.
+ * config/ia64/_floatditf.asm: Rename to ...
+ * config/ia64/_floatditf.S: ... this.
+ Adapt lib1funcs.asm filename.
+ * config/ia64/lib1funcs.S: New file.
+ * config/ia64/t-hpux (LIB1ASMFUNCS): Set.
+ * config/ia64/t-ia64 (LIB1ASMSRC, LIB1ASMFUNCS): Set.
+ * config/ia64/t-softfp-compat (libgcc1-tf-compats): Adapt suffix.
+ * config/m32c/lib1funcs.S, config/m32c/t-m32c: New files.
+ * config/m68k/lb1sf68.S, config/m68k/t-floatlib: New files.
+ * config/mcore/lib1funcs.S, config/mcore/t-mcore: New files.
+ * config/mep/lib1funcs.S: New file.
+ * config/mep/t-mep (LIB1ASMSRC, LIB1ASMFUNCS): Set.
+ * config/mips/mips16.S: New file.
+ * config/mips/t-mips16 (LIB1ASMSRC, LIB1ASMFUNCS): Set.
+ * config/pa/milli64.S: New file.
+ * config/pa/t-linux, config/pa/t-linux64: New files.
+ * config/picochip/lib1funcs.S: New file.
+ * config/picochip/t-picochip (LIB1ASMSRC, LIB1ASMFUNCS): Set.
+ * config/sh/lib1funcs.S, config/sh/lib1funcs.h: New files.
+ * config/sh/t-linux (LIB1ASMFUNCS_CACHE): Set.
+ * config/sh/t-netbsd: New file.
+ * config/sh/t-sh (LIB1ASMSRC, LIB1ASMFUNCS, LIB1ASMFUNCS_CACHE): Set.
+ Use $(srcdir) to refer to lib1funcs.S, adapt filename.
+ * config/sh/t-sh64: New file.
+ * config/sparc/lb1spc.S: New file.
+ * config/sparc/t-softmul (LIB1ASMSRC): Adapt sparc/lb1spc.asm
+ filename.
+ * config/v850/lib1funcs.S, config/v850/t-v850: New files.
+ * config/vax/lib1funcs.S, config/vax/t-linux: New files.
+ * config/xtensa/ieee754-df.S, config/xtensa/ieee754-sf.S,
+ config/xtensa/lib1funcs.S: New files.
+ * config/xtensa/t-xtensa (LIB1ASMSRC, LIB1ASMFUNCS): Set.
+ * config.host (arm-wrs-vxworks): Add arm/t-arm, arm/t-vxworks to
+ tmake_file.
+ (arm*-*-freebsd*): Add arm/t-arm, arm/t-strongarm-elf to tmake_file.
+ (arm*-*-netbsdelf*): Add arm/t-arm to tmake_file.
+ (arm*-*-linux*): Likewise.
+ Add arm/t-elf, arm/t-bpabi, arm/t-linux-eabi to tmake_file for
+ arm*-*-linux-*eabi, add arm/t-linux otherwise.
+ (arm*-*-uclinux*): Add arm/t-arm, arm/t-elf to tmake_file.
+ (arm*-*-ecos-elf): Likewise.
+ (arm*-*-eabi*, arm*-*-symbianelf*): Likewise.
+ (arm*-*-rtems*): Likewise.
+ (arm*-*-elf): Likewise.
+ (arm*-wince-pe*): Add arm/t-arm, arm/t-wince-pe to tmake_file.
+ (avr-*-rtems*): Add to tmake_file, add avr/t-avr.
+ (bfin*-elf*): Add bfin/t-bfin to tmake_file.
+ (bfin*-uclinux*): Likewise.
+ (bfin*-linux-uclibc*): Likewise.
+ (bfin*-rtems*): Likewise.
+ (bfin*-*): Likewise.
+ (fido-*-elf): Merge into m68k-*-elf*.
+ (fr30-*-elf)): Add fr30/t-fr30 to tmake_file.
+ (frv-*-*linux*): Add frv/t-frv to tmake_file.
+ (h8300-*-rtems*): Add h8300/t-h8300 to tmake_file.
+ (h8300-*-elf*): Likewise.
+ (hppa*64*-*-linux*): Add pa/t-linux, pa/t-linux64 to tmake_file.
+ (hppa*-*-linux*): Add pa/t-linux to tmake_file.
+ (i[34567]86-*-cygwin*): Add i386/t-chkstk to tmake_file.
+ (i[34567]86-*-mingw*): Likewise.
+ (x86_64-*-mingw*): Likewise.
+ (i[34567]86-*-interix3*): Likewise.
+ (ia64*-*-hpux*): Add ia64/t-ia64, ia64/t-hpux to tmake_file.
+ (ia64-hp-*vms*): Add ia64/t-ia64 to tmake_file.
+ (m68k-*-elf*): Also handle fido-*-elf.
+ Add m68k/t-floatlib to tmake_file.
+ (m68k-*-uclinux*): Add m68k/t-floatlib to tmake_file.
+ (m68k-*-linux*): Likewise.
+ (m68k-*-rtems*): Likewise.
+ (mcore-*-elf): Add mcore/t-mcore to tmake_file.
+ (sh-*-elf*, sh[12346l]*-*-elf*): Add sh/t-sh64 to tmake_file for
+ sh64*-*-*.
+ (sh-*-linux*, sh[2346lbe]*-*-linux*): Add sh/t-sh to tmake_file.
+ Add sh/t-sh64 to tmake_file for sh64*-*-linux*.
+ (sh-*-netbsdelf*, shl*-*-netbsdelf*, sh5-*-netbsd*)
+ (sh5l*-*-netbsd*, sh64-*-netbsd*, sh64l*-*-netbsd*): Add sh/t-sh,
+ sh/t-netbsd to tmake_file.
+ Add sh/t-sh64 to tmake_file for sh5*-*-netbsd*, sh64*-netbsd*.
+ (sh-*-rtems*): Add sh/t-sh to tmake_file.
+ (sh-wrs-vxworks): Likewise.
+ (sparc-*-linux*): Add sparc/t-softmul to tmake_file except for
+ *-leon[3-9]*.
+ (v850*-*-*): Add v850/t-v850 to tmake_file.
+ (vax-*-linux*): Add vax/t-linux to tmake_file.
+ (m32c-*-elf*, m32c-*-rtems*): Add m32c/t-m32c to tmake_file.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * crtstuff.c: New file.
+ * Makefile.in (CRTSTUFF_CFLAGS): Define.
+ (CRTSTUFF_T_CFLAGS): Define.
+ (extra-parts, INSTALL_PARTS): Remove conditional assignments.
+ (crtbegin$(objext), crtend$(objext), crtbeginS$(objext))
+ (crtendS$(objext), crtbeginT.o): Use $(srcdir) to refer to
+ crtstuff.c.
+ Use $<.
+ (crtbeginT.o): Use $(objext).
+ [!CUSTOM_CRTIN] (crti$(objext), crtn$(objext)): New rules.
+ (libgcc-extra-parts): Don't compare EXTRA_PARTS, GCC_EXTRA_PARTS.
+ (gcc-extra-parts): Remove.
+ * config.host (*-*-freebsd*): Add t-crtstuff-pic to tmake_file.
+ Set extra_parts.
+ (*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu,
+ *-*-gnu*): Also handle *-*-kopensolaris*-gnu.
+ Add t-crtstuff-pic to tmake_file.
+ (*-*-lynxos*): New case.
+ Set tmake_file, extra_parts.
+ (*-*-netbsd*): Add t-crtstuff-pic to tmake_file.
+ Set extra_parts for *-*-netbsd*1.[7-9]*, *-*-netbsd[2-9]*,
+ *-*-netbsdelf[2-9]*.
+ (*-*-openbsd*): Add t-crtstuff-pic to tmake_file.
+ (*-*-rtems*): Set extra_parts.
+ (*-*-solaris2*): Remove t-crtin from tmake_file for Solaris < 10.
+ (*-*-uclinux*): New case.
+ Set extra_parts.
+ (*-*-vms*): New case.
+ Set tmake_file, extra_parts.
+ (*-*-elf): Set extra_parts.
+ (alpha*-*-freebsd*): Add crtbeginT.o to extra_parts.
+ (alpha64-dec-*vms*): Append to tmake_file, remove vms/t-vms,
+ vms/t-vms64.
+ Set extra_parts.
+ (alpha*-dec-*vms*): Append to tmake_file, remove vms/t-vms.
+ Set extra_parts.
+ (arm*-*-freebsd*): Add t-crtin to tmake_file.
+ Add crtbegin.o, crtend.o, crti.o, crtn.o to extra_parts.
+ (arm-wrs-vxworks): Append to tmake_file.
+ Set extra_parts.
+ (arm*-*-uclinux*): Set extra_parts.
+ (arm*-*-ecos-elf): Likewise.
+ (arm*-*-eabi*, arm*-*-symbianelf*): Set extra_parts for
+ arm*-*-eabi*.
+ (arm*-*-rtems*): Set extra_parts.
+ (arm*-*-elf): Likewise.
+ (avr-*-rtems*): Clear extra_parts.
+ (bfin*-elf*): Add bfin/t-crtlibid, bfin/t-crtstuff to extra_parts.
+ Set extra_parts.
+ (bfin*-uclinux*): Likewise.
+ (bfin*-linux-uclibc*): Add bfin/t-crtstuff to tmake_file.
+ (bfin*-rtems*): Append to tmake_file.
+ Set extra_parts.
+ (bfin*-*): Likewise.
+ (crisv32-*-elf, crisv32-*-none, cris-*-elf, cris-*-none): Split into ...
+ (crisv32-*-elf): ... this.
+ (crisv32-*-none): ... this.
+ (cris-*-elf, cris-*-none): New cases.
+ Add cris/t-elfmulti to tmake_file.
+ (fr30-*-elf): Append to tmake_file.
+ Set extra_parts.
+ (frv-*-elf): Append to tmake_file, add frv/t-frv.
+ Set extra_parts.
+ (h8300-*-rtems*): Append to tmake_file.
+ Set extra_parts.
+ (h8300-*-elf*): Likewise.
+ (hppa*64*-*-hpux11*): Add pa/t-stublib, pa/t-stublib64 to tmake_file.
+ Set extra_parts.
+ (hppa[12]*-*-hpux11*): Add pa/t-stublib to tmake_file.
+ Set extra_parts.
+ (i[34567]86-*-elf*): Add i386/t-crtstuff, t-crtstuff-pic to tmake_file.
+ (x86_64-*-elf*): Likewise.
+ (i[34567]86-*-freebsd*): Add i386/t-crtstuff to tmake_file.
+ (x86_64-*-freebsd*): Likewise.
+ (x86_64-*-netbsd*): Likewise.
+ (i[34567]86-*-linux*): Likewise.
+ (i[34567]86-*-kfreebsd*-gnu, i[34567]86-*-knetbsd*-gnu)
+ (i[34567]86-*-gnu*, i[34567]86-*-kopensolaris*-gnu): Likewise.
+ (x86_64-*-linux*): Likewise.
+ (x86_64-*-kfreebsd*-gnu, x86_64-*-knetbsd*-gnu): Likewise.
+ (i[34567]86-*-lynxos*): Add t-crtstuff-pic, i386/t-crtstuff to
+ tmake_file.
+ Set extra_parts.
+ (i[34567]86-*-nto-qnx*): Set tmake_file, extra_parts.
+ (i[34567]86-*-rtems*): Append to tmake_file, remove t-crtin.
+ Append to extra_parts, remove crtbegin.o, crtend.o.
+ (ia64*-*-elf*): Append to extra_parts, remove crtbegin.o, crtend.o.
+ (ia64*-*-freebsd*): Append to extra_parts, remove crtbegin.o,
+ crtend.o, crtbeginS.o, crtendS.o.
+ (ia64*-*-linux*): Comment extra_parts.
+ (ia64-hp-*vms*): Append to tmake_file, remove vms/t-vms, vms/t-vms64.
+ Set extra_parts.
+ (iq2000*-*-elf*): Clear extra_parts.
+ (lm32-*-elf*, lm32-*-rtems*): Add t-crtin to tmake_file.
+ (lm32-*-uclinux*): Add to extra_parts, remove crtbegin.o, crtend.o
+ (m32r-*-elf*, m32r-*-rtems*): Split off ...
+ (m32r-*-rtems*): ... this.
+ Add m32r/t-m32r to tmake_file.
+ (m68k-*-elf*): Add t-crtin to tmake_file.
+ (m68k-*-rtems*): Add crti.o, crtn.o to extra_parts.
+ (mcore-*-elf): Likewise.
+ (microblaze*-*-*): Set extra_parts.
+ (mips*-sde-elf*): New case.
+ Set tmake_file, extra_parts.
+ (mipsisa32-*-elf*, mipsisa32el-*-elf*, mipsisa32r2-*-elf*)
+ (mipsisa32r2el-*-elf*, mipsisa64-*-elf*, mipsisa64el-*-elf*)
+ (mipsisa64r2-*-elf*, mipsisa64r2el-*-elf*): Add mips/t-crtstuff to
+ tmake_file.
+ Set extra_parts.
+ (mipsisa64sr71k-*-elf*): Likewise.
+ (mipsisa64sb1-*-elf*, mipsisa64sb1el-*-elf*): Likewise.
+ (mips-*-elf*, mipsel-*-elf*): Likewise.
+ (mips64-*-elf*, mips64el-*-elf*): Likewise.
+ (mips64vr-*-elf*, mips64vrel-*-elf*): Likewise.
+ (mips64orion-*-elf*, mips64orionel-*-elf*): Likewise.
+ (mips*-*-rtems*): Likewise.
+ (mipstx39-*-elf*, mipstx39el-*-elf*): Likewise.
+ (moxie-*-*): Split into ...
+ (moxie-*-elf, moxie-*-uclinux*): ... this.
+ Add to extra_parts, remove crtbegin.o, crtend.o.
+ (moxie-*-rtems*): New case.
+ Set tmake_file.
+ Clear extra_parts.
+ (powerpc-*-freebsd*): Add rs6000/t-crtstuff to tmake_file.
+ Set extra_parts.
+ (powerpc-*-netbsd*): Add rs6000/t-netbsd to tmake_file.
+ (powerpc-*-eabispe*): Add rs6000/t-crtstuff, t-crtstuff-pic to
+ tmake_file.
+ Set extra_parts.
+ (powerpc-*-eabisimaltivec*): Add to tmake_file, add rs6000/t-ppccomm,
+ rs6000/t-crtstuff, t-crtstuff-pic to tmake_file.
+ Set extra_parts.
+ (powerpc-*-eabisim*): Likewise.
+ (powerpc-*-elf*): Likewise.
+ (powerpc-*-eabialtivec*): Likewise.
+ (powerpc-xilinx-eabi*): Likewise.
+ (powerpc-*-eabi*): Likewise.
+ (powerpc-*-rtems*): Likewise.
+ (powerpc-*-linux*, powerpc64-*-linux*): Add rs6000/t-crtstuff to
+ tmake_file.
+ Set extra_parts.
+ (powerpc-*-lynxos*): Add to tmake_file.
+ (powerpcle-*-elf*): Add to tmake_file, add rs6000/t-ppccomm,
+ rs6000/t-crtstuff, t-crtstuff-pic.
+ Set extra_parts.
+ (powerpcle-*-eabisim*): Likewise.
+ (powerpcle-*-eabi*): Likewise.
+ (rx-*-elf): Remove extra_parts.
+ (s390x-ibm-tpf*): Set extra_parts.
+ (score-*-elf): Set extra_parts.
+ (sh-*-elf*, sh[12346l]*-*-elf*, sh-*-linux*)
+ (sh[2346lbe]*-*-linux*, sh-*-netbsdelf*, shl*-*-netbsdelf*)
+ (sh5-*-netbsd*, sh5l*-*-netbsd*, sh64-*-netbsd*)
+ (sh64l*-*-netbsd*): Split into ...
+ (sh-*-elf*, sh[12346l]*-*-elf*): ... this.
+ Add t-crtstuff-pic to tmake_file.
+ Set extra_parts.
+ (sh-*-rtems*): Add to tmake_file, add t-crtstuff-pic.
+ Set extra_parts.
+ (sh-wrs-vxworks): Add to tmake_file, add t-crtstuff-pic.
+ (sparc-*-elf*): Remove t-crtin from tmake_file.
+ Add to extra_parts, remove crtbegin.o, crtend.o.
+ (sparc-*-linux*): Add sparc/t-linux64 to tmake_file.
+ (sparc64-*-linux*): Likewise.
+ (sparc-*-rtems*): Remove sparc/t-elf from tmake_file.
+ Add to extra_parts, remove crtbegin.o, crtend.o.
+ (sparc64-*-elf*): Remove t-crtin from tmake_file.
+ Add to extra_parts, remove crtbegin.o, crtend.o.
+ (sparc64-*-rtems*): Remove t-crtin from tmake_file.
+ Add to extra_parts, remove crtbegin.o, crtend.o.
+ (sparc64-*-freebsd*, ultrasparc-*-freebsd*): Add to extra_parts.
+ (sparc64-*-linux*): Add sparc/t-linux64 to tmake_file.
+ (spu-*-elf*): Add to tmake_file, add spu/t-elf.
+ Set extra_parts.
+ (tic6x-*-uclinux): Add c6x/t-uxlinux, t-crtstuff-pic to tmake_file.
+ Set extra_parts.
+ (tic6x-*-*): Change to ...
+ (tic6x-*-elf): ... this.
+ Set extra_parts.
+ (xtensa*-*-elf*): Add to tmake_file, add xtensa/t-elf.
+ Set extra_parts.
+ (am33_2.0-*-linux*): Add comment.
+ (mep*-*-*): Add mep/t-mep to tmake_file.
+ Set extra_parts.
+ * config/alpha/t-vms: New file.
+ * config/alpha/vms-dwarf2.S, config/alpha/vms-dwarf2eh.S: New files.
+ * config/arm/crti.S, config/arm/crtn.S: New files.
+ * config/bfin/crti.S, config/bfin/crtn.S: New files.
+ * config/bfin/crtlibid.S: New file.
+ * config/bfin/t-crtlibid, config/bfin/t-crtstuff: New files.
+ * config/c6x/crti.S, config/c6x/crtn.S: New files.
+ * config/c6x/t-elf (CUSTOM_CRTIN): Set.
+ (crti.o, crtin.o): New rules.
+ (CRTSTUFF_T_CFLAGS, CRTSTUFF_T_CFLAGS_S): Set.
+ * config/c6x/t-uclinux: New file.
+ * config/cris/t-elfmulti: New file.
+ * config/cris/t-linux (CRTSTUFF_T_CFLAGS_S): Set.
+ * config/fr30/crti.S, config/fr30/crtn.S: New files.
+ * config/frv/frvbegin.c, config/frv/frvend.c: New files.
+ * config/frv/t-frv: New file.
+ * config/frv/t-linux (CRTSTUFF_T_CFLAGS): Set.
+ * config/h8300/crti.S, config/h8300/crtn.S: New files.
+ * config/i386/cygming-crtbegin.c, config/i386/cygming-crtend.c:
+ New files.
+ * config/i386/t-cygming (crtbegin.o, crtend.o): Use $(srcdir) to
+ refer to cygming-crtbegin.c, cygming-crtend.c.
+ Use $<.
+ * config/i386/t-nto: New file.
+ * config/ia64/crtbegin.S, config/ia64/crtend.S: New files.
+ * config/ia64/crti.S, config/ia64/crtn.S: New files.
+ * config/ia64/t-ia64 (crtbegin.o, crtend.o, crtbeginS.o,
+ crtendS.o): Use $(srcdir) to refer to crtbegin.S, crtend.S.
+ Use .S extension.
+ Use $<.
+ * config/ia64/t-vms (CRTSTUFF_T_CFLAGS, CRTSTUFF_T_CFLAGS_S): Set.
+ (crtinitS.o): New rule.
+ * config/ia64/vms-crtinit.S: New file.
+ * config/lm32/t-elf ($(T)crti.o, $(T)crtn.o): Remove.
+ * config/m32r/initfini.c: New file.
+ * config/m32r/t-linux, config/m32r/t-m32r: New files.
+ * config/m68k/crti.S, config/m68k/crtn.S: New files.
+ * config/mcore/crti.S, config/mcore/crtn.S: New files.
+ * config/mep/t-mep: New file.
+ * config/microblaze/crti.S, config/microblaze/crtn.S: New files.
+ * config/microblaze/t-microblaze (MULTILIB_OPTIONS): Remove.
+ * config/mips/crti.S, config/mips/crtn.S: New files.
+ * config/mips/t-crtstuff: New file.
+ * config/mmix/crti.S, config/mmix/crtn.S: New files.
+ * config/mmix/t-mmix (CRTSTUFF_T_CFLAGS): Set.
+ (CUSTOM_CRTIN): Set.
+ ($(T)crti.o, $(T)crtn.o): Remove $(T),
+ dependencies.
+ Use $(srcdir) to refer to crti.S, crtn.S.
+ Use .S extension, $<.
+ * config/moxie/crti.asm: Rename to ...
+ * config/moxie/crti.S: ... this.
+ * config/moxie/crtn.asm: Rename to ...
+ * config/moxie/crtn.S: ... this.
+ * config/moxie/t-moxie: Remove.
+ * config/pa/stublib.c: New file.
+ * config/pa/t-stublib, config/pa/t-stublib64: New files.
+ * config/rs6000/eabi-ci.S, config/rs6000/eabi-cn.S: New files.
+ * config/rs6000/sol-ci.S, config/rs6000/sol-cn.S: New files.
+ * config/rs6000/t-crtstuff: New file.
+ * config/rs6000/t-ppccomm (EXTRA_PARTS): Remove.
+ (ecrti.S, ecrtn.S, ncrti.S, ncrtn.S): Remove.
+ (ecrti$(objext)): Depend on $(srcdir)/config/rs6000/eabi-ci.S.
+ Make output file explicit.
+ (ecrtn$(objext)): Depend on $(srcdir)/config/rs6000/eabi-cn.S.
+ Make output file explicit.
+ (ncrti$(objext): Depend on $(srcdir)/config/rs6000/sol-ci.S.
+ Make output file explicit.
+ (ncrtn$(objext)): Depend on $(srcdir)/config/rs6000/sol-cn.S.
+ Make output file explicit.
+ * config/score/crti.S, config/score/crtn.S: New files.
+ * config/sh/crt1.S, config/sh/crti.S, config/sh/crtn.S: New files.
+ * config/sh/lib1funcs-4-300.S, config/sh/lib1funcs-Os-4-200.S: New
+ files.
+ * config/sh/t-sh, config/sh/t-superh: New files.
+ * config/sparc/t-linux64: New file.
+ * config/spu/cache.S, config/spu/cachemgr.c: New files.
+ * config/spu/t-elf (CRTSTUFF_T_CFLAGS): Set.
+ (cachemgr.o, cachemgr_nonatomic.o, libgcc_%.a, cache8k.o)
+ (cache16k.o, cache32k.o, cache64k.o, cache128k.o): New rules.
+ * config/t-crtin: Remove.
+ * config/t-crtstuff-pic: New file.
+ * config/t-sol2 (CUSTOM_CRTIN): Set.
+ (crti.o, crtn.o): New rules.
+ * config/vms/t-vms: New file.
+ * config/vms/vms-ucrt0.c: New file.
+ * config/xtensa/t-elf: New file.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makefile.in (SHLIB_NM_FLAGS): Set.
+ * mkmap-flat.awk, mkmap-symver.awk: New files.
+ * configure.ac (libgcc_cv_lib_sjlj_exceptions): Check for SjLj
+ exceptions.
+ * configure: Regenerate.
+ * config/libgcc-glibc.ver: New file.
+ * config/libgcc-libsystem.ver: New file.
+ * config/t-libunwind (SHLIB_LC): Set.
+ * config/t-linux: New file.
+ * config/t-slibgcc (INSTALL_SHLIB): New.
+ (SHLIB_INSTALL): Use it.
+ * config/t-slibgcc-darwin (SHLIB_MKMAP): Use $(srcdir) to refer
+ to mkmap-symver.awk.
+ (SHLIB_MAPFILES): Don't append, adapt pathname.
+ (SHLIB_VERPFX): Set.
+ * config/t-slibgcc-elf-ver (SHLIB_MKMAP): Use $(srcdir) to refer
+ to mkmap-symver.awk.
+ * config/t-slibgcc-gld-nover, config/t-slibgcc-hpux,
+ config/t-slibgcc-libgcc, config/t-slibgcc-vms: New files.
+ * config/alpha/libgcc-alpha-ldbl.ver, config/alpha/t-linux: New files.
+ * config/alpha/t-slibgcc-osf (SHLIB_MKMAP): Use $(srcdir) to refer
+ to mkmap-flat.awk.
+ * config/arm/t-bpabi (SHLIB_MAPFILES): Set.
+ * config/bfin/libgcc-glibc.ver, config/bfin/t-linux: New files.
+ * config/c6x/libgcc-eabi.ver, config/c6x/t-elf: New files.
+ * config/cris/libgcc-glibc.ver, config/cris/t-linux: New files.
+ * config/frv/libgcc-frv.ver, config/frv/t-linux: New files.
+ * config/i386/libgcc-darwin.10.4.ver,
+ config/i386/libgcc-darwin.10.5.ver, config/i386/libgcc-glibc.ver:
+ New files.
+ * config/i386/t-darwin: Remove.
+ * config/i386/t-darwin64: Likewise.
+ * config/i386/t-dw2-eh, config/i386/t-sjlj-eh: New files.
+ * config/i386/t-slibgcc-cygming, config/i386/t-cygwin,
+ config/i386/t-dlldir, config/i386/t-dlldir-x: New files.
+ * config/i386/t-linux: New file.
+ * config/i386/t-mingw32: New file.
+ * config/ia64/libgcc-glibc.ver, config/ia64/libgcc-ia64.ver: New files.
+ * config/ia64/t-glibc: Rename to ...
+ * config/ia64/t-linux: ... this.
+ (SHLIB_MAPFILES): Set.
+ * config/ia64/t-glibc-libunwind: Rename to ...
+ * config/ia64/t-linux-libunwind: ... this.
+ * config/ia64/t-ia64 (SHLIB_MAPFILES): Set.
+ * config/ia64/t-slibgcc-hpux: New file.
+ * config/m32r/libgcc-glibc.ver, config/m32r/t-linux: New files.
+ * config/m68k/t-slibgcc-elf-ver: New file.
+ * config/mips/t-mips16 (SHLIB_MAPFILES): Set.
+ * config/mips/t-slibgcc-irix (SHLIB_MKMAP): Use $(srcdir) to refer
+ to mkmap-flat.awk.
+ * config/pa/t-slibgcc-hpux: New file.
+ * config/pa/t-slibgcc-dwarf-ver, config/pa/t-slibgcc-sjsj-ver: New
+ files.
+ * config/rs6000/libgcc-darwin.10.4.ver,
+ config/rs6000/libgcc-darwin.10.5.ver: New files.
+ * config/rs6000/libgcc-ppc-glibc.ver: Rename to
+ config/rs6000/libgcc-glibc.ver.
+ * config/rs6000/libgcc-ppc64.ver: Rename to
+ config/rs6000/libgcc-ibm-ldouble.ver.
+ * config/rs6000/t-darwin (SHLIB_VERPFX): Remove.
+ * config/rs6000/t-ibm-ldouble (SHLIB_MAPFILES): Adapt filename.
+ * config/rs6000/t-ldbl128: Rename to ...
+ * config/rs6000/t-linux: ... this.
+ (SHLIB_MAPFILES): Adapt filename.
+ * config/rs6000/t-slibgcc-aix: New file.
+ * config/sh/libgcc-excl.ver, config/sh/libgcc-glibc.ver: New files.
+ * config/sh/t-linux (SHLIB_MAPFILES): Use $(srcdir) to refer to
+ libgcc-excl.ver, libgcc-glibc.ver.
+ (SHLIB_LINK, SHLIB_INSTALL): Remove.
+ * config/sparc/libgcc-glibc.ver: New file.
+ * config/sparc/t-linux: New file.
+ * config/xtensa/libgcc-glibc.ver, config/xtensa/t-linux: New files.
+ * config.host (*-*-freebsd*): Add t-slibgcc, t-slibgcc-gld,
+ t-slibgcc-elf-ver to tmake_file.
+ Add t-slibgcc-nolc-override to tmake_file for posix threads on
+ *-*-freebsd[34].
+ (*-*-linux*, frv-*-*linux*, *-*-kfreebsd*-gnu, *-*-knetbsd*-gnu,
+ *-*-gnu*, *-*-kopensolaris*-gnu): Add t-slibgcc, t-slibgcc-gld,
+ t-slibgcc-elf-ver, t-linux to tmake_file.
+ (*-*-netbsd*): Add t-slibgcc, t-slibgcc-gld, t-slibgcc-elf-ver to
+ tmake_file.
+ (alpha*-*-linux*): Add alpha/t-linux to tmake_file.
+ (alpha64-dec-*vms*): Add t-slibgcc-vms to tmake_file.
+ (alpha*-dec-*vms*): Likewise.
+ (arm*-*-freebsd*): Append to tmake_file.
+ (arm*-*-netbsdelf*): Add t-slibgcc-gld-nover to tmake_file.
+ (arm*-*-linux*): Add t-slibgcc-libgcc to tmake_file for
+ arm*-*-linux-*eabi.
+ (arm*-*-eabi*, arm*-*-symbianelf*): Add t-slibgcc-nolc-override to
+ tmake_file for arm*-*-symbianelf*.
+ (bfin*-linux-uclibc*): Append to tmake_file, add bfin/t-linux.
+ (cris-*-linux*, crisv32-*-linux*): Append to tmake_file, add
+ cris/t-linux.
+ (frv-*-*linux*): Append to tmake_file, add frv/t-linux.
+ (hppa*-*-linux*): Add t-slibgcc-libgcc, pa/t-slibgcc-sjlj-ver,
+ pa/t-slibgcc-dwarf-ver to tmake_file.
+ (hppa[12]*-*-hpux10*): Add t-slibgcc, pa/t-slibgcc-sjlj-ver,
+ pa/t-slibgcc-dwarf-ver, t-slibgcc-hpux, pa/t-slibgcc-hpux to tmake_file.
+ (hppa*64*-*-hpux11*): Likewise.
+ (hppa[12]*-*-hpux11*): Likewise.
+ (x86_64-*-darwin*): Don't override tmake_file, but only keep
+ i386/t-crtpc, i386/t-crtfm.
+ (i[34567]86-*-cygwin*): Set tmake_eh_file, tmake_dlldir_file.
+ Prepend $tmake_eh_file, $tmake_dlldir_file, i386/t-slibgcc-cygming
+ to tmake_file.
+ Add i386/t-cygwin to tmake_file.
+ Prepent i386/t-mingw-pthread to tmake_file for posix threads.
+ (i[34567]86-*-mingw*): Set tmake_eh_file, tmake_dlldir_file.
+ Prepend $tmake_eh_file, $tmake_dlldir_file, i386/t-slibgcc-cygming
+ to tmake_file.
+ Add i386/t-mingw32 to tmake_file.
+ (x86_64-*-mingw*): Likewise.
+ (ia64*-*-freebsd*): Append to tmake_file.
+ (ia64*-*-linux*): Append to tmake_file.
+ Replace ia64/t-glibc by ia64/t-linux.
+ Replace ia64/t-glibc-libunwind by ia64/t-linux-libunwind if using
+ system libunwind.
+ (ia64*-*-hpux*): Add t-slibgcc, ia64/t-slibgcc-hpux,
+ t-slibgcc-hpux to tmake_file.
+ (ia64-hp-*vms*): Add t-slibgcc-vms to tmake_file.
+ (m32r-*-linux*): Append to tmake_file, add m32r/t-linux.
+ (m32rle-*-linux*): Likewise.
+ (m68k-*-linux*)): Add m68k/t-slibgcc-elf-ver to tmake_file unless
+ sjlj exceptions.
+ (microblaze*-linux*): New case.
+ Append to tmake_file, add t-slibgcc-nolc-override.
+ (powerpc-*-freebsd*): Add t-slibgcc-libgcc to tmake_file.
+ (powerpc-*-linux*, powerpc64-*-linux*): Likewise.
+ Replace rs6000/t-ldbl128 by rs6000/t-linux in tmake_file.
+ (rs6000-ibm-aix4.[3456789]*, powerpc-ibm-aix4.[3456789]*): Add
+ rs6000/t-slibgcc-aix to tmake_file.
+ (rs6000-ibm-aix5.1.*, powerpc-ibm-aix5.1.*): Likewise.
+ (rs6000-ibm-aix[56789].*, powerpc-ibm-aix[56789].*): Likewise.
+ (sh-*-elf*, sh[12346l]*-*-elf*, sh-*-linux*)
+ (sh[2346lbe]*-*-linux*, sh-*-netbsdelf*, shl*-*-netbsdelf*)
+ (sh5-*-netbsd*, sh5l*-*-netbsd*, sh64-*-netbsd*)
+ (sh64l*-*-netbsd*): Add t-slibgcc-libgcc to tmake_file for
+ sh*-*-linux*.
+ (sparc-*-linux*): Append to tmake_file for *-leon*.
+ Add sparc/t-linux to tmake_file for non-Leon targets.
+ (sparc64-*-linux*): Add sparc/t-linux to tmake_file.
+ (tic6x-*-uclinux): New case.
+ Add t-slibgcc, t-slibgcc-gld, t-slibgcc-elf-ver to tmake_file.
+ (tic6x-*-*): Add c6x/t-elf to tmake_file.
+ (xtensa*-*-linux*): Append to tmake_file, add xtensa/t-linux.
+ (am33_2.0-*-linux*): Append to tmake_file.
+ (i[34567]86-*-linux*, x86_64-*-linux*, i[34567]86-*-kfreebsd*-gnu)
+ (i[34567]86-*-knetbsd*-gnu, i[34567]86-*-gnu*): Also handle
+ x86_64-*-kfreebsd*-gnu.
+ Add i386/t-linux to tmake_file.
+
+2011-10-28 Ian Lance Taylor <iant@google.com>
+
+ * config/i386/morestack.S: Correct CFI information to do proper
+ returns throughout function. In 32-bit mode, save %ebx so that it
+ is restored on unwind.
+
+2011-10-25 Bernd Schmidt <bernds@codesourcery.com>
+
+ * config/c6x/pr-support.c (__gnu_unwind_24bit): Correct logic for the
+ case where B3 isn't the return register.
+
+ * config/c6x/pr-support.c (pop_compact_frame, pop_frame): Correct
+ logic for doubleword pops.
+
+2011-10-25 Andreas Tobler <andreast@fgznet.ch>
+
+ * config/rs6000/t-freebsd: Add wildcard.
+
+2011-10-21 Paul Brook <paul@codesourcery.com>
+
+ * unwind-arm-common.inc: Handle ID3/4 unwinding data.
+
+2011-10-16 Uros Bizjak <ubizjak@gmail.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/50737
+ * config/alpha/linux-unwind.h (alpha_fallback_frame_state): Set
+ fs->signal_frame to 1.
+
2011-10-07 Ian Lance Taylor <iant@google.com>
* generic-morestack-thread.c: #include <errno.h>.
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index e9f2fa2f2b8..8f0c02ff3ec 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -22,7 +22,6 @@
libgcc_topdir = @libgcc_topdir@
host_subdir = @host_subdir@
-gcc_srcdir = $(libgcc_topdir)/gcc
gcc_objdir = $(MULTIBUILDTOP)../../$(host_subdir)/gcc
srcdir = @srcdir@
@@ -50,6 +49,8 @@ target_noncanonical = @target_noncanonical@
# The rules for compiling them should be in the t-* file for the machine.
EXTRA_PARTS = @extra_parts@
+extra-parts = libgcc-extra-parts
+
# Multilib support variables.
MULTISRCTOP =
MULTIBUILDTOP =
@@ -62,6 +63,7 @@ INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
mkinstalldirs = $(SHELL) $(libgcc_topdir)/mkinstalldirs
+INSTALL_PARTS = $(EXTRA_PARTS)
objext = .o
@@ -119,7 +121,7 @@ installcheck:
.PHONY: all clean
clean:
- -rm -f config.h stamp-h stmp-ldirs libgcc.map
+ -rm -f config.h libgcc_tm.h stamp-h stmp-ldirs libgcc.map
-rm -f *$(objext)
-rm -f *.dep
-rm -f *.a
@@ -217,6 +219,41 @@ else
DECNUMINC =
endif
+# Options to use when compiling libgcc2.a.
+#
+LIBGCC2_DEBUG_CFLAGS = -g
+LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
+ $(LIBGCC2_DEBUG_CFLAGS) -DIN_LIBGCC2 \
+ -fbuilding-libgcc -fno-stack-protector \
+ $(INHIBIT_LIBC_CFLAGS)
+
+# Additional options to use when compiling libgcc2.a.
+# Some targets override this to -isystem include
+LIBGCC2_INCLUDES =
+
+# Additional target-dependent options for compiling libgcc2.a.
+HOST_LIBGCC2_CFLAGS =
+
+PICFLAG = @PICFLAG@
+
+# Defined in libgcc2.c, included only in the static library.
+LIB2FUNCS_ST = _eprintf __gcc_bcmp
+
+# List of functions not to build from libgcc2.c.
+LIB2FUNCS_EXCLUDE =
+
+# 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
+
+# List of extra C and assembler files to add to static and shared libgcc2.
+# Assembler files should have names ending in `.S'.
+LIB2ADD =
+
+# List of extra C and assembler files to add to static libgcc2.
+# Assembler files should have names ending in `.S'.
+LIB2ADD_ST =
+
# Specify the directories to be searched for header files.
# Both . and srcdir are used, in that order,
# so that *config.h will be found in the compilation
@@ -238,6 +275,16 @@ override CFLAGS := $(filter-out -fprofile-generate -fprofile-use,$(CFLAGS))
INTERNAL_CFLAGS = $(CFLAGS) $(LIBGCC2_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
$(INCLUDES) @set_have_cc_tls@ @set_use_emutls@
+# Options to use when compiling crtbegin/end.
+CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
+ -finhibit-size-directive -fno-inline -fno-exceptions \
+ -fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
+ -fno-stack-protector \
+ $(INHIBIT_LIBC_CFLAGS)
+
+# Extra flags to use when compiling crt{begin,end}.o.
+CRTSTUFF_T_CFLAGS =
+
MULTIDIR := $(shell $(CC) $(CFLAGS) -print-multi-directory)
MULTIOSDIR := $(shell $(CC) $(CFLAGS) -print-multi-os-directory)
@@ -279,6 +326,9 @@ LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde.c \
LIB2ADDEHSTATIC = $(LIB2ADDEH)
LIB2ADDEHSHARED = $(LIB2ADDEH)
+# nm flags to list global symbols in libgcc object files.
+SHLIB_NM_FLAGS = -pg
+
# Don't build libunwind by default.
LIBUNWIND =
SHLIBUNWIND_LINK =
@@ -287,6 +337,16 @@ SHLIBUNWIND_INSTALL =
tmake_file = @tmake_file@
include $(srcdir)/empty.mk $(tmake_file)
+# Collect target defines and headers from config.host.
+libgcc_tm_defines = @tm_defines@
+libgcc_tm_file = @tm_file@
+libgcc_tm.h: libgcc_tm.stamp; @true
+libgcc_tm.stamp:
+ DEFINES='$(libgcc_tm_defines)' HEADERS='$(libgcc_tm_file)' \
+ $(srcdir)/mkheader.sh > tmp-libgcc_tm.h
+ $(SHELL) $(srcdir)/../move-if-change tmp-libgcc_tm.h libgcc_tm.h
+ echo timestamp > $@
+
# Only handle shared libraries if both:
# - the user requested them
# - we know how to build them
@@ -332,16 +392,6 @@ vis_hide =
gen-hide-list = echo > \$@
endif
-ifneq ($(EXTRA_PARTS),)
- extra-parts = libgcc-extra-parts
- INSTALL_PARTS = $(EXTRA_PARTS)
-else
-ifneq ($(GCC_EXTRA_PARTS),)
- extra-parts = gcc-extra-parts
- INSTALL_PARTS = $(GCC_EXTRA_PARTS)
-endif
-endif
-
LIB2ADD += enable-execute-stack.c
LIB2ADDEH += $(srcdir)/emutls.c
@@ -388,40 +438,36 @@ LIB2_DIVMOD_FUNCS := $(filter-out $(LIB2FUNCS_EXCLUDE) $(LIB1ASMFUNCS), \
ifeq ($(enable_shared),yes)
lib1asmfuncs-o = $(patsubst %,%$(objext),$(LIB1ASMFUNCS))
-$(lib1asmfuncs-o): %$(objext): $(gcc_srcdir)/config/$(LIB1ASMSRC) %.vis
- $(gcc_compile) -DL$* -xassembler-with-cpp \
- -c $(gcc_srcdir)/config/$(LIB1ASMSRC) -include $*.vis
+$(lib1asmfuncs-o): %$(objext): $(srcdir)/config/$(LIB1ASMSRC) %.vis
+ $(gcc_compile) -DL$* -xassembler-with-cpp -c $< -include $*.vis
$(patsubst %,%.vis,$(LIB1ASMFUNCS)): %.vis: %_s$(objext)
$(gen-hide-list)
libgcc-objects += $(lib1asmfuncs-o)
lib1asmfuncs-s-o = $(patsubst %,%_s$(objext),$(LIB1ASMFUNCS))
-$(lib1asmfuncs-s-o): %_s$(objext): $(gcc_srcdir)/config/$(LIB1ASMSRC)
- $(gcc_s_compile) -DL$* -xassembler-with-cpp \
- -c $(gcc_srcdir)/config/$(LIB1ASMSRC)
+$(lib1asmfuncs-s-o): %_s$(objext): $(srcdir)/config/$(LIB1ASMSRC)
+ $(gcc_s_compile) -DL$* -xassembler-with-cpp -c $<
libgcc-s-objects += $(lib1asmfuncs-s-o)
else
lib1asmfuncs-o = $(patsubst %,%$(objext),$(LIB1ASMFUNCS))
-$(lib1asmfuncs-o): %$(objext): $(gcc_srcdir)/config/$(LIB1ASMSRC)
- $(gcc_compile) -DL$* -xassembler-with-cpp \
- -c $(gcc_srcdir)/config/$(LIB1ASMSRC)
+$(lib1asmfuncs-o): %$(objext): $(srcdir)/config/$(LIB1ASMSRC)
+ $(gcc_compile) -DL$* -xassembler-with-cpp -c $<
libgcc-objects += $(lib1asmfuncs-o)
endif
# Build lib2funcs. For the static library also include LIB2FUNCS_ST.
lib2funcs-o = $(patsubst %,%$(objext),$(lib2funcs) $(LIB2FUNCS_ST))
-$(lib2funcs-o): %$(objext): $(gcc_srcdir)/libgcc2.c
- $(gcc_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \
- $(vis_hide)
+$(lib2funcs-o): %$(objext): $(srcdir)/libgcc2.c
+ $(gcc_compile) -DL$* -c $< $(vis_hide)
libgcc-objects += $(lib2funcs-o)
ifeq ($(enable_shared),yes)
lib2funcs-s-o = $(patsubst %,%_s$(objext),$(lib2funcs))
-$(lib2funcs-s-o): %_s$(objext): $(gcc_srcdir)/libgcc2.c
- $(gcc_s_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c
+$(lib2funcs-s-o): %_s$(objext): $(srcdir)/libgcc2.c
+ $(gcc_s_compile) -DL$* -c $<
libgcc-s-objects += $(lib2funcs-s-o)
endif
@@ -449,15 +495,15 @@ endif
# Build LIB2_DIVMOD_FUNCS.
lib2-divmod-o = $(patsubst %,%$(objext),$(LIB2_DIVMOD_FUNCS))
-$(lib2-divmod-o): %$(objext): $(gcc_srcdir)/libgcc2.c
- $(gcc_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \
+$(lib2-divmod-o): %$(objext): $(srcdir)/libgcc2.c
+ $(gcc_compile) -DL$* -c $< \
-fexceptions -fnon-call-exceptions $(vis_hide)
libgcc-objects += $(lib2-divmod-o)
ifeq ($(enable_shared),yes)
lib2-divmod-s-o = $(patsubst %,%_s$(objext),$(LIB2_DIVMOD_FUNCS))
-$(lib2-divmod-s-o): %_s$(objext): $(gcc_srcdir)/libgcc2.c
- $(gcc_s_compile) -DL$* -c $(gcc_srcdir)/libgcc2.c \
+$(lib2-divmod-s-o): %_s$(objext): $(srcdir)/libgcc2.c
+ $(gcc_s_compile) -DL$* -c $< \
-fexceptions -fnon-call-exceptions
libgcc-s-objects += $(lib2-divmod-s-o)
endif
@@ -897,45 +943,39 @@ ALL_CRT_CFLAGS = $(CFLAGS) $(CRTSTUFF_CFLAGS) $(INCLUDES)
crt_compile = $(CC) $(ALL_CRT_CFLAGS) -o $@ $(compile_deps)
ifeq ($(CUSTOM_CRTSTUFF),)
-crtbegin$(objext): $(gcc_srcdir)/crtstuff.c
- $(crt_compile) $(CRTSTUFF_T_CFLAGS) \
- -c $(gcc_srcdir)/crtstuff.c -DCRT_BEGIN
+# Compile two additional files that are linked with every program
+# linked using GCC on systems using COFF or ELF, for the sake of C++
+# constructors.
+crtbegin$(objext): $(srcdir)/crtstuff.c
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN
-crtend$(objext): $(gcc_srcdir)/crtstuff.c
- $(crt_compile) $(CRTSTUFF_T_CFLAGS) \
- -c $(gcc_srcdir)/crtstuff.c -DCRT_END
+crtend$(objext): $(srcdir)/crtstuff.c
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_END
# These are versions of crtbegin and crtend for shared libraries.
-crtbeginS$(objext): $(gcc_srcdir)/crtstuff.c
- $(crt_compile) $(CRTSTUFF_T_CFLAGS_S) \
- -c $(gcc_srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFS_O
+crtbeginS$(objext): $(srcdir)/crtstuff.c
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS_S) -c $< -DCRT_BEGIN -DCRTSTUFFS_O
-crtendS$(objext): $(gcc_srcdir)/crtstuff.c
- $(crt_compile) $(CRTSTUFF_T_CFLAGS_S) \
- -c $(gcc_srcdir)/crtstuff.c -DCRT_END -DCRTSTUFFS_O
+crtendS$(objext): $(srcdir)/crtstuff.c
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS_S) -c $< -DCRT_END -DCRTSTUFFS_O
# This is a version of crtbegin for -static links.
-crtbeginT.o: $(gcc_srcdir)/crtstuff.c
- $(crt_compile) $(CRTSTUFF_T_CFLAGS) \
- -c $(gcc_srcdir)/crtstuff.c -DCRT_BEGIN -DCRTSTUFFT_O
+crtbeginT$(objext): $(srcdir)/crtstuff.c
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $< -DCRT_BEGIN -DCRTSTUFFT_O
+endif
+
+ifeq ($(CUSTOM_CRTIN),)
+# -x assembler-with-cpp is only needed on case-insensitive filesystem.
+crti$(objext): $(srcdir)/config/$(cpu_type)/crti.S
+ $(crt_compile) -c -x assembler-with-cpp $<
+
+crtn$(objext): $(srcdir)/config/$(cpu_type)/crtn.S
+ $(crt_compile) -c -x assembler-with-cpp $<
endif
# Build extra startfiles in the libgcc directory.
.PHONY: libgcc-extra-parts
libgcc-extra-parts: $(EXTRA_PARTS)
-ifneq ($(GCC_EXTRA_PARTS),)
-ifneq ($(sort $(EXTRA_PARTS)),$(GCC_EXTRA_PARTS))
- # If the gcc directory specifies which extra parts to
- # build for this target, and the libgcc configuration also
- # specifies, make sure they match. This can be removed
- # when the gcc directory no longer holds libgcc configuration;
- # it is useful when migrating a target.
- @echo "Configuration mismatch!"
- @echo "Extra parts from gcc directory: $(GCC_EXTRA_PARTS)"
- @echo "Extra parts from libgcc: $(EXTRA_PARTS)"
- exit 1
-endif
-endif
# Early copyback; see "all" above for the rationale. The
# early copy is necessary so that the gcc -B options find
@@ -951,45 +991,13 @@ endif
esac; \
done
-# Build extra startfiles in the gcc directory, for unconverted
-# targets.
-.PHONY: gcc-extra-parts
-gcc-extra-parts:
- # Recursively invoke make in the GCC directory to build any
- # startfiles (for now). We must do this just once, passing
- # it all the GCC_EXTRA_PARTS as simultaneous goal targets,
- # so that rules which cannot execute simultaneously are properly
- # serialized. We indirect through T_TARGET in case any multilib
- # directories contain an equals sign, to prevent make from
- # interpreting any of the goals as variable assignments.
-
- # We must use cd && make rather than make -C, or else the stage
- # number will be embedded in debug information.
-
- T=`$(PWD_COMMAND)`/ \
- && cd $(gcc_objdir) \
- && $(MAKE) GCC_FOR_TARGET="$(CC)" \
- MULTILIB_CFLAGS="$(CFLAGS)" \
- T=$$T \
- T_TARGET="$(patsubst %,$${T}%,$(GCC_EXTRA_PARTS))" \
- T_TARGET
-
- # Early copyback; see "all" above for the rationale. The
- # early copy is necessary so that the gcc -B options find
- # the right startup files when linking shared libgcc.
- $(mkinstalldirs) $(gcc_objdir)$(MULTISUBDIR)
- parts="$(GCC_EXTRA_PARTS)"; \
- for file in $$parts; do \
- rm -f $(gcc_objdir)$(MULTISUBDIR)/$$file; \
- $(INSTALL_DATA) $$file $(gcc_objdir)$(MULTISUBDIR)/; \
- case $$file in \
- *.a) \
- $(RANLIB) $(gcc_objdir)$(MULTISUBDIR)/$$file ;; \
- esac; \
- done
-
all: $(extra-parts)
+$(libgcc-objects) $(libgcc-s-objects) $(libgcc-eh-objects) \
+ $(libgcov-objects) \
+ $(libunwind-objects) $(libunwind-s-objects) \
+ $(extra-parts): libgcc_tm.h
+
install-unwind_h:
dest=$(gcc_objdir)/include/tmp$$$$-unwind.h; \
cp unwind.h $$dest; \
@@ -1067,11 +1075,3 @@ install-strip: install
.NOEXPORT:
include $(srcdir)/empty.mk $(wildcard *.dep)
-
-# TODO QUEUE:
-# Garbage collect in gcc/:
-# $(LIBGCC) settings in t-* are now unused
-#
-# Remove use of $(gcc_srcdir). Source files referenced using $(gcc_srcdir)
-# should move into the libgcc directory.
-
diff --git a/libgcc/config.host b/libgcc/config.host
index 08c00a37f97..05f084b70a0 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -60,6 +60,11 @@
# tmake_file A list of machine-description-specific
# makefile-fragments, if different from
# "$cpu_type/t-$cpu_type".
+# tm_defines List of target macros to define for all compilations.
+# tm_file A list of target macro files used only for code
+# built for the target, not the host. These files
+# are relative to $srcdir/config and must not have
+# the same names as files in $srcdir/../gcc/config.
# unwind_header The name of the header file declaring the unwind
# runtime interface routines.
@@ -67,6 +72,8 @@ asm_hidden_op=.hidden
enable_execute_stack=
extra_parts=
tmake_file=
+tm_file=
+tm_define=
md_unwind_header=no-unwind.h
unwind_header=unwind-generic.h
@@ -163,7 +170,7 @@ esac
case ${host} in
*-*-darwin*)
asm_hidden_op=.private_extern
- tmake_file="$tmake_file t-darwin ${cpu_type}/t-darwin t-slibgcc-darwin"
+ tmake_file="$tmake_file t-darwin ${cpu_type}/t-darwin t-libgcc-pic t-slibgcc-darwin"
extra_parts=crt3.o
;;
*-*-freebsd[12] | *-*-freebsd[12].* | *-*-freebsd*aout*)
@@ -179,22 +186,55 @@ case ${host} in
# This is the generic ELF configuration of FreeBSD. Later
# machine-specific sections may refine and add to this
# configuration.
- tmake_file="$tmake_file t-eh-dw2-dip"
+ tmake_file="$tmake_file t-freebsd t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver"
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o"
+ case ${target_thread_file} in
+ posix)
+ tmake_file="${tmake_file} t-freebsd-thread"
+ # Before 5.0, FreeBSD can't bind shared libraries to -lc
+ # when "optionally" threaded via weak pthread_* checks.
+ case ${host} in
+ *-*-freebsd[34] | *-*-freebsd[34].*)
+ tmake_file="${tmake_file} t-slibgcc-nolc-override"
+ ;;
+ esac
+ ;;
+ esac
;;
*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu | *-*-gnu* | *-*-kopensolaris*-gnu)
- tmake_file="$tmake_file t-eh-dw2-dip"
+ tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-eh-dw2-dip t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver t-linux"
extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
;;
+*-*-lynxos*)
+ tmake_file="$tmake_file t-lynx $cpu_type/t-crtstuff t-crtstuff-pic t-libgcc-pic"
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ ;;
*-*-netbsd*)
+ tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver"
+ # 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 ${host} in
+ *-*-netbsd*1.[7-9]* | *-*-netbsd[2-9]* | *-*-netbsdelf[2-9]*)
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
+ ;;
+ esac
;;
*-*-openbsd*)
+ tmake_file="$tmake_file t-crtstuff-pic t-libgcc-pic"
+ case ${target_thread_file} in
+ posix)
+ tmake_file="$tmake_file t-openbsd-thread"
+ ;;
+ esac
;;
*-*-rtems*)
+ extra_parts="crtbegin.o crtend.o"
;;
*-*-solaris2*)
# Unless linker support and dl_iterate_phdr are present,
# unwind-dw2-fde-dip.c automatically falls back to unwind-dw2-fde.c.
- tmake_file="$tmake_file t-sol2 t-eh-dw2-dip t-slibgcc t-slibgcc-elf-ver"
+ tmake_file="$tmake_file t-sol2 t-eh-dw2-dip t-libgcc-pic t-slibgcc t-slibgcc-elf-ver"
if test $with_gnu_ld = yes; then
tmake_file="$tmake_file t-slibgcc-gld"
else
@@ -213,14 +253,22 @@ case ${host} in
extra_parts="$extra_parts crt1.o gcrt1.o"
;;
*)
- tmake_file="$tmake_file t-crtin"
extra_parts="$extra_parts crt1.o crti.o crtn.o gcrt1.o"
;;
esac
;;
+*-*-uclinux*)
+ extra_parts="crtbegin.o crtend.o"
+ ;;
+*-*-*vms*)
+ tmake_file="vms/t-vms"
+ extra_parts="vcrt0.o pcrt0.o crtbegin.o crtbeginS.o crtend.o crtendS.o"
+ ;;
*-*-vxworks*)
+ tmake_file=t-vxworks
;;
*-*-elf)
+ extra_parts="crtbegin.o crtend.o"
;;
esac
@@ -239,17 +287,19 @@ esac
case ${host} in
alpha*-*-linux*)
- tmake_file="${tmake_file} t-crtfm"
+ tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm alpha/t-linux"
extra_parts="$extra_parts crtfastmath.o"
md_unwind_header=alpha/linux-unwind.h
;;
alpha*-*-freebsd*)
- tmake_file="${tmake_file} t-crtfm"
- extra_parts="$extra_parts crtfastmath.o"
+ tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm"
+ extra_parts="$extra_parts crtbeginT.o crtfastmath.o"
;;
alpha*-*-netbsd*)
+ tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee"
;;
alpha*-*-openbsd*)
+ tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee"
;;
alpha*-dec-osf5.1*)
tmake_file="${tmake_file} alpha/t-alpha alpha/t-ieee t-crtfm t-slibgcc alpha/t-slibgcc-osf"
@@ -258,32 +308,40 @@ alpha*-dec-osf5.1*)
tmake_file="${tmake_file} alpha/t-osf-pthread"
;;
esac
- extra_parts="${extra_parts} qrnnd.o crtfastmath.o gthr-posix.o"
+ extra_parts="${extra_parts} crtfastmath.o"
md_unwind_header=alpha/osf5-unwind.h
;;
alpha64-dec-*vms*)
- tmake_file="vms/t-vms vms/t-vms64 alpha/t-vms"
+ tmake_file="$tmake_file alpha/t-alpha alpha/t-ieee alpha/t-vms t-slibgcc-vms"
+ extra_parts="$extra_parts vms-dwarf2.o vms-dwarf2eh.o"
md_unwind_header=alpha/vms-unwind.h
;;
alpha*-dec-*vms*)
- tmake_file="vms/t-vms alpha/t-vms"
+ tmake_file="$tmake_file alpha/t-alpha alpha/t-ieee alpha/t-vms t-slibgcc-vms"
+ extra_parts="$extra_parts vms-dwarf2.o vms-dwarf2eh.o"
md_unwind_header=alpha/vms-unwind.h
;;
arm-wrs-vxworks)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file arm/t-arm arm/t-vxworks t-fdpbit"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
arm*-*-freebsd*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file arm/t-arm arm/t-strongarm-elf t-fdpbit"
;;
arm*-*-netbsdelf*)
+ tmake_file="$tmake_file arm/t-arm arm/t-netbsd t-slibgcc-gld-nover"
;;
arm*-*-linux*) # ARM GNU/Linux with ELF
- tmake_file="${tmake_file} t-fixedpoint-gnu-prefix"
+ tmake_file="${tmake_file} arm/t-arm t-fixedpoint-gnu-prefix"
case ${host} in
arm*-*-linux-*eabi)
- tmake_file="${tmake_file} arm/t-bpabi"
+ tmake_file="${tmake_file} arm/t-elf arm/t-bpabi arm/t-linux-eabi t-slibgcc-libgcc"
+ tm_file="$tm_file arm/bpabi-lib.h"
unwind_header=config/arm/unwind-arm.h
;;
+ *)
+ tmake_file="$tmake_file arm/t-linux"
+ ;;
esac
tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
;;
@@ -292,121 +350,196 @@ arm*-*-uclinux*) # ARM ucLinux
case ${host} in
arm*-*-uclinux*eabi)
tmake_file="${tmake_file} arm/t-bpabi"
+ tm_file="$tm_file arm/bpabi-lib.h"
unwind_header=config/arm/unwind-arm.h
;;
esac
- tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
arm*-*-ecos-elf)
- tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
arm*-*-eabi* | arm*-*-symbianelf* )
- tmake_file="${tmake_file} t-fixedpoint-gnu-prefix"
+ tmake_file="${tmake_file} arm/t-arm arm/t-elf t-fixedpoint-gnu-prefix"
+ tm_file="$tm_file arm/bpabi-lib.h"
case ${host} in
arm*-*-eabi*)
tmake_file="${tmake_file} arm/t-bpabi"
+ extra_parts="crtbegin.o crtend.o crti.o crtn.o"
;;
arm*-*-symbianelf*)
- tmake_file="${tmake_file} arm/t-symbian"
+ tmake_file="${tmake_file} arm/t-symbian t-slibgcc-nolc-override"
+ tm_file="$tm_file arm/symbian-lib.h"
+ # Symbian OS provides its own startup code.
;;
esac
tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
unwind_header=config/arm/unwind-arm.h
;;
arm*-*-rtems*)
- tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
arm*-*-elf)
- tmake_file="$tmake_file t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ tmake_file="$tmake_file arm/t-arm arm/t-elf t-softfp-sfdf t-softfp-excl arm/t-softfp t-softfp"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
arm*-wince-pe*)
+ tmake_file="$tmake_file arm/t-arm arm/t-wince-pe"
;;
avr-*-rtems*)
- tmake_file=t-fpbit
+ tmake_file="$tmake_file avr/t-avr t-fpbit"
+ tm_file="$tm_file avr/avr-lib.h"
+ # Don't use default.
+ extra_parts=
;;
avr-*-*)
# Make HImode functions for AVR
tmake_file="${cpu_type}/t-avr t-fpbit"
+ tm_file="$tm_file avr/avr-lib.h"
;;
bfin*-elf*)
- tmke_file=t-fdpbit
+ tmake_file="bfin/t-bfin bfin/t-elf bfin/t-crtlibid bfin/t-crtstuff t-fdpbit"
+ extra_parts="$extra_parts crtbeginS.o crtendS.o crti.o crtn.o crtlibid.o"
;;
bfin*-uclinux*)
- tmake_file=t-fdpbit
+ tmake_file="bfin/t-bfin bfin/t-elf bfin/t-crtlibid bfin/t-crtstuff t-fdpbit"
+ extra_parts="$extra_parts crtbeginS.o crtendS.o crtlibid.o"
md_unwind_header=bfin/linux-unwind.h
;;
bfin*-linux-uclibc*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file bfin/t-bfin bfin/t-elf bfin/t-crtstuff t-fdpbit bfin/t-linux"
# No need to build crtbeginT.o on uClibc systems. Should probably
# be moved to the OS specific section above.
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
md_unwind_header=bfin/linux-unwind.h
;;
bfin*-rtems*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file bfin/t-bfin t-fdpbit"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
bfin*-*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file bfin/t-bfin t-fdpbit"
+ extra_parts="crtbegin.o crtend.o crti.o crtn.o"
;;
-crisv32-*-elf | crisv32-*-none | cris-*-elf | cris-*-none)
- tmake_file=t-fdpbit
+crisv32-*-elf)
+ tmake_file="cris/t-cris t-fdpbit"
+ ;;
+crisv32-*-none)
+ tmake_file="cris/t-cris t-fdpbit"
extra_parts="crtbegin.o crtend.o"
;;
-cris-*-linux* | crisv32-*-linux*)
- tmake_file=t-fdpbit
+cris-*-elf)
+ tmake_file="$tmake_file cris/t-cris cris/t-elfmulti"
;;
-fido-*-elf)
+cris-*-none)
+ tmake_file="$tmake_file cris/t-cris cris/t-elfmulti"
+ extra_parts="crtbegin.o crtend.o"
+ ;;
+cris-*-linux* | crisv32-*-linux*)
+ tmake_file="$tmake_file cris/t-cris t-fdpbit cris/t-linux"
;;
fr30-*-elf)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file fr30/t-fr30 t-fdpbit"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
frv-*-elf)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file frv/t-frv t-fdpbit"
+ tm_file="$tm_file frv/frv-abi.h"
+ # Don't use crtbegin.o, crtend.o.
+ extra_parts="frvbegin.o frvend.o"
;;
frv-*-*linux*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file frv/t-frv frv/t-linux t-fdpbit"
+ tm_file="$tm_file frv/frv-abi.h"
;;
h8300-*-rtems*)
- tmake_file=t-fpbit
+ tmake_file="$tmake_file h8300/t-h8300 t-fpbit"
+ tm_file="$tm_file h8300/h8300-lib.h"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
h8300-*-elf*)
- tmake_file=t-fpbit
+ tmake_file="$tmake_file h8300/t-h8300 t-fpbit"
+ tm_file="$tm_file h8300/h8300-lib.h"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
hppa*64*-*-linux*)
+ tmake_file="$tmake_file pa/t-linux pa/t-linux64"
;;
hppa*-*-linux*)
+ tmake_file="$tmake_file pa/t-linux t-slibgcc-libgcc"
+ # Set the libgcc version number
+ if test x$enable_sjlj_exceptions = xyes; then
+ tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
+ else
+ tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
+ fi
md_unwind_header=pa/linux-unwind.h
;;
hppa[12]*-*-hpux10*)
+ tmake_file="$tmake_file pa/t-hpux pa/t-hpux10 t-libgcc-pic t-slibgcc"
+ # Set the libgcc version number
+ if test x$enable_sjlj_exceptions = xyes; then
+ tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
+ else
+ tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
+ fi
+ tmake_file="$tmake_file pa/t-slibgcc-hpux t-slibgcc-hpux"
md_unwind_header=pa/hpux-unwind.h
;;
hppa*64*-*-hpux11*)
+ tmake_file="$tmake_file pa/t-hpux pa/t-pa64 pa/t-stublib pa/t-stublib64 t-libgcc-pic t-slibgcc"
+ # Set the libgcc version number
+ if test x$enable_sjlj_exceptions = xyes; then
+ tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
+ else
+ tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
+ fi
+ tmake_file="$tmake_file pa/t-slibgcc-hpux t-slibgcc-hpux"
+ extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o \
+ libgcc_stub.a"
md_unwind_header=pa/hpux-unwind.h
;;
hppa[12]*-*-hpux11*)
+ tmake_file="$tmake_file pa/t-hpux pa/t-stublib t-libgcc-pic t-slibgcc"
+ # Set the libgcc version number
+ if test x$enable_sjlj_exceptions = xyes; then
+ tmake_file="$tmake_file pa/t-slibgcc-sjlj-ver"
+ else
+ tmake_file="$tmake_file pa/t-slibgcc-dwarf-ver"
+ fi
+ tmake_file="$tmake_file pa/t-slibgcc-hpux t-slibgcc-hpux"
+ extra_parts="libgcc_stub.a"
md_unwind_header=pa/hpux-unwind.h
;;
i[34567]86-*-darwin*)
tmake_file="$tmake_file i386/t-crtpc i386/t-crtfm"
+ tm_file="$tm_file i386/darwin-lib.h"
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
;;
x86_64-*-darwin*)
- tmake_file="t-darwin ${cpu_type}/t-darwin64 i386/t-crtpc i386/t-crtfm t-slibgcc-darwin"
+ tmake_file="$tmake_file i386/t-crtpc i386/t-crtfm"
+ tm_file="$tm_file i386/darwin-lib.h"
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
;;
i[34567]86-*-elf*)
+ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
;;
x86_64-*-elf*)
+ tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic"
;;
i[34567]86-*-freebsd*)
- tmake_file="${tmake_file} i386/t-freebsd"
+ tmake_file="${tmake_file} i386/t-freebsd i386/t-crtstuff"
;;
x86_64-*-freebsd*)
- tmake_file="${tmake_file} i386/t-freebsd"
+ tmake_file="${tmake_file} i386/t-freebsd i386/t-crtstuff"
;;
i[34567]86-*-netbsdelf*)
;;
x86_64-*-netbsd*)
+ tmake_file="${tmake_file} i386/t-crtstuff"
;;
i[34567]86-*-openbsd2.*|i[34567]86-*openbsd3.[0123])
;;
@@ -414,31 +547,33 @@ i[34567]86-*-openbsd*)
;;
i[34567]86-*-linux*)
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
- tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm t-dfprules"
+ tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm i386/t-crtstuff t-dfprules"
md_unwind_header=i386/linux-unwind.h
;;
i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i[34567]86-*-gnu* | i[34567]86-*-kopensolaris*-gnu)
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
- tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm t-dfprules"
+ tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm i386/t-crtstuff t-dfprules"
;;
x86_64-*-linux*)
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
- tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm t-dfprules"
+ tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm i386/t-crtstuff t-dfprules"
md_unwind_header=i386/linux-unwind.h
;;
x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu)
extra_parts="$extra_parts crtprec32.o crtprec64.o crtprec80.o crtfastmath.o"
- tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm t-dfprules"
+ tmake_file="${tmake_file} i386/t-crtpc i386/t-crtfm i386/t-crtstuff t-dfprules"
;;
i[34567]86-pc-msdosdjgpp*)
;;
i[34567]86-*-lynxos*)
;;
i[34567]86-*-nto-qnx*)
+ tmake_file="$tmake_file i386/t-nto t-libgcc-pic"
+ extra_parts=crtbegin.o
;;
i[34567]86-*-rtems*)
- extra_parts="crtbegin.o crtend.o crti.o crtn.o"
- tmake_file="${tmake_file} t-crtin i386/t-softfp i386/t-crtstuff t-rtems"
+ extra_parts="$extra_parts crti.o crtn.o"
+ tmake_file="${tmake_file} i386/t-softfp i386/t-crtstuff t-rtems"
;;
i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*)
tmake_file="$tmake_file i386/t-crtpc i386/t-crtfm"
@@ -449,86 +584,160 @@ i[4567]86-wrs-vxworks|i[4567]86-wrs-vxworksae)
;;
i[34567]86-*-cygwin*)
extra_parts="crtbegin.o crtend.o crtfastmath.o"
- tmake_file="i386/t-cygming i386/t-crtfm t-dfprules"
+ # This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
+ if test x$enable_sjlj_exceptions = xyes; then
+ tmake_eh_file="i386/t-sjlj-eh"
+ else
+ tmake_eh_file="i386/t-dw2-eh"
+ fi
+ # Shared libgcc DLL install dir depends on cross/native build.
+ if test x${build} = x${host} ; then
+ tmake_dlldir_file="i386/t-dlldir"
+ else
+ tmake_dlldir_file="i386/t-dlldir-x"
+ fi
+ tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_dlldir_file} i386/t-slibgcc-cygming i386/t-cygming i386/t-cygwin i386/t-crtfm i386/t-chkstk t-dfprules"
+ case ${target_thread_file} in
+ posix)
+ tmake_file="i386/t-mingw-pthread $tmake_file"
+ ;;
+ esac
;;
i[34567]86-*-mingw*)
extra_parts="crtbegin.o crtend.o crtfastmath.o"
- tmake_file="i386/t-cygming i386/t-crtfm t-dfprules"
+ case ${target_thread_file} in
+ win32)
+ tmake_file="$tmake_file i386/t-gthr-win32"
+ ;;
+ esac
+ # This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
+ if test x$enable_sjlj_exceptions = xyes; then
+ tmake_eh_file="i386/t-sjlj-eh"
+ else
+ tmake_eh_file="i386/t-dw2-eh"
+ fi
+ # Shared libgcc DLL install dir depends on cross/native build.
+ if test x${build} = x${host} ; then
+ tmake_dlldir_file="i386/t-dlldir"
+ else
+ tmake_dlldir_file="i386/t-dlldir-x"
+ fi
+ tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_dlldir_file} i386/t-slibgcc-cygming i386/t-cygming i386/t-mingw32 i386/t-crtfm i386/t-chkstk t-dfprules"
md_unwind_header=i386/w32-unwind.h
;;
x86_64-*-mingw*)
- tmake_file="t-dfprules i386/t-crtfm"
+ case ${target_thread_file} in
+ win32)
+ tmake_file="$tmake_file i386/t-gthr-win32"
+ ;;
+ esac
+ # This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
+ if test x$enable_sjlj_exceptions = xyes; then
+ tmake_eh_file="i386/t-sjlj-eh"
+ else
+ tmake_eh_file="i386/t-dw2-eh"
+ fi
+ # Shared libgcc DLL install dir depends on cross/native build.
+ if test x${build} = x${host} ; then
+ tmake_dlldir_file="i386/t-dlldir"
+ else
+ tmake_dlldir_file="i386/t-dlldir-x"
+ fi
+ tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_dlldir_file} i386/t-slibgcc-cygming i386/t-mingw32 t-dfprules i386/t-crtfm i386/t-chkstk"
extra_parts="$extra_parts crtfastmath.o"
;;
i[34567]86-*-interix3*)
+ tmake_file="$tmake_file i386/t-interix i386/t-chkstk"
;;
ia64*-*-elf*)
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
+ extra_parts="$extra_parts crtbeginS.o crtendS.o crtfastmath.o"
tmake_file="ia64/t-ia64 ia64/t-eh-ia64 t-crtfm"
;;
ia64*-*-freebsd*)
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
- tmake_file="ia64/t-ia64 ia64/t-eh-ia64 t-crtfm"
+ extra_parts="$extra_parts crtfastmath.o"
+ tmake_file="$tmake_file ia64/t-ia64 ia64/t-eh-ia64 t-crtfm"
;;
ia64*-*-linux*)
+ # Don't use crtbeginT.o from *-*-linux* default.
extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtfastmath.o"
- tmake_file="ia64/t-ia64 t-crtfm t-softfp-tf ia64/t-softfp t-softfp ia64/t-softfp-compat ia64/t-eh-ia64 t-libunwind ia64/t-glibc"
+ tmake_file="$tmake_file ia64/t-ia64 t-crtfm t-softfp-tf ia64/t-softfp t-softfp ia64/t-softfp-compat ia64/t-eh-ia64 t-libunwind ia64/t-linux"
if test x$with_system_libunwind != xyes ; then
- tmake_file="${tmake_file} t-libunwind-elf ia64/t-glibc-libunwind"
+ tmake_file="${tmake_file} t-libunwind-elf ia64/t-linux-libunwind"
fi
md_unwind_header=ia64/linux-unwind.h
;;
ia64*-*-hpux*)
- tmake_file="ia64/t-hpux"
+ tmake_file="ia64/t-ia64 ia64/t-hpux t-slibgcc ia64/t-slibgcc-hpux t-slibgcc-hpux"
;;
ia64-hp-*vms*)
- tmake_file="vms/t-vms vms/t-vms64 ia64/t-eh-ia64 ia64/t-vms"
+ tmake_file="$tmake_file ia64/t-ia64 ia64/t-eh-ia64 ia64/t-vms t-slibgcc-vms"
+ extra_parts="$extra_parts crtinitS.o"
md_unwind_header=ia64/vms-unwind.h
;;
iq2000*-*-elf*)
tmake_file=t-fdpbit
+ # Don't use default.
+ extra_parts=
;;
lm32-*-elf*|lm32-*-rtems*)
- extra_parts="crtbegin.o crtend.o crti.o crtn.o"
+ extra_parts="$extra_parts crti.o crtn.o"
tmake_file="lm32/t-lm32 lm32/t-elf t-softfp-sfdf t-softfp"
;;
lm32-*-uclinux*)
- extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o"
- tmake_file="lm32/t-lm32 lm32/t-uclinux t-softfp-sfdf t-softfp"
+ extra_parts="$extra_parts crtbegin.o crtendS.o crtbeginT.o"
+ tmake_file="lm32/t-lm32 lm32/t-uclinux t-libgcc-pic t-softfp-sfdf t-softfp"
;;
-m32r-*-elf*|m32r-*-rtems*)
+m32r-*-elf*)
tmake_file=t-fdpbit
;;
+m32r-*-rtems*)
+ tmake_file="m32r/t-m32r t-fdpbit"
+ ;;
m32rle-*-elf*)
tmake_file=t-fdpbit
;;
m32r-*-linux*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
;;
m32rle-*-linux*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file m32r/t-linux t-fdpbit"
;;
-m68k-*-elf*)
+m68k-*-elf* | fido-*-elf)
+ tmake_file="$tmake_file m68k/t-floatlib"
;;
m68k*-*-netbsdelf*)
;;
m68k*-*-openbsd*)
;;
m68k-*-uclinux*) # Motorola m68k/ColdFire running uClinux with uClibc
+ tmake_file="$tmake_file m68k/t-floatlib"
md_unwind_header=m68k/linux-unwind.h
;;
m68k-*-linux*) # Motorola m68k's running GNU/Linux
# with ELF format using glibc 2
# aka the GNU/Linux C library 6.
+ tmake_file="$tmake_file m68k/t-floatlib"
+ # If not configured with --enable-sjlj-exceptions, bump the
+ # libgcc version number.
+ if test x$enable_sjlj_exceptions != xyes; then
+ tmake_file="$tmake_file m68k/t-slibgcc-elf-ver"
+ fi
md_unwind_header=m68k/linux-unwind.h
;;
m68k-*-rtems*)
+ tmake_file="$tmake_file m68k/t-floatlib"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mcore-*-elf)
- tmake_file=t-fdpbit
+ tmake_file="mcore/t-mcore t-fdpbit"
+ extra_parts="$extra_parts crti.o crtn.o"
+ ;;
+microblaze*-linux*)
+ tmake_file="$tmake_file t-slibgcc-nolc-override microblaze/t-microblaze t-fdpbit"
;;
microblaze*-*-*)
tmake_file="microblaze/t-microblaze t-fdpbit"
+ extra_parts="crtbegin.o crtend.o crti.o crtn.o"
;;
mips-sgi-irix6.5*)
tmake_file="$tmake_file mips/t-irix6 t-crtfm mips/t-tpbit t-slibgcc mips/t-slibgcc-irix"
@@ -550,47 +759,57 @@ mips*-*-linux*) # Linux MIPS, either endian.
mips*-*-openbsd*)
;;
mips*-sde-elf*)
+ tmake_file="mips/t-crtstuff mips/t-mips16"
case "${with_newlib}" in
yes)
# newlib / libgloss.
;;
*)
# MIPS toolkit libraries.
- tmake_file=mips/t-sdemtk
+ tmake_file="$tmake_file mips/t-sdemtk"
;;
esac
- tmake_file="$tmake_file mips/t-mips16"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mipsisa32-*-elf* | mipsisa32el-*-elf* | \
mipsisa32r2-*-elf* | mipsisa32r2el-*-elf* | \
mipsisa64-*-elf* | mipsisa64el-*-elf* | \
mipsisa64r2-*-elf* | mipsisa64r2el-*-elf*)
- tmake_file="$tmake_file mips/t-mips16"
+ tmake_file="$tmake_file mips/t-elf mips/t-crtstuff mips/t-mips16"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mipsisa64sr71k-*-elf*)
- tmake_file=t-fdpbit
+ tmake_file="mips/t-elf mips/t-crtstuff t-fdpbit"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mipsisa64sb1-*-elf* | mipsisa64sb1el-*-elf*)
- tmake_file="$tmake_file mips/t-mips16"
+ tmake_file="$tmake_file mips/t-elf mips/t-crtstuff mips/t-mips16"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mips-*-elf* | mipsel-*-elf*)
- tmake_file="$tmake_file mips/t-mips16"
+ tmake_file="$tmake_file mips/t-elf mips/t-crtstuff mips/t-mips16"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mips64-*-elf* | mips64el-*-elf*)
- tmake_file="$tmake_file mips/t-mips16"
+ tmake_file="$tmake_file mips/t-elf mips/t-crtstuff mips/t-mips16"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mips64vr-*-elf* | mips64vrel-*-elf*)
+ tmake_file="$tmake_file mips/t-elf mips/t-vr mips/t-crtstuff"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mips64orion-*-elf* | mips64orionel-*-elf*)
- tmake_file="$tmake_file mips/t-mips16"
+ tmake_file="$tmake_file mips/t-elf mips/t-crtstuff mips/t-mips16"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mips*-*-rtems*)
- tmake_file="$tmake_file mips/t-mips16"
+ tmake_file="$tmake_file mips/t-elf mips/t-crtstuff mips/t-mips16"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
mips-wrs-vxworks)
;;
mipstx39-*-elf* | mipstx39el-*-elf*)
- tmake_file="$tmake_file mips/t-mips16"
+ tmake_file="$tmake_file mips/t-crtstuff mips/t-mips16"
;;
mmix-knuth-mmixware)
extra_parts="crti.o crtn.o crtbegin.o crtend.o"
@@ -599,12 +818,17 @@ mmix-knuth-mmixware)
mn10300-*-*)
tmake_file=t-fdpbit
;;
-moxie-*-*)
+moxie-*-elf | moxie-*-uclinux*)
tmake_file="moxie/t-moxie t-softfp-sfdf t-softfp-excl t-softfp"
- extra_parts="crtbegin.o crtend.o crti.o crtn.o"
+ extra_parts="$extra_parts crti.o crtn.o"
+ ;;
+moxie-*-rtems*)
+ tmake_file="moxie/t-moxie t-softfp-sfdf t-softfp-excl t-softfp"
+ # Don't use default.
+ extra_parts=
;;
pdp11-*-*)
- tmake_file=t-fdpbit
+ tmake_file="pdp11/t-pdp11 t-fdpbit"
;;
picochip-*-*)
tmake_file="picochip/t-picochip t-fpbit"
@@ -623,72 +847,86 @@ powerpc-*-darwin*)
extra_parts="$extra_parts crt2.o"
;;
powerpc64-*-darwin*)
- tmake_file="$tmake_file rs6000/t-ibm-ldouble"
+ tmake_file="$tmake_file rs6000/t-darwin64 rs6000/t-ibm-ldouble"
extra_parts="$extra_parts crt2.o"
;;
powerpc-*-freebsd*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-freebsd t-softfp-sfdf t-softfp-excl t-softfp"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff rs6000/t-freebsd t-softfp-sfdf t-softfp-excl t-softfp t-slibgcc-libgcc"
+ extra_parts="$extra_parts crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-netbsd*)
+ tmake_file="$tmake_file rs6000/t-crtstuff"
;;
powerpc-*-eabispe*)
- tmake_file="${tmake_file} rs6000/t-ppccomm"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic"
+ extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-eabisimaltivec*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-eabisim*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-elf*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-eabialtivec*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-xilinx-eabi*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-eabi*)
- tmake_file="${tmake_file} rs6000/t-ppccomm t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-rtems*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpc-*-linux* | powerpc64-*-linux*)
- tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ldbl128 t-softfp-sfdf t-softfp-excl t-dfprules rs6000/t-ppc64-fp t-softfp"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-crtstuff rs6000/t-linux t-softfp-sfdf t-softfp-excl t-dfprules rs6000/t-ppc64-fp t-softfp t-slibgcc-libgcc"
+ extra_parts="$extra_parts ecrti.o ecrtn.o ncrti.o ncrtn.o"
md_unwind_header=rs6000/linux-unwind.h
;;
powerpc-wrs-vxworks|powerpc-wrs-vxworksae)
tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
;;
powerpc-*-lynxos*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file t-fdpbit"
;;
powerpcle-*-elf*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpcle-*-eabisim*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
powerpcle-*-eabi*)
- tmake_file="rs6000/t-ppccomm-ldbl t-fdpbit"
+ tmake_file="${tmake_file} rs6000/t-ppccomm rs6000/t-ppccomm-ldbl rs6000/t-crtstuff t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o ecrti.o ecrtn.o ncrti.o ncrtn.o"
;;
rs6000-ibm-aix4.[3456789]* | powerpc-ibm-aix4.[3456789]*)
md_unwind_header=rs6000/aix-unwind.h
- tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble"
+ tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble rs6000/t-slibgcc-aix"
;;
rs6000-ibm-aix5.1.* | powerpc-ibm-aix5.1.*)
md_unwind_header=rs6000/aix-unwind.h
- tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble"
+ tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble rs6000/t-slibgcc-aix"
;;
rs6000-ibm-aix[56789].* | powerpc-ibm-aix[56789].*)
md_unwind_header=rs6000/aix-unwind.h
- tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble"
+ tmake_file="t-fdpbit rs6000/t-ppc64-fp rs6000/t-ibm-ldouble rs6000/t-slibgcc-aix"
;;
rx-*-elf)
- extra_parts="crtbegin.o crtend.o"
tmake_file="rx/t-rx t-fdpbit"
+ tm_file="$tm_file rx/rx-abi.h rx/rx-lib.h"
;;
s390-*-linux*)
tmake_file="${tmake_file} s390/t-crtstuff s390/t-linux s390/32/t-floattodi"
@@ -699,37 +937,60 @@ s390x-*-linux*)
md_unwind_header=s390/linux-unwind.h
;;
s390x-ibm-tpf*)
- tmake_file="${tmake_file} s390/t-crtstuff s390/t-tpf t-eh-dw2-dip"
+ tmake_file="${tmake_file} s390/t-crtstuff t-libgcc-pic t-eh-dw2-dip"
+ extra_parts="crtbeginS.o crtendS.o"
md_unwind_header=s390/tpf-unwind.h
;;
score-*-elf)
tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl t-softfp"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
-sh-*-elf* | sh[12346l]*-*-elf* | \
- sh-*-linux* | sh[2346lbe]*-*-linux* | \
- sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
- sh64-*-netbsd* | sh64l*-*-netbsd*)
- case ${host} in
- sh*-*-linux*)
- tmake_file="${tmake_file} sh/t-linux t-fdpbit"
- md_unwind_header=sh/linux-unwind.h
+sh-*-elf* | sh[12346l]*-*-elf*)
+ tmake_file="$tmake_file sh/t-sh t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crt1.o crti.o crtn.o crtbeginS.o crtendS.o \
+ libic_invalidate_array_4-100.a \
+ libic_invalidate_array_4-200.a \
+ libic_invalidate_array_4a.a \
+ libgcc-Os-4-200.a libgcc-4-300.a"
+ case ${host} in sh64*-*-*)
+ tmake_file="$tmake_file sh/t-sh64"
;;
- sh*-*-netbsd*)
- # NetBSD's C library includes a fast software FP library that
- # has support for setting/setting the rounding mode, exception
- # mask, etc. Therefore, we don't want to include software FP
- # in libgcc.
+ esac
+ case ${host} in
+ sh*-superh-elf)
+ tmake_file="$tmake_file sh/t-superh"
+ extra_parts="$extra_parts crt1-mmu.o gcrt1-mmu.o gcrt1.o"
+ ;;
+ esac
+ ;;
+sh-*-linux* | sh[2346lbe]*-*-linux*)
+ tmake_file="${tmake_file} sh/t-sh t-slibgcc-libgcc sh/t-linux t-fdpbit"
+ case ${host} in sh64*-*-linux*)
+ tmake_file="$tmake_file sh/t-sh64"
;;
- sh*-*-*)
- tmake_file=t-fdpbit
+ esac
+ md_unwind_header=sh/linux-unwind.h
+ ;;
+sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
+ sh64-*-netbsd* | sh64l*-*-netbsd*)
+ tmake_file="$tmake_file sh/t-sh sh/t-netbsd"
+ case ${host} in
+ sh5*-*-netbsd* | sh64*-netbsd*)
+ tmake_file="$tmake_file sh/t-sh64"
;;
esac
+ # NetBSD's C library includes a fast software FP library that
+ # has support for setting/setting the rounding mode, exception
+ # mask, etc. Therefore, we don't want to include software FP
+ # in libgcc.
;;
sh-*-rtems*)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file sh/t-sh t-crtstuff-pic t-fdpbit"
+ extra_parts="$extra_parts crt1.o crti.o crtn.o crtbeginS.o crtendS.o \
+ $sh_ic_extra_parts $sh_opt_extra_parts"
;;
sh-wrs-vxworks)
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file sh/t-sh t-crtstuff-pic t-fdpbit"
;;
sparc-*-netbsdelf*)
;;
@@ -743,22 +1004,32 @@ sparc-*-elf*)
tmake_file="sparc/t-softmul"
;;
esac
- tmake_file="${tmake_file} t-fdpbit t-crtin t-crtfm"
- extra_parts="crtbegin.o crtend.o crti.o crtn.o crtfastmath.o"
+ tmake_file="${tmake_file} t-fdpbit t-crtfm"
+ extra_parts="$extra_parts crti.o crtn.o crtfastmath.o"
;;
sparc-*-linux*) # SPARC's running GNU/Linux, libc6
+ tmake_file="${tmake_file} t-crtfm sparc/t-linux64"
case ${host} in
*-leon*)
- tmake_file=t-fdpbit
+ tmake_file="${tmake_file} t-fdpbit"
+ ;;
+ *)
+ tmake_file="${tmake_file} sparc/t-linux"
+ ;;
+ esac
+ case ${host} in
+ *-leon[3-9]*)
;;
+ *)
+ tmake_file="$tmake_file sparc/t-softmul"
+ ;;
esac
extra_parts="$extra_parts crtfastmath.o"
- tmake_file="${tmake_file} t-crtfm"
md_unwind_header=sparc/linux-unwind.h
;;
sparc-*-rtems*)
- tmake_file="sparc/t-elf t-crtin t-crtfm t-rtems t-fdpbit"
- extra_parts="crtbegin.o crtend.o crti.o crtn.o crtfastmath.o"
+ tmake_file="sparc/t-elf t-crtfm t-rtems t-fdpbit"
+ extra_parts="$extra_parts crti.o crtn.o crtfastmath.o"
;;
sparc*-*-solaris2*)
tmake_file="$tmake_file t-crtfm"
@@ -766,37 +1037,50 @@ sparc*-*-solaris2*)
md_unwind_header=sparc/sol2-unwind.h
;;
sparc64-*-elf*)
- tmake_file="${tmake_file} t-crtin t-crtfm"
- extra_parts="crtbegin.o crtend.o crti.o crtn.o crtfastmath.o"
+ tmake_file="${tmake_file} t-crtfm"
+ extra_parts="$extra_parts crti.o crtn.o crtfastmath.o"
;;
sparc64-*-rtems*)
- tmake_file="sparc/t-elf t-crtin t-crtfm t-rtems"
- extra_parts="crtbegin.o crtend.o crti.o crtn.o crtfastmath.o"
+ tmake_file="sparc/t-elf t-crtfm t-rtems"
+ extra_parts="$extra_parts crti.o crtn.o crtfastmath.o"
;;
sparc-wrs-vxworks)
;;
sparc64-*-freebsd*|ultrasparc-*-freebsd*)
tmake_file="$tmake_file t-crtfm"
- extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o crtfastmath.o"
+ extra_parts="$extra_parts crtfastmath.o"
;;
sparc64-*-linux*) # 64-bit SPARC's running GNU/Linux
extra_parts="$extra_parts crtfastmath.o"
- tmake_file="${tmake_file} t-crtfm"
+ tmake_file="${tmake_file} t-crtfm sparc/t-linux sparc/t-linux64"
md_unwind_header=sparc/linux-unwind.h
;;
sparc64-*-netbsd*)
;;
spu-*-elf*)
- tmake_file="t-fdpbit spu/t-elf"
+ tmake_file="$tmake_file spu/t-elf t-libgcc-pic t-fdpbit"
+ extra_parts="$extra_parts \
+ libgcc_cachemgr.a libgcc_cachemgr_nonatomic.a \
+ libgcc_cache8k.a libgcc_cache16k.a libgcc_cache32k.a \
+ libgcc_cache64k.a libgcc_cache128k.a"
+ ;;
+tic6x-*-uclinux)
+ tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl t-softfp c6x/t-elf c6x/t-uclinux t-crtstuff-pic t-libgcc-pic t-slibgcc t-slibgcc-gld t-slibgcc-elf-ver t-gnu-prefix"
+ tm_file="$tm_file c6x/c6x-abi.h"
+ extra_parts="crtbeginS.o crtendS.o crti.o crtn.o"
+ unwind_header=config/c6x/unwind-c6x.h
;;
-tic6x-*-*)
- tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl t-softfp t-gnu-prefix c6x/t-c6x-elf"
+tic6x-*-elf)
+ tmake_file="${tmake_file} t-softfp-sfdf t-softfp-excl t-softfp t-gnu-prefix c6x/t-elf"
+ tm_file="$tm_file c6x/c6x-abi.h"
+ extra_parts="$extra_parts crtbeginS.o crtendS.o crti.o crtn.o"
unwind_header=config/c6x/unwind-c6x.h
;;
v850*-*-*)
- tmake_file=t-fdpbit
+ tmake_file="v850/t-v850 t-fdpbit"
;;
vax-*-linux*)
+ tmake_file="$tmake_file vax/t-linux"
;;
vax-*-netbsdelf*)
;;
@@ -806,20 +1090,24 @@ xstormy16-*-elf)
tmake_file=t-fdpbit
;;
xtensa*-*-elf*)
- tmake_file=xtensa/t-xtensa
+ tmake_file="$tmake_file xtensa/t-xtensa xtensa/t-elf"
+ extra_parts="$extra_parts crti.o crtn.o"
;;
xtensa*-*-linux*)
- tmake_file=xtensa/t-xtensa
+ tmake_file="$tmake_file xtensa/t-xtensa xtensa/t-linux"
md_unwind_header=xtensa/linux-unwind.h
;;
am33_2.0-*-linux*)
+ # Don't need crtbeginT.o from *-*-linux* default.
extra_parts="crtbegin.o crtend.o crtbeginS.o crtendS.o"
- tmake_file=t-fdpbit
+ tmake_file="$tmake_file t-fdpbit"
;;
m32c-*-elf*|m32c-*-rtems*)
+ tmake_file="$tmake_file m32c/t-m32c"
;;
mep*-*-*)
- tmake_file=t-fdpbit
+ tmake_file="mep/t-mep t-fdpbit"
+ extra_parts="crtbegin.o crtend.o"
;;
*)
echo "*** Configuration ${host} not supported" 1>&2
@@ -829,9 +1117,10 @@ esac
case ${host} in
i[34567]86-*-linux* | x86_64-*-linux* | \
- i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | \
+ i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu | \
+ i[34567]86-*-knetbsd*-gnu | \
i[34567]86-*-gnu*)
- tmake_file="${tmake_file} t-tls"
+ tmake_file="${tmake_file} t-tls i386/t-linux"
if test "$libgcc_cv_cfi" = "yes"; then
tmake_file="${tmake_file} t-stack i386/t-stack-i386"
fi
@@ -860,5 +1149,6 @@ i[34567]86-*-linux* | x86_64-*-linux*)
if test "${host_address}" = 64; then
tmake_file="${tmake_file} i386/${host_address}/t-softfp-compat"
fi
+ tm_file="${tm_file} i386/value-unwind.h"
;;
esac
diff --git a/libgcc/config/alpha/gthr-posix.c b/libgcc/config/alpha/gthr-posix.c
new file mode 100644
index 00000000000..02681a4371e
--- /dev/null
+++ b/libgcc/config/alpha/gthr-posix.c
@@ -0,0 +1,266 @@
+/* POSIX threads dummy routines for systems without weak definitions. */
+/* Compile this one with gcc. */
+/* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2011
+ 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "tconfig.h"
+#include "tm.h"
+#include "libgcc_tm.h"
+# define __gthrw_pragma(pragma) _Pragma (#pragma)
+/* Define so we provide weak definitions of functions used by libobjc only. */
+#define _LIBOBJC_WEAK
+#include "gthr.h"
+
+int
+pthread_once (pthread_once_t *once ATTRIBUTE_UNUSED,
+ void (*func) (void) ATTRIBUTE_UNUSED)
+{
+ return -1;
+}
+
+int
+pthread_key_create (pthread_key_t *key ATTRIBUTE_UNUSED,
+ void (*dtor) (void *) ATTRIBUTE_UNUSED)
+{
+ return -1;
+}
+
+int
+pthread_key_delete (pthread_key_t key ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+void *
+pthread_getspecific (pthread_key_t key ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_setspecific (pthread_key_t key ATTRIBUTE_UNUSED,
+ const void *ptr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_create (pthread_t *thread ATTRIBUTE_UNUSED,
+ const pthread_attr_t *attr ATTRIBUTE_UNUSED,
+ void *(*start_routine) (void *) ATTRIBUTE_UNUSED,
+ void *arg ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_join (pthread_t thread ATTRIBUTE_UNUSED,
+ void **value_ptr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+void
+pthread_exit (void *value_ptr ATTRIBUTE_UNUSED)
+{
+}
+
+int
+pthread_detach (pthread_t thread ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_cancel (pthread_t thread ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_mutex_lock (pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_mutex_trylock (pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+#ifdef _POSIX_TIMEOUTS
+#if _POSIX_TIMEOUTS >= 0
+int
+pthread_mutex_timedlock (pthread_mutex_t *mutex ATTRIBUTE_UNUSED,
+ const struct timespec *abs_timeout ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+#endif
+#endif /* _POSIX_TIMEOUTS */
+
+int
+pthread_mutex_unlock (pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_mutexattr_init (pthread_mutexattr_t *attr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_mutexattr_settype (pthread_mutexattr_t *attr ATTRIBUTE_UNUSED,
+ int type ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_mutexattr_destroy (pthread_mutexattr_t *attr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_cond_broadcast (pthread_cond_t *cond ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_cond_destroy (pthread_cond_t *cond ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_cond_init (pthread_cond_t *cond ATTRIBUTE_UNUSED,
+ const pthread_condattr_t *attr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_cond_signal (pthread_cond_t *cond ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_cond_wait (pthread_cond_t *cond ATTRIBUTE_UNUSED,
+ pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_cond_timedwait (pthread_cond_t *cond ATTRIBUTE_UNUSED,
+ pthread_mutex_t *mutex ATTRIBUTE_UNUSED,
+ const struct timespec *abstime ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_mutex_init (pthread_mutex_t *mutex ATTRIBUTE_UNUSED,
+ const pthread_mutexattr_t *attr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_mutex_destroy (pthread_mutex_t *mutex ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+pthread_t
+pthread_self (void)
+{
+ return (pthread_t) 0;
+}
+
+#ifdef _POSIX_PRIORITY_SCHEDULING
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
+int
+sched_get_priority_max (int policy ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+sched_get_priority_min (int policy ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
+#endif /* _POSIX_PRIORITY_SCHEDULING */
+
+int
+sched_yield (void)
+{
+ return 0;
+}
+
+int
+pthread_attr_destroy (pthread_attr_t *attr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_attr_init (pthread_attr_t *attr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_attr_setdetachstate (pthread_attr_t *attr ATTRIBUTE_UNUSED,
+ int detachstate ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
+int
+pthread_getschedparam (pthread_t thread ATTRIBUTE_UNUSED,
+ int *policy ATTRIBUTE_UNUSED,
+ struct sched_param *param ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+int
+pthread_setschedparam (pthread_t thread ATTRIBUTE_UNUSED,
+ int policy ATTRIBUTE_UNUSED,
+ const struct sched_param *param ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
+
diff --git a/gcc/config/alpha/libgcc-alpha-ldbl.ver b/libgcc/config/alpha/libgcc-alpha-ldbl.ver
index 8dc54a74980..8dc54a74980 100644
--- a/gcc/config/alpha/libgcc-alpha-ldbl.ver
+++ b/libgcc/config/alpha/libgcc-alpha-ldbl.ver
diff --git a/libgcc/config/alpha/linux-unwind.h b/libgcc/config/alpha/linux-unwind.h
index e43aacfd00b..629d557c46c 100644
--- a/libgcc/config/alpha/linux-unwind.h
+++ b/libgcc/config/alpha/linux-unwind.h
@@ -74,5 +74,7 @@ alpha_fallback_frame_state (struct _Unwind_Context *context,
fs->regs.reg[64].how = REG_SAVED_OFFSET;
fs->regs.reg[64].loc.offset = (long)&sc->sc_pc - new_cfa;
fs->retaddr_column = 64;
+ fs->signal_frame = 1;
+
return _URC_NO_REASON;
}
diff --git a/gcc/config/alpha/qrnnd.asm b/libgcc/config/alpha/qrnnd.S
index 51b13bce6ad..51b13bce6ad 100644
--- a/gcc/config/alpha/qrnnd.asm
+++ b/libgcc/config/alpha/qrnnd.S
diff --git a/libgcc/config/alpha/t-alpha b/libgcc/config/alpha/t-alpha
index 14c72d0808b..0b6ffb1ba34 100644
--- a/libgcc/config/alpha/t-alpha
+++ b/libgcc/config/alpha/t-alpha
@@ -1,2 +1,2 @@
# This is a support routine for longlong.h, used by libgcc2.c.
-LIB2ADD += $(gcc_srcdir)/config/alpha/qrnnd.asm
+LIB2ADD += $(srcdir)/config/alpha/qrnnd.S
diff --git a/gcc/config/alpha/t-linux b/libgcc/config/alpha/t-linux
index fabf38f9cce..fabf38f9cce 100644
--- a/gcc/config/alpha/t-linux
+++ b/libgcc/config/alpha/t-linux
diff --git a/libgcc/config/alpha/t-osf-pthread b/libgcc/config/alpha/t-osf-pthread
index c51f375a048..9a175dbeb9e 100644
--- a/libgcc/config/alpha/t-osf-pthread
+++ b/libgcc/config/alpha/t-osf-pthread
@@ -2,4 +2,4 @@
HOST_LIBGCC2_CFLAGS += -pthread
# Provide dummy POSIX threads functions
-LIB2ADD += $(gcc_srcdir)/gthr-posix.c
+LIB2ADD += $(srcdir)/config/alpha/gthr-posix.c
diff --git a/libgcc/config/alpha/t-slibgcc-osf b/libgcc/config/alpha/t-slibgcc-osf
index 33a07a7b6aa..66e5cf12aa1 100644
--- a/libgcc/config/alpha/t-slibgcc-osf
+++ b/libgcc/config/alpha/t-slibgcc-osf
@@ -22,7 +22,7 @@
SHLIB_LDFLAGS = -Wl,-msym -Wl,-set_version,gcc.1 -Wl,-soname,$(SHLIB_SONAME) \
-Wl,-hidden -Wl,-input,$(SHLIB_MAP)
-SHLIB_MKMAP = $(gcc_srcdir)/mkmap-flat.awk
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
SHLIB_MKMAP_OPTS = -v osf_export=1
# Needed so mkmap-flat.awk can parse the nm output.
SHLIB_NM_FLAGS = -Bg
diff --git a/libgcc/config/alpha/t-vms b/libgcc/config/alpha/t-vms
new file mode 100644
index 00000000000..dd5760d9747
--- /dev/null
+++ b/libgcc/config/alpha/t-vms
@@ -0,0 +1,9 @@
+# This object must be linked with in order to make the executable debuggable.
+# vms-ld handles it automatically when passed -g.
+vms-dwarf2.o: $(srcdir)/config/alpha/vms-dwarf2.S
+ $(gcc_compile) -c -x assembler-with-cpp $<
+
+vms-dwarf2eh.o: $(srcdir)/config/alpha/vms-dwarf2eh.S
+ $(gcc_compile) -c -x assembler-with-cpp $<
+
+LIB2ADD += $(srcdir)/config/alpha/vms-gcc_shell_handler.c
diff --git a/gcc/config/alpha/vms-dwarf2.asm b/libgcc/config/alpha/vms-dwarf2.S
index 531c7aa9984..531c7aa9984 100644
--- a/gcc/config/alpha/vms-dwarf2.asm
+++ b/libgcc/config/alpha/vms-dwarf2.S
diff --git a/gcc/config/alpha/vms-dwarf2eh.asm b/libgcc/config/alpha/vms-dwarf2eh.S
index e0eaf9d3741..e0eaf9d3741 100644
--- a/gcc/config/alpha/vms-dwarf2eh.asm
+++ b/libgcc/config/alpha/vms-dwarf2eh.S
diff --git a/gcc/config/alpha/vms-gcc_shell_handler.c b/libgcc/config/alpha/vms-gcc_shell_handler.c
index 67d0fe7f9aa..67d0fe7f9aa 100644
--- a/gcc/config/alpha/vms-gcc_shell_handler.c
+++ b/libgcc/config/alpha/vms-gcc_shell_handler.c
diff --git a/gcc/config/arm/bpabi-v6m.S b/libgcc/config/arm/bpabi-v6m.S
index 4ecea6da5a6..4ecea6da5a6 100644
--- a/gcc/config/arm/bpabi-v6m.S
+++ b/libgcc/config/arm/bpabi-v6m.S
diff --git a/gcc/config/arm/bpabi.S b/libgcc/config/arm/bpabi.S
index 2ff338927fa..2ff338927fa 100644
--- a/gcc/config/arm/bpabi.S
+++ b/libgcc/config/arm/bpabi.S
diff --git a/gcc/config/arm/bpabi.c b/libgcc/config/arm/bpabi.c
index 283bdc0acf0..283bdc0acf0 100644
--- a/gcc/config/arm/bpabi.c
+++ b/libgcc/config/arm/bpabi.c
diff --git a/libgcc/config/arm/crti.S b/libgcc/config/arm/crti.S
new file mode 100644
index 00000000000..50915f9e31f
--- /dev/null
+++ b/libgcc/config/arm/crti.S
@@ -0,0 +1,86 @@
+# Copyright (C) 2001, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+# Written By Nick Clifton
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+/* An executable stack is *not* required for these functions. */
+#if defined(__ELF__) && defined(__linux__)
+.section .note.GNU-stack,"",%progbits
+.previous
+#endif
+
+# This file just make a stack frame for the contents of the .fini and
+# .init sections. Users may put any desired instructions in those
+# sections.
+
+#ifdef __ELF__
+#define TYPE(x) .type x,function
+#else
+#define TYPE(x)
+#endif
+#ifdef __ARM_EABI__
+/* Some attributes that are common to all routines in this file. */
+ /* Tag_ABI_align_needed: This code does not require 8-byte
+ alignment from the caller. */
+ /* .eabi_attribute 24, 0 -- default setting. */
+ /* Tag_ABI_align_preserved: This code preserves 8-byte
+ alignment in any callee. */
+ .eabi_attribute 25, 1
+#endif /* __ARM_EABI__ */
+
+ # Note - this macro is complemented by the FUNC_END macro
+ # in crtn.S. If you change this macro you must also change
+ # that macro match.
+.macro FUNC_START
+#ifdef __thumb__
+ .thumb
+
+ push {r3, r4, r5, r6, r7, lr}
+#else
+ .arm
+ # Create a stack frame and save any call-preserved registers
+ mov ip, sp
+ stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
+ sub fp, ip, #4
+#endif
+.endm
+
+ .section ".init"
+ .align 2
+ .global _init
+#ifdef __thumb__
+ .thumb_func
+#endif
+ TYPE(_init)
+_init:
+ FUNC_START
+
+
+ .section ".fini"
+ .align 2
+ .global _fini
+#ifdef __thumb__
+ .thumb_func
+#endif
+ TYPE(_fini)
+_fini:
+ FUNC_START
+
+# end of crti.S
diff --git a/libgcc/config/arm/crtn.S b/libgcc/config/arm/crtn.S
new file mode 100644
index 00000000000..8c5f22572f7
--- /dev/null
+++ b/libgcc/config/arm/crtn.S
@@ -0,0 +1,83 @@
+# Copyright (C) 2001, 2004, 2008, 2009, 2010, 2011
+# Free Software Foundation, Inc.
+# Written By Nick Clifton
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+/* An executable stack is *not* required for these functions. */
+#if defined(__ELF__) && defined(__linux__)
+.section .note.GNU-stack,"",%progbits
+.previous
+#endif
+
+#ifdef __ARM_EABI__
+/* Some attributes that are common to all routines in this file. */
+ /* Tag_ABI_align_needed: This code does not require 8-byte
+ alignment from the caller. */
+ /* .eabi_attribute 24, 0 -- default setting. */
+ /* Tag_ABI_align_preserved: This code preserves 8-byte
+ alignment in any callee. */
+ .eabi_attribute 25, 1
+#endif /* __ARM_EABI__ */
+
+# This file just makes sure that the .fini and .init sections do in
+# fact return. Users may put any desired instructions in those sections.
+# This file is the last thing linked into any executable.
+
+ # Note - this macro is complemented by the FUNC_START macro
+ # in crti.S. If you change this macro you must also change
+ # that macro match.
+ #
+ # Note - we do not try any fancy optimizations of the return
+ # sequences here, it is just not worth it. Instead keep things
+ # simple. Restore all the save resgisters, including the link
+ # register and then perform the correct function return instruction.
+ # We also save/restore r3 to ensure stack alignment.
+.macro FUNC_END
+#ifdef __thumb__
+ .thumb
+
+ pop {r3, r4, r5, r6, r7}
+ pop {r3}
+ mov lr, r3
+#else
+ .arm
+
+ sub sp, fp, #40
+ ldmfd sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr}
+#endif
+
+#if defined __THUMB_INTERWORK__ || defined __thumb__
+ bx lr
+#else
+ mov pc, lr
+#endif
+.endm
+
+
+ .section ".init"
+ ;;
+ FUNC_END
+
+ .section ".fini"
+ ;;
+ FUNC_END
+
+# end of crtn.S
diff --git a/gcc/config/arm/fp16.c b/libgcc/config/arm/fp16.c
index 936caeb78d0..936caeb78d0 100644
--- a/gcc/config/arm/fp16.c
+++ b/libgcc/config/arm/fp16.c
diff --git a/gcc/config/arm/ieee754-df.S b/libgcc/config/arm/ieee754-df.S
index eb0c38632d0..eb0c38632d0 100644
--- a/gcc/config/arm/ieee754-df.S
+++ b/libgcc/config/arm/ieee754-df.S
diff --git a/gcc/config/arm/ieee754-sf.S b/libgcc/config/arm/ieee754-sf.S
index c93f66d8ff8..c93f66d8ff8 100644
--- a/gcc/config/arm/ieee754-sf.S
+++ b/libgcc/config/arm/ieee754-sf.S
diff --git a/gcc/config/arm/lib1funcs.asm b/libgcc/config/arm/lib1funcs.S
index 2e76c01df4b..2e76c01df4b 100644
--- a/gcc/config/arm/lib1funcs.asm
+++ b/libgcc/config/arm/lib1funcs.S
diff --git a/gcc/config/arm/libgcc-bpabi.ver b/libgcc/config/arm/libgcc-bpabi.ver
index 3ba8364dc8e..3ba8364dc8e 100644
--- a/gcc/config/arm/libgcc-bpabi.ver
+++ b/libgcc/config/arm/libgcc-bpabi.ver
diff --git a/libgcc/config/arm/libunwind.S b/libgcc/config/arm/libunwind.S
index a3a19daab4b..8166cd86e47 100644
--- a/libgcc/config/arm/libunwind.S
+++ b/libgcc/config/arm/libunwind.S
@@ -40,7 +40,7 @@
#ifndef __symbian__
-#include "config/arm/lib1funcs.asm"
+#include "lib1funcs.S"
.macro UNPREFIX name
.global SYM (\name)
diff --git a/libgcc/config/arm/linux-atomic-64bit.c b/libgcc/config/arm/linux-atomic-64bit.c
new file mode 100644
index 00000000000..af94c7f4ae5
--- /dev/null
+++ b/libgcc/config/arm/linux-atomic-64bit.c
@@ -0,0 +1,166 @@
+/* 64bit Linux-specific atomic operations for ARM EABI.
+ Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+ Based on linux-atomic.c
+
+ 64 bit additions david.gilbert@linaro.org
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* 64bit helper functions for atomic operations; the compiler will
+ call these when the code is compiled for a CPU without ldrexd/strexd.
+ (If the CPU had those then the compiler inlines the operation).
+
+ These helpers require a kernel helper that's only present on newer
+ kernels; we check for that in an init section and bail out rather
+ unceremoneously. */
+
+extern unsigned int __write (int fd, const void *buf, unsigned int count);
+extern void abort (void);
+
+/* Kernel helper for compare-and-exchange. */
+typedef int (__kernel_cmpxchg64_t) (const long long* oldval,
+ const long long* newval,
+ long long *ptr);
+#define __kernel_cmpxchg64 (*(__kernel_cmpxchg64_t *) 0xffff0f60)
+
+/* Kernel helper page version number. */
+#define __kernel_helper_version (*(unsigned int *)0xffff0ffc)
+
+/* Check that the kernel has a new enough version at load. */
+static void __check_for_sync8_kernelhelper (void)
+{
+ if (__kernel_helper_version < 5)
+ {
+ const char err[] = "A newer kernel is required to run this binary. "
+ "(__kernel_cmpxchg64 helper)\n";
+ /* At this point we need a way to crash with some information
+ for the user - I'm not sure I can rely on much else being
+ available at this point, so do the same as generic-morestack.c
+ write () and abort (). */
+ __write (2 /* stderr. */, err, sizeof (err));
+ abort ();
+ }
+};
+
+static void (*__sync8_kernelhelper_inithook[]) (void)
+ __attribute__ ((used, section (".init_array"))) = {
+ &__check_for_sync8_kernelhelper
+};
+
+#define HIDDEN __attribute__ ((visibility ("hidden")))
+
+#define FETCH_AND_OP_WORD64(OP, PFX_OP, INF_OP) \
+ long long HIDDEN \
+ __sync_fetch_and_##OP##_8 (long long *ptr, long long val) \
+ { \
+ int failure; \
+ long long tmp,tmp2; \
+ \
+ do { \
+ tmp = *ptr; \
+ tmp2 = PFX_OP (tmp INF_OP val); \
+ failure = __kernel_cmpxchg64 (&tmp, &tmp2, ptr); \
+ } while (failure != 0); \
+ \
+ return tmp; \
+ }
+
+FETCH_AND_OP_WORD64 (add, , +)
+FETCH_AND_OP_WORD64 (sub, , -)
+FETCH_AND_OP_WORD64 (or, , |)
+FETCH_AND_OP_WORD64 (and, , &)
+FETCH_AND_OP_WORD64 (xor, , ^)
+FETCH_AND_OP_WORD64 (nand, ~, &)
+
+#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
+#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
+
+/* Implement both __sync_<op>_and_fetch and __sync_fetch_and_<op> for
+ subword-sized quantities. */
+
+#define OP_AND_FETCH_WORD64(OP, PFX_OP, INF_OP) \
+ long long HIDDEN \
+ __sync_##OP##_and_fetch_8 (long long *ptr, long long val) \
+ { \
+ int failure; \
+ long long tmp,tmp2; \
+ \
+ do { \
+ tmp = *ptr; \
+ tmp2 = PFX_OP (tmp INF_OP val); \
+ failure = __kernel_cmpxchg64 (&tmp, &tmp2, ptr); \
+ } while (failure != 0); \
+ \
+ return tmp2; \
+ }
+
+OP_AND_FETCH_WORD64 (add, , +)
+OP_AND_FETCH_WORD64 (sub, , -)
+OP_AND_FETCH_WORD64 (or, , |)
+OP_AND_FETCH_WORD64 (and, , &)
+OP_AND_FETCH_WORD64 (xor, , ^)
+OP_AND_FETCH_WORD64 (nand, ~, &)
+
+long long HIDDEN
+__sync_val_compare_and_swap_8 (long long *ptr, long long oldval,
+ long long newval)
+{
+ int failure;
+ long long actual_oldval;
+
+ while (1)
+ {
+ actual_oldval = *ptr;
+
+ if (__builtin_expect (oldval != actual_oldval, 0))
+ return actual_oldval;
+
+ failure = __kernel_cmpxchg64 (&actual_oldval, &newval, ptr);
+
+ if (__builtin_expect (!failure, 1))
+ return oldval;
+ }
+}
+
+typedef unsigned char bool;
+
+bool HIDDEN
+__sync_bool_compare_and_swap_8 (long long *ptr, long long oldval,
+ long long newval)
+{
+ int failure = __kernel_cmpxchg64 (&oldval, &newval, ptr);
+ return (failure == 0);
+}
+
+long long HIDDEN
+__sync_lock_test_and_set_8 (long long *ptr, long long val)
+{
+ int failure;
+ long long oldval;
+
+ do {
+ oldval = *ptr;
+ failure = __kernel_cmpxchg64 (&oldval, &val, ptr);
+ } while (failure != 0);
+
+ return oldval;
+}
diff --git a/libgcc/config/arm/linux-atomic.c b/libgcc/config/arm/linux-atomic.c
new file mode 100644
index 00000000000..80f161d06a7
--- /dev/null
+++ b/libgcc/config/arm/linux-atomic.c
@@ -0,0 +1,279 @@
+/* Linux-specific atomic operations for ARM EABI.
+ Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+ Contributed by CodeSourcery.
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Kernel helper for compare-and-exchange. */
+typedef int (__kernel_cmpxchg_t) (int oldval, int newval, int *ptr);
+#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)
+
+/* Kernel helper for memory barrier. */
+typedef void (__kernel_dmb_t) (void);
+#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0)
+
+/* Note: we implement byte, short and int versions of atomic operations using
+ the above kernel helpers; see linux-atomic-64bit.c for "long long" (64-bit)
+ operations. */
+
+#define HIDDEN __attribute__ ((visibility ("hidden")))
+
+#ifdef __ARMEL__
+#define INVERT_MASK_1 0
+#define INVERT_MASK_2 0
+#else
+#define INVERT_MASK_1 24
+#define INVERT_MASK_2 16
+#endif
+
+#define MASK_1 0xffu
+#define MASK_2 0xffffu
+
+#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP) \
+ int HIDDEN \
+ __sync_fetch_and_##OP##_4 (int *ptr, int val) \
+ { \
+ int failure, tmp; \
+ \
+ do { \
+ tmp = *ptr; \
+ failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \
+ } while (failure != 0); \
+ \
+ return tmp; \
+ }
+
+FETCH_AND_OP_WORD (add, , +)
+FETCH_AND_OP_WORD (sub, , -)
+FETCH_AND_OP_WORD (or, , |)
+FETCH_AND_OP_WORD (and, , &)
+FETCH_AND_OP_WORD (xor, , ^)
+FETCH_AND_OP_WORD (nand, ~, &)
+
+#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH
+#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH
+
+/* Implement both __sync_<op>_and_fetch and __sync_fetch_and_<op> for
+ subword-sized quantities. */
+
+#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN) \
+ TYPE HIDDEN \
+ NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val) \
+ { \
+ int *wordptr = (int *) ((unsigned int) ptr & ~3); \
+ unsigned int mask, shift, oldval, newval; \
+ int failure; \
+ \
+ shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
+ mask = MASK_##WIDTH << shift; \
+ \
+ do { \
+ oldval = *wordptr; \
+ newval = ((PFX_OP (((oldval & mask) >> shift) \
+ INF_OP (unsigned int) val)) << shift) & mask; \
+ newval |= oldval & ~mask; \
+ failure = __kernel_cmpxchg (oldval, newval, wordptr); \
+ } while (failure != 0); \
+ \
+ return (RETURN & mask) >> shift; \
+ }
+
+SUBWORD_SYNC_OP (add, , +, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (or, , |, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (and, , &, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, oldval)
+SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, oldval)
+
+SUBWORD_SYNC_OP (add, , +, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (or, , |, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (and, , &, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, oldval)
+SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, oldval)
+
+#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \
+ int HIDDEN \
+ __sync_##OP##_and_fetch_4 (int *ptr, int val) \
+ { \
+ int tmp, failure; \
+ \
+ do { \
+ tmp = *ptr; \
+ failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \
+ } while (failure != 0); \
+ \
+ return PFX_OP (tmp INF_OP val); \
+ }
+
+OP_AND_FETCH_WORD (add, , +)
+OP_AND_FETCH_WORD (sub, , -)
+OP_AND_FETCH_WORD (or, , |)
+OP_AND_FETCH_WORD (and, , &)
+OP_AND_FETCH_WORD (xor, , ^)
+OP_AND_FETCH_WORD (nand, ~, &)
+
+SUBWORD_SYNC_OP (add, , +, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (or, , |, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (and, , &, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, newval)
+SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, newval)
+
+SUBWORD_SYNC_OP (add, , +, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (or, , |, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (and, , &, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, newval)
+SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, newval)
+
+int HIDDEN
+__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval)
+{
+ int actual_oldval, fail;
+
+ while (1)
+ {
+ actual_oldval = *ptr;
+
+ if (__builtin_expect (oldval != actual_oldval, 0))
+ return actual_oldval;
+
+ fail = __kernel_cmpxchg (actual_oldval, newval, ptr);
+
+ if (__builtin_expect (!fail, 1))
+ return oldval;
+ }
+}
+
+#define SUBWORD_VAL_CAS(TYPE, WIDTH) \
+ TYPE HIDDEN \
+ __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \
+ TYPE newval) \
+ { \
+ int *wordptr = (int *)((unsigned int) ptr & ~3), fail; \
+ unsigned int mask, shift, actual_oldval, actual_newval; \
+ \
+ shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
+ mask = MASK_##WIDTH << shift; \
+ \
+ while (1) \
+ { \
+ actual_oldval = *wordptr; \
+ \
+ if (__builtin_expect (((actual_oldval & mask) >> shift) != \
+ (unsigned int) oldval, 0)) \
+ return (actual_oldval & mask) >> shift; \
+ \
+ actual_newval = (actual_oldval & ~mask) \
+ | (((unsigned int) newval << shift) & mask); \
+ \
+ fail = __kernel_cmpxchg (actual_oldval, actual_newval, \
+ wordptr); \
+ \
+ if (__builtin_expect (!fail, 1)) \
+ return oldval; \
+ } \
+ }
+
+SUBWORD_VAL_CAS (unsigned short, 2)
+SUBWORD_VAL_CAS (unsigned char, 1)
+
+typedef unsigned char bool;
+
+bool HIDDEN
+__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval)
+{
+ int failure = __kernel_cmpxchg (oldval, newval, ptr);
+ return (failure == 0);
+}
+
+#define SUBWORD_BOOL_CAS(TYPE, WIDTH) \
+ bool HIDDEN \
+ __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \
+ TYPE newval) \
+ { \
+ TYPE actual_oldval \
+ = __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval); \
+ return (oldval == actual_oldval); \
+ }
+
+SUBWORD_BOOL_CAS (unsigned short, 2)
+SUBWORD_BOOL_CAS (unsigned char, 1)
+
+void HIDDEN
+__sync_synchronize (void)
+{
+ __kernel_dmb ();
+}
+
+int HIDDEN
+__sync_lock_test_and_set_4 (int *ptr, int val)
+{
+ int failure, oldval;
+
+ do {
+ oldval = *ptr;
+ failure = __kernel_cmpxchg (oldval, val, ptr);
+ } while (failure != 0);
+
+ return oldval;
+}
+
+#define SUBWORD_TEST_AND_SET(TYPE, WIDTH) \
+ TYPE HIDDEN \
+ __sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val) \
+ { \
+ int failure; \
+ unsigned int oldval, newval, shift, mask; \
+ int *wordptr = (int *) ((unsigned int) ptr & ~3); \
+ \
+ shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \
+ mask = MASK_##WIDTH << shift; \
+ \
+ do { \
+ oldval = *wordptr; \
+ newval = (oldval & ~mask) \
+ | (((unsigned int) val << shift) & mask); \
+ failure = __kernel_cmpxchg (oldval, newval, wordptr); \
+ } while (failure != 0); \
+ \
+ return (oldval & mask) >> shift; \
+ }
+
+SUBWORD_TEST_AND_SET (unsigned short, 2)
+SUBWORD_TEST_AND_SET (unsigned char, 1)
+
+#define SYNC_LOCK_RELEASE(TYPE, WIDTH) \
+ void HIDDEN \
+ __sync_lock_release_##WIDTH (TYPE *ptr) \
+ { \
+ /* All writes before this point must be seen before we release \
+ the lock itself. */ \
+ __kernel_dmb (); \
+ *ptr = 0; \
+ }
+
+SYNC_LOCK_RELEASE (long long, 8)
+SYNC_LOCK_RELEASE (int, 4)
+SYNC_LOCK_RELEASE (short, 2)
+SYNC_LOCK_RELEASE (char, 1)
diff --git a/libgcc/config/arm/t-arm b/libgcc/config/arm/t-arm
new file mode 100644
index 00000000000..4e17e99b4a5
--- /dev/null
+++ b/libgcc/config/arm/t-arm
@@ -0,0 +1,3 @@
+LIB1ASMSRC = arm/lib1funcs.S
+LIB1ASMFUNCS = _thumb1_case_sqi _thumb1_case_uqi _thumb1_case_shi \
+ _thumb1_case_uhi _thumb1_case_si
diff --git a/libgcc/config/arm/t-bpabi b/libgcc/config/arm/t-bpabi
index a3b23dcd20c..e79cbd7064e 100644
--- a/libgcc/config/arm/t-bpabi
+++ b/libgcc/config/arm/t-bpabi
@@ -1,3 +1,15 @@
+# Add the bpabi.S functions.
+LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
+
+# Add the BPABI C functions.
+LIB2ADD += $(srcdir)/config/arm/bpabi.c \
+ $(srcdir)/config/arm/unaligned-funcs.c
+
+LIB2ADD_ST += $(srcdir)/config/arm/fp16.c
+
LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
$(srcdir)/config/arm/libunwind.S \
$(srcdir)/config/arm/pr-support.c $(srcdir)/unwind-c.c
+
+# Add the BPABI names.
+SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
diff --git a/libgcc/config/arm/t-elf b/libgcc/config/arm/t-elf
new file mode 100644
index 00000000000..414484eb9ca
--- /dev/null
+++ b/libgcc/config/arm/t-elf
@@ -0,0 +1,18 @@
+# For most CPUs we have an assembly soft-float implementations.
+# However this is not true for ARMv6M. Here we want to use the soft-fp C
+# implementation. The soft-fp code is only build for ARMv6M. This pulls
+# in the asm implementation for other CPUs.
+LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
+ _call_via_rX _interwork_call_via_rX \
+ _lshrdi3 _ashrdi3 _ashldi3 \
+ _arm_negdf2 _arm_addsubdf3 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
+ _arm_fixdfsi _arm_fixunsdfsi \
+ _arm_truncdfsf2 _arm_negsf2 _arm_addsubsf3 _arm_muldivsf3 \
+ _arm_cmpsf2 _arm_unordsf2 _arm_fixsfsi _arm_fixunssfsi \
+ _arm_floatdidf _arm_floatdisf _arm_floatundidf _arm_floatundisf \
+ _clzsi2 _clzdi2
+
+# Currently there is a bug somewhere in GCC's alias analysis
+# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
+# Disabling function inlining is a workaround for this problem.
+HOST_LIBGCC2_CFLAGS = -fno-inline
diff --git a/libgcc/config/arm/t-linux b/libgcc/config/arm/t-linux
new file mode 100644
index 00000000000..4c1efebbd87
--- /dev/null
+++ b/libgcc/config/arm/t-linux
@@ -0,0 +1,7 @@
+LIB1ASMSRC = arm/lib1funcs.S
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \
+ _arm_addsubdf3 _arm_addsubsf3
+
+# Just for these, we omit the frame pointer since it makes such a big
+# difference.
+HOST_LIBGCC2_CFLAGS += -fomit-frame-pointer
diff --git a/libgcc/config/arm/t-linux-eabi b/libgcc/config/arm/t-linux-eabi
new file mode 100644
index 00000000000..a03e2b60064
--- /dev/null
+++ b/libgcc/config/arm/t-linux-eabi
@@ -0,0 +1,5 @@
+# Use a version of div0 which raises SIGFPE, and a special __clear_cache.
+LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx _clear_cache
+
+LIB2ADD_ST += $(srcdir)/config/arm/linux-atomic.c \
+ $(srcdir)/config/arm/linux-atomic-64bit.c
diff --git a/libgcc/config/arm/t-netbsd b/libgcc/config/arm/t-netbsd
new file mode 100644
index 00000000000..95358f931ba
--- /dev/null
+++ b/libgcc/config/arm/t-netbsd
@@ -0,0 +1,7 @@
+# Just for these, we omit the frame pointer since it makes such a big
+# difference. It is then pointless adding debugging.
+HOST_LIBGCC2_CFLAGS += -fomit-frame-pointer
+
+LIBGCC2_DEBUG_CFLAGS = -g0
+
+LIB2ADD += $(srcdir)/floatunsidf.c $(srcdir)/floatunsisf.c
diff --git a/libgcc/config/arm/t-strongarm-elf b/libgcc/config/arm/t-strongarm-elf
new file mode 100644
index 00000000000..369a8393738
--- /dev/null
+++ b/libgcc/config/arm/t-strongarm-elf
@@ -0,0 +1,6 @@
+LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _clzsi2 _clzdi2
+
+# Currently there is a bug somewhere in GCC's alias analysis
+# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
+# Disabling function inlining is a workaround for this problem.
+HOST_LIBGCC2_CFLAGS = -fno-inline
diff --git a/libgcc/config/arm/t-symbian b/libgcc/config/arm/t-symbian
index 6788d5f40b3..06d98faa6ae 100644
--- a/libgcc/config/arm/t-symbian
+++ b/libgcc/config/arm/t-symbian
@@ -1,2 +1,19 @@
+LIB1ASMFUNCS += _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
+
+# These functions have __aeabi equivalents and will never be called by GCC.
+# By putting them in LIB1ASMFUNCS, we avoid the standard libgcc2.c code being
+# used -- and we make sure that definitions are not available in lib1funcs.S,
+# either, so they end up undefined.
+LIB1ASMFUNCS += \
+ _ashldi3 _ashrdi3 _divdi3 _floatdidf _udivmoddi4 _umoddi3 \
+ _udivdi3 _lshrdi3 _moddi3 _muldi3 _negdi2 _cmpdi2 \
+ _fixdfdi _fixsfdi _fixunsdfdi _fixunssfdi _floatdisf \
+ _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
+ _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
+ _fixsfsi _fixunssfsi
+
+# Include half-float helpers.
+LIB2ADD_ST += $(srcdir)/config/arm/fp16.c
+
# Include the gcc personality routine
LIB2ADDEH = $(srcdir)/unwind-c.c $(srcdir)/config/arm/pr-support.c
diff --git a/libgcc/config/arm/t-vxworks b/libgcc/config/arm/t-vxworks
new file mode 100644
index 00000000000..70ccdc1556a
--- /dev/null
+++ b/libgcc/config/arm/t-vxworks
@@ -0,0 +1 @@
+LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
diff --git a/libgcc/config/arm/t-wince-pe b/libgcc/config/arm/t-wince-pe
new file mode 100644
index 00000000000..33ea969ccf4
--- /dev/null
+++ b/libgcc/config/arm/t-wince-pe
@@ -0,0 +1 @@
+LIB1ASMFUNCS += _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _call_via_rX _interwork_call_via_rX _clzsi2 _clzdi2
diff --git a/gcc/config/arm/unaligned-funcs.c b/libgcc/config/arm/unaligned-funcs.c
index 4e684f4fc94..4e684f4fc94 100644
--- a/gcc/config/arm/unaligned-funcs.c
+++ b/libgcc/config/arm/unaligned-funcs.c
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
new file mode 100644
index 00000000000..8c369c96a77
--- /dev/null
+++ b/libgcc/config/avr/lib1funcs.S
@@ -0,0 +1,1533 @@
+/* -*- Mode: Asm -*- */
+/* Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009
+ Free Software Foundation, Inc.
+ Contributed by Denis Chertykov <chertykov@gmail.com>
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#define __zero_reg__ r1
+#define __tmp_reg__ r0
+#define __SREG__ 0x3f
+#define __SP_H__ 0x3e
+#define __SP_L__ 0x3d
+#define __RAMPZ__ 0x3B
+#define __EIND__ 0x3C
+
+/* Most of the functions here are called directly from avr.md
+ patterns, instead of using the standard libcall mechanisms.
+ This can make better code because GCC knows exactly which
+ of the call-used registers (not all of them) are clobbered. */
+
+/* FIXME: At present, there is no SORT directive in the linker
+ script so that we must not assume that different modules
+ in the same input section like .libgcc.text.mul will be
+ located close together. Therefore, we cannot use
+ RCALL/RJMP to call a function like __udivmodhi4 from
+ __divmodhi4 and have to use lengthy XCALL/XJMP even
+ though they are in the same input section and all same
+ input sections together are small enough to reach every
+ location with a RCALL/RJMP instruction. */
+
+ .macro mov_l r_dest, r_src
+#if defined (__AVR_HAVE_MOVW__)
+ movw \r_dest, \r_src
+#else
+ mov \r_dest, \r_src
+#endif
+ .endm
+
+ .macro mov_h r_dest, r_src
+#if defined (__AVR_HAVE_MOVW__)
+ ; empty
+#else
+ mov \r_dest, \r_src
+#endif
+ .endm
+
+#if defined (__AVR_HAVE_JMP_CALL__)
+#define XCALL call
+#define XJMP jmp
+#else
+#define XCALL rcall
+#define XJMP rjmp
+#endif
+
+.macro DEFUN name
+.global \name
+.func \name
+\name:
+.endm
+
+.macro ENDF name
+.size \name, .-\name
+.endfunc
+.endm
+
+
+.section .text.libgcc.mul, "ax", @progbits
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+/* Note: mulqi3, mulhi3 are open-coded on the enhanced core. */
+#if !defined (__AVR_HAVE_MUL__)
+/*******************************************************
+ Multiplication 8 x 8 without MUL
+*******************************************************/
+#if defined (L_mulqi3)
+
+#define r_arg2 r22 /* multiplicand */
+#define r_arg1 r24 /* multiplier */
+#define r_res __tmp_reg__ /* result */
+
+DEFUN __mulqi3
+ clr r_res ; clear result
+__mulqi3_loop:
+ sbrc r_arg1,0
+ add r_res,r_arg2
+ add r_arg2,r_arg2 ; shift multiplicand
+ breq __mulqi3_exit ; while multiplicand != 0
+ lsr r_arg1 ;
+ brne __mulqi3_loop ; exit if multiplier = 0
+__mulqi3_exit:
+ mov r_arg1,r_res ; result to return register
+ ret
+ENDF __mulqi3
+
+#undef r_arg2
+#undef r_arg1
+#undef r_res
+
+#endif /* defined (L_mulqi3) */
+
+#if defined (L_mulqihi3)
+DEFUN __mulqihi3
+ clr r25
+ sbrc r24, 7
+ dec r25
+ clr r23
+ sbrc r22, 7
+ dec r22
+ XJMP __mulhi3
+ENDF __mulqihi3:
+#endif /* defined (L_mulqihi3) */
+
+#if defined (L_umulqihi3)
+DEFUN __umulqihi3
+ clr r25
+ clr r23
+ XJMP __mulhi3
+ENDF __umulqihi3
+#endif /* defined (L_umulqihi3) */
+
+/*******************************************************
+ Multiplication 16 x 16 without MUL
+*******************************************************/
+#if defined (L_mulhi3)
+#define r_arg1L r24 /* multiplier Low */
+#define r_arg1H r25 /* multiplier High */
+#define r_arg2L r22 /* multiplicand Low */
+#define r_arg2H r23 /* multiplicand High */
+#define r_resL __tmp_reg__ /* result Low */
+#define r_resH r21 /* result High */
+
+DEFUN __mulhi3
+ clr r_resH ; clear result
+ clr r_resL ; clear result
+__mulhi3_loop:
+ sbrs r_arg1L,0
+ rjmp __mulhi3_skip1
+ add r_resL,r_arg2L ; result + multiplicand
+ adc r_resH,r_arg2H
+__mulhi3_skip1:
+ add r_arg2L,r_arg2L ; shift multiplicand
+ adc r_arg2H,r_arg2H
+
+ cp r_arg2L,__zero_reg__
+ cpc r_arg2H,__zero_reg__
+ breq __mulhi3_exit ; while multiplicand != 0
+
+ lsr r_arg1H ; gets LSB of multiplier
+ ror r_arg1L
+ sbiw r_arg1L,0
+ brne __mulhi3_loop ; exit if multiplier = 0
+__mulhi3_exit:
+ mov r_arg1H,r_resH ; result to return register
+ mov r_arg1L,r_resL
+ ret
+ENDF __mulhi3
+
+#undef r_arg1L
+#undef r_arg1H
+#undef r_arg2L
+#undef r_arg2H
+#undef r_resL
+#undef r_resH
+
+#endif /* defined (L_mulhi3) */
+
+/*******************************************************
+ Widening Multiplication 32 = 16 x 16 without MUL
+*******************************************************/
+
+#if defined (L_mulhisi3)
+DEFUN __mulhisi3
+;;; FIXME: This is dead code (noone calls it)
+ mov_l r18, r24
+ mov_h r19, r25
+ clr r24
+ sbrc r23, 7
+ dec r24
+ mov r25, r24
+ clr r20
+ sbrc r19, 7
+ dec r20
+ mov r21, r20
+ XJMP __mulsi3
+ENDF __mulhisi3
+#endif /* defined (L_mulhisi3) */
+
+#if defined (L_umulhisi3)
+DEFUN __umulhisi3
+;;; FIXME: This is dead code (noone calls it)
+ mov_l r18, r24
+ mov_h r19, r25
+ clr r24
+ clr r25
+ mov_l r20, r24
+ mov_h r21, r25
+ XJMP __mulsi3
+ENDF __umulhisi3
+#endif /* defined (L_umulhisi3) */
+
+#if defined (L_mulsi3)
+/*******************************************************
+ Multiplication 32 x 32 without MUL
+*******************************************************/
+#define r_arg1L r22 /* multiplier Low */
+#define r_arg1H r23
+#define r_arg1HL r24
+#define r_arg1HH r25 /* multiplier High */
+
+#define r_arg2L r18 /* multiplicand Low */
+#define r_arg2H r19
+#define r_arg2HL r20
+#define r_arg2HH r21 /* multiplicand High */
+
+#define r_resL r26 /* result Low */
+#define r_resH r27
+#define r_resHL r30
+#define r_resHH r31 /* result High */
+
+DEFUN __mulsi3
+ clr r_resHH ; clear result
+ clr r_resHL ; clear result
+ clr r_resH ; clear result
+ clr r_resL ; clear result
+__mulsi3_loop:
+ sbrs r_arg1L,0
+ rjmp __mulsi3_skip1
+ add r_resL,r_arg2L ; result + multiplicand
+ adc r_resH,r_arg2H
+ adc r_resHL,r_arg2HL
+ adc r_resHH,r_arg2HH
+__mulsi3_skip1:
+ add r_arg2L,r_arg2L ; shift multiplicand
+ adc r_arg2H,r_arg2H
+ adc r_arg2HL,r_arg2HL
+ adc r_arg2HH,r_arg2HH
+
+ lsr r_arg1HH ; gets LSB of multiplier
+ ror r_arg1HL
+ ror r_arg1H
+ ror r_arg1L
+ brne __mulsi3_loop
+ sbiw r_arg1HL,0
+ cpc r_arg1H,r_arg1L
+ brne __mulsi3_loop ; exit if multiplier = 0
+__mulsi3_exit:
+ mov_h r_arg1HH,r_resHH ; result to return register
+ mov_l r_arg1HL,r_resHL
+ mov_h r_arg1H,r_resH
+ mov_l r_arg1L,r_resL
+ ret
+ENDF __mulsi3
+
+#undef r_arg1L
+#undef r_arg1H
+#undef r_arg1HL
+#undef r_arg1HH
+
+#undef r_arg2L
+#undef r_arg2H
+#undef r_arg2HL
+#undef r_arg2HH
+
+#undef r_resL
+#undef r_resH
+#undef r_resHL
+#undef r_resHH
+
+#endif /* defined (L_mulsi3) */
+
+#endif /* !defined (__AVR_HAVE_MUL__) */
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#if defined (__AVR_HAVE_MUL__)
+#define A0 26
+#define B0 18
+#define C0 22
+
+#define A1 A0+1
+
+#define B1 B0+1
+#define B2 B0+2
+#define B3 B0+3
+
+#define C1 C0+1
+#define C2 C0+2
+#define C3 C0+3
+
+/*******************************************************
+ Widening Multiplication 32 = 16 x 16
+*******************************************************/
+
+#if defined (L_mulhisi3)
+;;; R25:R22 = (signed long) R27:R26 * (signed long) R19:R18
+;;; C3:C0 = (signed long) A1:A0 * (signed long) B1:B0
+;;; Clobbers: __tmp_reg__
+DEFUN __mulhisi3
+ XCALL __umulhisi3
+ ;; Sign-extend B
+ tst B1
+ brpl 1f
+ sub C2, A0
+ sbc C3, A1
+1: ;; Sign-extend A
+ XJMP __usmulhisi3_tail
+ENDF __mulhisi3
+#endif /* L_mulhisi3 */
+
+#if defined (L_usmulhisi3)
+;;; R25:R22 = (signed long) R27:R26 * (unsigned long) R19:R18
+;;; C3:C0 = (signed long) A1:A0 * (unsigned long) B1:B0
+;;; Clobbers: __tmp_reg__
+DEFUN __usmulhisi3
+ XCALL __umulhisi3
+ ;; FALLTHRU
+ENDF __usmulhisi3
+
+DEFUN __usmulhisi3_tail
+ ;; Sign-extend A
+ sbrs A1, 7
+ ret
+ sub C2, B0
+ sbc C3, B1
+ ret
+ENDF __usmulhisi3_tail
+#endif /* L_usmulhisi3 */
+
+#if defined (L_umulhisi3)
+;;; R25:R22 = (unsigned long) R27:R26 * (unsigned long) R19:R18
+;;; C3:C0 = (unsigned long) A1:A0 * (unsigned long) B1:B0
+;;; Clobbers: __tmp_reg__
+DEFUN __umulhisi3
+ mul A0, B0
+ movw C0, r0
+ mul A1, B1
+ movw C2, r0
+ mul A0, B1
+ rcall 1f
+ mul A1, B0
+1: add C1, r0
+ adc C2, r1
+ clr __zero_reg__
+ adc C3, __zero_reg__
+ ret
+ENDF __umulhisi3
+#endif /* L_umulhisi3 */
+
+/*******************************************************
+ Widening Multiplication 32 = 16 x 32
+*******************************************************/
+
+#if defined (L_mulshisi3)
+;;; R25:R22 = (signed long) R27:R26 * R21:R18
+;;; (C3:C0) = (signed long) A1:A0 * B3:B0
+;;; Clobbers: __tmp_reg__
+DEFUN __mulshisi3
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ ;; Some cores have problem skipping 2-word instruction
+ tst A1
+ brmi __mulohisi3
+#else
+ sbrs A1, 7
+#endif /* __AVR_HAVE_JMP_CALL__ */
+ XJMP __muluhisi3
+ ;; FALLTHRU
+ENDF __mulshisi3
+
+;;; R25:R22 = (one-extended long) R27:R26 * R21:R18
+;;; (C3:C0) = (one-extended long) A1:A0 * B3:B0
+;;; Clobbers: __tmp_reg__
+DEFUN __mulohisi3
+ XCALL __muluhisi3
+ ;; One-extend R27:R26 (A1:A0)
+ sub C2, B0
+ sbc C3, B1
+ ret
+ENDF __mulohisi3
+#endif /* L_mulshisi3 */
+
+#if defined (L_muluhisi3)
+;;; R25:R22 = (unsigned long) R27:R26 * R21:R18
+;;; (C3:C0) = (unsigned long) A1:A0 * B3:B0
+;;; Clobbers: __tmp_reg__
+DEFUN __muluhisi3
+ XCALL __umulhisi3
+ mul A0, B3
+ add C3, r0
+ mul A1, B2
+ add C3, r0
+ mul A0, B2
+ add C2, r0
+ adc C3, r1
+ clr __zero_reg__
+ ret
+ENDF __muluhisi3
+#endif /* L_muluhisi3 */
+
+/*******************************************************
+ Multiplication 32 x 32
+*******************************************************/
+
+#if defined (L_mulsi3)
+;;; R25:R22 = R25:R22 * R21:R18
+;;; (C3:C0) = C3:C0 * B3:B0
+;;; Clobbers: R26, R27, __tmp_reg__
+DEFUN __mulsi3
+ movw A0, C0
+ push C2
+ push C3
+ XCALL __muluhisi3
+ pop A1
+ pop A0
+ ;; A1:A0 now contains the high word of A
+ mul A0, B0
+ add C2, r0
+ adc C3, r1
+ mul A0, B1
+ add C3, r0
+ mul A1, B0
+ add C3, r0
+ clr __zero_reg__
+ ret
+ENDF __mulsi3
+#endif /* L_mulsi3 */
+
+#undef A0
+#undef A1
+
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+
+#endif /* __AVR_HAVE_MUL__ */
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+.section .text.libgcc.div, "ax", @progbits
+
+/*******************************************************
+ Division 8 / 8 => (result + remainder)
+*******************************************************/
+#define r_rem r25 /* remainder */
+#define r_arg1 r24 /* dividend, quotient */
+#define r_arg2 r22 /* divisor */
+#define r_cnt r23 /* loop count */
+
+#if defined (L_udivmodqi4)
+DEFUN __udivmodqi4
+ sub r_rem,r_rem ; clear remainder and carry
+ ldi r_cnt,9 ; init loop counter
+ rjmp __udivmodqi4_ep ; jump to entry point
+__udivmodqi4_loop:
+ rol r_rem ; shift dividend into remainder
+ cp r_rem,r_arg2 ; compare remainder & divisor
+ brcs __udivmodqi4_ep ; remainder <= divisor
+ sub r_rem,r_arg2 ; restore remainder
+__udivmodqi4_ep:
+ rol r_arg1 ; shift dividend (with CARRY)
+ dec r_cnt ; decrement loop counter
+ brne __udivmodqi4_loop
+ com r_arg1 ; complement result
+ ; because C flag was complemented in loop
+ ret
+ENDF __udivmodqi4
+#endif /* defined (L_udivmodqi4) */
+
+#if defined (L_divmodqi4)
+DEFUN __divmodqi4
+ bst r_arg1,7 ; store sign of dividend
+ mov __tmp_reg__,r_arg1
+ eor __tmp_reg__,r_arg2; r0.7 is sign of result
+ sbrc r_arg1,7
+ neg r_arg1 ; dividend negative : negate
+ sbrc r_arg2,7
+ neg r_arg2 ; divisor negative : negate
+ XCALL __udivmodqi4 ; do the unsigned div/mod
+ brtc __divmodqi4_1
+ neg r_rem ; correct remainder sign
+__divmodqi4_1:
+ sbrc __tmp_reg__,7
+ neg r_arg1 ; correct result sign
+__divmodqi4_exit:
+ ret
+ENDF __divmodqi4
+#endif /* defined (L_divmodqi4) */
+
+#undef r_rem
+#undef r_arg1
+#undef r_arg2
+#undef r_cnt
+
+
+/*******************************************************
+ Division 16 / 16 => (result + remainder)
+*******************************************************/
+#define r_remL r26 /* remainder Low */
+#define r_remH r27 /* remainder High */
+
+/* return: remainder */
+#define r_arg1L r24 /* dividend Low */
+#define r_arg1H r25 /* dividend High */
+
+/* return: quotient */
+#define r_arg2L r22 /* divisor Low */
+#define r_arg2H r23 /* divisor High */
+
+#define r_cnt r21 /* loop count */
+
+#if defined (L_udivmodhi4)
+DEFUN __udivmodhi4
+ sub r_remL,r_remL
+ sub r_remH,r_remH ; clear remainder and carry
+ ldi r_cnt,17 ; init loop counter
+ rjmp __udivmodhi4_ep ; jump to entry point
+__udivmodhi4_loop:
+ rol r_remL ; shift dividend into remainder
+ rol r_remH
+ cp r_remL,r_arg2L ; compare remainder & divisor
+ cpc r_remH,r_arg2H
+ brcs __udivmodhi4_ep ; remainder < divisor
+ sub r_remL,r_arg2L ; restore remainder
+ sbc r_remH,r_arg2H
+__udivmodhi4_ep:
+ rol r_arg1L ; shift dividend (with CARRY)
+ rol r_arg1H
+ dec r_cnt ; decrement loop counter
+ brne __udivmodhi4_loop
+ com r_arg1L
+ com r_arg1H
+; div/mod results to return registers, as for the div() function
+ mov_l r_arg2L, r_arg1L ; quotient
+ mov_h r_arg2H, r_arg1H
+ mov_l r_arg1L, r_remL ; remainder
+ mov_h r_arg1H, r_remH
+ ret
+ENDF __udivmodhi4
+#endif /* defined (L_udivmodhi4) */
+
+#if defined (L_divmodhi4)
+DEFUN __divmodhi4
+ .global _div
+_div:
+ bst r_arg1H,7 ; store sign of dividend
+ mov __tmp_reg__,r_arg1H
+ eor __tmp_reg__,r_arg2H ; r0.7 is sign of result
+ rcall __divmodhi4_neg1 ; dividend negative : negate
+ sbrc r_arg2H,7
+ rcall __divmodhi4_neg2 ; divisor negative : negate
+ XCALL __udivmodhi4 ; do the unsigned div/mod
+ rcall __divmodhi4_neg1 ; correct remainder sign
+ tst __tmp_reg__
+ brpl __divmodhi4_exit
+__divmodhi4_neg2:
+ com r_arg2H
+ neg r_arg2L ; correct divisor/result sign
+ sbci r_arg2H,0xff
+__divmodhi4_exit:
+ ret
+__divmodhi4_neg1:
+ brtc __divmodhi4_exit
+ com r_arg1H
+ neg r_arg1L ; correct dividend/remainder sign
+ sbci r_arg1H,0xff
+ ret
+ENDF __divmodhi4
+#endif /* defined (L_divmodhi4) */
+
+#undef r_remH
+#undef r_remL
+
+#undef r_arg1H
+#undef r_arg1L
+
+#undef r_arg2H
+#undef r_arg2L
+
+#undef r_cnt
+
+/*******************************************************
+ Division 32 / 32 => (result + remainder)
+*******************************************************/
+#define r_remHH r31 /* remainder High */
+#define r_remHL r30
+#define r_remH r27
+#define r_remL r26 /* remainder Low */
+
+/* return: remainder */
+#define r_arg1HH r25 /* dividend High */
+#define r_arg1HL r24
+#define r_arg1H r23
+#define r_arg1L r22 /* dividend Low */
+
+/* return: quotient */
+#define r_arg2HH r21 /* divisor High */
+#define r_arg2HL r20
+#define r_arg2H r19
+#define r_arg2L r18 /* divisor Low */
+
+#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
+
+#if defined (L_udivmodsi4)
+DEFUN __udivmodsi4
+ ldi r_remL, 33 ; init loop counter
+ mov r_cnt, r_remL
+ sub r_remL,r_remL
+ sub r_remH,r_remH ; clear remainder and carry
+ mov_l r_remHL, r_remL
+ mov_h r_remHH, r_remH
+ rjmp __udivmodsi4_ep ; jump to entry point
+__udivmodsi4_loop:
+ rol r_remL ; shift dividend into remainder
+ rol r_remH
+ rol r_remHL
+ rol r_remHH
+ cp r_remL,r_arg2L ; compare remainder & divisor
+ cpc r_remH,r_arg2H
+ cpc r_remHL,r_arg2HL
+ cpc r_remHH,r_arg2HH
+ brcs __udivmodsi4_ep ; remainder <= divisor
+ sub r_remL,r_arg2L ; restore remainder
+ sbc r_remH,r_arg2H
+ sbc r_remHL,r_arg2HL
+ sbc r_remHH,r_arg2HH
+__udivmodsi4_ep:
+ rol r_arg1L ; shift dividend (with CARRY)
+ rol r_arg1H
+ rol r_arg1HL
+ rol r_arg1HH
+ dec r_cnt ; decrement loop counter
+ brne __udivmodsi4_loop
+ ; __zero_reg__ now restored (r_cnt == 0)
+ com r_arg1L
+ com r_arg1H
+ com r_arg1HL
+ com r_arg1HH
+; div/mod results to return registers, as for the ldiv() function
+ mov_l r_arg2L, r_arg1L ; quotient
+ mov_h r_arg2H, r_arg1H
+ mov_l r_arg2HL, r_arg1HL
+ mov_h r_arg2HH, r_arg1HH
+ mov_l r_arg1L, r_remL ; remainder
+ mov_h r_arg1H, r_remH
+ mov_l r_arg1HL, r_remHL
+ mov_h r_arg1HH, r_remHH
+ ret
+ENDF __udivmodsi4
+#endif /* defined (L_udivmodsi4) */
+
+#if defined (L_divmodsi4)
+DEFUN __divmodsi4
+ bst r_arg1HH,7 ; store sign of dividend
+ mov __tmp_reg__,r_arg1HH
+ eor __tmp_reg__,r_arg2HH ; r0.7 is sign of result
+ rcall __divmodsi4_neg1 ; dividend negative : negate
+ sbrc r_arg2HH,7
+ rcall __divmodsi4_neg2 ; divisor negative : negate
+ XCALL __udivmodsi4 ; do the unsigned div/mod
+ rcall __divmodsi4_neg1 ; correct remainder sign
+ rol __tmp_reg__
+ brcc __divmodsi4_exit
+__divmodsi4_neg2:
+ com r_arg2HH
+ com r_arg2HL
+ com r_arg2H
+ neg r_arg2L ; correct divisor/quotient sign
+ sbci r_arg2H,0xff
+ sbci r_arg2HL,0xff
+ sbci r_arg2HH,0xff
+__divmodsi4_exit:
+ ret
+__divmodsi4_neg1:
+ brtc __divmodsi4_exit
+ com r_arg1HH
+ com r_arg1HL
+ com r_arg1H
+ neg r_arg1L ; correct dividend/remainder sign
+ sbci r_arg1H, 0xff
+ sbci r_arg1HL,0xff
+ sbci r_arg1HH,0xff
+ ret
+ENDF __divmodsi4
+#endif /* defined (L_divmodsi4) */
+
+
+.section .text.libgcc.prologue, "ax", @progbits
+
+/**********************************
+ * This is a prologue subroutine
+ **********************************/
+#if defined (L_prologue)
+
+DEFUN __prologue_saves__
+ push r2
+ push r3
+ push r4
+ push r5
+ push r6
+ push r7
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+ push r16
+ push r17
+ push r28
+ push r29
+ in r28,__SP_L__
+ in r29,__SP_H__
+ sub r28,r26
+ sbc r29,r27
+ in __tmp_reg__,__SREG__
+ cli
+ out __SP_H__,r29
+ out __SREG__,__tmp_reg__
+ out __SP_L__,r28
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+ eijmp
+#else
+ ijmp
+#endif
+
+ENDF __prologue_saves__
+#endif /* defined (L_prologue) */
+
+/*
+ * This is an epilogue subroutine
+ */
+#if defined (L_epilogue)
+
+DEFUN __epilogue_restores__
+ ldd r2,Y+18
+ ldd r3,Y+17
+ ldd r4,Y+16
+ ldd r5,Y+15
+ ldd r6,Y+14
+ ldd r7,Y+13
+ ldd r8,Y+12
+ ldd r9,Y+11
+ ldd r10,Y+10
+ ldd r11,Y+9
+ ldd r12,Y+8
+ ldd r13,Y+7
+ ldd r14,Y+6
+ ldd r15,Y+5
+ ldd r16,Y+4
+ ldd r17,Y+3
+ ldd r26,Y+2
+ ldd r27,Y+1
+ add r28,r30
+ adc r29,__zero_reg__
+ in __tmp_reg__,__SREG__
+ cli
+ out __SP_H__,r29
+ out __SREG__,__tmp_reg__
+ out __SP_L__,r28
+ mov_l r28, r26
+ mov_h r29, r27
+ ret
+ENDF __epilogue_restores__
+#endif /* defined (L_epilogue) */
+
+#ifdef L_exit
+ .section .fini9,"ax",@progbits
+DEFUN _exit
+ .weak exit
+exit:
+ENDF _exit
+
+ /* Code from .fini8 ... .fini1 sections inserted by ld script. */
+
+ .section .fini0,"ax",@progbits
+ cli
+__stop_program:
+ rjmp __stop_program
+#endif /* defined (L_exit) */
+
+#ifdef L_cleanup
+ .weak _cleanup
+ .func _cleanup
+_cleanup:
+ ret
+.endfunc
+#endif /* defined (L_cleanup) */
+
+
+.section .text.libgcc, "ax", @progbits
+
+#ifdef L_tablejump
+DEFUN __tablejump2__
+ lsl r30
+ rol r31
+ ;; FALLTHRU
+ENDF __tablejump2__
+
+DEFUN __tablejump__
+#if defined (__AVR_HAVE_LPMX__)
+ lpm __tmp_reg__, Z+
+ lpm r31, Z
+ mov r30, __tmp_reg__
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+ eijmp
+#else
+ ijmp
+#endif
+
+#else /* !HAVE_LPMX */
+ lpm
+ adiw r30, 1
+ push r0
+ lpm
+ push r0
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+ in __tmp_reg__, __EIND__
+ push __tmp_reg__
+#endif
+ ret
+#endif /* !HAVE_LPMX */
+ENDF __tablejump__
+#endif /* defined (L_tablejump) */
+
+#ifdef L_copy_data
+ .section .init4,"ax",@progbits
+DEFUN __do_copy_data
+#if defined(__AVR_HAVE_ELPMX__)
+ ldi r17, hi8(__data_end)
+ ldi r26, lo8(__data_start)
+ ldi r27, hi8(__data_start)
+ ldi r30, lo8(__data_load_start)
+ ldi r31, hi8(__data_load_start)
+ ldi r16, hh8(__data_load_start)
+ out __RAMPZ__, r16
+ rjmp .L__do_copy_data_start
+.L__do_copy_data_loop:
+ elpm r0, Z+
+ st X+, r0
+.L__do_copy_data_start:
+ cpi r26, lo8(__data_end)
+ cpc r27, r17
+ brne .L__do_copy_data_loop
+#elif !defined(__AVR_HAVE_ELPMX__) && defined(__AVR_HAVE_ELPM__)
+ ldi r17, hi8(__data_end)
+ ldi r26, lo8(__data_start)
+ ldi r27, hi8(__data_start)
+ ldi r30, lo8(__data_load_start)
+ ldi r31, hi8(__data_load_start)
+ ldi r16, hh8(__data_load_start - 0x10000)
+.L__do_copy_data_carry:
+ inc r16
+ out __RAMPZ__, r16
+ rjmp .L__do_copy_data_start
+.L__do_copy_data_loop:
+ elpm
+ st X+, r0
+ adiw r30, 1
+ brcs .L__do_copy_data_carry
+.L__do_copy_data_start:
+ cpi r26, lo8(__data_end)
+ cpc r27, r17
+ brne .L__do_copy_data_loop
+#elif !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__)
+ ldi r17, hi8(__data_end)
+ ldi r26, lo8(__data_start)
+ ldi r27, hi8(__data_start)
+ ldi r30, lo8(__data_load_start)
+ ldi r31, hi8(__data_load_start)
+ rjmp .L__do_copy_data_start
+.L__do_copy_data_loop:
+#if defined (__AVR_HAVE_LPMX__)
+ lpm r0, Z+
+#else
+ lpm
+ adiw r30, 1
+#endif
+ st X+, r0
+.L__do_copy_data_start:
+ cpi r26, lo8(__data_end)
+ cpc r27, r17
+ brne .L__do_copy_data_loop
+#endif /* !defined(__AVR_HAVE_ELPMX__) && !defined(__AVR_HAVE_ELPM__) */
+ENDF __do_copy_data
+#endif /* L_copy_data */
+
+/* __do_clear_bss is only necessary if there is anything in .bss section. */
+
+#ifdef L_clear_bss
+ .section .init4,"ax",@progbits
+DEFUN __do_clear_bss
+ ldi r17, hi8(__bss_end)
+ ldi r26, lo8(__bss_start)
+ ldi r27, hi8(__bss_start)
+ rjmp .do_clear_bss_start
+.do_clear_bss_loop:
+ st X+, __zero_reg__
+.do_clear_bss_start:
+ cpi r26, lo8(__bss_end)
+ cpc r27, r17
+ brne .do_clear_bss_loop
+ENDF __do_clear_bss
+#endif /* L_clear_bss */
+
+/* __do_global_ctors and __do_global_dtors are only necessary
+ if there are any constructors/destructors. */
+
+#ifdef L_ctors
+ .section .init6,"ax",@progbits
+DEFUN __do_global_ctors
+#if defined(__AVR_HAVE_RAMPZ__)
+ ldi r17, hi8(__ctors_start)
+ ldi r28, lo8(__ctors_end)
+ ldi r29, hi8(__ctors_end)
+ ldi r16, hh8(__ctors_end)
+ rjmp .L__do_global_ctors_start
+.L__do_global_ctors_loop:
+ sbiw r28, 2
+ sbc r16, __zero_reg__
+ mov_h r31, r29
+ mov_l r30, r28
+ out __RAMPZ__, r16
+ XCALL __tablejump_elpm__
+.L__do_global_ctors_start:
+ cpi r28, lo8(__ctors_start)
+ cpc r29, r17
+ ldi r24, hh8(__ctors_start)
+ cpc r16, r24
+ brne .L__do_global_ctors_loop
+#else
+ ldi r17, hi8(__ctors_start)
+ ldi r28, lo8(__ctors_end)
+ ldi r29, hi8(__ctors_end)
+ rjmp .L__do_global_ctors_start
+.L__do_global_ctors_loop:
+ sbiw r28, 2
+ mov_h r31, r29
+ mov_l r30, r28
+ XCALL __tablejump__
+.L__do_global_ctors_start:
+ cpi r28, lo8(__ctors_start)
+ cpc r29, r17
+ brne .L__do_global_ctors_loop
+#endif /* defined(__AVR_HAVE_RAMPZ__) */
+ENDF __do_global_ctors
+#endif /* L_ctors */
+
+#ifdef L_dtors
+ .section .fini6,"ax",@progbits
+DEFUN __do_global_dtors
+#if defined(__AVR_HAVE_RAMPZ__)
+ ldi r17, hi8(__dtors_end)
+ ldi r28, lo8(__dtors_start)
+ ldi r29, hi8(__dtors_start)
+ ldi r16, hh8(__dtors_start)
+ rjmp .L__do_global_dtors_start
+.L__do_global_dtors_loop:
+ sbiw r28, 2
+ sbc r16, __zero_reg__
+ mov_h r31, r29
+ mov_l r30, r28
+ out __RAMPZ__, r16
+ XCALL __tablejump_elpm__
+.L__do_global_dtors_start:
+ cpi r28, lo8(__dtors_end)
+ cpc r29, r17
+ ldi r24, hh8(__dtors_end)
+ cpc r16, r24
+ brne .L__do_global_dtors_loop
+#else
+ ldi r17, hi8(__dtors_end)
+ ldi r28, lo8(__dtors_start)
+ ldi r29, hi8(__dtors_start)
+ rjmp .L__do_global_dtors_start
+.L__do_global_dtors_loop:
+ mov_h r31, r29
+ mov_l r30, r28
+ XCALL __tablejump__
+ adiw r28, 2
+.L__do_global_dtors_start:
+ cpi r28, lo8(__dtors_end)
+ cpc r29, r17
+ brne .L__do_global_dtors_loop
+#endif /* defined(__AVR_HAVE_RAMPZ__) */
+ENDF __do_global_dtors
+#endif /* L_dtors */
+
+.section .text.libgcc, "ax", @progbits
+
+#ifdef L_tablejump_elpm
+DEFUN __tablejump_elpm__
+#if defined (__AVR_HAVE_ELPM__)
+#if defined (__AVR_HAVE_LPMX__)
+ elpm __tmp_reg__, Z+
+ elpm r31, Z
+ mov r30, __tmp_reg__
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+ eijmp
+#else
+ ijmp
+#endif
+
+#else
+ elpm
+ adiw r30, 1
+ push r0
+ elpm
+ push r0
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+ in __tmp_reg__, __EIND__
+ push __tmp_reg__
+#endif
+ ret
+#endif
+#endif /* defined (__AVR_HAVE_ELPM__) */
+ENDF __tablejump_elpm__
+#endif /* defined (L_tablejump_elpm) */
+
+
+.section .text.libgcc.builtins, "ax", @progbits
+
+/**********************************
+ * Find first set Bit (ffs)
+ **********************************/
+
+#if defined (L_ffssi2)
+;; find first set bit
+;; r25:r24 = ffs32 (r25:r22)
+;; clobbers: r22, r26
+DEFUN __ffssi2
+ clr r26
+ tst r22
+ brne 1f
+ subi r26, -8
+ or r22, r23
+ brne 1f
+ subi r26, -8
+ or r22, r24
+ brne 1f
+ subi r26, -8
+ or r22, r25
+ brne 1f
+ ret
+1: mov r24, r22
+ XJMP __loop_ffsqi2
+ENDF __ffssi2
+#endif /* defined (L_ffssi2) */
+
+#if defined (L_ffshi2)
+;; find first set bit
+;; r25:r24 = ffs16 (r25:r24)
+;; clobbers: r26
+DEFUN __ffshi2
+ clr r26
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ ;; Some cores have problem skipping 2-word instruction
+ tst r24
+ breq 2f
+#else
+ cpse r24, __zero_reg__
+#endif /* __AVR_HAVE_JMP_CALL__ */
+1: XJMP __loop_ffsqi2
+2: ldi r26, 8
+ or r24, r25
+ brne 1b
+ ret
+ENDF __ffshi2
+#endif /* defined (L_ffshi2) */
+
+#if defined (L_loop_ffsqi2)
+;; Helper for ffshi2, ffssi2
+;; r25:r24 = r26 + zero_extend16 (ffs8(r24))
+;; r24 must be != 0
+;; clobbers: r26
+DEFUN __loop_ffsqi2
+ inc r26
+ lsr r24
+ brcc __loop_ffsqi2
+ mov r24, r26
+ clr r25
+ ret
+ENDF __loop_ffsqi2
+#endif /* defined (L_loop_ffsqi2) */
+
+
+/**********************************
+ * Count trailing Zeros (ctz)
+ **********************************/
+
+#if defined (L_ctzsi2)
+;; count trailing zeros
+;; r25:r24 = ctz32 (r25:r22)
+;; clobbers: r26, r22
+;; ctz(0) = 255
+;; Note that ctz(0) in undefined for GCC
+DEFUN __ctzsi2
+ XCALL __ffssi2
+ dec r24
+ ret
+ENDF __ctzsi2
+#endif /* defined (L_ctzsi2) */
+
+#if defined (L_ctzhi2)
+;; count trailing zeros
+;; r25:r24 = ctz16 (r25:r24)
+;; clobbers: r26
+;; ctz(0) = 255
+;; Note that ctz(0) in undefined for GCC
+DEFUN __ctzhi2
+ XCALL __ffshi2
+ dec r24
+ ret
+ENDF __ctzhi2
+#endif /* defined (L_ctzhi2) */
+
+
+/**********************************
+ * Count leading Zeros (clz)
+ **********************************/
+
+#if defined (L_clzdi2)
+;; count leading zeros
+;; r25:r24 = clz64 (r25:r18)
+;; clobbers: r22, r23, r26
+DEFUN __clzdi2
+ XCALL __clzsi2
+ sbrs r24, 5
+ ret
+ mov_l r22, r18
+ mov_h r23, r19
+ mov_l r24, r20
+ mov_h r25, r21
+ XCALL __clzsi2
+ subi r24, -32
+ ret
+ENDF __clzdi2
+#endif /* defined (L_clzdi2) */
+
+#if defined (L_clzsi2)
+;; count leading zeros
+;; r25:r24 = clz32 (r25:r22)
+;; clobbers: r26
+DEFUN __clzsi2
+ XCALL __clzhi2
+ sbrs r24, 4
+ ret
+ mov_l r24, r22
+ mov_h r25, r23
+ XCALL __clzhi2
+ subi r24, -16
+ ret
+ENDF __clzsi2
+#endif /* defined (L_clzsi2) */
+
+#if defined (L_clzhi2)
+;; count leading zeros
+;; r25:r24 = clz16 (r25:r24)
+;; clobbers: r26
+DEFUN __clzhi2
+ clr r26
+ tst r25
+ brne 1f
+ subi r26, -8
+ or r25, r24
+ brne 1f
+ ldi r24, 16
+ ret
+1: cpi r25, 16
+ brsh 3f
+ subi r26, -3
+ swap r25
+2: inc r26
+3: lsl r25
+ brcc 2b
+ mov r24, r26
+ clr r25
+ ret
+ENDF __clzhi2
+#endif /* defined (L_clzhi2) */
+
+
+/**********************************
+ * Parity
+ **********************************/
+
+#if defined (L_paritydi2)
+;; r25:r24 = parity64 (r25:r18)
+;; clobbers: __tmp_reg__
+DEFUN __paritydi2
+ eor r24, r18
+ eor r24, r19
+ eor r24, r20
+ eor r24, r21
+ XJMP __paritysi2
+ENDF __paritydi2
+#endif /* defined (L_paritydi2) */
+
+#if defined (L_paritysi2)
+;; r25:r24 = parity32 (r25:r22)
+;; clobbers: __tmp_reg__
+DEFUN __paritysi2
+ eor r24, r22
+ eor r24, r23
+ XJMP __parityhi2
+ENDF __paritysi2
+#endif /* defined (L_paritysi2) */
+
+#if defined (L_parityhi2)
+;; r25:r24 = parity16 (r25:r24)
+;; clobbers: __tmp_reg__
+DEFUN __parityhi2
+ eor r24, r25
+;; FALLTHRU
+ENDF __parityhi2
+
+;; r25:r24 = parity8 (r24)
+;; clobbers: __tmp_reg__
+DEFUN __parityqi2
+ ;; parity is in r24[0..7]
+ mov __tmp_reg__, r24
+ swap __tmp_reg__
+ eor r24, __tmp_reg__
+ ;; parity is in r24[0..3]
+ subi r24, -4
+ andi r24, -5
+ subi r24, -6
+ ;; parity is in r24[0,3]
+ sbrc r24, 3
+ inc r24
+ ;; parity is in r24[0]
+ andi r24, 1
+ clr r25
+ ret
+ENDF __parityqi2
+#endif /* defined (L_parityhi2) */
+
+
+/**********************************
+ * Population Count
+ **********************************/
+
+#if defined (L_popcounthi2)
+;; population count
+;; r25:r24 = popcount16 (r25:r24)
+;; clobbers: __tmp_reg__
+DEFUN __popcounthi2
+ XCALL __popcountqi2
+ push r24
+ mov r24, r25
+ XCALL __popcountqi2
+ clr r25
+ ;; FALLTHRU
+ENDF __popcounthi2
+
+DEFUN __popcounthi2_tail
+ pop __tmp_reg__
+ add r24, __tmp_reg__
+ ret
+ENDF __popcounthi2_tail
+#endif /* defined (L_popcounthi2) */
+
+#if defined (L_popcountsi2)
+;; population count
+;; r25:r24 = popcount32 (r25:r22)
+;; clobbers: __tmp_reg__
+DEFUN __popcountsi2
+ XCALL __popcounthi2
+ push r24
+ mov_l r24, r22
+ mov_h r25, r23
+ XCALL __popcounthi2
+ XJMP __popcounthi2_tail
+ENDF __popcountsi2
+#endif /* defined (L_popcountsi2) */
+
+#if defined (L_popcountdi2)
+;; population count
+;; r25:r24 = popcount64 (r25:r18)
+;; clobbers: r22, r23, __tmp_reg__
+DEFUN __popcountdi2
+ XCALL __popcountsi2
+ push r24
+ mov_l r22, r18
+ mov_h r23, r19
+ mov_l r24, r20
+ mov_h r25, r21
+ XCALL __popcountsi2
+ XJMP __popcounthi2_tail
+ENDF __popcountdi2
+#endif /* defined (L_popcountdi2) */
+
+#if defined (L_popcountqi2)
+;; population count
+;; r24 = popcount8 (r24)
+;; clobbers: __tmp_reg__
+DEFUN __popcountqi2
+ mov __tmp_reg__, r24
+ andi r24, 1
+ lsr __tmp_reg__
+ lsr __tmp_reg__
+ adc r24, __zero_reg__
+ lsr __tmp_reg__
+ adc r24, __zero_reg__
+ lsr __tmp_reg__
+ adc r24, __zero_reg__
+ lsr __tmp_reg__
+ adc r24, __zero_reg__
+ lsr __tmp_reg__
+ adc r24, __zero_reg__
+ lsr __tmp_reg__
+ adc r24, __tmp_reg__
+ ret
+ENDF __popcountqi2
+#endif /* defined (L_popcountqi2) */
+
+
+/**********************************
+ * Swap bytes
+ **********************************/
+
+;; swap two registers with different register number
+.macro bswap a, b
+ eor \a, \b
+ eor \b, \a
+ eor \a, \b
+.endm
+
+#if defined (L_bswapsi2)
+;; swap bytes
+;; r25:r22 = bswap32 (r25:r22)
+DEFUN __bswapsi2
+ bswap r22, r25
+ bswap r23, r24
+ ret
+ENDF __bswapsi2
+#endif /* defined (L_bswapsi2) */
+
+#if defined (L_bswapdi2)
+;; swap bytes
+;; r25:r18 = bswap64 (r25:r18)
+DEFUN __bswapdi2
+ bswap r18, r25
+ bswap r19, r24
+ bswap r20, r23
+ bswap r21, r22
+ ret
+ENDF __bswapdi2
+#endif /* defined (L_bswapdi2) */
+
+
+/**********************************
+ * 64-bit shifts
+ **********************************/
+
+#if defined (L_ashrdi3)
+;; Arithmetic shift right
+;; r25:r18 = ashr64 (r25:r18, r17:r16)
+DEFUN __ashrdi3
+ push r16
+ andi r16, 63
+ breq 2f
+1: asr r25
+ ror r24
+ ror r23
+ ror r22
+ ror r21
+ ror r20
+ ror r19
+ ror r18
+ dec r16
+ brne 1b
+2: pop r16
+ ret
+ENDF __ashrdi3
+#endif /* defined (L_ashrdi3) */
+
+#if defined (L_lshrdi3)
+;; Logic shift right
+;; r25:r18 = lshr64 (r25:r18, r17:r16)
+DEFUN __lshrdi3
+ push r16
+ andi r16, 63
+ breq 2f
+1: lsr r25
+ ror r24
+ ror r23
+ ror r22
+ ror r21
+ ror r20
+ ror r19
+ ror r18
+ dec r16
+ brne 1b
+2: pop r16
+ ret
+ENDF __lshrdi3
+#endif /* defined (L_lshrdi3) */
+
+#if defined (L_ashldi3)
+;; Shift left
+;; r25:r18 = ashl64 (r25:r18, r17:r16)
+DEFUN __ashldi3
+ push r16
+ andi r16, 63
+ breq 2f
+1: lsl r18
+ rol r19
+ rol r20
+ rol r21
+ rol r22
+ rol r23
+ rol r24
+ rol r25
+ dec r16
+ brne 1b
+2: pop r16
+ ret
+ENDF __ashldi3
+#endif /* defined (L_ashldi3) */
+
+
+.section .text.libgcc.fmul, "ax", @progbits
+
+/***********************************************************/
+;;; Softmul versions of FMUL, FMULS and FMULSU to implement
+;;; __builtin_avr_fmul* if !AVR_HAVE_MUL
+/***********************************************************/
+
+#define A1 24
+#define B1 25
+#define C0 22
+#define C1 23
+#define A0 __tmp_reg__
+
+#ifdef L_fmuls
+;;; r23:r22 = fmuls (r24, r25) like in FMULS instruction
+;;; Clobbers: r24, r25, __tmp_reg__
+DEFUN __fmuls
+ ;; A0.7 = negate result?
+ mov A0, A1
+ eor A0, B1
+ ;; B1 = |B1|
+ sbrc B1, 7
+ neg B1
+ XJMP __fmulsu_exit
+ENDF __fmuls
+#endif /* L_fmuls */
+
+#ifdef L_fmulsu
+;;; r23:r22 = fmulsu (r24, r25) like in FMULSU instruction
+;;; Clobbers: r24, r25, __tmp_reg__
+DEFUN __fmulsu
+ ;; A0.7 = negate result?
+ mov A0, A1
+;; FALLTHRU
+ENDF __fmulsu
+
+;; Helper for __fmuls and __fmulsu
+DEFUN __fmulsu_exit
+ ;; A1 = |A1|
+ sbrc A1, 7
+ neg A1
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ ;; Some cores have problem skipping 2-word instruction
+ tst A0
+ brmi 1f
+#else
+ sbrs A0, 7
+#endif /* __AVR_HAVE_JMP_CALL__ */
+ XJMP __fmul
+1: XCALL __fmul
+ ;; C = -C iff A0.7 = 1
+ com C1
+ neg C0
+ sbci C1, -1
+ ret
+ENDF __fmulsu_exit
+#endif /* L_fmulsu */
+
+
+#ifdef L_fmul
+;;; r22:r23 = fmul (r24, r25) like in FMUL instruction
+;;; Clobbers: r24, r25, __tmp_reg__
+DEFUN __fmul
+ ; clear result
+ clr C0
+ clr C1
+ clr A0
+1: tst B1
+ ;; 1.0 = 0x80, so test for bit 7 of B to see if A must to be added to C.
+2: brpl 3f
+ ;; C += A
+ add C0, A0
+ adc C1, A1
+3: ;; A >>= 1
+ lsr A1
+ ror A0
+ ;; B <<= 1
+ lsl B1
+ brne 2b
+ ret
+ENDF __fmul
+#endif /* L_fmul */
+
+#undef A0
+#undef A1
+#undef B1
+#undef C0
+#undef C1
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index 78829c76af4..a669f61629a 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -1,3 +1,59 @@
+LIB1ASMSRC = avr/lib1funcs.S
+LIB1ASMFUNCS = \
+ _mulqi3 \
+ _mulhi3 \
+ _mulhisi3 \
+ _umulhisi3 \
+ _usmulhisi3 \
+ _muluhisi3 \
+ _mulshisi3 \
+ _mulsi3 \
+ _udivmodqi4 \
+ _divmodqi4 \
+ _udivmodhi4 \
+ _divmodhi4 \
+ _udivmodsi4 \
+ _divmodsi4 \
+ _prologue \
+ _epilogue \
+ _exit \
+ _cleanup \
+ _tablejump \
+ _tablejump_elpm \
+ _copy_data \
+ _clear_bss \
+ _ctors \
+ _dtors \
+ _ffssi2 \
+ _ffshi2 \
+ _loop_ffsqi2 \
+ _ctzsi2 \
+ _ctzhi2 \
+ _clzdi2 \
+ _clzsi2 \
+ _clzhi2 \
+ _paritydi2 \
+ _paritysi2 \
+ _parityhi2 \
+ _popcounthi2 \
+ _popcountsi2 \
+ _popcountdi2 \
+ _popcountqi2 \
+ _bswapsi2 \
+ _bswapdi2 \
+ _ashldi3 \
+ _ashrdi3 \
+ _lshrdi3 \
+ _fmul _fmuls _fmulsu
+
+LIB2FUNCS_EXCLUDE = \
+ _clz
+
+# We do not have the DF type.
+# Most of the C functions in libgcc2 use almost all registers,
+# so use -mcall-prologues for smaller code size.
+HOST_LIBGCC2_CFLAGS = -DDF=SF -Dinhibit_libc -mcall-prologues -Os
+
# Extra 16-bit integer functions.
intfuncs16 = _absvXX2 _addvXX3 _subvXX3 _mulvXX3 _negvXX2 _clrsbXX2
diff --git a/gcc/config/bfin/crti.s b/libgcc/config/bfin/crti.S
index b6f20fc9e6b..b6f20fc9e6b 100644
--- a/gcc/config/bfin/crti.s
+++ b/libgcc/config/bfin/crti.S
diff --git a/gcc/config/bfin/crtlibid.s b/libgcc/config/bfin/crtlibid.S
index beab8093810..beab8093810 100644
--- a/gcc/config/bfin/crtlibid.s
+++ b/libgcc/config/bfin/crtlibid.S
diff --git a/gcc/config/bfin/crtn.s b/libgcc/config/bfin/crtn.S
index 7fcd27bfade..7fcd27bfade 100644
--- a/gcc/config/bfin/crtn.s
+++ b/libgcc/config/bfin/crtn.S
diff --git a/gcc/config/bfin/lib1funcs.asm b/libgcc/config/bfin/lib1funcs.S
index c7bf4f3f05c..c7bf4f3f05c 100644
--- a/gcc/config/bfin/lib1funcs.asm
+++ b/libgcc/config/bfin/lib1funcs.S
diff --git a/gcc/config/bfin/libgcc-bfin.ver b/libgcc/config/bfin/libgcc-glibc.ver
index 516d91f6584..516d91f6584 100644
--- a/gcc/config/bfin/libgcc-bfin.ver
+++ b/libgcc/config/bfin/libgcc-glibc.ver
diff --git a/libgcc/config/bfin/t-bfin b/libgcc/config/bfin/t-bfin
new file mode 100644
index 00000000000..bc2b088ffc1
--- /dev/null
+++ b/libgcc/config/bfin/t-bfin
@@ -0,0 +1,3 @@
+LIB1ASMSRC = bfin/lib1funcs.S
+LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3 _muldi3 _umulsi3_highpart
+LIB1ASMFUNCS += _smulsi3_highpart
diff --git a/libgcc/config/bfin/t-crtlibid b/libgcc/config/bfin/t-crtlibid
new file mode 100644
index 00000000000..b0c93e71eb9
--- /dev/null
+++ b/libgcc/config/bfin/t-crtlibid
@@ -0,0 +1,3 @@
+# Assemble startup files.
+crtlibid.o: $(srcdir)/config/bfin/crtlibid.S
+ $(gcc_compile) -c -x assembler-with-cpp $<
diff --git a/libgcc/config/bfin/t-crtstuff b/libgcc/config/bfin/t-crtstuff
new file mode 100644
index 00000000000..eee12eb697a
--- /dev/null
+++ b/libgcc/config/bfin/t-crtstuff
@@ -0,0 +1 @@
+CRTSTUFF_T_CFLAGS = $(PICFLAG)
diff --git a/libgcc/config/bfin/t-elf b/libgcc/config/bfin/t-elf
new file mode 100644
index 00000000000..cb243e60401
--- /dev/null
+++ b/libgcc/config/bfin/t-elf
@@ -0,0 +1 @@
+HOST_LIBGCC2_CFLAGS = $(PICFLAG)
diff --git a/libgcc/config/bfin/t-linux b/libgcc/config/bfin/t-linux
new file mode 100644
index 00000000000..1c42e482b8d
--- /dev/null
+++ b/libgcc/config/bfin/t-linux
@@ -0,0 +1 @@
+SHLIB_MAPFILES = $(srcdir)/config/bfin/libgcc-glibc.ver
diff --git a/gcc/config/c6x/crti.s b/libgcc/config/c6x/crti.S
index 8fe35c1f121..8fe35c1f121 100644
--- a/gcc/config/c6x/crti.s
+++ b/libgcc/config/c6x/crti.S
diff --git a/gcc/config/c6x/crtn.s b/libgcc/config/c6x/crtn.S
index 5900a4b14c4..5900a4b14c4 100644
--- a/gcc/config/c6x/crtn.s
+++ b/libgcc/config/c6x/crtn.S
diff --git a/gcc/config/c6x/eqd.c b/libgcc/config/c6x/eqd.c
index d6b32013bcb..d6b32013bcb 100644
--- a/gcc/config/c6x/eqd.c
+++ b/libgcc/config/c6x/eqd.c
diff --git a/gcc/config/c6x/eqf.c b/libgcc/config/c6x/eqf.c
index ee6dafc98b7..ee6dafc98b7 100644
--- a/gcc/config/c6x/eqf.c
+++ b/libgcc/config/c6x/eqf.c
diff --git a/gcc/config/c6x/ged.c b/libgcc/config/c6x/ged.c
index 2089904f92a..2089904f92a 100644
--- a/gcc/config/c6x/ged.c
+++ b/libgcc/config/c6x/ged.c
diff --git a/gcc/config/c6x/gef.c b/libgcc/config/c6x/gef.c
index ce4c1c0af3d..ce4c1c0af3d 100644
--- a/gcc/config/c6x/gef.c
+++ b/libgcc/config/c6x/gef.c
diff --git a/gcc/config/c6x/gtd.c b/libgcc/config/c6x/gtd.c
index 6d45aef9af8..6d45aef9af8 100644
--- a/gcc/config/c6x/gtd.c
+++ b/libgcc/config/c6x/gtd.c
diff --git a/gcc/config/c6x/gtf.c b/libgcc/config/c6x/gtf.c
index c6a108a2833..c6a108a2833 100644
--- a/gcc/config/c6x/gtf.c
+++ b/libgcc/config/c6x/gtf.c
diff --git a/gcc/config/c6x/led.c b/libgcc/config/c6x/led.c
index c99e29e0ddf..c99e29e0ddf 100644
--- a/gcc/config/c6x/led.c
+++ b/libgcc/config/c6x/led.c
diff --git a/gcc/config/c6x/lef.c b/libgcc/config/c6x/lef.c
index ce2c16f8ede..ce2c16f8ede 100644
--- a/gcc/config/c6x/lef.c
+++ b/libgcc/config/c6x/lef.c
diff --git a/gcc/config/c6x/lib1funcs.asm b/libgcc/config/c6x/lib1funcs.S
index 5bf34474bbd..5bf34474bbd 100644
--- a/gcc/config/c6x/lib1funcs.asm
+++ b/libgcc/config/c6x/lib1funcs.S
diff --git a/gcc/config/c6x/libgcc-c6xeabi.ver b/libgcc/config/c6x/libgcc-eabi.ver
index 6bce556512e..6bce556512e 100644
--- a/gcc/config/c6x/libgcc-c6xeabi.ver
+++ b/libgcc/config/c6x/libgcc-eabi.ver
diff --git a/gcc/config/c6x/ltd.c b/libgcc/config/c6x/ltd.c
index d4de25866b7..d4de25866b7 100644
--- a/gcc/config/c6x/ltd.c
+++ b/libgcc/config/c6x/ltd.c
diff --git a/gcc/config/c6x/ltf.c b/libgcc/config/c6x/ltf.c
index 2fe15b99fde..2fe15b99fde 100644
--- a/gcc/config/c6x/ltf.c
+++ b/libgcc/config/c6x/ltf.c
diff --git a/libgcc/config/c6x/pr-support.c b/libgcc/config/c6x/pr-support.c
index 6375013cb66..2e0958c4a23 100644
--- a/libgcc/config/c6x/pr-support.c
+++ b/libgcc/config/c6x/pr-support.c
@@ -153,10 +153,7 @@ pop_compact_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp)
{
int size;
_uw test;
- int i;
- int regno;
- int regno2;
- int nregs;
+ int i, regno, nregs;
size = 0;
nregs = __builtin_popcount (mask);
@@ -167,13 +164,11 @@ pop_compact_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp)
continue;
regno = unwind_frame_regs[12 - i];
- /* The last slot is a sigle word, so cannot store a register pair. */
- if (nregs > 2)
- regno2 = unwind_frame_regs[13 - i];
- else
- regno2 = 0xff;
- if ((mask & (test << 1)) != 0 && regno2 == regno + 1 && (regno & 1) == 0)
+ if (i < 12 && nregs > 2
+ && (mask & (test << 1)) != 0
+ && unwind_frame_regs[11 - i] == regno + 1
+ && (regno & 1) == 0)
{
i++;
nregs--;
@@ -196,12 +191,11 @@ pop_compact_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp)
continue;
regno = unwind_frame_regs[12 - i];
- if (nregs > 2)
- regno2 = unwind_frame_regs[13 - i];
- else
- regno2 = 0xff;
- if ((mask & (test << 1)) != 0 && regno2 == regno + 1 && (regno & 1) == 0)
+ if (i < 12 && nregs > 2
+ && (mask & (test << 1)) != 0
+ && unwind_frame_regs[11 - i] == regno + 1
+ && (regno & 1) == 0)
{
/* Register pair. */
unwind_restore_pair (context, regno, ptr);
@@ -243,7 +237,7 @@ pop_frame (_Unwind_Context * context, _uw mask, _uw *ptr, int inc_sp)
if ((mask & (1 << i)) == 0)
continue;
regno = unwind_frame_regs[12 - i];
- if (i < 12 && unwind_frame_regs[13 - i] == (regno + 1)
+ if (i < 12 && unwind_frame_regs[11 - i] == (regno + 1)
&& (mask & (1 << (i + 1))) != 0
&& (((_uw)ptr) & 4) == 0
&& (regno & 1) == 0)
@@ -273,6 +267,14 @@ __gnu_unwind_24bit (_Unwind_Context * context, _uw data, int compact)
_uw mask;
_uw *ptr;
_uw tmp;
+ int ret_reg = unwind_frame_regs[data & 0xf];
+
+ if (ret_reg != R_B3)
+ {
+ _Unwind_VRS_Get (context, _UVRSC_CORE, unwind_frame_regs[data & 0xf],
+ _UVRSD_UINT32, &tmp);
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &tmp);
+ }
mask = (data >> 4) & 0x1fff;
@@ -291,8 +293,7 @@ __gnu_unwind_24bit (_Unwind_Context * context, _uw data, int compact)
else
pop_frame (context, mask, ptr, offset != 0x7f);
- _Unwind_VRS_Get (context, _UVRSC_CORE, unwind_frame_regs[data & 0xf],
- _UVRSD_UINT32, &tmp);
+ _Unwind_VRS_Get (context, _UVRSC_CORE, R_B3, _UVRSD_UINT32, &tmp);
_Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32, &tmp);
return _URC_OK;
diff --git a/libgcc/config/c6x/t-elf b/libgcc/config/c6x/t-elf
new file mode 100644
index 00000000000..2ee6a957fd7
--- /dev/null
+++ b/libgcc/config/c6x/t-elf
@@ -0,0 +1,36 @@
+# Cannot use default rules due to $(CRTSTUFF_T_CFLAGS).
+CUSTOM_CRTIN = yes
+
+LIB1ASMSRC = c6x/lib1funcs.S
+LIB1ASMFUNCS = _divsi3 _udivsi3 _umodsi3 _modsi3 _udivmodsi4 _divmodsi4
+LIB1ASMFUNCS += _strasgi _strasgi_64plus _clzsi2 _clzdi2 _clz
+LIB1ASMFUNCS += _push_rts _pop_rts _call_stub
+
+LIB2FUNCS_EXCLUDE = _cmpdi2 _ucmpdi2 _gcc_bcmp _eprintf _clzsi _clzdi
+
+LIB2ADD = $(srcdir)/config/c6x/gef.c \
+ $(srcdir)/config/c6x/gtf.c \
+ $(srcdir)/config/c6x/lef.c \
+ $(srcdir)/config/c6x/ltf.c \
+ $(srcdir)/config/c6x/eqf.c \
+ $(srcdir)/config/c6x/ged.c \
+ $(srcdir)/config/c6x/gtd.c \
+ $(srcdir)/config/c6x/led.c \
+ $(srcdir)/config/c6x/ltd.c \
+ $(srcdir)/config/c6x/eqd.c
+
+# Avoid failures when the user's GOT becomes too large.
+HOST_LIBGCC2_CFLAGS = -msdata=none
+
+# Assemble startup files.
+crti.o: $(srcdir)/config/c6x/crti.S
+ $(crt_compile) -c $(CRTSTUFF_T_CFLAGS) $<
+
+crtn.o: $(srcdir)/config/c6x/crtn.S
+ $(crt_compile) -c $(CRTSTUFF_T_CFLAGS) $<
+
+# Avoid failures when the user's GOT becomes too large.
+CRTSTUFF_T_CFLAGS = -msdata=none
+CRTSTUFF_T_CFLAGS_S = -msdata=none
+
+SHLIB_MAPFILES += $(srcdir)/config/c6x/libgcc-eabi.ver
diff --git a/libgcc/config/c6x/t-uclinux b/libgcc/config/c6x/t-uclinux
new file mode 100644
index 00000000000..72a170a575a
--- /dev/null
+++ b/libgcc/config/c6x/t-uclinux
@@ -0,0 +1,3 @@
+HOST_LIBGCC2_CFLAGS += -msdata=none
+
+CRTSTUFF_T_CFLAGS += $(PICFLAG)
diff --git a/gcc/config/cris/arit.c b/libgcc/config/cris/arit.c
index 32255f99d39..32255f99d39 100644
--- a/gcc/config/cris/arit.c
+++ b/libgcc/config/cris/arit.c
diff --git a/gcc/config/cris/libgcc.ver b/libgcc/config/cris/libgcc-glibc.ver
index e35de83100f..e35de83100f 100644
--- a/gcc/config/cris/libgcc.ver
+++ b/libgcc/config/cris/libgcc-glibc.ver
diff --git a/gcc/config/cris/mulsi3.asm b/libgcc/config/cris/mulsi3.S
index 76dfb634680..76dfb634680 100644
--- a/gcc/config/cris/mulsi3.asm
+++ b/libgcc/config/cris/mulsi3.S
diff --git a/libgcc/config/cris/t-cris b/libgcc/config/cris/t-cris
new file mode 100644
index 00000000000..b582974a42e
--- /dev/null
+++ b/libgcc/config/cris/t-cris
@@ -0,0 +1,10 @@
+LIB2ADD = _udivsi3.c _divsi3.c _umodsi3.c _modsi3.c
+
+# The fixed-point arithmetic code is in one file, arit.c,
+# similar to libgcc2.c (or the old libgcc1.c). We need to
+# "split it up" with one file per define.
+$(LIB2ADD): $(srcdir)/config/cris/arit.c
+ name=`echo $@ | sed -e 's,.*/,,' | sed -e 's,.c$$,,'`; \
+ echo "#define L$$name" > tmp-$@ \
+ && echo '#include "$<"' >> tmp-$@ \
+ && mv -f tmp-$@ $@
diff --git a/libgcc/config/cris/t-elfmulti b/libgcc/config/cris/t-elfmulti
new file mode 100644
index 00000000000..b180521039e
--- /dev/null
+++ b/libgcc/config/cris/t-elfmulti
@@ -0,0 +1,3 @@
+LIB2ADD_ST = $(srcdir)/config/cris/mulsi3.S
+
+CRTSTUFF_T_CFLAGS = -moverride-best-lib-options
diff --git a/libgcc/config/cris/t-linux b/libgcc/config/cris/t-linux
new file mode 100644
index 00000000000..8c7f4d44249
--- /dev/null
+++ b/libgcc/config/cris/t-linux
@@ -0,0 +1,2 @@
+# Override t-linux default.
+SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/cris/libgcc-glibc.ver
diff --git a/gcc/config/darwin-64.c b/libgcc/config/darwin-64.c
index a012e9dbc1e..a012e9dbc1e 100644
--- a/gcc/config/darwin-64.c
+++ b/libgcc/config/darwin-64.c
diff --git a/libgcc/config/darwin-crt3.c b/libgcc/config/darwin-crt3.c
index 9b64f2aa8c3..5ef00546260 100644
--- a/libgcc/config/darwin-crt3.c
+++ b/libgcc/config/darwin-crt3.c
@@ -1,5 +1,5 @@
/* __cxa_atexit backwards-compatibility support for Darwin.
- Copyright (C) 2006, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -25,10 +25,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Don't do anything if we are compiling for a kext multilib. */
#ifdef __PIC__
-/* 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"
diff --git a/gcc/config/fr30/crti.asm b/libgcc/config/fr30/crti.S
index 4ce61231bd7..4ce61231bd7 100644
--- a/gcc/config/fr30/crti.asm
+++ b/libgcc/config/fr30/crti.S
diff --git a/libgcc/config/fr30/crtn.S b/libgcc/config/fr30/crtn.S
new file mode 100644
index 00000000000..c62d37b6671
--- /dev/null
+++ b/libgcc/config/fr30/crtn.S
@@ -0,0 +1,44 @@
+# crtn.S for ELF
+
+# Copyright (C) 1992, 1999, 2008, 2009, 2011 Free Software Foundation, Inc.
+# Written By David Vinayak Henkel-Wallace, June 1992
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file just makes sure that the .fini and .init sections do in
+# fact return. Users may put any desired instructions in those sections.
+# This file is the last thing linked into any executable.
+
+ .section ".init"
+ .align 4
+
+ leave
+ ld @r15+,rp
+ ret
+
+
+ .section ".fini"
+ .align 4
+
+ leave
+ ld @r15+,rp
+ ret
+
+# Th-th-th-that is all folks!
diff --git a/gcc/config/fr30/lib1funcs.asm b/libgcc/config/fr30/lib1funcs.S
index 7c63453123a..7c63453123a 100644
--- a/gcc/config/fr30/lib1funcs.asm
+++ b/libgcc/config/fr30/lib1funcs.S
diff --git a/libgcc/config/fr30/t-fr30 b/libgcc/config/fr30/t-fr30
new file mode 100644
index 00000000000..ee5ed9a127e
--- /dev/null
+++ b/libgcc/config/fr30/t-fr30
@@ -0,0 +1,2 @@
+LIB1ASMSRC = fr30/lib1funcs.S
+LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3
diff --git a/gcc/config/frv/cmovd.c b/libgcc/config/frv/cmovd.c
index e46070aac04..e46070aac04 100644
--- a/gcc/config/frv/cmovd.c
+++ b/libgcc/config/frv/cmovd.c
diff --git a/gcc/config/frv/cmovh.c b/libgcc/config/frv/cmovh.c
index 6b0901d95a7..6b0901d95a7 100644
--- a/gcc/config/frv/cmovh.c
+++ b/libgcc/config/frv/cmovh.c
diff --git a/gcc/config/frv/cmovw.c b/libgcc/config/frv/cmovw.c
index f27db75aaf6..f27db75aaf6 100644
--- a/gcc/config/frv/cmovw.c
+++ b/libgcc/config/frv/cmovw.c
diff --git a/gcc/config/frv/frvbegin.c b/libgcc/config/frv/frvbegin.c
index 23cbf1ecc93..23cbf1ecc93 100644
--- a/gcc/config/frv/frvbegin.c
+++ b/libgcc/config/frv/frvbegin.c
diff --git a/gcc/config/frv/frvend.c b/libgcc/config/frv/frvend.c
index 0bb07b56b4a..0bb07b56b4a 100644
--- a/gcc/config/frv/frvend.c
+++ b/libgcc/config/frv/frvend.c
diff --git a/gcc/config/frv/lib1funcs.asm b/libgcc/config/frv/lib1funcs.S
index d1ffcab6133..d1ffcab6133 100644
--- a/gcc/config/frv/lib1funcs.asm
+++ b/libgcc/config/frv/lib1funcs.S
diff --git a/gcc/config/frv/libgcc-frv.ver b/libgcc/config/frv/libgcc-glibc.ver
index 6e27b4f9b85..6e27b4f9b85 100644
--- a/gcc/config/frv/libgcc-frv.ver
+++ b/libgcc/config/frv/libgcc-glibc.ver
diff --git a/gcc/config/frv/modi.c b/libgcc/config/frv/modi.c
index d5a91fc0f55..d5a91fc0f55 100644
--- a/gcc/config/frv/modi.c
+++ b/libgcc/config/frv/modi.c
diff --git a/libgcc/config/frv/t-frv b/libgcc/config/frv/t-frv
new file mode 100644
index 00000000000..a4ff0585183
--- /dev/null
+++ b/libgcc/config/frv/t-frv
@@ -0,0 +1,22 @@
+LIB1ASMSRC = frv/lib1funcs.S
+LIB1ASMFUNCS = _cmpll _cmpf _cmpd _addll _subll _andll _orll _xorll _notll _cmov
+
+LIB2ADD = $(srcdir)/config/frv/cmovh.c \
+ $(srcdir)/config/frv/cmovw.c \
+ $(srcdir)/config/frv/cmovd.c \
+ $(srcdir)/config/frv/modi.c \
+ $(srcdir)/config/frv/umodi.c \
+ $(srcdir)/config/frv/uitof.c \
+ $(srcdir)/config/frv/uitod.c \
+ $(srcdir)/config/frv/ulltof.c \
+ $(srcdir)/config/frv/ulltod.c
+
+# 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.
+
+frvbegin$(objext): $(srcdir)/config/frv/frvbegin.c
+ $(gcc_compile) -c $<
+
+frvend$(objext): $(srcdir)/config/frv/frvend.c
+ $(gcc_compile) -c $<
diff --git a/libgcc/config/frv/t-linux b/libgcc/config/frv/t-linux
new file mode 100644
index 00000000000..0240efefae9
--- /dev/null
+++ b/libgcc/config/frv/t-linux
@@ -0,0 +1,3 @@
+CRTSTUFF_T_CFLAGS = $(PICFLAG)
+
+SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/frv/libgcc-glibc.ver
diff --git a/gcc/config/frv/uitod.c b/libgcc/config/frv/uitod.c
index 14290ab6b04..14290ab6b04 100644
--- a/gcc/config/frv/uitod.c
+++ b/libgcc/config/frv/uitod.c
diff --git a/gcc/config/frv/uitof.c b/libgcc/config/frv/uitof.c
index 059bc7c7417..059bc7c7417 100644
--- a/gcc/config/frv/uitof.c
+++ b/libgcc/config/frv/uitof.c
diff --git a/gcc/config/frv/ulltod.c b/libgcc/config/frv/ulltod.c
index e6bee12081f..e6bee12081f 100644
--- a/gcc/config/frv/ulltod.c
+++ b/libgcc/config/frv/ulltod.c
diff --git a/gcc/config/frv/ulltof.c b/libgcc/config/frv/ulltof.c
index 29cdfd4d2a1..29cdfd4d2a1 100644
--- a/gcc/config/frv/ulltof.c
+++ b/libgcc/config/frv/ulltof.c
diff --git a/gcc/config/frv/umodi.c b/libgcc/config/frv/umodi.c
index 4ffe5ad8132..4ffe5ad8132 100644
--- a/gcc/config/frv/umodi.c
+++ b/libgcc/config/frv/umodi.c
diff --git a/libgcc/config/gthr-lynx.h b/libgcc/config/gthr-lynx.h
new file mode 100644
index 00000000000..c98c2e6693e
--- /dev/null
+++ b/libgcc/config/gthr-lynx.h
@@ -0,0 +1,61 @@
+/* Threads compatibility routines for libgcc2 and libobjc for
+ LynxOS. */
+/* Compile this one with gcc. */
+/* Copyright (C) 2004, 2008, 2009, 2011 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_GTHR_LYNX_H
+#define GCC_GTHR_LYNX_H
+
+#ifdef _MULTITHREADED
+
+/* Using the macro version of pthread_setspecific leads to a
+ compilation error. Instead we have two choices either kill all
+ macros in pthread.h with defining _POSIX_THREADS_CALLS or undefine
+ individual macros where we should fall back on the function
+ implementation. We choose the second approach. */
+
+#include <pthread.h>
+#undef pthread_setspecific
+
+/* When using static libc on LynxOS, we cannot define pthread_create
+ weak. If the multi-threaded application includes iostream.h,
+ gthr-posix.h is included and pthread_create will be defined weak.
+ If pthread_create is weak its defining module in libc is not
+ necessarily included in the link and the symbol is resolved to zero.
+ Therefore the first call to it will crash.
+
+ Since -mthreads is a multilib switch on LynxOS we know that at this
+ point we are compiling for multi-threaded. Omitting the weak
+ definitions at this point should have no effect. */
+
+#undef GTHREAD_USE_WEAK
+#define GTHREAD_USE_WEAK 0
+
+#include "config/gthr-posix.h"
+
+#else
+#include "gthr-single.h"
+#endif
+
+#endif /* GCC_GTHR_LYNX_H */
diff --git a/gcc/gthr-posix.h b/libgcc/config/gthr-posix.h
index 46054f6a7c2..46054f6a7c2 100644
--- a/gcc/gthr-posix.h
+++ b/libgcc/config/gthr-posix.h
diff --git a/gcc/gthr-rtems.h b/libgcc/config/gthr-rtems.h
index c5bd52292cf..c5bd52292cf 100644
--- a/gcc/gthr-rtems.h
+++ b/libgcc/config/gthr-rtems.h
diff --git a/libgcc/config/gthr-vxworks.h b/libgcc/config/gthr-vxworks.h
new file mode 100644
index 00000000000..2346b528660
--- /dev/null
+++ b/libgcc/config/gthr-vxworks.h
@@ -0,0 +1,170 @@
+/* Threads compatibility routines for libgcc2 and libobjc for VxWorks. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1997, 1999, 2000, 2008, 2009, 2011
+ Free Software Foundation, Inc.
+ Contributed by Mike Stump <mrs@wrs.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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_GTHR_VXWORKS_H
+#define GCC_GTHR_VXWORKS_H
+
+#ifdef _LIBOBJC
+
+/* libobjc requires the optional pthreads component. */
+#include "config/gthr-posix.h"
+
+#else
+#ifdef __cplusplus
+#define UNUSED(x)
+#else
+#define UNUSED(x) x __attribute__((unused))
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __GTHREADS 1
+#define __gthread_active_p() 1
+
+/* Mutexes are easy, except that they need to be initialized at runtime. */
+
+#include <semLib.h>
+
+typedef SEM_ID __gthread_mutex_t;
+/* All VxWorks mutexes are recursive. */
+typedef SEM_ID __gthread_recursive_mutex_t;
+#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
+#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function
+
+static inline void
+__gthread_mutex_init_function (__gthread_mutex_t *mutex)
+{
+ *mutex = semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
+}
+
+static inline int
+__gthread_mutex_destroy (__gthread_mutex_t * UNUSED(mutex))
+{
+ return 0;
+}
+
+static inline int
+__gthread_mutex_lock (__gthread_mutex_t *mutex)
+{
+ return semTake (*mutex, WAIT_FOREVER);
+}
+
+static inline int
+__gthread_mutex_trylock (__gthread_mutex_t *mutex)
+{
+ return semTake (*mutex, NO_WAIT);
+}
+
+static inline int
+__gthread_mutex_unlock (__gthread_mutex_t *mutex)
+{
+ return semGive (*mutex);
+}
+
+static inline void
+__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
+{
+ __gthread_mutex_init_function (mutex);
+}
+
+static inline int
+__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
+{
+ return __gthread_mutex_lock (mutex);
+}
+
+static inline int
+__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
+{
+ return __gthread_mutex_trylock (mutex);
+}
+
+static inline int
+__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
+{
+ return __gthread_mutex_unlock (mutex);
+}
+
+/* pthread_once is complicated enough that it's implemented
+ out-of-line. See config/vxlib.c. */
+
+typedef struct
+{
+#if !defined(__RTP__)
+#if defined(__PPC__)
+ __attribute ((aligned (__alignof (unsigned))))
+#endif
+ volatile unsigned char busy;
+#endif
+ volatile unsigned char done;
+#if !defined(__RTP__) && defined(__PPC__)
+ /* PPC's test-and-set implementation requires a 4 byte aligned
+ object, of which it only sets the first byte. We use padding
+ here, in order to maintain some amount of backwards
+ compatibility. Without this padding, gthread_once objects worked
+ by accident because they happen to be static objects and the ppc
+ port automatically increased their alignment to 4 bytes. */
+ unsigned char pad1;
+ unsigned char pad2;
+#endif
+}
+__gthread_once_t;
+
+#if defined (__RTP__)
+# define __GTHREAD_ONCE_INIT { 0 }
+#elif defined (__PPC__)
+# define __GTHREAD_ONCE_INIT { 0, 0, 0, 0 }
+#else
+# define __GTHREAD_ONCE_INIT { 0, 0 }
+#endif
+
+extern int __gthread_once (__gthread_once_t *__once, void (*__func)(void));
+
+/* Thread-specific data requires a great deal of effort, since VxWorks
+ is not really set up for it. See config/vxlib.c for the gory
+ details. All the TSD routines are sufficiently complex that they
+ need to be implemented out of line. */
+
+typedef unsigned int __gthread_key_t;
+
+extern int __gthread_key_create (__gthread_key_t *__keyp, void (*__dtor)(void *));
+extern int __gthread_key_delete (__gthread_key_t __key);
+
+extern void *__gthread_getspecific (__gthread_key_t __key);
+extern int __gthread_setspecific (__gthread_key_t __key, void *__ptr);
+
+#undef UNUSED
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not _LIBOBJC */
+
+#endif /* gthr-vxworks.h */
diff --git a/gcc/config/h8300/clzhi2.c b/libgcc/config/h8300/clzhi2.c
index 54db7b9c56b..54db7b9c56b 100644
--- a/gcc/config/h8300/clzhi2.c
+++ b/libgcc/config/h8300/clzhi2.c
diff --git a/libgcc/config/h8300/crti.S b/libgcc/config/h8300/crti.S
new file mode 100644
index 00000000000..f58c3aac9dd
--- /dev/null
+++ b/libgcc/config/h8300/crti.S
@@ -0,0 +1,63 @@
+/* Copyright (C) 2001, 2002, 2009, 2011 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* The code in sections .init and .fini is supposed to be a single
+ regular function. The function in .init is called directly from
+ start in crt0.S. The function in .fini is atexit()ed in crt0.S
+ too.
+
+ crti.S contributes the prologue of a function to these sections,
+ and crtn.S comes up the epilogue. STARTFILE_SPEC should list
+ crti.o before any other object files that might add code to .init
+ or .fini sections, and ENDFILE_SPEC should list crtn.o after any
+ such object files. */
+
+#ifdef __H8300H__
+#ifdef __NORMAL_MODE__
+ .h8300hn
+#else
+ .h8300h
+#endif
+#endif
+
+#ifdef __H8300S__
+#ifdef __NORMAL_MODE__
+ .h8300sn
+#else
+ .h8300s
+#endif
+#endif
+#ifdef __H8300SX__
+#ifdef __NORMAL_MODE__
+ .h8300sxn
+#else
+ .h8300sx
+#endif
+#endif
+
+ .section .init, "ax", @progbits
+ .global __init
+__init:
+ .section .fini, "ax", @progbits
+ .global __fini
+__fini:
diff --git a/libgcc/config/h8300/crtn.S b/libgcc/config/h8300/crtn.S
new file mode 100644
index 00000000000..7a591694563
--- /dev/null
+++ b/libgcc/config/h8300/crtn.S
@@ -0,0 +1,53 @@
+/* Copyright (C) 2001, 2009, 2011 Free Software Foundation, Inc.
+ This file was adapted from glibc sources.
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* See an explanation about .init and .fini in crti.S. */
+
+#ifdef __H8300H__
+#ifdef __NORMAL_MODE__
+ .h8300hn
+#else
+ .h8300h
+#endif
+#endif
+
+#ifdef __H8300S__
+#ifdef __NORMAL_MODE__
+ .h8300sn
+#else
+ .h8300s
+#endif
+#endif
+#ifdef __H8300SX__
+#ifdef __NORMAL_MODE__
+ .h8300sxn
+#else
+ .h8300sx
+#endif
+#endif
+ .section .init, "ax", @progbits
+ rts
+
+ .section .fini, "ax", @progbits
+ rts
diff --git a/gcc/config/h8300/ctzhi2.c b/libgcc/config/h8300/ctzhi2.c
index ba6f8e9086f..ba6f8e9086f 100644
--- a/gcc/config/h8300/ctzhi2.c
+++ b/libgcc/config/h8300/ctzhi2.c
diff --git a/libgcc/config/h8300/fixunssfsi.c b/libgcc/config/h8300/fixunssfsi.c
new file mode 100644
index 00000000000..940d0c6dc6a
--- /dev/null
+++ b/libgcc/config/h8300/fixunssfsi.c
@@ -0,0 +1,41 @@
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 1992, 2001, 2002, 2003, 2004, 2009, 2011
+ 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* The libgcc2.c implementation gets confused by our type setup and creates
+ a directly recursive call, so we do our own implementation. For
+ the H8/300, that's in lib1funcs.S, for H8/300H and H8S, it's here. */
+
+#ifndef __H8300__
+long __fixunssfsi (float a);
+
+long
+__fixunssfsi (float a)
+{
+ if (a >= (float) 32768L)
+ return (long) (a - 32768L) + 32768L;
+ return (long) a;
+}
+#endif
diff --git a/gcc/config/h8300/lib1funcs.asm b/libgcc/config/h8300/lib1funcs.S
index 1b75b73269d..1b75b73269d 100644
--- a/gcc/config/h8300/lib1funcs.asm
+++ b/libgcc/config/h8300/lib1funcs.S
diff --git a/gcc/config/h8300/parityhi2.c b/libgcc/config/h8300/parityhi2.c
index d58cb89b5c7..d58cb89b5c7 100644
--- a/gcc/config/h8300/parityhi2.c
+++ b/libgcc/config/h8300/parityhi2.c
diff --git a/gcc/config/h8300/popcounthi2.c b/libgcc/config/h8300/popcounthi2.c
index 47be193b38d..47be193b38d 100644
--- a/gcc/config/h8300/popcounthi2.c
+++ b/libgcc/config/h8300/popcounthi2.c
diff --git a/libgcc/config/h8300/t-h8300 b/libgcc/config/h8300/t-h8300
new file mode 100644
index 00000000000..750529d92c2
--- /dev/null
+++ b/libgcc/config/h8300/t-h8300
@@ -0,0 +1,13 @@
+LIB1ASMSRC = h8300/lib1funcs.S
+LIB1ASMFUNCS = _cmpsi2 _ucmpsi2 _divhi3 _divsi3 _mulhi3 _mulsi3 \
+ _fixunssfsi_asm
+
+LIB2ADD = \
+ $(srcdir)/config/h8300/clzhi2.c \
+ $(srcdir)/config/h8300/ctzhi2.c \
+ $(srcdir)/config/h8300/parityhi2.c \
+ $(srcdir)/config/h8300/popcounthi2.c \
+ $(srcdir)/config/h8300/fixunssfsi.c
+
+# We do not have DF type, so fake out the libgcc2 compilation.
+HOST_LIBGCC2_CFLAGS = -DDF=SF
diff --git a/libgcc/config/i386/cygming-crtbegin.c b/libgcc/config/i386/cygming-crtbegin.c
new file mode 100644
index 00000000000..b589841fd01
--- /dev/null
+++ b/libgcc/config/i386/cygming-crtbegin.c
@@ -0,0 +1,136 @@
+/* crtbegin object for windows32 targets.
+ Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+
+ Contributed 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Target machine header files require this define. */
+#define IN_LIBGCC2
+
+#include "auto-host.h"
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "libgcc_tm.h"
+#include "unwind-dw2-fde.h"
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#ifndef LIBGCC_SONAME
+#define LIBGCC_SONAME "libgcc_s.dll"
+#endif
+
+#ifndef LIBGCJ_SONAME
+#define LIBGCJ_SONAME "libgcj_s.dll"
+#endif
+
+
+/* Make the declarations weak. This is critical for
+ _Jv_RegisterClasses because it lives in libgcj.a */
+extern void __register_frame_info (const void *, struct object *)
+ TARGET_ATTRIBUTE_WEAK;
+extern void *__deregister_frame_info (const void *)
+ TARGET_ATTRIBUTE_WEAK;
+extern void _Jv_RegisterClasses (const void *) TARGET_ATTRIBUTE_WEAK;
+
+#if defined(HAVE_LD_RO_RW_SECTION_MIXING)
+# define EH_FRAME_SECTION_CONST const
+#else
+# define EH_FRAME_SECTION_CONST
+#endif
+
+/* Stick a label at the beginning of the frame unwind info so we can
+ register/deregister it with the exception handling library code. */
+#if DWARF2_UNWIND_INFO
+static EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
+ __attribute__((used, section(EH_FRAME_SECTION_NAME), aligned(4)))
+ = { };
+
+static struct object obj;
+#endif
+
+#if TARGET_USE_JCR_SECTION
+static void *__JCR_LIST__[]
+ __attribute__ ((used, section(JCR_SECTION_NAME), aligned(4)))
+ = { };
+#endif
+
+/* Pull in references from libgcc.a(unwind-dw2-fde.o) in the
+ startfile. These are referenced by a ctor and dtor in crtend.o. */
+extern void __gcc_register_frame (void);
+extern void __gcc_deregister_frame (void);
+
+void
+__gcc_register_frame (void)
+{
+#if DWARF2_UNWIND_INFO
+/* Weak undefined symbols won't be pulled in from dlls; hence
+ we first test if the dll is already loaded and, if so,
+ get the symbol's address at run-time. If the dll is not loaded,
+ fallback to weak linkage to static archive. */
+
+ void (*register_frame_fn) (const void *, struct object *);
+ HANDLE h = GetModuleHandle (LIBGCC_SONAME);
+ if (h)
+ register_frame_fn = (void (*) (const void *, struct object *))
+ GetProcAddress (h, "__register_frame_info");
+ else
+ register_frame_fn = __register_frame_info;
+ if (register_frame_fn)
+ register_frame_fn (__EH_FRAME_BEGIN__, &obj);
+#endif
+
+#if TARGET_USE_JCR_SECTION
+ if (__JCR_LIST__[0])
+ {
+ void (*register_class_fn) (const void *);
+ HANDLE h = GetModuleHandle (LIBGCJ_SONAME);
+ if (h)
+ register_class_fn = (void (*) (const void *))
+ GetProcAddress (h, "_Jv_RegisterClasses");
+ else
+ register_class_fn = _Jv_RegisterClasses;
+
+ if (register_class_fn)
+ register_class_fn (__JCR_LIST__);
+ }
+#endif
+}
+
+void
+__gcc_deregister_frame (void)
+{
+#if DWARF2_UNWIND_INFO
+ void * (*deregister_frame_fn) (const void *);
+ HANDLE h = GetModuleHandle (LIBGCC_SONAME);
+ if (h)
+ deregister_frame_fn = (void* (*) (const void *))
+ GetProcAddress (h, "__deregister_frame_info");
+ else
+ deregister_frame_fn = __deregister_frame_info;
+ if (deregister_frame_fn)
+ deregister_frame_fn (__EH_FRAME_BEGIN__);
+#endif
+}
diff --git a/libgcc/config/i386/cygming-crtend.c b/libgcc/config/i386/cygming-crtend.c
new file mode 100644
index 00000000000..ea53c84f6f1
--- /dev/null
+++ b/libgcc/config/i386/cygming-crtend.c
@@ -0,0 +1,89 @@
+/* crtend object for windows32 targets.
+ Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+
+ Contributed 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* Target machine header files require this define. */
+#define IN_LIBGCC2
+
+/* auto-host.h is needed by cygming.h for HAVE_GAS_WEAK and here
+ for HAVE_LD_RO_RW_SECTION_MIXING. */
+#include "auto-host.h"
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "libgcc_tm.h"
+#include "unwind-dw2-fde.h"
+
+#if defined(HAVE_LD_RO_RW_SECTION_MIXING)
+# define EH_FRAME_SECTION_CONST const
+#else
+# define EH_FRAME_SECTION_CONST
+#endif
+
+#if DWARF2_UNWIND_INFO
+/* Terminate the frame unwind info section with a 0 as a sentinel;
+ this would be the 'length' field in a real FDE. */
+
+static EH_FRAME_SECTION_CONST int __FRAME_END__[]
+ __attribute__ ((used, section(EH_FRAME_SECTION_NAME),
+ aligned(4)))
+ = { 0 };
+#endif
+
+#if TARGET_USE_JCR_SECTION
+/* Null terminate the .jcr section array. */
+static void *__JCR_END__[1]
+ __attribute__ ((used, section(JCR_SECTION_NAME),
+ aligned(sizeof(void *))))
+ = { 0 };
+#endif
+
+extern void __gcc_register_frame (void);
+extern void __gcc_deregister_frame (void);
+
+static void register_frame_ctor (void) __attribute__ ((constructor (0)));
+
+static void
+register_frame_ctor (void)
+{
+ __gcc_register_frame ();
+#if DEFAULT_USE_CXA_ATEXIT
+ /* If we use the __cxa_atexit method to register C++ dtors
+ at object construction, also use atexit to register eh frame
+ info cleanup. */
+ atexit (__gcc_deregister_frame);
+#endif
+}
+
+#if !DEFAULT_USE_CXA_ATEXIT
+static void deregister_frame_dtor (void) __attribute__ ((destructor (0)));
+
+static void
+deregister_frame_dtor (void)
+{
+ __gcc_deregister_frame ();
+}
+#endif
diff --git a/gcc/config/i386/cygwin.asm b/libgcc/config/i386/cygwin.S
index 8f9c486850e..8f9c486850e 100644
--- a/gcc/config/i386/cygwin.asm
+++ b/libgcc/config/i386/cygwin.S
diff --git a/libgcc/config/i386/gthr-win32.c b/libgcc/config/i386/gthr-win32.c
new file mode 100644
index 00000000000..ab1b69fd4cf
--- /dev/null
+++ b/libgcc/config/i386/gthr-win32.c
@@ -0,0 +1,261 @@
+/* Implementation of W32-specific threads compatibility routines for
+ libgcc2. */
+
+/* Copyright (C) 1999, 2000, 2002, 2004, 2008, 2009, 2011
+ 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include <windows.h>
+#ifndef __GTHREAD_HIDE_WIN32API
+# define __GTHREAD_HIDE_WIN32API 1
+#endif
+#undef __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
+#define __GTHREAD_I486_INLINE_LOCK_PRIMITIVES
+#include "gthr-win32.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 are currently using a special mutex instead of the Critical
+ Sections, since Win9x does not support TryEnterCriticalSection
+ (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 *) __attribute__((unused)))
+{
+ 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)
+{
+ if (TlsSetValue (key, CONST_CAST2(void *, const void *, ptr)) != 0)
+ return 0;
+ else
+ return GetLastError ();
+}
+
+void
+__gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
+{
+ mutex->counter = -1;
+ mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
+}
+
+void
+__gthr_win32_mutex_destroy (__gthread_mutex_t *mutex)
+{
+ CloseHandle ((HANDLE) mutex->sema);
+}
+
+int
+__gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
+{
+ if (InterlockedIncrement (&mutex->counter) == 0 ||
+ WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
+ return 0;
+ else
+ {
+ /* WaitForSingleObject returns WAIT_FAILED, and we can only do
+ some best-effort cleanup here. */
+ InterlockedDecrement (&mutex->counter);
+ return 1;
+ }
+}
+
+int
+__gthr_win32_mutex_trylock (__gthread_mutex_t *mutex)
+{
+ if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
+ return 0;
+ else
+ return 1;
+}
+
+int
+__gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
+{
+ if (InterlockedDecrement (&mutex->counter) >= 0)
+ return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
+ else
+ return 0;
+}
+
+void
+__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
+{
+ mutex->counter = -1;
+ mutex->depth = 0;
+ mutex->owner = 0;
+ mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
+}
+
+int
+__gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
+{
+ DWORD me = GetCurrentThreadId();
+ if (InterlockedIncrement (&mutex->counter) == 0)
+ {
+ mutex->depth = 1;
+ mutex->owner = me;
+ }
+ else if (mutex->owner == me)
+ {
+ InterlockedDecrement (&mutex->counter);
+ ++(mutex->depth);
+ }
+ else if (WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
+ {
+ mutex->depth = 1;
+ mutex->owner = me;
+ }
+ else
+ {
+ /* WaitForSingleObject returns WAIT_FAILED, and we can only do
+ some best-effort cleanup here. */
+ InterlockedDecrement (&mutex->counter);
+ return 1;
+ }
+ return 0;
+}
+
+int
+__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
+{
+ DWORD me = GetCurrentThreadId();
+ if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
+ {
+ mutex->depth = 1;
+ mutex->owner = me;
+ }
+ else if (mutex->owner == me)
+ ++(mutex->depth);
+ else
+ return 1;
+
+ return 0;
+}
+
+int
+__gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
+{
+ --(mutex->depth);
+ if (mutex->depth == 0)
+ {
+ mutex->owner = 0;
+
+ if (InterlockedDecrement (&mutex->counter) >= 0)
+ return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
+ }
+
+ return 0;
+}
diff --git a/gcc/gthr-win32.h b/libgcc/config/i386/gthr-win32.h
index 53f8396cc81..53f8396cc81 100644
--- a/gcc/gthr-win32.h
+++ b/libgcc/config/i386/gthr-win32.h
diff --git a/gcc/config/i386/darwin-libgcc.10.4.ver b/libgcc/config/i386/libgcc-darwin.10.4.ver
index 67f5e239ca1..67f5e239ca1 100644
--- a/gcc/config/i386/darwin-libgcc.10.4.ver
+++ b/libgcc/config/i386/libgcc-darwin.10.4.ver
diff --git a/gcc/config/i386/darwin-libgcc.10.5.ver b/libgcc/config/i386/libgcc-darwin.10.5.ver
index eeec9fbfcdf..eeec9fbfcdf 100644
--- a/gcc/config/i386/darwin-libgcc.10.5.ver
+++ b/libgcc/config/i386/libgcc-darwin.10.5.ver
diff --git a/gcc/config/i386/libgcc-glibc.ver b/libgcc/config/i386/libgcc-glibc.ver
index e79d3267f6f..e79d3267f6f 100644
--- a/gcc/config/i386/libgcc-glibc.ver
+++ b/libgcc/config/i386/libgcc-glibc.ver
diff --git a/libgcc/config/i386/morestack.S b/libgcc/config/i386/morestack.S
index b09ac76d060..85c20ed7e93 100644
--- a/libgcc/config/i386/morestack.S
+++ b/libgcc/config/i386/morestack.S
@@ -139,44 +139,68 @@ __morestack:
.cfi_lsda 0x1b,.LLSDA1
#endif
- # Set up a normal backtrace.
- pushl %ebp
- .cfi_def_cfa_offset 8
- .cfi_offset %ebp, -8
- movl %esp, %ebp
- .cfi_def_cfa_register %ebp
-
# We return below with a ret $8. We will return to a single
# return instruction, which will return to the caller of our
# caller. We let the unwinder skip that single return
# instruction, and just return to the real caller.
- .cfi_offset 8, 8
+
+ # Here CFA points just past the return address on the stack,
+ # e.g., on function entry it is %esp + 4. Later we will
+ # change it to %ebp + 8, as set by .cfi_def_cfa_register and
+ # .cfi_def_cfa_offset above. The stack looks like this:
+ # CFA + 12: stack pointer after two returns
+ # CFA + 8: return address of morestack caller's caller
+ # CFA + 4: size of parameters
+ # CFA: new stack frame size
+ # CFA - 4: return address of this function
+ # CFA - 8: previous value of %ebp; %ebp points here
+ # We want to set %esp to the stack pointer after the double
+ # return, which is CFA + 12.
+ .cfi_offset 8, 8 # New PC stored at CFA + 8
.cfi_escape 0x15, 4, 0x7d # DW_CFA_val_offset_sf, %esp, 12/-4
+ # i.e., next %esp is CFA + 12
+
+ # Set up a normal backtrace.
+ pushl %ebp
+ .cfi_def_cfa_offset 8
+ .cfi_offset %ebp, -8
+ movl %esp,%ebp
+ .cfi_def_cfa_register %ebp
# In 32-bit mode the parameters are pushed on the stack. The
# argument size is pushed then the new stack frame size is
# pushed.
+ # Align stack to 16-byte boundary with enough space for saving
+ # registers and passing parameters to functions we call.
+ subl $40,%esp
+
+ # Because our cleanup code may need to clobber %ebx, we need
+ # to save it here so the unwinder can restore the value used
+ # by the caller. Note that we don't have to restore the
+ # register, since we don't change it, we just have to save it
+ # for the unwinder.
+ movl %ebx,-4(%ebp)
+ .cfi_offset %ebx, -12
+
# In 32-bit mode the registers %eax, %edx, and %ecx may be
# used for parameters, depending on the regparm and fastcall
# attributes.
- pushl %eax
- pushl %edx
- pushl %ecx
+ movl %eax,-8(%ebp)
+ movl %edx,-12(%ebp)
+ movl %ecx,-16(%ebp)
call __morestack_block_signals
- pushl 12(%ebp) # The size of the parameters.
+ movl 12(%ebp),%eax # The size of the parameters.
+ movl %eax,8(%esp)
leal 20(%ebp),%eax # Address of caller's parameters.
- pushl %eax
+ movl %eax,4(%esp)
addl $BACKOFF,8(%ebp) # Ask for backoff bytes.
leal 8(%ebp),%eax # The address of the new frame size.
- pushl %eax
+ movl %eax,(%esp)
- # Note that %esp is exactly 32 bytes below the CFA -- perfect for
- # a 16-byte aligned stack. That said, we still ought to compile
- # generic-morestack.c with -mpreferred-stack-boundary=2. FIXME.
call __generic_morestack
movl %eax,%esp # Switch to the new stack.
@@ -191,8 +215,8 @@ __morestack:
call __morestack_unblock_signals
- movl -8(%ebp),%edx # Restore registers.
- movl -12(%ebp),%ecx
+ movl -12(%ebp),%edx # Restore registers.
+ movl -16(%ebp),%ecx
movl 4(%ebp),%eax # Increment the return address
cmpb $0xc3,(%eax) # to skip the ret instruction;
@@ -200,12 +224,12 @@ __morestack:
addl $2,%eax
1: inc %eax
- movl %eax,-8(%ebp) # Store return address in an
+ movl %eax,-12(%ebp) # Store return address in an
# unused slot.
- movl -4(%ebp),%eax # Restore the last register.
+ movl -8(%ebp),%eax # Restore the last register.
- call *-8(%ebp) # Call our caller!
+ call *-12(%ebp) # Call our caller!
# The caller will return here, as predicted.
@@ -255,9 +279,13 @@ __morestack:
popl %eax
.cfi_remember_state
+
+ # We never changed %ebx, so we don't have to actually restore it.
+ .cfi_restore %ebx
+
popl %ebp
.cfi_restore %ebp
- .cfi_def_cfa %esp, 12
+ .cfi_def_cfa %esp, 4
ret $8 # Return to caller, which will
# immediately return. Pop
# arguments as we go.
@@ -300,13 +328,6 @@ __morestack:
.cfi_lsda 0x1b,.LLSDA1
#endif
- # Set up a normal backtrace.
- pushq %rbp
- .cfi_def_cfa_offset 16
- .cfi_offset %rbp, -16
- movq %rsp, %rbp
- .cfi_def_cfa_register %rbp
-
# We will return a single return instruction, which will
# return to the caller of our caller. Let the unwinder skip
# that single return instruction, and just return to the real
@@ -314,6 +335,13 @@ __morestack:
.cfi_offset 16, 0
.cfi_escape 0x15, 7, 0x7f # DW_CFA_val_offset_sf, %esp, 8/-8
+ # Set up a normal backtrace.
+ pushq %rbp
+ .cfi_def_cfa_offset 16
+ .cfi_offset %rbp, -16
+ movq %rsp, %rbp
+ .cfi_def_cfa_register %rbp
+
# In 64-bit mode the new stack frame size is passed in r10
# and the argument size is passed in r11.
diff --git a/libgcc/config/i386/t-chkstk b/libgcc/config/i386/t-chkstk
new file mode 100644
index 00000000000..822981faab8
--- /dev/null
+++ b/libgcc/config/i386/t-chkstk
@@ -0,0 +1,2 @@
+LIB1ASMSRC = i386/cygwin.S
+LIB1ASMFUNCS = _chkstk _chkstk_ms
diff --git a/libgcc/config/i386/t-cygming b/libgcc/config/i386/t-cygming
index 048cadbd5a1..d76004c48e5 100644
--- a/libgcc/config/i386/t-cygming
+++ b/libgcc/config/i386/t-cygming
@@ -1,11 +1,14 @@
+# If we are building next to winsup, this will let us find the real
+# limits.h when building libgcc2. Otherwise, winsup must be installed
+# first.
+LIBGCC2_INCLUDES = -I$(srcdir)/../winsup/w32api/include
+
CUSTOM_CRTSTUFF = yes
-crtbegin.o: $(gcc_srcdir)/config/i386/cygming-crtbegin.c
- $(crt_compile) -fno-omit-frame-pointer -c \
- $(gcc_srcdir)/config/i386/cygming-crtbegin.c
+crtbegin.o: $(srcdir)/config/i386/cygming-crtbegin.c
+ $(crt_compile) -fno-omit-frame-pointer -c $<
# We intentionally use a implementation-reserved init priority of 0,
# so allow the warning.
-crtend.o: $(gcc_srcdir)/config/i386/cygming-crtend.c
- $(crt_compile) -fno-omit-frame-pointer -Wno-error -c \
- $(gcc_srcdir)/config/i386/cygming-crtend.c
+crtend.o: $(srcdir)/config/i386/cygming-crtend.c
+ $(crt_compile) -fno-omit-frame-pointer -Wno-error -c $<
diff --git a/libgcc/config/i386/t-cygwin b/libgcc/config/i386/t-cygwin
new file mode 100644
index 00000000000..f85ec24220e
--- /dev/null
+++ b/libgcc/config/i386/t-cygwin
@@ -0,0 +1,19 @@
+# If we are building next to winsup, this will let us find the real
+# limits.h when building libgcc2. Otherwise, winsup must be installed
+# first.
+LIBGCC2_INCLUDES += -I$(srcdir)/../winsup/include \
+ -I$(srcdir)/../winsup/cygwin/include
+
+# Cygwin-specific parts of LIB_SPEC
+SHLIB_LC = -lcygwin -ladvapi32 -lshell32 -luser32 -lkernel32
+
+# We have already included one of the t-{dw2,sjlj}-eh fragments for EH_MODEL
+SHLIB_EH_EXTENSION = $(subst -dw2,,-$(EH_MODEL))
+
+# Cygwin uses different conventions than MinGW; override generic SHLIB_ def'ns here.
+SHLIB_IMPLIB = @shlib_base_name@$(SHLIB_EXT).a
+SHLIB_SONAME = cyggcc_s$(SHLIB_EH_EXTENSION)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
+# This must match the definitions of SHLIB_SONAME/SHLIB_SOVERSION and LIBGCC_SONAME.
+# We'd like to use SHLIB_SONAME here too, and we can, since
+# we don't rely on shlib_base_name substitution for it.
+SHLIB_MKMAP_OPTS = -v pe_dll=$(SHLIB_SONAME)
diff --git a/libgcc/config/i386/t-darwin b/libgcc/config/i386/t-darwin
index 4578f74c3fa..5f2c69725d0 100644
--- a/libgcc/config/i386/t-darwin
+++ b/libgcc/config/i386/t-darwin
@@ -1 +1,3 @@
-SHLIB_VERPFX = $(gcc_srcdir)/config/i386/darwin-libgcc
+LIB2_SIDITI_CONV_FUNCS = yes
+LIB2ADD = $(srcdir)/config/darwin-64.c
+LIB2FUNCS_EXCLUDE = _fixtfdi _fixunstfdi _floatditf _floatunditf
diff --git a/libgcc/config/i386/t-darwin64 b/libgcc/config/i386/t-darwin64
index 4578f74c3fa..30cf58b38f9 100644
--- a/libgcc/config/i386/t-darwin64
+++ b/libgcc/config/i386/t-darwin64
@@ -1 +1,2 @@
-SHLIB_VERPFX = $(gcc_srcdir)/config/i386/darwin-libgcc
+LIB2_SIDITI_CONV_FUNCS = yes
+LIB2ADD = $(srcdir)/config/darwin-64.c
diff --git a/libgcc/config/i386/t-dlldir b/libgcc/config/i386/t-dlldir
new file mode 100644
index 00000000000..d2cf39bddd6
--- /dev/null
+++ b/libgcc/config/i386/t-dlldir
@@ -0,0 +1,2 @@
+# In a native build, target DLLs go in bindir, where they can be executed.
+SHLIB_DLLDIR = $(bindir)
diff --git a/libgcc/config/i386/t-dlldir-x b/libgcc/config/i386/t-dlldir-x
new file mode 100644
index 00000000000..0f8c29b4e90
--- /dev/null
+++ b/libgcc/config/i386/t-dlldir-x
@@ -0,0 +1,3 @@
+# In a cross build, bindir contains host not target binaries, so target DLLs
+# instead go in toolexeclibdir, alongside other target binaries and static libs.
+SHLIB_DLLDIR = $(toolexeclibdir)
diff --git a/gcc/config/i386/t-dw2-eh b/libgcc/config/i386/t-dw2-eh
index ffcc39aea33..ffcc39aea33 100644
--- a/gcc/config/i386/t-dw2-eh
+++ b/libgcc/config/i386/t-dw2-eh
diff --git a/libgcc/config/i386/t-gthr-win32 b/libgcc/config/i386/t-gthr-win32
new file mode 100644
index 00000000000..e7380d6f6e4
--- /dev/null
+++ b/libgcc/config/i386/t-gthr-win32
@@ -0,0 +1,2 @@
+# We hide calls to w32api needed for w32 thread support here:
+LIB2ADD = $(srcdir)/config/i386/gthr-win32.c
diff --git a/libgcc/config/i386/t-interix b/libgcc/config/i386/t-interix
new file mode 100644
index 00000000000..8889e7c6c63
--- /dev/null
+++ b/libgcc/config/i386/t-interix
@@ -0,0 +1,3 @@
+# We need to override LIBGCC2_DEBUG_CFLAGS so libgcc2 will be
+# built without debugging information
+LIBGCC2_DEBUG_CFLAGS =
diff --git a/libgcc/config/i386/t-linux b/libgcc/config/i386/t-linux
new file mode 100644
index 00000000000..29b4c223983
--- /dev/null
+++ b/libgcc/config/i386/t-linux
@@ -0,0 +1,4 @@
+# On 64bit we do not need any exports for glibc for 64-bit libgcc_s.
+# Need to support TImode for x86. Override the settings from
+# t-slibgcc-elf-ver and t-linux
+SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/i386/libgcc-glibc.ver
diff --git a/gcc/config/i386/t-mingw-pthread b/libgcc/config/i386/t-mingw-pthread
index 622ef82be6e..622ef82be6e 100644
--- a/gcc/config/i386/t-mingw-pthread
+++ b/libgcc/config/i386/t-mingw-pthread
diff --git a/libgcc/config/i386/t-mingw32 b/libgcc/config/i386/t-mingw32
new file mode 100644
index 00000000000..bfdef6723ce
--- /dev/null
+++ b/libgcc/config/i386/t-mingw32
@@ -0,0 +1,2 @@
+# MinGW-specific parts of LIB_SPEC
+SHLIB_LC = -lmingwthrd -lmingw32 -lmingwex -lmoldname -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32
diff --git a/libgcc/config/i386/t-nto b/libgcc/config/i386/t-nto
new file mode 100644
index 00000000000..44c90661824
--- /dev/null
+++ b/libgcc/config/i386/t-nto
@@ -0,0 +1,3 @@
+HOST_LIBGCC2_CFLAGS += -fexceptions
+
+CRTSTUFF_T_CFLAGS = -fno-omit-frame-pointer $(PICFLAG)
diff --git a/gcc/config/i386/t-sjlj-eh b/libgcc/config/i386/t-sjlj-eh
index c9085f43216..c9085f43216 100644
--- a/gcc/config/i386/t-sjlj-eh
+++ b/libgcc/config/i386/t-sjlj-eh
diff --git a/libgcc/config/i386/t-slibgcc-cygming b/libgcc/config/i386/t-slibgcc-cygming
new file mode 100644
index 00000000000..3bee8b98084
--- /dev/null
+++ b/libgcc/config/i386/t-slibgcc-cygming
@@ -0,0 +1,58 @@
+# Build a shared libgcc library for PECOFF with a DEF file
+# with the GNU linker.
+#
+# mkmap-flat.awk is used with the pe_dll option to produce a DEF instead
+# of an ELF map file.
+#
+# Warning: If SHLIB_SOVERSION or SHLIB_SONAME are updated, LIBGCC_SONAME
+# in mingw32.h and SHLIB_MKMAP_OPTS below must be updated also.
+
+SHLIB_EXT = .dll
+SHLIB_IMPLIB = @shlib_base_name@.a
+SHLIB_SOVERSION = 1
+SHLIB_SONAME = @shlib_base_name@_$(EH_MODEL)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
+SHLIB_MAP = @shlib_map_file@
+SHLIB_OBJS = @shlib_objs@
+SHLIB_DIR = @multilib_dir@/shlib
+SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
+# SHLIB_DLLDIR is defined by including one of either t-dlldir or t-dlldir-x
+# (native/cross build respectively) in the tmake_file list in
+# libgcc/config.host.
+ifndef SHLIB_DLLDIR
+$(error SHLIB_DLLDIR must be defined)
+endif
+ifndef SHLIB_PTHREAD_CFLAG
+SHLIB_PTHREAD_CFLAG =
+endif
+ifndef SHLIB_PTHREAD_LDFLAG
+SHLIB_PTHREAD_LDFLAG =
+endif
+
+SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
+ if [ ! -d $(SHLIB_DIR) ]; then \
+ mkdir $(SHLIB_DIR); \
+ else true; fi && \
+ $(CC) $(LIBGCC2_CFLAGS) $(SHLIB_PTHREAD_CFLAG) \
+ -shared -nodefaultlibs \
+ $(SHLIB_MAP).def \
+ -Wl,--out-implib,$(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \
+ -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
+ $(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) && \
+ if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
+ mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
+ $(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
+ else true; fi && \
+ mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \
+ mv $(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp $(SHLIB_DIR)/$(SHLIB_IMPLIB)
+SHLIB_INSTALL = \
+ $(mkinstalldirs) $(DESTDIR)$(SHLIB_DLLDIR) \
+ $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
+ $(INSTALL) $(SHLIB_DIR)/$(SHLIB_SONAME) \
+ $(DESTDIR)$(SHLIB_DLLDIR)/$(SHLIB_SONAME); \
+ $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_IMPLIB) \
+ $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_IMPLIB)
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
+# We'd like to use SHLIB_SONAME here too, but shlib_base_name
+# does not get substituted before mkmap-flat.awk is run.
+SHLIB_MKMAP_OPTS = -v pe_dll=libgcc_s_$(EH_MODEL)-$(SHLIB_SOVERSION)$(SHLIB_EXT)
+SHLIB_MAPFILES = libgcc-std.ver
diff --git a/libgcc/config/i386/t-sol2 b/libgcc/config/i386/t-sol2
index 1102146a589..b9cfb00ef49 100644
--- a/libgcc/config/i386/t-sol2
+++ b/libgcc/config/i386/t-sol2
@@ -7,7 +7,7 @@
# We must also enable optimization to avoid having any code appear after
# the call & alignment statement, but before we switch back to the
# .text section.
-CRTSTUFF_T_CFLAGS = -fPIC -O2
+CRTSTUFF_T_CFLAGS = $(PICFLAG) -O2
# Add support for the introduction of 128-bit long double.
SHLIB_MAPFILES += $(srcdir)/config/i386/libgcc-sol2.ver
diff --git a/libgcc/config/ia64/__divxf3.S b/libgcc/config/ia64/__divxf3.S
new file mode 100644
index 00000000000..9cba8f59423
--- /dev/null
+++ b/libgcc/config/ia64/__divxf3.S
@@ -0,0 +1,11 @@
+#ifdef SHARED
+#define __divtf3 __divtf3_compat
+#endif
+
+#define L__divxf3
+#include "config/ia64/lib1funcs.S"
+
+#ifdef SHARED
+#undef __divtf3
+.symver __divtf3_compat, __divtf3@GCC_3.0
+#endif
diff --git a/libgcc/config/ia64/__divxf3.asm b/libgcc/config/ia64/__divxf3.asm
deleted file mode 100644
index f741bdaf9bc..00000000000
--- a/libgcc/config/ia64/__divxf3.asm
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifdef SHARED
-#define __divtf3 __divtf3_compat
-#endif
-
-#define L__divxf3
-#include "config/ia64/lib1funcs.asm"
-
-#ifdef SHARED
-#undef __divtf3
-.symver __divtf3_compat, __divtf3@GCC_3.0
-#endif
diff --git a/libgcc/config/ia64/_fixtfdi.S b/libgcc/config/ia64/_fixtfdi.S
new file mode 100644
index 00000000000..863b70f7edc
--- /dev/null
+++ b/libgcc/config/ia64/_fixtfdi.S
@@ -0,0 +1,11 @@
+#ifdef SHARED
+#define __fixtfti __fixtfti_compat
+#endif
+
+#define L_fixtfdi
+#include "config/ia64/lib1funcs.S"
+
+#ifdef SHARED
+#undef __fixtfti
+.symver __fixtfti_compat, __fixtfti@GCC_3.0
+#endif
diff --git a/libgcc/config/ia64/_fixtfdi.asm b/libgcc/config/ia64/_fixtfdi.asm
deleted file mode 100644
index 4d13c808c51..00000000000
--- a/libgcc/config/ia64/_fixtfdi.asm
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifdef SHARED
-#define __fixtfti __fixtfti_compat
-#endif
-
-#define L_fixtfdi
-#include "config/ia64/lib1funcs.asm"
-
-#ifdef SHARED
-#undef __fixtfti
-.symver __fixtfti_compat, __fixtfti@GCC_3.0
-#endif
diff --git a/libgcc/config/ia64/_fixunstfdi.S b/libgcc/config/ia64/_fixunstfdi.S
new file mode 100644
index 00000000000..aac6a284eaa
--- /dev/null
+++ b/libgcc/config/ia64/_fixunstfdi.S
@@ -0,0 +1,11 @@
+#ifdef SHARED
+#define __fixunstfti __fixunstfti_compat
+#endif
+
+#define L_fixunstfdi
+#include "config/ia64/lib1funcs.S"
+
+#ifdef SHARED
+#undef __fixunstfti
+.symver __fixunstfti_compat, __fixunstfti@GCC_3.0
+#endif
diff --git a/libgcc/config/ia64/_fixunstfdi.asm b/libgcc/config/ia64/_fixunstfdi.asm
deleted file mode 100644
index b722d9e90dc..00000000000
--- a/libgcc/config/ia64/_fixunstfdi.asm
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifdef SHARED
-#define __fixunstfti __fixunstfti_compat
-#endif
-
-#define L_fixunstfdi
-#include "config/ia64/lib1funcs.asm"
-
-#ifdef SHARED
-#undef __fixunstfti
-.symver __fixunstfti_compat, __fixunstfti@GCC_3.0
-#endif
diff --git a/libgcc/config/ia64/_floatditf.S b/libgcc/config/ia64/_floatditf.S
new file mode 100644
index 00000000000..e37404d26d5
--- /dev/null
+++ b/libgcc/config/ia64/_floatditf.S
@@ -0,0 +1,11 @@
+#ifdef SHARED
+#define __floattitf __floattitf_compat
+#endif
+
+#define L_floatditf
+#include "config/ia64/lib1funcs.S"
+
+#ifdef SHARED
+#undef __floattitf
+.symver __floattitf_compat, __floattitf@GCC_3.0
+#endif
diff --git a/libgcc/config/ia64/_floatditf.asm b/libgcc/config/ia64/_floatditf.asm
deleted file mode 100644
index 21d77028176..00000000000
--- a/libgcc/config/ia64/_floatditf.asm
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifdef SHARED
-#define __floattitf __floattitf_compat
-#endif
-
-#define L_floatditf
-#include "config/ia64/lib1funcs.asm"
-
-#ifdef SHARED
-#undef __floattitf
-.symver __floattitf_compat, __floattitf@GCC_3.0
-#endif
diff --git a/gcc/config/ia64/crtbegin.asm b/libgcc/config/ia64/crtbegin.S
index 638489990d5..638489990d5 100644
--- a/gcc/config/ia64/crtbegin.asm
+++ b/libgcc/config/ia64/crtbegin.S
diff --git a/gcc/config/ia64/crtend.asm b/libgcc/config/ia64/crtend.S
index a904af9cfd9..a904af9cfd9 100644
--- a/gcc/config/ia64/crtend.asm
+++ b/libgcc/config/ia64/crtend.S
diff --git a/libgcc/config/ia64/crti.S b/libgcc/config/ia64/crti.S
new file mode 100644
index 00000000000..c15ff662bbe
--- /dev/null
+++ b/libgcc/config/ia64/crti.S
@@ -0,0 +1,53 @@
+# Copyright (C) 2000, 2001, 2008, 2009, 2011 Free Software Foundation, Inc.
+# Written By Timothy Wall
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file just make a stack frame for the contents of the .fini and
+# .init sections. Users may put any desired instructions in those
+# sections.
+
+ .section ".init"
+ .align 16
+ .global _init
+_init:
+ .prologue 14, 33
+ .save ar.pfs, r34
+ alloc r34 = ar.pfs, 0, 4, 0, 0
+ .vframe r35
+ mov r35 = r12
+ .save rp, r33
+ mov r33 = b0
+ .body
+
+ .section ".fini"
+ .align 16
+ .global _fini
+_fini:
+ .prologue 14, 33
+ .save ar.pfs, r34
+ alloc r34 = ar.pfs, 0, 4, 0, 0
+ .vframe r35
+ mov r35 = r12
+ .save rp, r33
+ mov r33 = b0
+ .body
+
+# end of crti.S
diff --git a/libgcc/config/ia64/crtn.S b/libgcc/config/ia64/crtn.S
new file mode 100644
index 00000000000..d44abbea3c7
--- /dev/null
+++ b/libgcc/config/ia64/crtn.S
@@ -0,0 +1,43 @@
+# Copyright (C) 2000, 2001, 2008, 2009, 2011 Free Software Foundation, Inc.
+# Written By Timothy Wall
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file just makes sure that the .fini and .init sections do in
+# fact return. Users may put any desired instructions in those sections.
+# This file is the last thing linked into any executable.
+
+ .section ".init"
+ ;;
+ mov ar.pfs = r34
+ mov b0 = r33
+ .restore sp
+ mov r12 = r35
+ br.ret.sptk.many b0
+
+ .section ".fini"
+ ;;
+ mov ar.pfs = r34
+ mov b0 = r33
+ .restore sp
+ mov r12 = r35
+ br.ret.sptk.many b0
+
+# end of crtn.S
diff --git a/libgcc/config/ia64/fde-vms.c b/libgcc/config/ia64/fde-vms.c
index c9ac5d28076..234cb3d6b3b 100644
--- a/libgcc/config/ia64/fde-vms.c
+++ b/libgcc/config/ia64/fde-vms.c
@@ -29,6 +29,7 @@
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
diff --git a/gcc/config/ia64/lib1funcs.asm b/libgcc/config/ia64/lib1funcs.S
index b7eaa6eca3c..b7eaa6eca3c 100644
--- a/gcc/config/ia64/lib1funcs.asm
+++ b/libgcc/config/ia64/lib1funcs.S
diff --git a/gcc/config/ia64/libgcc-glibc.ver b/libgcc/config/ia64/libgcc-glibc.ver
index 34a69618d1b..34a69618d1b 100644
--- a/gcc/config/ia64/libgcc-glibc.ver
+++ b/libgcc/config/ia64/libgcc-glibc.ver
diff --git a/gcc/config/ia64/libgcc-ia64.ver b/libgcc/config/ia64/libgcc-ia64.ver
index 11c1fe629bd..11c1fe629bd 100644
--- a/gcc/config/ia64/libgcc-ia64.ver
+++ b/libgcc/config/ia64/libgcc-ia64.ver
diff --git a/gcc/config/ia64/quadlib.c b/libgcc/config/ia64/quadlib.c
index f9ee30b587c..f9ee30b587c 100644
--- a/gcc/config/ia64/quadlib.c
+++ b/libgcc/config/ia64/quadlib.c
diff --git a/libgcc/config/ia64/t-glibc b/libgcc/config/ia64/t-glibc
deleted file mode 100644
index df4fe9c4404..00000000000
--- a/libgcc/config/ia64/t-glibc
+++ /dev/null
@@ -1,3 +0,0 @@
-# Use system libunwind library on IA-64 GLIBC based system.
-LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
- $(srcdir)/unwind-compat.c
diff --git a/libgcc/config/ia64/t-hpux b/libgcc/config/ia64/t-hpux
index ef3387e7a61..ddc1135d737 100644
--- a/libgcc/config/ia64/t-hpux
+++ b/libgcc/config/ia64/t-hpux
@@ -1 +1,9 @@
+# On HP-UX we do not want _fixtfdi, _fixunstfdi, or _floatditf from
+# LIB1ASMSRC. These functions map the 128 bit conversion function names
+# to 80 bit conversions and were done for Linux backwards compatibility.
+LIB1ASMFUNCS := $(filter-out _fixtfdi _fixunstfdi _floatditf,$(LIB1ASMFUNCS))
+
+# Support routines for HP-UX 128 bit floats.
+LIB2ADD = $(srcdir)/config/ia64/quadlib.c $(srcdir)/floatunsitf.c
+
LIB2ADDEH = $(srcdir)/unwind-c.c
diff --git a/libgcc/config/ia64/t-ia64 b/libgcc/config/ia64/t-ia64
index 3ec5fc5db08..93f38da0ebf 100644
--- a/libgcc/config/ia64/t-ia64
+++ b/libgcc/config/ia64/t-ia64
@@ -1,15 +1,35 @@
+LIB1ASMSRC = ia64/lib1funcs.S
+
+# We use different names for the DImode div/mod files so that they won't
+# conflict with libgcc2.c files. We used to use __ia64 as a prefix, now
+# we use __ as the prefix. Note that L_divdi3 in libgcc2.c actually defines
+# a TImode divide function, so there is no actual overlap here between
+# libgcc2.c and lib1funcs.S.
+LIB1ASMFUNCS = __divxf3 __divdf3 __divsf3 \
+ __divdi3 __moddi3 __udivdi3 __umoddi3 \
+ __divsi3 __modsi3 __udivsi3 __umodsi3 __save_stack_nonlocal \
+ __nonlocal_goto __restore_stack_nonlocal __trampoline \
+ _fixtfdi _fixunstfdi _floatditf
+
+# ??? Hack to get -P option used when compiling lib1funcs.S, because Intel
+# assembler does not accept # line number as a comment.
+# ??? This breaks C++ pragma interface/implementation, which is used in the
+# C++ part of libgcc2, hence it had to be disabled. Must find some other way
+# to support the Intel assembler.
+#LIBGCC2_DEBUG_CFLAGS = -g1 -P
+
CUSTOM_CRTSTUFF = yes
# Assemble startup files.
-crtbegin.o: $(gcc_srcdir)/config/ia64/crtbegin.asm
- $(CC) $(compile_deps) -I. -I$(gcc_objdir) -c -x assembler-with-cpp \
- -o $@ $(gcc_srcdir)/config/ia64/crtbegin.asm
-crtend.o: $(gcc_srcdir)/config/ia64/crtend.asm
+# FIXME: -I$(gcc_objdir) is necessary to find auto-host.h. Really?
+crtbegin.o: $(srcdir)/config/ia64/crtbegin.S
+ $(CC) $(compile_deps) -I. -I$(gcc_objdir) -c -x assembler-with-cpp $<
+crtend.o: $(srcdir)/config/ia64/crtend.S
+ $(CC) $(compile_deps) -I. -I$(gcc_objdir) -c -x assembler-with-cpp $<
+crtbeginS.o: $(srcdir)/config/ia64/crtbegin.S
+ $(CC) $(compile_deps) -I. -I$(gcc_objdir) -c -x assembler-with-cpp \ -o $@ -DSHARED $<
+crtendS.o: $(srcdir)/config/ia64/crtend.S
$(CC) $(compile_deps) -I. -I$(gcc_objdir) -c -x assembler-with-cpp \
- -o $@ $(gcc_srcdir)/config/ia64/crtend.asm
-crtbeginS.o: $(gcc_srcdir)/config/ia64/crtbegin.asm
- $(CC) $(compile_deps) -I. -I$(gcc_objdir) -c -x assembler-with-cpp \
- -o $@ -DSHARED $(gcc_srcdir)/config/ia64/crtbegin.asm
-crtendS.o: $(gcc_srcdir)/config/ia64/crtend.asm
- $(CC) $(compile_deps) -I. -I$(gcc_objdir) -c -x assembler-with-cpp \
- -o $@ -DSHARED $(gcc_srcdir)/config/ia64/crtend.asm
+ -o $@ -DSHARED $<
+
+SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-ia64.ver
diff --git a/libgcc/config/ia64/t-linux b/libgcc/config/ia64/t-linux
new file mode 100644
index 00000000000..e6d72b94a87
--- /dev/null
+++ b/libgcc/config/ia64/t-linux
@@ -0,0 +1,5 @@
+# Use system libunwind library on IA-64 GLIBC based system.
+LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
+ $(srcdir)/unwind-compat.c
+
+SHLIB_MAPFILES += $(srcdir)/config/ia64/libgcc-glibc.ver
diff --git a/libgcc/config/ia64/t-glibc-libunwind b/libgcc/config/ia64/t-linux-libunwind
index 8b1736a2d67..8b1736a2d67 100644
--- a/libgcc/config/ia64/t-glibc-libunwind
+++ b/libgcc/config/ia64/t-linux-libunwind
diff --git a/libgcc/config/ia64/t-slibgcc-hpux b/libgcc/config/ia64/t-slibgcc-hpux
new file mode 100644
index 00000000000..27c7a661b1e
--- /dev/null
+++ b/libgcc/config/ia64/t-slibgcc-hpux
@@ -0,0 +1,6 @@
+# Build a shared libgcc library with the HP-UX linker on IA64.
+
+SHLIB_SOVERSION = 0
+# Must include -lunwind in the link, so that libgcc_s.so has the necessary
+# DT_NEEDED entry for libunwind.
+SHLIB_LC += -lunwind
diff --git a/libgcc/config/ia64/t-softfp-compat b/libgcc/config/ia64/t-softfp-compat
index d3dad68c48f..00f45d51cd0 100644
--- a/libgcc/config/ia64/t-softfp-compat
+++ b/libgcc/config/ia64/t-softfp-compat
@@ -3,5 +3,5 @@
# Replace __dvxf3 _fixtfdi _fixunstfdi _floatditf
libgcc1-tf-functions = __divxf3 _fixtfdi _fixunstfdi _floatditf
LIB1ASMFUNCS := $(filter-out $(libgcc1-tf-functions), $(LIB1ASMFUNCS))
-libgcc1-tf-compats = $(addsuffix .asm, $(libgcc1-tf-functions))
+libgcc1-tf-compats = $(addsuffix .S, $(libgcc1-tf-functions))
LIB2ADD += $(addprefix $(srcdir)/config/ia64/, $(libgcc1-tf-compats))
diff --git a/libgcc/config/ia64/t-vms b/libgcc/config/ia64/t-vms
index 9bc933adfe0..140c748b771 100644
--- a/libgcc/config/ia64/t-vms
+++ b/libgcc/config/ia64/t-vms
@@ -1 +1,7 @@
+CRTSTUFF_T_CFLAGS = -O0
+CRTSTUFF_T_CFLAGS_S = -O0
+
+crtinitS.o: $(srcdir)/config/ia64/vms-crtinit.S
+ $(gcc_compile) -c -x assembler-with-cpp $<
+
LIB2ADDEH += $(srcdir)/config/ia64/fde-vms.c
diff --git a/libgcc/config/ia64/unwind-ia64.c b/libgcc/config/ia64/unwind-ia64.c
index e9ddfca8864..ca5c2670bf2 100644
--- a/libgcc/config/ia64/unwind-ia64.c
+++ b/libgcc/config/ia64/unwind-ia64.c
@@ -31,6 +31,7 @@
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "unwind.h"
#include "unwind-ia64.h"
#include "unwind-compat.h"
diff --git a/gcc/config/ia64/vms-crtinit.asm b/libgcc/config/ia64/vms-crtinit.S
index 322b2927347..322b2927347 100644
--- a/gcc/config/ia64/vms-crtinit.asm
+++ b/libgcc/config/ia64/vms-crtinit.S
diff --git a/gcc/config/iq2000/lib2extra-funcs.c b/libgcc/config/iq2000/lib2funcs.c
index d53786c8c7d..d53786c8c7d 100644
--- a/gcc/config/iq2000/lib2extra-funcs.c
+++ b/libgcc/config/iq2000/lib2funcs.c
diff --git a/libgcc/config/iq2000/t-iq2000 b/libgcc/config/iq2000/t-iq2000
new file mode 100644
index 00000000000..18fd53c37d6
--- /dev/null
+++ b/libgcc/config/iq2000/t-iq2000
@@ -0,0 +1,5 @@
+LIB2ADD = $(srcdir)/udivmod.c \
+ $(srcdir)/divmod.c \
+ $(srcdir)/udivmodsi4.c \
+ $(srcdir)/config/iq2000/lib2funcs.c
+
diff --git a/libgcc/config/libbid/bid_gcc_intrinsics.h b/libgcc/config/libbid/bid_gcc_intrinsics.h
index 3f3e1ef1706..70529618c11 100644
--- a/libgcc/config/libbid/bid_gcc_intrinsics.h
+++ b/libgcc/config/libbid/bid_gcc_intrinsics.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -29,6 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
diff --git a/gcc/config/libgcc-glibc.ver b/libgcc/config/libgcc-glibc.ver
index 7824ad5a268..7824ad5a268 100644
--- a/gcc/config/libgcc-glibc.ver
+++ b/libgcc/config/libgcc-glibc.ver
diff --git a/gcc/libgcc-libsystem.ver b/libgcc/config/libgcc-libsystem.ver
index 47631749dc2..47631749dc2 100644
--- a/gcc/libgcc-libsystem.ver
+++ b/libgcc/config/libgcc-libsystem.ver
diff --git a/libgcc/config/lm32/t-elf b/libgcc/config/lm32/t-elf
index 679f00711e7..b1ee8f2a253 100644
--- a/libgcc/config/lm32/t-elf
+++ b/libgcc/config/lm32/t-elf
@@ -1,12 +1,2 @@
-# Assemble startup files.
-
-$(T)crti.o: $(srcdir)/config/lm32/crti.S $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/lm32/crti.S
-
-$(T)crtn.o: $(srcdir)/config/lm32/crtn.S $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/lm32/crtn.S
-
CRTSTUFF_T_CFLAGS = -G 0 -msign-extend-enabled
HOST_LIBGCC2_CFLAGS = -G 0 -msign-extend-enabled
diff --git a/libgcc/config/lm32/t-uclinux b/libgcc/config/lm32/t-uclinux
index d388f56c3a2..764243c8f88 100644
--- a/libgcc/config/lm32/t-uclinux
+++ b/libgcc/config/lm32/t-uclinux
@@ -1,2 +1,2 @@
-CRTSTUFF_T_CFLAGS = -fPIC -msign-extend-enabled
-HOST_LIBGCC2_CFLAGS = -fPIC -msign-extend-enabled
+CRTSTUFF_T_CFLAGS = $(PICFLAG) -msign-extend-enabled
+HOST_LIBGCC2_CFLAGS += -msign-extend-enabled
diff --git a/gcc/config/m32c/m32c-lib1.S b/libgcc/config/m32c/lib1funcs.S
index 9b657787187..9b657787187 100644
--- a/gcc/config/m32c/m32c-lib1.S
+++ b/libgcc/config/m32c/lib1funcs.S
diff --git a/gcc/config/m32c/m32c-lib2.c b/libgcc/config/m32c/lib2funcs.c
index 274affc4ab0..274affc4ab0 100644
--- a/gcc/config/m32c/m32c-lib2.c
+++ b/libgcc/config/m32c/lib2funcs.c
diff --git a/libgcc/config/m32c/t-m32c b/libgcc/config/m32c/t-m32c
new file mode 100644
index 00000000000..dac99ec652f
--- /dev/null
+++ b/libgcc/config/m32c/t-m32c
@@ -0,0 +1,13 @@
+LIB1ASMSRC = m32c/lib1funcs.S
+
+LIB1ASMFUNCS = \
+ __m32c_memregs \
+ __m32c_eh_return \
+ __m32c_mulsi3 \
+ __m32c_cmpsi2 \
+ __m32c_ucmpsi2 \
+ __m32c_jsri16
+
+LIB2ADD = $(srcdir)/config/m32c/lib2funcs.c \
+ $(srcdir)/config/m32c/trapv.c
+
diff --git a/libgcc/config/m32c/trapv.c b/libgcc/config/m32c/trapv.c
new file mode 100644
index 00000000000..0c8c174ef81
--- /dev/null
+++ b/libgcc/config/m32c/trapv.c
@@ -0,0 +1,43 @@
+/* 16-bit trapping arithmetic routines for R8C/M16C/M32C
+ Copyright (C) 2009, 2011
+ Free Software Foundation, Inc.
+ Contributed by Red Hat.
+
+ 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 3, 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* See the comment by the definition of LIBGCC2_UNITS_PER_WORD in
+ m32c.h for why we are creating extra versions of some of the
+ functions defined in libgcc2.c.
+
+ Note - this file is separate from lib2funcs.c so that the following
+ functions will appear in the their object file. This is necessary
+ because they call abort() which is defined in the C library whereas
+ the functions in lib2funcs.c are completely self sufficient. */
+
+#define LIBGCC2_UNITS_PER_WORD 2
+
+#define L_mulvsi3
+#define L_negvsi2
+#define L_addvsi3
+#define L_subvsi3
+
+#include "libgcc2.c"
diff --git a/libgcc/config/m32r/initfini.c b/libgcc/config/m32r/initfini.c
new file mode 100644
index 00000000000..56332459223
--- /dev/null
+++ b/libgcc/config/m32r/initfini.c
@@ -0,0 +1,168 @@
+/* .init/.fini section handling + C++ global constructor/destructor handling.
+ This file is based on crtstuff.c, sol2-crti.S, sol2-crtn.S.
+
+ Copyright (C) 1996, 1997, 1998, 2006, 2009 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 3, 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Declare a pointer to void function type. */
+typedef void (*func_ptr) (void);
+
+#ifdef CRT_INIT
+
+/* NOTE: In order to be able to support SVR4 shared libraries, we arrange
+ to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
+ __DTOR_END__ } per root executable and also one set of these symbols
+ per shared library. So in any given whole process image, we may have
+ multiple definitions of each of these symbols. In order to prevent
+ these definitions from conflicting with one another, and in order to
+ ensure that the proper lists are used for the initialization/finalization
+ of each individual shared library (respectively), we give these symbols
+ only internal (i.e. `static') linkage, and we also make it a point to
+ refer to only the __CTOR_END__ symbol in crtfini.o and the __DTOR_LIST__
+ symbol in crtinit.o, where they are defined. */
+
+static func_ptr __CTOR_LIST__[1]
+ __attribute__ ((used, section (".ctors")))
+ = { (func_ptr) (-1) };
+
+static func_ptr __DTOR_LIST__[1]
+ __attribute__ ((used, section (".dtors")))
+ = { (func_ptr) (-1) };
+
+/* Run all the global destructors on exit from the program. */
+
+/* Some systems place the number of pointers in the first word of the
+ table. On SVR4 however, that word is -1. In all cases, the table is
+ null-terminated. On SVR4, we start from the beginning of the list and
+ invoke each per-compilation-unit destructor routine in order
+ until we find that null.
+
+ Note that this function MUST be static. There will be one of these
+ functions in each root executable and one in each shared library, but
+ although they all have the same code, each one is unique in that it
+ refers to one particular associated `__DTOR_LIST__' which belongs to the
+ same particular root executable or shared library file. */
+
+static void __do_global_dtors (void)
+asm ("__do_global_dtors") __attribute__ ((used, section (".text")));
+
+static void
+__do_global_dtors (void)
+{
+ func_ptr *p;
+
+ for (p = __DTOR_LIST__ + 1; *p; p++)
+ (*p) ();
+}
+
+/* .init section start.
+ This must appear at the start of the .init section. */
+
+asm ("\n\
+ .section .init,\"ax\",@progbits\n\
+ .balign 4\n\
+ .global __init\n\
+__init:\n\
+ push fp\n\
+ push lr\n\
+ mv fp,sp\n\
+ seth r0, #shigh(__fini)\n\
+ add3 r0, r0, #low(__fini)\n\
+ bl atexit\n\
+ .fillinsn\n\
+");
+
+/* .fini section start.
+ This must appear at the start of the .init section. */
+
+asm ("\n\
+ .section .fini,\"ax\",@progbits\n\
+ .balign 4\n\
+ .global __fini\n\
+__fini:\n\
+ push fp\n\
+ push lr\n\
+ mv fp,sp\n\
+ bl __do_global_dtors\n\
+ .fillinsn\n\
+");
+
+#endif /* CRT_INIT */
+
+#ifdef CRT_FINI
+
+/* Put a word containing zero at the end of each of our two lists of function
+ addresses. Note that the words defined here go into the .ctors and .dtors
+ sections of the crtend.o file, and since that file is always linked in
+ last, these words naturally end up at the very ends of the two lists
+ contained in these two sections. */
+
+static func_ptr __CTOR_END__[1]
+ __attribute__ ((used, section (".ctors")))
+ = { (func_ptr) 0 };
+
+static func_ptr __DTOR_END__[1]
+ __attribute__ ((used, section (".dtors")))
+ = { (func_ptr) 0 };
+
+/* Run all global constructors for the program.
+ Note that they are run in reverse order. */
+
+static void __do_global_ctors (void)
+asm ("__do_global_ctors") __attribute__ ((used, section (".text")));
+
+static void
+__do_global_ctors (void)
+{
+ func_ptr *p;
+
+ for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+ (*p) ();
+}
+
+/* .init section end.
+ This must live at the end of the .init section. */
+
+asm ("\n\
+ .section .init,\"ax\",@progbits\n\
+ bl __do_global_ctors\n\
+ mv sp,fp\n\
+ pop lr\n\
+ pop fp\n\
+ jmp lr\n\
+ .fillinsn\n\
+");
+
+/* .fini section end.
+ This must live at the end of the .fini section. */
+
+asm ("\n\
+ .section .fini,\"ax\",@progbits\n\
+ mv sp,fp\n\
+ pop lr\n\
+ pop fp\n\
+ jmp lr\n\
+ .fillinsn\n\
+");
+
+#endif /* CRT_FINI */
diff --git a/gcc/config/m32r/libgcc-glibc.ver b/libgcc/config/m32r/libgcc-glibc.ver
index 0e1304b2a3a..0e1304b2a3a 100644
--- a/gcc/config/m32r/libgcc-glibc.ver
+++ b/libgcc/config/m32r/libgcc-glibc.ver
diff --git a/libgcc/config/m32r/t-linux b/libgcc/config/m32r/t-linux
new file mode 100644
index 00000000000..5223b731ff7
--- /dev/null
+++ b/libgcc/config/m32r/t-linux
@@ -0,0 +1,5 @@
+# Turn off the SDA while compiling libgcc2. There are no headers for it
+# and we want maximal upward compatibility here.
+HOST_LIBGCC2_CFLAGS += -G 0
+
+SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/m32r/libgcc-glibc.ver
diff --git a/libgcc/config/m32r/t-m32r b/libgcc/config/m32r/t-m32r
new file mode 100644
index 00000000000..f32cbbef4ee
--- /dev/null
+++ b/libgcc/config/m32r/t-m32r
@@ -0,0 +1,23 @@
+# Turn off the SDA while compiling libgcc2. There are no headers for it
+# and we want maximal upward compatibility here.
+HOST_LIBGCC2_CFLAGS = -G 0
+
+# We need to use -fpic when we are using gcc to compile the routines in
+# initfini.c. This is only really needed when we are going to use gcc/g++
+# to produce a shared library, but since we don't know ahead of time when
+# we will be doing that, we just always use -fpic when compiling the
+# routines in initfini.c.
+# -fpic currently isn't supported for the m32r.
+# FIXME: No longer true. Empty CRTSTUFF_T_CFLAGS is the default.
+CRTSTUFF_T_CFLAGS =
+
+# .init/.fini section routines
+crtinit.o: $(srcdir)/config/m32r/initfini.c
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS) -DCRT_INIT \
+ -finhibit-size-directive -fno-inline-functions -g0 \
+ -mmodel=medium -c $<
+
+crtfini.o: $(srcdir)/config/m32r/initfini.c
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS) -DCRT_FINI \
+ -finhibit-size-directive -fno-inline-functions -g0 \
+ -mmodel=medium -c $<
diff --git a/gcc/config/m68k/crti.s b/libgcc/config/m68k/crti.S
index 12fb59f4130..12fb59f4130 100644
--- a/gcc/config/m68k/crti.s
+++ b/libgcc/config/m68k/crti.S
diff --git a/gcc/config/m68k/crtn.s b/libgcc/config/m68k/crtn.S
index b7d70f02ed5..b7d70f02ed5 100644
--- a/gcc/config/m68k/crtn.s
+++ b/libgcc/config/m68k/crtn.S
diff --git a/libgcc/config/m68k/fpgnulib.c b/libgcc/config/m68k/fpgnulib.c
new file mode 100644
index 00000000000..fe41edf26aa
--- /dev/null
+++ b/libgcc/config/m68k/fpgnulib.c
@@ -0,0 +1,595 @@
+/* This is a stripped down version of floatlib.c. It supplies only those
+ functions which exist in libgcc, but for which there is not assembly
+ language versions in m68k/lb1sf68.S.
+
+ It also includes simplistic support for extended floats (by working in
+ double precision). You must compile this file again with -DEXTFLOAT
+ to get this support. */
+
+/*
+** gnulib support for software floating point.
+** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved.
+** Permission is granted to do *anything* you want with this file,
+** commercial or otherwise, provided this message remains intact. So there!
+** I would appreciate receiving any updates/patches/changes that anyone
+** makes, and am willing to be the repository for said changes (am I
+** making a big mistake?).
+**
+** Pat Wood
+** Pipeline Associates, Inc.
+** pipeline!phw@motown.com or
+** sun!pipeline!phw or
+** uunet!motown!pipeline!phw
+**
+** 05/01/91 -- V1.0 -- first release to gcc mailing lists
+** 05/04/91 -- V1.1 -- added float and double prototypes and return values
+** -- fixed problems with adding and subtracting zero
+** -- fixed rounding in truncdfsf2
+** -- fixed SWAP define and tested on 386
+*/
+
+/*
+** The following are routines that replace the gnulib soft floating point
+** routines that are called automatically when -msoft-float is selected.
+** The support single and double precision IEEE format, with provisions
+** for byte-swapped machines (tested on 386). Some of the double-precision
+** routines work at full precision, but most of the hard ones simply punt
+** and call the single precision routines, producing a loss of accuracy.
+** long long support is not assumed or included.
+** Overall accuracy is close to IEEE (actually 68882) for single-precision
+** arithmetic. I think there may still be a 1 in 1000 chance of a bit
+** being rounded the wrong way during a multiply. I'm not fussy enough to
+** bother with it, but if anyone is, knock yourself out.
+**
+** Efficiency has only been addressed where it was obvious that something
+** would make a big difference. Anyone who wants to do this right for
+** best speed should go in and rewrite in assembler.
+**
+** I have tested this only on a 68030 workstation and 386/ix integrated
+** in with -msoft-float.
+*/
+
+/* the following deal with IEEE single-precision numbers */
+#define EXCESS 126L
+#define SIGNBIT 0x80000000L
+#define HIDDEN (1L << 23L)
+#define SIGN(fp) ((fp) & SIGNBIT)
+#define EXP(fp) (((fp) >> 23L) & 0xFF)
+#define MANT(fp) (((fp) & 0x7FFFFFL) | HIDDEN)
+#define PACK(s,e,m) ((s) | ((e) << 23L) | (m))
+
+/* the following deal with IEEE double-precision numbers */
+#define EXCESSD 1022L
+#define HIDDEND (1L << 20L)
+#define EXPDBITS 11
+#define EXPDMASK 0x7FFL
+#define EXPD(fp) (((fp.l.upper) >> 20L) & 0x7FFL)
+#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
+#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
+ (fp.l.lower >> 22))
+#define MANTDMASK 0xFFFFFL /* mask of upper part */
+
+/* the following deal with IEEE extended-precision numbers */
+#define EXCESSX 16382L
+#define HIDDENX (1L << 31L)
+#define EXPXBITS 15
+#define EXPXMASK 0x7FFF
+#define EXPX(fp) (((fp.l.upper) >> 16) & EXPXMASK)
+#define SIGNX(fp) ((fp.l.upper) & SIGNBIT)
+#define MANTXMASK 0x7FFFFFFFL /* mask of upper part */
+
+union double_long
+{
+ double d;
+ struct {
+ long upper;
+ unsigned long lower;
+ } l;
+};
+
+union float_long {
+ float f;
+ long l;
+};
+
+union long_double_long
+{
+ long double ld;
+ struct
+ {
+ long upper;
+ unsigned long middle;
+ unsigned long lower;
+ } l;
+};
+
+#ifndef EXTFLOAT
+
+int
+__unordsf2(float a, float b)
+{
+ union float_long fl;
+
+ fl.f = a;
+ if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0)
+ return 1;
+ fl.f = b;
+ if (EXP(fl.l) == EXP(~0u) && (MANT(fl.l) & ~HIDDEN) != 0)
+ return 1;
+ return 0;
+}
+
+int
+__unorddf2(double a, double b)
+{
+ union double_long dl;
+
+ dl.d = a;
+ if (EXPD(dl) == EXPDMASK
+ && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0))
+ return 1;
+ dl.d = b;
+ if (EXPD(dl) == EXPDMASK
+ && ((dl.l.upper & MANTDMASK) != 0 || dl.l.lower != 0))
+ return 1;
+ return 0;
+}
+
+/* convert unsigned int to double */
+double
+__floatunsidf (unsigned long a1)
+{
+ long exp = 32 + EXCESSD;
+ union double_long dl;
+
+ if (!a1)
+ {
+ dl.l.upper = dl.l.lower = 0;
+ return dl.d;
+ }
+
+ while (a1 < 0x2000000L)
+ {
+ a1 <<= 4;
+ exp -= 4;
+ }
+
+ while (a1 < 0x80000000L)
+ {
+ a1 <<= 1;
+ exp--;
+ }
+
+ /* pack up and go home */
+ dl.l.upper = exp << 20L;
+ dl.l.upper |= (a1 >> 11L) & ~HIDDEND;
+ dl.l.lower = a1 << 21L;
+
+ return dl.d;
+}
+
+/* convert int to double */
+double
+__floatsidf (long a1)
+{
+ long sign = 0, exp = 31 + EXCESSD;
+ union double_long dl;
+
+ if (!a1)
+ {
+ dl.l.upper = dl.l.lower = 0;
+ return dl.d;
+ }
+
+ if (a1 < 0)
+ {
+ sign = SIGNBIT;
+ a1 = (long)-(unsigned long)a1;
+ if (a1 < 0)
+ {
+ dl.l.upper = SIGNBIT | ((32 + EXCESSD) << 20L);
+ dl.l.lower = 0;
+ return dl.d;
+ }
+ }
+
+ while (a1 < 0x1000000L)
+ {
+ a1 <<= 4;
+ exp -= 4;
+ }
+
+ while (a1 < 0x40000000L)
+ {
+ a1 <<= 1;
+ exp--;
+ }
+
+ /* pack up and go home */
+ dl.l.upper = sign;
+ dl.l.upper |= exp << 20L;
+ dl.l.upper |= (a1 >> 10L) & ~HIDDEND;
+ dl.l.lower = a1 << 22L;
+
+ return dl.d;
+}
+
+/* convert unsigned int to float */
+float
+__floatunsisf (unsigned long l)
+{
+ double foo = __floatunsidf (l);
+ return foo;
+}
+
+/* convert int to float */
+float
+__floatsisf (long l)
+{
+ double foo = __floatsidf (l);
+ return foo;
+}
+
+/* convert float to double */
+double
+__extendsfdf2 (float a1)
+{
+ register union float_long fl1;
+ register union double_long dl;
+ register long exp;
+ register long mant;
+
+ fl1.f = a1;
+
+ dl.l.upper = SIGN (fl1.l);
+ if ((fl1.l & ~SIGNBIT) == 0)
+ {
+ dl.l.lower = 0;
+ return dl.d;
+ }
+
+ exp = EXP(fl1.l);
+ mant = MANT (fl1.l) & ~HIDDEN;
+ if (exp == 0)
+ {
+ /* Denormal. */
+ exp = 1;
+ while (!(mant & HIDDEN))
+ {
+ mant <<= 1;
+ exp--;
+ }
+ mant &= ~HIDDEN;
+ }
+ exp = exp - EXCESS + EXCESSD;
+ dl.l.upper |= exp << 20;
+ dl.l.upper |= mant >> 3;
+ dl.l.lower = mant << 29;
+
+ return dl.d;
+}
+
+/* convert double to float */
+float
+__truncdfsf2 (double a1)
+{
+ register long exp;
+ register long mant;
+ register union float_long fl;
+ register union double_long dl1;
+ int sticky;
+ int shift;
+
+ dl1.d = a1;
+
+ if ((dl1.l.upper & ~SIGNBIT) == 0 && !dl1.l.lower)
+ {
+ fl.l = SIGND(dl1);
+ return fl.f;
+ }
+
+ exp = EXPD (dl1) - EXCESSD + EXCESS;
+
+ sticky = dl1.l.lower & ((1 << 22) - 1);
+ mant = MANTD (dl1);
+ /* shift double mantissa 6 bits so we can round */
+ sticky |= mant & ((1 << 6) - 1);
+ mant >>= 6;
+
+ /* Check for underflow and denormals. */
+ if (exp <= 0)
+ {
+ if (exp < -24)
+ {
+ sticky |= mant;
+ mant = 0;
+ }
+ else
+ {
+ sticky |= mant & ((1 << (1 - exp)) - 1);
+ mant >>= 1 - exp;
+ }
+ exp = 0;
+ }
+
+ /* now round */
+ shift = 1;
+ if ((mant & 1) && (sticky || (mant & 2)))
+ {
+ int rounding = exp ? 2 : 1;
+
+ mant += 1;
+
+ /* did the round overflow? */
+ if (mant >= (HIDDEN << rounding))
+ {
+ exp++;
+ shift = rounding;
+ }
+ }
+ /* shift down */
+ mant >>= shift;
+
+ mant &= ~HIDDEN;
+
+ /* pack up and go home */
+ fl.l = PACK (SIGND (dl1), exp, mant);
+ return (fl.f);
+}
+
+/* convert double to int */
+long
+__fixdfsi (double a1)
+{
+ register union double_long dl1;
+ register long exp;
+ register long l;
+
+ dl1.d = a1;
+
+ if (!dl1.l.upper && !dl1.l.lower)
+ return 0;
+
+ exp = EXPD (dl1) - EXCESSD - 31;
+ l = MANTD (dl1);
+
+ if (exp > 0)
+ {
+ /* Return largest integer. */
+ return SIGND (dl1) ? 0x80000000L : 0x7fffffffL;
+ }
+
+ if (exp <= -32)
+ return 0;
+
+ /* shift down until exp = 0 */
+ if (exp < 0)
+ l >>= -exp;
+
+ return (SIGND (dl1) ? -l : l);
+}
+
+/* convert float to int */
+long
+__fixsfsi (float a1)
+{
+ double foo = a1;
+ return __fixdfsi (foo);
+}
+
+#else /* EXTFLOAT */
+
+/* We do not need these routines for coldfire, as it has no extended
+ float format. */
+#if !defined (__mcoldfire__)
+
+/* Primitive extended precision floating point support.
+
+ We assume all numbers are normalized, don't do any rounding, etc. */
+
+/* Prototypes for the above in case we use them. */
+double __floatunsidf (unsigned long);
+double __floatsidf (long);
+float __floatsisf (long);
+double __extendsfdf2 (float);
+float __truncdfsf2 (double);
+long __fixdfsi (double);
+long __fixsfsi (float);
+
+int
+__unordxf2(long double a, long double b)
+{
+ union long_double_long ldl;
+
+ ldl.ld = a;
+ if (EXPX(ldl) == EXPXMASK
+ && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0))
+ return 1;
+ ldl.ld = b;
+ if (EXPX(ldl) == EXPXMASK
+ && ((ldl.l.middle & MANTXMASK) != 0 || ldl.l.lower != 0))
+ return 1;
+ return 0;
+}
+
+/* convert double to long double */
+long double
+__extenddfxf2 (double d)
+{
+ register union double_long dl;
+ register union long_double_long ldl;
+ register long exp;
+
+ dl.d = d;
+ /*printf ("dfxf in: %g\n", d);*/
+
+ ldl.l.upper = SIGND (dl);
+ if ((dl.l.upper & ~SIGNBIT) == 0 && !dl.l.lower)
+ {
+ ldl.l.middle = 0;
+ ldl.l.lower = 0;
+ return ldl.ld;
+ }
+
+ exp = EXPD (dl) - EXCESSD + EXCESSX;
+ ldl.l.upper |= exp << 16;
+ ldl.l.middle = HIDDENX;
+ /* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
+ ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
+ /* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
+ ldl.l.middle |= dl.l.lower >> (1 + 20);
+ /* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
+ ldl.l.lower = dl.l.lower << (32 - 21);
+
+ /*printf ("dfxf out: %s\n", dumpxf (ldl.ld));*/
+ return ldl.ld;
+}
+
+/* convert long double to double */
+double
+__truncxfdf2 (long double ld)
+{
+ register long exp;
+ register union double_long dl;
+ register union long_double_long ldl;
+
+ ldl.ld = ld;
+ /*printf ("xfdf in: %s\n", dumpxf (ld));*/
+
+ dl.l.upper = SIGNX (ldl);
+ if ((ldl.l.upper & ~SIGNBIT) == 0 && !ldl.l.middle && !ldl.l.lower)
+ {
+ dl.l.lower = 0;
+ return dl.d;
+ }
+
+ exp = EXPX (ldl) - EXCESSX + EXCESSD;
+ /* ??? quick and dirty: keep `exp' sane */
+ if (exp >= EXPDMASK)
+ exp = EXPDMASK - 1;
+ dl.l.upper |= exp << (32 - (EXPDBITS + 1));
+ /* +1-1: add one for sign bit, but take one off for explicit-integer-bit */
+ dl.l.upper |= (ldl.l.middle & MANTXMASK) >> (EXPDBITS + 1 - 1);
+ dl.l.lower = (ldl.l.middle & MANTXMASK) << (32 - (EXPDBITS + 1 - 1));
+ dl.l.lower |= ldl.l.lower >> (EXPDBITS + 1 - 1);
+
+ /*printf ("xfdf out: %g\n", dl.d);*/
+ return dl.d;
+}
+
+/* convert a float to a long double */
+long double
+__extendsfxf2 (float f)
+{
+ long double foo = __extenddfxf2 (__extendsfdf2 (f));
+ return foo;
+}
+
+/* convert a long double to a float */
+float
+__truncxfsf2 (long double ld)
+{
+ float foo = __truncdfsf2 (__truncxfdf2 (ld));
+ return foo;
+}
+
+/* convert an int to a long double */
+long double
+__floatsixf (long l)
+{
+ double foo = __floatsidf (l);
+ return foo;
+}
+
+/* convert an unsigned int to a long double */
+long double
+__floatunsixf (unsigned long l)
+{
+ double foo = __floatunsidf (l);
+ return foo;
+}
+
+/* convert a long double to an int */
+long
+__fixxfsi (long double ld)
+{
+ long foo = __fixdfsi ((double) ld);
+ return foo;
+}
+
+/* The remaining provide crude math support by working in double precision. */
+
+long double
+__addxf3 (long double x1, long double x2)
+{
+ return (double) x1 + (double) x2;
+}
+
+long double
+__subxf3 (long double x1, long double x2)
+{
+ return (double) x1 - (double) x2;
+}
+
+long double
+__mulxf3 (long double x1, long double x2)
+{
+ return (double) x1 * (double) x2;
+}
+
+long double
+__divxf3 (long double x1, long double x2)
+{
+ return (double) x1 / (double) x2;
+}
+
+long double
+__negxf2 (long double x1)
+{
+ return - (double) x1;
+}
+
+long
+__cmpxf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__eqxf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__nexf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__ltxf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__lexf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__gtxf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+long
+__gexf2 (long double x1, long double x2)
+{
+ return __cmpdf2 ((double) x1, (double) x2);
+}
+
+#endif /* !__mcoldfire__ */
+#endif /* EXTFLOAT */
diff --git a/gcc/config/m68k/lb1sf68.asm b/libgcc/config/m68k/lb1sf68.S
index 0339a092c4f..0339a092c4f 100644
--- a/gcc/config/m68k/lb1sf68.asm
+++ b/libgcc/config/m68k/lb1sf68.S
diff --git a/libgcc/config/m68k/t-floatlib b/libgcc/config/m68k/t-floatlib
new file mode 100644
index 00000000000..1ee8782d9fd
--- /dev/null
+++ b/libgcc/config/m68k/t-floatlib
@@ -0,0 +1,11 @@
+LIB1ASMSRC = m68k/lb1sf68.S
+LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
+ _double _float _floatex \
+ _eqdf2 _nedf2 _gtdf2 _gedf2 _ltdf2 _ledf2 \
+ _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2
+
+LIB2ADD = $(srcdir)/config/m68k/fpgnulib.c xfgnulib.c
+
+xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
+ echo '#define EXTFLOAT' > xfgnulib.c
+ cat $< >> xfgnulib.c
diff --git a/gcc/config/m68k/t-slibgcc-elf-ver b/libgcc/config/m68k/t-slibgcc-elf-ver
index 6aac37cc08f..6aac37cc08f 100644
--- a/gcc/config/m68k/t-slibgcc-elf-ver
+++ b/libgcc/config/m68k/t-slibgcc-elf-ver
diff --git a/libgcc/config/mcore/crti.S b/libgcc/config/mcore/crti.S
new file mode 100644
index 00000000000..467e944fb37
--- /dev/null
+++ b/libgcc/config/mcore/crti.S
@@ -0,0 +1,63 @@
+# crti.S for ELF based systems
+
+# Copyright (C) 1992, 1998, 1999, 2008, 2009, 2011
+# Free Software Foundation, Inc.
+# Written By David Vinayak Henkel-Wallace, June 1992
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+
+# This file just makes a stack frame for the contents of the .fini and
+# .init sections. Users may put any desired instructions in those
+# sections.
+
+ .section ".init"
+ .global _init
+ .type _init,@function
+ .align 4
+_init:
+ subi r0, 16
+ st.w r15, (r0, 12)
+
+ # These nops are here to align the end of this code with a 16 byte
+ # boundary. The linker will start inserting code into the .init
+ # section at such a boundary.
+
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+
+
+ .section ".fini"
+ .global _fini
+ .type _fini,@function
+ .align 4
+_fini:
+ subi r0, 16
+ st.w r15, (r0, 12)
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
diff --git a/libgcc/config/mcore/crtn.S b/libgcc/config/mcore/crtn.S
new file mode 100644
index 00000000000..85f75b1d42f
--- /dev/null
+++ b/libgcc/config/mcore/crtn.S
@@ -0,0 +1,45 @@
+# crtn.S for ELF based systems
+
+# Copyright (C) 1992, 1999, 2000, 2008, 2009, 2011
+# Free Software Foundation, Inc.
+# Written By David Vinayak Henkel-Wallace, June 1992
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file just makes sure that the .fini and .init sections do in
+# fact return. Users may put any desired instructions in those sections.
+# This file is the last thing linked into any executable.
+
+ .section ".init"
+ .align 4
+
+ ldw r15,(r0, 12)
+ addi r0,16
+ jmp r15
+
+ .section ".fini"
+ .align 4
+
+ ldw r15, (r0, 12)
+ addi r0,16
+ jmp r15
+
+# Th-th-th-that is all folks!
+
diff --git a/gcc/config/mcore/lib1.asm b/libgcc/config/mcore/lib1funcs.S
index 701762f2a3c..701762f2a3c 100644
--- a/gcc/config/mcore/lib1.asm
+++ b/libgcc/config/mcore/lib1funcs.S
diff --git a/libgcc/config/mcore/t-mcore b/libgcc/config/mcore/t-mcore
new file mode 100644
index 00000000000..fe024c7aee4
--- /dev/null
+++ b/libgcc/config/mcore/t-mcore
@@ -0,0 +1,5 @@
+LIB1ASMSRC = mcore/lib1funcs.S
+LIB1ASMFUNCS = _divsi3 _udivsi3 _modsi3 _umodsi3
+
+# could use -msifilter to be safe from interrupt/jmp interactions and others.
+HOST_LIBGCC2_CFLAGS = -O3 -DNO_FLOATLIB_FIXUNSDFSI #-msifilter
diff --git a/gcc/config/mep/mep-lib1.asm b/libgcc/config/mep/lib1funcs.S
index 0a18913f927..0a18913f927 100644
--- a/gcc/config/mep/mep-lib1.asm
+++ b/libgcc/config/mep/lib1funcs.S
diff --git a/gcc/config/mep/mep-lib2.c b/libgcc/config/mep/lib2funcs.c
index 1dbf57d9535..1dbf57d9535 100644
--- a/gcc/config/mep/mep-lib2.c
+++ b/libgcc/config/mep/lib2funcs.c
diff --git a/libgcc/config/mep/t-mep b/libgcc/config/mep/t-mep
new file mode 100644
index 00000000000..fb3a0d60c4d
--- /dev/null
+++ b/libgcc/config/mep/t-mep
@@ -0,0 +1,16 @@
+# profiling support
+LIB1ASMSRC = mep/lib1funcs.S
+
+LIB1ASMFUNCS = _mep_profile \
+ _mep_bb_init_trace \
+ _mep_bb_init \
+ _mep_bb_trace \
+ _mep_bb_increment
+
+# multiply and divide routines
+LIB2ADD = \
+ $(srcdir)/config/mep/lib2funcs.c \
+ $(srcdir)/config/mep/tramp.c
+
+# Use -O0 instead of -O2 so we don't get complex relocations
+CRTSTUFF_CFLAGS += -O0
diff --git a/gcc/config/mep/mep-tramp.c b/libgcc/config/mep/tramp.c
index bf484ca4e95..bf484ca4e95 100644
--- a/gcc/config/mep/mep-tramp.c
+++ b/libgcc/config/mep/tramp.c
diff --git a/gcc/config/microblaze/crti.s b/libgcc/config/microblaze/crti.S
index 3944443b437..3944443b437 100644
--- a/gcc/config/microblaze/crti.s
+++ b/libgcc/config/microblaze/crti.S
diff --git a/gcc/config/microblaze/crtn.s b/libgcc/config/microblaze/crtn.S
index 7970dee1c93..7970dee1c93 100644
--- a/gcc/config/microblaze/crtn.s
+++ b/libgcc/config/microblaze/crtn.S
diff --git a/libgcc/config/microblaze/divsi3.S b/libgcc/config/microblaze/divsi3.S
new file mode 100644
index 00000000000..f3b7a198306
--- /dev/null
+++ b/libgcc/config/microblaze/divsi3.S
@@ -0,0 +1,96 @@
+###################################-
+#
+# Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# divsi3.S
+#
+# Divide operation for 32 bit integers.
+# Input : Dividend in Reg r5
+# Divisor in Reg r6
+# Output: Result in Reg r3
+#
+#######################################
+
+ .globl __divsi3
+ .ent __divsi3
+ .type __divsi3,@function
+__divsi3:
+ .frame r1,0,r15
+
+ ADDIK r1,r1,-16
+ SWI r28,r1,0
+ SWI r29,r1,4
+ SWI r30,r1,8
+ SWI r31,r1,12
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQI r5,$LaResult_Is_Zero # Result is Zero
+ BGEID r5,$LaR5_Pos
+ XOR r28,r5,r6 # Get the sign of the result
+ RSUBI r5,r5,0 # Make r5 positive
+$LaR5_Pos:
+ BGEI r6,$LaR6_Pos
+ RSUBI r6,r6,0 # Make r6 positive
+$LaR6_Pos:
+ ADDIK r30,r0,0 # Clear mod
+ ADDIK r3,r0,0 # clear div
+ ADDIK r29,r0,32 # Initialize the loop count
+
+ # First part try to find the first '1' in the r5
+$LaDIV0:
+ BLTI r5,$LaDIV2 # This traps r5 == 0x80000000
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGTID r5,$LaDIV1
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r30,r30,r30 # Move that bit into the Mod register
+ RSUB r31,r6,r30 # Try to subtract (r30 a r6)
+ BLTI r31,$LaMOD_TOO_SMALL
+ OR r30,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r3,r3,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r3,r3,r3 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BGEI r28,$LaRETURN_HERE
+ BRID $LaRETURN_HERE
+ RSUBI r3,r3,0 # Negate the result
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ OR r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ LWI r28,r1,0
+ LWI r29,r1,4
+ LWI r30,r1,8
+ LWI r31,r1,12
+ RTSD r15,8
+ ADDIK r1,r1,16
+.end __divsi3
+ .size __divsi3, . - __divsi3
+
diff --git a/libgcc/config/microblaze/divsi3.asm b/libgcc/config/microblaze/divsi3.asm
deleted file mode 100644
index 7d888b32e8d..00000000000
--- a/libgcc/config/microblaze/divsi3.asm
+++ /dev/null
@@ -1,96 +0,0 @@
-###################################-
-#
-# Copyright 2009, 2010 Free Software Foundation, Inc.
-#
-# Contributed by Michael Eager <eager@eagercon.com>.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, 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.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# divsi3.asm
-#
-# Divide operation for 32 bit integers.
-# Input : Dividend in Reg r5
-# Divisor in Reg r6
-# Output: Result in Reg r3
-#
-#######################################
-
- .globl __divsi3
- .ent __divsi3
- .type __divsi3,@function
-__divsi3:
- .frame r1,0,r15
-
- ADDIK r1,r1,-16
- SWI r28,r1,0
- SWI r29,r1,4
- SWI r30,r1,8
- SWI r31,r1,12
-
- BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
- BEQI r5,$LaResult_Is_Zero # Result is Zero
- BGEID r5,$LaR5_Pos
- XOR r28,r5,r6 # Get the sign of the result
- RSUBI r5,r5,0 # Make r5 positive
-$LaR5_Pos:
- BGEI r6,$LaR6_Pos
- RSUBI r6,r6,0 # Make r6 positive
-$LaR6_Pos:
- ADDIK r30,r0,0 # Clear mod
- ADDIK r3,r0,0 # clear div
- ADDIK r29,r0,32 # Initialize the loop count
-
- # First part try to find the first '1' in the r5
-$LaDIV0:
- BLTI r5,$LaDIV2 # This traps r5 == 0x80000000
-$LaDIV1:
- ADD r5,r5,r5 # left shift logical r5
- BGTID r5,$LaDIV1
- ADDIK r29,r29,-1
-$LaDIV2:
- ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
- ADDC r30,r30,r30 # Move that bit into the Mod register
- RSUB r31,r6,r30 # Try to subtract (r30 a r6)
- BLTI r31,$LaMOD_TOO_SMALL
- OR r30,r0,r31 # Move the r31 to mod since the result was positive
- ADDIK r3,r3,1
-$LaMOD_TOO_SMALL:
- ADDIK r29,r29,-1
- BEQi r29,$LaLOOP_END
- ADD r3,r3,r3 # Shift in the '1' into div
- BRI $LaDIV2 # Div2
-$LaLOOP_END:
- BGEI r28,$LaRETURN_HERE
- BRID $LaRETURN_HERE
- RSUBI r3,r3,0 # Negate the result
-$LaDiv_By_Zero:
-$LaResult_Is_Zero:
- OR r3,r0,r0 # set result to 0
-$LaRETURN_HERE:
-# Restore values of CSRs and that of r3 and the divisor and the dividend
- LWI r28,r1,0
- LWI r29,r1,4
- LWI r30,r1,8
- LWI r31,r1,12
- RTSD r15,8
- ADDIK r1,r1,16
-.end __divsi3
- .size __divsi3, . - __divsi3
-
diff --git a/libgcc/config/microblaze/moddi3.S b/libgcc/config/microblaze/moddi3.S
new file mode 100644
index 00000000000..3e8d94f70a9
--- /dev/null
+++ b/libgcc/config/microblaze/moddi3.S
@@ -0,0 +1,115 @@
+###################################
+#
+# Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# modsi3.S
+#
+# modulo operation for 64 bit integers.
+#
+#######################################
+
+
+ .globl __moddi3
+ .ent __moddi3
+__moddi3:
+ .frame r1,0,r15
+
+#Change the stack pointer value and Save callee saved regs
+ addik r1,r1,-24
+ swi r25,r1,0
+ swi r26,r1,4
+ swi r27,r1,8 # used for sign
+ swi r28,r1,12 # used for loop count
+ swi r29,r1,16 # Used for div value High
+ swi r30,r1,20 # Used for div value Low
+
+#Check for Zero Value in the divisor/dividend
+ OR r9,r5,r6 # Check for the op1 being zero
+ BEQID r9,$LaResult_Is_Zero # Result is zero
+ OR r9,r7,r8 # Check for the dividend being zero
+ BEQI r9,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BGEId r5,$La1_Pos
+ XOR r27,r5,r7 # Get the sign of the result
+ RSUBI r6,r6,0 # Make dividend positive
+ RSUBIC r5,r5,0 # Make dividend positive
+$La1_Pos:
+ BGEI r7,$La2_Pos
+ RSUBI r8,r8,0 # Make Divisor Positive
+ RSUBIC r9,r9,0 # Make Divisor Positive
+$La2_Pos:
+ ADDIK r4,r0,0 # Clear mod low
+ ADDIK r3,r0,0 # Clear mod high
+ ADDIK r29,r0,0 # clear div high
+ ADDIK r30,r0,0 # clear div low
+ ADDIK r28,r0,64 # Initialize the loop count
+ # First part try to find the first '1' in the r5/r6
+$LaDIV1:
+ ADD r6,r6,r6
+ ADDC r5,r5,r5 # left shift logical r5
+ BGEID r5,$LaDIV1
+ ADDIK r28,r28,-1
+$LaDIV2:
+ ADD r6,r6,r6
+ ADDC r5,r5,r5 # left shift logical r5/r6 get the '1' into the Carry
+ ADDC r4,r4,r4 # Move that bit into the Mod register
+ ADDC r3,r3,r3 # Move carry into high mod register
+ rsub r18,r7,r3 # Compare the High Parts of Mod and Divisor
+ bnei r18,$L_High_EQ
+ rsub r18,r6,r4 # Compare Low Parts only if Mod[h] == Divisor[h]
+$L_High_EQ:
+ rSUB r26,r8,r4 # Subtract divisor[L] from Mod[L]
+ rsubc r25,r7,r3 # Subtract divisor[H] from Mod[H]
+ BLTi r25,$LaMOD_TOO_SMALL
+ OR r3,r0,r25 # move r25 to mod [h]
+ OR r4,r0,r26 # move r26 to mod [l]
+ ADDI r30,r30,1
+ ADDC r29,r29,r0
+$LaMOD_TOO_SMALL:
+ ADDIK r28,r28,-1
+ BEQi r28,$LaLOOP_END
+ ADD r30,r30,r30 # Shift in the '1' into div [low]
+ ADDC r29,r29,r29 # Move the carry generated into high
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BGEI r27,$LaRETURN_HERE
+ rsubi r30,r30,0
+ rsubc r29,r29,r0
+ BRI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ or r29,r0,r0 # set result to 0 [High]
+ or r30,r0,r0 # set result to 0 [Low]
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r29 and the divisor and the dividend
+
+ lwi r25,r1,0
+ lwi r26,r1,4
+ lwi r27,r1,8
+ lwi r28,r1,12
+ lwi r29,r1,16
+ lwi r30,r1,20
+ rtsd r15,8
+ addik r1,r1,24
+ .end __moddi3
+
diff --git a/libgcc/config/microblaze/moddi3.asm b/libgcc/config/microblaze/moddi3.asm
deleted file mode 100644
index 4923b45ffeb..00000000000
--- a/libgcc/config/microblaze/moddi3.asm
+++ /dev/null
@@ -1,115 +0,0 @@
-###################################
-#
-# Copyright 2009, 2010 Free Software Foundation, Inc.
-#
-# Contributed by Michael Eager <eager@eagercon.com>.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, 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.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# modsi3.asm
-#
-# modulo operation for 64 bit integers.
-#
-#######################################
-
-
- .globl __moddi3
- .ent __moddi3
-__moddi3:
- .frame r1,0,r15
-
-#Change the stack pointer value and Save callee saved regs
- addik r1,r1,-24
- swi r25,r1,0
- swi r26,r1,4
- swi r27,r1,8 # used for sign
- swi r28,r1,12 # used for loop count
- swi r29,r1,16 # Used for div value High
- swi r30,r1,20 # Used for div value Low
-
-#Check for Zero Value in the divisor/dividend
- OR r9,r5,r6 # Check for the op1 being zero
- BEQID r9,$LaResult_Is_Zero # Result is zero
- OR r9,r7,r8 # Check for the dividend being zero
- BEQI r9,$LaDiv_By_Zero # Div_by_Zero # Division Error
- BGEId r5,$La1_Pos
- XOR r27,r5,r7 # Get the sign of the result
- RSUBI r6,r6,0 # Make dividend positive
- RSUBIC r5,r5,0 # Make dividend positive
-$La1_Pos:
- BGEI r7,$La2_Pos
- RSUBI r8,r8,0 # Make Divisor Positive
- RSUBIC r9,r9,0 # Make Divisor Positive
-$La2_Pos:
- ADDIK r4,r0,0 # Clear mod low
- ADDIK r3,r0,0 # Clear mod high
- ADDIK r29,r0,0 # clear div high
- ADDIK r30,r0,0 # clear div low
- ADDIK r28,r0,64 # Initialize the loop count
- # First part try to find the first '1' in the r5/r6
-$LaDIV1:
- ADD r6,r6,r6
- ADDC r5,r5,r5 # left shift logical r5
- BGEID r5,$LaDIV1
- ADDIK r28,r28,-1
-$LaDIV2:
- ADD r6,r6,r6
- ADDC r5,r5,r5 # left shift logical r5/r6 get the '1' into the Carry
- ADDC r4,r4,r4 # Move that bit into the Mod register
- ADDC r3,r3,r3 # Move carry into high mod register
- rsub r18,r7,r3 # Compare the High Parts of Mod and Divisor
- bnei r18,$L_High_EQ
- rsub r18,r6,r4 # Compare Low Parts only if Mod[h] == Divisor[h]
-$L_High_EQ:
- rSUB r26,r8,r4 # Subtract divisor[L] from Mod[L]
- rsubc r25,r7,r3 # Subtract divisor[H] from Mod[H]
- BLTi r25,$LaMOD_TOO_SMALL
- OR r3,r0,r25 # move r25 to mod [h]
- OR r4,r0,r26 # move r26 to mod [l]
- ADDI r30,r30,1
- ADDC r29,r29,r0
-$LaMOD_TOO_SMALL:
- ADDIK r28,r28,-1
- BEQi r28,$LaLOOP_END
- ADD r30,r30,r30 # Shift in the '1' into div [low]
- ADDC r29,r29,r29 # Move the carry generated into high
- BRI $LaDIV2 # Div2
-$LaLOOP_END:
- BGEI r27,$LaRETURN_HERE
- rsubi r30,r30,0
- rsubc r29,r29,r0
- BRI $LaRETURN_HERE
-$LaDiv_By_Zero:
-$LaResult_Is_Zero:
- or r29,r0,r0 # set result to 0 [High]
- or r30,r0,r0 # set result to 0 [Low]
-$LaRETURN_HERE:
-# Restore values of CSRs and that of r29 and the divisor and the dividend
-
- lwi r25,r1,0
- lwi r26,r1,4
- lwi r27,r1,8
- lwi r28,r1,12
- lwi r29,r1,16
- lwi r30,r1,20
- rtsd r15,8
- addik r1,r1,24
- .end __moddi3
-
diff --git a/libgcc/config/microblaze/modsi3.S b/libgcc/config/microblaze/modsi3.S
new file mode 100644
index 00000000000..4be6be42616
--- /dev/null
+++ b/libgcc/config/microblaze/modsi3.S
@@ -0,0 +1,93 @@
+###################################
+#
+# Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# modsi3.S
+#
+# modulo operation for 32 bit integers.
+# Input : op1 in Reg r5
+# op2 in Reg r6
+# Output: op1 mod op2 in Reg r3
+#
+#######################################
+
+ .globl __modsi3
+ .ent __modsi3
+ .type __modsi3,@function
+__modsi3:
+ .frame r1,0,r15
+
+ addik r1,r1,-16
+ swi r28,r1,0
+ swi r29,r1,4
+ swi r30,r1,8
+ swi r31,r1,12
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQI r5,$LaResult_Is_Zero # Result is Zero
+ BGEId r5,$LaR5_Pos
+ ADD r28,r5,r0 # Get the sign of the result [ Depends only on the first arg]
+ RSUBI r5,r5,0 # Make r5 positive
+$LaR5_Pos:
+ BGEI r6,$LaR6_Pos
+ RSUBI r6,r6,0 # Make r6 positive
+$LaR6_Pos:
+ ADDIK r3,r0,0 # Clear mod
+ ADDIK r30,r0,0 # clear div
+ ADDIK r29,r0,32 # Initialize the loop count
+ # First part try to find the first '1' in the r5
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGEID r5,$LaDIV1 #
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r3,r3,r3 # Move that bit into the Mod register
+ rSUB r31,r6,r3 # Try to subtract (r30 a r6)
+ BLTi r31,$LaMOD_TOO_SMALL
+ OR r3,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r30,r30,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r30,r30,r30 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BGEI r28,$LaRETURN_HERE
+ BRId $LaRETURN_HERE
+ rsubi r3,r3,0 # Negate the result
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ or r3,r0,r0 # set result to 0 [Both mod as well as div are 0]
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ lwi r28,r1,0
+ lwi r29,r1,4
+ lwi r30,r1,8
+ lwi r31,r1,12
+ rtsd r15,8
+ addik r1,r1,16
+ .end __modsi3
+ .size __modsi3, . - __modsi3
+
diff --git a/libgcc/config/microblaze/modsi3.asm b/libgcc/config/microblaze/modsi3.asm
deleted file mode 100644
index cae95c8bc63..00000000000
--- a/libgcc/config/microblaze/modsi3.asm
+++ /dev/null
@@ -1,93 +0,0 @@
-###################################
-#
-# Copyright 2009, 2010 Free Software Foundation, Inc.
-#
-# Contributed by Michael Eager <eager@eagercon.com>.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, 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.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# modsi3.asm
-#
-# modulo operation for 32 bit integers.
-# Input : op1 in Reg r5
-# op2 in Reg r6
-# Output: op1 mod op2 in Reg r3
-#
-#######################################
-
- .globl __modsi3
- .ent __modsi3
- .type __modsi3,@function
-__modsi3:
- .frame r1,0,r15
-
- addik r1,r1,-16
- swi r28,r1,0
- swi r29,r1,4
- swi r30,r1,8
- swi r31,r1,12
-
- BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
- BEQI r5,$LaResult_Is_Zero # Result is Zero
- BGEId r5,$LaR5_Pos
- ADD r28,r5,r0 # Get the sign of the result [ Depends only on the first arg]
- RSUBI r5,r5,0 # Make r5 positive
-$LaR5_Pos:
- BGEI r6,$LaR6_Pos
- RSUBI r6,r6,0 # Make r6 positive
-$LaR6_Pos:
- ADDIK r3,r0,0 # Clear mod
- ADDIK r30,r0,0 # clear div
- ADDIK r29,r0,32 # Initialize the loop count
- # First part try to find the first '1' in the r5
-$LaDIV1:
- ADD r5,r5,r5 # left shift logical r5
- BGEID r5,$LaDIV1 #
- ADDIK r29,r29,-1
-$LaDIV2:
- ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
- ADDC r3,r3,r3 # Move that bit into the Mod register
- rSUB r31,r6,r3 # Try to subtract (r30 a r6)
- BLTi r31,$LaMOD_TOO_SMALL
- OR r3,r0,r31 # Move the r31 to mod since the result was positive
- ADDIK r30,r30,1
-$LaMOD_TOO_SMALL:
- ADDIK r29,r29,-1
- BEQi r29,$LaLOOP_END
- ADD r30,r30,r30 # Shift in the '1' into div
- BRI $LaDIV2 # Div2
-$LaLOOP_END:
- BGEI r28,$LaRETURN_HERE
- BRId $LaRETURN_HERE
- rsubi r3,r3,0 # Negate the result
-$LaDiv_By_Zero:
-$LaResult_Is_Zero:
- or r3,r0,r0 # set result to 0 [Both mod as well as div are 0]
-$LaRETURN_HERE:
-# Restore values of CSRs and that of r3 and the divisor and the dividend
- lwi r28,r1,0
- lwi r29,r1,4
- lwi r30,r1,8
- lwi r31,r1,12
- rtsd r15,8
- addik r1,r1,16
- .end __modsi3
- .size __modsi3, . - __modsi3
-
diff --git a/libgcc/config/microblaze/muldi3_hard.S b/libgcc/config/microblaze/muldi3_hard.S
new file mode 100644
index 00000000000..14cfff59772
--- /dev/null
+++ b/libgcc/config/microblaze/muldi3_hard.S
@@ -0,0 +1,144 @@
+###################################-
+#
+# Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# muldi3_hard.S
+#
+# Multiply operation for 64 bit integers, for devices with hard multiply
+# Input : Operand1[H] in Reg r5
+# Operand1[L] in Reg r6
+# Operand2[H] in Reg r7
+# Operand2[L] in Reg r8
+# Output: Result[H] in Reg r3
+# Result[L] in Reg r4
+#
+# Explaination:
+#
+# Both the input numbers are divided into 16 bit number as follows
+# op1 = A B C D
+# op2 = E F G H
+# result = D * H
+# + (C * H + D * G) << 16
+# + (B * H + C * G + D * F) << 32
+# + (A * H + B * G + C * F + D * E) << 48
+#
+# Only 64 bits of the output are considered
+#
+#######################################
+
+ .globl muldi3_hardproc
+ .ent muldi3_hardproc
+muldi3_hardproc:
+ addi r1,r1,-40
+
+# Save the input operands on the caller's stack
+ swi r5,r1,44
+ swi r6,r1,48
+ swi r7,r1,52
+ swi r8,r1,56
+
+# Store all the callee saved registers
+ sw r20,r1,r0
+ swi r21,r1,4
+ swi r22,r1,8
+ swi r23,r1,12
+ swi r24,r1,16
+ swi r25,r1,20
+ swi r26,r1,24
+ swi r27,r1,28
+
+# Load all the 16 bit values for A thru H
+ lhui r20,r1,44 # A
+ lhui r21,r1,46 # B
+ lhui r22,r1,48 # C
+ lhui r23,r1,50 # D
+ lhui r24,r1,52 # E
+ lhui r25,r1,54 # F
+ lhui r26,r1,56 # G
+ lhui r27,r1,58 # H
+
+# D * H ==> LSB of the result on stack ==> Store1
+ mul r9,r23,r27
+ swi r9,r1,36 # Pos2 and Pos3
+
+# Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2
+# Store the carry generated in position 2 for Pos 3
+ lhui r11,r1,36 # Pos2
+ mul r9,r22,r27 # C * H
+ mul r10,r23,r26 # D * G
+ add r9,r9,r10
+ addc r12,r0,r0
+ add r9,r9,r11
+ addc r12,r12,r0 # Store the Carry
+ shi r9,r1,36 # Store Pos2
+ swi r9,r1,32
+ lhui r11,r1,32
+ shi r11,r1,34 # Store Pos1
+
+# Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1
+ mul r9,r21,r27 # B * H
+ mul r10,r22,r26 # C * G
+ mul r7,r23,r25 # D * F
+ add r9,r9,r11
+ add r9,r9,r10
+ add r9,r9,r7
+ swi r9,r1,32 # Pos0 and Pos1
+
+# Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0
+ lhui r11,r1,32 # Pos0
+ mul r9,r20,r27 # A * H
+ mul r10,r21,r26 # B * G
+ mul r7,r22,r25 # C * F
+ mul r8,r23,r24 # D * E
+ add r9,r9,r11
+ add r9,r9,r10
+ add r9,r9,r7
+ add r9,r9,r8
+ sext16 r9,r9 # Sign extend the MSB
+ shi r9,r1,32
+
+# Move results to r3 and r4
+ lhui r3,r1,32
+ add r3,r3,r12
+ shi r3,r1,32
+ lwi r3,r1,32 # Hi Part
+ lwi r4,r1,36 # Lo Part
+
+# Restore Callee saved registers
+ lw r20,r1,r0
+ lwi r21,r1,4
+ lwi r22,r1,8
+ lwi r23,r1,12
+ lwi r24,r1,16
+ lwi r25,r1,20
+ lwi r26,r1,24
+ lwi r27,r1,28
+
+# Restore Frame and return
+ rtsd r15,8
+ addi r1,r1,40
+
+.end muldi3_hardproc
+
+
diff --git a/libgcc/config/microblaze/muldi3_hard.asm b/libgcc/config/microblaze/muldi3_hard.asm
deleted file mode 100644
index 0499e2a550b..00000000000
--- a/libgcc/config/microblaze/muldi3_hard.asm
+++ /dev/null
@@ -1,144 +0,0 @@
-###################################-
-#
-# Copyright 2009, 2010 Free Software Foundation, Inc.
-#
-# Contributed by Michael Eager <eager@eagercon.com>.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, 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.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# muldi3_hard.asm
-#
-# Multiply operation for 64 bit integers, for devices with hard multiply
-# Input : Operand1[H] in Reg r5
-# Operand1[L] in Reg r6
-# Operand2[H] in Reg r7
-# Operand2[L] in Reg r8
-# Output: Result[H] in Reg r3
-# Result[L] in Reg r4
-#
-# Explaination:
-#
-# Both the input numbers are divided into 16 bit number as follows
-# op1 = A B C D
-# op2 = E F G H
-# result = D * H
-# + (C * H + D * G) << 16
-# + (B * H + C * G + D * F) << 32
-# + (A * H + B * G + C * F + D * E) << 48
-#
-# Only 64 bits of the output are considered
-#
-#######################################
-
- .globl muldi3_hardproc
- .ent muldi3_hardproc
-muldi3_hardproc:
- addi r1,r1,-40
-
-# Save the input operands on the caller's stack
- swi r5,r1,44
- swi r6,r1,48
- swi r7,r1,52
- swi r8,r1,56
-
-# Store all the callee saved registers
- sw r20,r1,r0
- swi r21,r1,4
- swi r22,r1,8
- swi r23,r1,12
- swi r24,r1,16
- swi r25,r1,20
- swi r26,r1,24
- swi r27,r1,28
-
-# Load all the 16 bit values for A thru H
- lhui r20,r1,44 # A
- lhui r21,r1,46 # B
- lhui r22,r1,48 # C
- lhui r23,r1,50 # D
- lhui r24,r1,52 # E
- lhui r25,r1,54 # F
- lhui r26,r1,56 # G
- lhui r27,r1,58 # H
-
-# D * H ==> LSB of the result on stack ==> Store1
- mul r9,r23,r27
- swi r9,r1,36 # Pos2 and Pos3
-
-# Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2
-# Store the carry generated in position 2 for Pos 3
- lhui r11,r1,36 # Pos2
- mul r9,r22,r27 # C * H
- mul r10,r23,r26 # D * G
- add r9,r9,r10
- addc r12,r0,r0
- add r9,r9,r11
- addc r12,r12,r0 # Store the Carry
- shi r9,r1,36 # Store Pos2
- swi r9,r1,32
- lhui r11,r1,32
- shi r11,r1,34 # Store Pos1
-
-# Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1
- mul r9,r21,r27 # B * H
- mul r10,r22,r26 # C * G
- mul r7,r23,r25 # D * F
- add r9,r9,r11
- add r9,r9,r10
- add r9,r9,r7
- swi r9,r1,32 # Pos0 and Pos1
-
-# Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0
- lhui r11,r1,32 # Pos0
- mul r9,r20,r27 # A * H
- mul r10,r21,r26 # B * G
- mul r7,r22,r25 # C * F
- mul r8,r23,r24 # D * E
- add r9,r9,r11
- add r9,r9,r10
- add r9,r9,r7
- add r9,r9,r8
- sext16 r9,r9 # Sign extend the MSB
- shi r9,r1,32
-
-# Move results to r3 and r4
- lhui r3,r1,32
- add r3,r3,r12
- shi r3,r1,32
- lwi r3,r1,32 # Hi Part
- lwi r4,r1,36 # Lo Part
-
-# Restore Callee saved registers
- lw r20,r1,r0
- lwi r21,r1,4
- lwi r22,r1,8
- lwi r23,r1,12
- lwi r24,r1,16
- lwi r25,r1,20
- lwi r26,r1,24
- lwi r27,r1,28
-
-# Restore Frame and return
- rtsd r15,8
- addi r1,r1,40
-
-.end muldi3_hardproc
-
-
diff --git a/libgcc/config/microblaze/mulsi3.S b/libgcc/config/microblaze/mulsi3.S
new file mode 100644
index 00000000000..77d2daa9270
--- /dev/null
+++ b/libgcc/config/microblaze/mulsi3.S
@@ -0,0 +1,69 @@
+###################################-*-asm*-
+#
+# Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# mulsi3.S
+#
+# Multiply operation for 32 bit integers.
+# Input : Operand1 in Reg r5
+# Operand2 in Reg r6
+# Output: Result [op1 * op2] in Reg r3
+#
+#######################################
+
+ .globl __mulsi3
+ .ent __mulsi3
+ .type __mulsi3,@function
+__mulsi3:
+ .frame r1,0,r15
+ add r3,r0,r0
+ BEQI r5,$L_Result_Is_Zero # Multiply by Zero
+ BEQI r6,$L_Result_Is_Zero # Multiply by Zero
+ BGEId r5,$L_R5_Pos
+ XOR r4,r5,r6 # Get the sign of the result
+ RSUBI r5,r5,0 # Make r5 positive
+$L_R5_Pos:
+ BGEI r6,$L_R6_Pos
+ RSUBI r6,r6,0 # Make r6 positive
+$L_R6_Pos:
+ bri $L1
+$L2:
+ add r5,r5,r5
+$L1:
+ srl r6,r6
+ addc r7,r0,r0
+ beqi r7,$L2
+ bneid r6,$L2
+ add r3,r3,r5
+ blti r4,$L_NegateResult
+ rtsd r15,8
+ nop
+$L_NegateResult:
+ rtsd r15,8
+ rsub r3,r3,r0
+$L_Result_Is_Zero:
+ rtsd r15,8
+ addi r3,r0,0
+ .end __mulsi3
+ .size __mulsi3, . - __mulsi3
diff --git a/libgcc/config/microblaze/mulsi3.asm b/libgcc/config/microblaze/mulsi3.asm
deleted file mode 100644
index 03fe0288df8..00000000000
--- a/libgcc/config/microblaze/mulsi3.asm
+++ /dev/null
@@ -1,69 +0,0 @@
-###################################-*-asm*-
-#
-# Copyright 2009, 2010 Free Software Foundation, Inc.
-#
-# Contributed by Michael Eager <eager@eagercon.com>.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, 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.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# mulsi3.asm
-#
-# Multiply operation for 32 bit integers.
-# Input : Operand1 in Reg r5
-# Operand2 in Reg r6
-# Output: Result [op1 * op2] in Reg r3
-#
-#######################################
-
- .globl __mulsi3
- .ent __mulsi3
- .type __mulsi3,@function
-__mulsi3:
- .frame r1,0,r15
- add r3,r0,r0
- BEQI r5,$L_Result_Is_Zero # Multiply by Zero
- BEQI r6,$L_Result_Is_Zero # Multiply by Zero
- BGEId r5,$L_R5_Pos
- XOR r4,r5,r6 # Get the sign of the result
- RSUBI r5,r5,0 # Make r5 positive
-$L_R5_Pos:
- BGEI r6,$L_R6_Pos
- RSUBI r6,r6,0 # Make r6 positive
-$L_R6_Pos:
- bri $L1
-$L2:
- add r5,r5,r5
-$L1:
- srl r6,r6
- addc r7,r0,r0
- beqi r7,$L2
- bneid r6,$L2
- add r3,r3,r5
- blti r4,$L_NegateResult
- rtsd r15,8
- nop
-$L_NegateResult:
- rtsd r15,8
- rsub r3,r3,r0
-$L_Result_Is_Zero:
- rtsd r15,8
- addi r3,r0,0
- .end __mulsi3
- .size __mulsi3, . - __mulsi3
diff --git a/libgcc/config/microblaze/stack_overflow_exit.S b/libgcc/config/microblaze/stack_overflow_exit.S
new file mode 100644
index 00000000000..98182a2b361
--- /dev/null
+++ b/libgcc/config/microblaze/stack_overflow_exit.S
@@ -0,0 +1,61 @@
+###################################-*-asm*-
+#
+# Copyright 2009, 2011 Free Software Foundation, Inc.
+#
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# stack_overflow_exit.S
+#
+# Checks for stack overflows and sets the global variable
+# stack_overflow_error with the value of current stack pointer
+#
+# This routine exits from the program
+#
+#######################################
+
+ .globl _stack_overflow_error
+ .data
+ .align 2
+ .type _stack_overflow_error,@object
+ .size _stack_overflow_error,4
+_stack_overflow_error:
+ .data32 0
+
+ .text
+ .globl _stack_overflow_exit
+ .ent _stack_overflow_exit
+ .type _stack_overflow_exit,@function
+
+_stack_overflow_exit:
+#ifdef __PIC__
+ mfs r20,rpc
+ addik r20,r20,_GLOBAL_OFFSET_TABLE_+8
+ swi r1,r20,_stack_overflow_error@GOTOFF
+ bri exit@PLT
+#else
+ swi r1,r0,_stack_overflow_error
+ bri exit
+#endif
+
+ .end _stack_overflow_exit
+ .size _stack_overflow_exit,. - _stack_overflow_exit
diff --git a/libgcc/config/microblaze/stack_overflow_exit.asm b/libgcc/config/microblaze/stack_overflow_exit.asm
deleted file mode 100644
index 30b31f0a5ba..00000000000
--- a/libgcc/config/microblaze/stack_overflow_exit.asm
+++ /dev/null
@@ -1,61 +0,0 @@
-###################################-*-asm*-
-#
-# Copyright 2009 Free Software Foundation, Inc.
-#
-#
-# Contributed by Michael Eager <eager@eagercon.com>.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, 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.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# stack_overflow_exit.asm
-#
-# Checks for stack overflows and sets the global variable
-# stack_overflow_error with the value of current stack pointer
-#
-# This routine exits from the program
-#
-#######################################
-
- .globl _stack_overflow_error
- .data
- .align 2
- .type _stack_overflow_error,@object
- .size _stack_overflow_error,4
-_stack_overflow_error:
- .data32 0
-
- .text
- .globl _stack_overflow_exit
- .ent _stack_overflow_exit
- .type _stack_overflow_exit,@function
-
-_stack_overflow_exit:
-#ifdef __PIC__
- mfs r20,rpc
- addik r20,r20,_GLOBAL_OFFSET_TABLE_+8
- swi r1,r20,_stack_overflow_error@GOTOFF
- bri exit@PLT
-#else
- swi r1,r0,_stack_overflow_error
- bri exit
-#endif
-
- .end _stack_overflow_exit
- .size _stack_overflow_exit,. - _stack_overflow_exit
diff --git a/libgcc/config/microblaze/t-microblaze b/libgcc/config/microblaze/t-microblaze
index 85fc8d39d8a..3a9c7ff23fe 100644
--- a/libgcc/config/microblaze/t-microblaze
+++ b/libgcc/config/microblaze/t-microblaze
@@ -1,12 +1,10 @@
LIB2ADD += \
- $(srcdir)/config/microblaze/divsi3.asm \
- $(srcdir)/config/microblaze/moddi3.asm \
- $(srcdir)/config/microblaze/modsi3.asm \
- $(srcdir)/config/microblaze/muldi3_hard.asm \
- $(srcdir)/config/microblaze/mulsi3.asm \
- $(srcdir)/config/microblaze/stack_overflow_exit.asm \
- $(srcdir)/config/microblaze/udivsi3.asm \
- $(srcdir)/config/microblaze/umodsi3.asm \
+ $(srcdir)/config/microblaze/divsi3.S \
+ $(srcdir)/config/microblaze/moddi3.S \
+ $(srcdir)/config/microblaze/modsi3.S \
+ $(srcdir)/config/microblaze/muldi3_hard.S \
+ $(srcdir)/config/microblaze/mulsi3.S \
+ $(srcdir)/config/microblaze/stack_overflow_exit.S \
+ $(srcdir)/config/microblaze/udivsi3.S \
+ $(srcdir)/config/microblaze/umodsi3.S \
$(srcdir)/config/microblaze/divsi3_table.c
-
-MULTILIB_OPTIONS = mxl-barrel-shift mno-xl-soft-mul mxl-multiply-high
diff --git a/libgcc/config/microblaze/udivsi3.S b/libgcc/config/microblaze/udivsi3.S
new file mode 100644
index 00000000000..07a2d658092
--- /dev/null
+++ b/libgcc/config/microblaze/udivsi3.S
@@ -0,0 +1,103 @@
+###################################-
+#
+# Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# udivsi3.S
+#
+# Unsigned divide operation.
+# Input : Divisor in Reg r5
+# Dividend in Reg r6
+# Output: Result in Reg r3
+#
+#######################################
+
+ .globl __udivsi3
+ .ent __udivsi3
+ .type __udivsi3,@function
+__udivsi3:
+ .frame r1,0,r15
+
+ ADDIK r1,r1,-12
+ SWI r29,r1,0
+ SWI r30,r1,4
+ SWI r31,r1,8
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQID r5,$LaResult_Is_Zero # Result is Zero
+ ADDIK r30,r0,0 # Clear mod
+ ADDIK r29,r0,32 # Initialize the loop count
+
+ # Check if r6 and r5 are equal # if yes, return 1
+ RSUB r18,r5,r6
+ BEQID r18,$LaRETURN_HERE
+ ADDIK r3,r0,1
+
+ # Check if (uns)r6 is greater than (uns)r5. In that case, just return 0
+ XOR r18,r5,r6
+ BGEID r18,16
+ ADD r3,r0,r0 # We would anyways clear r3
+ BLTI r6,$LaRETURN_HERE # r6[bit 31 = 1] hence is greater
+ BRI $LCheckr6
+ RSUB r18,r6,r5 # MICROBLAZEcmp
+ BLTI r18,$LaRETURN_HERE
+
+ # If r6 [bit 31] is set, then return result as 1
+$LCheckr6:
+ BGTI r6,$LaDIV0
+ BRID $LaRETURN_HERE
+ ADDIK r3,r0,1
+
+ # First part try to find the first '1' in the r5
+$LaDIV0:
+ BLTI r5,$LaDIV2
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGTID r5,$LaDIV1
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r30,r30,r30 # Move that bit into the Mod register
+ RSUB r31,r6,r30 # Try to subtract (r30 a r6)
+ BLTI r31,$LaMOD_TOO_SMALL
+ OR r30,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r3,r3,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r3,r3,r3 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BRI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ OR r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+ # Restore values of CSRs and that of r3 and the divisor and the dividend
+ LWI r29,r1,0
+ LWI r30,r1,4
+ LWI r31,r1,8
+ RTSD r15,8
+ ADDIK r1,r1,12
+ .end __udivsi3
+ .size __udivsi3, . - __udivsi3
diff --git a/libgcc/config/microblaze/udivsi3.asm b/libgcc/config/microblaze/udivsi3.asm
deleted file mode 100644
index 879cd349ca7..00000000000
--- a/libgcc/config/microblaze/udivsi3.asm
+++ /dev/null
@@ -1,103 +0,0 @@
-###################################-
-#
-# Copyright 2009, 2010 Free Software Foundation, Inc.
-#
-# Contributed by Michael Eager <eager@eagercon.com>.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, 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.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# udivsi3.asm
-#
-# Unsigned divide operation.
-# Input : Divisor in Reg r5
-# Dividend in Reg r6
-# Output: Result in Reg r3
-#
-#######################################
-
- .globl __udivsi3
- .ent __udivsi3
- .type __udivsi3,@function
-__udivsi3:
- .frame r1,0,r15
-
- ADDIK r1,r1,-12
- SWI r29,r1,0
- SWI r30,r1,4
- SWI r31,r1,8
-
- BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
- BEQID r5,$LaResult_Is_Zero # Result is Zero
- ADDIK r30,r0,0 # Clear mod
- ADDIK r29,r0,32 # Initialize the loop count
-
- # Check if r6 and r5 are equal # if yes, return 1
- RSUB r18,r5,r6
- BEQID r18,$LaRETURN_HERE
- ADDIK r3,r0,1
-
- # Check if (uns)r6 is greater than (uns)r5. In that case, just return 0
- XOR r18,r5,r6
- BGEID r18,16
- ADD r3,r0,r0 # We would anyways clear r3
- BLTI r6,$LaRETURN_HERE # r6[bit 31 = 1] hence is greater
- BRI $LCheckr6
- RSUB r18,r6,r5 # MICROBLAZEcmp
- BLTI r18,$LaRETURN_HERE
-
- # If r6 [bit 31] is set, then return result as 1
-$LCheckr6:
- BGTI r6,$LaDIV0
- BRID $LaRETURN_HERE
- ADDIK r3,r0,1
-
- # First part try to find the first '1' in the r5
-$LaDIV0:
- BLTI r5,$LaDIV2
-$LaDIV1:
- ADD r5,r5,r5 # left shift logical r5
- BGTID r5,$LaDIV1
- ADDIK r29,r29,-1
-$LaDIV2:
- ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
- ADDC r30,r30,r30 # Move that bit into the Mod register
- RSUB r31,r6,r30 # Try to subtract (r30 a r6)
- BLTI r31,$LaMOD_TOO_SMALL
- OR r30,r0,r31 # Move the r31 to mod since the result was positive
- ADDIK r3,r3,1
-$LaMOD_TOO_SMALL:
- ADDIK r29,r29,-1
- BEQi r29,$LaLOOP_END
- ADD r3,r3,r3 # Shift in the '1' into div
- BRI $LaDIV2 # Div2
-$LaLOOP_END:
- BRI $LaRETURN_HERE
-$LaDiv_By_Zero:
-$LaResult_Is_Zero:
- OR r3,r0,r0 # set result to 0
-$LaRETURN_HERE:
- # Restore values of CSRs and that of r3 and the divisor and the dividend
- LWI r29,r1,0
- LWI r30,r1,4
- LWI r31,r1,8
- RTSD r15,8
- ADDIK r1,r1,12
- .end __udivsi3
- .size __udivsi3, . - __udivsi3
diff --git a/libgcc/config/microblaze/umodsi3.S b/libgcc/config/microblaze/umodsi3.S
new file mode 100644
index 00000000000..67de12c84ac
--- /dev/null
+++ b/libgcc/config/microblaze/umodsi3.S
@@ -0,0 +1,106 @@
+###################################
+#
+# Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# Contributed by Michael Eager <eager@eagercon.com>.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, 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.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+# umodsi3.S
+#
+# Unsigned modulo operation for 32 bit integers.
+# Input : op1 in Reg r5
+# op2 in Reg r6
+# Output: op1 mod op2 in Reg r3
+#
+#######################################
+
+ .globl __umodsi3
+ .ent __umodsi3
+ .type __umodsi3,@function
+__umodsi3:
+ .frame r1,0,r15
+
+ addik r1,r1,-12
+ swi r29,r1,0
+ swi r30,r1,4
+ swi r31,r1,8
+
+ BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
+ BEQId r5,$LaResult_Is_Zero # Result is Zero
+ ADDIK r3,r0,0 # Clear div
+ ADDIK r30,r0,0 # clear mod
+ ADDIK r29,r0,32 # Initialize the loop count
+
+# Check if r6 and r5 are equal # if yes, return 0
+ rsub r18,r5,r6
+ beqi r18,$LaRETURN_HERE
+
+# Check if (uns)r6 is greater than (uns)r5. In that case, just return r5
+ xor r18,r5,r6
+ bgeid r18,16
+ addik r3,r5,0
+ blti r6,$LaRETURN_HERE
+ bri $LCheckr6
+ rsub r18,r5,r6 # MICROBLAZEcmp
+ bgti r18,$LaRETURN_HERE
+
+# If r6 [bit 31] is set, then return result as r5-r6
+$LCheckr6:
+ bgtid r6,$LaDIV0
+ addik r3,r0,0
+ addik r18,r0,0x7fffffff
+ and r5,r5,r18
+ and r6,r6,r18
+ brid $LaRETURN_HERE
+ rsub r3,r6,r5
+# First part: try to find the first '1' in the r5
+$LaDIV0:
+ BLTI r5,$LaDIV2
+$LaDIV1:
+ ADD r5,r5,r5 # left shift logical r5
+ BGEID r5,$LaDIV1 #
+ ADDIK r29,r29,-1
+$LaDIV2:
+ ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
+ ADDC r3,r3,r3 # Move that bit into the Mod register
+ rSUB r31,r6,r3 # Try to subtract (r3 a r6)
+ BLTi r31,$LaMOD_TOO_SMALL
+ OR r3,r0,r31 # Move the r31 to mod since the result was positive
+ ADDIK r30,r30,1
+$LaMOD_TOO_SMALL:
+ ADDIK r29,r29,-1
+ BEQi r29,$LaLOOP_END
+ ADD r30,r30,r30 # Shift in the '1' into div
+ BRI $LaDIV2 # Div2
+$LaLOOP_END:
+ BRI $LaRETURN_HERE
+$LaDiv_By_Zero:
+$LaResult_Is_Zero:
+ or r3,r0,r0 # set result to 0
+$LaRETURN_HERE:
+# Restore values of CSRs and that of r3 and the divisor and the dividend
+ lwi r29,r1,0
+ lwi r30,r1,4
+ lwi r31,r1,8
+ rtsd r15,8
+ addik r1,r1,12
+.end __umodsi3
+ .size __umodsi3, . - __umodsi3
diff --git a/libgcc/config/microblaze/umodsi3.asm b/libgcc/config/microblaze/umodsi3.asm
deleted file mode 100644
index f7fd0087965..00000000000
--- a/libgcc/config/microblaze/umodsi3.asm
+++ /dev/null
@@ -1,106 +0,0 @@
-###################################
-#
-# Copyright 2009, 2010 Free Software Foundation, Inc.
-#
-# Contributed by Michael Eager <eager@eagercon.com>.
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, 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.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-#
-# umodsi3.asm
-#
-# Unsigned modulo operation for 32 bit integers.
-# Input : op1 in Reg r5
-# op2 in Reg r6
-# Output: op1 mod op2 in Reg r3
-#
-#######################################
-
- .globl __umodsi3
- .ent __umodsi3
- .type __umodsi3,@function
-__umodsi3:
- .frame r1,0,r15
-
- addik r1,r1,-12
- swi r29,r1,0
- swi r30,r1,4
- swi r31,r1,8
-
- BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
- BEQId r5,$LaResult_Is_Zero # Result is Zero
- ADDIK r3,r0,0 # Clear div
- ADDIK r30,r0,0 # clear mod
- ADDIK r29,r0,32 # Initialize the loop count
-
-# Check if r6 and r5 are equal # if yes, return 0
- rsub r18,r5,r6
- beqi r18,$LaRETURN_HERE
-
-# Check if (uns)r6 is greater than (uns)r5. In that case, just return r5
- xor r18,r5,r6
- bgeid r18,16
- addik r3,r5,0
- blti r6,$LaRETURN_HERE
- bri $LCheckr6
- rsub r18,r5,r6 # MICROBLAZEcmp
- bgti r18,$LaRETURN_HERE
-
-# If r6 [bit 31] is set, then return result as r5-r6
-$LCheckr6:
- bgtid r6,$LaDIV0
- addik r3,r0,0
- addik r18,r0,0x7fffffff
- and r5,r5,r18
- and r6,r6,r18
- brid $LaRETURN_HERE
- rsub r3,r6,r5
-# First part: try to find the first '1' in the r5
-$LaDIV0:
- BLTI r5,$LaDIV2
-$LaDIV1:
- ADD r5,r5,r5 # left shift logical r5
- BGEID r5,$LaDIV1 #
- ADDIK r29,r29,-1
-$LaDIV2:
- ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
- ADDC r3,r3,r3 # Move that bit into the Mod register
- rSUB r31,r6,r3 # Try to subtract (r3 a r6)
- BLTi r31,$LaMOD_TOO_SMALL
- OR r3,r0,r31 # Move the r31 to mod since the result was positive
- ADDIK r30,r30,1
-$LaMOD_TOO_SMALL:
- ADDIK r29,r29,-1
- BEQi r29,$LaLOOP_END
- ADD r30,r30,r30 # Shift in the '1' into div
- BRI $LaDIV2 # Div2
-$LaLOOP_END:
- BRI $LaRETURN_HERE
-$LaDiv_By_Zero:
-$LaResult_Is_Zero:
- or r3,r0,r0 # set result to 0
-$LaRETURN_HERE:
-# Restore values of CSRs and that of r3 and the divisor and the dividend
- lwi r29,r1,0
- lwi r30,r1,4
- lwi r31,r1,8
- rtsd r15,8
- addik r1,r1,12
-.end __umodsi3
- .size __umodsi3, . - __umodsi3
diff --git a/gcc/config/mips/crti.asm b/libgcc/config/mips/crti.S
index ac04271c598..ac04271c598 100644
--- a/gcc/config/mips/crti.asm
+++ b/libgcc/config/mips/crti.S
diff --git a/gcc/config/mips/crtn.asm b/libgcc/config/mips/crtn.S
index 03a6b68c9cf..03a6b68c9cf 100644
--- a/gcc/config/mips/crtn.asm
+++ b/libgcc/config/mips/crtn.S
diff --git a/gcc/gthr-mipssde.h b/libgcc/config/mips/gthr-mipssde.h
index 34f9b6cf54b..34f9b6cf54b 100644
--- a/gcc/gthr-mipssde.h
+++ b/libgcc/config/mips/gthr-mipssde.h
diff --git a/gcc/config/mips/libgcc-mips16.ver b/libgcc/config/mips/libgcc-mips16.ver
index ddb23e7e750..ddb23e7e750 100644
--- a/gcc/config/mips/libgcc-mips16.ver
+++ b/libgcc/config/mips/libgcc-mips16.ver
diff --git a/gcc/config/mips/mips16.S b/libgcc/config/mips/mips16.S
index ec331b5f65e..ec331b5f65e 100644
--- a/gcc/config/mips/mips16.S
+++ b/libgcc/config/mips/mips16.S
diff --git a/libgcc/config/mips/t-crtstuff b/libgcc/config/mips/t-crtstuff
new file mode 100644
index 00000000000..d8ab43be2ae
--- /dev/null
+++ b/libgcc/config/mips/t-crtstuff
@@ -0,0 +1,2 @@
+# Don't let CTOR_LIST end up in sdata section.
+CRTSTUFF_T_CFLAGS = -G 0
diff --git a/libgcc/config/mips/t-elf b/libgcc/config/mips/t-elf
new file mode 100644
index 00000000000..3a1dfd7648c
--- /dev/null
+++ b/libgcc/config/mips/t-elf
@@ -0,0 +1,3 @@
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+HOST_LIBGCC2_CFLAGS = -G 0
diff --git a/libgcc/config/mips/t-mips b/libgcc/config/mips/t-mips
index b7d13b3ddb3..719c062ef0d 100644
--- a/libgcc/config/mips/t-mips
+++ b/libgcc/config/mips/t-mips
@@ -1,3 +1,5 @@
+LIB2_SIDITI_CONV_FUNCS = yes
+
FPBIT = true
FPBIT_CFLAGS = -DQUIET_NAN_NEGATED
DPBIT = true
diff --git a/libgcc/config/mips/t-mips16 b/libgcc/config/mips/t-mips16
index 94fa0e94275..5553ed76e2d 100644
--- a/libgcc/config/mips/t-mips16
+++ b/libgcc/config/mips/t-mips16
@@ -1,2 +1,45 @@
+# Copyright (C) 2007, 2008, 2011 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+LIB1ASMSRC = mips/mips16.S
+LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \
+ _m16eqsf2 _m16nesf2 _m16gtsf2 _m16gesf2 _m16lesf2 _m16ltsf2 \
+ _m16unordsf2 \
+ _m16fltsisf _m16fix_truncsfsi _m16fltunsisf \
+ _m16adddf3 _m16subdf3 _m16muldf3 _m16divdf3 \
+ _m16extsfdf2 _m16trdfsf2 \
+ _m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \
+ _m16unorddf2 \
+ _m16fltsidf _m16fix_truncdfsi _m16fltunsidf \
+ _m16retsf _m16retdf \
+ _m16retsc _m16retdc \
+ _m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \
+ _m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \
+ _m16stubsf9 _m16stubsf10 \
+ _m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \
+ _m16stubdf9 _m16stubdf10 \
+ _m16stubsc0 _m16stubsc1 _m16stubsc2 _m16stubsc5 _m16stubsc6 \
+ _m16stubsc9 _m16stubsc10 \
+ _m16stubdc0 _m16stubdc1 _m16stubdc2 _m16stubdc5 _m16stubdc6 \
+ _m16stubdc9 _m16stubdc10
+
SYNC = yes
SYNC_CFLAGS = -mno-mips16
+
+# Version these symbols if building libgcc.so.
+SHLIB_MAPFILES += $(srcdir)/config/mips/libgcc-mips16.ver
diff --git a/libgcc/config/mips/t-slibgcc-irix b/libgcc/config/mips/t-slibgcc-irix
index 6e0ac365437..47b2e0eec21 100644
--- a/libgcc/config/mips/t-slibgcc-irix
+++ b/libgcc/config/mips/t-slibgcc-irix
@@ -3,5 +3,5 @@
SHLIB_LDFLAGS = -Wl,-soname,$(SHLIB_SONAME) \
-Wl,-exports_file,$(SHLIB_MAP)
-SHLIB_MKMAP = $(gcc_srcdir)/mkmap-flat.awk
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
SHLIB_MAPFILES = libgcc-std.ver
diff --git a/libgcc/config/mips/t-vr b/libgcc/config/mips/t-vr
new file mode 100644
index 00000000000..601fbdece1a
--- /dev/null
+++ b/libgcc/config/mips/t-vr
@@ -0,0 +1,2 @@
+LIB2ADD_ST = $(srcdir)/config/mips/mips16.S \
+ $(srcdir)/config/mips/vr4120-div.S
diff --git a/gcc/config/mips/vr4120-div.S b/libgcc/config/mips/vr4120-div.S
index 79ede3de955..79ede3de955 100644
--- a/gcc/config/mips/vr4120-div.S
+++ b/libgcc/config/mips/vr4120-div.S
diff --git a/libgcc/config/mmix/crti.S b/libgcc/config/mmix/crti.S
new file mode 100644
index 00000000000..69858046975
--- /dev/null
+++ b/libgcc/config/mmix/crti.S
@@ -0,0 +1,116 @@
+/* Copyright (C) 2001, 2002, 2011 Free Software Foundation, Inc.
+ Contributed by Hans-Peter Nilsson <hp@bitrange.com>
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+% This is the crt0 equivalent for mmix-knuth-mmixware, for setting up
+% things for compiler-generated assembly-code and for setting up things
+% between where the simulator calls and main, and shutting things down on
+% the way back. There's an actual crt0.o elsewhere, but that's a dummy.
+
+% This file and the GCC output are supposed to be *reasonably*
+% mmixal-compatible to enable people to re-use output with Knuth's mmixal.
+% However, forward references are used more freely: we are using the
+% binutils tools. Users of mmixal beware; you will sometimes have to
+% re-order things or use temporary variables.
+
+% Users of mmixal will want to set up 8H and 9H to be .text and .data
+% respectively, so the compiler can switch between them pretending they're
+% segments.
+
+% This little treasure is here so the 32 lowest address bits of user data
+% will not be zero. Because of truncation, that would cause testcase
+% gcc.c-torture/execute/980701-1.c to incorrectly fail.
+
+ .data ! mmixal:= 8H LOC Data_Segment
+ .p2align 3
+ LOC @+(8-@)@7
+ OCTA 2009
+
+ .text ! mmixal:= 9H LOC 8B; LOC #100
+ .global Main
+
+% The __Stack_start symbol is provided by the link script.
+stackpp OCTA __Stack_start
+
+% "Main" is the magic symbol the simulator jumps to. We want to go
+% on to "main".
+% We need to set rG explicitly to avoid hard-to-debug situations.
+Main SETL $255,32
+ PUT rG,$255
+
+% Initialize the stack pointer. It is supposedly made a global
+% zero-initialized (allowed to change) register in crtn.S; we use the
+% explicit number.
+ GETA $255,stackpp
+ LDOU $254,$255,0
+
+% Make sure we get more than one mem, to simplify counting cycles.
+ LDBU $255,$1,0
+ LDBU $255,$1,1
+
+ PUSHJ $2,_init
+
+#ifdef __MMIX_ABI_GNU__
+% Copy argc and argv from their initial position to argument registers
+% where necessary.
+ SET $231,$0
+ SET $232,$1
+#else
+% For the mmixware ABI, we need to move arguments. The return value will
+% appear in $0.
+ SET $2,$1
+ SET $1,$0
+#endif
+
+ PUSHJ $0,main
+ JMP exit
+
+% Provide the first part of _init and _fini. Save the return address on the
+% register stack. We eventually ignore the return address of these
+% PUSHJ:s, so it doesn't matter that whether .init and .fini code calls
+% functions or where they store rJ. We shouldn't get there, so die
+% (TRAP Halt) if that happens.
+
+ .section .init,"ax",@progbits
+ .global _init
+_init:
+ GET $0,:rJ
+ PUSHJ $1,0F
+ SETL $255,255
+ TRAP 0,0,0
+0H IS @
+
+% Register _fini to be executed as the last atexit function.
+#ifdef __MMIX_ABI_GNU__
+ GETA $231,_fini
+#else
+ GETA $1,_fini
+#endif
+ PUSHJ $0,atexit
+
+ .section .fini,"ax",@progbits
+ .global _fini
+_fini:
+ GET $0,:rJ
+ PUSHJ $1,0F
+ SETL $255,255
+ TRAP 0,0,0
+0H IS @
diff --git a/gcc/config/mmix/crtn.asm b/libgcc/config/mmix/crtn.S
index c109e54db01..c109e54db01 100644
--- a/gcc/config/mmix/crtn.asm
+++ b/libgcc/config/mmix/crtn.S
diff --git a/libgcc/config/mmix/t-mmix b/libgcc/config/mmix/t-mmix
index 9d66737e256..40ee1e4bdb1 100644
--- a/libgcc/config/mmix/t-mmix
+++ b/libgcc/config/mmix/t-mmix
@@ -1,14 +1,22 @@
+HOST_LIBGCC2_CFLAGS = -mlibfuncs -O2
+
+# We need to turn off some assumptions on normality for code in crtstuff.c
+# and crt{i,n}.S, specifically about execution not continuing past the
+# end of the section in the file being compiled. Thus we must stop the
+# assembler from generating stubbable PUSHJ relocs, because that will add
+# stubs at the end of the current section when necessary.
+CRTSTUFF_T_CFLAGS = -Wa,--no-stubs
+
# Don't use global registers in libraries.
# FIXME: Not applied at "root" level, so disabled at the moment to stop
# incorrect comparisons with -mabi=gnu.
#MULTILIB_EXTRA_OPTS = mno-base-addresses
-$(T)crti.o: $(gcc_srcdir)/config/mmix/crti.asm $(GCC_PASSES)
- $(crt_compile) $(INCLUDES) \
- $(CRTSTUFF_T_CFLAGS) -c -x assembler-with-cpp \
- $(gcc_srcdir)/config/mmix/crti.asm
+# Cannot use default rules due to $(CRTSTUFF_T_CFLAGS).
+CUSTOM_CRTIN = yes
+
+crti.o: $(srcdir)/config/mmix/crti.S
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $<
-$(T)crtn.o: $(gcc_srcdir)/config/mmix/crtn.asm $(GCC_PASSES)
- $(crt_compile) $(INCLUDES) \
- $(CRTSTUFF_T_CFLAGS) -c -x assembler-with-cpp \
- $(gcc_srcdir)/config/mmix/crtn.asm
+crtn.o: $(srcdir)/config/mmix/crtn.S
+ $(crt_compile) $(CRTSTUFF_T_CFLAGS) -c $<
diff --git a/libgcc/config/moxie/crti.S b/libgcc/config/moxie/crti.S
new file mode 100644
index 00000000000..c59d3ecf0ef
--- /dev/null
+++ b/libgcc/config/moxie/crti.S
@@ -0,0 +1,40 @@
+# crti.S for moxie
+#
+# Copyright (C) 2009, 2011 Free Software Foundation
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file just make a stack frame for the contents of the .fini and
+# .init sections. Users may put any desired instructions in those
+# sections.
+
+ .file "crti.S"
+
+ .section ".init"
+ .global _init
+ .type _init, @function
+ .p2align 1
+_init:
+
+ .section ".fini"
+ .global _fini
+ .type _fini,@function
+ .p2align 1
+_fini:
diff --git a/libgcc/config/moxie/crti.asm b/libgcc/config/moxie/crti.asm
deleted file mode 100644
index f44582799a3..00000000000
--- a/libgcc/config/moxie/crti.asm
+++ /dev/null
@@ -1,40 +0,0 @@
-# crti.asm for moxie
-#
-# Copyright (C) 2009 Free Software Foundation
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file just make a stack frame for the contents of the .fini and
-# .init sections. Users may put any desired instructions in those
-# sections.
-
- .file "crti.asm"
-
- .section ".init"
- .global _init
- .type _init, @function
- .p2align 1
-_init:
-
- .section ".fini"
- .global _fini
- .type _fini,@function
- .p2align 1
-_fini:
diff --git a/libgcc/config/moxie/crtn.S b/libgcc/config/moxie/crtn.S
new file mode 100644
index 00000000000..4455237a602
--- /dev/null
+++ b/libgcc/config/moxie/crtn.S
@@ -0,0 +1,34 @@
+# crtn.S for moxie
+#
+# Copyright (C) 2009, 2011 Free Software Foundation
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file just makes sure that the .fini and .init sections do in
+# fact return. Users may put any desired instructions in those sections.
+# This file is the last thing linked into any executable.
+
+ .file "crtn.S"
+
+ .section ".init"
+ ret
+
+ .section ".fini"
+ ret
diff --git a/libgcc/config/moxie/crtn.asm b/libgcc/config/moxie/crtn.asm
deleted file mode 100644
index 3ac9d31eed8..00000000000
--- a/libgcc/config/moxie/crtn.asm
+++ /dev/null
@@ -1,34 +0,0 @@
-# crtn.asm for moxie
-#
-# Copyright (C) 2009 Free Software Foundation
-#
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 3, or (at your option) any
-# later version.
-#
-# This file is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# Under Section 7 of GPL version 3, you are granted additional
-# permissions described in the GCC Runtime Library Exception, version
-# 3.1, as published by the Free Software Foundation.
-#
-# You should have received a copy of the GNU General Public License and
-# a copy of the GCC Runtime Library Exception along with this program;
-# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
-# <http://www.gnu.org/licenses/>.
-
-# This file just makes sure that the .fini and .init sections do in
-# fact return. Users may put any desired instructions in those sections.
-# This file is the last thing linked into any executable.
-
- .file "crtn.asm"
-
- .section ".init"
- ret
-
- .section ".fini"
- ret
diff --git a/libgcc/config/moxie/t-moxie b/libgcc/config/moxie/t-moxie
deleted file mode 100644
index 6e62aec2224..00000000000
--- a/libgcc/config/moxie/t-moxie
+++ /dev/null
@@ -1,9 +0,0 @@
-# Assemble startup files.
-
-$(T)crti.o: $(srcdir)/config/moxie/crti.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/moxie/crti.asm
-
-$(T)crtn.o: $(srcdir)/config/moxie/crtn.asm $(GCC_PASSES)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/moxie/crtn.asm
diff --git a/gcc/config/pa/fptr.c b/libgcc/config/pa/fptr.c
index 320d18267c8..320d18267c8 100644
--- a/gcc/config/pa/fptr.c
+++ b/libgcc/config/pa/fptr.c
diff --git a/gcc/gthr-dce.h b/libgcc/config/pa/gthr-dce.h
index d32155a9352..d32155a9352 100644
--- a/gcc/gthr-dce.h
+++ b/libgcc/config/pa/gthr-dce.h
diff --git a/gcc/config/pa/lib2funcs.asm b/libgcc/config/pa/lib2funcs.S
index 8aa398c8797..8aa398c8797 100644
--- a/gcc/config/pa/lib2funcs.asm
+++ b/libgcc/config/pa/lib2funcs.S
diff --git a/gcc/config/pa/linux-atomic.c b/libgcc/config/pa/linux-atomic.c
index 2ae2426357a..2ae2426357a 100644
--- a/gcc/config/pa/linux-atomic.c
+++ b/libgcc/config/pa/linux-atomic.c
diff --git a/gcc/config/pa/milli64.S b/libgcc/config/pa/milli64.S
index 2e9c4f741b6..2e9c4f741b6 100644
--- a/gcc/config/pa/milli64.S
+++ b/libgcc/config/pa/milli64.S
diff --git a/gcc/config/pa/quadlib.c b/libgcc/config/pa/quadlib.c
index 2c1160015ed..2c1160015ed 100644
--- a/gcc/config/pa/quadlib.c
+++ b/libgcc/config/pa/quadlib.c
diff --git a/gcc/config/pa/stublib.c b/libgcc/config/pa/stublib.c
index d3cf559c8ab..d3cf559c8ab 100644
--- a/gcc/config/pa/stublib.c
+++ b/libgcc/config/pa/stublib.c
diff --git a/libgcc/config/pa/t-hpux b/libgcc/config/pa/t-hpux
new file mode 100644
index 00000000000..fcf93aba3ab
--- /dev/null
+++ b/libgcc/config/pa/t-hpux
@@ -0,0 +1,3 @@
+LIB2ADD = $(srcdir)/config/pa/lib2funcs.S $(srcdir)/config/pa/quadlib.c
+
+HOST_LIBGCC2_CFLAGS += -frandom-seed=fixed-seed
diff --git a/libgcc/config/pa/t-hpux10 b/libgcc/config/pa/t-hpux10
new file mode 100644
index 00000000000..5620f314a62
--- /dev/null
+++ b/libgcc/config/pa/t-hpux10
@@ -0,0 +1 @@
+HOST_LIBGCC2_CFLAGS += -D_T_HPUX10
diff --git a/libgcc/config/pa/t-linux b/libgcc/config/pa/t-linux
new file mode 100644
index 00000000000..2157de9b007
--- /dev/null
+++ b/libgcc/config/pa/t-linux
@@ -0,0 +1,10 @@
+#Plug millicode routines into libgcc.a We want these on both native and
+#cross compiles. We use the "64-bit" routines because the "32-bit" code
+#is broken for certain corner cases.
+LIB1ASMSRC = pa/milli64.S
+LIB1ASMFUNCS = _divI _divU _remI _remU _div_const _mulI _dyncall
+
+HOST_LIBGCC2_CFLAGS += -DELF=1 -DLINUX=1
+
+LIB2ADD = $(srcdir)/config/pa/fptr.c
+LIB2ADD_ST = $(srcdir)/config/pa/linux-atomic.c
diff --git a/libgcc/config/pa/t-linux64 b/libgcc/config/pa/t-linux64
new file mode 100644
index 00000000000..1d0a6ada1a1
--- /dev/null
+++ b/libgcc/config/pa/t-linux64
@@ -0,0 +1,8 @@
+# Plug millicode routines into libgcc.a We want these on both native and
+# cross compiles.
+# FIXME: Explain.
+LIB1ASMFUNCS := $(filter-out _dyncall, $(LIB1ASMFUNCS))
+
+LIB2ADD_ST = $(srcdir)/config/pa/linux-atomic.c
+
+HOST_LIBGCC2_CFLAGS += -Dpa64=1 -DELF=1
diff --git a/libgcc/config/pa/t-pa64 b/libgcc/config/pa/t-pa64
new file mode 100644
index 00000000000..98f28edb1c6
--- /dev/null
+++ b/libgcc/config/pa/t-pa64
@@ -0,0 +1,3 @@
+LIB2ADD = $(srcdir)/config/pa/quadlib.c
+
+HOST_LIBGCC2_CFLAGS += -Dpa64=1 -DELF=1 -mlong-calls
diff --git a/gcc/config/pa/t-slibgcc-dwarf-ver b/libgcc/config/pa/t-slibgcc-dwarf-ver
index fa4688d6994..fa4688d6994 100644
--- a/gcc/config/pa/t-slibgcc-dwarf-ver
+++ b/libgcc/config/pa/t-slibgcc-dwarf-ver
diff --git a/libgcc/config/pa/t-slibgcc-hpux b/libgcc/config/pa/t-slibgcc-hpux
new file mode 100644
index 00000000000..d7ed64a8652
--- /dev/null
+++ b/libgcc/config/pa/t-slibgcc-hpux
@@ -0,0 +1,25 @@
+# Copyright (C) 2001, 2003, 2004, 2005, 2006, 2011
+# 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Build a shared libgcc library with the HP-UX linker on PA.
+
+SHLIB_EXT = .sl
+SHLIB_SOLINK = @shlib_base_name@$(SHLIB_EXT)
+SHLIB_SONAME = @shlib_base_name@.$(SHLIB_SOVERSION)
+SHLIB_LC =
diff --git a/gcc/config/pa/t-slibgcc-sjlj-ver b/libgcc/config/pa/t-slibgcc-sjlj-ver
index 00140cf204f..00140cf204f 100644
--- a/gcc/config/pa/t-slibgcc-sjlj-ver
+++ b/libgcc/config/pa/t-slibgcc-sjlj-ver
diff --git a/libgcc/config/pa/t-stublib b/libgcc/config/pa/t-stublib
new file mode 100644
index 00000000000..017998ff689
--- /dev/null
+++ b/libgcc/config/pa/t-stublib
@@ -0,0 +1,21 @@
+LIBGCCSTUB_OBJS = pthread_default_stacksize_np-stub.o \
+ pthread_mutex_lock-stub.o \
+ pthread_mutex_unlock-stub.o \
+ pthread_once-stub.o
+
+pthread_default_stacksize_np-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_pthread_default_stacksize_np $<
+
+pthread_mutex_lock-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_pthread_mutex_lock $<
+
+pthread_mutex_unlock-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_pthread_mutex_unlock $<
+
+pthread_once-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_pthread_once $<
+
+libgcc_stub.a: $(LIBGCCSTUB_OBJS)
+ -rm -rf $@
+ $(AR) rc $@ $<
+ $(RANLIB) $@
diff --git a/libgcc/config/pa/t-stublib64 b/libgcc/config/pa/t-stublib64
new file mode 100644
index 00000000000..5d0d9682abf
--- /dev/null
+++ b/libgcc/config/pa/t-stublib64
@@ -0,0 +1,13 @@
+LIBGCCSTUB_OBJS += rfi-stub.o dfi-stub.o jvrc-stub.o cxaf-stub.o
+
+rfi-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_register_frame_info $<
+
+dfi-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_deregister_frame_info $<
+
+cxaf-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_cxa_finalize $<
+
+jvrc-stub.o: $(srcdir)/config/pa/stublib.c
+ $(gcc_compile) -c -O2 -DL_Jv_RegisterClasses $<
diff --git a/libgcc/config/pdp11/t-pdp11 b/libgcc/config/pdp11/t-pdp11
new file mode 100644
index 00000000000..bcd88e4426c
--- /dev/null
+++ b/libgcc/config/pdp11/t-pdp11
@@ -0,0 +1,8 @@
+LIB2ADD = $(srcdir)/udivmod.c \
+ $(srcdir)/udivmodsi4.c \
+ $(srcdir)/memcmp.c \
+ $(srcdir)/memcpy.c \
+ $(srcdir)/memmove.c \
+ $(srcdir)/memset.c
+
+HOST_LIBGCC2_CFLAGS = -O2 -mfloat32
diff --git a/gcc/config/picochip/libgccExtras/adddi3.asm b/libgcc/config/picochip/adddi3.S
index 77373ed9f64..77373ed9f64 100644
--- a/gcc/config/picochip/libgccExtras/adddi3.asm
+++ b/libgcc/config/picochip/adddi3.S
diff --git a/gcc/config/picochip/libgccExtras/ashlsi3.asm b/libgcc/config/picochip/ashlsi3.S
index 688cd8d96ff..688cd8d96ff 100644
--- a/gcc/config/picochip/libgccExtras/ashlsi3.asm
+++ b/libgcc/config/picochip/ashlsi3.S
diff --git a/gcc/config/picochip/libgccExtras/ashlsi3.c b/libgcc/config/picochip/ashlsi3.c
index 600461c0b83..600461c0b83 100644
--- a/gcc/config/picochip/libgccExtras/ashlsi3.c
+++ b/libgcc/config/picochip/ashlsi3.c
diff --git a/gcc/config/picochip/libgccExtras/ashrsi3.asm b/libgcc/config/picochip/ashrsi3.S
index fddd70b6895..fddd70b6895 100644
--- a/gcc/config/picochip/libgccExtras/ashrsi3.asm
+++ b/libgcc/config/picochip/ashrsi3.S
diff --git a/gcc/config/picochip/libgccExtras/ashrsi3.c b/libgcc/config/picochip/ashrsi3.c
index 4f1567b1347..4f1567b1347 100644
--- a/gcc/config/picochip/libgccExtras/ashrsi3.c
+++ b/libgcc/config/picochip/ashrsi3.c
diff --git a/libgcc/config/picochip/clzsi2.S b/libgcc/config/picochip/clzsi2.S
new file mode 100644
index 00000000000..d5c99aa7154
--- /dev/null
+++ b/libgcc/config/picochip/clzsi2.S
@@ -0,0 +1,189 @@
+// Copyright (C) 2008, 2011 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 3, 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.
+//
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+//
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+// picoChip ASM file
+//.file "clzsi2.S"
+
+.section .text
+
+.global __clzsi2
+__clzsi2:
+_picoMark_FUNCTION_BEGIN=
+
+// picoChip Function Prologue : &__clzsi2 = 0 bytes
+
+ // What value should be operated on? If the top word is empty
+ // then count the bits in the bottom word, and add 16. If the
+ // top word is not empty, then count the bits in the top word.
+
+ // R4 stores the constant 0
+
+ sub.0 R1,0,r15 \ copy.1 16,r2
+ copyeq r0,r1
+ copyne 0,r2
+
+ // R1 now stores value to count, and R2 stores current bit offset.
+ sbc r1,r0
+ asr.0 r1,15,r15 \ add.1 r0,1,r0
+ jr (lr) \ copyne 0,r0
+=-> add.0 r0,r2,r0
+
+_picoMark_FUNCTION_END=
+
+// picoChip Function Epilogue : __clzsi2
+
+//============================================================================
+// All DWARF information between this marker, and the END OF DWARF
+// marker should be included in the source file. Search for
+// FUNCTION_STACK_SIZE_GOES_HERE and FUNCTION NAME GOES HERE, and
+// provide the relevent information. Add markers called
+// _picoMark_FUNCTION_BEGIN and _picoMark_FUNCTION_END around the
+// function in question.
+//============================================================================
+
+//============================================================================
+// Frame information.
+//============================================================================
+
+.section .debug_frame
+_picoMark_DebugFrame=
+
+// Common CIE header.
+.unalignedInitLong _picoMark_CieEnd-_picoMark_CieBegin
+_picoMark_CieBegin=
+.unalignedInitLong 0xffffffff
+.initByte 0x1 // CIE Version
+.ascii 16#0# // CIE Augmentation
+.uleb128 0x1 // CIE Code Alignment Factor
+.sleb128 2 // CIE Data Alignment Factor
+.initByte 0xc // CIE RA Column
+.initByte 0xc // DW_CFA_def_cfa
+.uleb128 0xd
+.uleb128 0x0
+.align 2
+_picoMark_CieEnd=
+
+// FDE
+_picoMark_LSFDE0I900821033007563=
+.unalignedInitLong _picoMark_FdeEnd-_picoMark_FdeBegin
+_picoMark_FdeBegin=
+.unalignedInitLong _picoMark_DebugFrame // FDE CIE offset
+.unalignedInitWord _picoMark_FUNCTION_BEGIN // FDE initial location
+.unalignedInitWord _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN
+.initByte 0xe // DW_CFA_def_cfa_offset
+.uleb128 0x0 // <-- FUNCTION_STACK_SIZE_GOES_HERE
+.initByte 0x4 // DW_CFA_advance_loc4
+.unalignedInitLong _picoMark_FUNCTION_END-_picoMark_FUNCTION_BEGIN
+.initByte 0xe // DW_CFA_def_cfa_offset
+.uleb128 0x0
+.align 2
+_picoMark_FdeEnd=
+
+//============================================================================
+// Abbrevation information.
+//============================================================================
+
+.section .debug_abbrev
+_picoMark_ABBREVIATIONS=
+
+.section .debug_abbrev
+ .uleb128 0x1 // (abbrev code)
+ .uleb128 0x11 // (TAG: DW_TAG_compile_unit)
+ .initByte 0x1 // DW_children_yes
+ .uleb128 0x10 // (DW_AT_stmt_list)
+ .uleb128 0x6 // (DW_FORM_data4)
+ .uleb128 0x12 // (DW_AT_high_pc)
+ .uleb128 0x1 // (DW_FORM_addr)
+ .uleb128 0x11 // (DW_AT_low_pc)
+ .uleb128 0x1 // (DW_FORM_addr)
+ .uleb128 0x25 // (DW_AT_producer)
+ .uleb128 0x8 // (DW_FORM_string)
+ .uleb128 0x13 // (DW_AT_language)
+ .uleb128 0x5 // (DW_FORM_data2)
+ .uleb128 0x3 // (DW_AT_name)
+ .uleb128 0x8 // (DW_FORM_string)
+.initByte 0x0
+.initByte 0x0
+
+ .uleb128 0x2 ;# (abbrev code)
+ .uleb128 0x2e ;# (TAG: DW_TAG_subprogram)
+.initByte 0x0 ;# DW_children_no
+ .uleb128 0x3 ;# (DW_AT_name)
+ .uleb128 0x8 ;# (DW_FORM_string)
+ .uleb128 0x11 ;# (DW_AT_low_pc)
+ .uleb128 0x1 ;# (DW_FORM_addr)
+ .uleb128 0x12 ;# (DW_AT_high_pc)
+ .uleb128 0x1 ;# (DW_FORM_addr)
+.initByte 0x0
+.initByte 0x0
+
+.initByte 0x0
+
+//============================================================================
+// Line information. DwarfLib requires this to be present, but it can
+// be empty.
+//============================================================================
+
+.section .debug_line
+_picoMark_LINES=
+
+//============================================================================
+// Debug Information
+//============================================================================
+.section .debug_info
+
+//Fixed header.
+.unalignedInitLong _picoMark_DEBUG_INFO_END-_picoMark_DEBUG_INFO_BEGIN
+_picoMark_DEBUG_INFO_BEGIN=
+.unalignedInitWord 0x2
+.unalignedInitLong _picoMark_ABBREVIATIONS
+.initByte 0x2
+
+// Compile unit information.
+.uleb128 0x1 // (DIE 0xb) DW_TAG_compile_unit)
+.unalignedInitLong _picoMark_LINES
+.unalignedInitWord _picoMark_FUNCTION_END
+.unalignedInitWord _picoMark_FUNCTION_BEGIN
+// Producer is `picoChip'
+.ascii 16#70# 16#69# 16#63# 16#6f# 16#43# 16#68# 16#69# 16#70# 16#00#
+.unalignedInitWord 0xcafe // ASM language
+.ascii 16#0# // Name. DwarfLib expects this to be present.
+
+.uleb128 0x2 ;# (DIE DW_TAG_subprogram)
+
+// FUNCTION NAME GOES HERE. Use `echo name | od -t x1' to get the hex. Each hex
+// digit is specified using the format 16#XX#
+.ascii 16#5F# 16#63# 16#6C# 16#7A# 16#73# 16#69# 16#32# 16#0# // Function name `_clzsi2'
+.unalignedInitWord _picoMark_FUNCTION_BEGIN // DW_AT_low_pc
+.unalignedInitWord _picoMark_FUNCTION_END // DW_AT_high_pc
+
+.initByte 0x0 // end of compile unit children.
+
+_picoMark_DEBUG_INFO_END=
+
+//============================================================================
+// END OF DWARF
+//============================================================================
+
+.section .endFile
+// End of picoChip ASM file
diff --git a/gcc/config/picochip/libgccExtras/cmpsi2.asm b/libgcc/config/picochip/cmpsi2.S
index 95322f32419..95322f32419 100644
--- a/gcc/config/picochip/libgccExtras/cmpsi2.asm
+++ b/libgcc/config/picochip/cmpsi2.S
diff --git a/gcc/config/picochip/libgccExtras/divmod15.asm b/libgcc/config/picochip/divmod15.S
index d314b3be570..d314b3be570 100644
--- a/gcc/config/picochip/libgccExtras/divmod15.asm
+++ b/libgcc/config/picochip/divmod15.S
diff --git a/gcc/config/picochip/libgccExtras/divmodhi4.asm b/libgcc/config/picochip/divmodhi4.S
index 9dad674c7bc..9dad674c7bc 100644
--- a/gcc/config/picochip/libgccExtras/divmodhi4.asm
+++ b/libgcc/config/picochip/divmodhi4.S
diff --git a/gcc/config/picochip/libgccExtras/divmodsi4.asm b/libgcc/config/picochip/divmodsi4.S
index 4fc1acb1b63..4fc1acb1b63 100644
--- a/gcc/config/picochip/libgccExtras/divmodsi4.asm
+++ b/libgcc/config/picochip/divmodsi4.S
diff --git a/libgcc/config/picochip/lib1funcs.S b/libgcc/config/picochip/lib1funcs.S
new file mode 100644
index 00000000000..d344170d248
--- /dev/null
+++ b/libgcc/config/picochip/lib1funcs.S
@@ -0,0 +1,4 @@
+// picoChip ASM file
+// Fake libgcc asm file. This contains nothing, but is used to prevent gcc
+// getting upset about the lack of a lib1funcs.S file when LIB1ASMFUNCS is
+// defined to switch off the compilation of parts of libgcc.
diff --git a/gcc/config/picochip/libgccExtras/longjmp.asm b/libgcc/config/picochip/longjmp.S
index d2a80aca730..d2a80aca730 100644
--- a/gcc/config/picochip/libgccExtras/longjmp.asm
+++ b/libgcc/config/picochip/longjmp.S
diff --git a/gcc/config/picochip/libgccExtras/lshrsi3.asm b/libgcc/config/picochip/lshrsi3.S
index 4fc53902955..4fc53902955 100644
--- a/gcc/config/picochip/libgccExtras/lshrsi3.asm
+++ b/libgcc/config/picochip/lshrsi3.S
diff --git a/gcc/config/picochip/libgccExtras/lshrsi3.c b/libgcc/config/picochip/lshrsi3.c
index fa32dc726ef..fa32dc726ef 100644
--- a/gcc/config/picochip/libgccExtras/lshrsi3.c
+++ b/libgcc/config/picochip/lshrsi3.c
diff --git a/gcc/config/picochip/libgccExtras/parityhi2.asm b/libgcc/config/picochip/parityhi2.S
index b9d0cdc63dd..b9d0cdc63dd 100644
--- a/gcc/config/picochip/libgccExtras/parityhi2.asm
+++ b/libgcc/config/picochip/parityhi2.S
diff --git a/gcc/config/picochip/libgccExtras/popcounthi2.asm b/libgcc/config/picochip/popcounthi2.S
index 2da618c96de..2da618c96de 100644
--- a/gcc/config/picochip/libgccExtras/popcounthi2.asm
+++ b/libgcc/config/picochip/popcounthi2.S
diff --git a/gcc/config/picochip/libgccExtras/setjmp.asm b/libgcc/config/picochip/setjmp.S
index 247c715f6a9..247c715f6a9 100644
--- a/gcc/config/picochip/libgccExtras/setjmp.asm
+++ b/libgcc/config/picochip/setjmp.S
diff --git a/gcc/config/picochip/libgccExtras/subdi3.asm b/libgcc/config/picochip/subdi3.S
index d1c833ea824..d1c833ea824 100644
--- a/gcc/config/picochip/libgccExtras/subdi3.asm
+++ b/libgcc/config/picochip/subdi3.S
diff --git a/libgcc/config/picochip/t-picochip b/libgcc/config/picochip/t-picochip
index 5135d500cbb..dd65f9e77d9 100644
--- a/libgcc/config/picochip/t-picochip
+++ b/libgcc/config/picochip/t-picochip
@@ -1,2 +1,39 @@
+# Prevent some of the more complicated libgcc functions from being
+# compiled. This is because they are generally too big to fit into an
+# AE anyway, so there is no point in having them. Also, some don't
+# compile properly so we'll ignore them for the moment.
+LIB1ASMSRC = picochip/lib1funcs.S
+LIB1ASMFUNCS = _mulsc3 _divsc3
+
+# Compile the extra library functions.
+LIB2ADD = \
+ $(srcdir)/config/picochip/ashrsi3.S \
+ $(srcdir)/config/picochip/ashlsi3.S \
+ $(srcdir)/config/picochip/divmodhi4.S \
+ $(srcdir)/config/picochip/udivmodhi4.S \
+ $(srcdir)/config/picochip/divmodsi4.S \
+ $(srcdir)/config/picochip/udivmodsi4.S \
+ $(srcdir)/config/picochip/divmod15.S \
+ $(srcdir)/config/picochip/ucmpsi2.S \
+ $(srcdir)/config/picochip/cmpsi2.S \
+ $(srcdir)/config/picochip/clzsi2.S \
+ $(srcdir)/config/picochip/adddi3.S \
+ $(srcdir)/config/picochip/subdi3.S \
+ $(srcdir)/config/picochip/lshrsi3.S \
+ $(srcdir)/config/picochip/parityhi2.S \
+ $(srcdir)/config/picochip/popcounthi2.S
+
+# Special libgcc setup. Make single/double floating point the same,
+# and use our own include files.
+HOST_LIBGCC2_CFLAGS = -DDF=SF -I../../includes/
+
+# Switch off all debugging for the embedded libraries.
+# (embedded processors need small libraries by default).
+# NOTE: If the debug level is increased, turn off instruction scheduling.
+LIBGCC2_DEBUG_CFLAGS = -g0
+
# Turn off the building of exception handling libraries.
LIB2ADDEH =
+
+# Turn off ranlib on target libraries.
+RANLIB_FOR_TARGET = cat
diff --git a/gcc/config/picochip/libgccExtras/ucmpsi2.asm b/libgcc/config/picochip/ucmpsi2.S
index 10c03cfcd6e..10c03cfcd6e 100644
--- a/gcc/config/picochip/libgccExtras/ucmpsi2.asm
+++ b/libgcc/config/picochip/ucmpsi2.S
diff --git a/gcc/config/picochip/libgccExtras/udivmodhi4.asm b/libgcc/config/picochip/udivmodhi4.S
index ac16fae39cf..ac16fae39cf 100644
--- a/gcc/config/picochip/libgccExtras/udivmodhi4.asm
+++ b/libgcc/config/picochip/udivmodhi4.S
diff --git a/gcc/config/picochip/libgccExtras/udivmodsi4.asm b/libgcc/config/picochip/udivmodsi4.S
index 92c2a4983ce..92c2a4983ce 100644
--- a/gcc/config/picochip/libgccExtras/udivmodsi4.asm
+++ b/libgcc/config/picochip/udivmodsi4.S
diff --git a/gcc/config/rs6000/crtresfpr.asm b/libgcc/config/rs6000/crtresfpr.S
index 9fb228cf458..9fb228cf458 100644
--- a/gcc/config/rs6000/crtresfpr.asm
+++ b/libgcc/config/rs6000/crtresfpr.S
diff --git a/gcc/config/rs6000/crtresgpr.asm b/libgcc/config/rs6000/crtresgpr.S
index 9f9cec9f9ca..9f9cec9f9ca 100644
--- a/gcc/config/rs6000/crtresgpr.asm
+++ b/libgcc/config/rs6000/crtresgpr.S
diff --git a/gcc/config/rs6000/crtresxfpr.asm b/libgcc/config/rs6000/crtresxfpr.S
index 633f2db61f0..633f2db61f0 100644
--- a/gcc/config/rs6000/crtresxfpr.asm
+++ b/libgcc/config/rs6000/crtresxfpr.S
diff --git a/gcc/config/rs6000/crtresxgpr.asm b/libgcc/config/rs6000/crtresxgpr.S
index 451b2b69d1e..451b2b69d1e 100644
--- a/gcc/config/rs6000/crtresxgpr.asm
+++ b/libgcc/config/rs6000/crtresxgpr.S
diff --git a/gcc/config/rs6000/crtsavfpr.asm b/libgcc/config/rs6000/crtsavfpr.S
index 3cdb25033ca..3cdb25033ca 100644
--- a/gcc/config/rs6000/crtsavfpr.asm
+++ b/libgcc/config/rs6000/crtsavfpr.S
diff --git a/gcc/config/rs6000/crtsavgpr.asm b/libgcc/config/rs6000/crtsavgpr.S
index 6d473963bad..6d473963bad 100644
--- a/gcc/config/rs6000/crtsavgpr.asm
+++ b/libgcc/config/rs6000/crtsavgpr.S
diff --git a/gcc/config/rs6000/darwin-asm.h b/libgcc/config/rs6000/darwin-asm.h
index 837b7a33ef8..837b7a33ef8 100644
--- a/gcc/config/rs6000/darwin-asm.h
+++ b/libgcc/config/rs6000/darwin-asm.h
diff --git a/libgcc/config/rs6000/darwin-fallback.c b/libgcc/config/rs6000/darwin-fallback.c
index 4591071ea74..a61ea0b9ca2 100644
--- a/libgcc/config/rs6000/darwin-fallback.c
+++ b/libgcc/config/rs6000/darwin-fallback.c
@@ -1,5 +1,5 @@
/* Fallback frame-state unwinder for Darwin.
- Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -28,6 +28,7 @@
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "dwarf2.h"
#include "unwind.h"
#include "unwind-dw2.h"
diff --git a/gcc/config/rs6000/darwin-fpsave.asm b/libgcc/config/rs6000/darwin-fpsave.S
index 47fdc92f860..47fdc92f860 100644
--- a/gcc/config/rs6000/darwin-fpsave.asm
+++ b/libgcc/config/rs6000/darwin-fpsave.S
diff --git a/libgcc/config/rs6000/darwin-gpsave.S b/libgcc/config/rs6000/darwin-gpsave.S
new file mode 100644
index 00000000000..d3c3b912d27
--- /dev/null
+++ b/libgcc/config/rs6000/darwin-gpsave.S
@@ -0,0 +1,118 @@
+/* This file contains the GPR save and restore routines for Darwin.
+ *
+ * Copyright (C) 2011 Free Software Foundation, Inc.
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Under Section 7 of GPL version 3, you are granted additional
+ * permissions described in the GCC Runtime Library Exception, version
+ * 3.1, as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License and
+ * a copy of the GCC Runtime Library Exception along with this program;
+ * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+/* Contributed by Iain Sandoe <iains@gcc.gnu.org> */
+
+/* Like their FP and VEC counterparts, these routines have only one externally
+ visible entry point. Calls have to be constructed as offsets from this.
+ (I.E. callers have to jump to "saveGPR+((x-13)*4" to save registers x..31).
+
+ Each save/load instruction is 4 bytes long (for both m32 and m64 builds).
+
+ The save/restores here are done w.r.t r11.
+
+ restGPRx restores the link reg from the stack and returns to the saved
+ address.
+
+ */
+
+#include "darwin-asm.h"
+
+ .text
+ .align 2
+
+ .private_extern saveGPR
+saveGPR:
+ stg r13,(-19 * GPR_BYTES)(r11)
+ stg r14,(-18 * GPR_BYTES)(r11)
+ stg r15,(-17 * GPR_BYTES)(r11)
+ stg r16,(-16 * GPR_BYTES)(r11)
+ stg r17,(-15 * GPR_BYTES)(r11)
+ stg r18,(-14 * GPR_BYTES)(r11)
+ stg r19,(-13 * GPR_BYTES)(r11)
+ stg r20,(-12 * GPR_BYTES)(r11)
+ stg r21,(-11 * GPR_BYTES)(r11)
+ stg r22,(-10 * GPR_BYTES)(r11)
+ stg r23,( -9 * GPR_BYTES)(r11)
+ stg r24,( -8 * GPR_BYTES)(r11)
+ stg r25,( -7 * GPR_BYTES)(r11)
+ stg r26,( -6 * GPR_BYTES)(r11)
+ stg r27,( -5 * GPR_BYTES)(r11)
+ stg r28,( -4 * GPR_BYTES)(r11)
+ stg r29,( -3 * GPR_BYTES)(r11)
+ stg r30,( -2 * GPR_BYTES)(r11)
+ stg r31,( -1 * GPR_BYTES)(r11)
+ blr
+
+/* */
+
+ .private_extern restGPR
+restGPR:
+ lg r13,(-19 * GPR_BYTES)(r11)
+ lg r14,(-18 * GPR_BYTES)(r11)
+ lg r15,(-17 * GPR_BYTES)(r11)
+ lg r16,(-16 * GPR_BYTES)(r11)
+ lg r17,(-15 * GPR_BYTES)(r11)
+ lg r18,(-14 * GPR_BYTES)(r11)
+ lg r19,(-13 * GPR_BYTES)(r11)
+ lg r20,(-12 * GPR_BYTES)(r11)
+ lg r21,(-11 * GPR_BYTES)(r11)
+ lg r22,(-10 * GPR_BYTES)(r11)
+ lg r23,( -9 * GPR_BYTES)(r11)
+ lg r24,( -8 * GPR_BYTES)(r11)
+ lg r25,( -7 * GPR_BYTES)(r11)
+ lg r26,( -6 * GPR_BYTES)(r11)
+ lg r27,( -5 * GPR_BYTES)(r11)
+ lg r28,( -4 * GPR_BYTES)(r11)
+ lg r29,( -3 * GPR_BYTES)(r11)
+ lg r30,( -2 * GPR_BYTES)(r11)
+ lg r31,( -1 * GPR_BYTES)(r11)
+ blr
+
+ .private_extern restGPRx
+restGPRx:
+ lg r13,(-19 * GPR_BYTES)(r11)
+ lg r14,(-18 * GPR_BYTES)(r11)
+ lg r15,(-17 * GPR_BYTES)(r11)
+ lg r16,(-16 * GPR_BYTES)(r11)
+ lg r17,(-15 * GPR_BYTES)(r11)
+ lg r18,(-14 * GPR_BYTES)(r11)
+ lg r19,(-13 * GPR_BYTES)(r11)
+ lg r20,(-12 * GPR_BYTES)(r11)
+ lg r21,(-11 * GPR_BYTES)(r11)
+ lg r22,(-10 * GPR_BYTES)(r11)
+ lg r23,( -9 * GPR_BYTES)(r11)
+ lg r24,( -8 * GPR_BYTES)(r11)
+ lg r25,( -7 * GPR_BYTES)(r11)
+ lg r26,( -6 * GPR_BYTES)(r11)
+ lg r27,( -5 * GPR_BYTES)(r11)
+ lg r28,( -4 * GPR_BYTES)(r11)
+ lg r29,( -3 * GPR_BYTES)(r11)
+ /* Like the FP restore, we start from the offset for r30
+ thus a restore of only r31 is not going to work. */
+ lg r0,SAVED_LR_OFFSET(r1)
+ lg r30,( -2 * GPR_BYTES)(r11)
+ mtlr r0
+ lg r31,( -1 * GPR_BYTES)(r11)
+ blr
diff --git a/gcc/config/rs6000/darwin-tramp.asm b/libgcc/config/rs6000/darwin-tramp.S
index 5188c98ef05..5188c98ef05 100644
--- a/gcc/config/rs6000/darwin-tramp.asm
+++ b/libgcc/config/rs6000/darwin-tramp.S
diff --git a/gcc/config/rs6000/darwin-vecsave.asm b/libgcc/config/rs6000/darwin-vecsave.S
index 0a46be20c89..0a46be20c89 100644
--- a/gcc/config/rs6000/darwin-vecsave.asm
+++ b/libgcc/config/rs6000/darwin-vecsave.S
diff --git a/gcc/config/rs6000/darwin-world.asm b/libgcc/config/rs6000/darwin-world.S
index c0b1bf1a2b1..c0b1bf1a2b1 100644
--- a/gcc/config/rs6000/darwin-world.asm
+++ b/libgcc/config/rs6000/darwin-world.S
diff --git a/gcc/config/rs6000/e500crtres32gpr.asm b/libgcc/config/rs6000/e500crtres32gpr.S
index 6fbff820b88..6fbff820b88 100644
--- a/gcc/config/rs6000/e500crtres32gpr.asm
+++ b/libgcc/config/rs6000/e500crtres32gpr.S
diff --git a/gcc/config/rs6000/e500crtres64gpr.asm b/libgcc/config/rs6000/e500crtres64gpr.S
index 5182e55392d..5182e55392d 100644
--- a/gcc/config/rs6000/e500crtres64gpr.asm
+++ b/libgcc/config/rs6000/e500crtres64gpr.S
diff --git a/gcc/config/rs6000/e500crtres64gprctr.asm b/libgcc/config/rs6000/e500crtres64gprctr.S
index 74309d6bed6..74309d6bed6 100644
--- a/gcc/config/rs6000/e500crtres64gprctr.asm
+++ b/libgcc/config/rs6000/e500crtres64gprctr.S
diff --git a/gcc/config/rs6000/e500crtrest32gpr.asm b/libgcc/config/rs6000/e500crtrest32gpr.S
index 4e61010dcff..4e61010dcff 100644
--- a/gcc/config/rs6000/e500crtrest32gpr.asm
+++ b/libgcc/config/rs6000/e500crtrest32gpr.S
diff --git a/gcc/config/rs6000/e500crtrest64gpr.asm b/libgcc/config/rs6000/e500crtrest64gpr.S
index 090786fdc71..090786fdc71 100644
--- a/gcc/config/rs6000/e500crtrest64gpr.asm
+++ b/libgcc/config/rs6000/e500crtrest64gpr.S
diff --git a/gcc/config/rs6000/e500crtresx32gpr.asm b/libgcc/config/rs6000/e500crtresx32gpr.S
index 0b35245df42..0b35245df42 100644
--- a/gcc/config/rs6000/e500crtresx32gpr.asm
+++ b/libgcc/config/rs6000/e500crtresx32gpr.S
diff --git a/gcc/config/rs6000/e500crtresx64gpr.asm b/libgcc/config/rs6000/e500crtresx64gpr.S
index ce2a6cfa2aa..ce2a6cfa2aa 100644
--- a/gcc/config/rs6000/e500crtresx64gpr.asm
+++ b/libgcc/config/rs6000/e500crtresx64gpr.S
diff --git a/gcc/config/rs6000/e500crtsav32gpr.asm b/libgcc/config/rs6000/e500crtsav32gpr.S
index c891030507e..c891030507e 100644
--- a/gcc/config/rs6000/e500crtsav32gpr.asm
+++ b/libgcc/config/rs6000/e500crtsav32gpr.S
diff --git a/gcc/config/rs6000/e500crtsav64gpr.asm b/libgcc/config/rs6000/e500crtsav64gpr.S
index 2a5d3e475fd..2a5d3e475fd 100644
--- a/gcc/config/rs6000/e500crtsav64gpr.asm
+++ b/libgcc/config/rs6000/e500crtsav64gpr.S
diff --git a/gcc/config/rs6000/e500crtsav64gprctr.asm b/libgcc/config/rs6000/e500crtsav64gprctr.S
index dd0bdf3c89a..dd0bdf3c89a 100644
--- a/gcc/config/rs6000/e500crtsav64gprctr.asm
+++ b/libgcc/config/rs6000/e500crtsav64gprctr.S
diff --git a/gcc/config/rs6000/e500crtsavg32gpr.asm b/libgcc/config/rs6000/e500crtsavg32gpr.S
index d14088e0dec..d14088e0dec 100644
--- a/gcc/config/rs6000/e500crtsavg32gpr.asm
+++ b/libgcc/config/rs6000/e500crtsavg32gpr.S
diff --git a/gcc/config/rs6000/e500crtsavg64gpr.asm b/libgcc/config/rs6000/e500crtsavg64gpr.S
index cbad75bc053..cbad75bc053 100644
--- a/gcc/config/rs6000/e500crtsavg64gpr.asm
+++ b/libgcc/config/rs6000/e500crtsavg64gpr.S
diff --git a/gcc/config/rs6000/e500crtsavg64gprctr.asm b/libgcc/config/rs6000/e500crtsavg64gprctr.S
index 238df4e8319..238df4e8319 100644
--- a/gcc/config/rs6000/e500crtsavg64gprctr.asm
+++ b/libgcc/config/rs6000/e500crtsavg64gprctr.S
diff --git a/gcc/config/rs6000/eabi-ci.asm b/libgcc/config/rs6000/eabi-ci.S
index 696f33d394f..696f33d394f 100644
--- a/gcc/config/rs6000/eabi-ci.asm
+++ b/libgcc/config/rs6000/eabi-ci.S
diff --git a/gcc/config/rs6000/eabi-cn.asm b/libgcc/config/rs6000/eabi-cn.S
index 68774097c7c..68774097c7c 100644
--- a/gcc/config/rs6000/eabi-cn.asm
+++ b/libgcc/config/rs6000/eabi-cn.S
diff --git a/gcc/config/rs6000/eabi.asm b/libgcc/config/rs6000/eabi.S
index 292d88e5016..292d88e5016 100644
--- a/gcc/config/rs6000/eabi.asm
+++ b/libgcc/config/rs6000/eabi.S
diff --git a/libgcc/config/rs6000/gthr-aix.h b/libgcc/config/rs6000/gthr-aix.h
new file mode 100644
index 00000000000..342f09187f0
--- /dev/null
+++ b/libgcc/config/rs6000/gthr-aix.h
@@ -0,0 +1,35 @@
+/* Threads compatibility routines for libgcc2 and libobjc. */
+/* Compile this one with gcc. */
+/* Copyright (C) 2000, 2009, 2011 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_GTHR_AIX_H
+#define GCC_GTHR_AIX_H
+
+#ifdef _THREAD_SAFE
+#include "config/gthr-posix.h"
+#else
+#include "gthr-single.h"
+#endif
+
+#endif /* GCC_GTHR_AIX_H */
diff --git a/gcc/config/rs6000/darwin-libgcc.10.4.ver b/libgcc/config/rs6000/libgcc-darwin.10.4.ver
index 0c6f7c23156..0c6f7c23156 100644
--- a/gcc/config/rs6000/darwin-libgcc.10.4.ver
+++ b/libgcc/config/rs6000/libgcc-darwin.10.4.ver
diff --git a/gcc/config/rs6000/darwin-libgcc.10.5.ver b/libgcc/config/rs6000/libgcc-darwin.10.5.ver
index c2f08924fd7..c2f08924fd7 100644
--- a/gcc/config/rs6000/darwin-libgcc.10.5.ver
+++ b/libgcc/config/rs6000/libgcc-darwin.10.5.ver
diff --git a/libgcc/config/rs6000/libgcc-ppc-glibc.ver b/libgcc/config/rs6000/libgcc-glibc.ver
index 8862c14cb3d..8862c14cb3d 100644
--- a/libgcc/config/rs6000/libgcc-ppc-glibc.ver
+++ b/libgcc/config/rs6000/libgcc-glibc.ver
diff --git a/libgcc/config/rs6000/libgcc-ppc64.ver b/libgcc/config/rs6000/libgcc-ibm-ldouble.ver
index b27b4b49249..b27b4b49249 100644
--- a/libgcc/config/rs6000/libgcc-ppc64.ver
+++ b/libgcc/config/rs6000/libgcc-ibm-ldouble.ver
diff --git a/gcc/config/rs6000/sol-ci.asm b/libgcc/config/rs6000/sol-ci.S
index 7c2fbae9747..7c2fbae9747 100644
--- a/gcc/config/rs6000/sol-ci.asm
+++ b/libgcc/config/rs6000/sol-ci.S
diff --git a/gcc/config/rs6000/sol-cn.asm b/libgcc/config/rs6000/sol-cn.S
index 4aeacaf2cff..4aeacaf2cff 100644
--- a/gcc/config/rs6000/sol-cn.asm
+++ b/libgcc/config/rs6000/sol-cn.S
diff --git a/libgcc/config/rs6000/t-crtstuff b/libgcc/config/rs6000/t-crtstuff
new file mode 100644
index 00000000000..7422d383754
--- /dev/null
+++ b/libgcc/config/rs6000/t-crtstuff
@@ -0,0 +1,3 @@
+# If .sdata is enabled __CTOR_{LIST,END}__ go into .sdata instead of
+# .ctors.
+CRTSTUFF_T_CFLAGS = -msdata=none
diff --git a/libgcc/config/rs6000/t-darwin b/libgcc/config/rs6000/t-darwin
index 4464fd7d6e6..abb41fc9bce 100644
--- a/libgcc/config/rs6000/t-darwin
+++ b/libgcc/config/rs6000/t-darwin
@@ -3,8 +3,21 @@ DARWIN_EXTRA_CRT_BUILD_CFLAGS = -mlongcall -mmacosx-version-min=10.4
crt2.o: $(srcdir)/config/rs6000/darwin-crt2.c
$(crt_compile) $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -c $<
-LIB2ADD += $(srcdir)/config/rs6000/ppc64-fp.c
+LIB2ADD = $(srcdir)/config/rs6000/darwin-tramp.S \
+ $(srcdir)/config/darwin-64.c \
+ $(srcdir)/config/rs6000/darwin-fpsave.S \
+ $(srcdir)/config/rs6000/darwin-gpsave.S \
+ $(srcdir)/config/rs6000/darwin-world.S \
+ $(srcdir)/config/rs6000/ppc64-fp.c
-LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c
+LIB2ADD_ST = \
+ $(srcdir)/config/rs6000/darwin-vecsave.S
+
+# The .S files above are designed to run on all processors, even though
+# they use AltiVec instructions.
+# -Wa is used because -force_cpusubtype_ALL doesn't work with -dynamiclib.
+# -mmacosx-version-min=10.4 is used to provide compatibility for code from
+# earlier OSX versions.
+HOST_LIBGCC2_CFLAGS += -Wa,-force_cpusubtype_ALL -mmacosx-version-min=10.4
-SHLIB_VERPFX = $(gcc_srcdir)/config/rs6000/darwin-libgcc
+LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c
diff --git a/libgcc/config/rs6000/t-darwin64 b/libgcc/config/rs6000/t-darwin64
new file mode 100644
index 00000000000..eea0671f3b5
--- /dev/null
+++ b/libgcc/config/rs6000/t-darwin64
@@ -0,0 +1,6 @@
+LIB2_SIDITI_CONV_FUNCS = yes
+
+LIB2ADD = $(srcdir)/config/rs6000/darwin-tramp.S \
+ $(srcdir)/config/darwin-64.c \
+ $(srcdir)/config/rs6000/darwin-world.S
+
diff --git a/libgcc/config/rs6000/t-freebsd b/libgcc/config/rs6000/t-freebsd
index 4234999f3cb..384c3b1c01c 100644
--- a/libgcc/config/rs6000/t-freebsd
+++ b/libgcc/config/rs6000/t-freebsd
@@ -19,4 +19,4 @@
# <http://www.gnu.org/licenses/>.
# We do not want to build ibm-ldouble.c.
-LIB2ADD := $(filter-out ibm-ldouble.c, $(LIB2ADD))
+LIB2ADD := $(filter-out %ibm-ldouble.c, $(LIB2ADD))
diff --git a/libgcc/config/rs6000/t-ibm-ldouble b/libgcc/config/rs6000/t-ibm-ldouble
index 3f7a2d847e2..b13278498ec 100644
--- a/libgcc/config/rs6000/t-ibm-ldouble
+++ b/libgcc/config/rs6000/t-ibm-ldouble
@@ -3,4 +3,4 @@ LIB2ADD += $(srcdir)/config/rs6000/ibm-ldouble.c
HOST_LIBGCC2_CFLAGS += -mlong-double-128
-SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc64.ver
+SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ibm-ldouble.ver
diff --git a/libgcc/config/rs6000/t-ldbl128 b/libgcc/config/rs6000/t-ldbl128
deleted file mode 100644
index ecc3581b1a0..00000000000
--- a/libgcc/config/rs6000/t-ldbl128
+++ /dev/null
@@ -1,3 +0,0 @@
-SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc-glibc.ver
-
-HOST_LIBGCC2_CFLAGS += -mlong-double-128
diff --git a/libgcc/config/rs6000/t-linux b/libgcc/config/rs6000/t-linux
new file mode 100644
index 00000000000..dcf7ffc255e
--- /dev/null
+++ b/libgcc/config/rs6000/t-linux
@@ -0,0 +1,3 @@
+SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-glibc.ver
+
+HOST_LIBGCC2_CFLAGS += -mlong-double-128
diff --git a/libgcc/config/rs6000/t-linux64 b/libgcc/config/rs6000/t-linux64
index 7b08315abc0..2b60f1a1f43 100644
--- a/libgcc/config/rs6000/t-linux64
+++ b/libgcc/config/rs6000/t-linux64
@@ -1,2 +1,4 @@
+HOST_LIBGCC2_CFLAGS += -mno-minimal-toc
+
softfp_wrap_start := '\#ifndef __powerpc64__'
softfp_wrap_end := '\#endif'
diff --git a/libgcc/config/rs6000/t-lynx b/libgcc/config/rs6000/t-lynx
new file mode 100644
index 00000000000..af7f5982b9c
--- /dev/null
+++ b/libgcc/config/rs6000/t-lynx
@@ -0,0 +1 @@
+LIB2ADD = $(srcdir)/config/rs6000/tramp.S
diff --git a/libgcc/config/rs6000/t-netbsd b/libgcc/config/rs6000/t-netbsd
new file mode 100644
index 00000000000..3b4ba32a215
--- /dev/null
+++ b/libgcc/config/rs6000/t-netbsd
@@ -0,0 +1,9 @@
+LIB2ADD = $(srcdir)/config/rs6000/tramp.S
+
+LIB2ADD_ST = \
+ $(srcdir)/config/rs6000/crtsavfpr.S \
+ $(srcdir)/config/rs6000/crtresfpr.S \
+ $(srcdir)/config/rs6000/crtsavgpr.S \
+ $(srcdir)/config/rs6000/crtresgpr.S \
+ $(srcdir)/config/rs6000/crtresxfpr.S \
+ $(srcdir)/config/rs6000/crtresxgpr.S
diff --git a/libgcc/config/rs6000/t-ppccomm b/libgcc/config/rs6000/t-ppccomm
index f75bee22737..99f3867e194 100644
--- a/libgcc/config/rs6000/t-ppccomm
+++ b/libgcc/config/rs6000/t-ppccomm
@@ -1,107 +1,41 @@
-LIB2ADD += $(srcdir)/config/rs6000/ibm-ldouble.c
-
-LIB2ADD_ST += crtsavfpr.S crtresfpr.S \
- crtsavgpr.S crtresgpr.S \
- crtresxfpr.S crtresxgpr.S \
- e500crtres32gpr.S \
- e500crtres64gpr.S \
- e500crtres64gprctr.S \
- e500crtrest32gpr.S \
- e500crtrest64gpr.S \
- e500crtresx32gpr.S \
- e500crtresx64gpr.S \
- e500crtsav32gpr.S \
- e500crtsav64gpr.S \
- e500crtsav64gprctr.S \
- e500crtsavg32gpr.S \
- e500crtsavg64gpr.S \
- e500crtsavg64gprctr.S
-
-EXTRA_PARTS += crtbegin$(objext) crtend$(objext) \
- crtbeginS$(objext) crtendS$(objext) crtbeginT$(objext) \
- ecrti$(objext) ecrtn$(objext) ncrti$(objext) ncrtn$(objext)
+LIB2ADD += $(srcdir)/config/rs6000/ibm-ldouble.c \
+ $(srcdir)/config/rs6000/tramp.S
+
+# These can't end up in shared libgcc
+LIB2ADD_ST += \
+ $(srcdir)/config/rs6000/crtsavfpr.S \
+ $(srcdir)/config/rs6000/crtresfpr.S \
+ $(srcdir)/config/rs6000/crtsavgpr.S \
+ $(srcdir)/config/rs6000/crtresgpr.S \
+ $(srcdir)/config/rs6000/crtresxfpr.S
+ $(srcdir)/config/rs6000/crtresxgpr.S \
+ $(srcdir)/config/rs6000/e500crtres32gpr.S \
+ $(srcdir)/config/rs6000/e500crtres64gpr.S \
+ $(srcdir)/config/rs6000/e500crtres64gprctr.S \
+ $(srcdir)/config/rs6000/e500crtrest32gpr.S \
+ $(srcdir)/config/rs6000/e500crtrest64gpr.S \
+ $(srcdir)/config/rs6000/e500crtresx32gpr.S \
+ $(srcdir)/config/rs6000/e500crtresx64gpr.S \
+ $(srcdir)/config/rs6000/e500crtsav32gpr.S \
+ $(srcdir)/config/rs6000/e500crtsav64gpr.S \
+ $(srcdir)/config/rs6000/e500crtsav64gprctr.S \
+ $(srcdir)/config/rs6000/e500crtsavg32gpr.S \
+ $(srcdir)/config/rs6000/e500crtsavg64gpr.S \
+ $(srcdir)/config/rs6000/e500crtsavg64gprctr.S
+ $(srcdir)/config/rs6000/eabi.S
# We build {e,n}crti.o and {e,n}crtn.o, which serve to add begin and
# end labels to all of the special sections used when we link using gcc.
# Assemble startup files.
-ecrti.S: $(gcc_srcdir)/config/rs6000/eabi-ci.asm
- cat $(gcc_srcdir)/config/rs6000/eabi-ci.asm >ecrti.S
-
-ecrtn.S: $(gcc_srcdir)/config/rs6000/eabi-cn.asm
- cat $(gcc_srcdir)/config/rs6000/eabi-cn.asm >ecrtn.S
-
-ncrti.S: $(gcc_srcdir)/config/rs6000/sol-ci.asm
- cat $(gcc_srcdir)/config/rs6000/sol-ci.asm >ncrti.S
-
-ncrtn.S: $(gcc_srcdir)/config/rs6000/sol-cn.asm
- cat $(gcc_srcdir)/config/rs6000/sol-cn.asm >ncrtn.S
-
-crtsavfpr.S: $(gcc_srcdir)/config/rs6000/crtsavfpr.asm
- cat $(gcc_srcdir)/config/rs6000/crtsavfpr.asm >crtsavfpr.S
-
-crtresfpr.S: $(gcc_srcdir)/config/rs6000/crtresfpr.asm
- cat $(gcc_srcdir)/config/rs6000/crtresfpr.asm >crtresfpr.S
-
-crtsavgpr.S: $(gcc_srcdir)/config/rs6000/crtsavgpr.asm
- cat $(gcc_srcdir)/config/rs6000/crtsavgpr.asm >crtsavgpr.S
-
-crtresgpr.S: $(gcc_srcdir)/config/rs6000/crtresgpr.asm
- cat $(gcc_srcdir)/config/rs6000/crtresgpr.asm >crtresgpr.S
-
-crtresxfpr.S: $(gcc_srcdir)/config/rs6000/crtresxfpr.asm
- cat $(gcc_srcdir)/config/rs6000/crtresxfpr.asm >crtresxfpr.S
-
-crtresxgpr.S: $(gcc_srcdir)/config/rs6000/crtresxgpr.asm
- cat $(gcc_srcdir)/config/rs6000/crtresxgpr.asm >crtresxgpr.S
-
-e500crtres32gpr.S: $(gcc_srcdir)/config/rs6000/e500crtres32gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtres32gpr.asm >e500crtres32gpr.S
-
-e500crtres64gpr.S: $(gcc_srcdir)/config/rs6000/e500crtres64gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtres64gpr.asm >e500crtres64gpr.S
-
-e500crtres64gprctr.S: $(gcc_srcdir)/config/rs6000/e500crtres64gprctr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtres64gprctr.asm >e500crtres64gprctr.S
-
-e500crtrest32gpr.S: $(gcc_srcdir)/config/rs6000/e500crtrest32gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtrest32gpr.asm >e500crtrest32gpr.S
-
-e500crtrest64gpr.S: $(gcc_srcdir)/config/rs6000/e500crtrest64gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtrest64gpr.asm >e500crtrest64gpr.S
-
-e500crtresx32gpr.S: $(gcc_srcdir)/config/rs6000/e500crtresx32gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtresx32gpr.asm >e500crtresx32gpr.S
-
-e500crtresx64gpr.S: $(gcc_srcdir)/config/rs6000/e500crtresx64gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtresx64gpr.asm >e500crtresx64gpr.S
-
-e500crtsav32gpr.S: $(gcc_srcdir)/config/rs6000/e500crtsav32gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtsav32gpr.asm >e500crtsav32gpr.S
-
-e500crtsav64gpr.S: $(gcc_srcdir)/config/rs6000/e500crtsav64gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtsav64gpr.asm >e500crtsav64gpr.S
-
-e500crtsav64gprctr.S: $(gcc_srcdir)/config/rs6000/e500crtsav64gprctr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtsav64gprctr.asm >e500crtsav64gprctr.S
-
-e500crtsavg32gpr.S: $(gcc_srcdir)/config/rs6000/e500crtsavg32gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtsavg32gpr.asm >e500crtsavg32gpr.S
-
-e500crtsavg64gpr.S: $(gcc_srcdir)/config/rs6000/e500crtsavg64gpr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtsavg64gpr.asm >e500crtsavg64gpr.S
-
-e500crtsavg64gprctr.S: $(gcc_srcdir)/config/rs6000/e500crtsavg64gprctr.asm
- cat $(gcc_srcdir)/config/rs6000/e500crtsavg64gprctr.asm >e500crtsavg64gprctr.S
-
-ecrti$(objext): ecrti.S
+ecrti$(objext): $(srcdir)/config/rs6000/eabi-ci.S
$(crt_compile) -c ecrti.S
-ecrtn$(objext): ecrtn.S
+ecrtn$(objext): $(srcdir)/config/rs6000/eabi-cn.S
$(crt_compile) -c ecrtn.S
-ncrti$(objext): ncrti.S
+ncrti$(objext): $(srcdir)/config/rs6000/sol-ci.S
$(crt_compile) -c ncrti.S
-ncrtn$(objext): ncrtn.S
+ncrtn$(objext): $(srcdir)/config/rs6000/sol-cn.S
$(crt_compile) -c ncrtn.S
diff --git a/libgcc/config/rs6000/t-slibgcc-aix b/libgcc/config/rs6000/t-slibgcc-aix
new file mode 100644
index 00000000000..a0fdd133926
--- /dev/null
+++ b/libgcc/config/rs6000/t-slibgcc-aix
@@ -0,0 +1,44 @@
+# Copyright (C) 2002, 2003, 2004, 2005, 2006,
+# 2008, 2011 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Build a shared libgcc library.
+SHLIB_EXT = .a
+SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+ -Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \
+ @multilib_flags@ @shlib_objs@ -lc \
+ `case @multilib_dir@ in \
+ *pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
+ *) echo -lc ;; esac` ; \
+ rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
+ $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
+ @multilib_dir@/shr.o ; \
+ mv @multilib_dir@/tmp-@shlib_base_name@.a \
+ @multilib_dir@/@shlib_base_name@.a ; \
+ rm -f @multilib_dir@/shr.o
+SHLIB_INSTALL = \
+ $(mkinstalldirs) $(DESTDIR)$(slibdir)@shlib_slibdir_qual@; \
+ $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \
+ $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/
+SHLIB_LIBS = -lc `case @multilib_dir@ in *pthread*) echo -lpthread ;; esac`
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
+SHLIB_MAPFILES = libgcc-std.ver
+SHLIB_NM_FLAGS = -Bpg -X32_64
+
+# Either 32-bit and 64-bit objects in archives.
+AR_FLAGS_FOR_TARGET = -X32_64
diff --git a/gcc/config/rs6000/tramp.asm b/libgcc/config/rs6000/tramp.S
index 133b98840f1..133b98840f1 100644
--- a/gcc/config/rs6000/tramp.asm
+++ b/libgcc/config/rs6000/tramp.S
diff --git a/gcc/gthr-tpf.h b/libgcc/config/s390/gthr-tpf.h
index fb23e91cfcd..fb23e91cfcd 100644
--- a/gcc/gthr-tpf.h
+++ b/libgcc/config/s390/gthr-tpf.h
diff --git a/libgcc/config/s390/t-tpf b/libgcc/config/s390/t-tpf
deleted file mode 100644
index 9d416acc12d..00000000000
--- a/libgcc/config/s390/t-tpf
+++ /dev/null
@@ -1,2 +0,0 @@
-# Compile libgcc2.a with pic.
-HOST_LIBGCC2_CFLAGS += -fPIC
diff --git a/libgcc/config/score/crti.S b/libgcc/config/score/crti.S
new file mode 100644
index 00000000000..8e7c78b978b
--- /dev/null
+++ b/libgcc/config/score/crti.S
@@ -0,0 +1,131 @@
+# crti.S for Sunplus S+CORE
+#
+# Copyright (C) 2005, 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file makes a stack frame for the contents of the .init and
+# .fini sections.
+.extern _stack
+
+#ifndef __pic__
+.section .init, "ax", @progbits
+ .weak _start
+ .ent _start
+ .frame r0, 0, r3, 0
+ .mask 0x00000000, 0
+_start:
+ la r28, _gp
+ la r8, __bss_start
+ la r9, __bss_end__
+ sub! r9, r8
+ srli! r9, 2
+ addi r9, -1
+ mtsr r9, sr0
+ li r9, 0
+1:
+ sw r9, [r8]+, 4
+ bcnz 1b
+ la r0, _stack
+ jl _init
+ la r4, _end
+ jl _init_argv
+ jl exit
+ .end _start
+
+ .weak _init_argv
+ .ent
+ .frame r0, 0, r3, 0
+ .mask 0x00000000, 0
+_init_argv:
+ ldiu! r4, 0
+ ldiu! r5, 0
+ j main
+ .end _init_argv
+
+ .globl _init
+ .type _init, %function
+_init:
+ addi r0, -32
+ sw r3, [r0, 20]
+
+ .section .fini, "ax", @progbits
+ .globl _fini
+ .type _fini, %function
+_fini:
+ addi r0, -32
+ sw r3, [r0, 20]
+#else
+.section .init, "ax", @progbits
+ .set pic
+ .weak _start
+ .ent _start
+ .frame r0, 0, r3, 0
+ .mask 0x00000000, 0
+_start:
+ mv r29, r3
+ bl 0f
+0:
+ .cpload r3
+ mv r3, r29
+ la r8, __bss_start
+ la r9, __bss_end__
+ sub! r9, r8
+ srli! r9, 2
+ addi r9, -1
+ mtsr r9, sr0
+ li r9, 0
+1:
+ sw r9, [r8]+, 4
+ bcnz 1b
+ la r0, _stack
+ bl _init
+ la r4, _end
+ la r29, _init_argv
+ brl r29
+ la r29, exit
+ brl r29
+ .end _start
+
+ .weak _init_argv
+ .ent _init_argv
+ .frame r0, 0, r3, 0
+ .mask 0x00000000, 0
+_init_argv:
+ ldiu! r4, 0
+ ldiu! r5, 0
+ la r29, main
+ brl r29
+ .end _init_argv
+
+ .globl _init
+ .type _init, %function
+_init:
+ addi r0, -32
+ sw r3, [r0, 20]
+
+ .section .fini, "ax", @progbits
+ .globl _fini
+ .type _fini, %function
+_fini:
+ addi r0, -32
+ sw r3, [r0, 20]
+
+#endif
diff --git a/libgcc/config/score/crtn.S b/libgcc/config/score/crtn.S
new file mode 100644
index 00000000000..adf4eb08400
--- /dev/null
+++ b/libgcc/config/score/crtn.S
@@ -0,0 +1,50 @@
+# crtn.S for Sunplus S+CORE
+
+# Copyright (C) 2005, 2009, 2010, 2011 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3, or (at your option) any
+# later version.
+#
+# This file is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# Under Section 7 of GPL version 3, you are granted additional
+# permissions described in the GCC Runtime Library Exception, version
+# 3.1, as published by the Free Software Foundation.
+#
+# You should have received a copy of the GNU General Public License and
+# a copy of the GCC Runtime Library Exception along with this program;
+# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file makes sure that the .init and .fini sections do in
+# fact return.
+
+#ifndef __pic__
+.section .init, "ax", @progbits
+ lw r3, [r0, 20]
+ addi r0, 32
+ br r3
+
+.section .fini, "ax", @progbits
+ lw r3, [r0, 20]
+ addi r0, 32
+ br r3
+#else
+ .set pic
+.section .init, "ax", @progbits
+ lw r3, [r0, 20]
+ addi r0, 32
+ br r3
+
+ .set pic
+.section .fini, "ax", @progbits
+ lw r3, [r0, 20]
+ addi r0, 32
+ br r3
+#endif
+
diff --git a/libgcc/config/sh/crt1.S b/libgcc/config/sh/crt1.S
new file mode 100644
index 00000000000..ce09a09458f
--- /dev/null
+++ b/libgcc/config/sh/crt1.S
@@ -0,0 +1,1369 @@
+/* Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2009, 2011
+ Free Software Foundation, Inc.
+ This file was pretty much copied from newlib.
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+
+#ifdef MMU_SUPPORT
+ /* Section used for exception/timer interrupt stack area */
+ .section .data.vbr.stack,"aw"
+ .align 4
+ .global __ST_VBR
+__ST_VBR:
+ .zero 1024 * 2 /* ; 2k for VBR handlers */
+/* Label at the highest stack address where the stack grows from */
+__timer_stack:
+#endif /* MMU_SUPPORT */
+
+ /* ;----------------------------------------
+ Normal newlib crt1.S */
+
+#ifdef __SH5__
+ .section .data,"aw"
+ .global ___data
+___data:
+
+ .section .rodata,"a"
+ .global ___rodata
+___rodata:
+
+#define ICCR_BASE 0x01600000
+#define OCCR_BASE 0x01e00000
+#define MMUIR_BASE 0x00000000
+#define MMUDR_BASE 0x00800000
+
+#define PTE_ENABLED 1
+#define PTE_DISABLED 0
+
+#define PTE_SHARED (1 << 1)
+#define PTE_NOT_SHARED 0
+
+#define PTE_CB_UNCACHEABLE 0
+#define PTE_CB_DEVICE 1
+#define PTE_CB_CACHEABLE_WB 2
+#define PTE_CB_CACHEABLE_WT 3
+
+#define PTE_SZ_4KB (0 << 3)
+#define PTE_SZ_64KB (1 << 3)
+#define PTE_SZ_1MB (2 << 3)
+#define PTE_SZ_512MB (3 << 3)
+
+#define PTE_PRR (1 << 6)
+#define PTE_PRX (1 << 7)
+#define PTE_PRW (1 << 8)
+#define PTE_PRU (1 << 9)
+
+#define SR_MMU_BIT 31
+#define SR_BL_BIT 28
+
+#define ALIGN_4KB (0xfff)
+#define ALIGN_1MB (0xfffff)
+#define ALIGN_512MB (0x1fffffff)
+
+#define DYNACON_BASE 0x0f000000
+#define DM_CB_DLINK_BASE 0x0c000000
+#define DM_DB_DLINK_BASE 0x0b000000
+
+#define FEMI_AREA_0 0x00000000
+#define FEMI_AREA_1 0x04000000
+#define FEMI_AREA_2 0x05000000
+#define FEMI_AREA_3 0x06000000
+#define FEMI_AREA_4 0x07000000
+#define FEMI_CB 0x08000000
+
+#define EMI_BASE 0X80000000
+
+#define DMA_BASE 0X0e000000
+
+#define CPU_BASE 0X0d000000
+
+#define PERIPH_BASE 0X09000000
+#define DMAC_BASE 0x0e000000
+#define INTC_BASE 0x0a000000
+#define CPRC_BASE 0x0a010000
+#define TMU_BASE 0x0a020000
+#define SCIF_BASE 0x0a030000
+#define RTC_BASE 0x0a040000
+
+
+
+#define LOAD_CONST32(val, reg) \
+ movi ((val) >> 16) & 65535, reg; \
+ shori (val) & 65535, reg
+
+#define LOAD_PTEH_VAL(sym, align, bits, scratch_reg, reg) \
+ LOAD_ADDR (sym, reg); \
+ LOAD_CONST32 ((align), scratch_reg); \
+ andc reg, scratch_reg, reg; \
+ LOAD_CONST32 ((bits), scratch_reg); \
+ or reg, scratch_reg, reg
+
+#define LOAD_PTEL_VAL(sym, align, bits, scratch_reg, reg) \
+ LOAD_ADDR (sym, reg); \
+ LOAD_CONST32 ((align), scratch_reg); \
+ andc reg, scratch_reg, reg; \
+ LOAD_CONST32 ((bits), scratch_reg); \
+ or reg, scratch_reg, reg
+
+#define SET_PTE(pte_addr_reg, pteh_val_reg, ptel_val_reg) \
+ putcfg pte_addr_reg, 0, r63; \
+ putcfg pte_addr_reg, 1, ptel_val_reg; \
+ putcfg pte_addr_reg, 0, pteh_val_reg
+
+#if __SH5__ == 64
+ .section .text,"ax"
+#define LOAD_ADDR(sym, reg) \
+ movi (sym >> 48) & 65535, reg; \
+ shori (sym >> 32) & 65535, reg; \
+ shori (sym >> 16) & 65535, reg; \
+ shori sym & 65535, reg
+#else
+ .mode SHmedia
+ .section .text..SHmedia32,"ax"
+#define LOAD_ADDR(sym, reg) \
+ movi (sym >> 16) & 65535, reg; \
+ shori sym & 65535, reg
+#endif
+ .global start
+start:
+ LOAD_ADDR (_stack, r15)
+
+#ifdef MMU_SUPPORT
+ ! Set up the VM using the MMU and caches
+
+ ! .vm_ep is first instruction to execute
+ ! after VM initialization
+ pt/l .vm_ep, tr1
+
+ ! Configure instruction cache (ICCR)
+ movi 3, r2
+ movi 0, r3
+ LOAD_ADDR (ICCR_BASE, r1)
+ putcfg r1, 0, r2
+ putcfg r1, 1, r3
+
+ ! movi 7, r2 ! write through
+ ! Configure operand cache (OCCR)
+ LOAD_ADDR (OCCR_BASE, r1)
+ putcfg r1, 0, r2
+ putcfg r1, 1, r3
+
+ ! Disable all PTE translations
+ LOAD_ADDR (MMUIR_BASE, r1)
+ LOAD_ADDR (MMUDR_BASE, r2)
+ movi 64, r3
+ pt/l .disable_ptes_loop, tr0
+.disable_ptes_loop:
+ putcfg r1, 0, r63
+ putcfg r2, 0, r63
+ addi r1, 16, r1
+ addi r2, 16, r2
+ addi r3, -1, r3
+ bgt r3, r63, tr0
+
+ LOAD_ADDR (MMUIR_BASE, r1)
+
+ ! FEMI instruction mappings
+ ! Area 0 - 1Mb cacheable at 0x00000000
+ ! Area 1 - None
+ ! Area 2 - 1Mb cacheable at 0x05000000
+ ! - 1Mb cacheable at 0x05100000
+ ! Area 3 - None
+ ! Area 4 - None
+
+ ! Map a 1Mb page for instructions at 0x00000000
+ LOAD_PTEH_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1Mb page for instructions at 0x05000000
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1Mb page for instructions at 0x05100000
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRX | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 512M page for instructions at EMI base
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (EMI_BASE, ALIGN_512MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (EMI_BASE, ALIGN_512MB, PTE_CB_CACHEABLE_WB | PTE_SZ_512MB | PTE_PRX | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 4K page for instructions at DM_DB_DLINK_BASE
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRX | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ LOAD_ADDR (MMUDR_BASE, r1)
+
+ ! FEMI data mappings
+ ! Area 0 - 1Mb cacheable at 0x00000000
+ ! Area 1 - 1Mb device at 0x04000000
+ ! Area 2 - 1Mb cacheable at 0x05000000
+ ! - 1Mb cacheable at 0x05100000
+ ! Area 3 - None
+ ! Area 4 - None
+ ! CB - 1Mb device at 0x08000000
+
+ ! Map a 1Mb page for data at 0x00000000
+ LOAD_PTEH_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (FEMI_AREA_0, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1Mb page for data at 0x04000000
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (FEMI_AREA_1, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (FEMI_AREA_1, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1Mb page for data at 0x05000000
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (FEMI_AREA_2, ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1Mb page for data at 0x05100000
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((FEMI_AREA_2+0x100000), ALIGN_1MB, PTE_CB_CACHEABLE_WB | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 4K page for registers at 0x08000000
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (FEMI_CB, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (FEMI_CB, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 512M page for data at EMI
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (EMI_BASE, ALIGN_512MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (EMI_BASE, ALIGN_512MB, PTE_CB_CACHEABLE_WB | PTE_SZ_512MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 4K page for DYNACON at DYNACON_BASE
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (DYNACON_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (DYNACON_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 4K page for instructions at DM_DB_DLINK_BASE
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (DM_DB_DLINK_BASE, ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 4K page for data at DM_DB_DLINK_BASE+0x1000
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((DM_DB_DLINK_BASE+0x1000), ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((DM_DB_DLINK_BASE+0x1000), ALIGN_4KB, PTE_CB_UNCACHEABLE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 4K page for stack DM_DB_DLINK_BASE+0x2000
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((DM_DB_DLINK_BASE+0x2000), ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((DM_DB_DLINK_BASE+0x2000), ALIGN_4KB, PTE_CB_CACHEABLE_WB | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
+ ! 0x0c000000 - 0x0c0fffff
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (DM_CB_DLINK_BASE, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (DM_CB_DLINK_BASE, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
+ ! 0x0c100000 - 0x0c1fffff
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x100000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
+ ! 0x0c200000 - 0x0c2fffff
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x200000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x200000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
+ ! 0x0c400000 - 0x0c4fffff
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x400000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x400000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 1M page for DM_CB_BASE2 at DM_CB_DLINK
+ ! 0x0c800000 - 0x0c8fffff
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((DM_CB_DLINK_BASE+0x800000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((DM_CB_DLINK_BASE+0x800000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map a 4K page for DMA control registers
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (DMA_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (DMA_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map lots of 4K pages for peripherals
+
+ ! /* peripheral */
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (PERIPH_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (PERIPH_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+ ! /* dmac */
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (DMAC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (DMAC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+ ! /* intc */
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (INTC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (INTC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+ ! /* rtc */
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (RTC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (RTC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+ ! /* dmac */
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (TMU_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (TMU_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+ ! /* scif */
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (SCIF_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (SCIF_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+ ! /* cprc */
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (CPRC_BASE, ALIGN_4KB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (CPRC_BASE, ALIGN_4KB, PTE_CB_DEVICE | PTE_SZ_4KB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Map CPU WPC registers
+ addi r1, 16, r1
+ LOAD_PTEH_VAL (CPU_BASE, ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL (CPU_BASE, ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+ addi r1, 16, r1
+
+ LOAD_PTEH_VAL ((CPU_BASE+0x100000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((CPU_BASE+0x100000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((CPU_BASE+0x200000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((CPU_BASE+0x200000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ addi r1, 16, r1
+ LOAD_PTEH_VAL ((CPU_BASE+0x400000), ALIGN_1MB, PTE_ENABLED | PTE_NOT_SHARED, r25, r2)
+ LOAD_PTEL_VAL ((CPU_BASE+0x400000), ALIGN_1MB, PTE_CB_DEVICE | PTE_SZ_1MB | PTE_PRR | PTE_PRW | PTE_PRU, r25, r3)
+ SET_PTE (r1, r2, r3)
+
+ ! Switch over to virtual addressing and enabled cache
+ getcon sr, r1
+ movi 1, r2
+ shlli r2, SR_BL_BIT, r2
+ or r1, r2, r1
+ putcon r1, ssr
+ getcon sr, r1
+ movi 1, r2
+ shlli r2, SR_MMU_BIT, r2
+ or r1, r2, r1
+ putcon r1, ssr
+ gettr tr1, r1
+ putcon r1, spc
+ synco
+ rte
+
+ ! VM entry point. From now on, we are in VM mode.
+.vm_ep:
+
+ ! Install the trap handler, by seeding vbr with the
+ ! correct value, and by assigning sr.bl = 0.
+
+ LOAD_ADDR (vbr_start, r1)
+ putcon r1, vbr
+ movi ~(1<<28), r1
+ getcon sr, r2
+ and r1, r2, r2
+ putcon r2, sr
+#endif /* MMU_SUPPORT */
+
+ pt/l .Lzero_bss_loop, tr0
+ pt/l _init, tr5
+ pt/l ___setup_argv_and_call_main, tr6
+ pt/l _exit, tr7
+
+ ! zero out bss
+ LOAD_ADDR (_edata, r0)
+ LOAD_ADDR (_end, r1)
+.Lzero_bss_loop:
+ stx.q r0, r63, r63
+ addi r0, 8, r0
+ bgt/l r1, r0, tr0
+
+ LOAD_ADDR (___data, r26)
+ LOAD_ADDR (___rodata, r27)
+
+#ifdef __SH_FPU_ANY__
+ getcon sr, r0
+ ! enable the FP unit, by resetting SR.FD
+ ! also zero out SR.FR, SR.SZ and SR.PR, as mandated by the ABI
+ movi 0, r1
+ shori 0xf000, r1
+ andc r0, r1, r0
+ putcon r0, sr
+#if __SH5__ == 32
+ pt/l ___set_fpscr, tr0
+ movi 0, r4
+ blink tr0, r18
+#endif
+#endif
+
+ ! arrange for exit to call fini
+ pt/l _atexit, tr1
+ LOAD_ADDR (_fini, r2)
+ blink tr1, r18
+
+ ! call init
+ blink tr5, r18
+
+ ! call the mainline
+ blink tr6, r18
+
+ ! call exit
+ blink tr7, r18
+ ! We should never return from _exit but in case we do we would enter the
+ ! the following tight loop. This avoids executing any data that might follow.
+limbo:
+ pt/l limbo, tr0
+ blink tr0, r63
+
+#ifdef MMU_SUPPORT
+ ! All these traps are handled in the same place.
+ .balign 256
+vbr_start:
+ pt/l handler, tr0 ! tr0 trashed.
+ blink tr0, r63
+ .balign 256
+vbr_100:
+ pt/l handler, tr0 ! tr0 trashed.
+ blink tr0, r63
+vbr_100_end:
+ .balign 256
+vbr_200:
+ pt/l handler, tr0 ! tr0 trashed.
+ blink tr0, r63
+ .balign 256
+vbr_300:
+ pt/l handler, tr0 ! tr0 trashed.
+ blink tr0, r63
+ .balign 256
+vbr_400: ! Should be at vbr+0x400
+handler:
+ /* If the trap handler is there call it */
+ LOAD_ADDR (__superh_trap_handler, r2)
+ pta chandler,tr2
+ beq r2, r63, tr2 /* If zero, ie not present branch around to chandler */
+ /* Now call the trap handler with as much of the context unchanged as possible.
+ Move trapping address into R18 to make it look like the trap point */
+ getcon spc, r18
+ pt/l __superh_trap_handler, tr0
+ blink tr0, r7
+chandler:
+ getcon spc, r62
+ getcon expevt, r2
+ pt/l _exit, tr0
+ blink tr0, r63
+
+ /* Simulated trap handler */
+ .section .text..SHmedia32,"ax"
+gcc2_compiled.:
+ .section .debug_abbrev
+.Ldebug_abbrev0:
+ .section .text..SHmedia32
+.Ltext0:
+ .section .debug_info
+.Ldebug_info0:
+ .section .debug_line
+.Ldebug_line0:
+ .section .text..SHmedia32,"ax"
+ .align 5
+ .global __superh_trap_handler
+ .type __superh_trap_handler,@function
+__superh_trap_handler:
+.LFB1:
+ ptabs r18, tr0
+ addi.l r15, -8, r15
+ st.l r15, 4, r14
+ addi.l r15, -8, r15
+ add.l r15, r63, r14
+ st.l r14, 0, r2
+ ptabs r7, tr0
+ addi.l r14, 8, r14
+ add.l r14, r63, r15
+ ld.l r15, 4, r14
+ addi.l r15, 8, r15
+ blink tr0, r63
+.LFE1:
+.Lfe1:
+ .size __superh_trap_handler,.Lfe1-__superh_trap_handler
+
+ .section .text..SHmedia32
+.Letext0:
+
+ .section .debug_info
+ .ualong 0xa7
+ .uaword 0x2
+ .ualong .Ldebug_abbrev0
+ .byte 0x4
+ .byte 0x1
+ .ualong .Ldebug_line0
+ .ualong .Letext0
+ .ualong .Ltext0
+ .string "trap_handler.c"
+
+ .string "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+
+ .string "GNU C 2.97-sh5-010522"
+
+ .byte 0x1
+ .byte 0x2
+ .ualong 0x9a
+ .byte 0x1
+ .string "_superh_trap_handler"
+
+ .byte 0x1
+ .byte 0x2
+ .byte 0x1
+ .ualong .LFB1
+ .ualong .LFE1
+ .byte 0x1
+ .byte 0x5e
+ .byte 0x3
+ .string "trap_reason"
+
+ .byte 0x1
+ .byte 0x1
+ .ualong 0x9a
+ .byte 0x2
+ .byte 0x91
+ .byte 0x0
+ .byte 0x0
+ .byte 0x4
+ .string "unsigned int"
+
+ .byte 0x4
+ .byte 0x7
+ .byte 0x0
+
+ .section .debug_abbrev
+ .byte 0x1
+ .byte 0x11
+ .byte 0x1
+ .byte 0x10
+ .byte 0x6
+ .byte 0x12
+ .byte 0x1
+ .byte 0x11
+ .byte 0x1
+ .byte 0x3
+ .byte 0x8
+ .byte 0x1b
+ .byte 0x8
+ .byte 0x25
+ .byte 0x8
+ .byte 0x13
+ .byte 0xb
+ .byte 0,0
+ .byte 0x2
+ .byte 0x2e
+ .byte 0x1
+ .byte 0x1
+ .byte 0x13
+ .byte 0x3f
+ .byte 0xc
+ .byte 0x3
+ .byte 0x8
+ .byte 0x3a
+ .byte 0xb
+ .byte 0x3b
+ .byte 0xb
+ .byte 0x27
+ .byte 0xc
+ .byte 0x11
+ .byte 0x1
+ .byte 0x12
+ .byte 0x1
+ .byte 0x40
+ .byte 0xa
+ .byte 0,0
+ .byte 0x3
+ .byte 0x5
+ .byte 0x0
+ .byte 0x3
+ .byte 0x8
+ .byte 0x3a
+ .byte 0xb
+ .byte 0x3b
+ .byte 0xb
+ .byte 0x49
+ .byte 0x13
+ .byte 0x2
+ .byte 0xa
+ .byte 0,0
+ .byte 0x4
+ .byte 0x24
+ .byte 0x0
+ .byte 0x3
+ .byte 0x8
+ .byte 0xb
+ .byte 0xb
+ .byte 0x3e
+ .byte 0xb
+ .byte 0,0
+ .byte 0
+
+ .section .debug_pubnames
+ .ualong 0x27
+ .uaword 0x2
+ .ualong .Ldebug_info0
+ .ualong 0xab
+ .ualong 0x5b
+ .string "_superh_trap_handler"
+
+ .ualong 0x0
+
+ .section .debug_aranges
+ .ualong 0x1c
+ .uaword 0x2
+ .ualong .Ldebug_info0
+ .byte 0x4
+ .byte 0x0
+ .uaword 0x0,0
+ .ualong .Ltext0
+ .ualong .Letext0-.Ltext0
+ .ualong 0x0
+ .ualong 0x0
+ .ident "GCC: (GNU) 2.97-sh5-010522"
+#endif /* MMU_SUPPORT */
+#else /* ! __SH5__ */
+
+ ! make a place to keep any previous value of the vbr register
+ ! this will only have a value if it has been set by redboot (for example)
+ .section .bss
+old_vbr:
+ .long 0
+#ifdef PROFILE
+profiling_enabled:
+ .long 0
+#endif
+
+
+ .section .text
+ .global start
+ .import ___rtos_profiler_start_timer
+ .weak ___rtos_profiler_start_timer
+start:
+ mov.l stack_k,r15
+
+#if defined (__SH3__) || (defined (__SH_FPU_ANY__) && ! defined (__SH2A__)) || defined (__SH4_NOFPU__)
+#define VBR_SETUP
+ ! before zeroing the bss ...
+ ! if the vbr is already set to vbr_start then the program has been restarted
+ ! (i.e. it is not the first time the program has been run since reset)
+ ! reset the vbr to its old value before old_vbr (in bss) is wiped
+ ! this ensures that the later code does not create a circular vbr chain
+ stc vbr, r1
+ mov.l vbr_start_k, r2
+ cmp/eq r1, r2
+ bf 0f
+ ! reset the old vbr value
+ mov.l old_vbr_k, r1
+ mov.l @r1, r2
+ ldc r2, vbr
+0:
+#endif /* VBR_SETUP */
+
+ ! zero out bss
+ mov.l edata_k,r0
+ mov.l end_k,r1
+ mov #0,r2
+start_l:
+ mov.l r2,@r0
+ add #4,r0
+ cmp/ge r0,r1
+ bt start_l
+
+#if defined (__SH_FPU_ANY__)
+ mov.l set_fpscr_k, r1
+ mov #4,r4
+ jsr @r1
+ shll16 r4 ! Set DN bit (flush denormal inputs to zero)
+ lds r3,fpscr ! Switch to default precision
+#endif /* defined (__SH_FPU_ANY__) */
+
+#ifdef VBR_SETUP
+ ! save the existing contents of the vbr
+ ! there will only be a prior value when using something like redboot
+ ! otherwise it will be zero
+ stc vbr, r1
+ mov.l old_vbr_k, r2
+ mov.l r1, @r2
+ ! setup vbr
+ mov.l vbr_start_k, r1
+ ldc r1,vbr
+#endif /* VBR_SETUP */
+
+ ! if an rtos is exporting a timer start fn,
+ ! then pick up an SR which does not enable ints
+ ! (the rtos will take care of this)
+ mov.l rtos_start_fn, r0
+ mov.l sr_initial_bare, r1
+ tst r0, r0
+ bt set_sr
+
+ mov.l sr_initial_rtos, r1
+
+set_sr:
+ ! Set status register (sr)
+ ldc r1, sr
+
+ ! arrange for exit to call fini
+ mov.l atexit_k,r0
+ mov.l fini_k,r4
+ jsr @r0
+ nop
+
+#ifdef PROFILE
+ ! arrange for exit to call _mcleanup (via stop_profiling)
+ mova stop_profiling,r0
+ mov.l atexit_k,r1
+ jsr @r1
+ mov r0, r4
+
+ ! Call profiler startup code
+ mov.l monstartup_k, r0
+ mov.l start_k, r4
+ mov.l etext_k, r5
+ jsr @r0
+ nop
+
+ ! enable profiling trap
+ ! until now any trap 33s will have been ignored
+ ! This means that all library functions called before this point
+ ! (directly or indirectly) may have the profiling trap at the start.
+ ! Therefore, only mcount itself may not have the extra header.
+ mov.l profiling_enabled_k2, r0
+ mov #1, r1
+ mov.l r1, @r0
+#endif /* PROFILE */
+
+ ! call init
+ mov.l init_k,r0
+ jsr @r0
+ nop
+
+ ! call the mainline
+ mov.l main_k,r0
+ jsr @r0
+ nop
+
+ ! call exit
+ mov r0,r4
+ mov.l exit_k,r0
+ jsr @r0
+ nop
+
+ .balign 4
+#ifdef PROFILE
+stop_profiling:
+ # stop mcount counting
+ mov.l profiling_enabled_k2, r0
+ mov #0, r1
+ mov.l r1, @r0
+
+ # call mcleanup
+ mov.l mcleanup_k, r0
+ jmp @r0
+ nop
+
+ .balign 4
+mcleanup_k:
+ .long __mcleanup
+monstartup_k:
+ .long ___monstartup
+profiling_enabled_k2:
+ .long profiling_enabled
+start_k:
+ .long _start
+etext_k:
+ .long __etext
+#endif /* PROFILE */
+
+ .align 2
+#if defined (__SH_FPU_ANY__)
+set_fpscr_k:
+ .long ___set_fpscr
+#endif /* defined (__SH_FPU_ANY__) */
+
+stack_k:
+ .long _stack
+edata_k:
+ .long _edata
+end_k:
+ .long _end
+main_k:
+ .long ___setup_argv_and_call_main
+exit_k:
+ .long _exit
+atexit_k:
+ .long _atexit
+init_k:
+ .long _init
+fini_k:
+ .long _fini
+#ifdef VBR_SETUP
+old_vbr_k:
+ .long old_vbr
+vbr_start_k:
+ .long vbr_start
+#endif /* VBR_SETUP */
+
+sr_initial_rtos:
+ ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
+ ! Whether profiling or not, keep interrupts masked,
+ ! the RTOS will enable these if required.
+ .long 0x600000f1
+
+rtos_start_fn:
+ .long ___rtos_profiler_start_timer
+
+#ifdef PROFILE
+sr_initial_bare:
+ ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
+ ! For bare machine, we need to enable interrupts to get profiling working
+ .long 0x60000001
+#else
+
+sr_initial_bare:
+ ! Privileged mode RB 1 BL 0. Keep BL 0 to allow default trap handlers to work.
+ ! Keep interrupts disabled - the application will enable as required.
+ .long 0x600000f1
+#endif
+
+ ! supplied for backward compatibility only, in case of linking
+ ! code whose main() was compiled with an older version of GCC.
+ .global ___main
+___main:
+ rts
+ nop
+#ifdef VBR_SETUP
+! Exception handlers
+ .section .text.vbr, "ax"
+vbr_start:
+
+ .org 0x100
+vbr_100:
+#ifdef PROFILE
+ ! Note on register usage.
+ ! we use r0..r3 as scratch in this code. If we are here due to a trapa for profiling
+ ! then this is OK as we are just before executing any function code.
+ ! The other r4..r7 we save explicityl on the stack
+ ! Remaining registers are saved by normal ABI conventions and we assert we do not
+ ! use floating point registers.
+ mov.l expevt_k1, r1
+ mov.l @r1, r1
+ mov.l event_mask, r0
+ and r0,r1
+ mov.l trapcode_k, r2
+ cmp/eq r1,r2
+ bt 1f
+ bra handler_100 ! if not a trapa, go to default handler
+ nop
+1:
+ mov.l trapa_k, r0
+ mov.l @r0, r0
+ shlr2 r0 ! trapa code is shifted by 2.
+ cmp/eq #33, r0
+ bt 2f
+ bra handler_100
+ nop
+2:
+
+ ! If here then it looks like we have trap #33
+ ! Now we need to call mcount with the following convention
+ ! Save and restore r4..r7
+ mov.l r4,@-r15
+ mov.l r5,@-r15
+ mov.l r6,@-r15
+ mov.l r7,@-r15
+ sts.l pr,@-r15
+
+ ! r4 is frompc.
+ ! r5 is selfpc
+ ! r0 is the branch back address.
+ ! The code sequence emitted by gcc for the profiling trap is
+ ! .align 2
+ ! trapa #33
+ ! .align 2
+ ! .long lab Where lab is planted by the compiler. This is the address
+ ! of a datum that needs to be incremented.
+ sts pr, r4 ! frompc
+ stc spc, r5 ! selfpc
+ mov #2, r2
+ not r2, r2 ! pattern to align to 4
+ and r2, r5 ! r5 now has aligned address
+! add #4, r5 ! r5 now has address of address
+ mov r5, r2 ! Remember it.
+! mov.l @r5, r5 ! r5 has value of lable (lab in above example)
+ add #8, r2
+ ldc r2, spc ! our return address avoiding address word
+
+ ! only call mcount if profiling is enabled
+ mov.l profiling_enabled_k, r0
+ mov.l @r0, r0
+ cmp/eq #0, r0
+ bt 3f
+ ! call mcount
+ mov.l mcount_k, r2
+ jsr @r2
+ nop
+3:
+ lds.l @r15+,pr
+ mov.l @r15+,r7
+ mov.l @r15+,r6
+ mov.l @r15+,r5
+ mov.l @r15+,r4
+ rte
+ nop
+ .balign 4
+event_mask:
+ .long 0xfff
+trapcode_k:
+ .long 0x160
+expevt_k1:
+ .long 0xff000024 ! Address of expevt
+trapa_k:
+ .long 0xff000020
+mcount_k:
+ .long __call_mcount
+profiling_enabled_k:
+ .long profiling_enabled
+#endif
+ ! Non profiling case.
+handler_100:
+ mov.l 2f, r0 ! load the old vbr setting (if any)
+ mov.l @r0, r0
+ cmp/eq #0, r0
+ bf 1f
+ ! no previous vbr - jump to own generic handler
+ bra handler
+ nop
+1: ! there was a previous handler - chain them
+ add #0x7f, r0 ! 0x7f
+ add #0x7f, r0 ! 0xfe
+ add #0x2, r0 ! add 0x100 without corrupting another register
+ jmp @r0
+ nop
+ .balign 4
+2:
+ .long old_vbr
+
+ .org 0x400
+vbr_400: ! Should be at vbr+0x400
+ mov.l 2f, r0 ! load the old vbr setting (if any)
+ mov.l @r0, r0
+ cmp/eq #0, r0
+ ! no previous vbr - jump to own generic handler
+ bt handler
+ ! there was a previous handler - chain them
+ rotcr r0
+ rotcr r0
+ add #0x7f, r0 ! 0x1fc
+ add #0x7f, r0 ! 0x3f8
+ add #0x02, r0 ! 0x400
+ rotcl r0
+ rotcl r0 ! Add 0x400 without corrupting another register
+ jmp @r0
+ nop
+ .balign 4
+2:
+ .long old_vbr
+handler:
+ /* If the trap handler is there call it */
+ mov.l superh_trap_handler_k, r0
+ cmp/eq #0, r0 ! True if zero.
+ bf 3f
+ bra chandler
+ nop
+3:
+ ! Here handler available, call it.
+ /* Now call the trap handler with as much of the context unchanged as possible.
+ Move trapping address into PR to make it look like the trap point */
+ stc spc, r1
+ lds r1, pr
+ mov.l expevt_k, r4
+ mov.l @r4, r4 ! r4 is value of expevt, first parameter.
+ mov r1, r5 ! Remember trapping pc.
+ mov r1, r6 ! Remember trapping pc.
+ mov.l chandler_k, r1
+ mov.l superh_trap_handler_k, r2
+ ! jmp to trap handler to avoid disturbing pr.
+ jmp @r2
+ nop
+
+ .org 0x600
+vbr_600:
+#ifdef PROFILE
+ ! Should be at vbr+0x600
+ ! Now we are in the land of interrupts so need to save more state.
+ ! Save register state
+ mov.l interrupt_stack_k, r15 ! r15 has been saved to sgr.
+ mov.l r0,@-r15
+ mov.l r1,@-r15
+ mov.l r2,@-r15
+ mov.l r3,@-r15
+ mov.l r4,@-r15
+ mov.l r5,@-r15
+ mov.l r6,@-r15
+ mov.l r7,@-r15
+ sts.l pr,@-r15
+ sts.l mach,@-r15
+ sts.l macl,@-r15
+#if defined(__SH_FPU_ANY__)
+ ! Save fpul and fpscr, save fr0-fr7 in 64 bit mode
+ ! and set the pervading precision for the timer_handler
+ mov #0,r0
+ sts.l fpul,@-r15
+ sts.l fpscr,@-r15
+ lds r0,fpscr ! Clear fpscr
+ fmov fr0,@-r15
+ fmov fr1,@-r15
+ fmov fr2,@-r15
+ fmov fr3,@-r15
+ mov.l pervading_precision_k,r0
+ fmov fr4,@-r15
+ fmov fr5,@-r15
+ mov.l @r0,r0
+ fmov fr6,@-r15
+ fmov fr7,@-r15
+ lds r0,fpscr
+#endif /* __SH_FPU_ANY__ */
+ ! Pass interrupted pc to timer_handler as first parameter (r4).
+ stc spc, r4
+ mov.l timer_handler_k, r0
+ jsr @r0
+ nop
+#if defined(__SH_FPU_ANY__)
+ mov #0,r0
+ lds r0,fpscr ! Clear the fpscr
+ fmov @r15+,fr7
+ fmov @r15+,fr6
+ fmov @r15+,fr5
+ fmov @r15+,fr4
+ fmov @r15+,fr3
+ fmov @r15+,fr2
+ fmov @r15+,fr1
+ fmov @r15+,fr0
+ lds.l @r15+,fpscr
+ lds.l @r15+,fpul
+#endif /* __SH_FPU_ANY__ */
+ lds.l @r15+,macl
+ lds.l @r15+,mach
+ lds.l @r15+,pr
+ mov.l @r15+,r7
+ mov.l @r15+,r6
+ mov.l @r15+,r5
+ mov.l @r15+,r4
+ mov.l @r15+,r3
+ mov.l @r15+,r2
+ mov.l @r15+,r1
+ mov.l @r15+,r0
+ stc sgr, r15 ! Restore r15, destroyed by this sequence.
+ rte
+ nop
+#if defined(__SH_FPU_ANY__)
+ .balign 4
+pervading_precision_k:
+#define CONCAT1(A,B) A##B
+#define CONCAT(A,B) CONCAT1(A,B)
+ .long CONCAT(__USER_LABEL_PREFIX__,__fpscr_values)+4
+#endif
+#else
+ mov.l 2f, r0 ! Load the old vbr setting (if any).
+ mov.l @r0, r0
+ cmp/eq #0, r0
+ ! no previous vbr - jump to own handler
+ bt chandler
+ ! there was a previous handler - chain them
+ rotcr r0
+ rotcr r0
+ add #0x7f, r0 ! 0x1fc
+ add #0x7f, r0 ! 0x3f8
+ add #0x7f, r0 ! 0x5f4
+ add #0x03, r0 ! 0x600
+ rotcl r0
+ rotcl r0 ! Add 0x600 without corrupting another register
+ jmp @r0
+ nop
+ .balign 4
+2:
+ .long old_vbr
+#endif /* PROFILE code */
+chandler:
+ mov.l expevt_k, r4
+ mov.l @r4, r4 ! r4 is value of expevt hence making this the return code
+ mov.l handler_exit_k,r0
+ jsr @r0
+ nop
+ ! We should never return from _exit but in case we do we would enter the
+ ! the following tight loop
+limbo:
+ bra limbo
+ nop
+ .balign 4
+#ifdef PROFILE
+interrupt_stack_k:
+ .long __timer_stack ! The high end of the stack
+timer_handler_k:
+ .long __profil_counter
+#endif
+expevt_k:
+ .long 0xff000024 ! Address of expevt
+chandler_k:
+ .long chandler
+superh_trap_handler_k:
+ .long __superh_trap_handler
+handler_exit_k:
+ .long _exit
+ .align 2
+! Simulated compile of trap handler.
+ .section .debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+ .section .debug_info,"",@progbits
+.Ldebug_info0:
+ .section .debug_line,"",@progbits
+.Ldebug_line0:
+ .text
+.Ltext0:
+ .align 5
+ .type __superh_trap_handler,@function
+__superh_trap_handler:
+.LFB1:
+ mov.l r14,@-r15
+.LCFI0:
+ add #-4,r15
+.LCFI1:
+ mov r15,r14
+.LCFI2:
+ mov.l r4,@r14
+ lds r1, pr
+ add #4,r14
+ mov r14,r15
+ mov.l @r15+,r14
+ rts
+ nop
+.LFE1:
+.Lfe1:
+ .size __superh_trap_handler,.Lfe1-__superh_trap_handler
+ .section .debug_frame,"",@progbits
+.Lframe0:
+ .ualong .LECIE0-.LSCIE0
+.LSCIE0:
+ .ualong 0xffffffff
+ .byte 0x1
+ .string ""
+ .uleb128 0x1
+ .sleb128 -4
+ .byte 0x11
+ .byte 0xc
+ .uleb128 0xf
+ .uleb128 0x0
+ .align 2
+.LECIE0:
+.LSFDE0:
+ .ualong .LEFDE0-.LASFDE0
+.LASFDE0:
+ .ualong .Lframe0
+ .ualong .LFB1
+ .ualong .LFE1-.LFB1
+ .byte 0x4
+ .ualong .LCFI0-.LFB1
+ .byte 0xe
+ .uleb128 0x4
+ .byte 0x4
+ .ualong .LCFI1-.LCFI0
+ .byte 0xe
+ .uleb128 0x8
+ .byte 0x8e
+ .uleb128 0x1
+ .byte 0x4
+ .ualong .LCFI2-.LCFI1
+ .byte 0xd
+ .uleb128 0xe
+ .align 2
+.LEFDE0:
+ .text
+.Letext0:
+ .section .debug_info
+ .ualong 0xb3
+ .uaword 0x2
+ .ualong .Ldebug_abbrev0
+ .byte 0x4
+ .uleb128 0x1
+ .ualong .Ldebug_line0
+ .ualong .Letext0
+ .ualong .Ltext0
+ .string "trap_handler.c"
+ .string "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+ .string "GNU C 3.2 20020529 (experimental)"
+ .byte 0x1
+ .uleb128 0x2
+ .ualong 0xa6
+ .byte 0x1
+ .string "_superh_trap_handler"
+ .byte 0x1
+ .byte 0x2
+ .byte 0x1
+ .ualong .LFB1
+ .ualong .LFE1
+ .byte 0x1
+ .byte 0x5e
+ .uleb128 0x3
+ .string "trap_reason"
+ .byte 0x1
+ .byte 0x1
+ .ualong 0xa6
+ .byte 0x2
+ .byte 0x91
+ .sleb128 0
+ .byte 0x0
+ .uleb128 0x4
+ .string "unsigned int"
+ .byte 0x4
+ .byte 0x7
+ .byte 0x0
+ .section .debug_abbrev
+ .uleb128 0x1
+ .uleb128 0x11
+ .byte 0x1
+ .uleb128 0x10
+ .uleb128 0x6
+ .uleb128 0x12
+ .uleb128 0x1
+ .uleb128 0x11
+ .uleb128 0x1
+ .uleb128 0x3
+ .uleb128 0x8
+ .uleb128 0x1b
+ .uleb128 0x8
+ .uleb128 0x25
+ .uleb128 0x8
+ .uleb128 0x13
+ .uleb128 0xb
+ .byte 0x0
+ .byte 0x0
+ .uleb128 0x2
+ .uleb128 0x2e
+ .byte 0x1
+ .uleb128 0x1
+ .uleb128 0x13
+ .uleb128 0x3f
+ .uleb128 0xc
+ .uleb128 0x3
+ .uleb128 0x8
+ .uleb128 0x3a
+ .uleb128 0xb
+ .uleb128 0x3b
+ .uleb128 0xb
+ .uleb128 0x27
+ .uleb128 0xc
+ .uleb128 0x11
+ .uleb128 0x1
+ .uleb128 0x12
+ .uleb128 0x1
+ .uleb128 0x40
+ .uleb128 0xa
+ .byte 0x0
+ .byte 0x0
+ .uleb128 0x3
+ .uleb128 0x5
+ .byte 0x0
+ .uleb128 0x3
+ .uleb128 0x8
+ .uleb128 0x3a
+ .uleb128 0xb
+ .uleb128 0x3b
+ .uleb128 0xb
+ .uleb128 0x49
+ .uleb128 0x13
+ .uleb128 0x2
+ .uleb128 0xa
+ .byte 0x0
+ .byte 0x0
+ .uleb128 0x4
+ .uleb128 0x24
+ .byte 0x0
+ .uleb128 0x3
+ .uleb128 0x8
+ .uleb128 0xb
+ .uleb128 0xb
+ .uleb128 0x3e
+ .uleb128 0xb
+ .byte 0x0
+ .byte 0x0
+ .byte 0x0
+ .section .debug_pubnames,"",@progbits
+ .ualong 0x27
+ .uaword 0x2
+ .ualong .Ldebug_info0
+ .ualong 0xb7
+ .ualong 0x67
+ .string "_superh_trap_handler"
+ .ualong 0x0
+ .section .debug_aranges,"",@progbits
+ .ualong 0x1c
+ .uaword 0x2
+ .ualong .Ldebug_info0
+ .byte 0x4
+ .byte 0x0
+ .uaword 0x0
+ .uaword 0x0
+ .ualong .Ltext0
+ .ualong .Letext0-.Ltext0
+ .ualong 0x0
+ .ualong 0x0
+#endif /* VBR_SETUP */
+#endif /* ! __SH5__ */
diff --git a/libgcc/config/sh/crti.S b/libgcc/config/sh/crti.S
new file mode 100644
index 00000000000..a8e4f8bed22
--- /dev/null
+++ b/libgcc/config/sh/crti.S
@@ -0,0 +1,125 @@
+/* Copyright (C) 2000, 2001, 2009, 2011 Free Software Foundation, Inc.
+ This file was adapted from glibc sources.
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+
+/* The code in sections .init and .fini is supposed to be a single
+ regular function. The function in .init is called directly from
+ start in crt1.S. The function in .fini is atexit()ed in crt1.S
+ too.
+
+ crti.S contributes the prologue of a function to these sections,
+ and crtn.S comes up the epilogue. STARTFILE_SPEC should list
+ crti.o before any other object files that might add code to .init
+ or .fini sections, and ENDFILE_SPEC should list crtn.o after any
+ such object files. */
+
+ .section .init
+/* The alignment below can't be smaller, otherwise the mova below
+ breaks. Yes, we might align just the label, but then we'd be
+ exchanging an alignment here for one there, since the code fragment
+ below ensures 4-byte alignment on __ELF__. */
+#ifdef __ELF__
+ .p2align 2
+#else
+ .p2align 1
+#endif
+ .global _init
+_init:
+#if __SHMEDIA__
+ addi r15, -16, r15
+ st.q r15, 8, r14
+ st.q r15, 0, r18
+ add r15, r63, r14
+#elif __SH5__ && ! __SHMEDIA__
+ mov r15,r0
+ add #-8,r15
+ mov.l r14,@-r0
+ sts.l pr,@-r0
+ mov r15,r14
+ nop
+#else
+#ifdef __ELF__
+ mov.l r12,@-r15
+ mova 0f,r0
+ mov.l 0f,r12
+#endif
+ mov.l r14,@-r15
+#ifdef __ELF__
+ add r0,r12
+#endif
+ sts.l pr,@-r15
+#ifdef __ELF__
+ bra 1f
+#endif
+ mov r15,r14
+#ifdef __ELF__
+0: .long _GLOBAL_OFFSET_TABLE_
+1:
+#endif
+#endif /* __SHMEDIA__ */
+
+ .section .fini
+/* The alignment below can't be smaller, otherwise the mova below
+ breaks. Yes, we might align just the label, but then we'd be
+ exchanging an alignment here for one there, since the code fragment
+ below ensures 4-byte alignment on __ELF__. */
+#ifdef __ELF__
+ .p2align 2
+#else
+ .p2align 1
+#endif
+ .global _fini
+_fini:
+#if __SHMEDIA__
+ addi r15, -16, r15
+ st.q r15, 8, r14
+ st.q r15, 0, r18
+ add r15, r63, r14
+#elif __SH5__ && ! __SHMEDIA__
+ mov r15,r0
+ add #-8,r15
+ mov.l r14,@-r0
+ sts.l pr,@-r0
+ mov r15,r14
+ nop
+#else
+#ifdef __ELF__
+ mov.l r12,@-r15
+ mova 0f,r0
+ mov.l 0f,r12
+#endif
+ mov.l r14,@-r15
+#ifdef __ELF__
+ add r0,r12
+#endif
+ sts.l pr,@-r15
+#ifdef __ELF__
+ bra 1f
+#endif
+ mov r15,r14
+#ifdef __ELF__
+0: .long _GLOBAL_OFFSET_TABLE_
+1:
+#endif
+#endif /* __SHMEDIA__ */
diff --git a/libgcc/config/sh/crtn.S b/libgcc/config/sh/crtn.S
new file mode 100644
index 00000000000..d2f58c01b1b
--- /dev/null
+++ b/libgcc/config/sh/crtn.S
@@ -0,0 +1,77 @@
+/* Copyright (C) 2000, 2001, 2009, 2011 Free Software Foundation, Inc.
+ This file was adapted from glibc sources.
+
+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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* See an explanation about .init and .fini in crti.S. */
+
+ .section .init
+#if __SHMEDIA__
+ add r14, r63, r15
+ ld.q r15, 0, r18
+ ptabs r18, tr0
+ ld.q r15, 8, r14
+ addi r15, 16, r15
+ blink tr0, r63
+#elif __SH5__ && ! __SHMEDIA__
+ mov r14,r15
+ lds.l @r14+,pr
+ mov.l @r14,r14
+ rts
+ add #8,r15
+#else
+ mov r14,r15
+ lds.l @r15+,pr
+ mov.l @r15+,r14
+ rts
+#ifdef __ELF__
+ mov.l @r15+,r12
+#else
+ nop
+#endif
+#endif /* __SHMEDIA__ */
+
+ .section .fini
+#if __SHMEDIA__
+ add r14, r63, r15
+ ld.q r15, 0, r18
+ ptabs r18, tr0
+ ld.q r15, 8, r14
+ addi r15, 16, r15
+ blink tr0, r63
+#elif __SH5__ && ! __SHMEDIA__
+ mov r14,r15
+ lds.l @r14+,pr
+ mov.l @r14,r14
+ rts
+ add #8,r15
+#else
+ mov r14,r15
+ lds.l @r15+,pr
+ mov.l @r15+,r14
+ rts
+#ifdef __ELF__
+ mov.l @r15+,r12
+#else
+ nop
+#endif
+#endif /* __SHMEDIA__ */
diff --git a/gcc/config/sh/lib1funcs-4-300.asm b/libgcc/config/sh/lib1funcs-4-300.S
index b131877f121..b131877f121 100644
--- a/gcc/config/sh/lib1funcs-4-300.asm
+++ b/libgcc/config/sh/lib1funcs-4-300.S
diff --git a/gcc/config/sh/lib1funcs-Os-4-200.asm b/libgcc/config/sh/lib1funcs-Os-4-200.S
index aae57ccd36c..aae57ccd36c 100644
--- a/gcc/config/sh/lib1funcs-Os-4-200.asm
+++ b/libgcc/config/sh/lib1funcs-Os-4-200.S
diff --git a/gcc/config/sh/lib1funcs.asm b/libgcc/config/sh/lib1funcs.S
index 2f0ca16cd91..2f0ca16cd91 100644
--- a/gcc/config/sh/lib1funcs.asm
+++ b/libgcc/config/sh/lib1funcs.S
diff --git a/gcc/config/sh/lib1funcs.h b/libgcc/config/sh/lib1funcs.h
index af4b41cc314..af4b41cc314 100644
--- a/gcc/config/sh/lib1funcs.h
+++ b/libgcc/config/sh/lib1funcs.h
diff --git a/gcc/config/sh/libgcc-excl.ver b/libgcc/config/sh/libgcc-excl.ver
index 325c74054ec..325c74054ec 100644
--- a/gcc/config/sh/libgcc-excl.ver
+++ b/libgcc/config/sh/libgcc-excl.ver
diff --git a/gcc/config/sh/libgcc-glibc.ver b/libgcc/config/sh/libgcc-glibc.ver
index b8ec3265310..b8ec3265310 100644
--- a/gcc/config/sh/libgcc-glibc.ver
+++ b/libgcc/config/sh/libgcc-glibc.ver
diff --git a/gcc/config/sh/linux-atomic.asm b/libgcc/config/sh/linux-atomic.S
index 743c61bb76c..743c61bb76c 100644
--- a/gcc/config/sh/linux-atomic.asm
+++ b/libgcc/config/sh/linux-atomic.S
diff --git a/libgcc/config/sh/t-linux b/libgcc/config/sh/t-linux
index a98fb18e8d1..d0f92405fd8 100644
--- a/libgcc/config/sh/t-linux
+++ b/libgcc/config/sh/t-linux
@@ -1,4 +1,8 @@
-HOST_LIBGCC2_CFLAGS = -fpic -mieee -DNO_FPSCR_VALUES
+LIB1ASMFUNCS_CACHE = _ic_invalidate _ic_invalidate_array
+
+LIB2ADD = $(srcdir)/config/sh/linux-atomic.S
+
+HOST_LIBGCC2_CFLAGS += -mieee -DNO_FPSCR_VALUES
# Override t-slibgcc-elf-ver to export some libgcc symbols with
# the symbol versions that glibc used, and hide some lib1func
@@ -6,32 +10,5 @@ HOST_LIBGCC2_CFLAGS = -fpic -mieee -DNO_FPSCR_VALUES
# the list from scratch.
SHLIB_MAPFILES = \
libgcc-std.ver \
- $(gcc_srcdir)/config/sh/libgcc-excl.ver \
- $(gcc_srcdir)/config/sh/libgcc-glibc.ver
-
-# Override SHLIB_LINK and SHLIB_INSTALL to use linker script
-# libgcc_s.so.
-SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
- -Wl,--soname=@shlib_base_name@.so.1 \
- -Wl,--version-script=@shlib_map_file@ \
- -o @multilib_dir@/@shlib_base_name@.so.1.tmp @multilib_flags@ \
- @shlib_objs@ -lc && \
- rm -f @multilib_dir@/@shlib_base_name@.so && \
- if [ -f @multilib_dir@/@shlib_base_name@.so.1 ]; then \
- mv -f @multilib_dir@/@shlib_base_name@.so.1 \
- @multilib_dir@/@shlib_base_name@.so.1.backup; \
- else true; fi && \
- mv @multilib_dir@/@shlib_base_name@.so.1.tmp \
- @multilib_dir@/@shlib_base_name@.so.1 && \
- (echo "/* GNU ld script"; \
- echo " Use the shared library, but some functions are only in"; \
- echo " the static library. */"; \
- echo "GROUP ( @shlib_base_name@.so.1 libgcc.a )" \
- ) > @multilib_dir@/@shlib_base_name@.so
-SHLIB_INSTALL = \
- $(mkinstalldirs) $(DESTDIR)$(slibdir)@shlib_slibdir_qual@; \
- $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.so.1 \
- $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so.1; \
- rm -f $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so; \
- $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.so \
- $(DESTDIR)$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so
+ $(srcdir)/config/sh/libgcc-excl.ver \
+ $(srcdir)/config/sh/libgcc-glibc.ver
diff --git a/libgcc/config/sh/t-netbsd b/libgcc/config/sh/t-netbsd
new file mode 100644
index 00000000000..d4df407fa16
--- /dev/null
+++ b/libgcc/config/sh/t-netbsd
@@ -0,0 +1,5 @@
+LIB1ASMFUNCS_CACHE = _ic_invalidate
+
+LIB2ADD =
+
+HOST_LIBGCC2_CFLAGS += -mieee
diff --git a/libgcc/config/sh/t-sh b/libgcc/config/sh/t-sh
new file mode 100644
index 00000000000..2a7bc7df96c
--- /dev/null
+++ b/libgcc/config/sh/t-sh
@@ -0,0 +1,63 @@
+# Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2006, 2008, 2009, 2011 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+LIB1ASMSRC = sh/lib1funcs.S
+LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movmem \
+ _movmem_i4 _mulsi3 _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
+ _div_table _udiv_qrnnd_16 \
+ $(LIB1ASMFUNCS_CACHE)
+LIB1ASMFUNCS_CACHE = _ic_invalidate _ic_invalidate_array
+
+crt1.o: $(srcdir)/config/sh/crt1.S
+ $(gcc_compile) -c $<
+
+ic_invalidate_array_4-100.o: $(srcdir)/config/sh/lib1funcs.S
+ $(gcc_compile) -c -DL_ic_invalidate_array -DWAYS=1 -DWAY_SIZE=0x2000 $<
+libic_invalidate_array_4-100.a: ic_invalidate_array_4-100.o
+ $(AR_CREATE_FOR_TARGET) $@ $<
+
+ic_invalidate_array_4-200.o: $(srcdir)/config/sh/lib1funcs.S
+ $(gcc_compile) -c -DL_ic_invalidate_array -DWAYS=2 -DWAY_SIZE=0x2000 $<
+libic_invalidate_array_4-200.a: ic_invalidate_array_4-200.o
+ $(AR_CREATE_FOR_TARGET) $@ $<
+
+ic_invalidate_array_4a.o: $(srcdir)/config/sh/lib1funcs.S
+ $(gcc_compile) -c -DL_ic_invalidate_array -D__FORCE_SH4A__ $<
+libic_invalidate_array_4a.a: ic_invalidate_array_4a.o
+ $(AR_CREATE_FOR_TARGET) $@ $<
+
+sdivsi3_i4i-Os-4-200.o: $(srcdir)/config/sh/lib1funcs-Os-4-200.S
+ $(compile) -c -DL_sdivsi3_i4i $<
+udivsi3_i4i-Os-4-200.o: $(srcdir)/config/sh/lib1funcs-Os-4-200.S
+ $(gcc_compile) -c -DL_udivsi3_i4i $<
+unwind-dw2-Os-4-200.o: $(srcdir)/unwind-dw2.c
+ $(gcc_compile) $(LIBGCC2_CFLAGS) $(vis_hide) -fexceptions -Os -c $<
+
+OBJS_Os_4_200=sdivsi3_i4i-Os-4-200.o udivsi3_i4i-Os-4-200.o unwind-dw2-Os-4-200.o
+libgcc-Os-4-200.a: $(OBJS_Os_4_200)
+ $(AR_CREATE_FOR_TARGET) $@ $(OBJS_Os_4_200)
+
+div_table-4-300.o: $(srcdir)/config/sh/lib1funcs-4-300.S
+ $(gcc_compile) -c -DL_div_table $<
+
+libgcc-4-300.a: div_table-4-300.o
+ $(AR_CREATE_FOR_TARGET) $@ div_table-4-300.o
+
+HOST_LIBGCC2_CFLAGS = -mieee
+
diff --git a/libgcc/config/sh/t-sh64 b/libgcc/config/sh/t-sh64
new file mode 100644
index 00000000000..fa9950e03b2
--- /dev/null
+++ b/libgcc/config/sh/t-sh64
@@ -0,0 +1,6 @@
+LIB1ASMFUNCS = \
+ _sdivsi3 _sdivsi3_i4 _udivsi3 _udivsi3_i4 _set_fpscr \
+ _shcompact_call_trampoline _shcompact_return_trampoline \
+ _shcompact_incoming_args _ic_invalidate _nested_trampoline \
+ _push_pop_shmedia_regs \
+ _udivdi3 _divdi3 _umoddi3 _moddi3 _div_table
diff --git a/libgcc/config/sh/t-superh b/libgcc/config/sh/t-superh
new file mode 100644
index 00000000000..b87aa5a3167
--- /dev/null
+++ b/libgcc/config/sh/t-superh
@@ -0,0 +1,11 @@
+# Compile crt1-mmu.o as crt1.o with -DMMU_SUPPORT
+crt1-mmu.o: $(srcdir)/config/sh/crt1.S
+ $(gcc_compile) -c -DMMU_SUPPORT $<
+
+# Compile gcrt1-mmu.o as crt1-mmu.o with -DPROFILE
+gcrt1-mmu.o: $(srcdir)/config/sh/crt1.S
+ $(gcc_compile) -c -DPROFILE -DMMU_SUPPORT $<
+
+# For sh4-400: Compile gcrt1.o as crt1.o with -DPROFILE
+gcrt1.o: $(srcdir)/config/sh/crt1.S
+ $(gcc_compile) -c -DPROFILE $<
diff --git a/gcc/config/sparc/lb1spc.asm b/libgcc/config/sparc/lb1spc.S
index b60bd5740e7..b60bd5740e7 100644
--- a/gcc/config/sparc/lb1spc.asm
+++ b/libgcc/config/sparc/lb1spc.S
diff --git a/gcc/config/sparc/libgcc-sparc-glibc.ver b/libgcc/config/sparc/libgcc-glibc.ver
index 91138d3795e..91138d3795e 100644
--- a/gcc/config/sparc/libgcc-sparc-glibc.ver
+++ b/libgcc/config/sparc/libgcc-glibc.ver
diff --git a/libgcc/config/sparc/t-linux b/libgcc/config/sparc/t-linux
new file mode 100644
index 00000000000..474f1755ea3
--- /dev/null
+++ b/libgcc/config/sparc/t-linux
@@ -0,0 +1,4 @@
+# Override t-slibgcc-elf-ver to export some libgcc symbols with
+# the symbol versions that glibc used.
+# Avoid the t-linux version file.
+SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/sparc/libgcc-glibc.ver
diff --git a/libgcc/config/sparc/t-linux64 b/libgcc/config/sparc/t-linux64
new file mode 100644
index 00000000000..ca4a8929163
--- /dev/null
+++ b/libgcc/config/sparc/t-linux64
@@ -0,0 +1,2 @@
+CRTSTUFF_T_CFLAGS = `if test x$$($(CC) -print-multi-os-directory) \
+ = x../lib64; then echo -mcmodel=medany; fi`
diff --git a/libgcc/config/sparc/t-softmul b/libgcc/config/sparc/t-softmul
index 49faae47c53..7142200600f 100644
--- a/libgcc/config/sparc/t-softmul
+++ b/libgcc/config/sparc/t-softmul
@@ -1,2 +1,2 @@
-LIB1ASMSRC = sparc/lb1spc.asm
+LIB1ASMSRC = sparc/lb1spc.S
LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3
diff --git a/libgcc/config/sparc/t-sol2 b/libgcc/config/sparc/t-sol2
index 372522bd0e4..ea3fa63a272 100644
--- a/libgcc/config/sparc/t-sol2
+++ b/libgcc/config/sparc/t-sol2
@@ -3,4 +3,4 @@
# to produce a shared library, but since we don't know ahead of time when
# we will be doing that, we just always use -fPIC when compiling the
# routines in crtstuff.c.
-CRTSTUFF_T_CFLAGS = -fPIC
+CRTSTUFF_T_CFLAGS = $(PICFLAG)
diff --git a/gcc/config/spu/cache.S b/libgcc/config/spu/cache.S
index 9ffb6a0d194..9ffb6a0d194 100644
--- a/gcc/config/spu/cache.S
+++ b/libgcc/config/spu/cache.S
diff --git a/gcc/config/spu/cachemgr.c b/libgcc/config/spu/cachemgr.c
index e7abd5e62db..e7abd5e62db 100644
--- a/gcc/config/spu/cachemgr.c
+++ b/libgcc/config/spu/cachemgr.c
diff --git a/libgcc/config/spu/divmodti4.c b/libgcc/config/spu/divmodti4.c
new file mode 100644
index 00000000000..c63fb6b393c
--- /dev/null
+++ b/libgcc/config/spu/divmodti4.c
@@ -0,0 +1,188 @@
+/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
+
+ This file is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your option)
+ any later version.
+
+ This file is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <spu_intrinsics.h>
+
+typedef unsigned int UTItype __attribute__ ((mode (TI)));
+typedef int TItype __attribute__ ((mode (TI)));
+TItype __divti3 (TItype u, TItype v);
+TItype __modti3 (TItype u, TItype v);
+UTItype __udivti3 (UTItype u, UTItype v);
+UTItype __umodti3 (UTItype u, UTItype v);
+UTItype __udivmodti4 (UTItype u, UTItype v, UTItype *w);
+
+union qword_UTItype
+ {
+ qword q;
+ UTItype t;
+ };
+
+inline static qword
+si_from_UTItype (UTItype t)
+{
+ union qword_UTItype u;
+ u.t = t;
+ return u.q;
+}
+
+inline static UTItype
+si_to_UTItype (qword q)
+{
+ union qword_UTItype u;
+ u.q = q;
+ return u.t;
+}
+
+inline static unsigned int
+count_leading_zeros (UTItype x)
+{
+ qword c = si_clz (*(qword *) & x);
+ qword cmp0 = si_cgti (c, 31);
+ qword cmp1 = si_and (cmp0, si_shlqbyi (cmp0, 4));
+ qword cmp2 = si_and (cmp1, si_shlqbyi (cmp0, 8));
+ qword s = si_a (c, si_and (cmp0, si_shlqbyi (c, 4)));
+ s = si_a (s, si_and (cmp1, si_shlqbyi (c, 8)));
+ s = si_a (s, si_and (cmp2, si_shlqbyi (c, 12)));
+ return si_to_uint (s);
+}
+
+/* Based on implementation of udivmodsi4, which is essentially
+ * an optimized version of libgcc/udivmodsi4.c
+ clz %7,%2
+ clz %4,%1
+ il %5,1
+ fsmbi %0,0
+ sf %7,%4,%7
+ ori %3,%1,0
+ shl %5,%5,%7
+ shl %4,%2,%7
+1: or %8,%0,%5
+ rotmi %5,%5,-1
+ clgt %6,%4,%3
+ sf %7,%4,%3
+ rotmi %4,%4,-1
+ selb %0,%8,%0,%6
+ selb %3,%7,%3,%6
+3: brnz %5,1b
+ */
+
+UTItype
+__udivmodti4 (UTItype num, UTItype den, UTItype * rp)
+{
+ qword shift =
+ si_from_uint (count_leading_zeros (den) - count_leading_zeros (num));
+ qword n0 = si_from_UTItype (num);
+ qword d0 = si_from_UTItype (den);
+ qword bit = si_andi (si_fsmbi (1), 1);
+ qword r0 = si_il (0);
+ qword m1 = si_fsmbi (0x000f);
+ qword mask, r1, n1;
+
+ d0 = si_shlqbybi (si_shlqbi (d0, shift), shift);
+ bit = si_shlqbybi (si_shlqbi (bit, shift), shift);
+
+ do
+ {
+ r1 = si_or (r0, bit);
+
+ // n1 = n0 - d0 in TImode
+ n1 = si_bg (d0, n0);
+ n1 = si_shlqbyi (n1, 4);
+ n1 = si_sf (m1, n1);
+ n1 = si_bgx (d0, n0, n1);
+ n1 = si_shlqbyi (n1, 4);
+ n1 = si_sf (m1, n1);
+ n1 = si_bgx (d0, n0, n1);
+ n1 = si_shlqbyi (n1, 4);
+ n1 = si_sf (m1, n1);
+ n1 = si_sfx (d0, n0, n1);
+
+ mask = si_fsm (si_cgti (n1, -1));
+ r0 = si_selb (r0, r1, mask);
+ n0 = si_selb (n0, n1, mask);
+ bit = si_rotqmbii (bit, -1);
+ d0 = si_rotqmbii (d0, -1);
+ }
+ while (si_to_uint (si_orx (bit)));
+ if (rp)
+ *rp = si_to_UTItype (n0);
+ return si_to_UTItype (r0);
+}
+
+UTItype
+__udivti3 (UTItype n, UTItype d)
+{
+ return __udivmodti4 (n, d, (UTItype *)0);
+}
+
+UTItype
+__umodti3 (UTItype n, UTItype d)
+{
+ UTItype w;
+ __udivmodti4 (n, d, &w);
+ return w;
+}
+
+TItype
+__divti3 (TItype n, TItype d)
+{
+ int c = 0;
+ TItype w;
+
+ if (n < 0)
+ {
+ c = ~c;
+ n = -n;
+ }
+ if (d < 0)
+ {
+ c = ~c;
+ d = -d;
+ }
+
+ w = __udivmodti4 (n, d, (UTItype *)0);
+ if (c)
+ w = -w;
+ return w;
+}
+
+TItype
+__modti3 (TItype n, TItype d)
+{
+ int c = 0;
+ TItype w;
+
+ if (n < 0)
+ {
+ c = ~c;
+ n = -n;
+ }
+ if (d < 0)
+ {
+ c = ~c;
+ d = -d;
+ }
+
+ __udivmodti4 (n, d, (UTItype *) &w);
+ if (c)
+ w = -w;
+ return w;
+}
diff --git a/gcc/config/spu/divv2df3.c b/libgcc/config/spu/divv2df3.c
index 9d5e1a594e1..9d5e1a594e1 100644
--- a/gcc/config/spu/divv2df3.c
+++ b/libgcc/config/spu/divv2df3.c
diff --git a/gcc/config/spu/float_disf.c b/libgcc/config/spu/float_disf.c
index 0f4fe3d8e29..0f4fe3d8e29 100644
--- a/gcc/config/spu/float_disf.c
+++ b/libgcc/config/spu/float_disf.c
diff --git a/gcc/config/spu/float_unsdidf.c b/libgcc/config/spu/float_unsdidf.c
index 4fdf0b88a2b..4fdf0b88a2b 100644
--- a/gcc/config/spu/float_unsdidf.c
+++ b/libgcc/config/spu/float_unsdidf.c
diff --git a/gcc/config/spu/float_unsdisf.c b/libgcc/config/spu/float_unsdisf.c
index 7af120ecc8c..7af120ecc8c 100644
--- a/gcc/config/spu/float_unsdisf.c
+++ b/libgcc/config/spu/float_unsdisf.c
diff --git a/gcc/config/spu/float_unssidf.c b/libgcc/config/spu/float_unssidf.c
index b255f81af55..b255f81af55 100644
--- a/gcc/config/spu/float_unssidf.c
+++ b/libgcc/config/spu/float_unssidf.c
diff --git a/gcc/config/spu/mfc_multi_tag_release.c b/libgcc/config/spu/mfc_multi_tag_release.c
index 62eb2beeb8f..62eb2beeb8f 100644
--- a/gcc/config/spu/mfc_multi_tag_release.c
+++ b/libgcc/config/spu/mfc_multi_tag_release.c
diff --git a/gcc/config/spu/mfc_multi_tag_reserve.c b/libgcc/config/spu/mfc_multi_tag_reserve.c
index 06d70259276..06d70259276 100644
--- a/gcc/config/spu/mfc_multi_tag_reserve.c
+++ b/libgcc/config/spu/mfc_multi_tag_reserve.c
diff --git a/gcc/config/spu/mfc_tag_release.c b/libgcc/config/spu/mfc_tag_release.c
index d59c5713053..d59c5713053 100644
--- a/gcc/config/spu/mfc_tag_release.c
+++ b/libgcc/config/spu/mfc_tag_release.c
diff --git a/gcc/config/spu/mfc_tag_reserve.c b/libgcc/config/spu/mfc_tag_reserve.c
index 23b4817c74f..23b4817c74f 100644
--- a/gcc/config/spu/mfc_tag_reserve.c
+++ b/libgcc/config/spu/mfc_tag_reserve.c
diff --git a/gcc/config/spu/mfc_tag_table.c b/libgcc/config/spu/mfc_tag_table.c
index bd08c580c18..bd08c580c18 100644
--- a/gcc/config/spu/mfc_tag_table.c
+++ b/libgcc/config/spu/mfc_tag_table.c
diff --git a/gcc/config/spu/multi3.c b/libgcc/config/spu/multi3.c
index b8b0e90ee25..b8b0e90ee25 100644
--- a/gcc/config/spu/multi3.c
+++ b/libgcc/config/spu/multi3.c
diff --git a/libgcc/config/spu/t-elf b/libgcc/config/spu/t-elf
index 7094da526bb..83616c1ca7d 100644
--- a/libgcc/config/spu/t-elf
+++ b/libgcc/config/spu/t-elf
@@ -1,3 +1,59 @@
+# Don't let CTOR_LIST end up in sdata section.
+# FIXME: This is the default.
+CRTSTUFF_T_CFLAGS =
+
+# We exclude those because the libgcc2.c default versions do not support
+# the SPU single-precision format (round towards zero). We provide our
+# own versions below and/or via direct expansion.
+LIB2ADD = _floatdisf _floatundisf _floattisf _floatunstisf
+
+LIB2ADD_ST = $(srcdir)/config/spu/float_unssidf.c \
+ $(srcdir)/config/spu/float_unsdidf.c \
+ $(srcdir)/config/spu/float_unsdisf.c \
+ $(srcdir)/config/spu/float_disf.c \
+ $(srcdir)/config/spu/mfc_tag_table.c \
+ $(srcdir)/config/spu/mfc_tag_reserve.c \
+ $(srcdir)/config/spu/mfc_tag_release.c \
+ $(srcdir)/config/spu/mfc_multi_tag_reserve.c \
+ $(srcdir)/config/spu/mfc_multi_tag_release.c \
+ $(srcdir)/config/spu/multi3.c \
+ $(srcdir)/config/spu/divmodti4.c \
+ $(srcdir)/config/spu/divv2df3.c
+
+# Build TImode conversion routines to support Fortran 128-bit
+# integer data types.
+LIB2_SIDITI_CONV_FUNCS = yes
+
+HOST_LIBGCC2_CFLAGS += -mwarn-reloc -D__IN_LIBGCC2
+
+# Neither gcc or newlib seem to have a standard way to generate multiple
+# crt*.o files. So we don't use the standard crt0.o name anymore.
+
+cachemgr.o: $(srcdir)/config/spu/cachemgr.c
+ $(gcc_compile) -c $<
+
+# Specialised rule to add a -D flag.
+cachemgr_nonatomic.o: $(srcdir)/config/spu/cachemgr.c
+ $(gcc_compile) -DNONATOMIC -c $<
+
+libgcc_%.a: %.o
+ $(AR_FOR_TARGET) -rcs $@ $<
+
+cache8k.o: $(srcdir)/config/spu/cache.S
+ $(gcc_compile) -D__CACHE_SIZE__=8 -c $<
+
+cache16k.o: $(srcdir)/config/spu/cache.S
+ $(gcc_compile) -D__CACHE_SIZE__=16 -c $<
+
+cache32k.o: $(srcdir)/config/spu/cache.S
+ $(gcc_compile) -D__CACHE_SIZE__=32 -c $<
+
+cache64k.o: $(srcdir)/config/spu/cache.S
+ $(gcc_compile) -D__CACHE_SIZE__=64 -c $<
+
+cache128k.o: $(srcdir)/config/spu/cache.S
+ $(gcc_compile) -D__CACHE_SIZE__=128 -c $<
+
# We provide our own version of __divdf3 that performs better and has
# better support for non-default rounding modes.
DPBIT_FUNCS := $(filter-out _div_df, $(DPBIT_FUNCS))
diff --git a/libgcc/config/stormy16/ashlsi3.c b/libgcc/config/stormy16/ashlsi3.c
new file mode 100644
index 00000000000..0ef42ad66d3
--- /dev/null
+++ b/libgcc/config/stormy16/ashlsi3.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_ASHLSI3
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/ashrsi3.c b/libgcc/config/stormy16/ashrsi3.c
new file mode 100644
index 00000000000..67bcbbbe05b
--- /dev/null
+++ b/libgcc/config/stormy16/ashrsi3.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_ASHRSI3
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/clzhi2.c b/libgcc/config/stormy16/clzhi2.c
new file mode 100644
index 00000000000..350ef41daaf
--- /dev/null
+++ b/libgcc/config/stormy16/clzhi2.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_CLZHI2
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/cmpsi2.c b/libgcc/config/stormy16/cmpsi2.c
new file mode 100644
index 00000000000..fe32fda95cb
--- /dev/null
+++ b/libgcc/config/stormy16/cmpsi2.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_CMPSI2
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/ctzhi2.c b/libgcc/config/stormy16/ctzhi2.c
new file mode 100644
index 00000000000..98ab76dcd69
--- /dev/null
+++ b/libgcc/config/stormy16/ctzhi2.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_CTZHI2
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/divsi3.c b/libgcc/config/stormy16/divsi3.c
new file mode 100644
index 00000000000..0fa75342f4a
--- /dev/null
+++ b/libgcc/config/stormy16/divsi3.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_DIVSI3
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/ffshi2.c b/libgcc/config/stormy16/ffshi2.c
new file mode 100644
index 00000000000..a36dec87eb9
--- /dev/null
+++ b/libgcc/config/stormy16/ffshi2.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_FFSHI2
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/lib2funcs.c b/libgcc/config/stormy16/lib2funcs.c
new file mode 100644
index 00000000000..a10a9b28119
--- /dev/null
+++ b/libgcc/config/stormy16/lib2funcs.c
@@ -0,0 +1,358 @@
+/* This file contains 16-bit versions of some of the functions found in
+ libgcc2.c. Really libgcc ought to be moved out of the gcc directory
+ and into its own top level directory, and then split up into multiple
+ files. On this glorious day maybe this code can be integrated into
+ it too. */
+
+/* Copyright (C) 2005, 2008, 2009, 2010, 2011 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 3, 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.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "libgcc_tm.h"
+
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
+#ifndef MIN_UNITS_PER_WORD
+#define MIN_UNITS_PER_WORD UNITS_PER_WORD
+#endif
+
+#ifndef LIBGCC2_UNITS_PER_WORD
+# if MIN_UNITS_PER_WORD > 4
+# define LIBGCC2_UNITS_PER_WORD 8
+# elif (MIN_UNITS_PER_WORD > 2 \
+ || (MIN_UNITS_PER_WORD > 1 && LONG_LONG_TYPE_SIZE > 32))
+# define LIBGCC2_UNITS_PER_WORD 4
+# else
+# define LIBGCC2_UNITS_PER_WORD MIN_UNITS_PER_WORD
+# endif
+#endif
+
+#define word_type Wtype
+
+#include "libgcc2.h"
+#undef int
+
+/* These prototypes would normally live in libgcc2.h, but this can
+ only happen once the code below is integrated into libgcc2.c. */
+
+extern USItype udivmodsi4 (USItype, USItype, word_type);
+extern SItype __divsi3 (SItype, SItype);
+extern SItype __modsi3 (SItype, SItype);
+extern SItype __udivsi3 (SItype, SItype);
+extern SItype __umodsi3 (SItype, SItype);
+extern SItype __ashlsi3 (SItype, SItype);
+extern SItype __ashrsi3 (SItype, SItype);
+extern USItype __lshrsi3 (USItype, USItype);
+extern int __popcounthi2 (UHWtype);
+extern int __parityhi2 (UHWtype);
+extern int __clzhi2 (UHWtype);
+extern int __ctzhi2 (UHWtype);
+
+
+#ifdef XSTORMY16_UDIVMODSI4
+USItype
+udivmodsi4 (USItype num, USItype den, word_type modwanted)
+{
+ USItype bit = 1;
+ USItype res = 0;
+
+ while (den < num && bit && !(den & (1L << 31)))
+ {
+ den <<= 1;
+ bit <<= 1;
+ }
+ while (bit)
+ {
+ if (num >= den)
+ {
+ num -= den;
+ res |= bit;
+ }
+ bit >>= 1;
+ den >>= 1;
+ }
+
+ if (modwanted)
+ return num;
+ return res;
+}
+#endif
+
+#ifdef XSTORMY16_DIVSI3
+SItype
+__divsi3 (SItype a, SItype b)
+{
+ word_type neg = 0;
+ SItype res;
+
+ if (a < 0)
+ {
+ a = -a;
+ neg = !neg;
+ }
+
+ if (b < 0)
+ {
+ b = -b;
+ neg = !neg;
+ }
+
+ res = udivmodsi4 (a, b, 0);
+
+ if (neg)
+ res = -res;
+
+ return res;
+}
+#endif
+
+#ifdef XSTORMY16_MODSI3
+SItype
+__modsi3 (SItype a, SItype b)
+{
+ word_type neg = 0;
+ SItype res;
+
+ if (a < 0)
+ {
+ a = -a;
+ neg = 1;
+ }
+
+ if (b < 0)
+ b = -b;
+
+ res = udivmodsi4 (a, b, 1);
+
+ if (neg)
+ res = -res;
+
+ return res;
+}
+#endif
+
+#ifdef XSTORMY16_UDIVSI3
+SItype
+__udivsi3 (SItype a, SItype b)
+{
+ return udivmodsi4 (a, b, 0);
+}
+#endif
+
+#ifdef XSTORMY16_UMODSI3
+SItype
+__umodsi3 (SItype a, SItype b)
+{
+ return udivmodsi4 (a, b, 1);
+}
+#endif
+
+#ifdef XSTORMY16_ASHLSI3
+SItype
+__ashlsi3 (SItype a, SItype b)
+{
+ word_type i;
+
+ if (b & 16)
+ a <<= 16;
+ if (b & 8)
+ a <<= 8;
+ for (i = (b & 0x7); i > 0; --i)
+ a <<= 1;
+ return a;
+}
+#endif
+
+#ifdef XSTORMY16_ASHRSI3
+SItype
+__ashrsi3 (SItype a, SItype b)
+{
+ word_type i;
+
+ if (b & 16)
+ a >>= 16;
+ if (b & 8)
+ a >>= 8;
+ for (i = (b & 0x7); i > 0; --i)
+ a >>= 1;
+ return a;
+}
+#endif
+
+#ifdef XSTORMY16_LSHRSI3
+USItype
+__lshrsi3 (USItype a, USItype b)
+{
+ word_type i;
+
+ if (b & 16)
+ a >>= 16;
+ if (b & 8)
+ a >>= 8;
+ for (i = (b & 0x7); i > 0; --i)
+ a >>= 1;
+ return a;
+}
+#endif
+
+#ifdef XSTORMY16_POPCOUNTHI2
+/* Returns the number of set bits in X.
+ FIXME: The return type really should be "unsigned int"
+ but this is not how the builtin is prototyped. */
+int
+__popcounthi2 (UHWtype x)
+{
+ int ret;
+
+ ret = __popcount_tab [x & 0xff];
+ ret += __popcount_tab [(x >> 8) & 0xff];
+
+ return ret;
+}
+#endif
+
+#ifdef XSTORMY16_PARITYHI2
+/* Returns the number of set bits in X, modulo 2.
+ FIXME: The return type really should be "unsigned int"
+ but this is not how the builtin is prototyped. */
+
+int
+__parityhi2 (UHWtype x)
+{
+ x ^= x >> 8;
+ x ^= x >> 4;
+ x &= 0xf;
+ return (0x6996 >> x) & 1;
+}
+#endif
+
+#ifdef XSTORMY16_CLZHI2
+/* Returns the number of zero-bits from the most significant bit to the
+ first nonzero bit in X. Returns 16 for X == 0. Implemented as a
+ simple for loop in order to save space by removing the need for
+ the __clz_tab array.
+ FIXME: The return type really should be "unsigned int" but this is
+ not how the builtin is prototyped. */
+#undef unsigned
+int
+__clzhi2 (UHWtype x)
+{
+ unsigned int i;
+ unsigned int c;
+ unsigned int value = x;
+
+ for (c = 0, i = 1 << 15; i; i >>= 1, c++)
+ if (i & value)
+ break;
+ return c;
+}
+#endif
+
+#ifdef XSTORMY16_CTZHI2
+/* Returns the number of trailing zero bits in X.
+ FIXME: The return type really should be "signed int" since
+ ctz(0) returns -1, but this is not how the builtin is prototyped. */
+
+int
+__ctzhi2 (UHWtype x)
+{
+ /* This is cunning. It converts X into a number with only the one bit
+ set, the bit that was the least significant bit in X. From this we
+ can use the count_leading_zeros to compute the number of trailing
+ bits. */
+ x &= - x;
+
+ return 15 - __builtin_clz (x);
+}
+#endif
+
+#ifdef XSTORMY16_FFSHI2
+/* Returns one plus the index of the least significant 1-bit of X,
+ or if X is zero, returns zero. FIXME: The return type really
+ should be "unsigned int" but this is not how the builtin is
+ prototyped. */
+
+int
+__ffshi2 (UHWtype u)
+{
+ UHWtype count;
+
+ if (u == 0)
+ return 0;
+
+ return 16 - __builtin_clz (u & - u);
+}
+#endif
+
+#ifdef XSTORMY16_UCMPSI2
+/* Performs an unsigned comparison of two 32-bit values: A and B.
+ If A is less than B, then 0 is returned. If A is greater than B,
+ then 2 is returned. Otherwise A and B are equal and 1 is returned. */
+
+word_type
+__ucmpsi2 (USItype a, USItype b)
+{
+ word_type hi_a = (a >> 16);
+ word_type hi_b = (b >> 16);
+
+ if (hi_a == hi_b)
+ {
+ word_type low_a = (a & 0xffff);
+ word_type low_b = (b & 0xffff);
+
+ return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1);
+ }
+
+ return hi_a < hi_b ? 0 : 2;
+}
+#endif
+
+#ifdef XSTORMY16_CMPSI2
+/* Performs an signed comparison of two 32-bit values: A and B.
+ If A is less than B, then 0 is returned. If A is greater than B,
+ then 2 is returned. Otherwise A and B are equal and 1 is returned. */
+
+word_type
+__cmpsi2 (SItype a, SItype b)
+{
+ word_type hi_a = (a >> 16);
+ word_type hi_b = (b >> 16);
+
+ if (hi_a == hi_b)
+ {
+ word_type low_a = (a & 0xffff);
+ word_type low_b = (b & 0xffff);
+
+ return low_a < low_b ? 0 : (low_a > low_b ? 2 : 1);
+ }
+
+ return hi_a < hi_b ? 0 : 2;
+}
+#endif
diff --git a/libgcc/config/stormy16/lshrsi3.c b/libgcc/config/stormy16/lshrsi3.c
new file mode 100644
index 00000000000..13903d3d24a
--- /dev/null
+++ b/libgcc/config/stormy16/lshrsi3.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_LSHRSI3
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/modsi3.c b/libgcc/config/stormy16/modsi3.c
new file mode 100644
index 00000000000..c63e8906824
--- /dev/null
+++ b/libgcc/config/stormy16/modsi3.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_MODSI3
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/parityhi2.c b/libgcc/config/stormy16/parityhi2.c
new file mode 100644
index 00000000000..4be7fbf3e14
--- /dev/null
+++ b/libgcc/config/stormy16/parityhi2.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_PARITYHI2
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/popcounthi2.c b/libgcc/config/stormy16/popcounthi2.c
new file mode 100644
index 00000000000..30bf0950d3d
--- /dev/null
+++ b/libgcc/config/stormy16/popcounthi2.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_POPCOUNTHI2
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/t-stormy16 b/libgcc/config/stormy16/t-stormy16
new file mode 100644
index 00000000000..8726a3dc4fc
--- /dev/null
+++ b/libgcc/config/stormy16/t-stormy16
@@ -0,0 +1,39 @@
+# -*- makefile -*-
+#
+# Copyright (C) 2001, 2004, 2010, 2011 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# SImode arithmetic and logical routines, HImode bit counting routines.
+LIB2ADD = \
+ $(srcdir)/config/stormy16/udivmodsi4.c \
+ $(srcdir)/config/stormy16/divsi3.c \
+ $(srcdir)/config/stormy16/modsi3.c \
+ $(srcdir)/config/stormy16/udivsi3.c \
+ $(srcdir)/config/stormy16/umodsi3.c \
+ $(srcdir)/config/stormy16/ashlsi3.c \
+ $(srcdir)/config/stormy16/ashrsi3.c \
+ $(srcdir)/config/stormy16/lshrsi3.c \
+ $(srcdir)/config/stormy16/popcounthi2.c \
+ $(srcdir)/config/stormy16/parityhi2.c \
+ $(srcdir)/config/stormy16/clzhi2.c \
+ $(srcdir)/config/stormy16/ctzhi2.c \
+ $(srcdir)/config/stormy16/ffshi2.c \
+ $(srcdir)/config/stormy16/cmpsi2.c \
+ $(srcdir)/config/stormy16/ucmpsi2.c
+
+HOST_LIBGCC2_CFLAGS = -O2
diff --git a/libgcc/config/stormy16/ucmpsi2.c b/libgcc/config/stormy16/ucmpsi2.c
new file mode 100644
index 00000000000..ee327b1da15
--- /dev/null
+++ b/libgcc/config/stormy16/ucmpsi2.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_UCMPSI2
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/udivmodsi4.c b/libgcc/config/stormy16/udivmodsi4.c
new file mode 100644
index 00000000000..5fdd0f9189e
--- /dev/null
+++ b/libgcc/config/stormy16/udivmodsi4.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_UDIVMODSI4
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/udivsi3.c b/libgcc/config/stormy16/udivsi3.c
new file mode 100644
index 00000000000..ad12bd86a58
--- /dev/null
+++ b/libgcc/config/stormy16/udivsi3.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_UDIVSI3
+#include "lib2funcs.c"
diff --git a/libgcc/config/stormy16/umodsi3.c b/libgcc/config/stormy16/umodsi3.c
new file mode 100644
index 00000000000..eeec67f56c0
--- /dev/null
+++ b/libgcc/config/stormy16/umodsi3.c
@@ -0,0 +1,2 @@
+#define XSTORMY16_UMODSI3
+#include "lib2funcs.c"
diff --git a/libgcc/config/t-crtin b/libgcc/config/t-crtin
deleted file mode 100644
index b30e0d52e2f..00000000000
--- a/libgcc/config/t-crtin
+++ /dev/null
@@ -1,4 +0,0 @@
-crti.o: $(srcdir)/config/$(cpu_type)/sol2-ci.S
- $(crt_compile) -c $<
-crtn.o: $(srcdir)/config/$(cpu_type)/sol2-cn.S
- $(crt_compile) -c $<
diff --git a/libgcc/config/t-crtstuff-pic b/libgcc/config/t-crtstuff-pic
new file mode 100644
index 00000000000..4cda4c9bffb
--- /dev/null
+++ b/libgcc/config/t-crtstuff-pic
@@ -0,0 +1,2 @@
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) $(PICFLAG)
diff --git a/libgcc/config/t-darwin b/libgcc/config/t-darwin
index 311b7e2679f..e32127e9d8a 100644
--- a/libgcc/config/t-darwin
+++ b/libgcc/config/t-darwin
@@ -3,6 +3,12 @@ crt3.o: $(srcdir)/config/darwin-crt3.c
$(crt_compile) \
-fno-tree-dominator-opts $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) -c $<
+# -pipe because there's an assembler bug, 4077127, which causes
+# it to not properly process the first # directive, causing temporary
+# file names to appear in stabs, causing the bootstrap to fail. Using -pipe
+# works around this by not having any temporary file names.
+HOST_LIBGCC2_CFLAGS += -pipe
+
# Use unwind-dw2-fde-darwin
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/config/unwind-dw2-fde-darwin.c \
$(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/t-freebsd-thread b/libgcc/config/t-freebsd-thread
new file mode 100644
index 00000000000..2948dc1a44c
--- /dev/null
+++ b/libgcc/config/t-freebsd-thread
@@ -0,0 +1,2 @@
+# This is currently needed to compile libgcc2 for threads support
+HOST_LIBGCC2_CFLAGS += -pthread
diff --git a/libgcc/config/t-libgcc-pic b/libgcc/config/t-libgcc-pic
new file mode 100644
index 00000000000..0eea16ebc39
--- /dev/null
+++ b/libgcc/config/t-libgcc-pic
@@ -0,0 +1,2 @@
+# Compile libgcc2.a with pic.
+HOST_LIBGCC2_CFLAGS += $(PICFLAG)
diff --git a/libgcc/config/t-libunwind b/libgcc/config/t-libunwind
index 1c7a898675f..5244928da3c 100644
--- a/libgcc/config/t-libunwind
+++ b/libgcc/config/t-libunwind
@@ -1,3 +1,12 @@
+# Use the system libunwind library.
+
+HOST_LIBGCC2_CFLAGS += -DUSE_GAS_SYMVER
+
LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
$(srcdir)/unwind-compat.c $(srcdir)/unwind-dw2-fde-compat.c
LIB2ADDEHSTATIC = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+
+# Override the default value from t-slibgcc-elf-ver and mention -lunwind
+# so that the resulting libgcc_s.so has the necessary DT_NEEDED entry for
+# libunwind.
+SHLIB_LC = -lunwind -lc
diff --git a/libgcc/config/t-linux b/libgcc/config/t-linux
new file mode 100644
index 00000000000..d1bdac4f32d
--- /dev/null
+++ b/libgcc/config/t-linux
@@ -0,0 +1,3 @@
+# Override t-slibgcc-elf-ver to export some libgcc symbols with
+# the symbol versions that glibc used.
+SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
diff --git a/libgcc/config/t-openbsd-thread b/libgcc/config/t-openbsd-thread
new file mode 100644
index 00000000000..17d17edf936
--- /dev/null
+++ b/libgcc/config/t-openbsd-thread
@@ -0,0 +1,3 @@
+# This is currently needed to compile libgcc2 for threads support
+HOST_LIBGCC2_CFLAGS=-pthread
+
diff --git a/libgcc/config/t-slibgcc b/libgcc/config/t-slibgcc
index 0b5cc4bfc50..3727244c424 100644
--- a/libgcc/config/t-slibgcc
+++ b/libgcc/config/t-slibgcc
@@ -43,9 +43,12 @@ SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
else true; fi && \
mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \
$(SHLIB_MAKE_SOLINK)
+
+INSTALL_SHLIB = $(INSTALL_DATA)
+
SHLIB_INSTALL = \
$(mkinstalldirs) $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
- $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_SONAME) \
+ $(INSTALL_SHLIB) $(SHLIB_DIR)/$(SHLIB_SONAME) \
$(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SONAME); \
rm -f $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
$(SHLIB_INSTALL_SOLINK)
diff --git a/libgcc/config/t-slibgcc-darwin b/libgcc/config/t-slibgcc-darwin
index bb6569a87d9..9970d003436 100644
--- a/libgcc/config/t-slibgcc-darwin
+++ b/libgcc/config/t-slibgcc-darwin
@@ -22,9 +22,10 @@ SHLIB_LINK = $(CC) $(LIBGCC2_CFLAGS) -dynamiclib -nodefaultlibs \
$(SHLIB_VERSTRING) \
@multilib_flags@ $(SHLIB_OBJS) $(SHLIB_LC)
-SHLIB_MKMAP = $(gcc_srcdir)/mkmap-flat.awk
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
SHLIB_MKMAP_OPTS = -v leading_underscore=1
-SHLIB_MAPFILES += libgcc-std.ver $(gcc_srcdir)/libgcc-libsystem.ver
+SHLIB_MAPFILES = libgcc-std.ver $(srcdir)/config/libgcc-libsystem.ver
+SHLIB_VERPFX = $(srcdir)/config/$(cpu_type)/libgcc-darwin
# we're only going to build the stubs if the target slib is /usr/lib
# there is no other case in which they're useful in a live system.
diff --git a/libgcc/config/t-slibgcc-elf-ver b/libgcc/config/t-slibgcc-elf-ver
index 2616d31cae5..4a00edc9663 100644
--- a/libgcc/config/t-slibgcc-elf-ver
+++ b/libgcc/config/t-slibgcc-elf-ver
@@ -1,4 +1,4 @@
# Build a shared libgcc library for ELF with symbol versioning.
-SHLIB_MKMAP = $(gcc_srcdir)/mkmap-symver.awk
+SHLIB_MKMAP = $(srcdir)/mkmap-symver.awk
SHLIB_MAPFILES = libgcc-std.ver
diff --git a/libgcc/config/t-slibgcc-gld-nover b/libgcc/config/t-slibgcc-gld-nover
new file mode 100644
index 00000000000..e9b78ea9410
--- /dev/null
+++ b/libgcc/config/t-slibgcc-gld-nover
@@ -0,0 +1,3 @@
+# Build a shared libgcc library for ELF with the GNU linker.
+
+SHLIB_LDFLAGS = -Wl,--soname=$(SHLIB_SONAME)
diff --git a/libgcc/config/t-slibgcc-hpux b/libgcc/config/t-slibgcc-hpux
new file mode 100644
index 00000000000..866457fe9ae
--- /dev/null
+++ b/libgcc/config/t-slibgcc-hpux
@@ -0,0 +1,7 @@
+# Build a shared libgcc library with the HP-UX linker.
+
+SHLIB_LDFLAGS = -Wl,+h,$(SHLIB_SONAME)
+
+INSTALL_SHLIB = $(INSTALL_DATA) -m 555
+
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
diff --git a/libgcc/config/t-slibgcc-libgcc b/libgcc/config/t-slibgcc-libgcc
new file mode 100644
index 00000000000..ec36b2727ae
--- /dev/null
+++ b/libgcc/config/t-slibgcc-libgcc
@@ -0,0 +1,32 @@
+# Copyright (C) 2009, 2011 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Instead of creating $(SHLIB_SOLINK) symlink create a GNU ld
+# linker script which sources in both $(SHLIB_SONAME) and libgcc.a.
+# This is needed on targets where libgcc.a contains routines that aren't in
+# $(SHLIB_SONAME) and are needed for shared libraries.
+
+SHLIB_MAKE_SOLINK = \
+ (echo "/* GNU ld script"; \
+ echo " Use the shared library, but some functions are only in"; \
+ echo " the static library. */"; \
+ echo "GROUP ( $(SHLIB_SONAME) libgcc.a )" \
+ ) > $(SHLIB_DIR)/$(SHLIB_SOLINK)
+SHLIB_INSTALL_SOLINK = \
+ $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_SOLINK) \
+ $(DESTDIR)$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
diff --git a/gcc/config/t-slibgcc-nolc-override b/libgcc/config/t-slibgcc-nolc-override
index 959d2cc2a1f..959d2cc2a1f 100644
--- a/gcc/config/t-slibgcc-nolc-override
+++ b/libgcc/config/t-slibgcc-nolc-override
diff --git a/libgcc/config/t-slibgcc-vms b/libgcc/config/t-slibgcc-vms
new file mode 100644
index 00000000000..d01c34341c8
--- /dev/null
+++ b/libgcc/config/t-slibgcc-vms
@@ -0,0 +1,28 @@
+shlib_version:=$(shell $(CC) --version 2>&1 | \
+ sed -n 's/^.*(GCC).* \([0-9]*\.[0-9.]*\).*$/\1/p' | \
+ sed -e 's/\./,/' -e 's/\.//g')
+SHLIB_EXT = .exe
+SHLIB_OBJS = @shlib_objs@
+SHLIB_NAME = @shlib_base_name@.exe
+SHLIB_MULTILIB =
+SHLIB_INSTALL = $(INSTALL_DATA) $(SHLIB_NAME) $(DESTDIR)$(libsubdir)/$(SHLIB_NAME)
+SHLIB_SYMVEC = \
+ grep -F -e "\$$BSS\$$" -e "\$$DATA\$$" -e " sdata " -e " data.rel " -e " data.rel.ro " -e " sbss " \
+ -e "\$$LINK\$$" -e "\$$READONLY\$$" | \
+ sed -e "s/.*\$$LINK\$$ \(.*\)/SYMBOL_VECTOR=(\1=PROCEDURE)/" \
+ -e "s/.*\$$DATA\$$ \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
+ -e "s/.* sbss \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
+ -e "s/.* sdata \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
+ -e "s/.* data.rel \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
+ -e "s/.* data.rel.ro \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
+ -e "s/.*\$$BSS\$$ \(.*\)/SYMBOL_VECTOR=(\1=DATA)/" \
+ -e "s/.*\$$READONLY\$$ \(.*\)/SYMBOL_VECTOR=(\1=DATA)/"
+SHLIB_LINK = \
+ echo "case_sensitive=yes" > SYMVEC_$$$$.opt; \
+ objdump --syms $(SHLIB_OBJS) | \
+ $(SHLIB_SYMVEC) >> SYMVEC_$$$$.opt ; \
+ echo "case_sensitive=NO" >> SYMVEC_$$$$.opt; \
+ $(CC) $(LIBGCC2_CFLAGS) -nodefaultlibs \
+ -shared --for-linker=/noinform -o $(SHLIB_NAME) $(SHLIB_OBJS) \
+ --for-linker=SYMVEC_$$$$.opt \
+ --for-linker=gsmatch=equal,$(shlib_version)
diff --git a/libgcc/config/t-sol2 b/libgcc/config/t-sol2
index bfb8f3b5cc2..09bbdf646ec 100644
--- a/libgcc/config/t-sol2
+++ b/libgcc/config/t-sol2
@@ -20,10 +20,14 @@
gmon.o: $(srcdir)/config/gmon-sol2.c
$(gcc_compile) -c $<
+CUSTOM_CRTIN = yes
+
# Assemble startup files.
crt1.o: $(srcdir)/config/$(cpu_type)/sol2-c1.S
$(crt_compile) -c $<
gcrt1.o: $(srcdir)/config/$(cpu_type)/sol2-c1.S
$(crt_compile) -c -DGCRT1 $<
-
-HOST_LIBGCC2_CFLAGS = -fPIC
+crti.o: $(srcdir)/config/$(cpu_type)/sol2-ci.S
+ $(crt_compile) -c $<
+crtn.o: $(srcdir)/config/$(cpu_type)/sol2-cn.S
+ $(crt_compile) -c $<
diff --git a/libgcc/config/t-vxworks b/libgcc/config/t-vxworks
new file mode 100644
index 00000000000..ab8f014dd5d
--- /dev/null
+++ b/libgcc/config/t-vxworks
@@ -0,0 +1,18 @@
+# FIXME: Need to specify the next two?
+# No special flags needed for libgcc.a
+HOST_LIBGCC2_CFLAGS =
+
+# Don't build libgcc.a with debug info
+LIBGCC2_DEBUG_CFLAGS =
+
+# Extra libgcc2 modules used by gthr-vxworks.h functions
+LIB2ADD = $(srcdir)/config/vxlib.c $(srcdir)/config/vxlib-tls.c
+
+# This ensures that the correct target headers are used; some
+# VxWorks system headers have names that collide with GCC's
+# internal (host) headers, e.g. regs.h.
+LIBGCC2_INCLUDES = -nostdinc -I \
+ `case "/$$(MULTIDIR)" in \
+ */mrtp*) echo $(WIND_USR)/h ;; \
+ *) echo $(WIND_BASE)/target/h ;; \
+ esac`
diff --git a/gcc/config/v850/lib1funcs.asm b/libgcc/config/v850/lib1funcs.S
index 04e9b1e0ad4..04e9b1e0ad4 100644
--- a/gcc/config/v850/lib1funcs.asm
+++ b/libgcc/config/v850/lib1funcs.S
diff --git a/libgcc/config/v850/t-v850 b/libgcc/config/v850/t-v850
new file mode 100644
index 00000000000..b61703ace09
--- /dev/null
+++ b/libgcc/config/v850/t-v850
@@ -0,0 +1,60 @@
+LIB1ASMSRC = v850/lib1funcs.S
+LIB1ASMFUNCS = _mulsi3 \
+ _divsi3 \
+ _udivsi3 \
+ _modsi3 \
+ _umodsi3 \
+ _save_2 \
+ _save_20 \
+ _save_21 \
+ _save_22 \
+ _save_23 \
+ _save_24 \
+ _save_25 \
+ _save_26 \
+ _save_27 \
+ _save_28 \
+ _save_29 \
+ _save_2c \
+ _save_20c \
+ _save_21c \
+ _save_22c \
+ _save_23c \
+ _save_24c \
+ _save_25c \
+ _save_26c \
+ _save_27c \
+ _save_28c \
+ _save_29c \
+ _save_31c \
+ _save_interrupt \
+ _save_all_interrupt \
+ _callt_save_20 \
+ _callt_save_21 \
+ _callt_save_22 \
+ _callt_save_23 \
+ _callt_save_24 \
+ _callt_save_25 \
+ _callt_save_26 \
+ _callt_save_27 \
+ _callt_save_28 \
+ _callt_save_29 \
+ _callt_save_20c \
+ _callt_save_21c \
+ _callt_save_22c \
+ _callt_save_23c \
+ _callt_save_24c \
+ _callt_save_25c \
+ _callt_save_26c \
+ _callt_save_27c \
+ _callt_save_28c \
+ _callt_save_29c \
+ _callt_save_31c \
+ _callt_save_interrupt \
+ _callt_save_all_interrupt \
+ _callt_save_r2_r29 \
+ _callt_save_r2_r31 \
+ _negdi2 \
+ _cmpdi2 \
+ _ucmpdi2 \
+ _muldi3
diff --git a/gcc/config/vax/lib1funcs.asm b/libgcc/config/vax/lib1funcs.S
index 1d57b56dad9..1d57b56dad9 100644
--- a/gcc/config/vax/lib1funcs.asm
+++ b/libgcc/config/vax/lib1funcs.S
diff --git a/libgcc/config/vax/t-linux b/libgcc/config/vax/t-linux
new file mode 100644
index 00000000000..17929c8717c
--- /dev/null
+++ b/libgcc/config/vax/t-linux
@@ -0,0 +1,2 @@
+LIB1ASMSRC = vax/lib1funcs.S
+LIB1ASMFUNCS = _udivsi3 _umodsi3
diff --git a/libgcc/config/vms/t-vms b/libgcc/config/vms/t-vms
new file mode 100644
index 00000000000..93d8255dcb0
--- /dev/null
+++ b/libgcc/config/vms/t-vms
@@ -0,0 +1,6 @@
+# Assemble startup files.
+vcrt0.o: $(srcdir)/config/vms/vms-ucrt0.c
+ $(gcc_compile) -c $<
+
+pcrt0.o: $(srcdir)/config/vms/vms-ucrt0.c
+ $(gcc_compile) -c -DCRT0_POSIX_EXIT $<
diff --git a/gcc/config/vms/vms-ucrt0.c b/libgcc/config/vms/vms-ucrt0.c
index 344b59520e0..344b59520e0 100644
--- a/gcc/config/vms/vms-ucrt0.c
+++ b/libgcc/config/vms/vms-ucrt0.c
diff --git a/gcc/config/vxlib-tls.c b/libgcc/config/vxlib-tls.c
index c4696768f0f..c4696768f0f 100644
--- a/gcc/config/vxlib-tls.c
+++ b/libgcc/config/vxlib-tls.c
diff --git a/gcc/config/vxlib.c b/libgcc/config/vxlib.c
index 0ff996cfced..0ff996cfced 100644
--- a/gcc/config/vxlib.c
+++ b/libgcc/config/vxlib.c
diff --git a/gcc/config/xtensa/crti.asm b/libgcc/config/xtensa/crti.S
index cbe91b0e748..cbe91b0e748 100644
--- a/gcc/config/xtensa/crti.asm
+++ b/libgcc/config/xtensa/crti.S
diff --git a/gcc/config/xtensa/crtn.asm b/libgcc/config/xtensa/crtn.S
index 413cfa0ac10..413cfa0ac10 100644
--- a/gcc/config/xtensa/crtn.asm
+++ b/libgcc/config/xtensa/crtn.S
diff --git a/gcc/config/xtensa/ieee754-df.S b/libgcc/config/xtensa/ieee754-df.S
index 9b46889bdc2..9b46889bdc2 100644
--- a/gcc/config/xtensa/ieee754-df.S
+++ b/libgcc/config/xtensa/ieee754-df.S
diff --git a/gcc/config/xtensa/ieee754-sf.S b/libgcc/config/xtensa/ieee754-sf.S
index d75be0e5ae5..d75be0e5ae5 100644
--- a/gcc/config/xtensa/ieee754-sf.S
+++ b/libgcc/config/xtensa/ieee754-sf.S
diff --git a/gcc/config/xtensa/lib1funcs.asm b/libgcc/config/xtensa/lib1funcs.S
index 071b9171177..071b9171177 100644
--- a/gcc/config/xtensa/lib1funcs.asm
+++ b/libgcc/config/xtensa/lib1funcs.S
diff --git a/gcc/config/xtensa/lib2funcs.S b/libgcc/config/xtensa/lib2funcs.S
index 65134e24ccf..65134e24ccf 100644
--- a/gcc/config/xtensa/lib2funcs.S
+++ b/libgcc/config/xtensa/lib2funcs.S
diff --git a/gcc/config/xtensa/libgcc-xtensa.ver b/libgcc/config/xtensa/libgcc-glibc.ver
index 43e7d4fc7c7..43e7d4fc7c7 100644
--- a/gcc/config/xtensa/libgcc-xtensa.ver
+++ b/libgcc/config/xtensa/libgcc-glibc.ver
diff --git a/libgcc/config/xtensa/t-elf b/libgcc/config/xtensa/t-elf
new file mode 100644
index 00000000000..59d51210b95
--- /dev/null
+++ b/libgcc/config/xtensa/t-elf
@@ -0,0 +1,5 @@
+# Build CRT files and libgcc with the "longcalls" option
+CRTSTUFF_T_CFLAGS += -mlongcalls
+CRTSTUFF_T_CFLAGS_S += -mlongcalls
+
+HOST_LIBGCC2_CFLAGS += -mlongcalls
diff --git a/libgcc/config/xtensa/t-linux b/libgcc/config/xtensa/t-linux
new file mode 100644
index 00000000000..6f4ae893486
--- /dev/null
+++ b/libgcc/config/xtensa/t-linux
@@ -0,0 +1 @@
+SHLIB_MAPFILES += $(srcdir)/config/xtensa/libgcc-glibc.ver
diff --git a/libgcc/config/xtensa/t-xtensa b/libgcc/config/xtensa/t-xtensa
index 7d9e9db0487..27399e67fa0 100644
--- a/libgcc/config/xtensa/t-xtensa
+++ b/libgcc/config/xtensa/t-xtensa
@@ -1,2 +1,16 @@
+LIB1ASMSRC = xtensa/lib1funcs.S
+LIB1ASMFUNCS = _mulsi3 _divsi3 _modsi3 _udivsi3 _umodsi3 \
+ _umulsidi3 _clz _clzsi2 _ctzsi2 _ffssi2 \
+ _ashldi3 _ashrdi3 _lshrdi3 \
+ _negsf2 _addsubsf3 _mulsf3 _divsf3 _cmpsf2 _fixsfsi _fixsfdi \
+ _fixunssfsi _fixunssfdi _floatsisf _floatunsisf \
+ _floatdisf _floatundisf \
+ _negdf2 _addsubdf3 _muldf3 _divdf3 _cmpdf2 _fixdfsi _fixdfdi \
+ _fixunsdfsi _fixunsdfdi _floatsidf _floatunsidf \
+ _floatdidf _floatundidf \
+ _truncdfsf2 _extendsfdf2
+
+LIB2ADD = $(srcdir)/config/xtensa/lib2funcs.S
+
LIB2ADDEH = $(srcdir)/config/xtensa/unwind-dw2-xtensa.c \
$(srcdir)/unwind-dw2-fde.c $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
diff --git a/libgcc/config/xtensa/unwind-dw2-xtensa.c b/libgcc/config/xtensa/unwind-dw2-xtensa.c
index 54daf7637ce..2ded579929f 100644
--- a/libgcc/config/xtensa/unwind-dw2-xtensa.c
+++ b/libgcc/config/xtensa/unwind-dw2-xtensa.c
@@ -28,6 +28,7 @@
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "dwarf2.h"
#include "unwind.h"
#ifdef __USING_SJLJ_EXCEPTIONS__
diff --git a/libgcc/configure b/libgcc/configure
index 80bb61c80af..0d91645ed67 100644
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -593,6 +593,8 @@ LIBOBJS
asm_hidden_op
extra_parts
cpu_type
+tm_defines
+tm_file
tmake_file
sfp_machine_header
set_use_emutls
@@ -627,6 +629,13 @@ build_subdir
build_libsubdir
target_noncanonical
host_noncanonical
+AWK
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+MAINT
+slibdir
+PICFLAG
host_os
host_vendor
host_cpu
@@ -635,12 +644,6 @@ build_os
build_vendor
build_cpu
build
-AWK
-INSTALL_DATA
-INSTALL_SCRIPT
-INSTALL_PROGRAM
-MAINT
-slibdir
enable_shared
libgcc_topdir
target_alias
@@ -694,6 +697,7 @@ enable_maintainer_mode
with_build_libsubdir
enable_decimal_float
with_system_libunwind
+enable_sjlj_exceptions
enable_tls
'
ac_precious_vars='build_alias
@@ -1328,6 +1332,8 @@ Optional Features:
enable decimal float extension to C. Selecting 'bid'
or 'dpd' choses which decimal floating point format
to use
+ --enable-sjlj-exceptions
+ force use of builtin_setjmp for exceptions
--enable-tls Use thread-local storage [default=yes]
Optional Packages:
@@ -2194,6 +2200,158 @@ fi
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+
+
+
+case "${host}" in
+ # PIC is the default on some targets or must not be used.
+ *-*-darwin*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ PICFLAG=-fno-common
+ ;;
+ alpha*-dec-osf5*)
+ # PIC is the default.
+ ;;
+ hppa*64*-*-hpux*)
+ # PIC is the default for 64-bit PA HP-UX.
+ ;;
+ i[34567]86-*-cygwin* | i[34567]86-*-mingw* | x86_64-*-mingw*)
+ ;;
+ i[34567]86-*-interix3*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ i[34567]86-*-nto-qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ PICFLAG='-fPIC -shared'
+ ;;
+ i[34567]86-pc-msdosdjgpp*)
+ # DJGPP does not support shared libraries at all.
+ ;;
+ ia64*-*-hpux*)
+ # On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ PICFLAG=-fPIC
+ ;;
+ mips-sgi-irix6*)
+ # PIC is the default.
+ ;;
+ rs6000-ibm-aix* | powerpc-ibm-aix*)
+ # All AIX code is PIC.
+ ;;
+
+ # Some targets support both -fPIC and -fpic, but prefer the latter.
+ # FIXME: Why?
+ i[34567]86-*-* | x86_64-*-*)
+ PICFLAG=-fpic
+ ;;
+ m68k-*-*)
+ PICFLAG=-fpic
+ ;;
+ s390*-*-*)
+ PICFLAG=-fpic
+ ;;
+ # FIXME: Override -fPIC default in libgcc only?
+ sh-*-linux* | sh[2346lbe]*-*-linux*)
+ PICFLAG=-fpic
+ ;;
+ # FIXME: Simplify to sh*-*-netbsd*?
+ sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
+ sh64-*-netbsd* | sh64l*-*-netbsd*)
+ PICFLAG=-fpic
+ ;;
+ # Default to -fPIC unless specified otherwise.
+ *)
+ PICFLAG=-fPIC
+ ;;
+esac
+
+# If the user explicitly uses -fpic/-fPIC, keep that.
+case "${CFLAGS}" in
+ *-fpic*)
+ PICFLAG=-fpic
+ ;;
+ *-fPIC*)
+ PICFLAG=-fPIC
+ ;;
+esac
+
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for --enable-version-specific-runtime-libs" >&5
$as_echo_n "checking for --enable-version-specific-runtime-libs... " >&6; }
# Check whether --enable-version-specific-runtime-libs was given.
@@ -2382,76 +2540,6 @@ case ${AWK} in
"") as_fn_error "can't build without awk, bailing out" "$LINENO" 5 ;;
esac
-# Make sure we can run config.sub.
-$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
- as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
-$as_echo_n "checking build system type... " >&6; }
-if test "${ac_cv_build+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- ac_build_alias=$build_alias
-test "x$ac_build_alias" = x &&
- ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
-test "x$ac_build_alias" = x &&
- as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5
-ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
- as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
-$as_echo "$ac_cv_build" >&6; }
-case $ac_cv_build in
-*-*-*) ;;
-*) as_fn_error "invalid value of canonical build" "$LINENO" 5;;
-esac
-build=$ac_cv_build
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_build
-shift
-build_cpu=$1
-build_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-build_os=$*
-IFS=$ac_save_IFS
-case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
-$as_echo_n "checking host system type... " >&6; }
-if test "${ac_cv_host+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- if test "x$host_alias" = x; then
- ac_cv_host=$ac_cv_build
-else
- ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
- as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
-$as_echo "$ac_cv_host" >&6; }
-case $ac_cv_host in
-*-*-*) ;;
-*) as_fn_error "invalid value of canonical host" "$LINENO" 5;;
-esac
-host=$ac_cv_host
-ac_save_IFS=$IFS; IFS='-'
-set x $ac_cv_host
-shift
-host_cpu=$1
-host_vendor=$2
-shift; shift
-# Remember, the first character of IFS is used to create $*,
-# except with old shells:
-host_os=$*
-IFS=$ac_save_IFS
-case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
-
case ${build_alias} in
"") build_noncanonical=${build} ;;
@@ -4408,6 +4496,72 @@ $as_echo "#define HAVE_GETIPINFO 1" >>confdefs.h
fi
+# The sjlj test is almost duplicated here and in libgo/configure.ac (for C),
+# libstdc++-v3/acinclude.m4 and libjava/configure.ac (for C++), and
+# libobjc/configure.ac (for Objective-C).
+# FIXME: This should be centralized in config/sjlj.m4.
+# Check whether --enable-sjlj-exceptions was given.
+if test "${enable_sjlj_exceptions+set}" = set; then :
+ enableval=$enable_sjlj_exceptions; case "$enableval" in
+ yes|no|auto) ;;
+ *) as_fn_error "unknown argument to --enable-sjlj-exceptions" "$LINENO" 5 ;;
+ esac
+else
+ enable_sjlj_exceptions=auto
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use setjmp/longjmp exceptions" >&5
+$as_echo_n "checking whether to use setjmp/longjmp exceptions... " >&6; }
+if test "${libgcc_cv_lib_sjlj_exceptions+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+void bar ();
+void clean (int *);
+void foo ()
+{
+ int i __attribute__ ((cleanup (clean)));
+ bar();
+}
+
+_ACEOF
+CFLAGS_hold=$CFLAGS
+CFLAGS="--save-temps -fexceptions"
+libgcc_cv_lib_sjlj_exceptions=unknown
+if ac_fn_c_try_compile; then :
+ if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1; then
+ libgcc_cv_lib_sjlj_exceptions=yes
+ elif grep _Unwind_Resume conftest.s >/dev/null 2>&1; then
+ libgcc_cv_lib_sjlj_exceptions=no
+ fi
+fi
+CFLAGS=$CFLAGS_hold
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_lib_sjlj_exceptions" >&5
+$as_echo "$libgcc_cv_lib_sjlj_exceptions" >&6; }
+
+if test "$enable_sjlj_exceptions" = "auto"; then
+ enable_sjlj_exceptions=$libgcc_cv_lib_sjlj_exceptions
+fi
+
+case $enable_sjlj_exceptions in
+yes)
+
+$as_echo "#define LIBGCC_SJLJ_EXCEPTIONS 1" >>confdefs.h
+
+ ;;
+no)
+ ;;
+*)
+ as_fn_error "unable to detect exception model" "$LINENO" 5
+ ;;
+esac
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
if test "${acl_cv_prog_gnu_ld+set}" = set; then :
@@ -4632,6 +4786,30 @@ done
tmake_file="${tmake_file_}"
+# Likewise export definitions for libgcc_tm.h
+tm_file_=
+for f in ${tm_file}
+do
+ tm_file_="${tm_file_} \$(srcdir)/config/$f"
+done
+tm_file="${tm_file_}"
+
+
+
+# Map from thread model to thread header.
+case $target_thread_file in
+ aix) thread_header=config/rs6000/gthr-aix.h ;;
+ dce) thread_header=config/pa/gthr-dce.h ;;
+ lynx) thread_header=config/gthr-lynx.h ;;
+ mipssde) thread_header=config/mips/gthr-mipssde.h ;;
+ posix) thread_header=config/gthr-posix.h ;;
+ rtems) thread_header=config/gthr-rtems.h ;;
+ single) thread_header=gthr-single.h ;;
+ tpf) thread_header=config/s390/gthr-tpf.h ;;
+ vxworks) thread_header=config/gthr-vxworks.h ;;
+ win32) thread_header=config/i386/gthr-win32.h ;;
+esac
+
# Substitute configuration variables
@@ -4644,6 +4822,8 @@ ac_config_links="$ac_config_links md-unwind-support.h:config/$md_unwind_header"
ac_config_links="$ac_config_links sfp-machine.h:config/$sfp_machine_header"
+ac_config_links="$ac_config_links gthr-default.h:$thread_header"
+
# We need multilib support.
ac_config_files="$ac_config_files Makefile"
@@ -5373,6 +5553,7 @@ do
"unwind.h") CONFIG_LINKS="$CONFIG_LINKS unwind.h:$unwind_header" ;;
"md-unwind-support.h") CONFIG_LINKS="$CONFIG_LINKS md-unwind-support.h:config/$md_unwind_header" ;;
"sfp-machine.h") CONFIG_LINKS="$CONFIG_LINKS sfp-machine.h:config/$sfp_machine_header" ;;
+ "gthr-default.h") CONFIG_LINKS="$CONFIG_LINKS gthr-default.h:$thread_header" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"default") CONFIG_COMMANDS="$CONFIG_COMMANDS default" ;;
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index c1a3dce0f5b..a505257ac23 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -6,6 +6,7 @@ sinclude(../config/acx.m4)
sinclude(../config/no-executables.m4)
sinclude(../config/lib-ld.m4)
sinclude(../config/override.m4)
+sinclude(../config/picflag.m4)
sinclude(../config/dfp.m4)
sinclude(../config/unwind_ipinfo.m4)
@@ -58,6 +59,9 @@ AC_ARG_ENABLE(shared,
], [enable_shared=yes])
AC_SUBST(enable_shared)
+GCC_PICFLAG
+AC_SUBST(PICFLAG)
+
AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
AC_ARG_ENABLE(version-specific-runtime-libs,
[ --enable-version-specific-runtime-libs Specify that runtime libraries should be installed in a compiler-specific directory ],
@@ -180,6 +184,60 @@ AC_SUBST(fixed_point)
# config.gcc also contains tests of with_system_libunwind.
GCC_CHECK_UNWIND_GETIPINFO
+# The sjlj test is almost duplicated here and in libgo/configure.ac (for C),
+# libstdc++-v3/acinclude.m4 and libjava/configure.ac (for C++), and
+# libobjc/configure.ac (for Objective-C).
+# FIXME: This should be centralized in config/sjlj.m4.
+AC_ARG_ENABLE(sjlj-exceptions,
+ AC_HELP_STRING([--enable-sjlj-exceptions],
+ [force use of builtin_setjmp for exceptions]),
+ [case "$enableval" in
+ yes|no|auto) ;;
+ *) AC_MSG_ERROR([unknown argument to --enable-sjlj-exceptions]) ;;
+ esac],
+ [enable_sjlj_exceptions=auto])
+
+AC_CACHE_CHECK([whether to use setjmp/longjmp exceptions],
+[libgcc_cv_lib_sjlj_exceptions],
+[AC_LANG_CONFTEST(
+ [AC_LANG_SOURCE([
+void bar ();
+void clean (int *);
+void foo ()
+{
+ int i __attribute__ ((cleanup (clean)));
+ bar();
+}
+])])
+CFLAGS_hold=$CFLAGS
+CFLAGS="--save-temps -fexceptions"
+libgcc_cv_lib_sjlj_exceptions=unknown
+AS_IF([ac_fn_c_try_compile],
+ [if grep _Unwind_SjLj_Resume conftest.s >/dev/null 2>&1; then
+ libgcc_cv_lib_sjlj_exceptions=yes
+ elif grep _Unwind_Resume conftest.s >/dev/null 2>&1; then
+ libgcc_cv_lib_sjlj_exceptions=no
+ fi])
+CFLAGS=$CFLAGS_hold
+rm -f conftest*
+])
+
+if test "$enable_sjlj_exceptions" = "auto"; then
+ enable_sjlj_exceptions=$libgcc_cv_lib_sjlj_exceptions
+fi
+
+case $enable_sjlj_exceptions in
+yes)
+ AC_DEFINE(LIBGCC_SJLJ_EXCEPTIONS, 1,
+ [Define if the C compiler is configured for setjmp/longjmp exceptions.])
+ ;;
+no)
+ ;;
+*)
+ AC_MSG_ERROR([unable to detect exception model])
+ ;;
+esac
+
AC_LIB_PROG_LD_GNU
AC_MSG_CHECKING([for thread model used by GCC])
@@ -296,6 +354,30 @@ done
tmake_file="${tmake_file_}"
AC_SUBST(tmake_file)
+# Likewise export definitions for libgcc_tm.h
+tm_file_=
+for f in ${tm_file}
+do
+ tm_file_="${tm_file_} \$(srcdir)/config/$f"
+done
+tm_file="${tm_file_}"
+AC_SUBST(tm_file)
+AC_SUBST(tm_defines)
+
+# Map from thread model to thread header.
+case $target_thread_file in
+ aix) thread_header=config/rs6000/gthr-aix.h ;;
+ dce) thread_header=config/pa/gthr-dce.h ;;
+ lynx) thread_header=config/gthr-lynx.h ;;
+ mipssde) thread_header=config/mips/gthr-mipssde.h ;;
+ posix) thread_header=config/gthr-posix.h ;;
+ rtems) thread_header=config/gthr-rtems.h ;;
+ single) thread_header=gthr-single.h ;;
+ tpf) thread_header=config/s390/gthr-tpf.h ;;
+ vxworks) thread_header=config/gthr-vxworks.h ;;
+ win32) thread_header=config/i386/gthr-win32.h ;;
+esac
+
# Substitute configuration variables
AC_SUBST(cpu_type)
AC_SUBST(extra_parts)
@@ -304,6 +386,7 @@ AC_CONFIG_LINKS([enable-execute-stack.c:$enable_execute_stack])
AC_CONFIG_LINKS([unwind.h:$unwind_header])
AC_CONFIG_LINKS([md-unwind-support.h:config/$md_unwind_header])
AC_CONFIG_LINKS([sfp-machine.h:config/$sfp_machine_header])
+AC_CONFIG_LINKS([gthr-default.h:$thread_header])
# We need multilib support.
AC_CONFIG_FILES([Makefile])
diff --git a/libgcc/crtstuff.c b/libgcc/crtstuff.c
new file mode 100644
index 00000000000..66b2cdf2446
--- /dev/null
+++ b/libgcc/crtstuff.c
@@ -0,0 +1,651 @@
+/* Specialized bits of code needed to support construction and
+ destruction of file-scope objects in C++ code.
+ Copyright (C) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
+ Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+/* This file is a bit like libgcc2.c in that it is compiled
+ multiple times and yields multiple .o files.
+
+ This file is useful on target machines where the object file format
+ supports multiple "user-defined" sections (e.g. COFF, ELF, ROSE). On
+ such systems, this file allows us to avoid running collect (or any
+ other such slow and painful kludge). Additionally, if the target
+ system supports a .init section, this file allows us to support the
+ linking of C++ code with a non-C++ main program.
+
+ Note that if INIT_SECTION_ASM_OP is defined in the tm.h file, then
+ this file *will* make use of the .init section. If that symbol is
+ not defined however, then the .init section will not be used.
+
+ Currently, only ELF and COFF are supported. It is likely however that
+ ROSE could also be supported, if someone was willing to do the work to
+ make whatever (small?) adaptations are needed. (Some work may be
+ needed on the ROSE assembler and linker also.)
+
+ This file must be compiled with gcc. */
+
+/* Target machine header files require this define. */
+#define IN_LIBGCC2
+
+/* FIXME: Including auto-host is incorrect, but until we have
+ identified the set of defines that need to go into auto-target.h,
+ this will have to do. */
+#include "auto-host.h"
+#undef pid_t
+#undef rlim_t
+#undef ssize_t
+#undef vfork
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "libgcc_tm.h"
+#include "unwind-dw2-fde.h"
+
+#ifndef FORCE_CODE_SECTION_ALIGN
+# define FORCE_CODE_SECTION_ALIGN
+#endif
+
+#ifndef CRT_CALL_STATIC_FUNCTION
+# define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+static void __attribute__((__used__)) \
+call_ ## FUNC (void) \
+{ \
+ asm (SECTION_OP); \
+ FUNC (); \
+ FORCE_CODE_SECTION_ALIGN \
+ asm (TEXT_SECTION_ASM_OP); \
+}
+#endif
+
+#if defined(OBJECT_FORMAT_ELF) \
+ && !defined(OBJECT_FORMAT_FLAT) \
+ && defined(HAVE_LD_EH_FRAME_HDR) \
+ && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
+ && defined(__FreeBSD__) && __FreeBSD__ >= 7
+#include <link.h>
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if defined(OBJECT_FORMAT_ELF) \
+ && !defined(OBJECT_FORMAT_FLAT) \
+ && defined(HAVE_LD_EH_FRAME_HDR) && defined(TARGET_DL_ITERATE_PHDR) \
+ && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
+ && defined(__sun__) && defined(__svr4__)
+#include <link.h>
+# define USE_PT_GNU_EH_FRAME
+#endif
+
+#if defined(OBJECT_FORMAT_ELF) \
+ && !defined(OBJECT_FORMAT_FLAT) \
+ && defined(HAVE_LD_EH_FRAME_HDR) \
+ && !defined(inhibit_libc) && !defined(CRTSTUFFT_O) \
+ && defined(__GLIBC__) && __GLIBC__ >= 2
+#include <link.h>
+/* uClibc pretends to be glibc 2.2 and DT_CONFIG is defined in its link.h.
+ But it doesn't use PT_GNU_EH_FRAME ELF segment currently. */
+# if !defined(__UCLIBC__) \
+ && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 2 && defined(DT_CONFIG)))
+# define USE_PT_GNU_EH_FRAME
+# endif
+#endif
+#if defined(EH_FRAME_SECTION_NAME) && !defined(USE_PT_GNU_EH_FRAME)
+# define USE_EH_FRAME_REGISTRY
+#endif
+#if defined(EH_FRAME_SECTION_NAME) && EH_TABLES_CAN_BE_READ_ONLY
+# define EH_FRAME_SECTION_CONST const
+#else
+# define EH_FRAME_SECTION_CONST
+#endif
+
+#if !defined(DTOR_LIST_END) && defined(OBJECT_FORMAT_ELF) \
+ && defined(HAVE_GAS_HIDDEN) && !defined(FINI_ARRAY_SECTION_ASM_OP)
+# define HIDDEN_DTOR_LIST_END
+#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
+ these symbols to be weak as well.
+
+ This exposes a core issue, how to handle creating weak references vs
+ how to create weak definitions. Either we have to have the definition
+ of TARGET_WEAK_ATTRIBUTE be conditional in the shared header files or
+ have a second declaration if we want a function's references to be weak,
+ but not its definition.
+
+ Making TARGET_WEAK_ATTRIBUTE conditional seems like a good solution until
+ one thinks about scaling to larger problems -- i.e., the condition under
+ which TARGET_WEAK_ATTRIBUTE is active will eventually get far too
+ complicated.
+
+ So, we take an approach similar to #pragma weak -- we have a second
+ declaration for functions that we want to have weak references.
+
+ Neither way is particularly good. */
+
+/* References to __register_frame_info and __deregister_frame_info should
+ be weak in this file if at all possible. */
+extern void __register_frame_info (const void *, struct object *)
+ TARGET_ATTRIBUTE_WEAK;
+extern void __register_frame_info_bases (const void *, struct object *,
+ void *, void *)
+ TARGET_ATTRIBUTE_WEAK;
+extern void *__deregister_frame_info (const void *)
+ TARGET_ATTRIBUTE_WEAK;
+extern void *__deregister_frame_info_bases (const void *)
+ TARGET_ATTRIBUTE_WEAK;
+extern void __do_global_ctors_1 (void);
+
+/* Likewise for _Jv_RegisterClasses. */
+extern void _Jv_RegisterClasses (void *) TARGET_ATTRIBUTE_WEAK;
+
+#ifdef OBJECT_FORMAT_ELF
+
+/* Declare a pointer to void function type. */
+typedef void (*func_ptr) (void);
+#define STATIC static
+
+#else /* OBJECT_FORMAT_ELF */
+
+#include "gbl-ctors.h"
+
+#define STATIC
+
+#endif /* OBJECT_FORMAT_ELF */
+
+#ifdef CRT_BEGIN
+
+/* NOTE: In order to be able to support SVR4 shared libraries, we arrange
+ to have one set of symbols { __CTOR_LIST__, __DTOR_LIST__, __CTOR_END__,
+ __DTOR_END__ } per root executable and also one set of these symbols
+ per shared library. So in any given whole process image, we may have
+ multiple definitions of each of these symbols. In order to prevent
+ these definitions from conflicting with one another, and in order to
+ ensure that the proper lists are used for the initialization/finalization
+ of each individual shared library (respectively), we give these symbols
+ only internal (i.e. `static') linkage, and we also make it a point to
+ refer to only the __CTOR_END__ symbol in crtend.o and the __DTOR_LIST__
+ symbol in crtbegin.o, where they are defined. */
+
+/* No need for .ctors/.dtors section if linker can place them in
+ .init_array/.fini_array section. */
+#ifndef USE_INITFINI_ARRAY
+/* The -1 is a flag to __do_global_[cd]tors indicating that this table
+ does not start with a count of elements. */
+#ifdef CTOR_LIST_BEGIN
+CTOR_LIST_BEGIN;
+#elif defined(CTORS_SECTION_ASM_OP)
+/* Hack: force cc1 to switch to .data section early, so that assembling
+ __CTOR_LIST__ does not undo our behind-the-back change to .ctors. */
+static func_ptr force_to_data[1] __attribute__ ((__used__)) = { };
+asm (CTORS_SECTION_ASM_OP);
+STATIC func_ptr __CTOR_LIST__[1]
+ __attribute__ ((__used__, aligned(sizeof(func_ptr))))
+ = { (func_ptr) (-1) };
+#else
+STATIC func_ptr __CTOR_LIST__[1]
+ __attribute__ ((__used__, section(".ctors"), aligned(sizeof(func_ptr))))
+ = { (func_ptr) (-1) };
+#endif /* __CTOR_LIST__ alternatives */
+
+#ifdef DTOR_LIST_BEGIN
+DTOR_LIST_BEGIN;
+#elif defined(DTORS_SECTION_ASM_OP)
+asm (DTORS_SECTION_ASM_OP);
+STATIC func_ptr __DTOR_LIST__[1]
+ __attribute__ ((aligned(sizeof(func_ptr))))
+ = { (func_ptr) (-1) };
+#else
+STATIC func_ptr __DTOR_LIST__[1]
+ __attribute__((section(".dtors"), aligned(sizeof(func_ptr))))
+ = { (func_ptr) (-1) };
+#endif /* __DTOR_LIST__ alternatives */
+#endif /* USE_INITFINI_ARRAY */
+
+#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 EH_FRAME_SECTION_CONST char __EH_FRAME_BEGIN__[]
+ __attribute__((section(EH_FRAME_SECTION_NAME), aligned(4)))
+ = { };
+#endif /* USE_EH_FRAME_REGISTRY */
+
+#ifdef JCR_SECTION_NAME
+/* Stick a label at the beginning of the java class registration info
+ so we can register them properly. */
+STATIC void *__JCR_LIST__[]
+ __attribute__ ((used, section(JCR_SECTION_NAME), aligned(sizeof(void*))))
+ = { };
+#endif /* JCR_SECTION_NAME */
+
+#if defined(INIT_SECTION_ASM_OP) || defined(INIT_ARRAY_SECTION_ASM_OP)
+
+#ifdef OBJECT_FORMAT_ELF
+
+/* Declare the __dso_handle variable. It should have a unique value
+ in every shared-object; in a main program its value is zero. The
+ object should in any case be protected. This means the instance
+ in one DSO or the main program is not used in another object. The
+ dynamic linker takes care of this. */
+
+#ifdef TARGET_LIBGCC_SDATA_SECTION
+extern void *__dso_handle __attribute__ ((__section__ (TARGET_LIBGCC_SDATA_SECTION)));
+#endif
+#ifdef HAVE_GAS_HIDDEN
+extern void *__dso_handle __attribute__ ((__visibility__ ("hidden")));
+#endif
+#ifdef CRTSTUFFS_O
+void *__dso_handle = &__dso_handle;
+#else
+void *__dso_handle = 0;
+#endif
+
+/* The __cxa_finalize function may not be available so we use only a
+ weak declaration. */
+extern void __cxa_finalize (void *) TARGET_ATTRIBUTE_WEAK;
+
+/* Run all the global destructors on exit from the program. */
+
+/* Some systems place the number of pointers in the first word of the
+ table. On SVR4 however, that word is -1. In all cases, the table is
+ null-terminated. On SVR4, we start from the beginning of the list and
+ invoke each per-compilation-unit destructor routine in order
+ until we find that null.
+
+ Note that this function MUST be static. There will be one of these
+ functions in each root executable and one in each shared library, but
+ although they all have the same code, each one is unique in that it
+ refers to one particular associated `__DTOR_LIST__' which belongs to the
+ same particular root executable or shared library file.
+
+ On some systems, this routine is run more than once from the .fini,
+ when exit is called recursively, so we arrange to remember where in
+ the list we left off processing, and we resume at that point,
+ should we be re-invoked. */
+
+static void __attribute__((used))
+__do_global_dtors_aux (void)
+{
+ static _Bool completed;
+
+ if (__builtin_expect (completed, 0))
+ return;
+
+#ifdef CRTSTUFFS_O
+ if (__cxa_finalize)
+ __cxa_finalize (__dso_handle);
+#endif
+
+#ifdef FINI_ARRAY_SECTION_ASM_OP
+ /* If we are using .fini_array then destructors will be run via that
+ mechanism. */
+#elif defined(HIDDEN_DTOR_LIST_END)
+ {
+ /* Safer version that makes sure only .dtors function pointers are
+ called even if the static variable is maliciously changed. */
+ extern func_ptr __DTOR_END__[] __attribute__((visibility ("hidden")));
+ static size_t dtor_idx;
+ const size_t max_idx = __DTOR_END__ - __DTOR_LIST__ - 1;
+ func_ptr f;
+
+ while (dtor_idx < max_idx)
+ {
+ f = __DTOR_LIST__[++dtor_idx];
+ f ();
+ }
+ }
+#else /* !defined (FINI_ARRAY_SECTION_ASM_OP) */
+ {
+ static func_ptr *p = __DTOR_LIST__ + 1;
+ func_ptr f;
+
+ while ((f = *p))
+ {
+ p++;
+ f ();
+ }
+ }
+#endif /* !defined(FINI_ARRAY_SECTION_ASM_OP) */
+
+#ifdef USE_EH_FRAME_REGISTRY
+#ifdef CRT_GET_RFIB_DATA
+ /* If we used the new __register_frame_info_bases interface,
+ make sure that we deregister from the same place. */
+ if (__deregister_frame_info_bases)
+ __deregister_frame_info_bases (__EH_FRAME_BEGIN__);
+#else
+ if (__deregister_frame_info)
+ __deregister_frame_info (__EH_FRAME_BEGIN__);
+#endif
+#endif
+
+ completed = 1;
+}
+
+/* Stick a call to __do_global_dtors_aux into the .fini section. */
+#ifdef FINI_SECTION_ASM_OP
+CRT_CALL_STATIC_FUNCTION (FINI_SECTION_ASM_OP, __do_global_dtors_aux)
+#elif defined (FINI_ARRAY_SECTION_ASM_OP)
+static func_ptr __do_global_dtors_aux_fini_array_entry[]
+ __attribute__ ((__used__, section(".fini_array")))
+ = { __do_global_dtors_aux };
+#else /* !FINI_SECTION_ASM_OP && !FINI_ARRAY_SECTION_ASM_OP */
+static void __attribute__((used))
+__do_global_dtors_aux_1 (void)
+{
+ atexit (__do_global_dtors_aux);
+}
+CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_dtors_aux_1)
+#endif
+
+#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
+/* Stick a call to __register_frame_info into the .init section. For some
+ reason calls with no arguments work more reliably in .init, so stick the
+ call in another function. */
+
+static void __attribute__((used))
+frame_dummy (void)
+{
+#ifdef USE_EH_FRAME_REGISTRY
+ static struct object object;
+#ifdef CRT_GET_RFIB_DATA
+ void *tbase, *dbase;
+ tbase = 0;
+ CRT_GET_RFIB_DATA (dbase);
+ if (__register_frame_info_bases)
+ __register_frame_info_bases (__EH_FRAME_BEGIN__, &object, tbase, dbase);
+#else
+ if (__register_frame_info)
+ __register_frame_info (__EH_FRAME_BEGIN__, &object);
+#endif /* CRT_GET_RFIB_DATA */
+#endif /* USE_EH_FRAME_REGISTRY */
+#ifdef JCR_SECTION_NAME
+ if (__JCR_LIST__[0])
+ {
+ void (*register_classes) (void *) = _Jv_RegisterClasses;
+ __asm ("" : "+r" (register_classes));
+ if (register_classes)
+ register_classes (__JCR_LIST__);
+ }
+#endif /* JCR_SECTION_NAME */
+}
+
+#ifdef INIT_SECTION_ASM_OP
+CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, frame_dummy)
+#else /* defined(INIT_SECTION_ASM_OP) */
+static func_ptr __frame_dummy_init_array_entry[]
+ __attribute__ ((__used__, section(".init_array")))
+ = { frame_dummy };
+#endif /* !defined(INIT_SECTION_ASM_OP) */
+#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
+
+#else /* OBJECT_FORMAT_ELF */
+
+/* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
+ and once in crtend.o). It must be declared static to avoid a link
+ error. Here, we define __do_global_ctors as an externally callable
+ function. It is externally callable so that __main can invoke it when
+ INVOKE__main is defined. This has the additional effect of forcing cc1
+ to switch to the .text section. */
+
+static void __do_global_ctors_aux (void);
+void
+__do_global_ctors (void)
+{
+#ifdef INVOKE__main
+ /* If __main won't actually call __do_global_ctors then it doesn't matter
+ what's inside the function. The inside of __do_global_ctors_aux is
+ called automatically in that case. And the Alliant fx2800 linker
+ crashes on this reference. So prevent the crash. */
+ __do_global_ctors_aux ();
+#endif
+}
+
+asm (INIT_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
+
+/* A routine to invoke all of the global constructors upon entry to the
+ program. We put this into the .init section (for systems that have
+ such a thing) so that we can properly perform the construction of
+ file-scope static-storage C++ objects within shared libraries. */
+
+static void __attribute__((used))
+__do_global_ctors_aux (void) /* prologue goes in .init section */
+{
+ FORCE_CODE_SECTION_ALIGN /* explicit align before switch to .text */
+ asm (TEXT_SECTION_ASM_OP); /* don't put epilogue and body in .init */
+ DO_GLOBAL_CTORS_BODY;
+ atexit (__do_global_dtors);
+}
+
+#endif /* OBJECT_FORMAT_ELF */
+
+#elif defined(HAS_INIT_SECTION) /* ! INIT_SECTION_ASM_OP */
+
+extern void __do_global_dtors (void);
+
+/* This case is used by the Irix 6 port, which supports named sections but
+ not an SVR4-style .fini section. __do_global_dtors can be non-static
+ in this case because we protect it with -hidden_symbol. */
+
+void
+__do_global_dtors (void)
+{
+ func_ptr *p, f;
+ for (p = __DTOR_LIST__ + 1; (f = *p); p++)
+ f ();
+
+#ifdef USE_EH_FRAME_REGISTRY
+ if (__deregister_frame_info)
+ __deregister_frame_info (__EH_FRAME_BEGIN__);
+#endif
+}
+
+#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
+/* A helper function for __do_global_ctors, which is in crtend.o. Here
+ in crtbegin.o, we can reference a couple of symbols not visible there.
+ Plus, since we're before libgcc.a, we have no problems referencing
+ functions from there. */
+void
+__do_global_ctors_1(void)
+{
+#ifdef USE_EH_FRAME_REGISTRY
+ static struct object object;
+ if (__register_frame_info)
+ __register_frame_info (__EH_FRAME_BEGIN__, &object);
+#endif
+#ifdef JCR_SECTION_NAME
+ if (__JCR_LIST__[0])
+ {
+ void (*register_classes) (void *) = _Jv_RegisterClasses;
+ __asm ("" : "+r" (register_classes));
+ if (register_classes)
+ register_classes (__JCR_LIST__);
+ }
+#endif
+}
+#endif /* USE_EH_FRAME_REGISTRY || JCR_SECTION_NAME */
+
+#else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */
+#error "What are you doing with crtstuff.c, then?"
+#endif
+
+#elif defined(CRT_END) /* ! CRT_BEGIN */
+
+/* No need for .ctors/.dtors section if linker can place them in
+ .init_array/.fini_array section. */
+#ifndef USE_INITFINI_ARRAY
+/* Put a word containing zero at the end of each of our two lists of function
+ addresses. Note that the words defined here go into the .ctors and .dtors
+ sections of the crtend.o file, and since that file is always linked in
+ last, these words naturally end up at the very ends of the two lists
+ contained in these two sections. */
+
+#ifdef CTOR_LIST_END
+CTOR_LIST_END;
+#elif defined(CTORS_SECTION_ASM_OP)
+/* Hack: force cc1 to switch to .data section early, so that assembling
+ __CTOR_LIST__ does not undo our behind-the-back change to .ctors. */
+static func_ptr force_to_data[1] __attribute__ ((__used__)) = { };
+asm (CTORS_SECTION_ASM_OP);
+STATIC func_ptr __CTOR_END__[1]
+ __attribute__((aligned(sizeof(func_ptr))))
+ = { (func_ptr) 0 };
+#else
+STATIC func_ptr __CTOR_END__[1]
+ __attribute__((section(".ctors"), aligned(sizeof(func_ptr))))
+ = { (func_ptr) 0 };
+#endif
+
+#ifdef DTOR_LIST_END
+DTOR_LIST_END;
+#elif defined(HIDDEN_DTOR_LIST_END)
+#ifdef DTORS_SECTION_ASM_OP
+asm (DTORS_SECTION_ASM_OP);
+#endif
+func_ptr __DTOR_END__[1]
+ __attribute__ ((used,
+#ifndef DTORS_SECTION_ASM_OP
+ section(".dtors"),
+#endif
+ aligned(sizeof(func_ptr)), visibility ("hidden")))
+ = { (func_ptr) 0 };
+#elif defined(DTORS_SECTION_ASM_OP)
+asm (DTORS_SECTION_ASM_OP);
+STATIC func_ptr __DTOR_END__[1]
+ __attribute__ ((used, aligned(sizeof(func_ptr))))
+ = { (func_ptr) 0 };
+#else
+STATIC func_ptr __DTOR_END__[1]
+ __attribute__((used, section(".dtors"), aligned(sizeof(func_ptr))))
+ = { (func_ptr) 0 };
+#endif
+#endif /* USE_INITFINI_ARRAY */
+
+#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. */
+# if __INT_MAX__ == 2147483647
+typedef int int32;
+# elif __LONG_MAX__ == 2147483647
+typedef long int32;
+# elif __SHRT_MAX__ == 2147483647
+typedef short int32;
+# else
+# error "Missing a 4 byte integer"
+# endif
+STATIC EH_FRAME_SECTION_CONST int32 __FRAME_END__[]
+ __attribute__ ((used, section(EH_FRAME_SECTION_NAME),
+ aligned(sizeof(int32))))
+ = { 0 };
+#endif /* EH_FRAME_SECTION_NAME */
+
+#ifdef JCR_SECTION_NAME
+/* Null terminate the .jcr section array. */
+STATIC void *__JCR_END__[1]
+ __attribute__ ((used, section(JCR_SECTION_NAME),
+ aligned(sizeof(void *))))
+ = { 0 };
+#endif /* JCR_SECTION_NAME */
+
+#ifdef INIT_ARRAY_SECTION_ASM_OP
+
+/* If we are using .init_array, there is nothing to do. */
+
+#elif defined(INIT_SECTION_ASM_OP)
+
+#ifdef OBJECT_FORMAT_ELF
+static void __attribute__((used))
+__do_global_ctors_aux (void)
+{
+ func_ptr *p;
+ for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+ (*p) ();
+}
+
+/* Stick a call to __do_global_ctors_aux into the .init section. */
+CRT_CALL_STATIC_FUNCTION (INIT_SECTION_ASM_OP, __do_global_ctors_aux)
+#else /* OBJECT_FORMAT_ELF */
+
+/* Stick the real initialization code, followed by a normal sort of
+ function epilogue at the very end of the .init section for this
+ entire root executable file or for this entire shared library file.
+
+ Note that we use some tricks here to get *just* the body and just
+ a function epilogue (but no function prologue) into the .init
+ section of the crtend.o file. Specifically, we switch to the .text
+ section, start to define a function, and then we switch to the .init
+ section just before the body code.
+
+ Earlier on, we put the corresponding function prologue into the .init
+ section of the crtbegin.o file (which will be linked in first).
+
+ Note that we want to invoke all constructors for C++ file-scope static-
+ storage objects AFTER any other possible initialization actions which
+ may be performed by the code in the .init section contributions made by
+ other libraries, etc. That's because those other initializations may
+ include setup operations for very primitive things (e.g. initializing
+ the state of the floating-point coprocessor, etc.) which should be done
+ before we start to execute any of the user's code. */
+
+static void
+__do_global_ctors_aux (void) /* prologue goes in .text section */
+{
+ asm (INIT_SECTION_ASM_OP);
+ DO_GLOBAL_CTORS_BODY;
+ atexit (__do_global_dtors);
+} /* epilogue and body go in .init section */
+
+FORCE_CODE_SECTION_ALIGN
+asm (TEXT_SECTION_ASM_OP);
+
+#endif /* OBJECT_FORMAT_ELF */
+
+#elif defined(HAS_INIT_SECTION) /* ! INIT_SECTION_ASM_OP */
+
+extern void __do_global_ctors (void);
+
+/* This case is used by the Irix 6 port, which supports named sections but
+ not an SVR4-style .init section. __do_global_ctors can be non-static
+ in this case because we protect it with -hidden_symbol. */
+void
+__do_global_ctors (void)
+{
+ func_ptr *p;
+#if defined(USE_EH_FRAME_REGISTRY) || defined(JCR_SECTION_NAME)
+ __do_global_ctors_1();
+#endif
+ for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+ (*p) ();
+}
+
+#else /* ! INIT_SECTION_ASM_OP && ! HAS_INIT_SECTION */
+#error "What are you doing with crtstuff.c, then?"
+#endif
+
+#else /* ! CRT_BEGIN && ! CRT_END */
+#error "One of CRT_BEGIN or CRT_END must be defined."
+#endif
diff --git a/libgcc/dfp-bit.h b/libgcc/dfp-bit.h
index 45b79086bc9..c97869baca1 100644
--- a/libgcc/dfp-bit.h
+++ b/libgcc/dfp-bit.h
@@ -1,5 +1,5 @@
/* Header file for dfp-bit.c.
- Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+ Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -33,6 +33,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
diff --git a/gcc/config/divmod.c b/libgcc/divmod.c
index c227b99ccd2..c227b99ccd2 100644
--- a/gcc/config/divmod.c
+++ b/libgcc/divmod.c
diff --git a/libgcc/emutls.c b/libgcc/emutls.c
index b7ee3bdfa7c..22ea4403edb 100644
--- a/libgcc/emutls.c
+++ b/libgcc/emutls.c
@@ -1,5 +1,5 @@
/* TLS emulation.
- Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2008, 2009, 2011 Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>.
This file is part of GCC.
@@ -27,6 +27,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "gthr.h"
typedef unsigned int word __attribute__((mode(word)));
diff --git a/libgcc/fixed-bit.c b/libgcc/fixed-bit.c
index d434d131eec..84e58155ccd 100644
--- a/libgcc/fixed-bit.c
+++ b/libgcc/fixed-bit.c
@@ -1,5 +1,5 @@
/* This is a software fixed-point library.
- Copyright (C) 2007, 2009 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -46,6 +46,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#ifndef MIN_UNITS_PER_WORD
#define MIN_UNITS_PER_WORD UNITS_PER_WORD
diff --git a/gcc/config/floatunsidf.c b/libgcc/floatunsidf.c
index ff28112502b..ff28112502b 100644
--- a/gcc/config/floatunsidf.c
+++ b/libgcc/floatunsidf.c
diff --git a/gcc/config/floatunsisf.c b/libgcc/floatunsisf.c
index 11d4aa78cbe..11d4aa78cbe 100644
--- a/gcc/config/floatunsisf.c
+++ b/libgcc/floatunsisf.c
diff --git a/gcc/config/floatunsitf.c b/libgcc/floatunsitf.c
index 955d67666c5..955d67666c5 100644
--- a/gcc/config/floatunsitf.c
+++ b/libgcc/floatunsitf.c
diff --git a/gcc/config/floatunsixf.c b/libgcc/floatunsixf.c
index 52511688dad..52511688dad 100644
--- a/gcc/config/floatunsixf.c
+++ b/libgcc/floatunsixf.c
diff --git a/libgcc/fp-bit.c b/libgcc/fp-bit.c
index de9b3ada5ec..7509f76f71e 100644
--- a/libgcc/fp-bit.c
+++ b/libgcc/fp-bit.c
@@ -37,6 +37,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tconfig.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "fp-bit.h"
/* The following macros can be defined to change the behavior of this file:
diff --git a/gcc/gbl-ctors.h b/libgcc/gbl-ctors.h
index ac4faae1292..ac4faae1292 100644
--- a/gcc/gbl-ctors.h
+++ b/libgcc/gbl-ctors.h
diff --git a/libgcc/generic-morestack-thread.c b/libgcc/generic-morestack-thread.c
index 794fdc3dc54..bbe6dd12b5a 100644
--- a/libgcc/generic-morestack-thread.c
+++ b/libgcc/generic-morestack-thread.c
@@ -27,6 +27,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
/* If inhibit_libc is defined, we can not compile this file. The
effect is that people will not be able to use -fsplit-stack. That
diff --git a/libgcc/generic-morestack.c b/libgcc/generic-morestack.c
index 0b660cedd5f..07bc2a66073 100644
--- a/libgcc/generic-morestack.c
+++ b/libgcc/generic-morestack.c
@@ -27,6 +27,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
/* If inhibit_libc is defined, we can not compile this file. The
effect is that people will not be able to use -fsplit-stack. That
diff --git a/gcc/gthr-single.h b/libgcc/gthr-single.h
index 357528ad1f1..357528ad1f1 100644
--- a/gcc/gthr-single.h
+++ b/libgcc/gthr-single.h
diff --git a/libgcc/gthr.h b/libgcc/gthr.h
new file mode 100644
index 00000000000..607c26eb563
--- /dev/null
+++ b/libgcc/gthr.h
@@ -0,0 +1,148 @@
+/* Threads compatibility routines for libgcc2. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1997, 1998, 2004, 2008, 2009, 2011
+ 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_GTHR_H
+#define GCC_GTHR_H
+
+#ifndef HIDE_EXPORTS
+#pragma GCC visibility push(default)
+#endif
+
+/* 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
+ int __gthread_active_p ()
+ that returns 1 if thread system is active, 0 if not.
+
+ The threads interface must define the following types:
+ __gthread_key_t
+ __gthread_once_t
+ __gthread_mutex_t
+ __gthread_recursive_mutex_t
+
+ The threads interface must define the following macros:
+
+ __GTHREAD_ONCE_INIT
+ to initialize __gthread_once_t
+ __GTHREAD_MUTEX_INIT
+ to initialize __gthread_mutex_t to get a fast
+ non-recursive mutex.
+ __GTHREAD_MUTEX_INIT_FUNCTION
+ some systems can't initialize a mutex without a
+ function call. On such systems, define this to a
+ function which looks like this:
+ void __GTHREAD_MUTEX_INIT_FUNCTION (__gthread_mutex_t *)
+ Don't define __GTHREAD_MUTEX_INIT in this case
+ __GTHREAD_RECURSIVE_MUTEX_INIT
+ __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION
+ as above, but for a recursive mutex.
+
+ The threads interface must define the following static functions:
+
+ int __gthread_once (__gthread_once_t *once, void (*func) ())
+
+ int __gthread_key_create (__gthread_key_t *keyp, void (*dtor) (void *))
+ int __gthread_key_delete (__gthread_key_t key)
+
+ void *__gthread_getspecific (__gthread_key_t key)
+ int __gthread_setspecific (__gthread_key_t key, const void *ptr)
+
+ int __gthread_mutex_destroy (__gthread_mutex_t *mutex);
+
+ int __gthread_mutex_lock (__gthread_mutex_t *mutex);
+ int __gthread_mutex_trylock (__gthread_mutex_t *mutex);
+ int __gthread_mutex_unlock (__gthread_mutex_t *mutex);
+
+ int __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex);
+ int __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex);
+ int __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex);
+
+ The following are supported in POSIX threads only. They are required to
+ fix a deadlock in static initialization inside libsupc++. The header file
+ gthr-posix.h defines a symbol __GTHREAD_HAS_COND to signify that these extra
+ features are supported.
+
+ Types:
+ __gthread_cond_t
+
+ Macros:
+ __GTHREAD_COND_INIT
+ __GTHREAD_COND_INIT_FUNCTION
+
+ Interface:
+ int __gthread_cond_broadcast (__gthread_cond_t *cond);
+ int __gthread_cond_wait (__gthread_cond_t *cond, __gthread_mutex_t *mutex);
+ int __gthread_cond_wait_recursive (__gthread_cond_t *cond,
+ __gthread_recursive_mutex_t *mutex);
+
+ All functions returning int should return zero on success or the error
+ number. If the operation is not supported, -1 is returned.
+
+ If the following are also defined, you should
+ #define __GTHREADS_CXX0X 1
+ to enable the c++0x thread library.
+
+ Types:
+ __gthread_t
+ __gthread_time_t
+
+ Interface:
+ int __gthread_create (__gthread_t *thread, void *(*func) (void*),
+ void *args);
+ int __gthread_join (__gthread_t thread, void **value_ptr);
+ int __gthread_detach (__gthread_t thread);
+ int __gthread_equal (__gthread_t t1, __gthread_t t2);
+ __gthread_t __gthread_self (void);
+ int __gthread_yield (void);
+
+ int __gthread_mutex_timedlock (__gthread_mutex_t *m,
+ const __gthread_time_t *abs_timeout);
+ int __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *m,
+ const __gthread_time_t *abs_time);
+
+ int __gthread_cond_signal (__gthread_cond_t *cond);
+ int __gthread_cond_timedwait (__gthread_cond_t *cond,
+ __gthread_mutex_t *mutex,
+ const __gthread_time_t *abs_timeout);
+ int __gthread_cond_timedwait_recursive (__gthread_cond_t *cond,
+ __gthread_recursive_mutex_t *mutex,
+ const __gthread_time_t *abs_time)
+
+*/
+
+#if SUPPORTS_WEAK
+#ifndef GTHREAD_USE_WEAK
+#define GTHREAD_USE_WEAK 1
+#endif
+#endif
+#include "gthr-default.h"
+
+#ifndef HIDE_EXPORTS
+#pragma GCC visibility pop
+#endif
+
+#endif /* ! GCC_GTHR_H */
diff --git a/libgcc/libgcc2.c b/libgcc/libgcc2.c
new file mode 100644
index 00000000000..b672bcbdd41
--- /dev/null
+++ b/libgcc/libgcc2.c
@@ -0,0 +1,2253 @@
+/* More subroutines needed by GCC output code on some machines. */
+/* Compile this one with gcc. */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+ 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "libgcc_tm.h"
+
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
+/* Work out the largest "word" size that we can deal with on this target. */
+#if MIN_UNITS_PER_WORD > 4
+# define LIBGCC2_MAX_UNITS_PER_WORD 8
+#elif (MIN_UNITS_PER_WORD > 2 \
+ || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4))
+# define LIBGCC2_MAX_UNITS_PER_WORD 4
+#else
+# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
+#endif
+
+/* Work out what word size we are using for this compilation.
+ The value can be set on the command line. */
+#ifndef LIBGCC2_UNITS_PER_WORD
+#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
+#endif
+
+#if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD
+
+#include "libgcc2.h"
+
+#ifdef DECLARE_LIBRARY_RENAMES
+ DECLARE_LIBRARY_RENAMES
+#endif
+
+#if defined (L_negdi2)
+DWtype
+__negdi2 (DWtype u)
+{
+ const DWunion uu = {.ll = u};
+ const DWunion w = { {.low = -uu.s.low,
+ .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } };
+
+ return w.ll;
+}
+#endif
+
+#ifdef L_addvsi3
+Wtype
+__addvSI3 (Wtype a, Wtype b)
+{
+ const Wtype w = (UWtype) a + (UWtype) b;
+
+ if (b >= 0 ? w < a : w > a)
+ abort ();
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__addvsi3 (SItype a, SItype b)
+{
+ const SItype w = (USItype) a + (USItype) b;
+
+ if (b >= 0 ? w < a : w > a)
+ abort ();
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
+#endif
+
+#ifdef L_addvdi3
+DWtype
+__addvDI3 (DWtype a, DWtype b)
+{
+ const DWtype w = (UDWtype) a + (UDWtype) b;
+
+ if (b >= 0 ? w < a : w > a)
+ abort ();
+
+ return w;
+}
+#endif
+
+#ifdef L_subvsi3
+Wtype
+__subvSI3 (Wtype a, Wtype b)
+{
+ const Wtype w = (UWtype) a - (UWtype) b;
+
+ if (b >= 0 ? w > a : w < a)
+ abort ();
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__subvsi3 (SItype a, SItype b)
+{
+ const SItype w = (USItype) a - (USItype) b;
+
+ if (b >= 0 ? w > a : w < a)
+ abort ();
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
+#endif
+
+#ifdef L_subvdi3
+DWtype
+__subvDI3 (DWtype a, DWtype b)
+{
+ const DWtype w = (UDWtype) a - (UDWtype) b;
+
+ if (b >= 0 ? w > a : w < a)
+ abort ();
+
+ return w;
+}
+#endif
+
+#ifdef L_mulvsi3
+Wtype
+__mulvSI3 (Wtype a, Wtype b)
+{
+ const DWtype w = (DWtype) a * (DWtype) b;
+
+ if ((Wtype) (w >> W_TYPE_SIZE) != (Wtype) w >> (W_TYPE_SIZE - 1))
+ abort ();
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+#undef WORD_SIZE
+#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+SItype
+__mulvsi3 (SItype a, SItype b)
+{
+ const DItype w = (DItype) a * (DItype) b;
+
+ if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1))
+ abort ();
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
+#endif
+
+#ifdef L_negvsi2
+Wtype
+__negvSI2 (Wtype a)
+{
+ const Wtype w = -(UWtype) a;
+
+ if (a >= 0 ? w > 0 : w < 0)
+ abort ();
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__negvsi2 (SItype a)
+{
+ const SItype w = -(USItype) a;
+
+ if (a >= 0 ? w > 0 : w < 0)
+ abort ();
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
+#endif
+
+#ifdef L_negvdi2
+DWtype
+__negvDI2 (DWtype a)
+{
+ const DWtype w = -(UDWtype) a;
+
+ if (a >= 0 ? w > 0 : w < 0)
+ abort ();
+
+ return w;
+}
+#endif
+
+#ifdef L_absvsi2
+Wtype
+__absvSI2 (Wtype a)
+{
+ Wtype w = a;
+
+ if (a < 0)
+#ifdef L_negvsi2
+ w = __negvSI2 (a);
+#else
+ w = -(UWtype) a;
+
+ if (w < 0)
+ abort ();
+#endif
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__absvsi2 (SItype a)
+{
+ SItype w = a;
+
+ if (a < 0)
+#ifdef L_negvsi2
+ w = __negvsi2 (a);
+#else
+ w = -(USItype) a;
+
+ if (w < 0)
+ abort ();
+#endif
+
+ return w;
+}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
+#endif
+
+#ifdef L_absvdi2
+DWtype
+__absvDI2 (DWtype a)
+{
+ DWtype w = a;
+
+ if (a < 0)
+#ifdef L_negvdi2
+ w = __negvDI2 (a);
+#else
+ w = -(UDWtype) a;
+
+ if (w < 0)
+ abort ();
+#endif
+
+ return w;
+}
+#endif
+
+#ifdef L_mulvdi3
+DWtype
+__mulvDI3 (DWtype u, DWtype v)
+{
+ /* The unchecked multiplication needs 3 Wtype x Wtype multiplications,
+ but the checked multiplication needs only two. */
+ const DWunion uu = {.ll = u};
+ const DWunion vv = {.ll = v};
+
+ if (__builtin_expect (uu.s.high == uu.s.low >> (W_TYPE_SIZE - 1), 1))
+ {
+ /* u fits in a single Wtype. */
+ if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
+ {
+ /* v fits in a single Wtype as well. */
+ /* A single multiplication. No overflow risk. */
+ return (DWtype) uu.s.low * (DWtype) vv.s.low;
+ }
+ else
+ {
+ /* Two multiplications. */
+ DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+ DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.high};
+
+ if (vv.s.high < 0)
+ w1.s.high -= uu.s.low;
+ if (uu.s.low < 0)
+ w1.ll -= vv.ll;
+ w1.ll += (UWtype) w0.s.high;
+ if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
+ {
+ w0.s.high = w1.s.low;
+ return w0.ll;
+ }
+ }
+ }
+ else
+ {
+ if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
+ {
+ /* v fits into a single Wtype. */
+ /* Two multiplications. */
+ DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+ DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.high
+ * (UDWtype) (UWtype) vv.s.low};
+
+ if (uu.s.high < 0)
+ w1.s.high -= vv.s.low;
+ if (vv.s.low < 0)
+ w1.ll -= uu.ll;
+ w1.ll += (UWtype) w0.s.high;
+ if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
+ {
+ w0.s.high = w1.s.low;
+ return w0.ll;
+ }
+ }
+ else
+ {
+ /* A few sign checks and a single multiplication. */
+ if (uu.s.high >= 0)
+ {
+ if (vv.s.high >= 0)
+ {
+ if (uu.s.high == 0 && vv.s.high == 0)
+ {
+ const DWtype w = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low;
+ if (__builtin_expect (w >= 0, 1))
+ return w;
+ }
+ }
+ else
+ {
+ if (uu.s.high == 0 && vv.s.high == (Wtype) -1)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= uu.s.low;
+ if (__builtin_expect (ww.s.high < 0, 1))
+ return ww.ll;
+ }
+ }
+ }
+ else
+ {
+ if (vv.s.high >= 0)
+ {
+ if (uu.s.high == (Wtype) -1 && vv.s.high == 0)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= vv.s.low;
+ if (__builtin_expect (ww.s.high < 0, 1))
+ return ww.ll;
+ }
+ }
+ else
+ {
+ if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= uu.s.low;
+ ww.s.high -= vv.s.low;
+ if (__builtin_expect (ww.s.high >= 0, 1))
+ return ww.ll;
+ }
+ }
+ }
+ }
+ }
+
+ /* Overflow. */
+ abort ();
+}
+#endif
+
+
+/* Unless shift functions are defined with full ANSI prototypes,
+ parameter b will be promoted to int if shift_count_type is smaller than an int. */
+#ifdef L_lshrdi3
+DWtype
+__lshrdi3 (DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = W_TYPE_SIZE - b;
+ DWunion w;
+
+ if (bm <= 0)
+ {
+ w.s.high = 0;
+ w.s.low = (UWtype) uu.s.high >> -bm;
+ }
+ else
+ {
+ const UWtype carries = (UWtype) uu.s.high << bm;
+
+ w.s.high = (UWtype) uu.s.high >> b;
+ w.s.low = ((UWtype) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+#endif
+
+#ifdef L_ashldi3
+DWtype
+__ashldi3 (DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = W_TYPE_SIZE - b;
+ DWunion w;
+
+ if (bm <= 0)
+ {
+ w.s.low = 0;
+ w.s.high = (UWtype) uu.s.low << -bm;
+ }
+ else
+ {
+ const UWtype carries = (UWtype) uu.s.low >> bm;
+
+ w.s.low = (UWtype) uu.s.low << b;
+ w.s.high = ((UWtype) uu.s.high << b) | carries;
+ }
+
+ return w.ll;
+}
+#endif
+
+#ifdef L_ashrdi3
+DWtype
+__ashrdi3 (DWtype u, shift_count_type b)
+{
+ if (b == 0)
+ return u;
+
+ const DWunion uu = {.ll = u};
+ const shift_count_type bm = W_TYPE_SIZE - b;
+ DWunion w;
+
+ if (bm <= 0)
+ {
+ /* w.s.high = 1..1 or 0..0 */
+ w.s.high = uu.s.high >> (W_TYPE_SIZE - 1);
+ w.s.low = uu.s.high >> -bm;
+ }
+ else
+ {
+ const UWtype carries = (UWtype) uu.s.high << bm;
+
+ w.s.high = uu.s.high >> b;
+ w.s.low = ((UWtype) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
+}
+#endif
+
+#ifdef L_bswapsi2
+SItype
+__bswapsi2 (SItype u)
+{
+ return ((((u) & 0xff000000) >> 24)
+ | (((u) & 0x00ff0000) >> 8)
+ | (((u) & 0x0000ff00) << 8)
+ | (((u) & 0x000000ff) << 24));
+}
+#endif
+#ifdef L_bswapdi2
+DItype
+__bswapdi2 (DItype u)
+{
+ return ((((u) & 0xff00000000000000ull) >> 56)
+ | (((u) & 0x00ff000000000000ull) >> 40)
+ | (((u) & 0x0000ff0000000000ull) >> 24)
+ | (((u) & 0x000000ff00000000ull) >> 8)
+ | (((u) & 0x00000000ff000000ull) << 8)
+ | (((u) & 0x0000000000ff0000ull) << 24)
+ | (((u) & 0x000000000000ff00ull) << 40)
+ | (((u) & 0x00000000000000ffull) << 56));
+}
+#endif
+#ifdef L_ffssi2
+#undef int
+int
+__ffsSI2 (UWtype u)
+{
+ UWtype count;
+
+ if (u == 0)
+ return 0;
+
+ count_trailing_zeros (count, u);
+ return count + 1;
+}
+#endif
+
+#ifdef L_ffsdi2
+#undef int
+int
+__ffsDI2 (DWtype u)
+{
+ const DWunion uu = {.ll = u};
+ UWtype word, count, add;
+
+ if (uu.s.low != 0)
+ word = uu.s.low, add = 0;
+ else if (uu.s.high != 0)
+ word = uu.s.high, add = W_TYPE_SIZE;
+ else
+ return 0;
+
+ count_trailing_zeros (count, word);
+ return count + add + 1;
+}
+#endif
+
+#ifdef L_muldi3
+DWtype
+__muldi3 (DWtype u, DWtype v)
+{
+ const DWunion uu = {.ll = u};
+ const DWunion vv = {.ll = v};
+ DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)};
+
+ w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
+ + (UWtype) uu.s.high * (UWtype) vv.s.low);
+
+ return w.ll;
+}
+#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)
+{
+ UWtype q, r;
+ UWtype c0, c1, b1;
+
+ if ((Wtype) d >= 0)
+ {
+ if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
+ {
+ /* Dividend, divisor, and quotient are nonnegative. */
+ sdiv_qrnnd (q, r, a1, a0, d);
+ }
+ else
+ {
+ /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d. */
+ sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
+ /* Divide (c1*2^32 + c0) by d. */
+ sdiv_qrnnd (q, r, c1, c0, d);
+ /* Add 2^31 to quotient. */
+ q += (UWtype) 1 << (W_TYPE_SIZE - 1);
+ }
+ }
+ else
+ {
+ b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
+ c1 = a1 >> 1; /* A/2 */
+ c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
+
+ if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
+ {
+ sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+ r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
+ if ((d & 1) != 0)
+ {
+ if (r >= q)
+ r = r - q;
+ else if (q - r <= d)
+ {
+ r = r - q + d;
+ q--;
+ }
+ else
+ {
+ r = r - q + 2*d;
+ q -= 2;
+ }
+ }
+ }
+ else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
+ {
+ c1 = (b1 - 1) - c1;
+ c0 = ~c0; /* logical NOT */
+
+ sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
+
+ q = ~q; /* (A/2)/b1 */
+ r = (b1 - 1) - r;
+
+ r = 2*r + (a0 & 1); /* A/(2*b1) */
+
+ if ((d & 1) != 0)
+ {
+ if (r >= q)
+ r = r - q;
+ else if (q - r <= d)
+ {
+ r = r - q + d;
+ q--;
+ }
+ else
+ {
+ r = r - q + 2*d;
+ q -= 2;
+ }
+ }
+ }
+ else /* Implies c1 = b1 */
+ { /* Hence a1 = d - 1 = 2*b1 - 1 */
+ if (a0 >= -d)
+ {
+ q = -1;
+ r = a0 + d;
+ }
+ else
+ {
+ q = -2;
+ r = a0 + 2*d;
+ }
+ }
+ }
+
+ *rp = r;
+ return q;
+}
+#else
+/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
+UWtype
+__udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
+ UWtype a1 __attribute__ ((__unused__)),
+ UWtype a0 __attribute__ ((__unused__)),
+ UWtype d __attribute__ ((__unused__)))
+{
+ return 0;
+}
+#endif
+#endif
+
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+#define L_udivmoddi4
+#endif
+
+#ifdef L_clz
+const UQItype __clz_tab[256] =
+{
+ 0,1,2,2,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,
+ 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,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,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
+};
+#endif
+
+#ifdef L_clzsi2
+#undef int
+int
+__clzSI2 (UWtype x)
+{
+ Wtype ret;
+
+ count_leading_zeros (ret, x);
+
+ return ret;
+}
+#endif
+
+#ifdef L_clzdi2
+#undef int
+int
+__clzDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype word;
+ Wtype ret, add;
+
+ if (uu.s.high)
+ word = uu.s.high, add = 0;
+ else
+ word = uu.s.low, add = W_TYPE_SIZE;
+
+ count_leading_zeros (ret, word);
+ return ret + add;
+}
+#endif
+
+#ifdef L_ctzsi2
+#undef int
+int
+__ctzSI2 (UWtype x)
+{
+ Wtype ret;
+
+ count_trailing_zeros (ret, x);
+
+ return ret;
+}
+#endif
+
+#ifdef L_ctzdi2
+#undef int
+int
+__ctzDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype word;
+ Wtype ret, add;
+
+ if (uu.s.low)
+ word = uu.s.low, add = 0;
+ else
+ word = uu.s.high, add = W_TYPE_SIZE;
+
+ count_trailing_zeros (ret, word);
+ return ret + add;
+}
+#endif
+
+#ifdef L_clrsbsi2
+#undef int
+int
+__clrsbSI2 (Wtype x)
+{
+ Wtype ret;
+
+ if (x < 0)
+ x = ~x;
+ if (x == 0)
+ return W_TYPE_SIZE - 1;
+ count_leading_zeros (ret, x);
+ return ret - 1;
+}
+#endif
+
+#ifdef L_clrsbdi2
+#undef int
+int
+__clrsbDI2 (DWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype word;
+ Wtype ret, add;
+
+ if (uu.s.high == 0)
+ word = uu.s.low, add = W_TYPE_SIZE;
+ else if (uu.s.high == -1)
+ word = ~uu.s.low, add = W_TYPE_SIZE;
+ else if (uu.s.high >= 0)
+ word = uu.s.high, add = 0;
+ else
+ word = ~uu.s.high, add = 0;
+
+ if (word == 0)
+ ret = W_TYPE_SIZE;
+ else
+ count_leading_zeros (ret, word);
+
+ return ret + add - 1;
+}
+#endif
+
+#ifdef L_popcount_tab
+const UQItype __popcount_tab[256] =
+{
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+};
+#endif
+
+#ifdef L_popcountsi2
+#undef int
+int
+__popcountSI2 (UWtype x)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < W_TYPE_SIZE; i += 8)
+ ret += __popcount_tab[(x >> i) & 0xff];
+
+ return ret;
+}
+#endif
+
+#ifdef L_popcountdi2
+#undef int
+int
+__popcountDI2 (UDWtype x)
+{
+ int i, ret = 0;
+
+ for (i = 0; i < 2*W_TYPE_SIZE; i += 8)
+ ret += __popcount_tab[(x >> i) & 0xff];
+
+ return ret;
+}
+#endif
+
+#ifdef L_paritysi2
+#undef int
+int
+__paritySI2 (UWtype x)
+{
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+ x ^= x >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+ x ^= x >> 16;
+#endif
+ x ^= x >> 8;
+ x ^= x >> 4;
+ x &= 0xf;
+ return (0x6996 >> x) & 1;
+}
+#endif
+
+#ifdef L_paritydi2
+#undef int
+int
+__parityDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype nx = uu.s.low ^ uu.s.high;
+
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+ nx ^= nx >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+ nx ^= nx >> 16;
+#endif
+ nx ^= nx >> 8;
+ nx ^= nx >> 4;
+ nx &= 0xf;
+ return (0x6996 >> nx) & 1;
+}
+#endif
+
+#ifdef L_udivmoddi4
+
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+ defined (L_umoddi3) || defined (L_moddi3))
+static inline __attribute__ ((__always_inline__))
+#endif
+UDWtype
+__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
+{
+ const DWunion nn = {.ll = n};
+ const DWunion dd = {.ll = d};
+ DWunion rr;
+ UWtype d0, d1, n0, n1, n2;
+ UWtype q0, q1;
+ UWtype b, bm;
+
+ d0 = dd.s.low;
+ d1 = dd.s.high;
+ n0 = nn.s.low;
+ n1 = nn.s.high;
+
+#if !UDIV_NEEDS_NORMALIZATION
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ udiv_qrnnd (q1, n1, 0, n1, d0);
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+
+#else /* UDIV_NEEDS_NORMALIZATION */
+
+ if (d1 == 0)
+ {
+ if (d0 > n1)
+ {
+ /* 0q = nn / 0D */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm != 0)
+ {
+ /* Normalize, i.e. make the most significant bit of the
+ denominator set. */
+
+ d0 = d0 << bm;
+ n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
+ n0 = n0 << bm;
+ }
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0 >> bm. */
+ }
+ else
+ {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ count_leading_zeros (bm, d0);
+
+ if (bm == 0)
+ {
+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ leading quotient digit q1 = 1).
+
+ This special case is necessary, not an optimization.
+ (Shifts counts of W_TYPE_SIZE are undefined.) */
+
+ n1 -= d0;
+ q1 = 1;
+ }
+ else
+ {
+ /* Normalize. */
+
+ b = W_TYPE_SIZE - bm;
+
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q1, n1, n2, n1, d0);
+ }
+
+ /* n1 != d0... */
+
+ udiv_qrnnd (q0, n0, n1, n0, d0);
+
+ /* Remainder in n0 >> bm. */
+ }
+
+ if (rp != 0)
+ {
+ rr.s.low = n0 >> bm;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ }
+#endif /* UDIV_NEEDS_NORMALIZATION */
+
+ else
+ {
+ if (d1 > n1)
+ {
+ /* 00 = nn / DD */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* Remainder in n1n0. */
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ /* 0q = NN / dd */
+
+ count_leading_zeros (bm, d1);
+ if (bm == 0)
+ {
+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ quotient digit q0 = 0 or 1).
+
+ This special case is necessary, not an optimization. */
+
+ /* The condition on the next line takes advantage of that
+ n1 >= d1 (true due to program flow). */
+ if (n1 > d1 || n0 >= d0)
+ {
+ q0 = 1;
+ sub_ddmmss (n1, n0, n1, n0, d1, d0);
+ }
+ else
+ q0 = 0;
+
+ q1 = 0;
+
+ if (rp != 0)
+ {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ }
+ else
+ {
+ UWtype m1, m0;
+ /* Normalize. */
+
+ b = W_TYPE_SIZE - bm;
+
+ d1 = (d1 << bm) | (d0 >> b);
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd (q0, n1, n2, n1, d1);
+ umul_ppmm (m1, m0, q0, d0);
+
+ if (m1 > n1 || (m1 == n1 && m0 > n0))
+ {
+ q0--;
+ sub_ddmmss (m1, m0, m1, m0, d1, d0);
+ }
+
+ q1 = 0;
+
+ /* Remainder in (n1n0 - m1m0) >> bm. */
+ if (rp != 0)
+ {
+ sub_ddmmss (n1, n0, n1, n0, m1, m0);
+ rr.s.low = (n1 << b) | (n0 >> bm);
+ rr.s.high = n1 >> bm;
+ *rp = rr.ll;
+ }
+ }
+ }
+ }
+
+ const DWunion ww = {{.low = q0, .high = q1}};
+ return ww.ll;
+}
+#endif
+
+#ifdef L_divdi3
+DWtype
+__divdi3 (DWtype u, DWtype v)
+{
+ Wtype c = 0;
+ DWunion uu = {.ll = u};
+ DWunion vv = {.ll = v};
+ DWtype w;
+
+ if (uu.s.high < 0)
+ c = ~c,
+ uu.ll = -uu.ll;
+ if (vv.s.high < 0)
+ c = ~c,
+ vv.ll = -vv.ll;
+
+ w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
+ if (c)
+ w = -w;
+
+ return w;
+}
+#endif
+
+#ifdef L_moddi3
+DWtype
+__moddi3 (DWtype u, DWtype v)
+{
+ Wtype c = 0;
+ DWunion uu = {.ll = u};
+ DWunion vv = {.ll = v};
+ DWtype w;
+
+ if (uu.s.high < 0)
+ c = ~c,
+ uu.ll = -uu.ll;
+ if (vv.s.high < 0)
+ vv.ll = -vv.ll;
+
+ (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
+ if (c)
+ w = -w;
+
+ return w;
+}
+#endif
+
+#ifdef L_umoddi3
+UDWtype
+__umoddi3 (UDWtype u, UDWtype v)
+{
+ UDWtype w;
+
+ (void) __udivmoddi4 (u, v, &w);
+
+ return w;
+}
+#endif
+
+#ifdef L_udivdi3
+UDWtype
+__udivdi3 (UDWtype n, UDWtype d)
+{
+ return __udivmoddi4 (n, d, (UDWtype *) 0);
+}
+#endif
+
+#ifdef L_cmpdi2
+cmp_return_type
+__cmpdi2 (DWtype a, DWtype b)
+{
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
+
+ if (au.s.high < bu.s.high)
+ return 0;
+ else if (au.s.high > bu.s.high)
+ return 2;
+ if ((UWtype) au.s.low < (UWtype) bu.s.low)
+ return 0;
+ else if ((UWtype) au.s.low > (UWtype) bu.s.low)
+ return 2;
+ return 1;
+}
+#endif
+
+#ifdef L_ucmpdi2
+cmp_return_type
+__ucmpdi2 (DWtype a, DWtype b)
+{
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
+
+ if ((UWtype) au.s.high < (UWtype) bu.s.high)
+ return 0;
+ else if ((UWtype) au.s.high > (UWtype) bu.s.high)
+ return 2;
+ if ((UWtype) au.s.low < (UWtype) bu.s.low)
+ return 0;
+ else if ((UWtype) au.s.low > (UWtype) bu.s.low)
+ return 2;
+ return 1;
+}
+#endif
+
+#if defined(L_fixunstfdi) && LIBGCC2_HAS_TF_MODE
+UDWtype
+__fixunstfDI (TFtype a)
+{
+ if (a < 0)
+ return 0;
+
+ /* Compute high word of result, as a flonum. */
+ const TFtype b = (a / Wtype_MAXp1_F);
+ /* Convert that to fixed (but not to DWtype!),
+ and shift it into the high word. */
+ UDWtype v = (UWtype) b;
+ v <<= W_TYPE_SIZE;
+ /* Remove high part from the TFtype, leaving the low part as flonum. */
+ a -= (TFtype)v;
+ /* Convert that to fixed (but not to DWtype!) and add it in.
+ Sometimes A comes out negative. This is significant, since
+ A has more bits than a long int does. */
+ if (a < 0)
+ v -= (UWtype) (- a);
+ else
+ v += (UWtype) a;
+ return v;
+}
+#endif
+
+#if defined(L_fixtfdi) && LIBGCC2_HAS_TF_MODE
+DWtype
+__fixtfdi (TFtype a)
+{
+ if (a < 0)
+ return - __fixunstfDI (-a);
+ return __fixunstfDI (a);
+}
+#endif
+
+#if defined(L_fixunsxfdi) && LIBGCC2_HAS_XF_MODE
+UDWtype
+__fixunsxfDI (XFtype a)
+{
+ if (a < 0)
+ return 0;
+
+ /* Compute high word of result, as a flonum. */
+ const XFtype b = (a / Wtype_MAXp1_F);
+ /* Convert that to fixed (but not to DWtype!),
+ and shift it into the high word. */
+ UDWtype v = (UWtype) b;
+ v <<= W_TYPE_SIZE;
+ /* Remove high part from the XFtype, leaving the low part as flonum. */
+ a -= (XFtype)v;
+ /* Convert that to fixed (but not to DWtype!) and add it in.
+ Sometimes A comes out negative. This is significant, since
+ A has more bits than a long int does. */
+ if (a < 0)
+ v -= (UWtype) (- a);
+ else
+ v += (UWtype) a;
+ return v;
+}
+#endif
+
+#if defined(L_fixxfdi) && LIBGCC2_HAS_XF_MODE
+DWtype
+__fixxfdi (XFtype a)
+{
+ if (a < 0)
+ return - __fixunsxfDI (-a);
+ return __fixunsxfDI (a);
+}
+#endif
+
+#if defined(L_fixunsdfdi) && LIBGCC2_HAS_DF_MODE
+UDWtype
+__fixunsdfDI (DFtype a)
+{
+ /* Get high part of result. The division here will just moves the radix
+ point and will not cause any rounding. Then the conversion to integral
+ type chops result as desired. */
+ const UWtype hi = a / Wtype_MAXp1_F;
+
+ /* Get low part of result. Convert `hi' to floating type and scale it back,
+ then subtract this from the number being converted. This leaves the low
+ part. Convert that to integral type. */
+ const UWtype lo = a - (DFtype) hi * Wtype_MAXp1_F;
+
+ /* Assemble result from the two parts. */
+ return ((UDWtype) hi << W_TYPE_SIZE) | lo;
+}
+#endif
+
+#if defined(L_fixdfdi) && LIBGCC2_HAS_DF_MODE
+DWtype
+__fixdfdi (DFtype a)
+{
+ if (a < 0)
+ return - __fixunsdfDI (-a);
+ return __fixunsdfDI (a);
+}
+#endif
+
+#if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE
+UDWtype
+__fixunssfDI (SFtype a)
+{
+#if LIBGCC2_HAS_DF_MODE
+ /* Convert the SFtype to a DFtype, because that is surely not going
+ to lose any bits. Some day someone else can write a faster version
+ that avoids converting to DFtype, and verify it really works right. */
+ const DFtype dfa = a;
+
+ /* Get high part of result. The division here will just moves the radix
+ point and will not cause any rounding. Then the conversion to integral
+ type chops result as desired. */
+ const UWtype hi = dfa / Wtype_MAXp1_F;
+
+ /* Get low part of result. Convert `hi' to floating type and scale it back,
+ then subtract this from the number being converted. This leaves the low
+ part. Convert that to integral type. */
+ const UWtype lo = dfa - (DFtype) hi * Wtype_MAXp1_F;
+
+ /* Assemble result from the two parts. */
+ return ((UDWtype) hi << W_TYPE_SIZE) | lo;
+#elif FLT_MANT_DIG < W_TYPE_SIZE
+ if (a < 1)
+ return 0;
+ if (a < Wtype_MAXp1_F)
+ return (UWtype)a;
+ if (a < Wtype_MAXp1_F * Wtype_MAXp1_F)
+ {
+ /* Since we know that there are fewer significant bits in the SFmode
+ quantity than in a word, we know that we can convert out all the
+ significant bits in one step, and thus avoid losing bits. */
+
+ /* ??? This following loop essentially performs frexpf. If we could
+ use the real libm function, or poke at the actual bits of the fp
+ format, it would be significantly faster. */
+
+ UWtype shift = 0, counter;
+ SFtype msb;
+
+ a /= Wtype_MAXp1_F;
+ for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1)
+ {
+ SFtype counterf = (UWtype)1 << counter;
+ if (a >= counterf)
+ {
+ shift |= counter;
+ a /= counterf;
+ }
+ }
+
+ /* Rescale into the range of one word, extract the bits of that
+ one word, and shift the result into position. */
+ a *= Wtype_MAXp1_F;
+ counter = a;
+ return (DWtype)counter << shift;
+ }
+ return -1;
+#else
+# error
+#endif
+}
+#endif
+
+#if defined(L_fixsfdi) && LIBGCC2_HAS_SF_MODE
+DWtype
+__fixsfdi (SFtype a)
+{
+ if (a < 0)
+ return - __fixunssfDI (-a);
+ return __fixunssfDI (a);
+}
+#endif
+
+#if defined(L_floatdixf) && LIBGCC2_HAS_XF_MODE
+XFtype
+__floatdixf (DWtype u)
+{
+#if W_TYPE_SIZE > XF_SIZE
+# error
+#endif
+ XFtype d = (Wtype) (u >> W_TYPE_SIZE);
+ d *= Wtype_MAXp1_F;
+ d += (UWtype)u;
+ return d;
+}
+#endif
+
+#if defined(L_floatundixf) && LIBGCC2_HAS_XF_MODE
+XFtype
+__floatundixf (UDWtype u)
+{
+#if W_TYPE_SIZE > XF_SIZE
+# error
+#endif
+ XFtype d = (UWtype) (u >> W_TYPE_SIZE);
+ d *= Wtype_MAXp1_F;
+ d += (UWtype)u;
+ return d;
+}
+#endif
+
+#if defined(L_floatditf) && LIBGCC2_HAS_TF_MODE
+TFtype
+__floatditf (DWtype u)
+{
+#if W_TYPE_SIZE > TF_SIZE
+# error
+#endif
+ TFtype d = (Wtype) (u >> W_TYPE_SIZE);
+ d *= Wtype_MAXp1_F;
+ d += (UWtype)u;
+ return d;
+}
+#endif
+
+#if defined(L_floatunditf) && LIBGCC2_HAS_TF_MODE
+TFtype
+__floatunditf (UDWtype u)
+{
+#if W_TYPE_SIZE > TF_SIZE
+# error
+#endif
+ TFtype d = (UWtype) (u >> W_TYPE_SIZE);
+ d *= Wtype_MAXp1_F;
+ d += (UWtype)u;
+ return d;
+}
+#endif
+
+#if (defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE) \
+ || (defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE)
+#define DI_SIZE (W_TYPE_SIZE * 2)
+#define F_MODE_OK(SIZE) \
+ (SIZE < DI_SIZE \
+ && SIZE > (DI_SIZE - SIZE + FSSIZE) \
+ && !AVOID_FP_TYPE_CONVERSION(SIZE))
+#if defined(L_floatdisf)
+#define FUNC __floatdisf
+#define FSTYPE SFtype
+#define FSSIZE SF_SIZE
+#else
+#define FUNC __floatdidf
+#define FSTYPE DFtype
+#define FSSIZE DF_SIZE
+#endif
+
+FSTYPE
+FUNC (DWtype u)
+{
+#if FSSIZE >= W_TYPE_SIZE
+ /* When the word size is small, we never get any rounding error. */
+ FSTYPE f = (Wtype) (u >> W_TYPE_SIZE);
+ f *= Wtype_MAXp1_F;
+ f += (UWtype)u;
+ return f;
+#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \
+ || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \
+ || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
+
+#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE))
+# define FSIZE DF_SIZE
+# define FTYPE DFtype
+#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE))
+# define FSIZE XF_SIZE
+# define FTYPE XFtype
+#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
+# define FSIZE TF_SIZE
+# define FTYPE TFtype
+#else
+# error
+#endif
+
+#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE))
+
+ /* Protect against double-rounding error.
+ Represent any low-order bits, that might be truncated by a bit that
+ won't be lost. The bit can go in anywhere below the rounding position
+ of the FSTYPE. A fixed mask and bit position handles all usual
+ configurations. */
+ if (! (- ((DWtype) 1 << FSIZE) < u
+ && u < ((DWtype) 1 << FSIZE)))
+ {
+ if ((UDWtype) u & (REP_BIT - 1))
+ {
+ u &= ~ (REP_BIT - 1);
+ u |= REP_BIT;
+ }
+ }
+
+ /* Do the calculation in a wider type so that we don't lose any of
+ the precision of the high word while multiplying it. */
+ FTYPE f = (Wtype) (u >> W_TYPE_SIZE);
+ f *= Wtype_MAXp1_F;
+ f += (UWtype)u;
+ return (FSTYPE) f;
+#else
+#if FSSIZE >= W_TYPE_SIZE - 2
+# error
+#endif
+ /* Finally, the word size is larger than the number of bits in the
+ required FSTYPE, and we've got no suitable wider type. The only
+ way to avoid double rounding is to special case the
+ extraction. */
+
+ /* If there are no high bits set, fall back to one conversion. */
+ if ((Wtype)u == u)
+ return (FSTYPE)(Wtype)u;
+
+ /* Otherwise, find the power of two. */
+ Wtype hi = u >> W_TYPE_SIZE;
+ if (hi < 0)
+ hi = -hi;
+
+ UWtype count, shift;
+ count_leading_zeros (count, hi);
+
+ /* No leading bits means u == minimum. */
+ if (count == 0)
+ return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2));
+
+ shift = 1 + W_TYPE_SIZE - count;
+
+ /* Shift down the most significant bits. */
+ hi = u >> shift;
+
+ /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */
+ if ((UWtype)u << (W_TYPE_SIZE - shift))
+ hi |= 1;
+
+ /* Convert the one word of data, and rescale. */
+ FSTYPE f = hi, e;
+ if (shift == W_TYPE_SIZE)
+ e = Wtype_MAXp1_F;
+ /* The following two cases could be merged if we knew that the target
+ supported a native unsigned->float conversion. More often, we only
+ have a signed conversion, and have to add extra fixup code. */
+ else if (shift == W_TYPE_SIZE - 1)
+ e = Wtype_MAXp1_F / 2;
+ else
+ e = (Wtype)1 << shift;
+ return f * e;
+#endif
+}
+#endif
+
+#if (defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE) \
+ || (defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE)
+#define DI_SIZE (W_TYPE_SIZE * 2)
+#define F_MODE_OK(SIZE) \
+ (SIZE < DI_SIZE \
+ && SIZE > (DI_SIZE - SIZE + FSSIZE) \
+ && !AVOID_FP_TYPE_CONVERSION(SIZE))
+#if defined(L_floatundisf)
+#define FUNC __floatundisf
+#define FSTYPE SFtype
+#define FSSIZE SF_SIZE
+#else
+#define FUNC __floatundidf
+#define FSTYPE DFtype
+#define FSSIZE DF_SIZE
+#endif
+
+FSTYPE
+FUNC (UDWtype u)
+{
+#if FSSIZE >= W_TYPE_SIZE
+ /* When the word size is small, we never get any rounding error. */
+ FSTYPE f = (UWtype) (u >> W_TYPE_SIZE);
+ f *= Wtype_MAXp1_F;
+ f += (UWtype)u;
+ return f;
+#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \
+ || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \
+ || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
+
+#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE))
+# define FSIZE DF_SIZE
+# define FTYPE DFtype
+#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE))
+# define FSIZE XF_SIZE
+# define FTYPE XFtype
+#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE))
+# define FSIZE TF_SIZE
+# define FTYPE TFtype
+#else
+# error
+#endif
+
+#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE))
+
+ /* Protect against double-rounding error.
+ Represent any low-order bits, that might be truncated by a bit that
+ won't be lost. The bit can go in anywhere below the rounding position
+ of the FSTYPE. A fixed mask and bit position handles all usual
+ configurations. */
+ if (u >= ((UDWtype) 1 << FSIZE))
+ {
+ if ((UDWtype) u & (REP_BIT - 1))
+ {
+ u &= ~ (REP_BIT - 1);
+ u |= REP_BIT;
+ }
+ }
+
+ /* Do the calculation in a wider type so that we don't lose any of
+ the precision of the high word while multiplying it. */
+ FTYPE f = (UWtype) (u >> W_TYPE_SIZE);
+ f *= Wtype_MAXp1_F;
+ f += (UWtype)u;
+ return (FSTYPE) f;
+#else
+#if FSSIZE == W_TYPE_SIZE - 1
+# error
+#endif
+ /* Finally, the word size is larger than the number of bits in the
+ required FSTYPE, and we've got no suitable wider type. The only
+ way to avoid double rounding is to special case the
+ extraction. */
+
+ /* If there are no high bits set, fall back to one conversion. */
+ if ((UWtype)u == u)
+ return (FSTYPE)(UWtype)u;
+
+ /* Otherwise, find the power of two. */
+ UWtype hi = u >> W_TYPE_SIZE;
+
+ UWtype count, shift;
+ count_leading_zeros (count, hi);
+
+ shift = W_TYPE_SIZE - count;
+
+ /* Shift down the most significant bits. */
+ hi = u >> shift;
+
+ /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */
+ if ((UWtype)u << (W_TYPE_SIZE - shift))
+ hi |= 1;
+
+ /* Convert the one word of data, and rescale. */
+ FSTYPE f = hi, e;
+ if (shift == W_TYPE_SIZE)
+ e = Wtype_MAXp1_F;
+ /* The following two cases could be merged if we knew that the target
+ supported a native unsigned->float conversion. More often, we only
+ have a signed conversion, and have to add extra fixup code. */
+ else if (shift == W_TYPE_SIZE - 1)
+ e = Wtype_MAXp1_F / 2;
+ else
+ e = (Wtype)1 << shift;
+ return f * e;
+#endif
+}
+#endif
+
+#if defined(L_fixunsxfsi) && LIBGCC2_HAS_XF_MODE
+/* Reenable the normal types, in case limits.h needs them. */
+#undef char
+#undef short
+#undef int
+#undef long
+#undef unsigned
+#undef float
+#undef double
+#undef MIN
+#undef MAX
+#include <limits.h>
+
+UWtype
+__fixunsxfSI (XFtype a)
+{
+ if (a >= - (DFtype) Wtype_MIN)
+ return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+ return (Wtype) a;
+}
+#endif
+
+#if defined(L_fixunsdfsi) && LIBGCC2_HAS_DF_MODE
+/* Reenable the normal types, in case limits.h needs them. */
+#undef char
+#undef short
+#undef int
+#undef long
+#undef unsigned
+#undef float
+#undef double
+#undef MIN
+#undef MAX
+#include <limits.h>
+
+UWtype
+__fixunsdfSI (DFtype a)
+{
+ if (a >= - (DFtype) Wtype_MIN)
+ return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+ return (Wtype) a;
+}
+#endif
+
+#if defined(L_fixunssfsi) && LIBGCC2_HAS_SF_MODE
+/* Reenable the normal types, in case limits.h needs them. */
+#undef char
+#undef short
+#undef int
+#undef long
+#undef unsigned
+#undef float
+#undef double
+#undef MIN
+#undef MAX
+#include <limits.h>
+
+UWtype
+__fixunssfSI (SFtype a)
+{
+ if (a >= - (SFtype) Wtype_MIN)
+ return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+ return (Wtype) a;
+}
+#endif
+
+/* Integer power helper used from __builtin_powi for non-constant
+ exponents. */
+
+#if (defined(L_powisf2) && LIBGCC2_HAS_SF_MODE) \
+ || (defined(L_powidf2) && LIBGCC2_HAS_DF_MODE) \
+ || (defined(L_powixf2) && LIBGCC2_HAS_XF_MODE) \
+ || (defined(L_powitf2) && LIBGCC2_HAS_TF_MODE)
+# if defined(L_powisf2)
+# define TYPE SFtype
+# define NAME __powisf2
+# elif defined(L_powidf2)
+# define TYPE DFtype
+# define NAME __powidf2
+# elif defined(L_powixf2)
+# define TYPE XFtype
+# define NAME __powixf2
+# elif defined(L_powitf2)
+# define TYPE TFtype
+# define NAME __powitf2
+# endif
+
+#undef int
+#undef unsigned
+TYPE
+NAME (TYPE x, int m)
+{
+ unsigned int n = m < 0 ? -m : m;
+ TYPE y = n % 2 ? x : 1;
+ while (n >>= 1)
+ {
+ x = x * x;
+ if (n % 2)
+ y = y * x;
+ }
+ return m < 0 ? 1/y : y;
+}
+
+#endif
+
+#if ((defined(L_mulsc3) || defined(L_divsc3)) && LIBGCC2_HAS_SF_MODE) \
+ || ((defined(L_muldc3) || defined(L_divdc3)) && LIBGCC2_HAS_DF_MODE) \
+ || ((defined(L_mulxc3) || defined(L_divxc3)) && LIBGCC2_HAS_XF_MODE) \
+ || ((defined(L_multc3) || defined(L_divtc3)) && LIBGCC2_HAS_TF_MODE)
+
+#undef float
+#undef double
+#undef long
+
+#if defined(L_mulsc3) || defined(L_divsc3)
+# define MTYPE SFtype
+# define CTYPE SCtype
+# define MODE sc
+# define CEXT f
+# define NOTRUNC __FLT_EVAL_METHOD__ == 0
+#elif defined(L_muldc3) || defined(L_divdc3)
+# define MTYPE DFtype
+# define CTYPE DCtype
+# define MODE dc
+# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64
+# define CEXT l
+# define NOTRUNC 1
+# else
+# define CEXT
+# define NOTRUNC __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1
+# endif
+#elif defined(L_mulxc3) || defined(L_divxc3)
+# define MTYPE XFtype
+# define CTYPE XCtype
+# define MODE xc
+# define CEXT l
+# define NOTRUNC 1
+#elif defined(L_multc3) || defined(L_divtc3)
+# define MTYPE TFtype
+# define CTYPE TCtype
+# define MODE tc
+# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
+# define CEXT l
+# else
+# define CEXT LIBGCC2_TF_CEXT
+# endif
+# define NOTRUNC 1
+#else
+# error
+#endif
+
+#define CONCAT3(A,B,C) _CONCAT3(A,B,C)
+#define _CONCAT3(A,B,C) A##B##C
+
+#define CONCAT2(A,B) _CONCAT2(A,B)
+#define _CONCAT2(A,B) A##B
+
+/* All of these would be present in a full C99 implementation of <math.h>
+ and <complex.h>. Our problem is that only a few systems have such full
+ implementations. Further, libgcc_s.so isn't currently linked against
+ libm.so, and even for systems that do provide full C99, the extra overhead
+ of all programs using libgcc having to link against libm. So avoid it. */
+
+#define isnan(x) __builtin_expect ((x) != (x), 0)
+#define isfinite(x) __builtin_expect (!isnan((x) - (x)), 1)
+#define isinf(x) __builtin_expect (!isnan(x) & !isfinite(x), 0)
+
+#define INFINITY CONCAT2(__builtin_huge_val, CEXT) ()
+#define I 1i
+
+/* Helpers to make the following code slightly less gross. */
+#define COPYSIGN CONCAT2(__builtin_copysign, CEXT)
+#define FABS CONCAT2(__builtin_fabs, CEXT)
+
+/* Verify that MTYPE matches up with CEXT. */
+extern void *compile_type_assert[sizeof(INFINITY) == sizeof(MTYPE) ? 1 : -1];
+
+/* Ensure that we've lost any extra precision. */
+#if NOTRUNC
+# define TRUNC(x)
+#else
+# define TRUNC(x) __asm__ ("" : "=m"(x) : "m"(x))
+#endif
+
+#if defined(L_mulsc3) || defined(L_muldc3) \
+ || defined(L_mulxc3) || defined(L_multc3)
+
+CTYPE
+CONCAT3(__mul,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d)
+{
+ MTYPE ac, bd, ad, bc, x, y;
+ CTYPE res;
+
+ ac = a * c;
+ bd = b * d;
+ ad = a * d;
+ bc = b * c;
+
+ TRUNC (ac);
+ TRUNC (bd);
+ TRUNC (ad);
+ TRUNC (bc);
+
+ x = ac - bd;
+ y = ad + bc;
+
+ if (isnan (x) && isnan (y))
+ {
+ /* Recover infinities that computed as NaN + iNaN. */
+ _Bool recalc = 0;
+ if (isinf (a) || isinf (b))
+ {
+ /* z is infinite. "Box" the infinity and change NaNs in
+ the other factor to 0. */
+ a = COPYSIGN (isinf (a) ? 1 : 0, a);
+ b = COPYSIGN (isinf (b) ? 1 : 0, b);
+ if (isnan (c)) c = COPYSIGN (0, c);
+ if (isnan (d)) d = COPYSIGN (0, d);
+ recalc = 1;
+ }
+ if (isinf (c) || isinf (d))
+ {
+ /* w is infinite. "Box" the infinity and change NaNs in
+ the other factor to 0. */
+ c = COPYSIGN (isinf (c) ? 1 : 0, c);
+ d = COPYSIGN (isinf (d) ? 1 : 0, d);
+ if (isnan (a)) a = COPYSIGN (0, a);
+ if (isnan (b)) b = COPYSIGN (0, b);
+ recalc = 1;
+ }
+ if (!recalc
+ && (isinf (ac) || isinf (bd)
+ || isinf (ad) || isinf (bc)))
+ {
+ /* Recover infinities from overflow by changing NaNs to 0. */
+ if (isnan (a)) a = COPYSIGN (0, a);
+ if (isnan (b)) b = COPYSIGN (0, b);
+ if (isnan (c)) c = COPYSIGN (0, c);
+ if (isnan (d)) d = COPYSIGN (0, d);
+ recalc = 1;
+ }
+ if (recalc)
+ {
+ x = INFINITY * (a * c - b * d);
+ y = INFINITY * (a * d + b * c);
+ }
+ }
+
+ __real__ res = x;
+ __imag__ res = y;
+ return res;
+}
+#endif /* complex multiply */
+
+#if defined(L_divsc3) || defined(L_divdc3) \
+ || defined(L_divxc3) || defined(L_divtc3)
+
+CTYPE
+CONCAT3(__div,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d)
+{
+ MTYPE denom, ratio, x, y;
+ CTYPE res;
+
+ /* ??? We can get better behavior from logarithmic scaling instead of
+ the division. But that would mean starting to link libgcc against
+ libm. We could implement something akin to ldexp/frexp as gcc builtins
+ fairly easily... */
+ if (FABS (c) < FABS (d))
+ {
+ ratio = c / d;
+ denom = (c * ratio) + d;
+ x = ((a * ratio) + b) / denom;
+ y = ((b * ratio) - a) / denom;
+ }
+ else
+ {
+ ratio = d / c;
+ denom = (d * ratio) + c;
+ x = ((b * ratio) + a) / denom;
+ y = (b - (a * ratio)) / denom;
+ }
+
+ /* Recover infinities and zeros that computed as NaN+iNaN; the only cases
+ are nonzero/zero, infinite/finite, and finite/infinite. */
+ if (isnan (x) && isnan (y))
+ {
+ if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b)))
+ {
+ x = COPYSIGN (INFINITY, c) * a;
+ y = COPYSIGN (INFINITY, c) * b;
+ }
+ else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d))
+ {
+ a = COPYSIGN (isinf (a) ? 1 : 0, a);
+ b = COPYSIGN (isinf (b) ? 1 : 0, b);
+ x = INFINITY * (a * c + b * d);
+ y = INFINITY * (b * c - a * d);
+ }
+ else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b))
+ {
+ c = COPYSIGN (isinf (c) ? 1 : 0, c);
+ d = COPYSIGN (isinf (d) ? 1 : 0, d);
+ x = 0.0 * (a * c + b * d);
+ y = 0.0 * (b * c - a * d);
+ }
+ }
+
+ __real__ res = x;
+ __imag__ res = y;
+ return res;
+}
+#endif /* complex divide */
+
+#endif /* all complex float routines */
+
+/* From here on down, the routines use normal data types. */
+
+#define SItype bogus_type
+#define USItype bogus_type
+#define DItype bogus_type
+#define UDItype bogus_type
+#define SFtype bogus_type
+#define DFtype bogus_type
+#undef Wtype
+#undef UWtype
+#undef HWtype
+#undef UHWtype
+#undef DWtype
+#undef UDWtype
+
+#undef char
+#undef short
+#undef int
+#undef long
+#undef unsigned
+#undef float
+#undef double
+
+#ifdef L__gcc_bcmp
+
+/* Like bcmp except the sign is meaningful.
+ Result is negative if S1 is less than S2,
+ positive if S1 is greater, 0 if S1 and S2 are equal. */
+
+int
+__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
+{
+ while (size > 0)
+ {
+ const unsigned char c1 = *s1++, c2 = *s2++;
+ if (c1 != c2)
+ return c1 - c2;
+ size--;
+ }
+ return 0;
+}
+
+#endif
+
+/* __eprintf used to be used by GCC's private version of <assert.h>.
+ We no longer provide that header, but this routine remains in libgcc.a
+ for binary backward compatibility. Note that it is not included in
+ the shared version of libgcc. */
+#ifdef L_eprintf
+#ifndef inhibit_libc
+
+#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
+#include <stdio.h>
+
+void
+__eprintf (const char *string, const char *expression,
+ unsigned int line, const char *filename)
+{
+ fprintf (stderr, string, expression, line, filename);
+ fflush (stderr);
+ abort ();
+}
+
+#endif
+#endif
+
+
+#ifdef L_clear_cache
+/* Clear part of an instruction cache. */
+
+void
+__clear_cache (char *beg __attribute__((__unused__)),
+ char *end __attribute__((__unused__)))
+{
+#ifdef CLEAR_INSN_CACHE
+ CLEAR_INSN_CACHE (beg, end);
+#endif /* CLEAR_INSN_CACHE */
+}
+
+#endif /* L_clear_cache */
+
+#ifdef L_trampoline
+
+/* Jump to a trampoline, loading the static chain address. */
+
+#if defined(WINNT) && ! defined(__CYGWIN__)
+#include <windows.h>
+int getpagesize (void);
+int mprotect (char *,int, int);
+
+int
+getpagesize (void)
+{
+#ifdef _ALPHA_
+ return 8192;
+#else
+ return 4096;
+#endif
+}
+
+int
+mprotect (char *addr, int len, int prot)
+{
+ DWORD np, op;
+
+ if (prot == 7)
+ np = 0x40;
+ else if (prot == 5)
+ np = 0x20;
+ else if (prot == 4)
+ np = 0x10;
+ else if (prot == 3)
+ np = 0x04;
+ else if (prot == 1)
+ np = 0x02;
+ else if (prot == 0)
+ np = 0x01;
+ else
+ return -1;
+
+ if (VirtualProtect (addr, len, np, &op))
+ return 0;
+ else
+ return -1;
+}
+
+#endif /* WINNT && ! __CYGWIN__ */
+
+#ifdef TRANSFER_FROM_TRAMPOLINE
+TRANSFER_FROM_TRAMPOLINE
+#endif
+#endif /* L_trampoline */
+
+#ifndef __CYGWIN__
+#ifdef L__main
+
+#include "gbl-ctors.h"
+
+/* 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. */
+#ifndef NAME__MAIN
+#define NAME__MAIN "__main"
+#define SYMBOL__MAIN __main
+#endif
+
+#if defined (INIT_SECTION_ASM_OP) || defined (INIT_ARRAY_SECTION_ASM_OP)
+#undef HAS_INIT_SECTION
+#define HAS_INIT_SECTION
+#endif
+
+#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
+
+/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
+ code to run constructors. In that case, we need to handle EH here, too. */
+
+#ifdef EH_FRAME_SECTION_NAME
+#include "unwind-dw2-fde.h"
+extern unsigned char __EH_FRAME_BEGIN__[];
+#endif
+
+/* Run all the global destructors on exit from the program. */
+
+void
+__do_global_dtors (void)
+{
+#ifdef DO_GLOBAL_DTORS_BODY
+ DO_GLOBAL_DTORS_BODY;
+#else
+ static func_ptr *p = __DTOR_LIST__ + 1;
+ while (*p)
+ {
+ p++;
+ (*(p-1)) ();
+ }
+#endif
+#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
+ {
+ static int completed = 0;
+ if (! completed)
+ {
+ completed = 1;
+ __deregister_frame_info (__EH_FRAME_BEGIN__);
+ }
+ }
+#endif
+}
+#endif
+
+#ifndef HAS_INIT_SECTION
+/* Run all the global constructors on entry to the program. */
+
+void
+__do_global_ctors (void)
+{
+#ifdef EH_FRAME_SECTION_NAME
+ {
+ static struct object object;
+ __register_frame_info (__EH_FRAME_BEGIN__, &object);
+ }
+#endif
+ DO_GLOBAL_CTORS_BODY;
+ atexit (__do_global_dtors);
+}
+#endif /* no HAS_INIT_SECTION */
+
+#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
+/* Subroutine called automatically by `main'.
+ Compiling a global function named `main'
+ produces an automatic call to this function at the beginning.
+
+ 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. */
+
+extern void SYMBOL__MAIN (void);
+void
+SYMBOL__MAIN (void)
+{
+ /* Support recursive calls to `main': run initializers just once. */
+ static int initialized;
+ if (! initialized)
+ {
+ initialized = 1;
+ __do_global_ctors ();
+ }
+}
+#endif /* no HAS_INIT_SECTION or INVOKE__main */
+
+#endif /* L__main */
+#endif /* __CYGWIN__ */
+
+#ifdef L_ctors
+
+#include "gbl-ctors.h"
+
+/* Provide default definitions for the lists of constructors and
+ destructors, so that we don't get linker errors. These symbols are
+ intentionally bss symbols, so that gld and/or collect will provide
+ the right values. */
+
+/* We declare the lists here with two elements each,
+ so that they are valid empty lists if no other definition is loaded.
+
+ If we are using the old "set" extensions to have the gnu linker
+ collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
+ must be in the bss/common section.
+
+ Long term no port should use those extensions. But many still do. */
+#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
+#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
+func_ptr __CTOR_LIST__[2] = {0, 0};
+func_ptr __DTOR_LIST__[2] = {0, 0};
+#else
+func_ptr __CTOR_LIST__[2];
+func_ptr __DTOR_LIST__[2];
+#endif
+#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
+#endif /* L_ctors */
+#endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */
diff --git a/gcc/libgcc2.h b/libgcc/libgcc2.h
index 0c7d0e15623..0c7d0e15623 100644
--- a/gcc/libgcc2.h
+++ b/libgcc/libgcc2.h
diff --git a/libgcc/libgcov.c b/libgcc/libgcov.c
index b39ef49343f..26370c5948c 100644
--- a/libgcc/libgcov.c
+++ b/libgcc/libgcov.c
@@ -1,7 +1,7 @@
/* Routines required for instrumenting a program. */
/* Compile this one with gcc. */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010
+ 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
This file is part of GCC.
@@ -29,6 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#if defined(inhibit_libc)
#define IN_LIBGCOV (-1)
diff --git a/gcc/longlong.h b/libgcc/longlong.h
index 30cc2e337f3..30cc2e337f3 100644
--- a/gcc/longlong.h
+++ b/libgcc/longlong.h
diff --git a/gcc/config/memcmp.c b/libgcc/memcmp.c
index 2348afe1d27..2348afe1d27 100644
--- a/gcc/config/memcmp.c
+++ b/libgcc/memcmp.c
diff --git a/gcc/config/memcpy.c b/libgcc/memcpy.c
index 58b1e405627..58b1e405627 100644
--- a/gcc/config/memcpy.c
+++ b/libgcc/memcpy.c
diff --git a/gcc/config/memmove.c b/libgcc/memmove.c
index 13b340af6a0..13b340af6a0 100644
--- a/gcc/config/memmove.c
+++ b/libgcc/memmove.c
diff --git a/gcc/config/memset.c b/libgcc/memset.c
index 3e7025ee394..3e7025ee394 100644
--- a/gcc/config/memset.c
+++ b/libgcc/memset.c
diff --git a/libgcc/mkheader.sh b/libgcc/mkheader.sh
new file mode 100755
index 00000000000..69ea3704901
--- /dev/null
+++ b/libgcc/mkheader.sh
@@ -0,0 +1,41 @@
+#! /bin/sh
+
+# Copyright (C) 2001, 2002, 2006, 2007, 2010, 2011 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 3, 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 COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+
+# Print libgcc_tm.h to the standard output.
+# DEFINES and HEADERS are expected to be set in the environment.
+
+# Add multiple inclusion protection guard, part one.
+echo "#ifndef LIBGCC_TM_H"
+echo "#define LIBGCC_TM_H"
+
+# Generate the body of the file
+echo "/* Automatically generated by mkheader.sh. */"
+for def in $DEFINES; do
+ echo "#ifndef $def" | sed 's/=.*//'
+ echo "# define $def" | sed 's/=/ /'
+ echo "#endif"
+done
+
+for file in $HEADERS; do
+ echo "#include \"$file\""
+done
+
+# Add multiple inclusion protection guard, part two.
+echo "#endif /* LIBGCC_TM_H */"
diff --git a/gcc/mkmap-flat.awk b/libgcc/mkmap-flat.awk
index ec5e1fdf513..ec5e1fdf513 100644
--- a/gcc/mkmap-flat.awk
+++ b/libgcc/mkmap-flat.awk
diff --git a/gcc/mkmap-symver.awk b/libgcc/mkmap-symver.awk
index 4877e905147..4877e905147 100644
--- a/gcc/mkmap-symver.awk
+++ b/libgcc/mkmap-symver.awk
diff --git a/libgcc/siditi-object.mk b/libgcc/siditi-object.mk
index 69df8338f52..77699cb79ec 100644
--- a/libgcc/siditi-object.mk
+++ b/libgcc/siditi-object.mk
@@ -11,12 +11,12 @@ iter-labels := $(wordlist 2,$(words $(iter-labels)),$(iter-labels))
$o-size := $(firstword $(iter-sizes))
iter-sizes := $(wordlist 2,$(words $(iter-sizes)),$(iter-sizes))
-$o$(objext): %$(objext): $(gcc_srcdir)/libgcc2.c
- $(gcc_compile) -DL$($*-label) -c $(gcc_srcdir)/libgcc2.c $(vis_hide) \
+$o$(objext): %$(objext): $(srcdir)/libgcc2.c
+ $(gcc_compile) -DL$($*-label) -c $< $(vis_hide) \
-DLIBGCC2_UNITS_PER_WORD=$($*-size)
ifeq ($(enable_shared),yes)
-$(o)_s$(objext): %_s$(objext): $(gcc_srcdir)/libgcc2.c
- $(gcc_s_compile) -DL$($*-label) -c $(gcc_srcdir)/libgcc2.c \
+$(o)_s$(objext): %_s$(objext): $(srcdir)/libgcc2.c
+ $(gcc_s_compile) -DL$($*-label) -c $< \
-DLIBGCC2_UNITS_PER_WORD=$($*-size)
endif
diff --git a/gcc/config/udivmod.c b/libgcc/udivmod.c
index dc70de64fc7..dc70de64fc7 100644
--- a/gcc/config/udivmod.c
+++ b/libgcc/udivmod.c
diff --git a/gcc/config/udivmodsi4.c b/libgcc/udivmodsi4.c
index 39c030fa4df..39c030fa4df 100644
--- a/gcc/config/udivmodsi4.c
+++ b/libgcc/udivmodsi4.c
diff --git a/libgcc/unwind-arm-common.inc b/libgcc/unwind-arm-common.inc
index 04bfd8b7e57..0713056bd1d 100644
--- a/libgcc/unwind-arm-common.inc
+++ b/libgcc/unwind-arm-common.inc
@@ -583,7 +583,7 @@ __gnu_unwind_pr_common (_Unwind_State state,
uws.words_left = 0;
uws.bytes_left = 3;
}
- else
+ else if (id < 3)
{
uws.words_left = (uws.data >> 16) & 0xff;
uws.data <<= 16;
diff --git a/libgcc/unwind-dw2-fde-dip.c b/libgcc/unwind-dw2-fde-dip.c
index d8e3c0e934b..f57dc8c3925 100644
--- a/libgcc/unwind-dw2-fde-dip.c
+++ b/libgcc/unwind-dw2-fde-dip.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009, 2010
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Jakub Jelinek <jakub@redhat.com>.
@@ -38,6 +38,7 @@
#endif
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "dwarf2.h"
#include "unwind.h"
#define NO_BASE_OF_ENCODED_VALUE
diff --git a/libgcc/unwind-dw2-fde.c b/libgcc/unwind-dw2-fde.c
index 93d427165c4..7a783329f7c 100644
--- a/libgcc/unwind-dw2-fde.c
+++ b/libgcc/unwind-dw2-fde.c
@@ -1,6 +1,6 @@
/* Subroutines needed for unwinding stack frames for exception handling. */
/* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008,
- 2009, 2010 Free Software Foundation, Inc.
+ 2009, 2010, 2011 Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@cygnus.com>.
This file is part of GCC.
@@ -29,6 +29,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "dwarf2.h"
#include "unwind.h"
#define NO_BASE_OF_ENCODED_VALUE
diff --git a/libgcc/unwind-dw2.c b/libgcc/unwind-dw2.c
index 92aa233eb26..475ad00bf52 100644
--- a/libgcc/unwind-dw2.c
+++ b/libgcc/unwind-dw2.c
@@ -27,6 +27,7 @@
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "dwarf2.h"
#include "unwind.h"
#ifdef __USING_SJLJ_EXCEPTIONS__
diff --git a/libgcc/unwind-sjlj.c b/libgcc/unwind-sjlj.c
index c71e79858ee..1fc1c5d3dc9 100644
--- a/libgcc/unwind-sjlj.c
+++ b/libgcc/unwind-sjlj.c
@@ -1,6 +1,6 @@
/* SJLJ exception handling and frame unwind runtime interface routines.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006,
- 2009 Free Software Foundation, Inc.
+ 2009, 2011 Free Software Foundation, Inc.
This file is part of GCC.
@@ -27,6 +27,7 @@
#include "tsystem.h"
#include "coretypes.h"
#include "tm.h"
+#include "libgcc_tm.h"
#include "unwind.h"
#include "gthr.h"
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 4546c276dfa..264f196d9df 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,70 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makefile.am (AM_CPPFLAGS): Add
+ -I$(srcdir)/$(MULTISRCTOP)../libgcc, -I$(MULTIBUILDTOP)../libgcc.
+ * Makefile.in: Regenerate.
+ * acinclude.m4 (LIBGFOR_CHECK_GTHR_DEFAULT): Remove.
+ * configure.ac (LIBGFOR_CHECK_GTHR_DEFAULT): Likewise.
+ * configure: Regenerate.
+ * config.h.in: Regenerate.
+
+2011-11-01 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * io/io.h (next_available_newunit): Remove prototype.
+ * io/unit.h (next_available_newunit): Make variable static,
+ initialize it.
+ (init_units): Don't initialize next_available_newunit.
+ (get_unique_unit_number): Use atomic builtin if available.
+
+2011-10-31 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * io/inquire.c (inquire_via_unit): Check whether we're at the
+ beginning or end if the position is unspecified. If the position
+ is not one of the 3 standard ones, return unspecified.
+ * io/io.h (update_position): Remove prototype.
+ * io/transfer.c (next_record): Set the position to unspecified,
+ letting inquire figure it out more exactly when needed.
+ * io/unit.c (update_position): Remove function.
+
+2011-10-31 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * io/unix.h (struct stream): Add size function pointer.
+ (ssize): New inline function.
+ (file_length): Remove prototype.
+ * io/unix.c (raw_size): New function.
+ (raw_init): Initialize st.size pointer.
+ (buf_size): New function.
+ (buf_init): Initialize st.size pointer.
+ (open_internal): Likewise.
+ (open_internal4): Likewise.
+ (file_length): Remove function.
+ * io/file_pos.c (st_rewind): Use ssize instead of file_length.
+ * io/open.c (test_endfile): Likewise.
+ * io/transfer.c (data_transfer_init): Likewise.
+ (next_record_r): Likewise.
+ (next_record_w): Likewise.
+ * io/unit.c (update_position): Likewise.
+
+2011-10-31 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * io/file_pos.c (st_rewind): Handle regular and special files
+ identically.
+ * io/intrinsics.c (fseek_sub): Don't check whether we think the
+ file is seekable, just do what the caller says.
+ * io/transfer.c (skip_record): First try to seek, then fallback to
+ reading and throwing away what we read.
+ * io/unit.c (update_position): Don't check whether file is
+ seekable, just try to do what we're told.
+ (unit_truncate): Likewise.
+ * io/unix.c (struct unix_stream): Remove special_file flag.
+ (buf_flush): Remove code for handling unseekable files.
+ (buf_seek): Likewise.
+ (fd_to_stream): Use buffered IO only for regular files.
+ (file_length): Remove is_seekable() call.
+ (is_seekable): Remove function.
+ (is_special): Likewise.
+ * io/unix.h: Remove prototypes for is_seekable and is_special.
+
2011-09-10 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/49479
diff --git a/libgfortran/Makefile.am b/libgfortran/Makefile.am
index ce0d7250328..350b7161059 100644
--- a/libgfortran/Makefile.am
+++ b/libgfortran/Makefile.am
@@ -56,7 +56,9 @@ libcaf_single_la_LINK = $(LINK) $(libcaf_single_la_LDFLAGS)
## use -iquote
AM_CPPFLAGS = -iquote$(srcdir)/io -I$(srcdir)/$(MULTISRCTOP)../gcc \
-I$(srcdir)/$(MULTISRCTOP)../gcc/config $(LIBQUADINCLUDE) \
- -I$(MULTIBUILDTOP)../../$(host_subdir)/gcc
+ -I$(MULTIBUILDTOP)../../$(host_subdir)/gcc \
+ -I$(srcdir)/$(MULTISRCTOP)../libgcc \
+ -I$(MULTIBUILDTOP)../libgcc
# Fortran rules for complex multiplication and division
AM_CFLAGS += -fcx-fortran-rules
diff --git a/libgfortran/Makefile.in b/libgfortran/Makefile.in
index d41b7bb2b82..80a6c60968d 100644
--- a/libgfortran/Makefile.in
+++ b/libgfortran/Makefile.in
@@ -506,7 +506,9 @@ libcaf_single_la_DEPENDENCIES = caf/libcaf.h
libcaf_single_la_LINK = $(LINK) $(libcaf_single_la_LDFLAGS)
AM_CPPFLAGS = -iquote$(srcdir)/io -I$(srcdir)/$(MULTISRCTOP)../gcc \
-I$(srcdir)/$(MULTISRCTOP)../gcc/config $(LIBQUADINCLUDE) \
- -I$(MULTIBUILDTOP)../../$(host_subdir)/gcc
+ -I$(MULTIBUILDTOP)../../$(host_subdir)/gcc \
+ -I$(srcdir)/$(MULTISRCTOP)../libgcc \
+ -I$(MULTIBUILDTOP)../libgcc
gfor_io_src = \
io/close.c \
diff --git a/libgfortran/acinclude.m4 b/libgfortran/acinclude.m4
index 92e027177b5..b6cb40430af 100644
--- a/libgfortran/acinclude.m4
+++ b/libgfortran/acinclude.m4
@@ -83,17 +83,6 @@ if (foovar > 10) return __sync_add_and_fetch (&foovar, -1);]])],
[Define to 1 if the target supports __sync_fetch_and_add])
fi])
-dnl Check if threads are supported.
-AC_DEFUN([LIBGFOR_CHECK_GTHR_DEFAULT], [
- AC_CACHE_CHECK([configured target thread model],
- libgfor_cv_target_thread_file, [
-libgfor_cv_target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`])
-
- if test $libgfor_cv_target_thread_file != single; then
- AC_DEFINE(HAVE_GTHR_DEFAULT, 1,
- [Define if the compiler has a thread header that is non single.])
- fi])
-
dnl Check for pragma weak.
AC_DEFUN([LIBGFOR_GTHREAD_WEAK], [
AC_CACHE_CHECK([whether pragma weak works],
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index 57f66b51ab9..708ec7cd02d 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -483,9 +483,6 @@
/* Define to 1 if you have the `gmtime_r' function. */
#undef HAVE_GMTIME_R
-/* Define if the compiler has a thread header that is non single. */
-#undef HAVE_GTHR_DEFAULT
-
/* libm includes hypot */
#undef HAVE_HYPOT
diff --git a/libgfortran/configure b/libgfortran/configure
index a716ff37faf..3a1174a1237 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -25704,25 +25704,6 @@ $as_echo "#define HAVE_SYNC_FETCH_AND_ADD 1" >>confdefs.h
fi
-# Check out thread support.
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking configured target thread model" >&5
-$as_echo_n "checking configured target thread model... " >&6; }
-if test "${libgfor_cv_target_thread_file+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
-
-libgfor_cv_target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgfor_cv_target_thread_file" >&5
-$as_echo "$libgfor_cv_target_thread_file" >&6; }
-
- if test $libgfor_cv_target_thread_file != single; then
-
-$as_echo "#define HAVE_GTHR_DEFAULT 1" >>confdefs.h
-
- fi
-
# Check out #pragma weak.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pragma weak works" >&5
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index 74cfe441a75..447ea9df998 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -550,9 +550,6 @@ LIBGFOR_CHECK_ATTRIBUTE_ALIAS
# Check out sync builtins support.
LIBGFOR_CHECK_SYNC_FETCH_AND_ADD
-# Check out thread support.
-LIBGFOR_CHECK_GTHR_DEFAULT
-
# Check out #pragma weak.
LIBGFOR_GTHREAD_WEAK
diff --git a/libgfortran/io/file_pos.c b/libgfortran/io/file_pos.c
index b034f382557..c8ecc3ad66e 100644
--- a/libgfortran/io/file_pos.c
+++ b/libgfortran/io/file_pos.c
@@ -407,20 +407,15 @@ st_rewind (st_parameter_filepos *fpp)
if (sseek (u->s, 0, SEEK_SET) < 0)
generate_error (&fpp->common, LIBERROR_OS, NULL);
- /* Handle special files like /dev/null differently. */
- if (!is_special (u->s))
+ /* Set this for compatibilty with g77 for /dev/null. */
+ if (ssize (u->s) == 0)
+ u->endfile = AT_ENDFILE;
+ else
{
/* We are rewinding so we are not at the end. */
u->endfile = NO_ENDFILE;
}
- else
- {
- /* Set this for compatibilty with g77 for /dev/null. */
- if (file_length (u->s) == 0 && stell (u->s) == 0)
- u->endfile = AT_ENDFILE;
- /* Future refinements on special files can go here. */
- }
-
+
u->current_record = 0;
u->strm_pos = 1;
u->read_bad = 0;
diff --git a/libgfortran/io/inquire.c b/libgfortran/io/inquire.c
index 252f29f0aef..fb525caf863 100644
--- a/libgfortran/io/inquire.c
+++ b/libgfortran/io/inquire.c
@@ -418,24 +418,36 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit * u)
if (u == NULL || u->flags.access == ACCESS_DIRECT)
p = undefined;
else
- switch (u->flags.position)
- {
- case POSITION_REWIND:
- p = "REWIND";
- break;
- case POSITION_APPEND:
- p = "APPEND";
- break;
- case POSITION_ASIS:
- p = "ASIS";
- break;
- default:
- /* if not direct access, it must be
- either REWIND, APPEND, or ASIS.
- ASIS seems to be the best default */
- p = "ASIS";
- break;
- }
+ {
+ /* If the position is unspecified, check if we can figure
+ out whether it's at the beginning or end. */
+ if (u->flags.position == POSITION_UNSPECIFIED)
+ {
+ gfc_offset cur = stell (u->s);
+ if (cur == 0)
+ u->flags.position = POSITION_REWIND;
+ else if (cur != -1 && (ssize (u->s) == cur))
+ u->flags.position = POSITION_APPEND;
+ }
+ switch (u->flags.position)
+ {
+ case POSITION_REWIND:
+ p = "REWIND";
+ break;
+ case POSITION_APPEND:
+ p = "APPEND";
+ break;
+ case POSITION_ASIS:
+ p = "ASIS";
+ break;
+ default:
+ /* If the position has changed and is not rewind or
+ append, it must be set to a processor-dependent
+ value. */
+ p = "UNSPECIFIED";
+ break;
+ }
+ }
cf_strcpy (iqp->position, iqp->position_len, p);
}
diff --git a/libgfortran/io/intrinsics.c b/libgfortran/io/intrinsics.c
index f48bd777456..c1287d4bd23 100644
--- a/libgfortran/io/intrinsics.c
+++ b/libgfortran/io/intrinsics.c
@@ -246,7 +246,7 @@ fseek_sub (int * unit, GFC_IO_INT * offset, int * whence, int * status)
gfc_unit * u = find_unit (*unit);
ssize_t result = -1;
- if (u != NULL && is_seekable(u->s))
+ if (u != NULL)
{
result = sseek(u->s, *offset, *whence);
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 37353d742e8..5270fd7c0b4 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+ 2011
Free Software Foundation, Inc.
Contributed by Andy Vaught
F2003 I/O support contributed by Jerry DeLisle
@@ -576,10 +577,6 @@ gfc_unit;
extern gfc_offset max_offset;
internal_proto(max_offset);
-/* Unit number to be assigned when NEWUNIT is used in an OPEN statement. */
-extern GFC_INTEGER_4 next_available_newunit;
-internal_proto(next_available_newunit);
-
/* Unit tree root. */
extern gfc_unit *unit_root;
internal_proto(unit_root);
@@ -608,9 +605,6 @@ internal_proto(get_unit);
extern void unlock_unit (gfc_unit *);
internal_proto(unlock_unit);
-extern void update_position (gfc_unit *);
-internal_proto(update_position);
-
extern void finish_last_advance_record (gfc_unit *u);
internal_proto (finish_last_advance_record);
diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c
index b26d14d8069..0102b9cf99f 100644
--- a/libgfortran/io/open.c
+++ b/libgfortran/io/open.c
@@ -153,7 +153,7 @@ static const st_option async_opt[] =
static void
test_endfile (gfc_unit * u)
{
- if (u->endfile == NO_ENDFILE && file_length (u->s) == stell (u->s))
+ if (u->endfile == NO_ENDFILE && ssize (u->s) == stell (u->s))
u->endfile = AT_ENDFILE;
}
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 12aca9779b6..062f80efec4 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -2627,7 +2627,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
a partial record needs to exist. */
if (dtp->u.p.mode == READING && (dtp->rec - 1)
- * dtp->u.p.current_unit->recl >= file_length (dtp->u.p.current_unit->s))
+ * dtp->u.p.current_unit->recl >= ssize (dtp->u.p.current_unit->s))
{
generate_error (&dtp->common, LIBERROR_BAD_OPTION,
"Non-existing record number");
@@ -2823,18 +2823,12 @@ skip_record (st_parameter_dt *dtp, ssize_t bytes)
if (dtp->u.p.current_unit->bytes_left_subrecord == 0)
return;
- if (is_seekable (dtp->u.p.current_unit->s))
+ /* Direct access files do not generate END conditions,
+ only I/O errors. */
+ if (sseek (dtp->u.p.current_unit->s,
+ dtp->u.p.current_unit->bytes_left_subrecord, SEEK_CUR) < 0)
{
- /* Direct access files do not generate END conditions,
- only I/O errors. */
- if (sseek (dtp->u.p.current_unit->s,
- dtp->u.p.current_unit->bytes_left_subrecord, SEEK_CUR) < 0)
- generate_error (&dtp->common, LIBERROR_OS, NULL);
-
- dtp->u.p.current_unit->bytes_left_subrecord = 0;
- }
- else
- { /* Seek by reading data. */
+ /* Seeking failed, fall back to seeking by reading data. */
while (dtp->u.p.current_unit->bytes_left_subrecord > 0)
{
rlength =
@@ -2850,8 +2844,9 @@ skip_record (st_parameter_dt *dtp, ssize_t bytes)
dtp->u.p.current_unit->bytes_left_subrecord -= readb;
}
+ return;
}
-
+ dtp->u.p.current_unit->bytes_left_subrecord = 0;
}
@@ -2949,7 +2944,7 @@ next_record_r (st_parameter_dt *dtp, int done)
{
bytes_left = (int) dtp->u.p.current_unit->bytes_left;
bytes_left = min_off (bytes_left,
- file_length (dtp->u.p.current_unit->s)
+ ssize (dtp->u.p.current_unit->s)
- stell (dtp->u.p.current_unit->s));
if (sseek (dtp->u.p.current_unit->s,
bytes_left, SEEK_CUR) < 0)
@@ -3314,7 +3309,7 @@ next_record_w (st_parameter_dt *dtp, int done)
{
dtp->u.p.current_unit->strm_pos += len;
if (dtp->u.p.current_unit->strm_pos
- < file_length (dtp->u.p.current_unit->s))
+ < ssize (dtp->u.p.current_unit->s))
unit_truncate (dtp->u.p.current_unit,
dtp->u.p.current_unit->strm_pos - 1,
&dtp->common);
@@ -3348,9 +3343,10 @@ next_record (st_parameter_dt *dtp, int done)
if (!is_stream_io (dtp))
{
- /* Keep position up to date for INQUIRE */
+ /* Since we have changed the position, set it to unspecified so
+ that INQUIRE(POSITION=) knows it needs to look into it. */
if (done)
- update_position (dtp->u.p.current_unit);
+ dtp->u.p.current_unit->flags.position = POSITION_UNSPECIFIED;
dtp->u.p.current_unit->current_record = 0;
if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT)
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index e8a9b848367..7c71b090e3a 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005, 2007, 2008, 2009, 2010
+/* Copyright (C) 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Andy Vaught
F2003 I/O support contributed by Jerry DeLisle
@@ -71,8 +71,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Subroutines related to units */
-GFC_INTEGER_4 next_available_newunit;
+/* Unit number to be assigned when NEWUNIT is used in an OPEN statement. */
#define GFC_FIRST_NEWUNIT -10
+static GFC_INTEGER_4 next_available_newunit = GFC_FIRST_NEWUNIT;
#define CACHE_SIZE 3
static gfc_unit *unit_cache[CACHE_SIZE];
@@ -525,8 +526,6 @@ init_units (void)
__GTHREAD_MUTEX_INIT_FUNCTION (&unit_lock);
#endif
- next_available_newunit = GFC_FIRST_NEWUNIT;
-
if (options.stdin_unit >= 0)
{ /* STDIN */
u = insert_unit (options.stdin_unit);
@@ -706,31 +705,9 @@ close_units (void)
}
-/* update_position()-- Update the flags position for later use by inquire. */
-
-void
-update_position (gfc_unit *u)
-{
- /* If unit is not seekable, this makes no sense (and the standard is
- silent on this matter), and thus we don't change the position for
- a non-seekable file. */
- if (is_seekable (u->s))
- {
- gfc_offset cur = stell (u->s);
- if (cur == 0)
- u->flags.position = POSITION_REWIND;
- else if (cur != -1 && (file_length (u->s) == cur))
- u->flags.position = POSITION_APPEND;
- else
- u->flags.position = POSITION_ASIS;
- }
-}
-
-
-/* High level interface to truncate a file safely, i.e. flush format
- buffers, check that it's a regular file, and generate error if that
- occurs. Just like POSIX ftruncate, returns 0 on success, -1 on
- failure. */
+/* High level interface to truncate a file, i.e. flush format buffers,
+ and generate an error or set some flags. Just like POSIX
+ ftruncate, returns 0 on success, -1 on failure. */
int
unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
@@ -746,24 +723,12 @@ unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
fbuf_flush (u, u->mode);
}
- /* Don't try to truncate a special file, just pretend that it
- succeeds. */
- if (is_special (u->s) || !is_seekable (u->s))
- {
- sflush (u->s);
- return 0;
- }
-
/* struncate() should flush the stream buffer if necessary, so don't
bother calling sflush() here. */
ret = struncate (u->s, pos);
if (ret != 0)
- {
- generate_error (common, LIBERROR_OS, NULL);
- u->endfile = NO_ENDFILE;
- u->flags.position = POSITION_ASIS;
- }
+ generate_error (common, LIBERROR_OS, NULL);
else
{
u->endfile = AT_ENDFILE;
@@ -842,16 +807,19 @@ get_unique_unit_number (st_parameter_open *opp)
{
GFC_INTEGER_4 num;
+#ifdef HAVE_SYNC_FETCH_AND_ADD
+ num = __sync_fetch_and_add (&next_available_newunit, -1);
+#else
__gthread_mutex_lock (&unit_lock);
num = next_available_newunit--;
+ __gthread_mutex_unlock (&unit_lock);
+#endif
/* Do not allow NEWUNIT numbers to wrap. */
- if (next_available_newunit >= GFC_FIRST_NEWUNIT )
+ if (num > GFC_FIRST_NEWUNIT)
{
- __gthread_mutex_unlock (&unit_lock);
generate_error (&opp->common, LIBERROR_INTERNAL, "NEWUNIT exhausted");
return 0;
}
- __gthread_mutex_unlock (&unit_lock);
return num;
}
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 25cb559db01..c87be134a69 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -187,7 +187,7 @@ typedef struct
gfc_offset buffer_offset; /* File offset of the start of the buffer */
gfc_offset physical_offset; /* Current physical file offset */
gfc_offset logical_offset; /* Current logical file offset */
- gfc_offset file_length; /* Length of the file, -1 if not seekable. */
+ gfc_offset file_length; /* Length of the file. */
char *buffer; /* Pointer to the buffer. */
int fd; /* The POSIX file descriptor. */
@@ -196,8 +196,6 @@ typedef struct
int ndirty; /* Dirty bytes starting at buffer_offset */
- int special_file; /* =1 if the fd refers to a special file */
-
/* Cached stat(2) values. */
dev_t st_dev;
ino_t st_ino;
@@ -334,6 +332,16 @@ raw_tell (unix_stream * s)
return lseek (s->fd, 0, SEEK_CUR);
}
+static gfc_offset
+raw_size (unix_stream * s)
+{
+ struct stat statbuf;
+ int ret = fstat (s->fd, &statbuf);
+ if (ret == -1)
+ return ret;
+ return statbuf.st_size;
+}
+
static int
raw_truncate (unix_stream * s, gfc_offset length)
{
@@ -400,6 +408,7 @@ raw_init (unix_stream * s)
s->st.write = (void *) raw_write;
s->st.seek = (void *) raw_seek;
s->st.tell = (void *) raw_tell;
+ s->st.size = (void *) raw_size;
s->st.trunc = (void *) raw_truncate;
s->st.close = (void *) raw_close;
s->st.flush = (void *) raw_flush;
@@ -413,7 +422,7 @@ raw_init (unix_stream * s)
Buffered I/O functions. These functions have the same semantics as the
raw I/O functions above, except that they are buffered in order to
improve performance. The buffer must be flushed when switching from
-reading to writing and vice versa.
+reading to writing and vice versa. Only supported for regular files.
*********************************************************************/
static int
@@ -427,7 +436,7 @@ buf_flush (unix_stream * s)
if (s->ndirty == 0)
return 0;
- if (s->file_length != -1 && s->physical_offset != s->buffer_offset
+ if (s->physical_offset != s->buffer_offset
&& lseek (s->fd, s->buffer_offset, SEEK_SET) < 0)
return -1;
@@ -435,8 +444,7 @@ buf_flush (unix_stream * s)
s->physical_offset = s->buffer_offset + writelen;
- /* Don't increment file_length if the file is non-seekable. */
- if (s->file_length != -1 && s->physical_offset > s->file_length)
+ if (s->physical_offset > s->file_length)
s->file_length = s->physical_offset;
s->ndirty -= writelen;
@@ -481,7 +489,7 @@ buf_read (unix_stream * s, void * buf, ssize_t nbyte)
/* At this point we consider all bytes in the buffer discarded. */
to_read = nbyte - nread;
new_logical = s->logical_offset + nread;
- if (s->file_length != -1 && s->physical_offset != new_logical
+ if (s->physical_offset != new_logical
&& lseek (s->fd, new_logical, SEEK_SET) < 0)
return -1;
s->buffer_offset = s->physical_offset = new_logical;
@@ -539,7 +547,7 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
}
else
{
- if (s->file_length != -1 && s->physical_offset != s->logical_offset)
+ if (s->physical_offset != s->logical_offset)
{
if (lseek (s->fd, s->logical_offset, SEEK_SET) < 0)
return -1;
@@ -551,8 +559,7 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
}
}
s->logical_offset += nbyte;
- /* Don't increment file_length if the file is non-seekable. */
- if (s->file_length != -1 && s->logical_offset > s->file_length)
+ if (s->logical_offset > s->file_length)
s->file_length = s->logical_offset;
return nbyte;
}
@@ -560,11 +567,6 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte)
static gfc_offset
buf_seek (unix_stream * s, gfc_offset offset, int whence)
{
- if (s->file_length == -1)
- {
- errno = ESPIPE;
- return -1;
- }
switch (whence)
{
case SEEK_SET:
@@ -593,6 +595,12 @@ buf_tell (unix_stream * s)
return buf_seek (s, 0, SEEK_CUR);
}
+static gfc_offset
+buf_size (unix_stream * s)
+{
+ return s->file_length;
+}
+
static int
buf_truncate (unix_stream * s, gfc_offset length)
{
@@ -622,6 +630,7 @@ buf_init (unix_stream * s)
s->st.write = (void *) buf_write;
s->st.seek = (void *) buf_seek;
s->st.tell = (void *) buf_tell;
+ s->st.size = (void *) buf_size;
s->st.trunc = (void *) buf_truncate;
s->st.close = (void *) buf_close;
s->st.flush = (void *) buf_flush;
@@ -893,6 +902,9 @@ open_internal (char *base, int length, gfc_offset offset)
s->st.close = (void *) mem_close;
s->st.seek = (void *) mem_seek;
s->st.tell = (void *) mem_tell;
+ /* buf_size is not a typo, we just reuse an identical
+ implementation. */
+ s->st.size = (void *) buf_size;
s->st.trunc = (void *) mem_truncate;
s->st.read = (void *) mem_read;
s->st.write = (void *) mem_write;
@@ -921,6 +933,9 @@ open_internal4 (char *base, int length, gfc_offset offset)
s->st.close = (void *) mem_close;
s->st.seek = (void *) mem_seek;
s->st.tell = (void *) mem_tell;
+ /* buf_size is not a typo, we just reuse an identical
+ implementation. */
+ s->st.size = (void *) buf_size;
s->st.trunc = (void *) mem_truncate;
s->st.read = (void *) mem_read4;
s->st.write = (void *) mem_write4;
@@ -953,30 +968,18 @@ fd_to_stream (int fd)
s->st_dev = statbuf.st_dev;
s->st_ino = statbuf.st_ino;
- s->special_file = !S_ISREG (statbuf.st_mode);
-
- if (S_ISREG (statbuf.st_mode))
- s->file_length = statbuf.st_size;
+ s->file_length = statbuf.st_size;
+
+ /* Only use buffered IO for regular files. */
+ if (S_ISREG (statbuf.st_mode)
+ && !options.all_unbuffered
+ && !(options.unbuffered_preconnected &&
+ (s->fd == STDIN_FILENO
+ || s->fd == STDOUT_FILENO
+ || s->fd == STDERR_FILENO)))
+ buf_init (s);
else
- {
- /* Some character special files are seekable but most are not,
- so figure it out by trying to seek. On Linux, /dev/null is
- an example of such a special file. */
- s->file_length = lseek (fd, 0, SEEK_END);
- if (s->file_length > 0)
- lseek (fd, 0, SEEK_SET);
- }
-
- if (!(S_ISREG (statbuf.st_mode) || S_ISBLK (statbuf.st_mode))
- || options.all_unbuffered
- ||(options.unbuffered_preconnected &&
- (s->fd == STDIN_FILENO
- || s->fd == STDOUT_FILENO
- || s->fd == STDERR_FILENO))
- || isatty (s->fd))
raw_init (s);
- else
- buf_init (s);
return (stream *) s;
}
@@ -1761,44 +1764,6 @@ inquire_readwrite (const char *string, int len)
}
-/* file_length()-- Return the file length in bytes, -1 if unknown */
-
-gfc_offset
-file_length (stream * s)
-{
- gfc_offset curr, end;
- if (!is_seekable (s))
- return -1;
- curr = stell (s);
- if (curr == -1)
- return curr;
- end = sseek (s, 0, SEEK_END);
- sseek (s, curr, SEEK_SET);
- return end;
-}
-
-
-/* is_seekable()-- Return nonzero if the stream is seekable, zero if
- * it is not */
-
-int
-is_seekable (stream *s)
-{
- /* By convention, if file_length == -1, the file is not
- seekable. */
- return ((unix_stream *) s)->file_length!=-1;
-}
-
-
-/* is_special()-- Return nonzero if the stream is not a regular file. */
-
-int
-is_special (stream *s)
-{
- return ((unix_stream *) s)->special_file;
-}
-
-
int
stream_isatty (stream *s)
{
diff --git a/libgfortran/io/unix.h b/libgfortran/io/unix.h
index f7d6f08643e..52f3e0c8111 100644
--- a/libgfortran/io/unix.h
+++ b/libgfortran/io/unix.h
@@ -35,6 +35,7 @@ struct stream
ssize_t (*write) (struct stream *, const void *, ssize_t);
gfc_offset (*seek) (struct stream *, gfc_offset, int);
gfc_offset (*tell) (struct stream *);
+ gfc_offset (*size) (struct stream *);
/* Avoid keyword truncate due to AIX namespace collision. */
int (*trunc) (struct stream *, gfc_offset);
int (*flush) (struct stream *);
@@ -67,6 +68,12 @@ stell (stream * s)
return s->tell (s);
}
+static inline gfc_offset
+ssize (stream * s)
+{
+ return s->size (s);
+}
+
static inline int
struncate (stream * s, gfc_offset length)
{
@@ -155,15 +162,6 @@ internal_proto(inquire_write);
extern const char *inquire_readwrite (const char *, int);
internal_proto(inquire_readwrite);
-extern gfc_offset file_length (stream *);
-internal_proto(file_length);
-
-extern int is_seekable (stream *);
-internal_proto(is_seekable);
-
-extern int is_special (stream *);
-internal_proto(is_special);
-
extern void flush_if_preconnected (stream *);
internal_proto(flush_if_preconnected);
diff --git a/libgo/MERGE b/libgo/MERGE
index 41cab710019..8ba17deb09e 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-fd30c132d1bd
+6d7136d74b65
The first line of this file holds the Mercurial revision number of the
last merge done from the master library sources.
diff --git a/libgo/Makefile.am b/libgo/Makefile.am
index 6992ce19e3f..eb414906605 100644
--- a/libgo/Makefile.am
+++ b/libgo/Makefile.am
@@ -107,7 +107,6 @@ toolexeclibgo_DATA = \
cmath.gox \
crypto.gox \
csv.gox \
- ebnf.gox \
exec.gox \
expvar.gox \
flag.gox \
@@ -124,7 +123,6 @@ toolexeclibgo_DATA = \
mail.gox \
mime.gox \
net.gox \
- netchan.gox \
os.gox \
patch.gox \
path.gox \
@@ -145,7 +143,6 @@ toolexeclibgo_DATA = \
template.gox \
testing.gox \
time.gox \
- try.gox \
unicode.gox \
url.gox \
utf16.gox \
@@ -173,13 +170,13 @@ toolexeclibgocontainerdir = $(toolexeclibgodir)/container
toolexeclibgocontainer_DATA = \
container/heap.gox \
container/list.gox \
- container/ring.gox \
- container/vector.gox
+ container/ring.gox
toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
toolexeclibgocrypto_DATA = \
crypto/aes.gox \
+ crypto/bcrypt.gox \
crypto/blowfish.gox \
crypto/cast5.gox \
crypto/cipher.gox \
@@ -242,20 +239,24 @@ toolexeclibgoencoding_DATA = \
toolexeclibgoexpdir = $(toolexeclibgodir)/exp
toolexeclibgoexp_DATA = \
- exp/datafmt.gox \
+ exp/ebnf.gox \
exp/gui.gox \
exp/norm.gox \
- exp/regexp.gox
+ exp/spdy.gox \
+ exp/sql.gox \
+ exp/ssh.gox \
+ exp/terminal.gox \
+ exp/types.gox
toolexeclibgoexpguidir = $(toolexeclibgoexpdir)/gui
toolexeclibgoexpgui_DATA = \
exp/gui/x11.gox
-toolexeclibgoexpregexpdir = $(toolexeclibgoexpdir)/regexp
+toolexeclibgoexpsqldir = $(toolexeclibgoexpdir)/sql
-toolexeclibgoexpregexp_DATA = \
- exp/regexp/syntax.gox
+toolexeclibgoexpsql_DATA = \
+ exp/sql/driver.gox
toolexeclibgoexptemplatedir = $(toolexeclibgoexpdir)/template
@@ -271,9 +272,7 @@ toolexeclibgogo_DATA = \
go/parser.gox \
go/printer.gox \
go/scanner.gox \
- go/token.gox \
- go/typechecker.gox \
- go/types.gox
+ go/token.gox
toolexeclibgohashdir = $(toolexeclibgodir)/hash
@@ -289,13 +288,13 @@ toolexeclibgohttp_DATA = \
http/cgi.gox \
http/fcgi.gox \
http/httptest.gox \
- http/pprof.gox \
- http/spdy.gox
+ http/pprof.gox
toolexeclibgoimagedir = $(toolexeclibgodir)/image
toolexeclibgoimage_DATA = \
image/bmp.gox \
+ image/color.gox \
image/draw.gox \
image/gif.gox \
image/jpeg.gox \
@@ -327,6 +326,8 @@ toolexeclibgonet_DATA = \
toolexeclibgoolddir = $(toolexeclibgodir)/old
toolexeclibgoold_DATA = \
+ old/netchan.gox \
+ old/regexp.gox \
old/template.gox
toolexeclibgoosdir = $(toolexeclibgodir)/os
@@ -348,6 +349,11 @@ toolexeclibgopathdir = $(toolexeclibgodir)/path
toolexeclibgopath_DATA = \
path/filepath.gox
+toolexeclibgoregexpdir = $(toolexeclibgodir)/regexp
+
+toolexeclibgoregexp_DATA = \
+ regexp/syntax.gox
+
toolexeclibgorpcdir = $(toolexeclibgodir)/rpc
toolexeclibgorpc_DATA = \
@@ -480,6 +486,7 @@ runtime_files = \
runtime/msize.c \
runtime/proc.c \
runtime/thread.c \
+ runtime/yield.c \
$(rtems_task_variable_add_file) \
chan.c \
iface.c \
@@ -560,10 +567,6 @@ go_csv_files = \
go/csv/reader.go \
go/csv/writer.go
-go_ebnf_files = \
- go/ebnf/ebnf.go \
- go/ebnf/parser.go
-
go_exec_files = \
go/exec/exec.go \
go/exec/lp_unix.go
@@ -599,6 +602,7 @@ go_html_files = \
go/html/escape.go \
go/html/node.go \
go/html/parse.go \
+ go/html/render.go \
go/html/token.go
go_http_files = \
@@ -606,6 +610,7 @@ go_http_files = \
go/http/client.go \
go/http/cookie.go \
go/http/dump.go \
+ go/http/filetransport.go \
go/http/fs.go \
go/http/header.go \
go/http/lex.go \
@@ -620,7 +625,6 @@ go_http_files = \
go/http/transport.go
go_image_files = \
- go/image/color.go \
go/image/format.go \
go/image/geom.go \
go/image/image.go \
@@ -643,6 +647,7 @@ go_log_files = \
go/log/log.go
go_math_files = \
+ go/math/abs.go \
go/math/acosh.go \
go/math/asin.go \
go/math/asinh.go \
@@ -653,15 +658,13 @@ go_math_files = \
go/math/cbrt.go \
go/math/const.go \
go/math/copysign.go \
+ go/math/dim.go \
go/math/erf.go \
go/math/exp.go \
go/math/exp_port.go \
go/math/exp2.go \
go/math/expm1.go \
- go/math/fabs.go \
- go/math/fdim.go \
go/math/floor.go \
- go/math/fmod.go \
go/math/frexp.go \
go/math/gamma.go \
go/math/hypot.go \
@@ -675,6 +678,7 @@ go_math_files = \
go/math/log1p.go \
go/math/log10.go \
go/math/logb.go \
+ go/math/mod.go \
go/math/modf.go \
go/math/nextafter.go \
go/math/pow.go \
@@ -778,11 +782,6 @@ go_net_files = \
go/net/unixsock.go \
go/net/unixsock_posix.go
-go_netchan_files = \
- go/netchan/common.go \
- go/netchan/export.go \
- go/netchan/import.go
-
if LIBGO_IS_SOLARIS
if LIBGO_IS_386
go_os_dir_file = go/os/dir_largefile.go
@@ -866,6 +865,7 @@ go_reflect_files = \
go/reflect/value.go
go_regexp_files = \
+ go/regexp/exec.go \
go/regexp/regexp.go
go_rpc_files = \
@@ -916,6 +916,7 @@ go_strconv_files = \
go_strings_files = \
go/strings/reader.go \
+ go/strings/replace.go \
go/strings/strings.go
go_sync_files = \
@@ -954,21 +955,19 @@ go_template_files = \
go_testing_files = \
go/testing/benchmark.go \
+ go/testing/example.go \
go/testing/testing.go
go_time_files = \
go/time/format.go \
go/time/sleep.go \
go/time/sys.go \
- go/time/sys_posix.go \
+ go/time/sys_unix.go \
go/time/tick.go \
go/time/time.go \
go/time/zoneinfo_posix.go \
go/time/zoneinfo_unix.go
-go_try_files = \
- go/try/try.go
-
go_unicode_files = \
go/unicode/casetables.go \
go/unicode/digit.go \
@@ -988,6 +987,8 @@ go_utf8_files = \
go_websocket_files = \
go/websocket/client.go \
+ go/websocket/hixie.go \
+ go/websocket/hybi.go \
go/websocket/server.go \
go/websocket/websocket.go
@@ -1042,16 +1043,13 @@ go_container_list_files = \
go_container_ring_files = \
go/container/ring/ring.go
-go_container_vector_files = \
- go/container/vector/defs.go \
- go/container/vector/intvector.go \
- go/container/vector/stringvector.go \
- go/container/vector/vector.go
-
go_crypto_aes_files = \
go/crypto/aes/block.go \
go/crypto/aes/cipher.go \
go/crypto/aes/const.go
+go_crypto_bcrypt_files = \
+ go/crypto/bcrypt/base64.go \
+ go/crypto/bcrypt/bcrypt.go
go_crypto_blowfish_files = \
go/crypto/blowfish/block.go \
go/crypto/blowfish/const.go \
@@ -1124,11 +1122,13 @@ go_crypto_tls_files = \
go/crypto/tls/handshake_server.go \
go/crypto/tls/key_agreement.go \
go/crypto/tls/prf.go \
+ go/crypto/tls/root_unix.go \
go/crypto/tls/tls.go
go_crypto_twofish_files = \
go/crypto/twofish/twofish.go
go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \
+ go/crypto/x509/pkcs1.go \
go/crypto/x509/verify.go \
go/crypto/x509/x509.go
go_crypto_xtea_files = \
@@ -1188,7 +1188,8 @@ go_encoding_base32_files = \
go_encoding_base64_files = \
go/encoding/base64/base64.go
go_encoding_binary_files = \
- go/encoding/binary/binary.go
+ go/encoding/binary/binary.go \
+ go/encoding/binary/varint.go
go_encoding_git85_files = \
go/encoding/git85/git.go
go_encoding_hex_files = \
@@ -1196,36 +1197,66 @@ go_encoding_hex_files = \
go_encoding_pem_files = \
go/encoding/pem/pem.go
-go_exp_datafmt_files = \
- go/exp/datafmt/datafmt.go \
- go/exp/datafmt/parser.go
+go_exp_ebnf_files = \
+ go/exp/ebnf/ebnf.go \
+ go/exp/ebnf/parser.go
go_exp_gui_files = \
go/exp/gui/gui.go
go_exp_norm_files = \
go/exp/norm/composition.go \
go/exp/norm/forminfo.go \
+ go/exp/norm/input.go \
go/exp/norm/normalize.go \
+ go/exp/norm/readwriter.go \
go/exp/norm/tables.go \
go/exp/norm/trie.go
-go_exp_regexp_files = \
- go/exp/regexp/exec.go \
- go/exp/regexp/regexp.go
+go_exp_spdy_files = \
+ go/exp/spdy/read.go \
+ go/exp/spdy/types.go \
+ go/exp/spdy/write.go
+go_exp_sql_files = \
+ go/exp/sql/convert.go \
+ go/exp/sql/sql.go
+go_exp_ssh_files = \
+ go/exp/ssh/channel.go \
+ go/exp/ssh/common.go \
+ go/exp/ssh/doc.go \
+ go/exp/ssh/messages.go \
+ go/exp/ssh/server.go \
+ go/exp/ssh/server_shell.go \
+ go/exp/ssh/transport.go
+go_exp_terminal_files = \
+ go/exp/terminal/shell.go \
+ go/exp/terminal/terminal.go
+go_exp_types_files = \
+ go/exp/types/check.go \
+ go/exp/types/const.go \
+ go/exp/types/exportdata.go \
+ go/exp/types/gcimporter.go \
+ go/exp/types/types.go \
+ go/exp/types/universe.go
go_exp_gui_x11_files = \
go/exp/gui/x11/auth.go \
go/exp/gui/x11/conn.go
+go_exp_sql_driver_files = \
+ go/exp/sql/driver/driver.go \
+ go/exp/sql/driver/types.go
+
go_exp_template_html_files = \
+ go/exp/template/html/attr.go \
+ go/exp/template/html/clone.go \
+ go/exp/template/html/content.go \
go/exp/template/html/context.go \
- go/exp/template/html/escape.go
-
-go_exp_regexp_syntax_files = \
- go/exp/regexp/syntax/compile.go \
- go/exp/regexp/syntax/parse.go \
- go/exp/regexp/syntax/perl_groups.go \
- go/exp/regexp/syntax/prog.go \
- go/exp/regexp/syntax/regexp.go \
- go/exp/regexp/syntax/simplify.go
+ go/exp/template/html/css.go \
+ go/exp/template/html/doc.go \
+ go/exp/template/html/error.go \
+ go/exp/template/html/escape.go \
+ go/exp/template/html/html.go \
+ go/exp/template/html/js.go \
+ go/exp/template/html/transition.go \
+ go/exp/template/html/url.go
go_go_ast_files = \
go/go/ast/ast.go \
@@ -1241,7 +1272,8 @@ go_go_build_files = \
syslist.go
go_go_doc_files = \
go/go/doc/comment.go \
- go/go/doc/doc.go
+ go/go/doc/doc.go \
+ go/go/doc/example.go
go_go_parser_files = \
go/go/parser/interface.go \
go/go/parser/parser.go
@@ -1253,19 +1285,8 @@ go_go_scanner_files = \
go/go/scanner/scanner.go
go_go_token_files = \
go/go/token/position.go \
+ go/go/token/serialize.go \
go/go/token/token.go
-go_go_typechecker_files = \
- go/go/typechecker/scope.go \
- go/go/typechecker/type.go \
- go/go/typechecker/typechecker.go \
- go/go/typechecker/universe.go
-go_go_types_files = \
- go/go/types/check.go \
- go/go/types/const.go \
- go/go/types/exportdata.go \
- go/go/types/gcimporter.go \
- go/go/types/types.go \
- go/go/types/universe.go
go_hash_adler32_files = \
go/hash/adler32/adler32.go
@@ -1288,14 +1309,13 @@ go_http_httptest_files = \
go/http/httptest/server.go
go_http_pprof_files = \
go/http/pprof/pprof.go
-go_http_spdy_files = \
- go/http/spdy/read.go \
- go/http/spdy/types.go \
- go/http/spdy/write.go
go_image_bmp_files = \
go/image/bmp/reader.go
+go_image_color_files = \
+ go/image/color/color.go
+
go_image_draw_files = \
go/image/draw/draw.go
@@ -1315,6 +1335,7 @@ go_image_png_files = \
go_image_tiff_files = \
go/image/tiff/buffer.go \
+ go/image/tiff/compress.go \
go/image/tiff/consts.go \
go/image/tiff/reader.go
@@ -1344,6 +1365,12 @@ go_net_textproto_files = \
go/net/textproto/textproto.go \
go/net/textproto/writer.go
+go_old_netchan_files = \
+ go/old/netchan/common.go \
+ go/old/netchan/export.go \
+ go/old/netchan/import.go
+go_old_regexp_files = \
+ go/old/regexp/regexp.go
go_old_template_files = \
go/old/template/doc.go \
go/old/template/execute.go \
@@ -1365,6 +1392,14 @@ go_path_filepath_files = \
go/path/filepath/path.go \
go/path/filepath/path_unix.go
+go_regexp_syntax_files = \
+ go/regexp/syntax/compile.go \
+ go/regexp/syntax/parse.go \
+ go/regexp/syntax/perl_groups.go \
+ go/regexp/syntax/prog.go \
+ go/regexp/syntax/regexp.go \
+ go/regexp/syntax/simplify.go
+
go_rpc_jsonrpc_files = \
go/rpc/jsonrpc/client.go \
go/rpc/jsonrpc/server.go
@@ -1396,128 +1431,142 @@ go_testing_script_files = \
# Define Syscall and Syscall6.
if LIBGO_IS_RTEMS
-syscall_syscall_file = syscalls/syscall_stubs.go
+syscall_syscall_file = go/syscall/syscall_stubs.go
else
-syscall_syscall_file = syscalls/syscall.go
+syscall_syscall_file = go/syscall/syscall_unix.go
endif
-# Declare libc functions that vary for largefile systems.
-if LIBGO_IS_LINUX
-# Always use lseek64 on GNU/Linux.
-syscall_filesize_file = syscalls/sysfile_largefile.go
-syscall_stat_file = syscalls/sysfile_stat_largefile.go
-else # !LIBGO_IS_LINUX
-if LIBGO_IS_SOLARIS
-if LIBGO_IS_386
-# Use lseek64 on 32-bit Solaris/x86.
-syscall_filesize_file = syscalls/sysfile_largefile.go
-syscall_stat_file = syscalls/sysfile_stat_largefile.go
-else # !LIBGO_IS_386
-if LIBGO_IS_SPARC
-# Use lseek64 on 32-bit Solaris/SPARC.
-syscall_filesize_file = syscalls/sysfile_largefile.go
-syscall_stat_file = syscalls/sysfile_stat_largefile.go
-else # !LIBGO_IS_386 && !LIBGO_IS_SPARC
-# Use lseek on 64-bit Solaris.
-syscall_filesize_file = syscalls/sysfile_regfile.go
-syscall_stat_file = syscalls/sysfile_stat_regfile.go
-endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC
-endif # !LIBGO_IS_SOLARIS
-else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS
-# Use lseek by default.
-syscall_filesize_file = syscalls/sysfile_regfile.go
-syscall_stat_file = syscalls/sysfile_stat_regfile.go
-endif # !LIBGO_IS_SOLARIS
-endif # !LIBGO_IS_LINUX
-
-
-# Define ForkExec, PtraceForkExec, and Exec.
+# Define ForkExec and Exec.
if LIBGO_IS_RTEMS
-syscall_exec_os_file = syscalls/exec_stubs.go
+syscall_exec_file = go/syscall/exec_stubs.go
else
-syscall_exec_os_file = syscalls/exec.go
+syscall_exec_file = go/syscall/exec_unix.go
endif
# Define Wait4.
if HAVE_WAIT4
-syscall_wait_file = syscalls/wait4.go
+syscall_wait_file = go/syscall/libcall_wait4.go
else
-syscall_wait_file = syscalls/waitpid.go
+syscall_wait_file = go/syscall/libcall_waitpid.go
endif
# Define Sleep.
if LIBGO_IS_RTEMS
-syscall_sleep_file = syscalls/sleep_rtems.go
+syscall_sleep_file = go/syscall/sleep_rtems.go
else
-syscall_sleep_file = syscalls/sleep_select.go
+syscall_sleep_file = go/syscall/sleep_select.go
endif
# Define Errstr.
+if LIBGO_IS_LINUX
+syscall_errstr_file = go/syscall/errstr_linux.go
+else
if LIBGO_IS_RTEMS
-syscall_errstr_file = syscalls/errstr_rtems.go
+syscall_errstr_file = go/syscall/errstr_linux.go
else
if HAVE_STRERROR_R
-syscall_errstr_file = syscalls/errstr.go
+syscall_errstr_file = go/syscall/errstr.go
else
-syscall_errstr_file = syscalls/errstr_nor.go
+syscall_errstr_file = go/syscall/errstr_nor.go
+endif
endif
endif
-# Declare libc_strerror_r which is the Go name for strerror_r.
-if LIBGO_IS_RTEMS
-# RTEMS uses newlib in which strerror_r returns char *.
-syscall_errstr_decl_file = syscalls/errstr_decl_rtems.go
-else
+# Declare libc functions that vary for largefile systems.
if LIBGO_IS_LINUX
-# On GNU/Linux the POSIX strerror_r is called __xpg_strerror_r.
-syscall_errstr_decl_file = syscalls/errstr_decl_linux.go
-else
-# On other systems we hope strerror_r is just strerror_r.
-syscall_errstr_decl_file = syscalls/errstr_decl.go
-endif
-endif
+# Always use lseek64 on GNU/Linux.
+syscall_size_file = go/syscall/libcall_posix_largefile.go
+else # !LIBGO_IS_LINUX
+if LIBGO_IS_SOLARIS
+if LIBGO_IS_386
+# Use lseek64 on 32-bit Solaris/x86.
+syscall_size_file = go/syscall/libcall_posix_largefile.go
+else # !LIBGO_IS_386
+if LIBGO_IS_SPARC
+# Use lseek64 on 32-bit Solaris/SPARC.
+syscall_size_file = go/syscall/libcall_posix_largefile.go
+else # !LIBGO_IS_386 && !LIBGO_IS_SPARC
+# Use lseek on 64-bit Solaris.
+syscall_size_file = go/syscall/libcall_posix_regfile.go
+endif # !LIBGO_IS_386 && !LIBGO_IS_SPARC
+endif # !LIBGO_IS_SOLARIS
+else # !LIBGO_IS_LINUX && !LIBGO_IS_SOLARIS
+# Use lseek by default.
+syscall_size_file = go/syscall/libcall_posix_regfile.go
+endif # !LIBGO_IS_SOLARIS
+endif # !LIBGO_IS_LINUX
# Define socket sizes and types.
if LIBGO_IS_LINUX
-syscall_socket_os_file = syscalls/socket_linux.go
+syscall_socket_file = go/syscall/socket_linux.go epoll.go
else
if LIBGO_IS_SOLARIS
-syscall_socket_os_file = syscalls/socket_solaris.go
+syscall_socket_file = go/syscall/socket_solaris.go
else
if LIBGO_IS_IRIX
-syscall_socket_os_file = syscalls/socket_irix.go
+syscall_socket_file = go/syscall/socket_irix.go
else
-syscall_socket_os_file = syscalls/socket_bsd.go
-endif
+syscall_socket_file = go/syscall/socket_bsd.go
endif
endif
-
-# Support for epoll.
-if LIBGO_IS_LINUX
-syscall_socket_epoll_file = syscalls/socket_epoll.go
-else
-syscall_socket_epoll_file =
endif
# Support for uname.
if LIBGO_IS_SOLARIS
if LIBGO_IS_386
-# 32-bit Solaris 2/x86 needs _nuname, handled in syscall_solaris_386.go.
+# 32-bit Solaris 2/x86 needs _nuname, handled in libcall_solaris_386.go.
syscall_uname_file =
else # !LIBGO_IS_386 && LIBGO_IS_SOLARIS
-syscall_uname_file = syscalls/syscall_uname.go
+syscall_uname_file = go/syscall/libcall_uname.go
endif
else # !LIBGO_IS_SOLARIS
-syscall_uname_file = syscalls/syscall_uname.go
+syscall_uname_file = go/syscall/libcall_uname.go
endif
# Support for netlink sockets and messages.
if LIBGO_IS_LINUX
-syscall_netlink_file = syscalls/netlink_linux.go
+syscall_netlink_file = go/syscall/netlink_linux.go
else
syscall_netlink_file =
endif
+go_base_syscall_files = \
+ go/syscall/libcall_support.go \
+ go/syscall/libcall_posix.go \
+ go/syscall/socket.go \
+ go/syscall/str.go \
+ go/syscall/syscall.go \
+ $(syscall_syscall_file) \
+ $(syscall_exec_file) \
+ $(syscall_wait_file) \
+ $(syscall_sleep_file) \
+ $(syscall_errstr_file) \
+ $(syscall_size_file) \
+ $(syscall_socket_file) \
+ $(syscall_uname_file) \
+ $(syscall_netlink_file) \
+ $(GO_LIBCALL_OS_FILE) \
+ $(GO_LIBCALL_OS_ARCH_FILE) \
+ $(GO_SYSCALL_OS_FILE) \
+ $(GO_SYSCALL_OS_ARCH_FILE)
+
+go_syscall_files = \
+ $(go_base_syscall_files) \
+ libcalls.go \
+ sysinfo.go \
+ syscall_arch.go
+go_syscall_c_files = \
+ go/syscall/errno.c \
+ go/syscall/wait.c
+
+libcalls.go: s-libcalls; @true
+s-libcalls: Makefile go/syscall/mksyscall.awk $(go_base_syscall_files)
+ rm -f libcalls.go.tmp
+ files=`echo $^ | sed -e 's/Makefile//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \
+ $(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp
+ $(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go
+ $(STAMP) $@
+
syscall_arch.go: s-syscall_arch; @true
s-syscall_arch: Makefile
rm -f syscall_arch.go.tmp
@@ -1527,30 +1576,39 @@ s-syscall_arch: Makefile
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
$(STAMP) $@
-go_syscall_files = \
- $(syscall_errstr_file) \
- $(syscall_errstr_decl_file) \
- syscalls/exec_helpers.go \
- $(syscall_exec_os_file) \
- $(syscall_wait_file) \
- $(syscall_filesize_file) \
- $(syscall_netlink_file) \
- $(syscall_stat_file) \
- $(syscall_sleep_file) \
- syscalls/socket.go \
- $(syscall_socket_os_file) \
- $(syscall_socket_epoll_file) \
- $(syscall_syscall_file) \
- $(syscall_uname_file) \
- syscalls/syscall_unix.go \
- syscalls/stringbyte.go \
- syscalls/syscall_$(GOOS).go \
- $(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \
- syscalls/sysfile_posix.go \
- sysinfo.go \
- syscall_arch.go
-go_syscall_c_files = \
- syscalls/errno.c
+sysinfo.go: s-sysinfo; @true
+s-sysinfo: $(srcdir)/mksysinfo.sh config.h
+ CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
+ $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
+ $(STAMP) $@
+
+# The epoll struct has an embedded union and is packed on x86_64,
+# which is too complicated for mksysinfo.sh. We find the offset of
+# the only field we care about in configure.ac, and generate the
+# struct here.
+epoll.go: s-epoll; @true
+s-epoll: Makefile
+ rm -f epoll.go.tmp
+ echo 'package syscall' > epoll.go.tmp
+ echo 'type EpollEvent struct {' >> epoll.go.tmp
+ echo ' Events uint32' >> epoll.go.tmp
+ case "$(SIZEOF_STRUCT_EPOLL_EVENT),$(STRUCT_EPOLL_EVENT_FD_OFFSET)" in \
+ 0,0) echo 1>&2 "*** struct epoll_event data.fd offset unknown"; \
+ exit 1; ;; \
+ 8,4) echo ' Fd int32' >> epoll.go.tmp; ;; \
+ 12,4) echo ' Fd int32' >> epoll.go.tmp; \
+ echo ' Pad [4]byte' >> epoll.go.tmp; ;; \
+ 12,8) echo ' Pad [4]byte' >> epoll.go.tmp; \
+ echo ' Fd int32' >> epoll.go.tmp; ;; \
+ 16,8) echo ' Pad [4]byte' >> epoll.go.tmp; \
+ echo ' Fd int32' >> epoll.go.tmp; \
+ echo ' Pad2 [4]byte' >> epoll.go.tmp; ;; \
+ *) echo 1>&2 "*** struct epoll_event unsupported"; \
+ exit 1; ;; \
+ esac
+ echo '}' >> epoll.go.tmp
+ $(SHELL) $(srcdir)/../move-if-change epoll.go.tmp epoll.go
+ $(STAMP) $@
if LIBGO_IS_LINUX
# os_lib_inotify_lo = os/inotify.lo
@@ -1568,7 +1626,6 @@ libgo_go_objs = \
cmath/cmath.lo \
crypto/crypto.lo \
csv/csv.lo \
- ebnf/ebnf.lo \
exec/exec.lo \
expvar/expvar.lo \
flag/flag.lo \
@@ -1585,7 +1642,6 @@ libgo_go_objs = \
mail/mail.lo \
mime/mime.lo \
net/net.lo \
- netchan/netchan.lo \
os/os.lo \
patch/patch.lo \
path/path.lo \
@@ -1605,7 +1661,6 @@ libgo_go_objs = \
tabwriter/tabwriter.lo \
template/template.lo \
time/time.lo \
- try/try.lo \
unicode/unicode.lo \
url/url.lo \
utf16/utf16.lo \
@@ -1622,8 +1677,8 @@ libgo_go_objs = \
container/heap.lo \
container/list.lo \
container/ring.lo \
- container/vector.lo \
crypto/aes.lo \
+ crypto/bcrypt.lo \
crypto/blowfish.lo \
crypto/cast5.lo \
crypto/cipher.lo \
@@ -1666,12 +1721,16 @@ libgo_go_objs = \
encoding/git85.lo \
encoding/hex.lo \
encoding/pem.lo \
- exp/datafmt.lo \
+ exp/ebnf.lo \
exp/gui.lo \
exp/norm.lo \
- exp/regexp.lo \
+ exp/spdy.lo \
+ exp/sql.lo \
+ exp/ssh.lo \
+ exp/terminal.lo \
+ exp/types.lo \
exp/gui/x11.lo \
- exp/regexp/syntax.lo \
+ exp/sql/driver.lo \
exp/template/html.lo \
go/ast.lo \
go/build.lo \
@@ -1680,8 +1739,6 @@ libgo_go_objs = \
go/printer.lo \
go/scanner.lo \
go/token.lo \
- go/typechecker.lo \
- go/types.lo \
hash/adler32.lo \
hash/crc32.lo \
hash/crc64.lo \
@@ -1690,8 +1747,8 @@ libgo_go_objs = \
http/fcgi.lo \
http/httptest.lo \
http/pprof.lo \
- http/spdy.lo \
image/bmp.lo \
+ image/color.lo \
image/draw.lo \
image/gif.lo \
image/jpeg.lo \
@@ -1703,18 +1760,22 @@ libgo_go_objs = \
mime/multipart.lo \
net/dict.lo \
net/textproto.lo \
+ old/netchan.lo \
+ old/regexp.lo \
old/template.lo \
$(os_lib_inotify_lo) \
os/user.lo \
os/signal.lo \
path/filepath.lo \
+ regexp/syntax.lo \
rpc/jsonrpc.lo \
runtime/debug.lo \
runtime/pprof.lo \
sync/atomic.lo \
sync/atomic_c.lo \
- syscalls/syscall.lo \
- syscalls/errno.lo \
+ syscall/syscall.lo \
+ syscall/errno.lo \
+ syscall/wait.lo \
template/parse.lo \
testing/testing.lo \
testing/iotest.lo \
@@ -1862,13 +1923,6 @@ csv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: csv/check
-ebnf/ebnf.lo: $(go_ebnf_files) container/vector.gox go/scanner.gox \
- go/token.gox os.gox strconv.gox unicode.gox utf8.gox
- $(BUILDPACKAGE)
-ebnf/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: ebnf/check
-
exec/exec.lo: $(go_exec_files) bytes.gox io.gox os.gox strconv.gox \
strings.gox syscall.gox
$(BUILDPACKAGE)
@@ -1890,7 +1944,7 @@ flag/check: $(CHECK_DEPS)
.PHONY: flag/check
fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox math.gox os.gox reflect.gox \
- strconv.gox strings.gox unicode.gox utf8.gox
+ strconv.gox strings.gox sync.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
fmt/check: $(CHECK_DEPS)
@$(CHECK)
@@ -1910,8 +1964,8 @@ hash/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: hash/check
-html/html.lo: $(go_html_files) bytes.gox io.gox os.gox strconv.gox strings.gox \
- utf8.gox
+html/html.lo: $(go_html_files) bufio.gox bytes.gox fmt.gox io.gox os.gox \
+ strconv.gox strings.gox utf8.gox
$(BUILDPACKAGE)
html/check: $(CHECK_DEPS)
@$(CHECK)
@@ -1928,7 +1982,8 @@ http/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: http/check
-image/image.lo: $(go_image_files) bufio.gox io.gox os.gox strconv.gox
+image/image.lo: $(go_image_files) bufio.gox image/color.gox io.gox os.gox \
+ strconv.gox
$(BUILDPACKAGE)
image/check: $(CHECK_DEPS)
@$(CHECK)
@@ -1984,13 +2039,6 @@ net/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: net/check
-netchan/netchan.lo: $(go_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
- reflect.gox strconv.gox sync.gox time.gox
- $(BUILDPACKAGE)
-netchan/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: netchan/check
-
os/os.lo: $(go_os_files) runtime.gox sync.gox syscall.gox
$(BUILDPACKAGE)
os/check: $(CHECK_DEPS)
@@ -2028,8 +2076,8 @@ reflect/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: reflect/check
-regexp/regexp.lo: $(go_regexp_files) bytes.gox io.gox os.gox strings.gox \
- utf8.gox
+regexp/regexp.lo: $(go_regexp_files) bytes.gox io.gox os.gox \
+ regexp/syntax.gox strconv.gox strings.gox sync.gox utf8.gox
$(BUILDPACKAGE)
regexp/check: $(CHECK_DEPS)
@$(CHECK)
@@ -2076,7 +2124,7 @@ strconv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: strconv/check
-strings/strings.lo: $(go_strings_files) os.gox unicode.gox utf8.gox
+strings/strings.lo: $(go_strings_files) io.gox os.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
strings/check: $(CHECK_DEPS)
@$(CHECK)
@@ -2111,8 +2159,9 @@ template/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: template/check
-testing/testing.lo: $(go_testing_files) flag.gox fmt.gox os.gox regexp.gox \
- runtime.gox runtime/pprof.gox strings.gox strconv.gox time.gox
+testing/testing.lo: $(go_testing_files) bytes.gox flag.gox fmt.gox io.gox \
+ os.gox regexp.gox runtime.gox runtime/pprof.gox strings.gox \
+ strconv.gox time.gox
$(BUILDPACKAGE)
testing/check: $(CHECK_DEPS)
@$(CHECK)
@@ -2125,12 +2174,6 @@ time/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: time/check
-try/try.lo: $(go_try_files) fmt.gox io.gox os.gox reflect.gox unicode.gox
- $(BUILDPACKAGE)
-try/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: try/check
-
unicode/unicode.lo: $(go_unicode_files)
$(BUILDPACKAGE)
unicode/check: $(CHECK_DEPS)
@@ -2156,8 +2199,10 @@ utf8/check: $(CHECK_DEPS)
.PHONY: utf8/check
websocket/websocket.lo: $(go_websocket_files) bufio.gox bytes.gox \
- crypto/md5.gox crypto/tls.gox encoding/binary.gox fmt.gox \
- http.gox io.gox net.gox os.gox rand.gox strings.gox url.gox
+ crypto/md5.gox crypto/rand.gox crypto/sha1.gox crypto/tls.gox \
+ encoding/base64.gox encoding/binary.gox fmt.gox http.gox \
+ io.gox io/ioutil.gox json.gox net.gox os.gox rand.gox \
+ strings.gox strconv.gox sync.gox url.gox
$(BUILDPACKAGE)
websocket/check: $(CHECK_DEPS)
@$(CHECK)
@@ -2246,13 +2291,6 @@ container/ring/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: container/ring/check
-container/vector.lo: $(go_container_vector_files)
- $(BUILDPACKAGE)
-container/vector/check: $(CHECK_DEPS)
- @$(MKDIR_P) container/vector
- @$(CHECK)
-.PHONY: container/vector/check
-
crypto/aes.lo: $(go_crypto_aes_files) os.gox strconv.gox
$(BUILDPACKAGE)
crypto/aes/check: $(CHECK_DEPS)
@@ -2260,6 +2298,15 @@ crypto/aes/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/aes/check
+crypto/bcrypt.lo: $(go_crypto_bcrypt_files) crypto/blowfish.gox \
+ crypto/rand.gox crypto/subtle.gox encoding/base64.gox \
+ fmt.gox io.gox os.gox strconv.gox
+ $(BUILDPACKAGE)
+crypto/bcrypt/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/bcrypt
+ @$(CHECK)
+.PHONY: crypto/bcrypt/check
+
crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
$(BUILDPACKAGE)
crypto/blowfish/check: $(CHECK_DEPS)
@@ -2412,12 +2459,12 @@ crypto/subtle/check: $(CHECK_DEPS)
.PHONY: crypto/subtle/check
crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \
- crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \
- crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \
- crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
- crypto/x509.gox crypto/x509/pkix.gox encoding/pem.gox \
- hash.gox io.gox io/ioutil.gox net.gox os.gox strconv.gox \
- strings.gox sync.gox time.gox
+ crypto/aes.gox crypto/cipher.gox crypto/des.gox \
+ crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
+ crypto/rand.gox crypto/rc4.gox crypto/rsa.gox crypto/sha1.gox \
+ crypto/subtle.gox crypto/x509.gox crypto/x509/pkix.gox \
+ encoding/pem.gox hash.gox io.gox io/ioutil.gox net.gox os.gox \
+ strconv.gox strings.gox sync.gox time.gox
$(BUILDPACKAGE)
crypto/tls/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/tls
@@ -2592,14 +2639,13 @@ encoding/pem/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: encoding/pem/check
-exp/datafmt.lo: $(go_exp_datafmt_files) bytes.gox fmt.gox go/scanner.gox \
- go/token.gox io.gox os.gox reflect.gox runtime.gox \
- strconv.gox strings.gox
+exp/ebnf.lo: $(go_exp_ebnf_files) scanner.gox go/token.gox os.gox \
+ strconv.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
-exp/datafmt/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/datafmt
+exp/ebnf/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/ebnf
@$(CHECK)
-.PHONY: exp/datafmt/check
+.PHONY: exp/ebnf/check
exp/gui.lo: $(go_exp_gui_files) image.gox image/draw.gox os.gox
$(BUILDPACKAGE)
@@ -2608,20 +2654,55 @@ exp/gui/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/gui/check
-exp/norm.lo: $(go_exp_norm_files) utf8.gox
+exp/norm.lo: $(go_exp_norm_files) io.gox os.gox utf8.gox
$(BUILDPACKAGE)
exp/norm/check: $(CHECK_DEPS)
@$(MKDIR_P) exp/norm
@$(CHECK)
.PHONY: exp/norm/check
-exp/regexp.lo: $(go_exp_regexp_files) bytes.gox exp/regexp/syntax.gox io.gox \
- os.gox strings.gox sync.gox utf8.gox
+exp/spdy.lo: $(go_exp_spdy_files) bytes.gox compress/zlib.gox \
+ encoding/binary.gox http.gox io.gox os.gox strings.gox
+ $(BUILDPACKAGE)
+exp/spdy/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/spdy
+ @$(CHECK)
+.PHONY: exp/spdy/check
+
+exp/sql.lo: $(go_exp_sql_files) exp/sql/driver.gox fmt.gox os.gox reflect.gox \
+ runtime.gox strconv.gox sync.gox
+ $(BUILDPACKAGE)
+exp/sql/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/sql
+ @$(CHECK)
+.PHONY: exp/sql/check
+
+exp/ssh.lo: $(go_exp_ssh_files) big.gox bufio.gox bytes.gox crypto.gox \
+ crypto/aes.gox crypto/cipher.gox crypto/hmac.gox \
+ crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
+ crypto/subtle.gox crypto/x509.gox encoding/pem.gox hash.gox \
+ io.gox net.gox os.gox reflect.gox strconv.gox sync.gox
+ $(BUILDPACKAGE)
+exp/ssh/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/ssh
+ @$(CHECK)
+.PHONY: exp/ssh/check
+
+exp/terminal.lo: $(go_exp_terminal_files) io.gox os.gox syscall.gox
+ $(BUILDPACKAGE)
+exp/terminal/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/terminal
+ @$(CHECK)
+.PHONY: exp/terminal/check
+
+exp/types.lo: $(go_exp_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
+ go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
+ scanner.gox sort.gox strconv.gox strings.gox
$(BUILDPACKAGE)
-exp/regexp/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/regexp
+exp/types/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/types
@$(CHECK)
-.PHONY: exp/regexp/check
+.PHONY: exp/types/check
exp/gui/x11.lo: $(go_exp_gui_x11_files) bufio.gox exp/gui.gox image.gox \
image/draw.gox io.gox log.gox net.gox os.gox strconv.gox \
@@ -2632,15 +2713,17 @@ exp/gui/x11/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/gui/x11/check
-exp/regexp/syntax.lo: $(go_exp_regexp_syntax_files) bytes.gox os.gox sort.gox strconv.gox strings.gox unicode.gox utf8.gox
+exp/sql/driver.lo: $(go_exp_sql_driver_files) fmt.gox os.gox reflect.gox \
+ strconv.gox
$(BUILDPACKAGE)
-exp/regexp/syntax/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/regexp/syntax
+exp/sql/driver/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/sql/driver
@$(CHECK)
-.PHONY: exp/regexp/syntax/check
+.PHONY: exp/sql/driver/check
-exp/template/html.lo: $(go_exp_template_html_files) fmt.gox template.gox \
- template/parse.gox
+exp/template/html.lo: $(go_exp_template_html_files) bytes.gox fmt.gox \
+ html.gox json.gox os.gox strings.gox template.gox \
+ template/parse.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
exp/template/html/check: $(CHECK_DEPS)
@$(MKDIR_P) exp/template/html
@@ -2655,9 +2738,10 @@ go/ast/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/ast/check
-go/build.lo: $(go_go_build_files) bytes.gox exec.gox fmt.gox go/parser.gox \
- go/token.gox log.gox os.gox path/filepath.gox regexp.gox \
- runtime.gox strconv.gox strings.gox runtime.gox
+go/build.lo: $(go_go_build_files) bytes.gox exec.gox fmt.gox go/ast.gox \
+ go/doc.gox go/parser.gox go/token.gox io/ioutil.gox log.gox \
+ os.gox path.gox path/filepath.gox regexp.gox runtime.gox \
+ sort.gox strconv.gox strings.gox runtime.gox unicode.gox
$(BUILDPACKAGE)
go/build/check: $(CHECK_DEPS)
@$(MKDIR_P) go/build
@@ -2674,7 +2758,7 @@ s-syslist: Makefile
$(STAMP) $@
go/doc.lo: $(go_go_doc_files) go/ast.gox go/token.gox io.gox regexp.gox \
- sort.gox strings.gox template.gox
+ sort.gox strings.gox template.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
go/doc/check: $(CHECK_DEPS)
@$(MKDIR_P) go/doc
@@ -2692,7 +2776,7 @@ go/parser/check: $(CHECK_DEPS)
go/printer.lo: $(go_go_printer_files) bytes.gox fmt.gox go/ast.gox \
go/token.gox io.gox os.gox path/filepath.gox reflect.gox \
- runtime.gox strings.gox tabwriter.gox
+ strings.gox tabwriter.gox
$(BUILDPACKAGE)
go/printer/check: $(CHECK_DEPS)
@$(MKDIR_P) go/printer
@@ -2708,30 +2792,14 @@ go/scanner/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/scanner/check
-go/token.lo: $(go_go_token_files) fmt.gox strconv.gox
+go/token.lo: $(go_go_token_files) fmt.gox gob.gox io.gox os.gox sort.gox \
+ strconv.gox sync.gox
$(BUILDPACKAGE)
go/token/check: $(CHECK_DEPS)
@$(MKDIR_P) go/token
@$(CHECK)
.PHONY: go/token/check
-go/typechecker.lo: $(go_go_typechecker_files) fmt.gox go/ast.gox go/token.gox \
- go/scanner.gox os.gox
- $(BUILDPACKAGE)
-go/typechecker/check: $(CHECK_DEPS)
- @$(MKDIR_P) go/typechecker
- @$(CHECK)
-.PHONY: go/typechecker/check
-
-go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
- go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
- scanner.gox sort.gox strconv.gox strings.gox
- $(BUILDPACKAGE)
-go/types/check: $(CHECK_DEPS)
- @$(MKDIR_P) go/types
- @$(CHECK)
-.PHONY: go/types/check
-
hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox
$(BUILDPACKAGE)
hash/adler32/check: $(CHECK_DEPS)
@@ -2795,23 +2863,21 @@ http/pprof/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: http/pprof/check
-http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \
- encoding/binary.gox http.gox io.gox os.gox strconv.gox \
- strings.gox sync.gox
- $(BUILDPACKAGE)
-http/spdy/check: $(CHECK_DEPS)
- @$(MKDIR_P) http/spdy
- @$(CHECK)
-.PHONY: http/spdy/check
-
-image/bmp.lo: $(go_image_bmp_files) image.gox io.gox os.gox
+image/bmp.lo: $(go_image_bmp_files) image.gox image/color.gox io.gox os.gox
$(BUILDPACKAGE)
image/bmp/check: $(CHECK_DEPS)
@$(MKDIR_P) image/bmp
@$(CHECK)
.PHONY: image/bmp/check
-image/draw.lo: $(go_image_draw_files) image.gox image/ycbcr.gox
+image/color.lo: $(go_image_color_files)
+ $(BUILDPACKAGE)
+image/color/check: $(CHECK_DEPS)
+ @$(MKDIR_P) image/color
+ @$(CHECK)
+.PHONY: image/color/check
+
+image/draw.lo: $(go_image_draw_files) image.gox image/color.gox image/ycbcr.gox
$(BUILDPACKAGE)
image/draw/check: $(CHECK_DEPS)
@$(MKDIR_P) image/draw
@@ -2819,46 +2885,48 @@ image/draw/check: $(CHECK_DEPS)
.PHONY: image/draw/check
image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \
- image.gox io.gox os.gox
+ image.gox image/color.gox io.gox os.gox
$(BUILDPACKAGE)
image/gif/check: $(CHECK_DEPS)
@$(MKDIR_P) image/gif
@$(CHECK)
.PHONY: image/gif/check
-image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \
- io.gox os.gox
+image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/color.gox \
+ image/ycbcr.gox io.gox os.gox
$(BUILDPACKAGE)
image/jpeg/check: $(CHECK_DEPS)
@$(MKDIR_P) image/jpeg
@$(CHECK)
.PHONY: image/jpeg/check
-image/png.lo: $(go_image_png_files) bufio.gox compress/zlib.gox fmt.gox \
- hash.gox hash/crc32.gox image.gox io.gox os.gox strconv.gox
+image/png.lo: $(go_image_png_files) bufio.gox compress/zlib.gox \
+ encoding/binary.gox fmt.gox hash.gox hash/crc32.gox image.gox \
+ image/color.gox io.gox os.gox strconv.gox
$(BUILDPACKAGE)
image/png/check: $(CHECK_DEPS)
@$(MKDIR_P) image/png
@$(CHECK)
.PHONY: image/png/check
-image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \
- encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox
+image/tiff.lo: $(go_image_tiff_files) bufio.gox compress/lzw.gox \
+ compress/zlib.gox encoding/binary.gox image.gox \
+ image/color.gox io.gox io/ioutil.gox os.gox
$(BUILDPACKAGE)
image/tiff/check: $(CHECK_DEPS)
@$(MKDIR_P) image/tiff
@$(CHECK)
.PHONY: image/tiff/check
-image/ycbcr.lo: $(go_image_ycbcr_files) image.gox
+image/ycbcr.lo: $(go_image_ycbcr_files) image.gox image/color.gox
$(BUILDPACKAGE)
image/ycbcr/check: $(CHECK_DEPS)
@$(MKDIR_P) image/ycbcr
@$(CHECK)
.PHONY: image/ycbcr/check
-index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \
- sort.gox
+index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox \
+ encoding/binary.gox io.gox os.gox regexp.gox sort.gox
$(BUILDPACKAGE)
index/suffixarray/check: $(CHECK_DEPS)
@$(MKDIR_P) index/suffixarray
@@ -2887,13 +2955,30 @@ net/dict.lo: $(go_net_dict_files) net/textproto.gox os.gox strconv.gox \
$(BUILDPACKAGE)
net/textproto.lo: $(go_net_textproto_files) bufio.gox bytes.gox fmt.gox \
- io.gox io/ioutil.gox net.gox os.gox strconv.gox sync.gox
+ io.gox io/ioutil.gox net.gox os.gox strings.gox strconv.gox \
+ sync.gox
$(BUILDPACKAGE)
net/textproto/check: $(CHECK_DEPS)
@$(MKDIR_P) net/textproto
@$(CHECK)
.PHONY: net/textproto/check
+old/netchan.lo: $(go_old_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
+ reflect.gox strconv.gox sync.gox time.gox
+ $(BUILDPACKAGE)
+old/netchan/check: $(CHECK_DEPS)
+ @$(MKDIR_P) old/netchan
+ @$(CHECK)
+.PHONY: old/netchan/check
+
+old/regexp.lo: $(go_old_regexp_files) bytes.gox io.gox os.gox strings.gox \
+ utf8.gox
+ $(BUILDPACKAGE)
+old/regexp/check: $(CHECK_DEPS)
+ @$(MKDIR_P) old/regexp
+ @$(CHECK)
+.PHONY: old/regexp/check
+
old/template.lo: $(go_old_template_files) bytes.gox fmt.gox io.gox \
io/ioutil.gox os.gox reflect.gox strconv.gox strings.gox \
unicode.gox utf8.gox
@@ -2933,6 +3018,14 @@ path/filepath/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: path/filepath/check
+regexp/syntax.lo: $(go_regexp_syntax_files) bytes.gox os.gox sort.gox \
+ strconv.gox strings.gox unicode.gox utf8.gox
+ $(BUILDPACKAGE)
+regexp/syntax/check: $(CHECK_DEPS)
+ @$(MKDIR_P) regexp/syntax
+ @$(CHECK)
+.PHONY: regexp/syntax/check
+
rpc/jsonrpc.lo: $(go_rpc_jsonrpc_files) fmt.gox io.gox json.gox net.gox \
os.gox rpc.gox sync.gox
$(BUILDPACKAGE)
@@ -2997,16 +3090,12 @@ testing/script/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: testing/script/check
-sysinfo.go: s-sysinfo; @true
-s-sysinfo: $(srcdir)/mksysinfo.sh config.h
- CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
- $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
- $(STAMP) $@
-
-syscalls/syscall.lo: $(go_syscall_files) sync.gox
+syscall/syscall.lo: $(go_syscall_files) sync.gox
$(BUILDPACKAGE)
-syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo
- $(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c
+syscall/errno.lo: go/syscall/errno.c
+ $(LTCOMPILE) -c -o $@ $<
+syscall/wait.lo: go/syscall/wait.c
+ $(LTCOMPILE) -c -o $@ $<
# How to build a .gox file from a .lo file.
BUILDGOX = \
@@ -3027,8 +3116,6 @@ crypto.gox: crypto/crypto.lo
$(BUILDGOX)
csv.gox: csv/csv.lo
$(BUILDGOX)
-ebnf.gox: ebnf/ebnf.lo
- $(BUILDGOX)
exec.gox: exec/exec.lo
$(BUILDGOX)
expvar.gox: expvar/expvar.lo
@@ -3061,8 +3148,6 @@ mime.gox: mime/mime.lo
$(BUILDGOX)
net.gox: net/net.lo
$(BUILDGOX)
-netchan.gox: netchan/netchan.lo
- $(BUILDGOX)
os.gox: os/os.lo
$(BUILDGOX)
patch.gox: patch/patch.lo
@@ -3093,7 +3178,7 @@ sync.gox: sync/sync.lo
$(BUILDGOX)
syslog.gox: syslog/syslog.lo
$(BUILDGOX)
-syscall.gox: syscalls/syscall.lo
+syscall.gox: syscall/syscall.lo
$(BUILDGOX)
tabwriter.gox: tabwriter/tabwriter.lo
$(BUILDGOX)
@@ -3103,8 +3188,6 @@ testing.gox: testing/testing.lo
$(BUILDGOX)
time.gox: time/time.lo
$(BUILDGOX)
-try.gox: try/try.lo
- $(BUILDGOX)
unicode.gox: unicode/unicode.lo
$(BUILDGOX)
url.gox: url/url.lo
@@ -3140,11 +3223,11 @@ container/list.gox: container/list.lo
$(BUILDGOX)
container/ring.gox: container/ring.lo
$(BUILDGOX)
-container/vector.gox: container/vector.lo
- $(BUILDGOX)
crypto/aes.gox: crypto/aes.lo
$(BUILDGOX)
+crypto/bcrypt.gox: crypto/bcrypt.lo
+ $(BUILDGOX)
crypto/blowfish.gox: crypto/blowfish.lo
$(BUILDGOX)
crypto/cast5.gox: crypto/cast5.lo
@@ -3234,19 +3317,27 @@ encoding/hex.gox: encoding/hex.lo
encoding/pem.gox: encoding/pem.lo
$(BUILDGOX)
-exp/datafmt.gox: exp/datafmt.lo
+exp/ebnf.gox: exp/ebnf.lo
$(BUILDGOX)
exp/gui.gox: exp/gui.lo
$(BUILDGOX)
exp/norm.gox: exp/norm.lo
$(BUILDGOX)
-exp/regexp.gox: exp/regexp.lo
+exp/spdy.gox: exp/spdy.lo
+ $(BUILDGOX)
+exp/sql.gox: exp/sql.lo
+ $(BUILDGOX)
+exp/ssh.gox: exp/ssh.lo
+ $(BUILDGOX)
+exp/terminal.gox: exp/terminal.lo
+ $(BUILDGOX)
+exp/types.gox: exp/types.lo
$(BUILDGOX)
exp/gui/x11.gox: exp/gui/x11.lo
$(BUILDGOX)
-exp/regexp/syntax.gox: exp/regexp/syntax.lo
+exp/sql/driver.gox: exp/sql/driver.lo
$(BUILDGOX)
exp/template/html.gox: exp/template/html.lo
@@ -3266,10 +3357,6 @@ go/scanner.gox: go/scanner.lo
$(BUILDGOX)
go/token.gox: go/token.lo
$(BUILDGOX)
-go/typechecker.gox: go/typechecker.lo
- $(BUILDGOX)
-go/types.gox: go/types.lo
- $(BUILDGOX)
hash/adler32.gox: hash/adler32.lo
$(BUILDGOX)
@@ -3288,11 +3375,11 @@ http/httptest.gox: http/httptest.lo
$(BUILDGOX)
http/pprof.gox: http/pprof.lo
$(BUILDGOX)
-http/spdy.gox: http/spdy.lo
- $(BUILDGOX)
image/bmp.gox: image/bmp.lo
$(BUILDGOX)
+image/color.gox: image/color.lo
+ $(BUILDGOX)
image/draw.gox: image/draw.lo
$(BUILDGOX)
image/gif.gox: image/gif.lo
@@ -3320,6 +3407,10 @@ net/dict.gox: net/dict.lo
net/textproto.gox: net/textproto.lo
$(BUILDGOX)
+old/netchan.gox: old/netchan.lo
+ $(BUILDGOX)
+old/regexp.gox: old/regexp.lo
+ $(BUILDGOX)
old/template.gox: old/template.lo
$(BUILDGOX)
@@ -3333,6 +3424,9 @@ os/signal.gox: os/signal.lo
path/filepath.gox: path/filepath.lo
$(BUILDGOX)
+regexp/syntax.gox: regexp/syntax.lo
+ $(BUILDGOX)
+
rpc/jsonrpc.gox: rpc/jsonrpc.lo
$(BUILDGOX)
@@ -3368,7 +3462,6 @@ TEST_PACKAGES = \
bytes/check \
cmath/check \
csv/check \
- ebnf/check \
exec/check \
expvar/check \
flag/check \
@@ -3384,7 +3477,6 @@ TEST_PACKAGES = \
mail/check \
mime/check \
net/check \
- netchan/check \
os/check \
patch/check \
path/check \
@@ -3403,7 +3495,6 @@ TEST_PACKAGES = \
tabwriter/check \
template/check \
time/check \
- try/check \
unicode/check \
url/check \
utf16/check \
@@ -3420,8 +3511,8 @@ TEST_PACKAGES = \
container/heap/check \
container/list/check \
container/ring/check \
- container/vector/check \
crypto/aes/check \
+ crypto/bcrypt/check \
crypto/blowfish/check \
crypto/cast5/check \
crypto/cipher/check \
@@ -3461,10 +3552,12 @@ TEST_PACKAGES = \
encoding/git85/check \
encoding/hex/check \
encoding/pem/check \
- exp/datafmt/check \
+ exp/ebnf/check \
exp/norm/check \
- exp/regexp/check \
- exp/regexp/syntax/check \
+ exp/spdy/check \
+ exp/sql/check \
+ exp/ssh/check \
+ exp/terminal/check \
exp/template/html/check \
go/ast/check \
$(go_build_check_omitted_since_it_calls_6g) \
@@ -3472,7 +3565,6 @@ TEST_PACKAGES = \
go/printer/check \
go/scanner/check \
go/token/check \
- go/typechecker/check \
$(go_types_check_omitted_since_it_calls_6g) \
hash/adler32/check \
hash/crc32/check \
@@ -3480,7 +3572,6 @@ TEST_PACKAGES = \
hash/fnv/check \
http/cgi/check \
http/fcgi/check \
- http/spdy/check \
image/draw/check \
image/jpeg/check \
image/png/check \
@@ -3490,11 +3581,14 @@ TEST_PACKAGES = \
io/ioutil/check \
mime/multipart/check \
net/textproto/check \
+ old/netchan/check \
+ old/regexp/check \
old/template/check \
$(os_inotify_check) \
os/user/check \
os/signal/check \
path/filepath/check \
+ regexp/syntax/check \
rpc/jsonrpc/check \
sync/atomic/check \
template/parse/check \
diff --git a/libgo/Makefile.in b/libgo/Makefile.in
index cdabd023d1a..4c07233d43d 100644
--- a/libgo/Makefile.in
+++ b/libgo/Makefile.in
@@ -103,7 +103,7 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgoencodingdir)" \
"$(DESTDIR)$(toolexeclibgoexpdir)" \
"$(DESTDIR)$(toolexeclibgoexpguidir)" \
- "$(DESTDIR)$(toolexeclibgoexpregexpdir)" \
+ "$(DESTDIR)$(toolexeclibgoexpsqldir)" \
"$(DESTDIR)$(toolexeclibgoexptemplatedir)" \
"$(DESTDIR)$(toolexeclibgogodir)" \
"$(DESTDIR)$(toolexeclibgohashdir)" \
@@ -116,6 +116,7 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibgoolddir)" \
"$(DESTDIR)$(toolexeclibgoosdir)" \
"$(DESTDIR)$(toolexeclibgopathdir)" \
+ "$(DESTDIR)$(toolexeclibgoregexpdir)" \
"$(DESTDIR)$(toolexeclibgorpcdir)" \
"$(DESTDIR)$(toolexeclibgoruntimedir)" \
"$(DESTDIR)$(toolexeclibgosyncdir)" \
@@ -131,22 +132,21 @@ LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
am__DEPENDENCIES_1 =
am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
bytes/bytes.lo bytes/index.lo cmath/cmath.lo crypto/crypto.lo \
- csv/csv.lo ebnf/ebnf.lo exec/exec.lo expvar/expvar.lo \
- flag/flag.lo fmt/fmt.lo gob/gob.lo hash/hash.lo html/html.lo \
- http/http.lo image/image.lo io/io.lo json/json.lo log/log.lo \
- math/math.lo mail/mail.lo mime/mime.lo net/net.lo \
- netchan/netchan.lo os/os.lo patch/patch.lo path/path.lo \
- rand/rand.lo reflect/reflect.lo regexp/regexp.lo rpc/rpc.lo \
- runtime/runtime.lo scanner/scanner.lo smtp/smtp.lo \
+ csv/csv.lo exec/exec.lo expvar/expvar.lo flag/flag.lo \
+ fmt/fmt.lo gob/gob.lo hash/hash.lo html/html.lo http/http.lo \
+ image/image.lo io/io.lo json/json.lo log/log.lo math/math.lo \
+ mail/mail.lo mime/mime.lo net/net.lo os/os.lo patch/patch.lo \
+ path/path.lo rand/rand.lo reflect/reflect.lo regexp/regexp.lo \
+ rpc/rpc.lo runtime/runtime.lo scanner/scanner.lo smtp/smtp.lo \
sort/sort.lo strconv/strconv.lo strings/strings.lo \
sync/sync.lo syslog/syslog.lo syslog/syslog_c.lo \
tabwriter/tabwriter.lo template/template.lo time/time.lo \
- try/try.lo unicode/unicode.lo url/url.lo utf16/utf16.lo \
- utf8/utf8.lo websocket/websocket.lo xml/xml.lo archive/tar.lo \
+ unicode/unicode.lo url/url.lo utf16/utf16.lo utf8/utf8.lo \
+ websocket/websocket.lo xml/xml.lo archive/tar.lo \
archive/zip.lo compress/bzip2.lo compress/flate.lo \
compress/gzip.lo compress/lzw.lo compress/zlib.lo \
container/heap.lo container/list.lo container/ring.lo \
- container/vector.lo crypto/aes.lo crypto/blowfish.lo \
+ crypto/aes.lo crypto/bcrypt.lo crypto/blowfish.lo \
crypto/cast5.lo crypto/cipher.lo crypto/des.lo crypto/dsa.lo \
crypto/ecdsa.lo crypto/elliptic.lo crypto/hmac.lo \
crypto/md4.lo crypto/md5.lo crypto/ocsp.lo crypto/openpgp.lo \
@@ -159,21 +159,22 @@ am__DEPENDENCIES_2 = asn1/asn1.lo big/big.lo bufio/bufio.lo \
crypto/x509/pkix.lo debug/dwarf.lo debug/elf.lo debug/gosym.lo \
debug/macho.lo debug/pe.lo encoding/ascii85.lo \
encoding/base32.lo encoding/base64.lo encoding/binary.lo \
- encoding/git85.lo encoding/hex.lo encoding/pem.lo \
- exp/datafmt.lo exp/gui.lo exp/norm.lo exp/regexp.lo \
- exp/gui/x11.lo exp/regexp/syntax.lo exp/template/html.lo \
- go/ast.lo go/build.lo go/doc.lo go/parser.lo go/printer.lo \
- go/scanner.lo go/token.lo go/typechecker.lo go/types.lo \
+ encoding/git85.lo encoding/hex.lo encoding/pem.lo exp/ebnf.lo \
+ exp/gui.lo exp/norm.lo exp/spdy.lo exp/sql.lo exp/ssh.lo \
+ exp/terminal.lo exp/types.lo exp/gui/x11.lo exp/sql/driver.lo \
+ exp/template/html.lo go/ast.lo go/build.lo go/doc.lo \
+ go/parser.lo go/printer.lo go/scanner.lo go/token.lo \
hash/adler32.lo hash/crc32.lo hash/crc64.lo hash/fnv.lo \
http/cgi.lo http/fcgi.lo http/httptest.lo http/pprof.lo \
- http/spdy.lo image/bmp.lo image/draw.lo image/gif.lo \
+ image/bmp.lo image/color.lo image/draw.lo image/gif.lo \
image/jpeg.lo image/png.lo image/tiff.lo image/ycbcr.lo \
index/suffixarray.lo io/ioutil.lo mime/multipart.lo \
- net/dict.lo net/textproto.lo old/template.lo \
- $(am__DEPENDENCIES_1) os/user.lo os/signal.lo path/filepath.lo \
- rpc/jsonrpc.lo runtime/debug.lo runtime/pprof.lo \
- sync/atomic.lo sync/atomic_c.lo syscalls/syscall.lo \
- syscalls/errno.lo template/parse.lo testing/testing.lo \
+ net/dict.lo net/textproto.lo old/netchan.lo old/regexp.lo \
+ old/template.lo $(am__DEPENDENCIES_1) os/user.lo os/signal.lo \
+ path/filepath.lo regexp/syntax.lo rpc/jsonrpc.lo \
+ runtime/debug.lo runtime/pprof.lo sync/atomic.lo \
+ sync/atomic_c.lo syscall/syscall.lo syscall/errno.lo \
+ syscall/wait.lo template/parse.lo testing/testing.lo \
testing/iotest.lo testing/quick.lo testing/script.lo
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
@@ -221,8 +222,8 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \
runtime/mem_posix_memalign.c runtime/mem.c runtime/mfinal.c \
runtime/mfixalloc.c runtime/mgc0.c runtime/mheap.c \
runtime/msize.c runtime/proc.c runtime/thread.c \
- runtime/rtems-task-variable-add.c chan.c iface.c malloc.c \
- map.c mprof.c reflect.c sigqueue.c string.c
+ runtime/yield.c runtime/rtems-task-variable-add.c chan.c \
+ iface.c malloc.c map.c mprof.c reflect.c sigqueue.c string.c
@HAVE_SYS_MMAN_H_FALSE@am__objects_1 = mem_posix_memalign.lo
@HAVE_SYS_MMAN_H_TRUE@am__objects_1 = mem.lo
@LIBGO_IS_RTEMS_TRUE@am__objects_2 = rtems-task-variable-add.lo
@@ -253,9 +254,9 @@ am__objects_3 = go-append.lo go-assert.lo go-assert-interface.lo \
go-unreflect.lo go-unsafe-new.lo go-unsafe-newarray.lo \
go-unsafe-pointer.lo go-unwind.lo cpuprof.lo mcache.lo \
mcentral.lo $(am__objects_1) mfinal.lo mfixalloc.lo mgc0.lo \
- mheap.lo msize.lo proc.lo thread.lo $(am__objects_2) chan.lo \
- iface.lo malloc.lo map.lo mprof.lo reflect.lo sigqueue.lo \
- string.lo
+ mheap.lo msize.lo proc.lo thread.lo yield.lo $(am__objects_2) \
+ chan.lo iface.lo malloc.lo map.lo mprof.lo reflect.lo \
+ sigqueue.lo string.lo
am_libgo_la_OBJECTS = $(am__objects_3)
libgo_la_OBJECTS = $(am_libgo_la_OBJECTS)
libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -294,16 +295,16 @@ DATA = $(toolexeclibgo_DATA) $(toolexeclibgoarchive_DATA) \
$(toolexeclibgocrypto_DATA) $(toolexeclibgocryptoopenpgp_DATA) \
$(toolexeclibgocryptox509_DATA) $(toolexeclibgodebug_DATA) \
$(toolexeclibgoencoding_DATA) $(toolexeclibgoexp_DATA) \
- $(toolexeclibgoexpgui_DATA) $(toolexeclibgoexpregexp_DATA) \
+ $(toolexeclibgoexpgui_DATA) $(toolexeclibgoexpsql_DATA) \
$(toolexeclibgoexptemplate_DATA) $(toolexeclibgogo_DATA) \
$(toolexeclibgohash_DATA) $(toolexeclibgohttp_DATA) \
$(toolexeclibgoimage_DATA) $(toolexeclibgoindex_DATA) \
$(toolexeclibgoio_DATA) $(toolexeclibgomime_DATA) \
$(toolexeclibgonet_DATA) $(toolexeclibgoold_DATA) \
$(toolexeclibgoos_DATA) $(toolexeclibgopath_DATA) \
- $(toolexeclibgorpc_DATA) $(toolexeclibgoruntime_DATA) \
- $(toolexeclibgosync_DATA) $(toolexeclibgotemplate_DATA) \
- $(toolexeclibgotesting_DATA)
+ $(toolexeclibgoregexp_DATA) $(toolexeclibgorpc_DATA) \
+ $(toolexeclibgoruntime_DATA) $(toolexeclibgosync_DATA) \
+ $(toolexeclibgotemplate_DATA) $(toolexeclibgotesting_DATA)
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
@@ -376,7 +377,10 @@ GOARCH = @GOARCH@
GOC = @GOC@
GOCFLAGS = $(CFLAGS)
GOOS = @GOOS@
-GO_SYSCALLS_SYSCALL_OS_ARCH_FILE = @GO_SYSCALLS_SYSCALL_OS_ARCH_FILE@
+GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@
+GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@
+GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@
+GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -420,9 +424,11 @@ RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
+SIZEOF_STRUCT_EPOLL_EVENT = @SIZEOF_STRUCT_EPOLL_EVENT@
SPLIT_STACK = @SPLIT_STACK@
STRINGOPS_FLAG = @STRINGOPS_FLAG@
STRIP = @STRIP@
+STRUCT_EPOLL_EVENT_FD_OFFSET = @STRUCT_EPOLL_EVENT_FD_OFFSET@
VERSION = @VERSION@
WARN_FLAGS = @WARN_FLAGS@
WERROR = @WERROR@
@@ -572,7 +578,6 @@ toolexeclibgo_DATA = \
cmath.gox \
crypto.gox \
csv.gox \
- ebnf.gox \
exec.gox \
expvar.gox \
flag.gox \
@@ -589,7 +594,6 @@ toolexeclibgo_DATA = \
mail.gox \
mime.gox \
net.gox \
- netchan.gox \
os.gox \
patch.gox \
path.gox \
@@ -610,7 +614,6 @@ toolexeclibgo_DATA = \
template.gox \
testing.gox \
time.gox \
- try.gox \
unicode.gox \
url.gox \
utf16.gox \
@@ -635,12 +638,12 @@ toolexeclibgocontainerdir = $(toolexeclibgodir)/container
toolexeclibgocontainer_DATA = \
container/heap.gox \
container/list.gox \
- container/ring.gox \
- container/vector.gox
+ container/ring.gox
toolexeclibgocryptodir = $(toolexeclibgodir)/crypto
toolexeclibgocrypto_DATA = \
crypto/aes.gox \
+ crypto/bcrypt.gox \
crypto/blowfish.gox \
crypto/cast5.gox \
crypto/cipher.gox \
@@ -698,18 +701,22 @@ toolexeclibgoencoding_DATA = \
toolexeclibgoexpdir = $(toolexeclibgodir)/exp
toolexeclibgoexp_DATA = \
- exp/datafmt.gox \
+ exp/ebnf.gox \
exp/gui.gox \
exp/norm.gox \
- exp/regexp.gox
+ exp/spdy.gox \
+ exp/sql.gox \
+ exp/ssh.gox \
+ exp/terminal.gox \
+ exp/types.gox
toolexeclibgoexpguidir = $(toolexeclibgoexpdir)/gui
toolexeclibgoexpgui_DATA = \
exp/gui/x11.gox
-toolexeclibgoexpregexpdir = $(toolexeclibgoexpdir)/regexp
-toolexeclibgoexpregexp_DATA = \
- exp/regexp/syntax.gox
+toolexeclibgoexpsqldir = $(toolexeclibgoexpdir)/sql
+toolexeclibgoexpsql_DATA = \
+ exp/sql/driver.gox
toolexeclibgoexptemplatedir = $(toolexeclibgoexpdir)/template
toolexeclibgoexptemplate_DATA = \
@@ -723,9 +730,7 @@ toolexeclibgogo_DATA = \
go/parser.gox \
go/printer.gox \
go/scanner.gox \
- go/token.gox \
- go/typechecker.gox \
- go/types.gox
+ go/token.gox
toolexeclibgohashdir = $(toolexeclibgodir)/hash
toolexeclibgohash_DATA = \
@@ -739,12 +744,12 @@ toolexeclibgohttp_DATA = \
http/cgi.gox \
http/fcgi.gox \
http/httptest.gox \
- http/pprof.gox \
- http/spdy.gox
+ http/pprof.gox
toolexeclibgoimagedir = $(toolexeclibgodir)/image
toolexeclibgoimage_DATA = \
image/bmp.gox \
+ image/color.gox \
image/draw.gox \
image/gif.gox \
image/jpeg.gox \
@@ -771,6 +776,8 @@ toolexeclibgonet_DATA = \
toolexeclibgoolddir = $(toolexeclibgodir)/old
toolexeclibgoold_DATA = \
+ old/netchan.gox \
+ old/regexp.gox \
old/template.gox
toolexeclibgoosdir = $(toolexeclibgodir)/os
@@ -787,6 +794,10 @@ toolexeclibgopathdir = $(toolexeclibgodir)/path
toolexeclibgopath_DATA = \
path/filepath.gox
+toolexeclibgoregexpdir = $(toolexeclibgodir)/regexp
+toolexeclibgoregexp_DATA = \
+ regexp/syntax.gox
+
toolexeclibgorpcdir = $(toolexeclibgodir)/rpc
toolexeclibgorpc_DATA = \
rpc/jsonrpc.gox
@@ -906,6 +917,7 @@ runtime_files = \
runtime/msize.c \
runtime/proc.c \
runtime/thread.c \
+ runtime/yield.c \
$(rtems_task_variable_add_file) \
chan.c \
iface.c \
@@ -961,10 +973,6 @@ go_csv_files = \
go/csv/reader.go \
go/csv/writer.go
-go_ebnf_files = \
- go/ebnf/ebnf.go \
- go/ebnf/parser.go
-
go_exec_files = \
go/exec/exec.go \
go/exec/lp_unix.go
@@ -1000,6 +1008,7 @@ go_html_files = \
go/html/escape.go \
go/html/node.go \
go/html/parse.go \
+ go/html/render.go \
go/html/token.go
go_http_files = \
@@ -1007,6 +1016,7 @@ go_http_files = \
go/http/client.go \
go/http/cookie.go \
go/http/dump.go \
+ go/http/filetransport.go \
go/http/fs.go \
go/http/header.go \
go/http/lex.go \
@@ -1021,7 +1031,6 @@ go_http_files = \
go/http/transport.go
go_image_files = \
- go/image/color.go \
go/image/format.go \
go/image/geom.go \
go/image/image.go \
@@ -1044,6 +1053,7 @@ go_log_files = \
go/log/log.go
go_math_files = \
+ go/math/abs.go \
go/math/acosh.go \
go/math/asin.go \
go/math/asinh.go \
@@ -1054,15 +1064,13 @@ go_math_files = \
go/math/cbrt.go \
go/math/const.go \
go/math/copysign.go \
+ go/math/dim.go \
go/math/erf.go \
go/math/exp.go \
go/math/exp_port.go \
go/math/exp2.go \
go/math/expm1.go \
- go/math/fabs.go \
- go/math/fdim.go \
go/math/floor.go \
- go/math/fmod.go \
go/math/frexp.go \
go/math/gamma.go \
go/math/hypot.go \
@@ -1076,6 +1084,7 @@ go_math_files = \
go/math/log1p.go \
go/math/log10.go \
go/math/logb.go \
+ go/math/mod.go \
go/math/modf.go \
go/math/nextafter.go \
go/math/pow.go \
@@ -1154,11 +1163,6 @@ go_net_files = \
go/net/unixsock.go \
go/net/unixsock_posix.go
-go_netchan_files = \
- go/netchan/common.go \
- go/netchan/export.go \
- go/netchan/import.go
-
@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@go_os_dir_file = go/os/dir_regfile.go
@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@go_os_dir_file = go/os/dir_largefile.go
@LIBGO_IS_386_TRUE@@LIBGO_IS_SOLARIS_TRUE@go_os_dir_file = go/os/dir_largefile.go
@@ -1216,6 +1220,7 @@ go_reflect_files = \
go/reflect/value.go
go_regexp_files = \
+ go/regexp/exec.go \
go/regexp/regexp.go
go_rpc_files = \
@@ -1255,6 +1260,7 @@ go_strconv_files = \
go_strings_files = \
go/strings/reader.go \
+ go/strings/replace.go \
go/strings/strings.go
go_sync_files = \
@@ -1287,21 +1293,19 @@ go_template_files = \
go_testing_files = \
go/testing/benchmark.go \
+ go/testing/example.go \
go/testing/testing.go
go_time_files = \
go/time/format.go \
go/time/sleep.go \
go/time/sys.go \
- go/time/sys_posix.go \
+ go/time/sys_unix.go \
go/time/tick.go \
go/time/time.go \
go/time/zoneinfo_posix.go \
go/time/zoneinfo_unix.go
-go_try_files = \
- go/try/try.go
-
go_unicode_files = \
go/unicode/casetables.go \
go/unicode/digit.go \
@@ -1321,6 +1325,8 @@ go_utf8_files = \
go_websocket_files = \
go/websocket/client.go \
+ go/websocket/hixie.go \
+ go/websocket/hybi.go \
go/websocket/server.go \
go/websocket/websocket.go
@@ -1375,17 +1381,15 @@ go_container_list_files = \
go_container_ring_files = \
go/container/ring/ring.go
-go_container_vector_files = \
- go/container/vector/defs.go \
- go/container/vector/intvector.go \
- go/container/vector/stringvector.go \
- go/container/vector/vector.go
-
go_crypto_aes_files = \
go/crypto/aes/block.go \
go/crypto/aes/cipher.go \
go/crypto/aes/const.go
+go_crypto_bcrypt_files = \
+ go/crypto/bcrypt/base64.go \
+ go/crypto/bcrypt/bcrypt.go
+
go_crypto_blowfish_files = \
go/crypto/blowfish/block.go \
go/crypto/blowfish/const.go \
@@ -1478,6 +1482,7 @@ go_crypto_tls_files = \
go/crypto/tls/handshake_server.go \
go/crypto/tls/key_agreement.go \
go/crypto/tls/prf.go \
+ go/crypto/tls/root_unix.go \
go/crypto/tls/tls.go
go_crypto_twofish_files = \
@@ -1485,6 +1490,7 @@ go_crypto_twofish_files = \
go_crypto_x509_files = \
go/crypto/x509/cert_pool.go \
+ go/crypto/x509/pkcs1.go \
go/crypto/x509/verify.go \
go/crypto/x509/x509.go
@@ -1556,7 +1562,8 @@ go_encoding_base64_files = \
go/encoding/base64/base64.go
go_encoding_binary_files = \
- go/encoding/binary/binary.go
+ go/encoding/binary/binary.go \
+ go/encoding/binary/varint.go
go_encoding_git85_files = \
go/encoding/git85/git.go
@@ -1567,9 +1574,9 @@ go_encoding_hex_files = \
go_encoding_pem_files = \
go/encoding/pem/pem.go
-go_exp_datafmt_files = \
- go/exp/datafmt/datafmt.go \
- go/exp/datafmt/parser.go
+go_exp_ebnf_files = \
+ go/exp/ebnf/ebnf.go \
+ go/exp/ebnf/parser.go
go_exp_gui_files = \
go/exp/gui/gui.go
@@ -1577,29 +1584,63 @@ go_exp_gui_files = \
go_exp_norm_files = \
go/exp/norm/composition.go \
go/exp/norm/forminfo.go \
+ go/exp/norm/input.go \
go/exp/norm/normalize.go \
+ go/exp/norm/readwriter.go \
go/exp/norm/tables.go \
go/exp/norm/trie.go
-go_exp_regexp_files = \
- go/exp/regexp/exec.go \
- go/exp/regexp/regexp.go
+go_exp_spdy_files = \
+ go/exp/spdy/read.go \
+ go/exp/spdy/types.go \
+ go/exp/spdy/write.go
+
+go_exp_sql_files = \
+ go/exp/sql/convert.go \
+ go/exp/sql/sql.go
+
+go_exp_ssh_files = \
+ go/exp/ssh/channel.go \
+ go/exp/ssh/common.go \
+ go/exp/ssh/doc.go \
+ go/exp/ssh/messages.go \
+ go/exp/ssh/server.go \
+ go/exp/ssh/server_shell.go \
+ go/exp/ssh/transport.go
+
+go_exp_terminal_files = \
+ go/exp/terminal/shell.go \
+ go/exp/terminal/terminal.go
+
+go_exp_types_files = \
+ go/exp/types/check.go \
+ go/exp/types/const.go \
+ go/exp/types/exportdata.go \
+ go/exp/types/gcimporter.go \
+ go/exp/types/types.go \
+ go/exp/types/universe.go
go_exp_gui_x11_files = \
go/exp/gui/x11/auth.go \
go/exp/gui/x11/conn.go
+go_exp_sql_driver_files = \
+ go/exp/sql/driver/driver.go \
+ go/exp/sql/driver/types.go
+
go_exp_template_html_files = \
+ go/exp/template/html/attr.go \
+ go/exp/template/html/clone.go \
+ go/exp/template/html/content.go \
go/exp/template/html/context.go \
- go/exp/template/html/escape.go
-
-go_exp_regexp_syntax_files = \
- go/exp/regexp/syntax/compile.go \
- go/exp/regexp/syntax/parse.go \
- go/exp/regexp/syntax/perl_groups.go \
- go/exp/regexp/syntax/prog.go \
- go/exp/regexp/syntax/regexp.go \
- go/exp/regexp/syntax/simplify.go
+ go/exp/template/html/css.go \
+ go/exp/template/html/doc.go \
+ go/exp/template/html/error.go \
+ go/exp/template/html/escape.go \
+ go/exp/template/html/html.go \
+ go/exp/template/html/js.go \
+ go/exp/template/html/transition.go \
+ go/exp/template/html/url.go
go_go_ast_files = \
go/go/ast/ast.go \
@@ -1617,7 +1658,8 @@ go_go_build_files = \
go_go_doc_files = \
go/go/doc/comment.go \
- go/go/doc/doc.go
+ go/go/doc/doc.go \
+ go/go/doc/example.go
go_go_parser_files = \
go/go/parser/interface.go \
@@ -1633,22 +1675,9 @@ go_go_scanner_files = \
go_go_token_files = \
go/go/token/position.go \
+ go/go/token/serialize.go \
go/go/token/token.go
-go_go_typechecker_files = \
- go/go/typechecker/scope.go \
- go/go/typechecker/type.go \
- go/go/typechecker/typechecker.go \
- go/go/typechecker/universe.go
-
-go_go_types_files = \
- go/go/types/check.go \
- go/go/types/const.go \
- go/go/types/exportdata.go \
- go/go/types/gcimporter.go \
- go/go/types/types.go \
- go/go/types/universe.go
-
go_hash_adler32_files = \
go/hash/adler32/adler32.go
@@ -1677,14 +1706,12 @@ go_http_httptest_files = \
go_http_pprof_files = \
go/http/pprof/pprof.go
-go_http_spdy_files = \
- go/http/spdy/read.go \
- go/http/spdy/types.go \
- go/http/spdy/write.go
-
go_image_bmp_files = \
go/image/bmp/reader.go
+go_image_color_files = \
+ go/image/color/color.go
+
go_image_draw_files = \
go/image/draw/draw.go
@@ -1704,6 +1731,7 @@ go_image_png_files = \
go_image_tiff_files = \
go/image/tiff/buffer.go \
+ go/image/tiff/compress.go \
go/image/tiff/consts.go \
go/image/tiff/reader.go
@@ -1733,6 +1761,14 @@ go_net_textproto_files = \
go/net/textproto/textproto.go \
go/net/textproto/writer.go
+go_old_netchan_files = \
+ go/old/netchan/common.go \
+ go/old/netchan/export.go \
+ go/old/netchan/import.go
+
+go_old_regexp_files = \
+ go/old/regexp/regexp.go
+
go_old_template_files = \
go/old/template/doc.go \
go/old/template/execute.go \
@@ -1754,6 +1790,14 @@ go_path_filepath_files = \
go/path/filepath/path.go \
go/path/filepath/path_unix.go
+go_regexp_syntax_files = \
+ go/regexp/syntax/compile.go \
+ go/regexp/syntax/parse.go \
+ go/regexp/syntax/perl_groups.go \
+ go/regexp/syntax/prog.go \
+ go/regexp/syntax/regexp.go \
+ go/regexp/syntax/simplify.go
+
go_rpc_jsonrpc_files = \
go/rpc/jsonrpc/client.go \
go/rpc/jsonrpc/server.go
@@ -1787,97 +1831,85 @@ go_testing_quick_files = \
go_testing_script_files = \
go/testing/script/script.go
-@LIBGO_IS_RTEMS_FALSE@syscall_syscall_file = syscalls/syscall.go
+@LIBGO_IS_RTEMS_FALSE@syscall_syscall_file = go/syscall/syscall_unix.go
# Define Syscall and Syscall6.
-@LIBGO_IS_RTEMS_TRUE@syscall_syscall_file = syscalls/syscall_stubs.go
-# Use lseek on 64-bit Solaris.
-@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_filesize_file = syscalls/sysfile_regfile.go
-# Use lseek64 on 32-bit Solaris/SPARC.
-@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go
-# Use lseek64 on 32-bit Solaris/x86.
-@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go
-# Use lseek by default.
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_filesize_file = syscalls/sysfile_regfile.go
+@LIBGO_IS_RTEMS_TRUE@syscall_syscall_file = go/syscall/syscall_stubs.go
+@LIBGO_IS_RTEMS_FALSE@syscall_exec_file = go/syscall/exec_unix.go
-# Declare libc functions that vary for largefile systems.
-# Always use lseek64 on GNU/Linux.
-@LIBGO_IS_LINUX_TRUE@syscall_filesize_file = syscalls/sysfile_largefile.go
-@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_stat_file = syscalls/sysfile_stat_regfile.go
-@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go
-@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_stat_file = syscalls/sysfile_stat_regfile.go
-@LIBGO_IS_LINUX_TRUE@syscall_stat_file = syscalls/sysfile_stat_largefile.go
-@LIBGO_IS_RTEMS_FALSE@syscall_exec_os_file = syscalls/exec.go
-
-# Define ForkExec, PtraceForkExec, and Exec.
-@LIBGO_IS_RTEMS_TRUE@syscall_exec_os_file = syscalls/exec_stubs.go
-@HAVE_WAIT4_FALSE@syscall_wait_file = syscalls/waitpid.go
+# Define ForkExec and Exec.
+@LIBGO_IS_RTEMS_TRUE@syscall_exec_file = go/syscall/exec_stubs.go
+@HAVE_WAIT4_FALSE@syscall_wait_file = go/syscall/libcall_waitpid.go
# Define Wait4.
-@HAVE_WAIT4_TRUE@syscall_wait_file = syscalls/wait4.go
-@LIBGO_IS_RTEMS_FALSE@syscall_sleep_file = syscalls/sleep_select.go
+@HAVE_WAIT4_TRUE@syscall_wait_file = go/syscall/libcall_wait4.go
+@LIBGO_IS_RTEMS_FALSE@syscall_sleep_file = go/syscall/sleep_select.go
# Define Sleep.
-@LIBGO_IS_RTEMS_TRUE@syscall_sleep_file = syscalls/sleep_rtems.go
-@HAVE_STRERROR_R_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = syscalls/errstr_nor.go
-@HAVE_STRERROR_R_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = syscalls/errstr.go
+@LIBGO_IS_RTEMS_TRUE@syscall_sleep_file = go/syscall/sleep_rtems.go
+@HAVE_STRERROR_R_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = go/syscall/errstr_nor.go
+@HAVE_STRERROR_R_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_file = go/syscall/errstr.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_TRUE@syscall_errstr_file = go/syscall/errstr_linux.go
# Define Errstr.
-@LIBGO_IS_RTEMS_TRUE@syscall_errstr_file = syscalls/errstr_rtems.go
-# On other systems we hope strerror_r is just strerror_r.
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_decl_file = syscalls/errstr_decl.go
-# On GNU/Linux the POSIX strerror_r is called __xpg_strerror_r.
-@LIBGO_IS_LINUX_TRUE@@LIBGO_IS_RTEMS_FALSE@syscall_errstr_decl_file = syscalls/errstr_decl_linux.go
-
-# Declare libc_strerror_r which is the Go name for strerror_r.
-# RTEMS uses newlib in which strerror_r returns char *.
-@LIBGO_IS_RTEMS_TRUE@syscall_errstr_decl_file = syscalls/errstr_decl_rtems.go
-@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_os_file = syscalls/socket_bsd.go
-@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_os_file = syscalls/socket_irix.go
-@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_socket_os_file = syscalls/socket_solaris.go
+@LIBGO_IS_LINUX_TRUE@syscall_errstr_file = go/syscall/errstr_linux.go
+# Use lseek on 64-bit Solaris.
+@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_FALSE@syscall_size_file = go/syscall/libcall_posix_regfile.go
+# Use lseek64 on 32-bit Solaris/SPARC.
+@LIBGO_IS_386_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@@LIBGO_IS_SPARC_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
+# Use lseek64 on 32-bit Solaris/x86.
+@LIBGO_IS_386_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
+# Use lseek by default.
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_size_file = go/syscall/libcall_posix_regfile.go
-# Define socket sizes and types.
-@LIBGO_IS_LINUX_TRUE@syscall_socket_os_file = syscalls/socket_linux.go
-@LIBGO_IS_LINUX_FALSE@syscall_socket_epoll_file =
+# Declare libc functions that vary for largefile systems.
+# Always use lseek64 on GNU/Linux.
+@LIBGO_IS_LINUX_TRUE@syscall_size_file = go/syscall/libcall_posix_largefile.go
+@LIBGO_IS_IRIX_FALSE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_bsd.go
+@LIBGO_IS_IRIX_TRUE@@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_FALSE@syscall_socket_file = go/syscall/socket_irix.go
+@LIBGO_IS_LINUX_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_socket_file = go/syscall/socket_solaris.go
-# Support for epoll.
-@LIBGO_IS_LINUX_TRUE@syscall_socket_epoll_file = syscalls/socket_epoll.go
-@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = syscalls/syscall_uname.go
+# Define socket sizes and types.
+@LIBGO_IS_LINUX_TRUE@syscall_socket_file = go/syscall/socket_linux.go epoll.go
+@LIBGO_IS_386_FALSE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file = go/syscall/libcall_uname.go
# Support for uname.
-# 32-bit Solaris 2/x86 needs _nuname, handled in syscall_solaris_386.go.
+# 32-bit Solaris 2/x86 needs _nuname, handled in libcall_solaris_386.go.
@LIBGO_IS_386_TRUE@@LIBGO_IS_SOLARIS_TRUE@syscall_uname_file =
-@LIBGO_IS_SOLARIS_FALSE@syscall_uname_file = syscalls/syscall_uname.go
+@LIBGO_IS_SOLARIS_FALSE@syscall_uname_file = go/syscall/libcall_uname.go
@LIBGO_IS_LINUX_FALSE@syscall_netlink_file =
# Support for netlink sockets and messages.
-@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = syscalls/netlink_linux.go
-go_syscall_files = \
- $(syscall_errstr_file) \
- $(syscall_errstr_decl_file) \
- syscalls/exec_helpers.go \
- $(syscall_exec_os_file) \
+@LIBGO_IS_LINUX_TRUE@syscall_netlink_file = go/syscall/netlink_linux.go
+go_base_syscall_files = \
+ go/syscall/libcall_support.go \
+ go/syscall/libcall_posix.go \
+ go/syscall/socket.go \
+ go/syscall/str.go \
+ go/syscall/syscall.go \
+ $(syscall_syscall_file) \
+ $(syscall_exec_file) \
$(syscall_wait_file) \
- $(syscall_filesize_file) \
- $(syscall_netlink_file) \
- $(syscall_stat_file) \
$(syscall_sleep_file) \
- syscalls/socket.go \
- $(syscall_socket_os_file) \
- $(syscall_socket_epoll_file) \
- $(syscall_syscall_file) \
+ $(syscall_errstr_file) \
+ $(syscall_size_file) \
+ $(syscall_socket_file) \
$(syscall_uname_file) \
- syscalls/syscall_unix.go \
- syscalls/stringbyte.go \
- syscalls/syscall_$(GOOS).go \
- $(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE) \
- syscalls/sysfile_posix.go \
+ $(syscall_netlink_file) \
+ $(GO_LIBCALL_OS_FILE) \
+ $(GO_LIBCALL_OS_ARCH_FILE) \
+ $(GO_SYSCALL_OS_FILE) \
+ $(GO_SYSCALL_OS_ARCH_FILE)
+
+go_syscall_files = \
+ $(go_base_syscall_files) \
+ libcalls.go \
sysinfo.go \
syscall_arch.go
go_syscall_c_files = \
- syscalls/errno.c
+ go/syscall/errno.c \
+ go/syscall/wait.c
@LIBGO_IS_LINUX_FALSE@os_lib_inotify_lo =
@@ -1892,7 +1924,6 @@ libgo_go_objs = \
cmath/cmath.lo \
crypto/crypto.lo \
csv/csv.lo \
- ebnf/ebnf.lo \
exec/exec.lo \
expvar/expvar.lo \
flag/flag.lo \
@@ -1909,7 +1940,6 @@ libgo_go_objs = \
mail/mail.lo \
mime/mime.lo \
net/net.lo \
- netchan/netchan.lo \
os/os.lo \
patch/patch.lo \
path/path.lo \
@@ -1929,7 +1959,6 @@ libgo_go_objs = \
tabwriter/tabwriter.lo \
template/template.lo \
time/time.lo \
- try/try.lo \
unicode/unicode.lo \
url/url.lo \
utf16/utf16.lo \
@@ -1946,8 +1975,8 @@ libgo_go_objs = \
container/heap.lo \
container/list.lo \
container/ring.lo \
- container/vector.lo \
crypto/aes.lo \
+ crypto/bcrypt.lo \
crypto/blowfish.lo \
crypto/cast5.lo \
crypto/cipher.lo \
@@ -1990,12 +2019,16 @@ libgo_go_objs = \
encoding/git85.lo \
encoding/hex.lo \
encoding/pem.lo \
- exp/datafmt.lo \
+ exp/ebnf.lo \
exp/gui.lo \
exp/norm.lo \
- exp/regexp.lo \
+ exp/spdy.lo \
+ exp/sql.lo \
+ exp/ssh.lo \
+ exp/terminal.lo \
+ exp/types.lo \
exp/gui/x11.lo \
- exp/regexp/syntax.lo \
+ exp/sql/driver.lo \
exp/template/html.lo \
go/ast.lo \
go/build.lo \
@@ -2004,8 +2037,6 @@ libgo_go_objs = \
go/printer.lo \
go/scanner.lo \
go/token.lo \
- go/typechecker.lo \
- go/types.lo \
hash/adler32.lo \
hash/crc32.lo \
hash/crc64.lo \
@@ -2014,8 +2045,8 @@ libgo_go_objs = \
http/fcgi.lo \
http/httptest.lo \
http/pprof.lo \
- http/spdy.lo \
image/bmp.lo \
+ image/color.lo \
image/draw.lo \
image/gif.lo \
image/jpeg.lo \
@@ -2027,18 +2058,22 @@ libgo_go_objs = \
mime/multipart.lo \
net/dict.lo \
net/textproto.lo \
+ old/netchan.lo \
+ old/regexp.lo \
old/template.lo \
$(os_lib_inotify_lo) \
os/user.lo \
os/signal.lo \
path/filepath.lo \
+ regexp/syntax.lo \
rpc/jsonrpc.lo \
runtime/debug.lo \
runtime/pprof.lo \
sync/atomic.lo \
sync/atomic_c.lo \
- syscalls/syscall.lo \
- syscalls/errno.lo \
+ syscall/syscall.lo \
+ syscall/errno.lo \
+ syscall/wait.lo \
template/parse.lo \
testing/testing.lo \
testing/iotest.lo \
@@ -2149,7 +2184,6 @@ TEST_PACKAGES = \
bytes/check \
cmath/check \
csv/check \
- ebnf/check \
exec/check \
expvar/check \
flag/check \
@@ -2165,7 +2199,6 @@ TEST_PACKAGES = \
mail/check \
mime/check \
net/check \
- netchan/check \
os/check \
patch/check \
path/check \
@@ -2184,7 +2217,6 @@ TEST_PACKAGES = \
tabwriter/check \
template/check \
time/check \
- try/check \
unicode/check \
url/check \
utf16/check \
@@ -2201,8 +2233,8 @@ TEST_PACKAGES = \
container/heap/check \
container/list/check \
container/ring/check \
- container/vector/check \
crypto/aes/check \
+ crypto/bcrypt/check \
crypto/blowfish/check \
crypto/cast5/check \
crypto/cipher/check \
@@ -2242,10 +2274,12 @@ TEST_PACKAGES = \
encoding/git85/check \
encoding/hex/check \
encoding/pem/check \
- exp/datafmt/check \
+ exp/ebnf/check \
exp/norm/check \
- exp/regexp/check \
- exp/regexp/syntax/check \
+ exp/spdy/check \
+ exp/sql/check \
+ exp/ssh/check \
+ exp/terminal/check \
exp/template/html/check \
go/ast/check \
$(go_build_check_omitted_since_it_calls_6g) \
@@ -2253,7 +2287,6 @@ TEST_PACKAGES = \
go/printer/check \
go/scanner/check \
go/token/check \
- go/typechecker/check \
$(go_types_check_omitted_since_it_calls_6g) \
hash/adler32/check \
hash/crc32/check \
@@ -2261,7 +2294,6 @@ TEST_PACKAGES = \
hash/fnv/check \
http/cgi/check \
http/fcgi/check \
- http/spdy/check \
image/draw/check \
image/jpeg/check \
image/png/check \
@@ -2271,11 +2303,14 @@ TEST_PACKAGES = \
io/ioutil/check \
mime/multipart/check \
net/textproto/check \
+ old/netchan/check \
+ old/regexp/check \
old/template/check \
$(os_inotify_check) \
os/user/check \
os/signal/check \
path/filepath/check \
+ regexp/syntax/check \
rpc/jsonrpc/check \
sync/atomic/check \
template/parse/check \
@@ -2518,6 +2553,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sigqueue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/string.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/yield.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -3198,6 +3234,13 @@ thread.lo: runtime/thread.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thread.lo `test -f 'runtime/thread.c' || echo '$(srcdir)/'`runtime/thread.c
+yield.lo: runtime/yield.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT yield.lo -MD -MP -MF $(DEPDIR)/yield.Tpo -c -o yield.lo `test -f 'runtime/yield.c' || echo '$(srcdir)/'`runtime/yield.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/yield.Tpo $(DEPDIR)/yield.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/yield.c' object='yield.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o yield.lo `test -f 'runtime/yield.c' || echo '$(srcdir)/'`runtime/yield.c
+
rtems-task-variable-add.lo: runtime/rtems-task-variable-add.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT rtems-task-variable-add.lo -MD -MP -MF $(DEPDIR)/rtems-task-variable-add.Tpo -c -o rtems-task-variable-add.lo `test -f 'runtime/rtems-task-variable-add.c' || echo '$(srcdir)/'`runtime/rtems-task-variable-add.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/rtems-task-variable-add.Tpo $(DEPDIR)/rtems-task-variable-add.Plo
@@ -3450,26 +3493,26 @@ uninstall-toolexeclibgoexpguiDATA:
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(toolexeclibgoexpguidir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(toolexeclibgoexpguidir)" && rm -f $$files
-install-toolexeclibgoexpregexpDATA: $(toolexeclibgoexpregexp_DATA)
+install-toolexeclibgoexpsqlDATA: $(toolexeclibgoexpsql_DATA)
@$(NORMAL_INSTALL)
- test -z "$(toolexeclibgoexpregexpdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexpregexpdir)"
- @list='$(toolexeclibgoexpregexp_DATA)'; test -n "$(toolexeclibgoexpregexpdir)" || list=; \
+ test -z "$(toolexeclibgoexpsqldir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexpsqldir)"
+ @list='$(toolexeclibgoexpsql_DATA)'; test -n "$(toolexeclibgoexpsqldir)" || list=; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
- echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexpregexpdir)'"; \
- $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexpregexpdir)" || exit $$?; \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoexpsqldir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoexpsqldir)" || exit $$?; \
done
-uninstall-toolexeclibgoexpregexpDATA:
+uninstall-toolexeclibgoexpsqlDATA:
@$(NORMAL_UNINSTALL)
- @list='$(toolexeclibgoexpregexp_DATA)'; test -n "$(toolexeclibgoexpregexpdir)" || list=; \
+ @list='$(toolexeclibgoexpsql_DATA)'; test -n "$(toolexeclibgoexpsqldir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
test -n "$$files" || exit 0; \
- echo " ( cd '$(DESTDIR)$(toolexeclibgoexpregexpdir)' && rm -f" $$files ")"; \
- cd "$(DESTDIR)$(toolexeclibgoexpregexpdir)" && rm -f $$files
+ echo " ( cd '$(DESTDIR)$(toolexeclibgoexpsqldir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(toolexeclibgoexpsqldir)" && rm -f $$files
install-toolexeclibgoexptemplateDATA: $(toolexeclibgoexptemplate_DATA)
@$(NORMAL_INSTALL)
test -z "$(toolexeclibgoexptemplatedir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoexptemplatedir)"
@@ -3710,6 +3753,26 @@ uninstall-toolexeclibgopathDATA:
test -n "$$files" || exit 0; \
echo " ( cd '$(DESTDIR)$(toolexeclibgopathdir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(toolexeclibgopathdir)" && rm -f $$files
+install-toolexeclibgoregexpDATA: $(toolexeclibgoregexp_DATA)
+ @$(NORMAL_INSTALL)
+ test -z "$(toolexeclibgoregexpdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgoregexpdir)"
+ @list='$(toolexeclibgoregexp_DATA)'; test -n "$(toolexeclibgoregexpdir)" || list=; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(toolexeclibgoregexpdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(toolexeclibgoregexpdir)" || exit $$?; \
+ done
+
+uninstall-toolexeclibgoregexpDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(toolexeclibgoregexp_DATA)'; test -n "$(toolexeclibgoregexpdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ test -n "$$files" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(toolexeclibgoregexpdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(toolexeclibgoregexpdir)" && rm -f $$files
install-toolexeclibgorpcDATA: $(toolexeclibgorpc_DATA)
@$(NORMAL_INSTALL)
test -z "$(toolexeclibgorpcdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibgorpcdir)"
@@ -4127,7 +4190,7 @@ all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) all-multi $(DATA) \
config.h
installdirs: installdirs-recursive
installdirs-am:
- for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgoexpguidir)" "$(DESTDIR)$(toolexeclibgoexpregexpdir)" "$(DESTDIR)$(toolexeclibgoexptemplatedir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohttpdir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgorpcdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotemplatedir)" "$(DESTDIR)$(toolexeclibgotestingdir)"; do \
+ for dir in "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibdir)" "$(DESTDIR)$(toolexeclibgodir)" "$(DESTDIR)$(toolexeclibgoarchivedir)" "$(DESTDIR)$(toolexeclibgocompressdir)" "$(DESTDIR)$(toolexeclibgocontainerdir)" "$(DESTDIR)$(toolexeclibgocryptodir)" "$(DESTDIR)$(toolexeclibgocryptoopenpgpdir)" "$(DESTDIR)$(toolexeclibgocryptox509dir)" "$(DESTDIR)$(toolexeclibgodebugdir)" "$(DESTDIR)$(toolexeclibgoencodingdir)" "$(DESTDIR)$(toolexeclibgoexpdir)" "$(DESTDIR)$(toolexeclibgoexpguidir)" "$(DESTDIR)$(toolexeclibgoexpsqldir)" "$(DESTDIR)$(toolexeclibgoexptemplatedir)" "$(DESTDIR)$(toolexeclibgogodir)" "$(DESTDIR)$(toolexeclibgohashdir)" "$(DESTDIR)$(toolexeclibgohttpdir)" "$(DESTDIR)$(toolexeclibgoimagedir)" "$(DESTDIR)$(toolexeclibgoindexdir)" "$(DESTDIR)$(toolexeclibgoiodir)" "$(DESTDIR)$(toolexeclibgomimedir)" "$(DESTDIR)$(toolexeclibgonetdir)" "$(DESTDIR)$(toolexeclibgoolddir)" "$(DESTDIR)$(toolexeclibgoosdir)" "$(DESTDIR)$(toolexeclibgopathdir)" "$(DESTDIR)$(toolexeclibgoregexpdir)" "$(DESTDIR)$(toolexeclibgorpcdir)" "$(DESTDIR)$(toolexeclibgoruntimedir)" "$(DESTDIR)$(toolexeclibgosyncdir)" "$(DESTDIR)$(toolexeclibgotemplatedir)" "$(DESTDIR)$(toolexeclibgotestingdir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-recursive
@@ -4198,15 +4261,16 @@ install-exec-am: install-multi install-toolexeclibLIBRARIES \
install-toolexeclibgodebugDATA \
install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
install-toolexeclibgoexpguiDATA \
- install-toolexeclibgoexpregexpDATA \
+ install-toolexeclibgoexpsqlDATA \
install-toolexeclibgoexptemplateDATA \
install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
install-toolexeclibgohttpDATA install-toolexeclibgoimageDATA \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
install-toolexeclibgooldDATA install-toolexeclibgoosDATA \
- install-toolexeclibgopathDATA install-toolexeclibgorpcDATA \
- install-toolexeclibgoruntimeDATA install-toolexeclibgosyncDATA \
+ install-toolexeclibgopathDATA install-toolexeclibgoregexpDATA \
+ install-toolexeclibgorpcDATA install-toolexeclibgoruntimeDATA \
+ install-toolexeclibgosyncDATA \
install-toolexeclibgotemplateDATA \
install-toolexeclibgotestingDATA
@@ -4262,7 +4326,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgoencodingDATA \
uninstall-toolexeclibgoexpDATA \
uninstall-toolexeclibgoexpguiDATA \
- uninstall-toolexeclibgoexpregexpDATA \
+ uninstall-toolexeclibgoexpsqlDATA \
uninstall-toolexeclibgoexptemplateDATA \
uninstall-toolexeclibgogoDATA uninstall-toolexeclibgohashDATA \
uninstall-toolexeclibgohttpDATA \
@@ -4270,7 +4334,9 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \
uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
uninstall-toolexeclibgooldDATA uninstall-toolexeclibgoosDATA \
- uninstall-toolexeclibgopathDATA uninstall-toolexeclibgorpcDATA \
+ uninstall-toolexeclibgopathDATA \
+ uninstall-toolexeclibgoregexpDATA \
+ uninstall-toolexeclibgorpcDATA \
uninstall-toolexeclibgoruntimeDATA \
uninstall-toolexeclibgosyncDATA \
uninstall-toolexeclibgotemplateDATA \
@@ -4305,15 +4371,16 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
install-toolexeclibgodebugDATA \
install-toolexeclibgoencodingDATA install-toolexeclibgoexpDATA \
install-toolexeclibgoexpguiDATA \
- install-toolexeclibgoexpregexpDATA \
+ install-toolexeclibgoexpsqlDATA \
install-toolexeclibgoexptemplateDATA \
install-toolexeclibgogoDATA install-toolexeclibgohashDATA \
install-toolexeclibgohttpDATA install-toolexeclibgoimageDATA \
install-toolexeclibgoindexDATA install-toolexeclibgoioDATA \
install-toolexeclibgomimeDATA install-toolexeclibgonetDATA \
install-toolexeclibgooldDATA install-toolexeclibgoosDATA \
- install-toolexeclibgopathDATA install-toolexeclibgorpcDATA \
- install-toolexeclibgoruntimeDATA install-toolexeclibgosyncDATA \
+ install-toolexeclibgopathDATA install-toolexeclibgoregexpDATA \
+ install-toolexeclibgorpcDATA install-toolexeclibgoruntimeDATA \
+ install-toolexeclibgosyncDATA \
install-toolexeclibgotemplateDATA \
install-toolexeclibgotestingDATA installcheck installcheck-am \
installdirs installdirs-am maintainer-clean \
@@ -4333,7 +4400,7 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgoencodingDATA \
uninstall-toolexeclibgoexpDATA \
uninstall-toolexeclibgoexpguiDATA \
- uninstall-toolexeclibgoexpregexpDATA \
+ uninstall-toolexeclibgoexpsqlDATA \
uninstall-toolexeclibgoexptemplateDATA \
uninstall-toolexeclibgogoDATA uninstall-toolexeclibgohashDATA \
uninstall-toolexeclibgohttpDATA \
@@ -4341,7 +4408,9 @@ uninstall-am: uninstall-toolexeclibLIBRARIES \
uninstall-toolexeclibgoindexDATA uninstall-toolexeclibgoioDATA \
uninstall-toolexeclibgomimeDATA uninstall-toolexeclibgonetDATA \
uninstall-toolexeclibgooldDATA uninstall-toolexeclibgoosDATA \
- uninstall-toolexeclibgopathDATA uninstall-toolexeclibgorpcDATA \
+ uninstall-toolexeclibgopathDATA \
+ uninstall-toolexeclibgoregexpDATA \
+ uninstall-toolexeclibgorpcDATA \
uninstall-toolexeclibgoruntimeDATA \
uninstall-toolexeclibgosyncDATA \
uninstall-toolexeclibgotemplateDATA \
@@ -4385,6 +4454,14 @@ s-version: Makefile
$(SHELL) $(srcdir)/../move-if-change version.go.tmp version.go
$(STAMP) $@
+libcalls.go: s-libcalls; @true
+s-libcalls: Makefile go/syscall/mksyscall.awk $(go_base_syscall_files)
+ rm -f libcalls.go.tmp
+ files=`echo $^ | sed -e 's/Makefile//' -e 's|[^ ]*go/syscall/mksyscall.awk||'`; \
+ $(AWK) -f $(srcdir)/go/syscall/mksyscall.awk $${files} > libcalls.go.tmp
+ $(SHELL) $(srcdir)/../move-if-change libcalls.go.tmp libcalls.go
+ $(STAMP) $@
+
syscall_arch.go: s-syscall_arch; @true
s-syscall_arch: Makefile
rm -f syscall_arch.go.tmp
@@ -4394,6 +4471,40 @@ s-syscall_arch: Makefile
$(SHELL) $(srcdir)/../move-if-change syscall_arch.go.tmp syscall_arch.go
$(STAMP) $@
+sysinfo.go: s-sysinfo; @true
+s-sysinfo: $(srcdir)/mksysinfo.sh config.h
+ CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
+ $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
+ $(STAMP) $@
+
+# The epoll struct has an embedded union and is packed on x86_64,
+# which is too complicated for mksysinfo.sh. We find the offset of
+# the only field we care about in configure.ac, and generate the
+# struct here.
+epoll.go: s-epoll; @true
+s-epoll: Makefile
+ rm -f epoll.go.tmp
+ echo 'package syscall' > epoll.go.tmp
+ echo 'type EpollEvent struct {' >> epoll.go.tmp
+ echo ' Events uint32' >> epoll.go.tmp
+ case "$(SIZEOF_STRUCT_EPOLL_EVENT),$(STRUCT_EPOLL_EVENT_FD_OFFSET)" in \
+ 0,0) echo 1>&2 "*** struct epoll_event data.fd offset unknown"; \
+ exit 1; ;; \
+ 8,4) echo ' Fd int32' >> epoll.go.tmp; ;; \
+ 12,4) echo ' Fd int32' >> epoll.go.tmp; \
+ echo ' Pad [4]byte' >> epoll.go.tmp; ;; \
+ 12,8) echo ' Pad [4]byte' >> epoll.go.tmp; \
+ echo ' Fd int32' >> epoll.go.tmp; ;; \
+ 16,8) echo ' Pad [4]byte' >> epoll.go.tmp; \
+ echo ' Fd int32' >> epoll.go.tmp; \
+ echo ' Pad2 [4]byte' >> epoll.go.tmp; ;; \
+ *) echo 1>&2 "*** struct epoll_event unsupported"; \
+ exit 1; ;; \
+ esac
+ echo '}' >> epoll.go.tmp
+ $(SHELL) $(srcdir)/../move-if-change epoll.go.tmp epoll.go
+ $(STAMP) $@
+
asn1/asn1.lo: $(go_asn1_files) big.gox bytes.gox fmt.gox io.gox os.gox \
reflect.gox strconv.gox strings.gox time.gox
$(BUILDPACKAGE)
@@ -4441,13 +4552,6 @@ csv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: csv/check
-ebnf/ebnf.lo: $(go_ebnf_files) container/vector.gox go/scanner.gox \
- go/token.gox os.gox strconv.gox unicode.gox utf8.gox
- $(BUILDPACKAGE)
-ebnf/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: ebnf/check
-
exec/exec.lo: $(go_exec_files) bytes.gox io.gox os.gox strconv.gox \
strings.gox syscall.gox
$(BUILDPACKAGE)
@@ -4469,7 +4573,7 @@ flag/check: $(CHECK_DEPS)
.PHONY: flag/check
fmt/fmt.lo: $(go_fmt_files) bytes.gox io.gox math.gox os.gox reflect.gox \
- strconv.gox strings.gox unicode.gox utf8.gox
+ strconv.gox strings.gox sync.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
fmt/check: $(CHECK_DEPS)
@$(CHECK)
@@ -4489,8 +4593,8 @@ hash/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: hash/check
-html/html.lo: $(go_html_files) bytes.gox io.gox os.gox strconv.gox strings.gox \
- utf8.gox
+html/html.lo: $(go_html_files) bufio.gox bytes.gox fmt.gox io.gox os.gox \
+ strconv.gox strings.gox utf8.gox
$(BUILDPACKAGE)
html/check: $(CHECK_DEPS)
@$(CHECK)
@@ -4507,7 +4611,8 @@ http/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: http/check
-image/image.lo: $(go_image_files) bufio.gox io.gox os.gox strconv.gox
+image/image.lo: $(go_image_files) bufio.gox image/color.gox io.gox os.gox \
+ strconv.gox
$(BUILDPACKAGE)
image/check: $(CHECK_DEPS)
@$(CHECK)
@@ -4563,13 +4668,6 @@ net/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: net/check
-netchan/netchan.lo: $(go_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
- reflect.gox strconv.gox sync.gox time.gox
- $(BUILDPACKAGE)
-netchan/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: netchan/check
-
os/os.lo: $(go_os_files) runtime.gox sync.gox syscall.gox
$(BUILDPACKAGE)
os/check: $(CHECK_DEPS)
@@ -4607,8 +4705,8 @@ reflect/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: reflect/check
-regexp/regexp.lo: $(go_regexp_files) bytes.gox io.gox os.gox strings.gox \
- utf8.gox
+regexp/regexp.lo: $(go_regexp_files) bytes.gox io.gox os.gox \
+ regexp/syntax.gox strconv.gox strings.gox sync.gox utf8.gox
$(BUILDPACKAGE)
regexp/check: $(CHECK_DEPS)
@$(CHECK)
@@ -4655,7 +4753,7 @@ strconv/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: strconv/check
-strings/strings.lo: $(go_strings_files) os.gox unicode.gox utf8.gox
+strings/strings.lo: $(go_strings_files) io.gox os.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
strings/check: $(CHECK_DEPS)
@$(CHECK)
@@ -4690,8 +4788,9 @@ template/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: template/check
-testing/testing.lo: $(go_testing_files) flag.gox fmt.gox os.gox regexp.gox \
- runtime.gox runtime/pprof.gox strings.gox strconv.gox time.gox
+testing/testing.lo: $(go_testing_files) bytes.gox flag.gox fmt.gox io.gox \
+ os.gox regexp.gox runtime.gox runtime/pprof.gox strings.gox \
+ strconv.gox time.gox
$(BUILDPACKAGE)
testing/check: $(CHECK_DEPS)
@$(CHECK)
@@ -4704,12 +4803,6 @@ time/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: time/check
-try/try.lo: $(go_try_files) fmt.gox io.gox os.gox reflect.gox unicode.gox
- $(BUILDPACKAGE)
-try/check: $(CHECK_DEPS)
- @$(CHECK)
-.PHONY: try/check
-
unicode/unicode.lo: $(go_unicode_files)
$(BUILDPACKAGE)
unicode/check: $(CHECK_DEPS)
@@ -4735,8 +4828,10 @@ utf8/check: $(CHECK_DEPS)
.PHONY: utf8/check
websocket/websocket.lo: $(go_websocket_files) bufio.gox bytes.gox \
- crypto/md5.gox crypto/tls.gox encoding/binary.gox fmt.gox \
- http.gox io.gox net.gox os.gox rand.gox strings.gox url.gox
+ crypto/md5.gox crypto/rand.gox crypto/sha1.gox crypto/tls.gox \
+ encoding/base64.gox encoding/binary.gox fmt.gox http.gox \
+ io.gox io/ioutil.gox json.gox net.gox os.gox rand.gox \
+ strings.gox strconv.gox sync.gox url.gox
$(BUILDPACKAGE)
websocket/check: $(CHECK_DEPS)
@$(CHECK)
@@ -4825,13 +4920,6 @@ container/ring/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: container/ring/check
-container/vector.lo: $(go_container_vector_files)
- $(BUILDPACKAGE)
-container/vector/check: $(CHECK_DEPS)
- @$(MKDIR_P) container/vector
- @$(CHECK)
-.PHONY: container/vector/check
-
crypto/aes.lo: $(go_crypto_aes_files) os.gox strconv.gox
$(BUILDPACKAGE)
crypto/aes/check: $(CHECK_DEPS)
@@ -4839,6 +4927,15 @@ crypto/aes/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: crypto/aes/check
+crypto/bcrypt.lo: $(go_crypto_bcrypt_files) crypto/blowfish.gox \
+ crypto/rand.gox crypto/subtle.gox encoding/base64.gox \
+ fmt.gox io.gox os.gox strconv.gox
+ $(BUILDPACKAGE)
+crypto/bcrypt/check: $(CHECK_DEPS)
+ @$(MKDIR_P) crypto/bcrypt
+ @$(CHECK)
+.PHONY: crypto/bcrypt/check
+
crypto/blowfish.lo: $(go_crypto_blowfish_files) os.gox strconv.gox
$(BUILDPACKAGE)
crypto/blowfish/check: $(CHECK_DEPS)
@@ -4991,12 +5088,12 @@ crypto/subtle/check: $(CHECK_DEPS)
.PHONY: crypto/subtle/check
crypto/tls.lo: $(go_crypto_tls_files) big.gox bytes.gox crypto.gox \
- crypto/aes.gox crypto/cipher.gox crypto/elliptic.gox \
- crypto/hmac.gox crypto/md5.gox crypto/rand.gox crypto/rc4.gox \
- crypto/rsa.gox crypto/sha1.gox crypto/subtle.gox \
- crypto/x509.gox crypto/x509/pkix.gox encoding/pem.gox \
- hash.gox io.gox io/ioutil.gox net.gox os.gox strconv.gox \
- strings.gox sync.gox time.gox
+ crypto/aes.gox crypto/cipher.gox crypto/des.gox \
+ crypto/elliptic.gox crypto/hmac.gox crypto/md5.gox \
+ crypto/rand.gox crypto/rc4.gox crypto/rsa.gox crypto/sha1.gox \
+ crypto/subtle.gox crypto/x509.gox crypto/x509/pkix.gox \
+ encoding/pem.gox hash.gox io.gox io/ioutil.gox net.gox os.gox \
+ strconv.gox strings.gox sync.gox time.gox
$(BUILDPACKAGE)
crypto/tls/check: $(CHECK_DEPS)
@$(MKDIR_P) crypto/tls
@@ -5171,14 +5268,13 @@ encoding/pem/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: encoding/pem/check
-exp/datafmt.lo: $(go_exp_datafmt_files) bytes.gox fmt.gox go/scanner.gox \
- go/token.gox io.gox os.gox reflect.gox runtime.gox \
- strconv.gox strings.gox
+exp/ebnf.lo: $(go_exp_ebnf_files) scanner.gox go/token.gox os.gox \
+ strconv.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
-exp/datafmt/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/datafmt
+exp/ebnf/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/ebnf
@$(CHECK)
-.PHONY: exp/datafmt/check
+.PHONY: exp/ebnf/check
exp/gui.lo: $(go_exp_gui_files) image.gox image/draw.gox os.gox
$(BUILDPACKAGE)
@@ -5187,20 +5283,55 @@ exp/gui/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/gui/check
-exp/norm.lo: $(go_exp_norm_files) utf8.gox
+exp/norm.lo: $(go_exp_norm_files) io.gox os.gox utf8.gox
$(BUILDPACKAGE)
exp/norm/check: $(CHECK_DEPS)
@$(MKDIR_P) exp/norm
@$(CHECK)
.PHONY: exp/norm/check
-exp/regexp.lo: $(go_exp_regexp_files) bytes.gox exp/regexp/syntax.gox io.gox \
- os.gox strings.gox sync.gox utf8.gox
+exp/spdy.lo: $(go_exp_spdy_files) bytes.gox compress/zlib.gox \
+ encoding/binary.gox http.gox io.gox os.gox strings.gox
+ $(BUILDPACKAGE)
+exp/spdy/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/spdy
+ @$(CHECK)
+.PHONY: exp/spdy/check
+
+exp/sql.lo: $(go_exp_sql_files) exp/sql/driver.gox fmt.gox os.gox reflect.gox \
+ runtime.gox strconv.gox sync.gox
+ $(BUILDPACKAGE)
+exp/sql/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/sql
+ @$(CHECK)
+.PHONY: exp/sql/check
+
+exp/ssh.lo: $(go_exp_ssh_files) big.gox bufio.gox bytes.gox crypto.gox \
+ crypto/aes.gox crypto/cipher.gox crypto/hmac.gox \
+ crypto/rand.gox crypto/rsa.gox crypto/sha1.gox \
+ crypto/subtle.gox crypto/x509.gox encoding/pem.gox hash.gox \
+ io.gox net.gox os.gox reflect.gox strconv.gox sync.gox
+ $(BUILDPACKAGE)
+exp/ssh/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/ssh
+ @$(CHECK)
+.PHONY: exp/ssh/check
+
+exp/terminal.lo: $(go_exp_terminal_files) io.gox os.gox syscall.gox
+ $(BUILDPACKAGE)
+exp/terminal/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/terminal
+ @$(CHECK)
+.PHONY: exp/terminal/check
+
+exp/types.lo: $(go_exp_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
+ go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
+ scanner.gox sort.gox strconv.gox strings.gox
$(BUILDPACKAGE)
-exp/regexp/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/regexp
+exp/types/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/types
@$(CHECK)
-.PHONY: exp/regexp/check
+.PHONY: exp/types/check
exp/gui/x11.lo: $(go_exp_gui_x11_files) bufio.gox exp/gui.gox image.gox \
image/draw.gox io.gox log.gox net.gox os.gox strconv.gox \
@@ -5211,15 +5342,17 @@ exp/gui/x11/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: exp/gui/x11/check
-exp/regexp/syntax.lo: $(go_exp_regexp_syntax_files) bytes.gox os.gox sort.gox strconv.gox strings.gox unicode.gox utf8.gox
+exp/sql/driver.lo: $(go_exp_sql_driver_files) fmt.gox os.gox reflect.gox \
+ strconv.gox
$(BUILDPACKAGE)
-exp/regexp/syntax/check: $(CHECK_DEPS)
- @$(MKDIR_P) exp/regexp/syntax
+exp/sql/driver/check: $(CHECK_DEPS)
+ @$(MKDIR_P) exp/sql/driver
@$(CHECK)
-.PHONY: exp/regexp/syntax/check
+.PHONY: exp/sql/driver/check
-exp/template/html.lo: $(go_exp_template_html_files) fmt.gox template.gox \
- template/parse.gox
+exp/template/html.lo: $(go_exp_template_html_files) bytes.gox fmt.gox \
+ html.gox json.gox os.gox strings.gox template.gox \
+ template/parse.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
exp/template/html/check: $(CHECK_DEPS)
@$(MKDIR_P) exp/template/html
@@ -5234,9 +5367,10 @@ go/ast/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/ast/check
-go/build.lo: $(go_go_build_files) bytes.gox exec.gox fmt.gox go/parser.gox \
- go/token.gox log.gox os.gox path/filepath.gox regexp.gox \
- runtime.gox strconv.gox strings.gox runtime.gox
+go/build.lo: $(go_go_build_files) bytes.gox exec.gox fmt.gox go/ast.gox \
+ go/doc.gox go/parser.gox go/token.gox io/ioutil.gox log.gox \
+ os.gox path.gox path/filepath.gox regexp.gox runtime.gox \
+ sort.gox strconv.gox strings.gox runtime.gox unicode.gox
$(BUILDPACKAGE)
go/build/check: $(CHECK_DEPS)
@$(MKDIR_P) go/build
@@ -5253,7 +5387,7 @@ s-syslist: Makefile
$(STAMP) $@
go/doc.lo: $(go_go_doc_files) go/ast.gox go/token.gox io.gox regexp.gox \
- sort.gox strings.gox template.gox
+ sort.gox strings.gox template.gox unicode.gox utf8.gox
$(BUILDPACKAGE)
go/doc/check: $(CHECK_DEPS)
@$(MKDIR_P) go/doc
@@ -5271,7 +5405,7 @@ go/parser/check: $(CHECK_DEPS)
go/printer.lo: $(go_go_printer_files) bytes.gox fmt.gox go/ast.gox \
go/token.gox io.gox os.gox path/filepath.gox reflect.gox \
- runtime.gox strings.gox tabwriter.gox
+ strings.gox tabwriter.gox
$(BUILDPACKAGE)
go/printer/check: $(CHECK_DEPS)
@$(MKDIR_P) go/printer
@@ -5287,30 +5421,14 @@ go/scanner/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: go/scanner/check
-go/token.lo: $(go_go_token_files) fmt.gox strconv.gox
+go/token.lo: $(go_go_token_files) fmt.gox gob.gox io.gox os.gox sort.gox \
+ strconv.gox sync.gox
$(BUILDPACKAGE)
go/token/check: $(CHECK_DEPS)
@$(MKDIR_P) go/token
@$(CHECK)
.PHONY: go/token/check
-go/typechecker.lo: $(go_go_typechecker_files) fmt.gox go/ast.gox go/token.gox \
- go/scanner.gox os.gox
- $(BUILDPACKAGE)
-go/typechecker/check: $(CHECK_DEPS)
- @$(MKDIR_P) go/typechecker
- @$(CHECK)
-.PHONY: go/typechecker/check
-
-go/types.lo: $(go_go_types_files) big.gox bufio.gox fmt.gox go/ast.gox \
- go/token.gox io.gox os.gox path/filepath.gox runtime.gox \
- scanner.gox sort.gox strconv.gox strings.gox
- $(BUILDPACKAGE)
-go/types/check: $(CHECK_DEPS)
- @$(MKDIR_P) go/types
- @$(CHECK)
-.PHONY: go/types/check
-
hash/adler32.lo: $(go_hash_adler32_files) hash.gox os.gox
$(BUILDPACKAGE)
hash/adler32/check: $(CHECK_DEPS)
@@ -5374,23 +5492,21 @@ http/pprof/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: http/pprof/check
-http/spdy.lo: $(go_http_spdy_files) bytes.gox compress/zlib.gox \
- encoding/binary.gox http.gox io.gox os.gox strconv.gox \
- strings.gox sync.gox
- $(BUILDPACKAGE)
-http/spdy/check: $(CHECK_DEPS)
- @$(MKDIR_P) http/spdy
- @$(CHECK)
-.PHONY: http/spdy/check
-
-image/bmp.lo: $(go_image_bmp_files) image.gox io.gox os.gox
+image/bmp.lo: $(go_image_bmp_files) image.gox image/color.gox io.gox os.gox
$(BUILDPACKAGE)
image/bmp/check: $(CHECK_DEPS)
@$(MKDIR_P) image/bmp
@$(CHECK)
.PHONY: image/bmp/check
-image/draw.lo: $(go_image_draw_files) image.gox image/ycbcr.gox
+image/color.lo: $(go_image_color_files)
+ $(BUILDPACKAGE)
+image/color/check: $(CHECK_DEPS)
+ @$(MKDIR_P) image/color
+ @$(CHECK)
+.PHONY: image/color/check
+
+image/draw.lo: $(go_image_draw_files) image.gox image/color.gox image/ycbcr.gox
$(BUILDPACKAGE)
image/draw/check: $(CHECK_DEPS)
@$(MKDIR_P) image/draw
@@ -5398,46 +5514,48 @@ image/draw/check: $(CHECK_DEPS)
.PHONY: image/draw/check
image/gif.lo: $(go_image_gif_files) bufio.gox compress/lzw.gox fmt.gox \
- image.gox io.gox os.gox
+ image.gox image/color.gox io.gox os.gox
$(BUILDPACKAGE)
image/gif/check: $(CHECK_DEPS)
@$(MKDIR_P) image/gif
@$(CHECK)
.PHONY: image/gif/check
-image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/ycbcr.gox \
- io.gox os.gox
+image/jpeg.lo: $(go_image_jpeg_files) bufio.gox image.gox image/color.gox \
+ image/ycbcr.gox io.gox os.gox
$(BUILDPACKAGE)
image/jpeg/check: $(CHECK_DEPS)
@$(MKDIR_P) image/jpeg
@$(CHECK)
.PHONY: image/jpeg/check
-image/png.lo: $(go_image_png_files) bufio.gox compress/zlib.gox fmt.gox \
- hash.gox hash/crc32.gox image.gox io.gox os.gox strconv.gox
+image/png.lo: $(go_image_png_files) bufio.gox compress/zlib.gox \
+ encoding/binary.gox fmt.gox hash.gox hash/crc32.gox image.gox \
+ image/color.gox io.gox os.gox strconv.gox
$(BUILDPACKAGE)
image/png/check: $(CHECK_DEPS)
@$(MKDIR_P) image/png
@$(CHECK)
.PHONY: image/png/check
-image/tiff.lo: $(go_image_tiff_files) compress/lzw.gox compress/zlib.gox \
- encoding/binary.gox image.gox io.gox io/ioutil.gox os.gox
+image/tiff.lo: $(go_image_tiff_files) bufio.gox compress/lzw.gox \
+ compress/zlib.gox encoding/binary.gox image.gox \
+ image/color.gox io.gox io/ioutil.gox os.gox
$(BUILDPACKAGE)
image/tiff/check: $(CHECK_DEPS)
@$(MKDIR_P) image/tiff
@$(CHECK)
.PHONY: image/tiff/check
-image/ycbcr.lo: $(go_image_ycbcr_files) image.gox
+image/ycbcr.lo: $(go_image_ycbcr_files) image.gox image/color.gox
$(BUILDPACKAGE)
image/ycbcr/check: $(CHECK_DEPS)
@$(MKDIR_P) image/ycbcr
@$(CHECK)
.PHONY: image/ycbcr/check
-index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox regexp.gox \
- sort.gox
+index/suffixarray.lo: $(go_index_suffixarray_files) bytes.gox \
+ encoding/binary.gox io.gox os.gox regexp.gox sort.gox
$(BUILDPACKAGE)
index/suffixarray/check: $(CHECK_DEPS)
@$(MKDIR_P) index/suffixarray
@@ -5466,13 +5584,30 @@ net/dict.lo: $(go_net_dict_files) net/textproto.gox os.gox strconv.gox \
$(BUILDPACKAGE)
net/textproto.lo: $(go_net_textproto_files) bufio.gox bytes.gox fmt.gox \
- io.gox io/ioutil.gox net.gox os.gox strconv.gox sync.gox
+ io.gox io/ioutil.gox net.gox os.gox strings.gox strconv.gox \
+ sync.gox
$(BUILDPACKAGE)
net/textproto/check: $(CHECK_DEPS)
@$(MKDIR_P) net/textproto
@$(CHECK)
.PHONY: net/textproto/check
+old/netchan.lo: $(go_old_netchan_files) gob.gox io.gox log.gox net.gox os.gox \
+ reflect.gox strconv.gox sync.gox time.gox
+ $(BUILDPACKAGE)
+old/netchan/check: $(CHECK_DEPS)
+ @$(MKDIR_P) old/netchan
+ @$(CHECK)
+.PHONY: old/netchan/check
+
+old/regexp.lo: $(go_old_regexp_files) bytes.gox io.gox os.gox strings.gox \
+ utf8.gox
+ $(BUILDPACKAGE)
+old/regexp/check: $(CHECK_DEPS)
+ @$(MKDIR_P) old/regexp
+ @$(CHECK)
+.PHONY: old/regexp/check
+
old/template.lo: $(go_old_template_files) bytes.gox fmt.gox io.gox \
io/ioutil.gox os.gox reflect.gox strconv.gox strings.gox \
unicode.gox utf8.gox
@@ -5512,6 +5647,14 @@ path/filepath/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: path/filepath/check
+regexp/syntax.lo: $(go_regexp_syntax_files) bytes.gox os.gox sort.gox \
+ strconv.gox strings.gox unicode.gox utf8.gox
+ $(BUILDPACKAGE)
+regexp/syntax/check: $(CHECK_DEPS)
+ @$(MKDIR_P) regexp/syntax
+ @$(CHECK)
+.PHONY: regexp/syntax/check
+
rpc/jsonrpc.lo: $(go_rpc_jsonrpc_files) fmt.gox io.gox json.gox net.gox \
os.gox rpc.gox sync.gox
$(BUILDPACKAGE)
@@ -5576,16 +5719,12 @@ testing/script/check: $(CHECK_DEPS)
@$(CHECK)
.PHONY: testing/script/check
-sysinfo.go: s-sysinfo; @true
-s-sysinfo: $(srcdir)/mksysinfo.sh config.h
- CC="$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(OSCFLAGS)" $(SHELL) $(srcdir)/mksysinfo.sh
- $(SHELL) $(srcdir)/../move-if-change tmp-sysinfo.go sysinfo.go
- $(STAMP) $@
-
-syscalls/syscall.lo: $(go_syscall_files) sync.gox
+syscall/syscall.lo: $(go_syscall_files) sync.gox
$(BUILDPACKAGE)
-syscalls/errno.lo: $(go_syscall_c_files) syscalls/syscall.lo
- $(LTCOMPILE) -c -o $@ $(srcdir)/syscalls/errno.c
+syscall/errno.lo: go/syscall/errno.c
+ $(LTCOMPILE) -c -o $@ $<
+syscall/wait.lo: go/syscall/wait.c
+ $(LTCOMPILE) -c -o $@ $<
asn1.gox: asn1/asn1.lo
$(BUILDGOX)
@@ -5601,8 +5740,6 @@ crypto.gox: crypto/crypto.lo
$(BUILDGOX)
csv.gox: csv/csv.lo
$(BUILDGOX)
-ebnf.gox: ebnf/ebnf.lo
- $(BUILDGOX)
exec.gox: exec/exec.lo
$(BUILDGOX)
expvar.gox: expvar/expvar.lo
@@ -5635,8 +5772,6 @@ mime.gox: mime/mime.lo
$(BUILDGOX)
net.gox: net/net.lo
$(BUILDGOX)
-netchan.gox: netchan/netchan.lo
- $(BUILDGOX)
os.gox: os/os.lo
$(BUILDGOX)
patch.gox: patch/patch.lo
@@ -5667,7 +5802,7 @@ sync.gox: sync/sync.lo
$(BUILDGOX)
syslog.gox: syslog/syslog.lo
$(BUILDGOX)
-syscall.gox: syscalls/syscall.lo
+syscall.gox: syscall/syscall.lo
$(BUILDGOX)
tabwriter.gox: tabwriter/tabwriter.lo
$(BUILDGOX)
@@ -5677,8 +5812,6 @@ testing.gox: testing/testing.lo
$(BUILDGOX)
time.gox: time/time.lo
$(BUILDGOX)
-try.gox: try/try.lo
- $(BUILDGOX)
unicode.gox: unicode/unicode.lo
$(BUILDGOX)
url.gox: url/url.lo
@@ -5714,11 +5847,11 @@ container/list.gox: container/list.lo
$(BUILDGOX)
container/ring.gox: container/ring.lo
$(BUILDGOX)
-container/vector.gox: container/vector.lo
- $(BUILDGOX)
crypto/aes.gox: crypto/aes.lo
$(BUILDGOX)
+crypto/bcrypt.gox: crypto/bcrypt.lo
+ $(BUILDGOX)
crypto/blowfish.gox: crypto/blowfish.lo
$(BUILDGOX)
crypto/cast5.gox: crypto/cast5.lo
@@ -5808,19 +5941,27 @@ encoding/hex.gox: encoding/hex.lo
encoding/pem.gox: encoding/pem.lo
$(BUILDGOX)
-exp/datafmt.gox: exp/datafmt.lo
+exp/ebnf.gox: exp/ebnf.lo
$(BUILDGOX)
exp/gui.gox: exp/gui.lo
$(BUILDGOX)
exp/norm.gox: exp/norm.lo
$(BUILDGOX)
-exp/regexp.gox: exp/regexp.lo
+exp/spdy.gox: exp/spdy.lo
+ $(BUILDGOX)
+exp/sql.gox: exp/sql.lo
+ $(BUILDGOX)
+exp/ssh.gox: exp/ssh.lo
+ $(BUILDGOX)
+exp/terminal.gox: exp/terminal.lo
+ $(BUILDGOX)
+exp/types.gox: exp/types.lo
$(BUILDGOX)
exp/gui/x11.gox: exp/gui/x11.lo
$(BUILDGOX)
-exp/regexp/syntax.gox: exp/regexp/syntax.lo
+exp/sql/driver.gox: exp/sql/driver.lo
$(BUILDGOX)
exp/template/html.gox: exp/template/html.lo
@@ -5840,10 +5981,6 @@ go/scanner.gox: go/scanner.lo
$(BUILDGOX)
go/token.gox: go/token.lo
$(BUILDGOX)
-go/typechecker.gox: go/typechecker.lo
- $(BUILDGOX)
-go/types.gox: go/types.lo
- $(BUILDGOX)
hash/adler32.gox: hash/adler32.lo
$(BUILDGOX)
@@ -5862,11 +5999,11 @@ http/httptest.gox: http/httptest.lo
$(BUILDGOX)
http/pprof.gox: http/pprof.lo
$(BUILDGOX)
-http/spdy.gox: http/spdy.lo
- $(BUILDGOX)
image/bmp.gox: image/bmp.lo
$(BUILDGOX)
+image/color.gox: image/color.lo
+ $(BUILDGOX)
image/draw.gox: image/draw.lo
$(BUILDGOX)
image/gif.gox: image/gif.lo
@@ -5894,6 +6031,10 @@ net/dict.gox: net/dict.lo
net/textproto.gox: net/textproto.lo
$(BUILDGOX)
+old/netchan.gox: old/netchan.lo
+ $(BUILDGOX)
+old/regexp.gox: old/regexp.lo
+ $(BUILDGOX)
old/template.gox: old/template.lo
$(BUILDGOX)
@@ -5907,6 +6048,9 @@ os/signal.gox: os/signal.lo
path/filepath.gox: path/filepath.lo
$(BUILDGOX)
+regexp/syntax.gox: regexp/syntax.lo
+ $(BUILDGOX)
+
rpc/jsonrpc.gox: rpc/jsonrpc.lo
$(BUILDGOX)
diff --git a/libgo/configure b/libgo/configure
index e6b5d15ba59..9c619bed47d 100755
--- a/libgo/configure
+++ b/libgo/configure
@@ -602,6 +602,8 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+STRUCT_EPOLL_EVENT_FD_OFFSET
+SIZEOF_STRUCT_EPOLL_EVENT
STRINGOPS_FLAG
HAVE_WAIT4_FALSE
HAVE_WAIT4_TRUE
@@ -617,7 +619,10 @@ USING_SPLIT_STACK_FALSE
USING_SPLIT_STACK_TRUE
SPLIT_STACK
OSCFLAGS
-GO_SYSCALLS_SYSCALL_OS_ARCH_FILE
+GO_SYSCALL_OS_ARCH_FILE
+GO_SYSCALL_OS_FILE
+GO_LIBCALL_OS_ARCH_FILE
+GO_LIBCALL_OS_FILE
GOARCH
LIBGO_IS_X86_64_FALSE
LIBGO_IS_X86_64_TRUE
@@ -1946,6 +1951,184 @@ $as_echo "$ac_res" >&6; }
eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
} # ac_fn_c_check_type
+
+# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES
+# --------------------------------------------
+# Tries to find the compile-time value of EXPR in a program that includes
+# INCLUDES, setting VAR accordingly. Returns whether the value could be
+# computed
+ac_fn_c_compute_int ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if test "$cross_compiling" = yes; then
+ # Depending upon the size, compute the lo and hi bounds.
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_lo=0 ac_mid=0
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_hi=$ac_mid; break
+else
+ as_fn_arith $ac_mid + 1 && ac_lo=$as_val
+ if test $ac_lo -le $ac_mid; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) < 0)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_hi=-1 ac_mid=-1
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) >= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_lo=$ac_mid; break
+else
+ as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val
+ if test $ac_mid -le $ac_hi; then
+ ac_lo= ac_hi=
+ break
+ fi
+ as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ done
+else
+ ac_lo= ac_hi=
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+# Binary search between lo and hi bounds.
+while test "x$ac_lo" != "x$ac_hi"; do
+ as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+static int test_array [1 - 2 * !(($2) <= $ac_mid)];
+test_array [0] = 0
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_hi=$ac_mid
+else
+ as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+done
+case $ac_lo in #((
+?*) eval "$3=\$ac_lo"; ac_retval=0 ;;
+'') ac_retval=1 ;;
+esac
+ else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+static long int longval () { return $2; }
+static unsigned long int ulongval () { return $2; }
+#include <stdio.h>
+#include <stdlib.h>
+int
+main ()
+{
+
+ FILE *f = fopen ("conftest.val", "w");
+ if (! f)
+ return 1;
+ if (($2) < 0)
+ {
+ long int i = longval ();
+ if (i != ($2))
+ return 1;
+ fprintf (f, "%ld", i);
+ }
+ else
+ {
+ unsigned long int i = ulongval ();
+ if (i != ($2))
+ return 1;
+ fprintf (f, "%lu", i);
+ }
+ /* Do not output a trailing newline, as this causes \r\n confusion
+ on some platforms. */
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ echo >>conftest.val; read $3 <conftest.val; ac_retval=0
+else
+ ac_retval=1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+rm -f conftest.val
+
+ fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_c_compute_int
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
@@ -10913,7 +11096,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10916 "configure"
+#line 11099 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11019,7 +11202,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11022 "configure"
+#line 11205 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -13151,6 +13334,49 @@ CC="$lt_save_CC"
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
@@ -13551,10 +13777,25 @@ fi
-GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=
-if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then
- GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go
+GO_LIBCALL_OS_FILE=
+GO_LIBCALL_OS_ARCH_FILE=
+GO_SYSCALL_OS_FILE=
+GO_SYSCALL_OS_ARCH_FILE=
+if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then
+ GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go
+fi
+if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then
+ GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go
+fi
+if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then
+ GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go
fi
+if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then
+ GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go
+fi
+
+
+
case "$target" in
@@ -14417,6 +14658,41 @@ fi
CFLAGS=$CFLAGS_hold
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking epoll_event size" >&5
+$as_echo_n "checking epoll_event size... " >&6; }
+if test "${libgo_cv_c_epoll_event_size+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "sizeof (struct epoll_event)" "libgo_cv_c_epoll_event_size" "#include <sys/epoll.h>"; then :
+
+else
+ libgo_cv_c_epoll_event_size=0
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_epoll_event_size" >&5
+$as_echo "$libgo_cv_c_epoll_event_size" >&6; }
+SIZEOF_STRUCT_EPOLL_EVENT=${libgo_cv_c_epoll_event_size}
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking epoll_event data.fd offset" >&5
+$as_echo_n "checking epoll_event data.fd offset... " >&6; }
+if test "${libgo_cv_c_epoll_event_fd_offset+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "offsetof (struct epoll_event, data.fd)" "libgo_cv_c_epoll_event_fd_offset" "#include <stddef.h>
+#include <sys/epoll.h>"; then :
+
+else
+ libgo_cv_c_epoll_event_fd_offset=0
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_c_epoll_event_fd_offset" >&5
+$as_echo "$libgo_cv_c_epoll_event_fd_offset" >&6; }
+STRUCT_EPOLL_EVENT_FD_OFFSET=${libgo_cv_c_epoll_event_fd_offset}
+
+
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
diff --git a/libgo/configure.ac b/libgo/configure.ac
index 6702c26c2f8..e19b5f37b70 100644
--- a/libgo/configure.ac
+++ b/libgo/configure.ac
@@ -45,6 +45,8 @@ AC_SUBST(enable_static)
CC_FOR_BUILD=${CC_FOR_BUILD:-gcc}
AC_SUBST(CC_FOR_BUILD)
+AC_PROG_AWK
+
WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual'
AC_SUBST(WARN_FLAGS)
@@ -249,11 +251,26 @@ AM_CONDITIONAL(LIBGO_IS_X86_64, test $is_x86_64 = yes)
AC_SUBST(GOARCH)
dnl Some files are only present when needed for specific architectures.
-GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=
-if test -f ${srcdir}/syscalls/syscall_${GOOS}_${GOARCH}.go; then
- GO_SYSCALLS_SYSCALL_OS_ARCH_FILE=syscalls/syscall_${GOOS}_${GOARCH}.go
+GO_LIBCALL_OS_FILE=
+GO_LIBCALL_OS_ARCH_FILE=
+GO_SYSCALL_OS_FILE=
+GO_SYSCALL_OS_ARCH_FILE=
+if test -f ${srcdir}/go/syscall/libcall_${GOOS}.go; then
+ GO_LIBCALL_OS_FILE=go/syscall/libcall_${GOOS}.go
+fi
+if test -f ${srcdir}/go/syscall/libcall_${GOOS}_${GOARCH}.go; then
+ GO_LIBCALL_OS_ARCH_FILE=go/syscall/libcall_${GOOS}_${GOARCH}.go
+fi
+if test -f ${srcdir}/go/syscall/syscall_${GOOS}.go; then
+ GO_SYSCALL_OS_FILE=go/syscall/syscall_${GOOS}.go
fi
-AC_SUBST(GO_SYSCALLS_SYSCALL_OS_ARCH_FILE)
+if test -f ${srcdir}/go/syscall/syscall_${GOOS}_${GOARCH}.go; then
+ GO_SYSCALL_OS_ARCH_FILE=go/syscall/syscall_${GOOS}_${GOARCH}.go
+fi
+AC_SUBST(GO_LIBCALL_OS_FILE)
+AC_SUBST(GO_LIBCALL_OS_ARCH_FILE)
+AC_SUBST(GO_SYSCALL_OS_FILE)
+AC_SUBST(GO_SYSCALL_OS_ARCH_FILE)
dnl Some targets need special flags to build sysinfo.go.
case "$target" in
@@ -488,6 +505,28 @@ CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE"
AC_CHECK_TYPES(off64_t)
CFLAGS=$CFLAGS_hold
+dnl Work out the size of the epoll_events struct on GNU/Linux.
+AC_CACHE_CHECK([epoll_event size],
+[libgo_cv_c_epoll_event_size],
+[AC_COMPUTE_INT(libgo_cv_c_epoll_event_size,
+[sizeof (struct epoll_event)],
+[#include <sys/epoll.h>],
+[libgo_cv_c_epoll_event_size=0])])
+SIZEOF_STRUCT_EPOLL_EVENT=${libgo_cv_c_epoll_event_size}
+AC_SUBST(SIZEOF_STRUCT_EPOLL_EVENT)
+
+dnl Work out the offset of the fd field in the epoll_events struct on
+dnl GNU/Linux.
+AC_CACHE_CHECK([epoll_event data.fd offset],
+[libgo_cv_c_epoll_event_fd_offset],
+[AC_COMPUTE_INT(libgo_cv_c_epoll_event_fd_offset,
+[offsetof (struct epoll_event, data.fd)],
+[#include <stddef.h>
+#include <sys/epoll.h>],
+[libgo_cv_c_epoll_event_fd_offset=0])])
+STRUCT_EPOLL_EVENT_FD_OFFSET=${libgo_cv_c_epoll_event_fd_offset}
+AC_SUBST(STRUCT_EPOLL_EVENT_FD_OFFSET)
+
AC_CACHE_SAVE
if test ${multilib} = yes; then
diff --git a/libgo/go/archive/tar/common.go b/libgo/go/archive/tar/common.go
index 52885876589..67355086a63 100644
--- a/libgo/go/archive/tar/common.go
+++ b/libgo/go/archive/tar/common.go
@@ -15,36 +15,37 @@ const (
blockSize = 512
// Types
- TypeReg = '0'
- TypeRegA = '\x00'
- TypeLink = '1'
- TypeSymlink = '2'
- TypeChar = '3'
- TypeBlock = '4'
- TypeDir = '5'
- TypeFifo = '6'
- TypeCont = '7'
- TypeXHeader = 'x'
- TypeXGlobalHeader = 'g'
+ TypeReg = '0' // regular file.
+ TypeRegA = '\x00' // regular file.
+ TypeLink = '1' // hard link.
+ TypeSymlink = '2' // symbolic link.
+ TypeChar = '3' // character device node.
+ TypeBlock = '4' // block device node.
+ TypeDir = '5' // directory.
+ TypeFifo = '6' // fifo node.
+ TypeCont = '7' // reserved.
+ TypeXHeader = 'x' // extended header.
+ TypeXGlobalHeader = 'g' // global extended header.
)
// A Header represents a single header in a tar archive.
// Some fields may not be populated.
type Header struct {
- Name string
- Mode int64
- Uid int
- Gid int
- Size int64
- Mtime int64
- Typeflag byte
- Linkname string
- Uname string
- Gname string
- Devmajor int64
- Devminor int64
- Atime int64
- Ctime int64
+ Name string // name of header file entry.
+ Mode int64 // permission and mode bits.
+ Uid int // user id of owner.
+ Gid int // group id of owner.
+ Size int64 // length in bytes.
+ Mtime int64 // modified time; seconds since epoch.
+ Typeflag byte // type of header entry.
+ Linkname string // target name of link.
+ Uname string // user name of owner.
+ Gname string // group name of owner.
+ Devmajor int64 // major number of character or block device.
+ Devminor int64 // minor number of character or block device.
+ Atime int64 // access time; seconds since epoch.
+ Ctime int64 // status change time; seconds since epoch.
+
}
var zeroBlock = make([]byte, blockSize)
diff --git a/libgo/go/archive/tar/reader.go b/libgo/go/archive/tar/reader.go
index 45d95c3df29..12de2ada083 100644
--- a/libgo/go/archive/tar/reader.go
+++ b/libgo/go/archive/tar/reader.go
@@ -94,7 +94,7 @@ func (tr *Reader) skipUnread() {
return
}
}
- _, tr.err = io.Copyn(ioutil.Discard, tr.r, nr)
+ _, tr.err = io.CopyN(ioutil.Discard, tr.r, nr)
}
func (tr *Reader) verifyChecksum(header []byte) bool {
diff --git a/libgo/go/archive/tar/testdata/writer.tar b/libgo/go/archive/tar/testdata/writer.tar
index 0358f91b98b..e6d816ad077 100644
--- a/libgo/go/archive/tar/testdata/writer.tar
+++ b/libgo/go/archive/tar/testdata/writer.tar
Binary files differ
diff --git a/libgo/go/archive/tar/writer.go b/libgo/go/archive/tar/writer.go
index 8673bad3166..c6ce2241af0 100644
--- a/libgo/go/archive/tar/writer.go
+++ b/libgo/go/archive/tar/writer.go
@@ -134,7 +134,7 @@ func (tw *Writer) WriteHeader(hdr *Header) os.Error {
tw.numeric(s.next(12), hdr.Mtime) // 136:148
s.next(8) // chksum (148:156)
s.next(1)[0] = hdr.Typeflag // 156:157
- s.next(100) // linkname (157:257)
+ tw.cString(s.next(100), hdr.Linkname) // linkname (157:257)
copy(s.next(8), []byte("ustar\x0000")) // 257:265
tw.cString(s.next(32), hdr.Uname) // 265:297
tw.cString(s.next(32), hdr.Gname) // 297:329
diff --git a/libgo/go/archive/tar/writer_test.go b/libgo/go/archive/tar/writer_test.go
index 838cb7e1fef..6cc93868820 100644
--- a/libgo/go/archive/tar/writer_test.go
+++ b/libgo/go/archive/tar/writer_test.go
@@ -24,6 +24,10 @@ type writerTest struct {
}
var writerTests = []*writerTest{
+ // The writer test file was produced with this command:
+ // tar (GNU tar) 1.26
+ // ln -s small.txt link.txt
+ // tar -b 1 --format=ustar -c -f writer.tar small.txt small2.txt link.txt
&writerTest{
file: "testdata/writer.tar",
entries: []*writerTestEntry{
@@ -55,6 +59,21 @@ var writerTests = []*writerTest{
},
contents: "Google.com\n",
},
+ &writerTestEntry{
+ header: &Header{
+ Name: "link.txt",
+ Mode: 0777,
+ Uid: 1000,
+ Gid: 1000,
+ Size: 0,
+ Mtime: 1314603082,
+ Typeflag: '2',
+ Linkname: "small.txt",
+ Uname: "strings",
+ Gname: "strings",
+ },
+ // no contents
+ },
},
},
// The truncated test file was produced using these commands:
diff --git a/libgo/go/archive/zip/reader.go b/libgo/go/archive/zip/reader.go
index f92f9297ada..b0a559936bd 100644
--- a/libgo/go/archive/zip/reader.go
+++ b/libgo/go/archive/zip/reader.go
@@ -238,7 +238,7 @@ func readDirectoryHeader(f *File, r io.Reader) os.Error {
commentLen := int(c.Uint16(b[32:34]))
// startDiskNumber := c.Uint16(b[34:36]) // Unused
// internalAttributes := c.Uint16(b[36:38]) // Unused
- // externalAttributes := c.Uint32(b[38:42]) // Unused
+ f.ExternalAttrs = c.Uint32(b[38:42])
f.headerOffset = int64(c.Uint32(b[42:46]))
d := make([]byte, filenameLen+extraLen+commentLen)
if _, err := io.ReadFull(r, d); err != nil {
diff --git a/libgo/go/archive/zip/reader_test.go b/libgo/go/archive/zip/reader_test.go
index fd5fed2af05..3b7b0dc1304 100644
--- a/libgo/go/archive/zip/reader_test.go
+++ b/libgo/go/archive/zip/reader_test.go
@@ -26,6 +26,7 @@ type ZipTestFile struct {
Content []byte // if blank, will attempt to compare against File
File string // name of file to compare to (relative to testdata/)
Mtime string // modified time in format "mm-dd-yy hh:mm:ss"
+ Mode uint32
}
// Caution: The Mtime values found for the test files should correspond to
@@ -47,11 +48,13 @@ var tests = []ZipTest{
Name: "test.txt",
Content: []byte("This is a test text file.\n"),
Mtime: "09-05-10 12:12:02",
+ Mode: 0x81a4,
},
{
Name: "gophercolor16x16.png",
File: "gophercolor16x16.png",
Mtime: "09-05-10 15:52:58",
+ Mode: 0x81a4,
},
},
},
@@ -162,6 +165,8 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
t.Errorf("%s: mtime=%s (%d); want %s (%d)", f.Name, time.SecondsToUTC(got), got, mtime, want)
}
+ testFileMode(t, f, ft.Mode)
+
size0 := f.UncompressedSize
var b bytes.Buffer
@@ -203,6 +208,19 @@ func readTestFile(t *testing.T, ft ZipTestFile, f *File) {
}
}
+func testFileMode(t *testing.T, f *File, want uint32) {
+ mode, err := f.Mode()
+ if want == 0 {
+ if err == nil {
+ t.Errorf("%s mode: got %v, want none", f.Name, mode)
+ }
+ } else if err != nil {
+ t.Errorf("%s mode: %s", f.Name, err)
+ } else if mode != want {
+ t.Errorf("%s mode: want 0x%x, got 0x%x", f.Name, want, mode)
+ }
+}
+
func TestInvalidFiles(t *testing.T) {
const size = 1024 * 70 // 70kb
b := make([]byte, size)
diff --git a/libgo/go/archive/zip/struct.go b/libgo/go/archive/zip/struct.go
index 1d6e70f105a..a32de5a9e0d 100644
--- a/libgo/go/archive/zip/struct.go
+++ b/libgo/go/archive/zip/struct.go
@@ -28,6 +28,9 @@ const (
directoryHeaderLen = 46 // + filename + extra + comment
directoryEndLen = 22 // + comment
dataDescriptorLen = 12
+
+ // Constants for the first byte in CreatorVersion
+ creatorUnix = 3
)
type FileHeader struct {
@@ -42,6 +45,7 @@ type FileHeader struct {
CompressedSize uint32
UncompressedSize uint32
Extra []byte
+ ExternalAttrs uint32 // Meaning depends on CreatorVersion
Comment string
}
@@ -89,3 +93,18 @@ func (h *FileHeader) Mtime_ns() int64 {
t := msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
return t.Seconds() * 1e9
}
+
+// Mode returns the permission and mode bits for the FileHeader.
+// An error is returned in case the information is not available.
+func (h *FileHeader) Mode() (mode uint32, err os.Error) {
+ if h.CreatorVersion>>8 == creatorUnix {
+ return h.ExternalAttrs >> 16, nil
+ }
+ return 0, os.NewError("file mode not available")
+}
+
+// SetMode changes the permission and mode bits for the FileHeader.
+func (h *FileHeader) SetMode(mode uint32) {
+ h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
+ h.ExternalAttrs = mode << 16
+}
diff --git a/libgo/go/archive/zip/writer.go b/libgo/go/archive/zip/writer.go
index 2065b06daac..3a6dc38e20f 100644
--- a/libgo/go/archive/zip/writer.go
+++ b/libgo/go/archive/zip/writer.go
@@ -69,7 +69,7 @@ func (w *Writer) Close() (err os.Error) {
write(w, uint16(len(h.Comment)))
write(w, uint16(0)) // disk number start
write(w, uint16(0)) // internal file attributes
- write(w, uint32(0)) // external file attributes
+ write(w, h.ExternalAttrs)
write(w, h.offset)
writeBytes(w, []byte(h.Name))
writeBytes(w, h.Extra)
@@ -115,7 +115,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, os.Error) {
}
fh.Flags |= 0x8 // we will write a data descriptor
- fh.CreatorVersion = 0x14
+ fh.CreatorVersion = fh.CreatorVersion&0xff00 | 0x14
fh.ReaderVersion = 0x14
fw := &fileWriter{
diff --git a/libgo/go/archive/zip/writer_test.go b/libgo/go/archive/zip/writer_test.go
index eb2a80c3f70..b562f843053 100644
--- a/libgo/go/archive/zip/writer_test.go
+++ b/libgo/go/archive/zip/writer_test.go
@@ -13,19 +13,45 @@ import (
// TODO(adg): a more sophisticated test suite
-const testString = "Rabbits, guinea pigs, gophers, marsupial rats, and quolls."
+type WriteTest struct {
+ Name string
+ Data []byte
+ Method uint16
+ Mode uint32
+}
+
+var writeTests = []WriteTest{
+ WriteTest{
+ Name: "foo",
+ Data: []byte("Rabbits, guinea pigs, gophers, marsupial rats, and quolls."),
+ Method: Store,
+ },
+ WriteTest{
+ Name: "bar",
+ Data: nil, // large data set in the test
+ Method: Deflate,
+ Mode: 0x81ed,
+ },
+}
func TestWriter(t *testing.T) {
largeData := make([]byte, 1<<17)
for i := range largeData {
largeData[i] = byte(rand.Int())
}
+ writeTests[1].Data = largeData
+ defer func() {
+ writeTests[1].Data = nil
+ }()
// write a zip file
buf := new(bytes.Buffer)
w := NewWriter(buf)
- testCreate(t, w, "foo", []byte(testString), Store)
- testCreate(t, w, "bar", largeData, Deflate)
+
+ for _, wt := range writeTests {
+ testCreate(t, w, &wt)
+ }
+
if err := w.Close(); err != nil {
t.Fatal(err)
}
@@ -35,26 +61,34 @@ func TestWriter(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- testReadFile(t, r.File[0], []byte(testString))
- testReadFile(t, r.File[1], largeData)
+ for i, wt := range writeTests {
+ testReadFile(t, r.File[i], &wt)
+ }
}
-func testCreate(t *testing.T, w *Writer, name string, data []byte, method uint16) {
+func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
header := &FileHeader{
- Name: name,
- Method: method,
+ Name: wt.Name,
+ Method: wt.Method,
+ }
+ if wt.Mode != 0 {
+ header.SetMode(wt.Mode)
}
f, err := w.CreateHeader(header)
if err != nil {
t.Fatal(err)
}
- _, err = f.Write(data)
+ _, err = f.Write(wt.Data)
if err != nil {
t.Fatal(err)
}
}
-func testReadFile(t *testing.T, f *File, data []byte) {
+func testReadFile(t *testing.T, f *File, wt *WriteTest) {
+ if f.Name != wt.Name {
+ t.Fatalf("File name: got %q, want %q", f.Name, wt.Name)
+ }
+ testFileMode(t, f, wt.Mode)
rc, err := f.Open()
if err != nil {
t.Fatal("opening:", err)
@@ -67,7 +101,7 @@ func testReadFile(t *testing.T, f *File, data []byte) {
if err != nil {
t.Fatal("closing:", err)
}
- if !bytes.Equal(b, data) {
- t.Errorf("File contents %q, want %q", b, data)
+ if !bytes.Equal(b, wt.Data) {
+ t.Errorf("File contents %q, want %q", b, wt.Data)
}
}
diff --git a/libgo/go/asn1/asn1.go b/libgo/go/asn1/asn1.go
index 39b676b4190..e7bd62ee0a7 100644
--- a/libgo/go/asn1/asn1.go
+++ b/libgo/go/asn1/asn1.go
@@ -516,6 +516,8 @@ func parseField(v reflect.Value, bytes []byte, initOffset int, params fieldParam
result, err = parseIA5String(innerBytes)
case tagT61String:
result, err = parseT61String(innerBytes)
+ case tagUTF8String:
+ result, err = parseUTF8String(innerBytes)
case tagInteger:
result, err = parseInt64(innerBytes)
case tagBitString:
diff --git a/libgo/go/asn1/asn1_test.go b/libgo/go/asn1/asn1_test.go
index 9f48f7bdd5d..1c529bdb30c 100644
--- a/libgo/go/asn1/asn1_test.go
+++ b/libgo/go/asn1/asn1_test.go
@@ -206,10 +206,10 @@ type timeTest struct {
}
var utcTestData = []timeTest{
- {"910506164540-0700", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 0, -7 * 60 * 60, ""}},
- {"910506164540+0730", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 0, 7*60*60 + 30*60, ""}},
- {"910506234540Z", true, &time.Time{1991, 05, 06, 23, 45, 40, 0, 0, 0, "UTC"}},
- {"9105062345Z", true, &time.Time{1991, 05, 06, 23, 45, 0, 0, 0, 0, "UTC"}},
+ {"910506164540-0700", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, -7 * 60 * 60, ""}},
+ {"910506164540+0730", true, &time.Time{1991, 05, 06, 16, 45, 40, 0, 7*60*60 + 30*60, ""}},
+ {"910506234540Z", true, &time.Time{1991, 05, 06, 23, 45, 40, 0, 0, "UTC"}},
+ {"9105062345Z", true, &time.Time{1991, 05, 06, 23, 45, 0, 0, 0, "UTC"}},
{"a10506234540Z", false, nil},
{"91a506234540Z", false, nil},
{"9105a6234540Z", false, nil},
@@ -235,10 +235,10 @@ func TestUTCTime(t *testing.T) {
}
var generalizedTimeTestData = []timeTest{
- {"20100102030405Z", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, 0, "UTC"}},
+ {"20100102030405Z", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, "UTC"}},
{"20100102030405", false, nil},
- {"20100102030405+0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, 6*60*60 + 7*60, ""}},
- {"20100102030405-0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 0, -6*60*60 - 7*60, ""}},
+ {"20100102030405+0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, 6*60*60 + 7*60, ""}},
+ {"20100102030405-0607", true, &time.Time{2010, 01, 02, 03, 04, 05, 0, -6*60*60 - 7*60, ""}},
}
func TestGeneralizedTime(t *testing.T) {
@@ -475,7 +475,7 @@ var derEncodedSelfSignedCert = Certificate{
RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 3}, Value: "false.example.com"}},
RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, Value: "false@example.com"}},
},
- Validity: Validity{NotBefore: &time.Time{Year: 2009, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, Weekday: 0, ZoneOffset: 0, Zone: "UTC"}, NotAfter: &time.Time{Year: 2010, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, Weekday: 0, ZoneOffset: 0, Zone: "UTC"}},
+ Validity: Validity{NotBefore: &time.Time{Year: 2009, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}, NotAfter: &time.Time{Year: 2010, Month: 10, Day: 8, Hour: 0, Minute: 25, Second: 53, ZoneOffset: 0, Zone: "UTC"}},
Subject: RDNSequence{
RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 6}, Value: "XX"}},
RelativeDistinguishedNameSET{AttributeTypeAndValue{Type: ObjectIdentifier{2, 5, 4, 8}, Value: "Some-State"}},
diff --git a/libgo/go/asn1/marshal.go b/libgo/go/asn1/marshal.go
index d7eb63bf82c..6d1f78bcc10 100644
--- a/libgo/go/asn1/marshal.go
+++ b/libgo/go/asn1/marshal.go
@@ -464,11 +464,15 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
if v.Type() == rawValueType {
rv := v.Interface().(RawValue)
- err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
- if err != nil {
- return
+ if len(rv.FullBytes) != 0 {
+ _, err = out.Write(rv.FullBytes)
+ } else {
+ err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
+ if err != nil {
+ return
+ }
+ _, err = out.Write(rv.Bytes)
}
- _, err = out.Write(rv.Bytes)
return
}
diff --git a/libgo/go/big/int.go b/libgo/go/big/int.go
index 701b69715db..9e1d1ae1318 100644
--- a/libgo/go/big/int.go
+++ b/libgo/go/big/int.go
@@ -163,7 +163,7 @@ func (z *Int) Binomial(n, k int64) *Int {
// Quo sets z to the quotient x/y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
-// See QuoRem for more details.
+// Quo implements truncated division (like Go); see QuoRem for more details.
func (z *Int) Quo(x, y *Int) *Int {
z.abs, _ = z.abs.div(nil, x.abs, y.abs)
z.neg = len(z.abs) > 0 && x.neg != y.neg // 0 has no sign
@@ -172,7 +172,7 @@ func (z *Int) Quo(x, y *Int) *Int {
// Rem sets z to the remainder x%y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
-// See QuoRem for more details.
+// Rem implements truncated modulus (like Go); see QuoRem for more details.
func (z *Int) Rem(x, y *Int) *Int {
_, z.abs = nat(nil).div(z.abs, x.abs, y.abs)
z.neg = len(z.abs) > 0 && x.neg // 0 has no sign
@@ -198,7 +198,7 @@ func (z *Int) QuoRem(x, y, r *Int) (*Int, *Int) {
// Div sets z to the quotient x/y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
-// See DivMod for more details.
+// Div implements Euclidean division (unlike Go); see DivMod for more details.
func (z *Int) Div(x, y *Int) *Int {
y_neg := y.neg // z may be an alias for y
var r Int
@@ -215,7 +215,7 @@ func (z *Int) Div(x, y *Int) *Int {
// Mod sets z to the modulus x%y for y != 0 and returns z.
// If y == 0, a division-by-zero run-time panic occurs.
-// See DivMod for more details.
+// Mod implements Euclidean modulus (unlike Go); see DivMod for more details.
func (z *Int) Mod(x, y *Int) *Int {
y0 := y // save y
if z == y || alias(z.abs, y.abs) {
diff --git a/libgo/go/big/int_test.go b/libgo/go/big/int_test.go
index 03446d6ae2d..b2e16921799 100644
--- a/libgo/go/big/int_test.go
+++ b/libgo/go/big/int_test.go
@@ -301,6 +301,9 @@ func TestGetString(t *testing.T) {
func TestSetString(t *testing.T) {
tmp := new(Int)
for i, test := range stringTests {
+ // initialize to a non-zero value so that issues with parsing
+ // 0 are detected
+ tmp.SetInt64(1234567890)
n1, ok1 := new(Int).SetString(test.in, test.base)
n2, ok2 := tmp.SetString(test.in, test.base)
expected := NewInt(test.val)
diff --git a/libgo/go/big/nat.go b/libgo/go/big/nat.go
index be3aff29d18..33d6bb16ffd 100644
--- a/libgo/go/big/nat.go
+++ b/libgo/go/big/nat.go
@@ -646,7 +646,7 @@ func (z nat) scan(r io.RuneScanner, base int) (nat, int, os.Error) {
}
}
case os.EOF:
- return z, 10, nil
+ return z.make(0), 10, nil
default:
return z, 10, err
}
diff --git a/libgo/go/big/rat.go b/libgo/go/big/rat.go
index 327b9bd9ca7..f435e637f19 100644
--- a/libgo/go/big/rat.go
+++ b/libgo/go/big/rat.go
@@ -27,9 +27,13 @@ func NewRat(a, b int64) *Rat {
// SetFrac sets z to a/b and returns z.
func (z *Rat) SetFrac(a, b *Int) *Rat {
- z.a.Set(a)
z.a.neg = a.neg != b.neg
- z.b = z.b.set(b.abs)
+ babs := b.abs
+ if &z.a == b || alias(z.a.abs, babs) {
+ babs = nat(nil).set(babs) // make a copy
+ }
+ z.a.abs = z.a.abs.set(a.abs)
+ z.b = z.b.set(babs)
return z.norm()
}
diff --git a/libgo/go/big/rat_test.go b/libgo/go/big/rat_test.go
index dbc5bb6cca1..a2b905525ee 100644
--- a/libgo/go/big/rat_test.go
+++ b/libgo/go/big/rat_test.go
@@ -330,3 +330,43 @@ func TestRatGobEncoding(t *testing.T) {
}
}
}
+
+func TestIssue2379(t *testing.T) {
+ // 1) no aliasing
+ q := NewRat(3, 2)
+ x := new(Rat)
+ x.SetFrac(NewInt(3), NewInt(2))
+ if x.Cmp(q) != 0 {
+ t.Errorf("1) got %s want %s", x, q)
+ }
+
+ // 2) aliasing of numerator
+ x = NewRat(2, 3)
+ x.SetFrac(NewInt(3), x.Num())
+ if x.Cmp(q) != 0 {
+ t.Errorf("2) got %s want %s", x, q)
+ }
+
+ // 3) aliasing of denominator
+ x = NewRat(2, 3)
+ x.SetFrac(x.Denom(), NewInt(2))
+ if x.Cmp(q) != 0 {
+ t.Errorf("3) got %s want %s", x, q)
+ }
+
+ // 4) aliasing of numerator and denominator
+ x = NewRat(2, 3)
+ x.SetFrac(x.Denom(), x.Num())
+ if x.Cmp(q) != 0 {
+ t.Errorf("4) got %s want %s", x, q)
+ }
+
+ // 5) numerator and denominator are the same
+ q = NewRat(1, 1)
+ x = new(Rat)
+ n := NewInt(7)
+ x.SetFrac(n, n)
+ if x.Cmp(q) != 0 {
+ t.Errorf("5) got %s want %s", x, q)
+ }
+}
diff --git a/libgo/go/bufio/bufio.go b/libgo/go/bufio/bufio.go
index 727ebfdbbe2..2ea7af3e25b 100644
--- a/libgo/go/bufio/bufio.go
+++ b/libgo/go/bufio/bufio.go
@@ -54,11 +54,11 @@ type Reader struct {
}
// NewReaderSize creates a new Reader whose buffer has the specified size,
-// which must be greater than zero. If the argument io.Reader is already a
+// which must be greater than one. If the argument io.Reader is already a
// Reader with large enough size, it returns the underlying Reader.
// It returns the Reader and any error.
func NewReaderSize(rd io.Reader, size int) (*Reader, os.Error) {
- if size <= 0 {
+ if size <= 1 {
return nil, BufSizeError(size)
}
// Is it already a Reader?
@@ -298,6 +298,17 @@ func (b *Reader) ReadSlice(delim byte) (line []byte, err os.Error) {
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
line, err = b.ReadSlice('\n')
if err == ErrBufferFull {
+ // Handle the case where "\r\n" straddles the buffer.
+ if len(line) > 0 && line[len(line)-1] == '\r' {
+ // Put the '\r' back on buf and drop it from line.
+ // Let the next call to ReadLine check for "\r\n".
+ if b.r == 0 {
+ // should be unreachable
+ panic("bufio: tried to rewind past start of buffer")
+ }
+ b.r--
+ line = line[:len(line)-1]
+ }
return line, true, nil
}
@@ -307,10 +318,11 @@ func (b *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
err = nil
if line[len(line)-1] == '\n' {
- line = line[:len(line)-1]
- }
- if len(line) > 0 && line[len(line)-1] == '\r' {
- line = line[:len(line)-1]
+ drop := 1
+ if len(line) > 1 && line[len(line)-2] == '\r' {
+ drop = 2
+ }
+ line = line[:len(line)-drop]
}
return
}
diff --git a/libgo/go/bufio/bufio_test.go b/libgo/go/bufio/bufio_test.go
index 82c73d36a9c..38213ffe788 100644
--- a/libgo/go/bufio/bufio_test.go
+++ b/libgo/go/bufio/bufio_test.go
@@ -137,7 +137,7 @@ var bufreaders = []bufReader{
}
var bufsizes = []int{
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 2, 3, 4, 5, 6, 7, 8, 9, 10,
23, 32, 46, 64, 93, 128, 1024, 4096,
}
@@ -697,3 +697,71 @@ func TestLinesAfterRead(t *testing.T) {
t.Errorf("expected EOF from ReadLine, got '%s' %t %s", line, isPrefix, err)
}
}
+
+type readLineResult struct {
+ line []byte
+ isPrefix bool
+ err os.Error
+}
+
+var readLineNewlinesTests = []struct {
+ input string
+ bufSize int
+ expect []readLineResult
+}{
+ {"h\r\nb\r\n", 2, []readLineResult{
+ {[]byte("h"), true, nil},
+ {nil, false, nil},
+ {[]byte("b"), true, nil},
+ {nil, false, nil},
+ {nil, false, os.EOF},
+ }},
+ {"hello\r\nworld\r\n", 6, []readLineResult{
+ {[]byte("hello"), true, nil},
+ {nil, false, nil},
+ {[]byte("world"), true, nil},
+ {nil, false, nil},
+ {nil, false, os.EOF},
+ }},
+ {"hello\rworld\r", 6, []readLineResult{
+ {[]byte("hello"), true, nil},
+ {[]byte("\rworld"), true, nil},
+ {[]byte("\r"), false, nil},
+ {nil, false, os.EOF},
+ }},
+ {"h\ri\r\n\r", 2, []readLineResult{
+ {[]byte("h"), true, nil},
+ {[]byte("\ri"), true, nil},
+ {nil, false, nil},
+ {[]byte("\r"), false, nil},
+ {nil, false, os.EOF},
+ }},
+}
+
+func TestReadLineNewlines(t *testing.T) {
+ for _, e := range readLineNewlinesTests {
+ testReadLineNewlines(t, e.input, e.bufSize, e.expect)
+ }
+}
+
+func testReadLineNewlines(t *testing.T, input string, bufSize int, expect []readLineResult) {
+ b, err := NewReaderSize(strings.NewReader(input), bufSize)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for i, e := range expect {
+ line, isPrefix, err := b.ReadLine()
+ if bytes.Compare(line, e.line) != 0 {
+ t.Errorf("%q call %d, line == %q, want %q", input, i, line, e.line)
+ return
+ }
+ if isPrefix != e.isPrefix {
+ t.Errorf("%q call %d, isPrefix == %v, want %v", input, i, isPrefix, e.isPrefix)
+ return
+ }
+ if err != e.err {
+ t.Errorf("%q call %d, err == %v, want %v", input, i, err, e.err)
+ return
+ }
+ }
+}
diff --git a/libgo/go/bytes/buffer.go b/libgo/go/bytes/buffer.go
index 5de86105d05..975031bfa4f 100644
--- a/libgo/go/bytes/buffer.go
+++ b/libgo/go/bytes/buffer.go
@@ -336,13 +336,18 @@ func (b *Buffer) ReadString(delim byte) (line string, err os.Error) {
// NewBuffer creates and initializes a new Buffer using buf as its initial
// contents. It is intended to prepare a Buffer to read existing data. It
-// can also be used to size the internal buffer for writing. To do that,
+// can also be used to size the internal buffer for writing. To do that,
// buf should have the desired capacity but a length of zero.
+//
+// In most cases, new(Buffer) (or just declaring a Buffer variable) is
+// preferable to NewBuffer. In particular, passing a non-empty buf to
+// NewBuffer and then writing to the Buffer will overwrite buf, not append to
+// it.
func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
// NewBufferString creates and initializes a new Buffer using string s as its
// initial contents. It is intended to prepare a buffer to read an existing
-// string.
+// string. See the warnings about NewBuffer; similar issues apply here.
func NewBufferString(s string) *Buffer {
return &Buffer{buf: []byte(s)}
}
diff --git a/libgo/go/bytes/bytes.go b/libgo/go/bytes/bytes.go
index 5119fce949e..2fb456900a7 100644
--- a/libgo/go/bytes/bytes.go
+++ b/libgo/go/bytes/bytes.go
@@ -572,13 +572,18 @@ func Runes(s []byte) []int {
// non-overlapping instances of old replaced by new.
// If n < 0, there is no limit on the number of replacements.
func Replace(s, old, new []byte, n int) []byte {
- if n == 0 {
- return s // avoid allocation
- }
- // Compute number of replacements.
- if m := Count(s, old); m == 0 {
- return s // avoid allocation
- } else if n <= 0 || m < n {
+ m := 0
+ if n != 0 {
+ // Compute number of replacements.
+ m = Count(s, old)
+ }
+ if m == 0 {
+ // Nothing to do. Just copy.
+ t := make([]byte, len(s))
+ copy(t, s)
+ return t
+ }
+ if n < 0 || m < n {
n = m
}
@@ -603,3 +608,58 @@ func Replace(s, old, new []byte, n int) []byte {
w += copy(t[w:], s[start:])
return t[0:w]
}
+
+// EqualFold reports whether s and t, interpreted as UTF-8 strings,
+// are equal under Unicode case-folding.
+func EqualFold(s, t []byte) bool {
+ for len(s) != 0 && len(t) != 0 {
+ // Extract first rune from each.
+ var sr, tr int
+ if s[0] < utf8.RuneSelf {
+ sr, s = int(s[0]), s[1:]
+ } else {
+ r, size := utf8.DecodeRune(s)
+ sr, s = r, s[size:]
+ }
+ if t[0] < utf8.RuneSelf {
+ tr, t = int(t[0]), t[1:]
+ } else {
+ r, size := utf8.DecodeRune(t)
+ tr, t = r, t[size:]
+ }
+
+ // If they match, keep going; if not, return false.
+
+ // Easy case.
+ if tr == sr {
+ continue
+ }
+
+ // Make sr < tr to simplify what follows.
+ if tr < sr {
+ tr, sr = sr, tr
+ }
+ // Fast check for ASCII.
+ if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
+ // ASCII, and sr is upper case. tr must be lower case.
+ if tr == sr+'a'-'A' {
+ continue
+ }
+ return false
+ }
+
+ // General case. SimpleFold(x) returns the next equivalent rune > x
+ // or wraps around to smaller values.
+ r := unicode.SimpleFold(sr)
+ for r != sr && r < tr {
+ r = unicode.SimpleFold(r)
+ }
+ if r == tr {
+ continue
+ }
+ return false
+ }
+
+ // One string is empty. Are both?
+ return len(s) == len(t)
+}
diff --git a/libgo/go/bytes/bytes_test.go b/libgo/go/bytes/bytes_test.go
index 9444358a858..ce3f37e4de2 100644
--- a/libgo/go/bytes/bytes_test.go
+++ b/libgo/go/bytes/bytes_test.go
@@ -829,9 +829,15 @@ var ReplaceTests = []ReplaceTest{
func TestReplace(t *testing.T) {
for _, tt := range ReplaceTests {
- if s := string(Replace([]byte(tt.in), []byte(tt.old), []byte(tt.new), tt.n)); s != tt.out {
+ in := append([]byte(tt.in), "<spare>"...)
+ in = in[:len(tt.in)]
+ out := Replace(in, []byte(tt.old), []byte(tt.new), tt.n)
+ if s := string(out); s != tt.out {
t.Errorf("Replace(%q, %q, %q, %d) = %q, want %q", tt.in, tt.old, tt.new, tt.n, s, tt.out)
}
+ if cap(in) == cap(out) && &in[:1][0] == &out[:1][0] {
+ t.Errorf("Replace(%q, %q, %q, %d) didn't copy", tt.in, tt.old, tt.new, tt.n)
+ }
}
}
@@ -856,3 +862,31 @@ func TestTitle(t *testing.T) {
}
}
}
+
+var EqualFoldTests = []struct {
+ s, t string
+ out bool
+}{
+ {"abc", "abc", true},
+ {"ABcd", "ABcd", true},
+ {"123abc", "123ABC", true},
+ {"αβδ", "ΑΒΔ", true},
+ {"abc", "xyz", false},
+ {"abc", "XYZ", false},
+ {"abcdefghijk", "abcdefghijX", false},
+ {"abcdefghijk", "abcdefghij\u212A", true},
+ {"abcdefghijK", "abcdefghij\u212A", true},
+ {"abcdefghijkz", "abcdefghij\u212Ay", false},
+ {"abcdefghijKz", "abcdefghij\u212Ay", false},
+}
+
+func TestEqualFold(t *testing.T) {
+ for _, tt := range EqualFoldTests {
+ if out := EqualFold([]byte(tt.s), []byte(tt.t)); out != tt.out {
+ t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out)
+ }
+ if out := EqualFold([]byte(tt.t), []byte(tt.s)); out != tt.out {
+ t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out)
+ }
+ }
+}
diff --git a/libgo/go/cmath/asin.go b/libgo/go/cmath/asin.go
index d6a3ca48026..01ce80a1946 100644
--- a/libgo/go/cmath/asin.go
+++ b/libgo/go/cmath/asin.go
@@ -50,7 +50,7 @@ import "math"
// Asin returns the inverse sine of x.
func Asin(x complex128) complex128 {
if imag(x) == 0 {
- if math.Fabs(real(x)) > 1 {
+ if math.Abs(real(x)) > 1 {
return complex(math.Pi/2, 0) // DOMAIN error
}
return complex(math.Asin(real(x)), 0)
@@ -67,7 +67,7 @@ func Asin(x complex128) complex128 {
func Asinh(x complex128) complex128 {
// TODO check range
if imag(x) == 0 {
- if math.Fabs(real(x)) > 1 {
+ if math.Abs(real(x)) > 1 {
return complex(math.Pi/2, 0) // DOMAIN error
}
return complex(math.Asinh(real(x)), 0)
diff --git a/libgo/go/cmath/sin.go b/libgo/go/cmath/sin.go
index 8900ecddea3..486b717877e 100644
--- a/libgo/go/cmath/sin.go
+++ b/libgo/go/cmath/sin.go
@@ -122,7 +122,7 @@ func Cosh(x complex128) complex128 {
// calculate sinh and cosh
func sinhcosh(x float64) (sh, ch float64) {
- if math.Fabs(x) <= 0.5 {
+ if math.Abs(x) <= 0.5 {
return math.Sinh(x), math.Cosh(x)
}
e := math.Exp(x)
diff --git a/libgo/go/cmath/sqrt.go b/libgo/go/cmath/sqrt.go
index e77a9b9df21..4e7e8050f94 100644
--- a/libgo/go/cmath/sqrt.go
+++ b/libgo/go/cmath/sqrt.go
@@ -76,7 +76,7 @@ func Sqrt(x complex128) complex128 {
b := imag(x)
var scale float64
// Rescale to avoid internal overflow or underflow.
- if math.Fabs(a) > 4 || math.Fabs(b) > 4 {
+ if math.Abs(a) > 4 || math.Abs(b) > 4 {
a *= 0.25
b *= 0.25
scale = 2
@@ -89,11 +89,11 @@ func Sqrt(x complex128) complex128 {
var t float64
if a > 0 {
t = math.Sqrt(0.5*r + 0.5*a)
- r = scale * math.Fabs((0.5*b)/t)
+ r = scale * math.Abs((0.5*b)/t)
t *= scale
} else {
r = math.Sqrt(0.5*r - 0.5*a)
- t = scale * math.Fabs((0.5*b)/r)
+ t = scale * math.Abs((0.5*b)/r)
r *= scale
}
if b < 0 {
diff --git a/libgo/go/cmath/tan.go b/libgo/go/cmath/tan.go
index 94b517521ec..67dc22ad0fd 100644
--- a/libgo/go/cmath/tan.go
+++ b/libgo/go/cmath/tan.go
@@ -58,7 +58,7 @@ import "math"
// Tan returns the tangent of x.
func Tan(x complex128) complex128 {
d := math.Cos(2*real(x)) + math.Cosh(2*imag(x))
- if math.Fabs(d) < 0.25 {
+ if math.Abs(d) < 0.25 {
d = tanSeries(x)
}
if d == 0 {
@@ -109,8 +109,8 @@ func reducePi(x float64) float64 {
// Taylor series expansion for cosh(2y) - cos(2x)
func tanSeries(z complex128) float64 {
const MACHEP = 1.0 / (1 << 53)
- x := math.Fabs(2 * real(z))
- y := math.Fabs(2 * imag(z))
+ x := math.Abs(2 * real(z))
+ y := math.Abs(2 * imag(z))
x = reducePi(x)
x = x * x
y = y * y
@@ -139,7 +139,7 @@ func tanSeries(z complex128) float64 {
t = y2 - x2
t /= f
d += t
- if math.Fabs(t/d) <= MACHEP {
+ if math.Abs(t/d) <= MACHEP {
break
}
}
@@ -174,7 +174,7 @@ func tanSeries(z complex128) float64 {
// Cot returns the cotangent of x.
func Cot(x complex128) complex128 {
d := math.Cosh(2*imag(x)) - math.Cos(2*real(x))
- if math.Fabs(d) < 0.25 {
+ if math.Abs(d) < 0.25 {
d = tanSeries(x)
}
if d == 0 {
diff --git a/libgo/go/container/heap/heap_test.go b/libgo/go/container/heap/heap_test.go
index c5c1f76e1e1..6625e3a2b0f 100644
--- a/libgo/go/container/heap/heap_test.go
+++ b/libgo/go/container/heap/heap_test.go
@@ -6,32 +6,46 @@ package heap_test
import (
"testing"
- "container/vector"
. "container/heap"
)
-type myHeap struct {
- // A vector.Vector implements sort.Interface except for Less,
- // and it implements Push and Pop as required for heap.Interface.
- vector.Vector
+type myHeap []int
+
+func (h *myHeap) Less(i, j int) bool {
+ return (*h)[i] < (*h)[j]
+}
+
+func (h *myHeap) Swap(i, j int) {
+ (*h)[i], (*h)[j] = (*h)[j], (*h)[i]
+}
+
+func (h *myHeap) Len() int {
+ return len(*h)
+}
+
+func (h *myHeap) Pop() (v interface{}) {
+ *h, v = (*h)[:h.Len()-1], (*h)[h.Len()-1]
+ return
}
-func (h *myHeap) Less(i, j int) bool { return h.At(i).(int) < h.At(j).(int) }
+func (h *myHeap) Push(v interface{}) {
+ *h = append(*h, v.(int))
+}
-func (h *myHeap) verify(t *testing.T, i int) {
+func (h myHeap) verify(t *testing.T, i int) {
n := h.Len()
j1 := 2*i + 1
j2 := 2*i + 2
if j1 < n {
if h.Less(j1, i) {
- t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h.At(i), j1, h.At(j1))
+ t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h[i], j1, h[j1])
return
}
h.verify(t, j1)
}
if j2 < n {
if h.Less(j2, i) {
- t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h.At(i), j1, h.At(j2))
+ t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h[i], j1, h[j2])
return
}
h.verify(t, j2)
diff --git a/libgo/go/container/vector/defs.go b/libgo/go/container/vector/defs.go
deleted file mode 100644
index 6d6b2ac81a3..00000000000
--- a/libgo/go/container/vector/defs.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package vector implements containers for managing sequences of elements.
-// Vectors grow and shrink dynamically as necessary.
-package vector
-
-// Vector is a container for numbered sequences of elements of type interface{}.
-// A vector's length and capacity adjusts automatically as necessary.
-// The zero value for Vector is an empty vector ready to use.
-type Vector []interface{}
-
-// IntVector is a container for numbered sequences of elements of type int.
-// A vector's length and capacity adjusts automatically as necessary.
-// The zero value for IntVector is an empty vector ready to use.
-type IntVector []int
-
-// StringVector is a container for numbered sequences of elements of type string.
-// A vector's length and capacity adjusts automatically as necessary.
-// The zero value for StringVector is an empty vector ready to use.
-type StringVector []string
-
-// Initial underlying array size
-const initialSize = 8
-
-// Partial sort.Interface support
-
-// LessInterface provides partial support of the sort.Interface.
-type LessInterface interface {
- Less(y interface{}) bool
-}
-
-// Less returns a boolean denoting whether the i'th element is less than the j'th element.
-func (p *Vector) Less(i, j int) bool { return (*p)[i].(LessInterface).Less((*p)[j]) }
-
-// sort.Interface support
-
-// Less returns a boolean denoting whether the i'th element is less than the j'th element.
-func (p *IntVector) Less(i, j int) bool { return (*p)[i] < (*p)[j] }
-
-// Less returns a boolean denoting whether the i'th element is less than the j'th element.
-func (p *StringVector) Less(i, j int) bool { return (*p)[i] < (*p)[j] }
diff --git a/libgo/go/container/vector/intvector.go b/libgo/go/container/vector/intvector.go
deleted file mode 100644
index aa88cfeb367..00000000000
--- a/libgo/go/container/vector/intvector.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector.go, it was generated
-// automatically from vector.go - DO NOT EDIT in that case!
-
-package vector
-
-func (p *IntVector) realloc(length, capacity int) (b []int) {
- if capacity < initialSize {
- capacity = initialSize
- }
- if capacity < length {
- capacity = length
- }
- b = make(IntVector, length, capacity)
- copy(b, *p)
- *p = b
- return
-}
-
-// Insert n elements at position i.
-func (p *IntVector) Expand(i, n int) {
- a := *p
-
- // make sure we have enough space
- len0 := len(a)
- len1 := len0 + n
- if len1 <= cap(a) {
- // enough space - just expand
- a = a[0:len1]
- } else {
- // not enough space - double capacity
- capb := cap(a) * 2
- if capb < len1 {
- // still not enough - use required length
- capb = len1
- }
- // capb >= len1
- a = p.realloc(len1, capb)
- }
-
- // make a hole
- for j := len0 - 1; j >= i; j-- {
- a[j+n] = a[j]
- }
-
- *p = a
-}
-
-// Insert n elements at the end of a vector.
-func (p *IntVector) Extend(n int) { p.Expand(len(*p), n) }
-
-// Resize changes the length and capacity of a vector.
-// If the new length is shorter than the current length, Resize discards
-// trailing elements. If the new length is longer than the current length,
-// Resize adds the respective zero values for the additional elements. The capacity
-// parameter is ignored unless the new length or capacity is longer than the current
-// capacity. The resized vector's capacity may be larger than the requested capacity.
-func (p *IntVector) Resize(length, capacity int) *IntVector {
- a := *p
-
- if length > cap(a) || capacity > cap(a) {
- // not enough space or larger capacity requested explicitly
- a = p.realloc(length, capacity)
- } else if length < len(a) {
- // clear trailing elements
- for i := range a[length:] {
- var zero int
- a[length+i] = zero
- }
- }
-
- *p = a[0:length]
- return p
-}
-
-// Len returns the number of elements in the vector.
-// Same as len(*p).
-func (p *IntVector) Len() int { return len(*p) }
-
-// Cap returns the capacity of the vector; that is, the
-// maximum length the vector can grow without resizing.
-// Same as cap(*p).
-func (p *IntVector) Cap() int { return cap(*p) }
-
-// At returns the i'th element of the vector.
-func (p *IntVector) At(i int) int { return (*p)[i] }
-
-// Set sets the i'th element of the vector to value x.
-func (p *IntVector) Set(i int, x int) { (*p)[i] = x }
-
-// Last returns the element in the vector of highest index.
-func (p *IntVector) Last() int { return (*p)[len(*p)-1] }
-
-// Copy makes a copy of the vector and returns it.
-func (p *IntVector) Copy() IntVector {
- arr := make(IntVector, len(*p))
- copy(arr, *p)
- return arr
-}
-
-// Insert inserts into the vector an element of value x before
-// the current element at index i.
-func (p *IntVector) Insert(i int, x int) {
- p.Expand(i, 1)
- (*p)[i] = x
-}
-
-// Delete deletes the i'th element of the vector. The gap is closed so the old
-// element at index i+1 has index i afterwards.
-func (p *IntVector) Delete(i int) {
- a := *p
- n := len(a)
-
- copy(a[i:n-1], a[i+1:n])
- var zero int
- a[n-1] = zero // support GC, zero out entry
- *p = a[0 : n-1]
-}
-
-// InsertVector inserts into the vector the contents of the vector
-// x such that the 0th element of x appears at index i after insertion.
-func (p *IntVector) InsertVector(i int, x *IntVector) {
- b := *x
-
- p.Expand(i, len(b))
- copy((*p)[i:i+len(b)], b)
-}
-
-// Cut deletes elements i through j-1, inclusive.
-func (p *IntVector) Cut(i, j int) {
- a := *p
- n := len(a)
- m := n - (j - i)
-
- copy(a[i:m], a[j:n])
- for k := m; k < n; k++ { //TODO(bflm) don't zero out the elements unless it's a Vector.
- var zero int
- a[k] = zero // support GC, zero out entries
- }
-
- *p = a[0:m]
-}
-
-// Slice returns a new sub-vector by slicing the old one to extract slice [i:j].
-// The elements are copied. The original vector is unchanged.
-func (p *IntVector) Slice(i, j int) *IntVector {
- var s IntVector
- s.realloc(j-i, 0) // will fail in Init() if j < i
- copy(s, (*p)[i:j])
- return &s
-}
-
-// Convenience wrappers
-
-// Push appends x to the end of the vector.
-func (p *IntVector) Push(x int) { p.Insert(len(*p), x) }
-
-// Pop deletes the last element of the vector.
-func (p *IntVector) Pop() int {
- a := *p
-
- i := len(a) - 1
- x := a[i]
- var zero int
- a[i] = zero // support GC, zero out entry
- *p = a[0:i]
- return x
-}
-
-// AppendVector appends the entire vector x to the end of this vector.
-func (p *IntVector) AppendVector(x *IntVector) { p.InsertVector(len(*p), x) }
-
-// Swap exchanges the elements at indexes i and j.
-func (p *IntVector) Swap(i, j int) {
- a := *p
- a[i], a[j] = a[j], a[i]
-}
-
-// Do calls function f for each element of the vector, in order.
-// The behavior of Do is undefined if f changes *p.
-func (p *IntVector) Do(f func(elem int)) {
- for _, e := range *p {
- f(e)
- }
-}
diff --git a/libgo/go/container/vector/intvector_test.go b/libgo/go/container/vector/intvector_test.go
deleted file mode 100644
index b825af91221..00000000000
--- a/libgo/go/container/vector/intvector_test.go
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector_test.go, it was generated
-// automatically from vector_test.go - DO NOT EDIT in that case!
-
-package vector
-
-import "testing"
-
-func TestIntZeroLen(t *testing.T) {
- a := new(IntVector)
- if a.Len() != 0 {
- t.Errorf("%T: B1) expected 0, got %d", a, a.Len())
- }
- if len(*a) != 0 {
- t.Errorf("%T: B2) expected 0, got %d", a, len(*a))
- }
- var b IntVector
- if b.Len() != 0 {
- t.Errorf("%T: B3) expected 0, got %d", b, b.Len())
- }
- if len(b) != 0 {
- t.Errorf("%T: B4) expected 0, got %d", b, len(b))
- }
-}
-
-func TestIntResize(t *testing.T) {
- var a IntVector
- checkSize(t, &a, 0, 0)
- checkSize(t, a.Resize(0, 5), 0, 5)
- checkSize(t, a.Resize(1, 0), 1, 5)
- checkSize(t, a.Resize(10, 0), 10, 10)
- checkSize(t, a.Resize(5, 0), 5, 10)
- checkSize(t, a.Resize(3, 8), 3, 10)
- checkSize(t, a.Resize(0, 100), 0, 100)
- checkSize(t, a.Resize(11, 100), 11, 100)
-}
-
-func TestIntResize2(t *testing.T) {
- var a IntVector
- checkSize(t, &a, 0, 0)
- a.Push(int2IntValue(1))
- a.Push(int2IntValue(2))
- a.Push(int2IntValue(3))
- a.Push(int2IntValue(4))
- checkSize(t, &a, 4, 4)
- checkSize(t, a.Resize(10, 0), 10, 10)
- for i := 4; i < a.Len(); i++ {
- if a.At(i) != intzero {
- t.Errorf("%T: expected a.At(%d) == %v; found %v!", a, i, intzero, a.At(i))
- }
- }
- for i := 4; i < len(a); i++ {
- if a[i] != intzero {
- t.Errorf("%T: expected a[%d] == %v; found %v", a, i, intzero, a[i])
- }
- }
-}
-
-func checkIntZero(t *testing.T, a *IntVector, i int) {
- for j := 0; j < i; j++ {
- if a.At(j) == intzero {
- t.Errorf("%T: 1 expected a.At(%d) == %d; found %v", a, j, j, a.At(j))
- }
- if (*a)[j] == intzero {
- t.Errorf("%T: 2 expected (*a)[%d] == %d; found %v", a, j, j, (*a)[j])
- }
- }
- for ; i < a.Len(); i++ {
- if a.At(i) != intzero {
- t.Errorf("%T: 3 expected a.At(%d) == %v; found %v", a, i, intzero, a.At(i))
- }
- if (*a)[i] != intzero {
- t.Errorf("%T: 4 expected (*a)[%d] == %v; found %v", a, i, intzero, (*a)[i])
- }
- }
-}
-
-func TestIntTrailingElements(t *testing.T) {
- var a IntVector
- for i := 0; i < 10; i++ {
- a.Push(int2IntValue(i + 1))
- }
- checkIntZero(t, &a, 10)
- checkSize(t, &a, 10, 16)
- checkSize(t, a.Resize(5, 0), 5, 16)
- checkSize(t, a.Resize(10, 0), 10, 16)
- checkIntZero(t, &a, 5)
-}
-
-func TestIntAccess(t *testing.T) {
- const n = 100
- var a IntVector
- a.Resize(n, 0)
- for i := 0; i < n; i++ {
- a.Set(i, int2IntValue(val(i)))
- }
- for i := 0; i < n; i++ {
- if elem2IntValue(a.At(i)) != int2IntValue(val(i)) {
- t.Error(i)
- }
- }
- var b IntVector
- b.Resize(n, 0)
- for i := 0; i < n; i++ {
- b[i] = int2IntValue(val(i))
- }
- for i := 0; i < n; i++ {
- if elem2IntValue(b[i]) != int2IntValue(val(i)) {
- t.Error(i)
- }
- }
-}
-
-func TestIntInsertDeleteClear(t *testing.T) {
- const n = 100
- var a IntVector
-
- for i := 0; i < n; i++ {
- if a.Len() != i {
- t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
- }
- if len(a) != i {
- t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
- }
- a.Insert(0, int2IntValue(val(i)))
- if elem2IntValue(a.Last()) != int2IntValue(val(0)) {
- t.Errorf("%T: B", a)
- }
- }
- for i := n - 1; i >= 0; i-- {
- if elem2IntValue(a.Last()) != int2IntValue(val(0)) {
- t.Errorf("%T: C", a)
- }
- if elem2IntValue(a.At(0)) != int2IntValue(val(i)) {
- t.Errorf("%T: D", a)
- }
- if elem2IntValue(a[0]) != int2IntValue(val(i)) {
- t.Errorf("%T: D2", a)
- }
- a.Delete(0)
- if a.Len() != i {
- t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
- }
- if len(a) != i {
- t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
- }
- }
-
- if a.Len() != 0 {
- t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
- }
- if len(a) != 0 {
- t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
- }
- for i := 0; i < n; i++ {
- a.Push(int2IntValue(val(i)))
- if a.Len() != i+1 {
- t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
- }
- if len(a) != i+1 {
- t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
- }
- if elem2IntValue(a.Last()) != int2IntValue(val(i)) {
- t.Errorf("%T: H", a)
- }
- }
- a.Resize(0, 0)
- if a.Len() != 0 {
- t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
- }
- if len(a) != 0 {
- t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
- }
-
- const m = 5
- for j := 0; j < m; j++ {
- a.Push(int2IntValue(j))
- for i := 0; i < n; i++ {
- x := val(i)
- a.Push(int2IntValue(x))
- if elem2IntValue(a.Pop()) != int2IntValue(x) {
- t.Errorf("%T: J", a)
- }
- if a.Len() != j+1 {
- t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
- }
- if len(a) != j+1 {
- t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
- }
- }
- }
- if a.Len() != m {
- t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
- }
- if len(a) != m {
- t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
- }
-}
-
-func verify_sliceInt(t *testing.T, x *IntVector, elt, i, j int) {
- for k := i; k < j; k++ {
- if elem2IntValue(x.At(k)) != int2IntValue(elt) {
- t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2IntValue(x.At(k)), int2IntValue(elt))
- }
- }
-
- s := x.Slice(i, j)
- for k, n := 0, j-i; k < n; k++ {
- if elem2IntValue(s.At(k)) != int2IntValue(elt) {
- t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2IntValue(x.At(k)), int2IntValue(elt))
- }
- }
-}
-
-func verify_patternInt(t *testing.T, x *IntVector, a, b, c int) {
- n := a + b + c
- if x.Len() != n {
- t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
- }
- if len(*x) != n {
- t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
- }
- verify_sliceInt(t, x, 0, 0, a)
- verify_sliceInt(t, x, 1, a, a+b)
- verify_sliceInt(t, x, 0, a+b, n)
-}
-
-func make_vectorInt(elt, len int) *IntVector {
- x := new(IntVector).Resize(len, 0)
- for i := 0; i < len; i++ {
- x.Set(i, int2IntValue(elt))
- }
- return x
-}
-
-func TestIntInsertVector(t *testing.T) {
- // 1
- a := make_vectorInt(0, 0)
- b := make_vectorInt(1, 10)
- a.InsertVector(0, b)
- verify_patternInt(t, a, 0, 10, 0)
- // 2
- a = make_vectorInt(0, 10)
- b = make_vectorInt(1, 0)
- a.InsertVector(5, b)
- verify_patternInt(t, a, 5, 0, 5)
- // 3
- a = make_vectorInt(0, 10)
- b = make_vectorInt(1, 3)
- a.InsertVector(3, b)
- verify_patternInt(t, a, 3, 3, 7)
- // 4
- a = make_vectorInt(0, 10)
- b = make_vectorInt(1, 1000)
- a.InsertVector(8, b)
- verify_patternInt(t, a, 8, 1000, 2)
-}
-
-func TestIntDo(t *testing.T) {
- const n = 25
- const salt = 17
- a := new(IntVector).Resize(n, 0)
- for i := 0; i < n; i++ {
- a.Set(i, int2IntValue(salt*i))
- }
- count := 0
- a.Do(func(e int) {
- i := intf2IntValue(e)
- if i != int2IntValue(count*salt) {
- t.Error(tname(a), "value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(a), "should visit", n, "values; did visit", count)
- }
-
- b := new(IntVector).Resize(n, 0)
- for i := 0; i < n; i++ {
- (*b)[i] = int2IntValue(salt * i)
- }
- count = 0
- b.Do(func(e int) {
- i := intf2IntValue(e)
- if i != int2IntValue(count*salt) {
- t.Error(tname(b), "b) value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(b), "b) should visit", n, "values; did visit", count)
- }
-
- var c IntVector
- c.Resize(n, 0)
- for i := 0; i < n; i++ {
- c[i] = int2IntValue(salt * i)
- }
- count = 0
- c.Do(func(e int) {
- i := intf2IntValue(e)
- if i != int2IntValue(count*salt) {
- t.Error(tname(c), "c) value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(c), "c) should visit", n, "values; did visit", count)
- }
-
-}
-
-func TestIntVectorCopy(t *testing.T) {
- // verify Copy() returns a copy, not simply a slice of the original vector
- const Len = 10
- var src IntVector
- for i := 0; i < Len; i++ {
- src.Push(int2IntValue(i * i))
- }
- dest := src.Copy()
- for i := 0; i < Len; i++ {
- src[i] = int2IntValue(-1)
- v := elem2IntValue(dest[i])
- if v != int2IntValue(i*i) {
- t.Error(tname(src), "expected", i*i, "got", v)
- }
- }
-}
diff --git a/libgo/go/container/vector/nogen_test.go b/libgo/go/container/vector/nogen_test.go
deleted file mode 100644
index 7b6a25952b1..00000000000
--- a/libgo/go/container/vector/nogen_test.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vector
-
-import (
- "fmt"
- "sort"
- "testing"
-)
-
-var (
- zero interface{}
- intzero int
- strzero string
-)
-
-func int2Value(x int) int { return x }
-func int2IntValue(x int) int { return x }
-func int2StrValue(x int) string { return string(x) }
-
-func elem2Value(x interface{}) int { return x.(int) }
-func elem2IntValue(x int) int { return x }
-func elem2StrValue(x string) string { return x }
-
-func intf2Value(x interface{}) int { return x.(int) }
-func intf2IntValue(x interface{}) int { return x.(int) }
-func intf2StrValue(x interface{}) string { return x.(string) }
-
-type VectorInterface interface {
- Len() int
- Cap() int
-}
-
-func checkSize(t *testing.T, v VectorInterface, len, cap int) {
- if v.Len() != len {
- t.Errorf("%T expected len = %d; found %d", v, len, v.Len())
- }
- if v.Cap() < cap {
- t.Errorf("%T expected cap >= %d; found %d", v, cap, v.Cap())
- }
-}
-
-func val(i int) int { return i*991 - 1234 }
-
-func TestSorting(t *testing.T) {
- const n = 100
-
- a := new(IntVector).Resize(n, 0)
- for i := n - 1; i >= 0; i-- {
- a.Set(i, n-1-i)
- }
- if sort.IsSorted(a) {
- t.Error("int vector not sorted")
- }
-
- b := new(StringVector).Resize(n, 0)
- for i := n - 1; i >= 0; i-- {
- b.Set(i, fmt.Sprint(n-1-i))
- }
- if sort.IsSorted(b) {
- t.Error("string vector not sorted")
- }
-}
-
-func tname(x interface{}) string { return fmt.Sprintf("%T: ", x) }
diff --git a/libgo/go/container/vector/numbers_test.go b/libgo/go/container/vector/numbers_test.go
deleted file mode 100644
index abe01a8fb18..00000000000
--- a/libgo/go/container/vector/numbers_test.go
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package vector
-
-import (
- "fmt"
- "runtime"
- "strings"
- "testing"
-)
-
-const memTestN = 1000000
-
-func s(n uint64) string {
- str := fmt.Sprintf("%d", n)
- lens := len(str)
- a := make([]string, (lens+2)/3)
- start := lens
- for i := range a {
- start -= 3
- if start < 0 {
- start = 0
- }
- a[len(a)-i-1] = str[start:lens]
- lens -= 3
- }
- return strings.Join(a, " ")
-}
-
-func TestVectorNums(t *testing.T) {
- if testing.Short() {
- return
- }
- var v Vector
- c := int(0)
- runtime.GC()
- m0 := runtime.MemStats
- v.Resize(memTestN, memTestN)
- for i := 0; i < memTestN; i++ {
- v.Set(i, c)
- }
- runtime.GC()
- m := runtime.MemStats
- v.Resize(0, 0)
- runtime.GC()
- n := m.Alloc - m0.Alloc
- t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
-}
-
-func TestIntVectorNums(t *testing.T) {
- if testing.Short() {
- return
- }
- var v IntVector
- c := int(0)
- runtime.GC()
- m0 := runtime.MemStats
- v.Resize(memTestN, memTestN)
- for i := 0; i < memTestN; i++ {
- v.Set(i, c)
- }
- runtime.GC()
- m := runtime.MemStats
- v.Resize(0, 0)
- runtime.GC()
- n := m.Alloc - m0.Alloc
- t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
-}
-
-func TestStringVectorNums(t *testing.T) {
- if testing.Short() {
- return
- }
- var v StringVector
- c := ""
- runtime.GC()
- m0 := runtime.MemStats
- v.Resize(memTestN, memTestN)
- for i := 0; i < memTestN; i++ {
- v.Set(i, c)
- }
- runtime.GC()
- m := runtime.MemStats
- v.Resize(0, 0)
- runtime.GC()
- n := m.Alloc - m0.Alloc
- t.Logf("%T.Push(%#v), n = %s: Alloc/n = %.2f\n", v, c, s(memTestN), float64(n)/memTestN)
-}
-
-func BenchmarkVectorNums(b *testing.B) {
- c := int(0)
- var v Vector
- b.StopTimer()
- runtime.GC()
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- v.Push(c)
- }
-}
-
-func BenchmarkIntVectorNums(b *testing.B) {
- c := int(0)
- var v IntVector
- b.StopTimer()
- runtime.GC()
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- v.Push(c)
- }
-}
-
-func BenchmarkStringVectorNums(b *testing.B) {
- c := ""
- var v StringVector
- b.StopTimer()
- runtime.GC()
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- v.Push(c)
- }
-}
diff --git a/libgo/go/container/vector/stringvector.go b/libgo/go/container/vector/stringvector.go
deleted file mode 100644
index dc81f06b74d..00000000000
--- a/libgo/go/container/vector/stringvector.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector.go, it was generated
-// automatically from vector.go - DO NOT EDIT in that case!
-
-package vector
-
-func (p *StringVector) realloc(length, capacity int) (b []string) {
- if capacity < initialSize {
- capacity = initialSize
- }
- if capacity < length {
- capacity = length
- }
- b = make(StringVector, length, capacity)
- copy(b, *p)
- *p = b
- return
-}
-
-// Insert n elements at position i.
-func (p *StringVector) Expand(i, n int) {
- a := *p
-
- // make sure we have enough space
- len0 := len(a)
- len1 := len0 + n
- if len1 <= cap(a) {
- // enough space - just expand
- a = a[0:len1]
- } else {
- // not enough space - double capacity
- capb := cap(a) * 2
- if capb < len1 {
- // still not enough - use required length
- capb = len1
- }
- // capb >= len1
- a = p.realloc(len1, capb)
- }
-
- // make a hole
- for j := len0 - 1; j >= i; j-- {
- a[j+n] = a[j]
- }
-
- *p = a
-}
-
-// Insert n elements at the end of a vector.
-func (p *StringVector) Extend(n int) { p.Expand(len(*p), n) }
-
-// Resize changes the length and capacity of a vector.
-// If the new length is shorter than the current length, Resize discards
-// trailing elements. If the new length is longer than the current length,
-// Resize adds the respective zero values for the additional elements. The capacity
-// parameter is ignored unless the new length or capacity is longer than the current
-// capacity. The resized vector's capacity may be larger than the requested capacity.
-func (p *StringVector) Resize(length, capacity int) *StringVector {
- a := *p
-
- if length > cap(a) || capacity > cap(a) {
- // not enough space or larger capacity requested explicitly
- a = p.realloc(length, capacity)
- } else if length < len(a) {
- // clear trailing elements
- for i := range a[length:] {
- var zero string
- a[length+i] = zero
- }
- }
-
- *p = a[0:length]
- return p
-}
-
-// Len returns the number of elements in the vector.
-// Same as len(*p).
-func (p *StringVector) Len() int { return len(*p) }
-
-// Cap returns the capacity of the vector; that is, the
-// maximum length the vector can grow without resizing.
-// Same as cap(*p).
-func (p *StringVector) Cap() int { return cap(*p) }
-
-// At returns the i'th element of the vector.
-func (p *StringVector) At(i int) string { return (*p)[i] }
-
-// Set sets the i'th element of the vector to value x.
-func (p *StringVector) Set(i int, x string) { (*p)[i] = x }
-
-// Last returns the element in the vector of highest index.
-func (p *StringVector) Last() string { return (*p)[len(*p)-1] }
-
-// Copy makes a copy of the vector and returns it.
-func (p *StringVector) Copy() StringVector {
- arr := make(StringVector, len(*p))
- copy(arr, *p)
- return arr
-}
-
-// Insert inserts into the vector an element of value x before
-// the current element at index i.
-func (p *StringVector) Insert(i int, x string) {
- p.Expand(i, 1)
- (*p)[i] = x
-}
-
-// Delete deletes the i'th element of the vector. The gap is closed so the old
-// element at index i+1 has index i afterwards.
-func (p *StringVector) Delete(i int) {
- a := *p
- n := len(a)
-
- copy(a[i:n-1], a[i+1:n])
- var zero string
- a[n-1] = zero // support GC, zero out entry
- *p = a[0 : n-1]
-}
-
-// InsertVector inserts into the vector the contents of the vector
-// x such that the 0th element of x appears at index i after insertion.
-func (p *StringVector) InsertVector(i int, x *StringVector) {
- b := *x
-
- p.Expand(i, len(b))
- copy((*p)[i:i+len(b)], b)
-}
-
-// Cut deletes elements i through j-1, inclusive.
-func (p *StringVector) Cut(i, j int) {
- a := *p
- n := len(a)
- m := n - (j - i)
-
- copy(a[i:m], a[j:n])
- for k := m; k < n; k++ { //TODO(bflm) don't zero out the elements unless it's a Vector.
- var zero string
- a[k] = zero // support GC, zero out entries
- }
-
- *p = a[0:m]
-}
-
-// Slice returns a new sub-vector by slicing the old one to extract slice [i:j].
-// The elements are copied. The original vector is unchanged.
-func (p *StringVector) Slice(i, j int) *StringVector {
- var s StringVector
- s.realloc(j-i, 0) // will fail in Init() if j < i
- copy(s, (*p)[i:j])
- return &s
-}
-
-// Convenience wrappers
-
-// Push appends x to the end of the vector.
-func (p *StringVector) Push(x string) { p.Insert(len(*p), x) }
-
-// Pop deletes the last element of the vector.
-func (p *StringVector) Pop() string {
- a := *p
-
- i := len(a) - 1
- x := a[i]
- var zero string
- a[i] = zero // support GC, zero out entry
- *p = a[0:i]
- return x
-}
-
-// AppendVector appends the entire vector x to the end of this vector.
-func (p *StringVector) AppendVector(x *StringVector) { p.InsertVector(len(*p), x) }
-
-// Swap exchanges the elements at indexes i and j.
-func (p *StringVector) Swap(i, j int) {
- a := *p
- a[i], a[j] = a[j], a[i]
-}
-
-// Do calls function f for each element of the vector, in order.
-// The behavior of Do is undefined if f changes *p.
-func (p *StringVector) Do(f func(elem string)) {
- for _, e := range *p {
- f(e)
- }
-}
diff --git a/libgo/go/container/vector/stringvector_test.go b/libgo/go/container/vector/stringvector_test.go
deleted file mode 100644
index c75676f786c..00000000000
--- a/libgo/go/container/vector/stringvector_test.go
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector_test.go, it was generated
-// automatically from vector_test.go - DO NOT EDIT in that case!
-
-package vector
-
-import "testing"
-
-func TestStrZeroLen(t *testing.T) {
- a := new(StringVector)
- if a.Len() != 0 {
- t.Errorf("%T: B1) expected 0, got %d", a, a.Len())
- }
- if len(*a) != 0 {
- t.Errorf("%T: B2) expected 0, got %d", a, len(*a))
- }
- var b StringVector
- if b.Len() != 0 {
- t.Errorf("%T: B3) expected 0, got %d", b, b.Len())
- }
- if len(b) != 0 {
- t.Errorf("%T: B4) expected 0, got %d", b, len(b))
- }
-}
-
-func TestStrResize(t *testing.T) {
- var a StringVector
- checkSize(t, &a, 0, 0)
- checkSize(t, a.Resize(0, 5), 0, 5)
- checkSize(t, a.Resize(1, 0), 1, 5)
- checkSize(t, a.Resize(10, 0), 10, 10)
- checkSize(t, a.Resize(5, 0), 5, 10)
- checkSize(t, a.Resize(3, 8), 3, 10)
- checkSize(t, a.Resize(0, 100), 0, 100)
- checkSize(t, a.Resize(11, 100), 11, 100)
-}
-
-func TestStrResize2(t *testing.T) {
- var a StringVector
- checkSize(t, &a, 0, 0)
- a.Push(int2StrValue(1))
- a.Push(int2StrValue(2))
- a.Push(int2StrValue(3))
- a.Push(int2StrValue(4))
- checkSize(t, &a, 4, 4)
- checkSize(t, a.Resize(10, 0), 10, 10)
- for i := 4; i < a.Len(); i++ {
- if a.At(i) != strzero {
- t.Errorf("%T: expected a.At(%d) == %v; found %v!", a, i, strzero, a.At(i))
- }
- }
- for i := 4; i < len(a); i++ {
- if a[i] != strzero {
- t.Errorf("%T: expected a[%d] == %v; found %v", a, i, strzero, a[i])
- }
- }
-}
-
-func checkStrZero(t *testing.T, a *StringVector, i int) {
- for j := 0; j < i; j++ {
- if a.At(j) == strzero {
- t.Errorf("%T: 1 expected a.At(%d) == %d; found %v", a, j, j, a.At(j))
- }
- if (*a)[j] == strzero {
- t.Errorf("%T: 2 expected (*a)[%d] == %d; found %v", a, j, j, (*a)[j])
- }
- }
- for ; i < a.Len(); i++ {
- if a.At(i) != strzero {
- t.Errorf("%T: 3 expected a.At(%d) == %v; found %v", a, i, strzero, a.At(i))
- }
- if (*a)[i] != strzero {
- t.Errorf("%T: 4 expected (*a)[%d] == %v; found %v", a, i, strzero, (*a)[i])
- }
- }
-}
-
-func TestStrTrailingElements(t *testing.T) {
- var a StringVector
- for i := 0; i < 10; i++ {
- a.Push(int2StrValue(i + 1))
- }
- checkStrZero(t, &a, 10)
- checkSize(t, &a, 10, 16)
- checkSize(t, a.Resize(5, 0), 5, 16)
- checkSize(t, a.Resize(10, 0), 10, 16)
- checkStrZero(t, &a, 5)
-}
-
-func TestStrAccess(t *testing.T) {
- const n = 100
- var a StringVector
- a.Resize(n, 0)
- for i := 0; i < n; i++ {
- a.Set(i, int2StrValue(val(i)))
- }
- for i := 0; i < n; i++ {
- if elem2StrValue(a.At(i)) != int2StrValue(val(i)) {
- t.Error(i)
- }
- }
- var b StringVector
- b.Resize(n, 0)
- for i := 0; i < n; i++ {
- b[i] = int2StrValue(val(i))
- }
- for i := 0; i < n; i++ {
- if elem2StrValue(b[i]) != int2StrValue(val(i)) {
- t.Error(i)
- }
- }
-}
-
-func TestStrInsertDeleteClear(t *testing.T) {
- const n = 100
- var a StringVector
-
- for i := 0; i < n; i++ {
- if a.Len() != i {
- t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
- }
- if len(a) != i {
- t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
- }
- a.Insert(0, int2StrValue(val(i)))
- if elem2StrValue(a.Last()) != int2StrValue(val(0)) {
- t.Errorf("%T: B", a)
- }
- }
- for i := n - 1; i >= 0; i-- {
- if elem2StrValue(a.Last()) != int2StrValue(val(0)) {
- t.Errorf("%T: C", a)
- }
- if elem2StrValue(a.At(0)) != int2StrValue(val(i)) {
- t.Errorf("%T: D", a)
- }
- if elem2StrValue(a[0]) != int2StrValue(val(i)) {
- t.Errorf("%T: D2", a)
- }
- a.Delete(0)
- if a.Len() != i {
- t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
- }
- if len(a) != i {
- t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
- }
- }
-
- if a.Len() != 0 {
- t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
- }
- if len(a) != 0 {
- t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
- }
- for i := 0; i < n; i++ {
- a.Push(int2StrValue(val(i)))
- if a.Len() != i+1 {
- t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
- }
- if len(a) != i+1 {
- t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
- }
- if elem2StrValue(a.Last()) != int2StrValue(val(i)) {
- t.Errorf("%T: H", a)
- }
- }
- a.Resize(0, 0)
- if a.Len() != 0 {
- t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
- }
- if len(a) != 0 {
- t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
- }
-
- const m = 5
- for j := 0; j < m; j++ {
- a.Push(int2StrValue(j))
- for i := 0; i < n; i++ {
- x := val(i)
- a.Push(int2StrValue(x))
- if elem2StrValue(a.Pop()) != int2StrValue(x) {
- t.Errorf("%T: J", a)
- }
- if a.Len() != j+1 {
- t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
- }
- if len(a) != j+1 {
- t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
- }
- }
- }
- if a.Len() != m {
- t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
- }
- if len(a) != m {
- t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
- }
-}
-
-func verify_sliceStr(t *testing.T, x *StringVector, elt, i, j int) {
- for k := i; k < j; k++ {
- if elem2StrValue(x.At(k)) != int2StrValue(elt) {
- t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2StrValue(x.At(k)), int2StrValue(elt))
- }
- }
-
- s := x.Slice(i, j)
- for k, n := 0, j-i; k < n; k++ {
- if elem2StrValue(s.At(k)) != int2StrValue(elt) {
- t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2StrValue(x.At(k)), int2StrValue(elt))
- }
- }
-}
-
-func verify_patternStr(t *testing.T, x *StringVector, a, b, c int) {
- n := a + b + c
- if x.Len() != n {
- t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
- }
- if len(*x) != n {
- t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
- }
- verify_sliceStr(t, x, 0, 0, a)
- verify_sliceStr(t, x, 1, a, a+b)
- verify_sliceStr(t, x, 0, a+b, n)
-}
-
-func make_vectorStr(elt, len int) *StringVector {
- x := new(StringVector).Resize(len, 0)
- for i := 0; i < len; i++ {
- x.Set(i, int2StrValue(elt))
- }
- return x
-}
-
-func TestStrInsertVector(t *testing.T) {
- // 1
- a := make_vectorStr(0, 0)
- b := make_vectorStr(1, 10)
- a.InsertVector(0, b)
- verify_patternStr(t, a, 0, 10, 0)
- // 2
- a = make_vectorStr(0, 10)
- b = make_vectorStr(1, 0)
- a.InsertVector(5, b)
- verify_patternStr(t, a, 5, 0, 5)
- // 3
- a = make_vectorStr(0, 10)
- b = make_vectorStr(1, 3)
- a.InsertVector(3, b)
- verify_patternStr(t, a, 3, 3, 7)
- // 4
- a = make_vectorStr(0, 10)
- b = make_vectorStr(1, 1000)
- a.InsertVector(8, b)
- verify_patternStr(t, a, 8, 1000, 2)
-}
-
-func TestStrDo(t *testing.T) {
- const n = 25
- const salt = 17
- a := new(StringVector).Resize(n, 0)
- for i := 0; i < n; i++ {
- a.Set(i, int2StrValue(salt*i))
- }
- count := 0
- a.Do(func(e string) {
- i := intf2StrValue(e)
- if i != int2StrValue(count*salt) {
- t.Error(tname(a), "value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(a), "should visit", n, "values; did visit", count)
- }
-
- b := new(StringVector).Resize(n, 0)
- for i := 0; i < n; i++ {
- (*b)[i] = int2StrValue(salt * i)
- }
- count = 0
- b.Do(func(e string) {
- i := intf2StrValue(e)
- if i != int2StrValue(count*salt) {
- t.Error(tname(b), "b) value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(b), "b) should visit", n, "values; did visit", count)
- }
-
- var c StringVector
- c.Resize(n, 0)
- for i := 0; i < n; i++ {
- c[i] = int2StrValue(salt * i)
- }
- count = 0
- c.Do(func(e string) {
- i := intf2StrValue(e)
- if i != int2StrValue(count*salt) {
- t.Error(tname(c), "c) value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(c), "c) should visit", n, "values; did visit", count)
- }
-
-}
-
-func TestStrVectorCopy(t *testing.T) {
- // verify Copy() returns a copy, not simply a slice of the original vector
- const Len = 10
- var src StringVector
- for i := 0; i < Len; i++ {
- src.Push(int2StrValue(i * i))
- }
- dest := src.Copy()
- for i := 0; i < Len; i++ {
- src[i] = int2StrValue(-1)
- v := elem2StrValue(dest[i])
- if v != int2StrValue(i*i) {
- t.Error(tname(src), "expected", i*i, "got", v)
- }
- }
-}
diff --git a/libgo/go/container/vector/vector.go b/libgo/go/container/vector/vector.go
deleted file mode 100644
index 8470ec067ac..00000000000
--- a/libgo/go/container/vector/vector.go
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector.go, it was generated
-// automatically from vector.go - DO NOT EDIT in that case!
-
-package vector
-
-func (p *Vector) realloc(length, capacity int) (b []interface{}) {
- if capacity < initialSize {
- capacity = initialSize
- }
- if capacity < length {
- capacity = length
- }
- b = make(Vector, length, capacity)
- copy(b, *p)
- *p = b
- return
-}
-
-// Insert n elements at position i.
-func (p *Vector) Expand(i, n int) {
- a := *p
-
- // make sure we have enough space
- len0 := len(a)
- len1 := len0 + n
- if len1 <= cap(a) {
- // enough space - just expand
- a = a[0:len1]
- } else {
- // not enough space - double capacity
- capb := cap(a) * 2
- if capb < len1 {
- // still not enough - use required length
- capb = len1
- }
- // capb >= len1
- a = p.realloc(len1, capb)
- }
-
- // make a hole
- for j := len0 - 1; j >= i; j-- {
- a[j+n] = a[j]
- }
-
- *p = a
-}
-
-// Insert n elements at the end of a vector.
-func (p *Vector) Extend(n int) { p.Expand(len(*p), n) }
-
-// Resize changes the length and capacity of a vector.
-// If the new length is shorter than the current length, Resize discards
-// trailing elements. If the new length is longer than the current length,
-// Resize adds the respective zero values for the additional elements. The capacity
-// parameter is ignored unless the new length or capacity is longer than the current
-// capacity. The resized vector's capacity may be larger than the requested capacity.
-func (p *Vector) Resize(length, capacity int) *Vector {
- a := *p
-
- if length > cap(a) || capacity > cap(a) {
- // not enough space or larger capacity requested explicitly
- a = p.realloc(length, capacity)
- } else if length < len(a) {
- // clear trailing elements
- for i := range a[length:] {
- var zero interface{}
- a[length+i] = zero
- }
- }
-
- *p = a[0:length]
- return p
-}
-
-// Len returns the number of elements in the vector.
-// Same as len(*p).
-func (p *Vector) Len() int { return len(*p) }
-
-// Cap returns the capacity of the vector; that is, the
-// maximum length the vector can grow without resizing.
-// Same as cap(*p).
-func (p *Vector) Cap() int { return cap(*p) }
-
-// At returns the i'th element of the vector.
-func (p *Vector) At(i int) interface{} { return (*p)[i] }
-
-// Set sets the i'th element of the vector to value x.
-func (p *Vector) Set(i int, x interface{}) { (*p)[i] = x }
-
-// Last returns the element in the vector of highest index.
-func (p *Vector) Last() interface{} { return (*p)[len(*p)-1] }
-
-// Copy makes a copy of the vector and returns it.
-func (p *Vector) Copy() Vector {
- arr := make(Vector, len(*p))
- copy(arr, *p)
- return arr
-}
-
-// Insert inserts into the vector an element of value x before
-// the current element at index i.
-func (p *Vector) Insert(i int, x interface{}) {
- p.Expand(i, 1)
- (*p)[i] = x
-}
-
-// Delete deletes the i'th element of the vector. The gap is closed so the old
-// element at index i+1 has index i afterwards.
-func (p *Vector) Delete(i int) {
- a := *p
- n := len(a)
-
- copy(a[i:n-1], a[i+1:n])
- var zero interface{}
- a[n-1] = zero // support GC, zero out entry
- *p = a[0 : n-1]
-}
-
-// InsertVector inserts into the vector the contents of the vector
-// x such that the 0th element of x appears at index i after insertion.
-func (p *Vector) InsertVector(i int, x *Vector) {
- b := *x
-
- p.Expand(i, len(b))
- copy((*p)[i:i+len(b)], b)
-}
-
-// Cut deletes elements i through j-1, inclusive.
-func (p *Vector) Cut(i, j int) {
- a := *p
- n := len(a)
- m := n - (j - i)
-
- copy(a[i:m], a[j:n])
- for k := m; k < n; k++ { //TODO(bflm) don't zero out the elements unless it's a Vector.
- var zero interface{}
- a[k] = zero // support GC, zero out entries
- }
-
- *p = a[0:m]
-}
-
-// Slice returns a new sub-vector by slicing the old one to extract slice [i:j].
-// The elements are copied. The original vector is unchanged.
-func (p *Vector) Slice(i, j int) *Vector {
- var s Vector
- s.realloc(j-i, 0) // will fail in Init() if j < i
- copy(s, (*p)[i:j])
- return &s
-}
-
-// Convenience wrappers
-
-// Push appends x to the end of the vector.
-func (p *Vector) Push(x interface{}) { p.Insert(len(*p), x) }
-
-// Pop deletes the last element of the vector.
-func (p *Vector) Pop() interface{} {
- a := *p
-
- i := len(a) - 1
- x := a[i]
- var zero interface{}
- a[i] = zero // support GC, zero out entry
- *p = a[0:i]
- return x
-}
-
-// AppendVector appends the entire vector x to the end of this vector.
-func (p *Vector) AppendVector(x *Vector) { p.InsertVector(len(*p), x) }
-
-// Swap exchanges the elements at indexes i and j.
-func (p *Vector) Swap(i, j int) {
- a := *p
- a[i], a[j] = a[j], a[i]
-}
-
-// Do calls function f for each element of the vector, in order.
-// The behavior of Do is undefined if f changes *p.
-func (p *Vector) Do(f func(elem interface{})) {
- for _, e := range *p {
- f(e)
- }
-}
diff --git a/libgo/go/container/vector/vector_test.go b/libgo/go/container/vector/vector_test.go
deleted file mode 100644
index a7f47b8c2a5..00000000000
--- a/libgo/go/container/vector/vector_test.go
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// CAUTION: If this file is not vector_test.go, it was generated
-// automatically from vector_test.go - DO NOT EDIT in that case!
-
-package vector
-
-import "testing"
-
-func TestZeroLen(t *testing.T) {
- a := new(Vector)
- if a.Len() != 0 {
- t.Errorf("%T: B1) expected 0, got %d", a, a.Len())
- }
- if len(*a) != 0 {
- t.Errorf("%T: B2) expected 0, got %d", a, len(*a))
- }
- var b Vector
- if b.Len() != 0 {
- t.Errorf("%T: B3) expected 0, got %d", b, b.Len())
- }
- if len(b) != 0 {
- t.Errorf("%T: B4) expected 0, got %d", b, len(b))
- }
-}
-
-func TestResize(t *testing.T) {
- var a Vector
- checkSize(t, &a, 0, 0)
- checkSize(t, a.Resize(0, 5), 0, 5)
- checkSize(t, a.Resize(1, 0), 1, 5)
- checkSize(t, a.Resize(10, 0), 10, 10)
- checkSize(t, a.Resize(5, 0), 5, 10)
- checkSize(t, a.Resize(3, 8), 3, 10)
- checkSize(t, a.Resize(0, 100), 0, 100)
- checkSize(t, a.Resize(11, 100), 11, 100)
-}
-
-func TestResize2(t *testing.T) {
- var a Vector
- checkSize(t, &a, 0, 0)
- a.Push(int2Value(1))
- a.Push(int2Value(2))
- a.Push(int2Value(3))
- a.Push(int2Value(4))
- checkSize(t, &a, 4, 4)
- checkSize(t, a.Resize(10, 0), 10, 10)
- for i := 4; i < a.Len(); i++ {
- if a.At(i) != zero {
- t.Errorf("%T: expected a.At(%d) == %v; found %v!", a, i, zero, a.At(i))
- }
- }
- for i := 4; i < len(a); i++ {
- if a[i] != zero {
- t.Errorf("%T: expected a[%d] == %v; found %v", a, i, zero, a[i])
- }
- }
-}
-
-func checkZero(t *testing.T, a *Vector, i int) {
- for j := 0; j < i; j++ {
- if a.At(j) == zero {
- t.Errorf("%T: 1 expected a.At(%d) == %d; found %v", a, j, j, a.At(j))
- }
- if (*a)[j] == zero {
- t.Errorf("%T: 2 expected (*a)[%d] == %d; found %v", a, j, j, (*a)[j])
- }
- }
- for ; i < a.Len(); i++ {
- if a.At(i) != zero {
- t.Errorf("%T: 3 expected a.At(%d) == %v; found %v", a, i, zero, a.At(i))
- }
- if (*a)[i] != zero {
- t.Errorf("%T: 4 expected (*a)[%d] == %v; found %v", a, i, zero, (*a)[i])
- }
- }
-}
-
-func TestTrailingElements(t *testing.T) {
- var a Vector
- for i := 0; i < 10; i++ {
- a.Push(int2Value(i + 1))
- }
- checkZero(t, &a, 10)
- checkSize(t, &a, 10, 16)
- checkSize(t, a.Resize(5, 0), 5, 16)
- checkSize(t, a.Resize(10, 0), 10, 16)
- checkZero(t, &a, 5)
-}
-
-func TestAccess(t *testing.T) {
- const n = 100
- var a Vector
- a.Resize(n, 0)
- for i := 0; i < n; i++ {
- a.Set(i, int2Value(val(i)))
- }
- for i := 0; i < n; i++ {
- if elem2Value(a.At(i)) != int2Value(val(i)) {
- t.Error(i)
- }
- }
- var b Vector
- b.Resize(n, 0)
- for i := 0; i < n; i++ {
- b[i] = int2Value(val(i))
- }
- for i := 0; i < n; i++ {
- if elem2Value(b[i]) != int2Value(val(i)) {
- t.Error(i)
- }
- }
-}
-
-func TestInsertDeleteClear(t *testing.T) {
- const n = 100
- var a Vector
-
- for i := 0; i < n; i++ {
- if a.Len() != i {
- t.Errorf("%T: A) wrong Len() %d (expected %d)", a, a.Len(), i)
- }
- if len(a) != i {
- t.Errorf("%T: A) wrong len() %d (expected %d)", a, len(a), i)
- }
- a.Insert(0, int2Value(val(i)))
- if elem2Value(a.Last()) != int2Value(val(0)) {
- t.Errorf("%T: B", a)
- }
- }
- for i := n - 1; i >= 0; i-- {
- if elem2Value(a.Last()) != int2Value(val(0)) {
- t.Errorf("%T: C", a)
- }
- if elem2Value(a.At(0)) != int2Value(val(i)) {
- t.Errorf("%T: D", a)
- }
- if elem2Value(a[0]) != int2Value(val(i)) {
- t.Errorf("%T: D2", a)
- }
- a.Delete(0)
- if a.Len() != i {
- t.Errorf("%T: E) wrong Len() %d (expected %d)", a, a.Len(), i)
- }
- if len(a) != i {
- t.Errorf("%T: E) wrong len() %d (expected %d)", a, len(a), i)
- }
- }
-
- if a.Len() != 0 {
- t.Errorf("%T: F) wrong Len() %d (expected 0)", a, a.Len())
- }
- if len(a) != 0 {
- t.Errorf("%T: F) wrong len() %d (expected 0)", a, len(a))
- }
- for i := 0; i < n; i++ {
- a.Push(int2Value(val(i)))
- if a.Len() != i+1 {
- t.Errorf("%T: G) wrong Len() %d (expected %d)", a, a.Len(), i+1)
- }
- if len(a) != i+1 {
- t.Errorf("%T: G) wrong len() %d (expected %d)", a, len(a), i+1)
- }
- if elem2Value(a.Last()) != int2Value(val(i)) {
- t.Errorf("%T: H", a)
- }
- }
- a.Resize(0, 0)
- if a.Len() != 0 {
- t.Errorf("%T: I wrong Len() %d (expected 0)", a, a.Len())
- }
- if len(a) != 0 {
- t.Errorf("%T: I wrong len() %d (expected 0)", a, len(a))
- }
-
- const m = 5
- for j := 0; j < m; j++ {
- a.Push(int2Value(j))
- for i := 0; i < n; i++ {
- x := val(i)
- a.Push(int2Value(x))
- if elem2Value(a.Pop()) != int2Value(x) {
- t.Errorf("%T: J", a)
- }
- if a.Len() != j+1 {
- t.Errorf("%T: K) wrong Len() %d (expected %d)", a, a.Len(), j+1)
- }
- if len(a) != j+1 {
- t.Errorf("%T: K) wrong len() %d (expected %d)", a, len(a), j+1)
- }
- }
- }
- if a.Len() != m {
- t.Errorf("%T: L) wrong Len() %d (expected %d)", a, a.Len(), m)
- }
- if len(a) != m {
- t.Errorf("%T: L) wrong len() %d (expected %d)", a, len(a), m)
- }
-}
-
-func verify_slice(t *testing.T, x *Vector, elt, i, j int) {
- for k := i; k < j; k++ {
- if elem2Value(x.At(k)) != int2Value(elt) {
- t.Errorf("%T: M) wrong [%d] element %v (expected %v)", x, k, elem2Value(x.At(k)), int2Value(elt))
- }
- }
-
- s := x.Slice(i, j)
- for k, n := 0, j-i; k < n; k++ {
- if elem2Value(s.At(k)) != int2Value(elt) {
- t.Errorf("%T: N) wrong [%d] element %v (expected %v)", x, k, elem2Value(x.At(k)), int2Value(elt))
- }
- }
-}
-
-func verify_pattern(t *testing.T, x *Vector, a, b, c int) {
- n := a + b + c
- if x.Len() != n {
- t.Errorf("%T: O) wrong Len() %d (expected %d)", x, x.Len(), n)
- }
- if len(*x) != n {
- t.Errorf("%T: O) wrong len() %d (expected %d)", x, len(*x), n)
- }
- verify_slice(t, x, 0, 0, a)
- verify_slice(t, x, 1, a, a+b)
- verify_slice(t, x, 0, a+b, n)
-}
-
-func make_vector(elt, len int) *Vector {
- x := new(Vector).Resize(len, 0)
- for i := 0; i < len; i++ {
- x.Set(i, int2Value(elt))
- }
- return x
-}
-
-func TestInsertVector(t *testing.T) {
- // 1
- a := make_vector(0, 0)
- b := make_vector(1, 10)
- a.InsertVector(0, b)
- verify_pattern(t, a, 0, 10, 0)
- // 2
- a = make_vector(0, 10)
- b = make_vector(1, 0)
- a.InsertVector(5, b)
- verify_pattern(t, a, 5, 0, 5)
- // 3
- a = make_vector(0, 10)
- b = make_vector(1, 3)
- a.InsertVector(3, b)
- verify_pattern(t, a, 3, 3, 7)
- // 4
- a = make_vector(0, 10)
- b = make_vector(1, 1000)
- a.InsertVector(8, b)
- verify_pattern(t, a, 8, 1000, 2)
-}
-
-func TestDo(t *testing.T) {
- const n = 25
- const salt = 17
- a := new(Vector).Resize(n, 0)
- for i := 0; i < n; i++ {
- a.Set(i, int2Value(salt*i))
- }
- count := 0
- a.Do(func(e interface{}) {
- i := intf2Value(e)
- if i != int2Value(count*salt) {
- t.Error(tname(a), "value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(a), "should visit", n, "values; did visit", count)
- }
-
- b := new(Vector).Resize(n, 0)
- for i := 0; i < n; i++ {
- (*b)[i] = int2Value(salt * i)
- }
- count = 0
- b.Do(func(e interface{}) {
- i := intf2Value(e)
- if i != int2Value(count*salt) {
- t.Error(tname(b), "b) value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(b), "b) should visit", n, "values; did visit", count)
- }
-
- var c Vector
- c.Resize(n, 0)
- for i := 0; i < n; i++ {
- c[i] = int2Value(salt * i)
- }
- count = 0
- c.Do(func(e interface{}) {
- i := intf2Value(e)
- if i != int2Value(count*salt) {
- t.Error(tname(c), "c) value at", count, "should be", count*salt, "not", i)
- }
- count++
- })
- if count != n {
- t.Error(tname(c), "c) should visit", n, "values; did visit", count)
- }
-
-}
-
-func TestVectorCopy(t *testing.T) {
- // verify Copy() returns a copy, not simply a slice of the original vector
- const Len = 10
- var src Vector
- for i := 0; i < Len; i++ {
- src.Push(int2Value(i * i))
- }
- dest := src.Copy()
- for i := 0; i < Len; i++ {
- src[i] = int2Value(-1)
- v := elem2Value(dest[i])
- if v != int2Value(i*i) {
- t.Error(tname(src), "expected", i*i, "got", v)
- }
- }
-}
diff --git a/libgo/go/crypto/bcrypt/base64.go b/libgo/go/crypto/bcrypt/base64.go
new file mode 100644
index 00000000000..ed6cea70c59
--- /dev/null
+++ b/libgo/go/crypto/bcrypt/base64.go
@@ -0,0 +1,38 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bcrypt
+
+import (
+ "encoding/base64"
+ "os"
+)
+
+const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+
+var bcEncoding = base64.NewEncoding(alphabet)
+
+func base64Encode(src []byte) []byte {
+ n := bcEncoding.EncodedLen(len(src))
+ dst := make([]byte, n)
+ bcEncoding.Encode(dst, src)
+ for dst[n-1] == '=' {
+ n--
+ }
+ return dst[:n]
+}
+
+func base64Decode(src []byte) ([]byte, os.Error) {
+ numOfEquals := 4 - (len(src) % 4)
+ for i := 0; i < numOfEquals; i++ {
+ src = append(src, '=')
+ }
+
+ dst := make([]byte, bcEncoding.DecodedLen(len(src)))
+ n, err := bcEncoding.Decode(dst, src)
+ if err != nil {
+ return nil, err
+ }
+ return dst[:n], nil
+}
diff --git a/libgo/go/crypto/bcrypt/bcrypt.go b/libgo/go/crypto/bcrypt/bcrypt.go
new file mode 100644
index 00000000000..1e8ccfac195
--- /dev/null
+++ b/libgo/go/crypto/bcrypt/bcrypt.go
@@ -0,0 +1,282 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package bcrypt implements Provos and Mazières's bcrypt adapative hashing
+// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf
+package bcrypt
+
+// The code is a port of Provos and Mazières's C implementation.
+import (
+ "crypto/blowfish"
+ "crypto/rand"
+ "crypto/subtle"
+ "fmt"
+ "io"
+ "os"
+ "strconv"
+)
+
+const (
+ MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword
+ MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword
+ DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword
+)
+
+// The error returned from CompareHashAndPassword when a password and hash do
+// not match.
+var MismatchedHashAndPasswordError = os.NewError("crypto/bcrypt: hashedPassword is not the hash of the given password")
+
+// The error returned from CompareHashAndPassword when a hash is too short to
+// be a bcrypt hash.
+var HashTooShortError = os.NewError("crypto/bcrypt: hashedSecret too short to be a bcrypted password")
+
+// The error returned from CompareHashAndPassword when a hash was created with
+// a bcrypt algorithm newer than this implementation.
+type HashVersionTooNewError byte
+
+func (hv HashVersionTooNewError) String() string {
+ return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion)
+}
+
+// The error returned from CompareHashAndPassword when a hash starts with something other than '$'
+type InvalidHashPrefixError byte
+
+func (ih InvalidHashPrefixError) String() string {
+ return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih))
+}
+
+type InvalidCostError int
+
+func (ic InvalidCostError) String() string {
+ return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost))
+}
+
+const (
+ majorVersion = '2'
+ minorVersion = 'a'
+ maxSaltSize = 16
+ maxCryptedHashSize = 23
+ encodedSaltSize = 22
+ encodedHashSize = 31
+ minHashSize = 59
+)
+
+// magicCipherData is an IV for the 64 Blowfish encryption calls in
+// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes.
+var magicCipherData = []byte{
+ 0x4f, 0x72, 0x70, 0x68,
+ 0x65, 0x61, 0x6e, 0x42,
+ 0x65, 0x68, 0x6f, 0x6c,
+ 0x64, 0x65, 0x72, 0x53,
+ 0x63, 0x72, 0x79, 0x44,
+ 0x6f, 0x75, 0x62, 0x74,
+}
+
+type hashed struct {
+ hash []byte
+ salt []byte
+ cost uint32 // allowed range is MinCost to MaxCost
+ major byte
+ minor byte
+}
+
+// GenerateFromPassword returns the bcrypt hash of the password at the given
+// cost. If the cost given is less than MinCost, the cost will be set to
+// MinCost, instead. Use CompareHashAndPassword, as defined in this package,
+// to compare the returned hashed password with its cleartext version.
+func GenerateFromPassword(password []byte, cost int) ([]byte, os.Error) {
+ p, err := newFromPassword(password, cost)
+ if err != nil {
+ return nil, err
+ }
+ return p.Hash(), nil
+}
+
+// CompareHashAndPassword compares a bcrypt hashed password with its possible
+// plaintext equivalent. Note: Using bytes.Equal for this job is
+// insecure. Returns nil on success, or an error on failure.
+func CompareHashAndPassword(hashedPassword, password []byte) os.Error {
+ p, err := newFromHash(hashedPassword)
+ if err != nil {
+ return err
+ }
+
+ otherHash, err := bcrypt(password, p.cost, p.salt)
+ if err != nil {
+ return err
+ }
+
+ otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor}
+ if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 {
+ return nil
+ }
+
+ return MismatchedHashAndPasswordError
+}
+
+func newFromPassword(password []byte, cost int) (*hashed, os.Error) {
+ if cost < MinCost {
+ cost = DefaultCost
+ }
+ p := new(hashed)
+ p.major = majorVersion
+ p.minor = minorVersion
+
+ err := checkCost(cost)
+ if err != nil {
+ return nil, err
+ }
+ p.cost = uint32(cost)
+
+ unencodedSalt := make([]byte, maxSaltSize)
+ _, err = io.ReadFull(rand.Reader, unencodedSalt)
+ if err != nil {
+ return nil, err
+ }
+
+ p.salt = base64Encode(unencodedSalt)
+ hash, err := bcrypt(password, p.cost, p.salt)
+ if err != nil {
+ return nil, err
+ }
+ p.hash = hash
+ return p, err
+}
+
+func newFromHash(hashedSecret []byte) (*hashed, os.Error) {
+ if len(hashedSecret) < minHashSize {
+ return nil, HashTooShortError
+ }
+ p := new(hashed)
+ n, err := p.decodeVersion(hashedSecret)
+ if err != nil {
+ return nil, err
+ }
+ hashedSecret = hashedSecret[n:]
+ n, err = p.decodeCost(hashedSecret)
+ if err != nil {
+ return nil, err
+ }
+ hashedSecret = hashedSecret[n:]
+
+ // The "+2" is here because we'll have to append at most 2 '=' to the salt
+ // when base64 decoding it in expensiveBlowfishSetup().
+ p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2)
+ copy(p.salt, hashedSecret[:encodedSaltSize])
+
+ hashedSecret = hashedSecret[encodedSaltSize:]
+ p.hash = make([]byte, len(hashedSecret))
+ copy(p.hash, hashedSecret)
+
+ return p, nil
+}
+
+func bcrypt(password []byte, cost uint32, salt []byte) ([]byte, os.Error) {
+ cipherData := make([]byte, len(magicCipherData))
+ copy(cipherData, magicCipherData)
+
+ c, err := expensiveBlowfishSetup(password, cost, salt)
+ if err != nil {
+ return nil, err
+ }
+
+ for i := 0; i < 24; i += 8 {
+ for j := 0; j < 64; j++ {
+ c.Encrypt(cipherData[i:i+8], cipherData[i:i+8])
+ }
+ }
+
+ // Bug compatibility with C bcrypt implementations. We only encode 23 of
+ // the 24 bytes encrypted.
+ hsh := base64Encode(cipherData[:maxCryptedHashSize])
+ return hsh, nil
+}
+
+func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, os.Error) {
+
+ csalt, err := base64Decode(salt)
+ if err != nil {
+ return nil, err
+ }
+
+ // Bug compatibility with C bcrypt implementations. They use the trailing
+ // NULL in the key string during expansion.
+ ckey := append(key, 0)
+
+ c, err := blowfish.NewSaltedCipher(ckey, csalt)
+ if err != nil {
+ return nil, err
+ }
+
+ rounds := 1 << cost
+ for i := 0; i < rounds; i++ {
+ blowfish.ExpandKey(ckey, c)
+ blowfish.ExpandKey(csalt, c)
+ }
+
+ return c, nil
+}
+
+func (p *hashed) Hash() []byte {
+ arr := make([]byte, 60)
+ arr[0] = '$'
+ arr[1] = p.major
+ n := 2
+ if p.minor != 0 {
+ arr[2] = p.minor
+ n = 3
+ }
+ arr[n] = '$'
+ n += 1
+ copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost)))
+ n += 2
+ arr[n] = '$'
+ n += 1
+ copy(arr[n:], p.salt)
+ n += encodedSaltSize
+ copy(arr[n:], p.hash)
+ n += encodedHashSize
+ return arr[:n]
+}
+
+func (p *hashed) decodeVersion(sbytes []byte) (int, os.Error) {
+ if sbytes[0] != '$' {
+ return -1, InvalidHashPrefixError(sbytes[0])
+ }
+ if sbytes[1] > majorVersion {
+ return -1, HashVersionTooNewError(sbytes[1])
+ }
+ p.major = sbytes[1]
+ n := 3
+ if sbytes[2] != '$' {
+ p.minor = sbytes[2]
+ n++
+ }
+ return n, nil
+}
+
+// sbytes should begin where decodeVersion left off.
+func (p *hashed) decodeCost(sbytes []byte) (int, os.Error) {
+ cost, err := strconv.Atoi(string(sbytes[0:2]))
+ if err != nil {
+ return -1, err
+ }
+ err = checkCost(cost)
+ if err != nil {
+ return -1, err
+ }
+ p.cost = uint32(cost)
+ return 3, nil
+}
+
+func (p *hashed) String() string {
+ return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor)
+}
+
+func checkCost(cost int) os.Error {
+ if cost < MinCost || cost > MaxCost {
+ return InvalidCostError(cost)
+ }
+ return nil
+}
diff --git a/libgo/go/crypto/bcrypt/bcrypt_test.go b/libgo/go/crypto/bcrypt/bcrypt_test.go
new file mode 100644
index 00000000000..89eca0a4488
--- /dev/null
+++ b/libgo/go/crypto/bcrypt/bcrypt_test.go
@@ -0,0 +1,195 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bcrypt
+
+import (
+ "bytes"
+ "os"
+ "testing"
+)
+
+func TestBcryptingIsEasy(t *testing.T) {
+ pass := []byte("mypassword")
+ hp, err := GenerateFromPassword(pass, 0)
+ if err != nil {
+ t.Fatalf("GenerateFromPassword error: %s", err)
+ }
+
+ if CompareHashAndPassword(hp, pass) != nil {
+ t.Errorf("%v should hash %s correctly", hp, pass)
+ }
+
+ notPass := "notthepass"
+ err = CompareHashAndPassword(hp, []byte(notPass))
+ if err != MismatchedHashAndPasswordError {
+ t.Errorf("%v and %s should be mismatched", hp, notPass)
+ }
+}
+
+func TestBcryptingIsCorrect(t *testing.T) {
+ pass := []byte("allmine")
+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+ expectedHash := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
+
+ hash, err := bcrypt(pass, 10, salt)
+ if err != nil {
+ t.Fatalf("bcrypt blew up: %v", err)
+ }
+ if !bytes.HasSuffix(expectedHash, hash) {
+ t.Errorf("%v should be the suffix of %v", hash, expectedHash)
+ }
+
+ h, err := newFromHash(expectedHash)
+ if err != nil {
+ t.Errorf("Unable to parse %s: %v", string(expectedHash), err)
+ }
+
+ // This is not the safe way to compare these hashes. We do this only for
+ // testing clarity. Use bcrypt.CompareHashAndPassword()
+ if err == nil && !bytes.Equal(expectedHash, h.Hash()) {
+ t.Errorf("Parsed hash %v should equal %v", h.Hash(), expectedHash)
+ }
+}
+
+func TestTooLongPasswordsWork(t *testing.T) {
+ salt := []byte("XajjQvNhvvRt5GSeFk1xFe")
+ // One byte over the usual 56 byte limit that blowfish has
+ tooLongPass := []byte("012345678901234567890123456789012345678901234567890123456")
+ tooLongExpected := []byte("$2a$10$XajjQvNhvvRt5GSeFk1xFe5l47dONXg781AmZtd869sO8zfsHuw7C")
+ hash, err := bcrypt(tooLongPass, 10, salt)
+ if err != nil {
+ t.Fatalf("bcrypt blew up on long password: %v", err)
+ }
+ if !bytes.HasSuffix(tooLongExpected, hash) {
+ t.Errorf("%v should be the suffix of %v", hash, tooLongExpected)
+ }
+}
+
+type InvalidHashTest struct {
+ err os.Error
+ hash []byte
+}
+
+var invalidTests = []InvalidHashTest{
+ {HashTooShortError, []byte("$2a$10$fooo")},
+ {HashTooShortError, []byte("$2a")},
+ {HashVersionTooNewError('3'), []byte("$3a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+ {InvalidHashPrefixError('%'), []byte("%2a$10$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+ {InvalidCostError(32), []byte("$2a$32$sssssssssssssssssssssshhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")},
+}
+
+func TestInvalidHashErrors(t *testing.T) {
+ check := func(name string, expected, err os.Error) {
+ if err == nil {
+ t.Errorf("%s: Should have returned an error", name)
+ }
+ if err != nil && err != expected {
+ t.Errorf("%s gave err %v but should have given %v", name, err.String(), expected.String())
+ }
+ }
+ for _, iht := range invalidTests {
+ _, err := newFromHash(iht.hash)
+ check("newFromHash", iht.err, err)
+ err = CompareHashAndPassword(iht.hash, []byte("anything"))
+ check("CompareHashAndPassword", iht.err, err)
+ }
+}
+
+func TestUnpaddedBase64Encoding(t *testing.T) {
+ original := []byte{101, 201, 101, 75, 19, 227, 199, 20, 239, 236, 133, 32, 30, 109, 243, 30}
+ encodedOriginal := []byte("XajjQvNhvvRt5GSeFk1xFe")
+
+ encoded := base64Encode(original)
+
+ if !bytes.Equal(encodedOriginal, encoded) {
+ t.Errorf("Encoded %v should have equaled %v", encoded, encodedOriginal)
+ }
+
+ decoded, err := base64Decode(encodedOriginal)
+ if err != nil {
+ t.Fatalf("base64Decode blew up: %s", err)
+ }
+
+ if !bytes.Equal(decoded, original) {
+ t.Errorf("Decoded %v should have equaled %v", decoded, original)
+ }
+}
+
+func TestCost(t *testing.T) {
+ if testing.Short() {
+ return
+ }
+
+ pass := []byte("mypassword")
+
+ for c := 0; c < MinCost; c++ {
+ p, _ := newFromPassword(pass, c)
+ if p.cost != uint32(DefaultCost) {
+ t.Errorf("newFromPassword should default costs below %d to %d, but was %d", MinCost, DefaultCost, p.cost)
+ }
+ }
+
+ p, _ := newFromPassword(pass, 14)
+ if p.cost != 14 {
+ t.Errorf("newFromPassword should default cost to 14, but was %d", p.cost)
+ }
+
+ hp, _ := newFromHash(p.Hash())
+ if p.cost != hp.cost {
+ t.Errorf("newFromHash should maintain the cost at %d, but was %d", p.cost, hp.cost)
+ }
+
+ _, err := newFromPassword(pass, 32)
+ if err == nil {
+ t.Fatalf("newFromPassword: should return a cost error")
+ }
+ if err != InvalidCostError(32) {
+ t.Errorf("newFromPassword: should return cost error, got %#v", err)
+ }
+}
+
+func TestCostReturnsWithLeadingZeroes(t *testing.T) {
+ hp, _ := newFromPassword([]byte("abcdefgh"), 7)
+ cost := hp.Hash()[4:7]
+ expected := []byte("07$")
+
+ if !bytes.Equal(expected, cost) {
+ t.Errorf("single digit costs in hash should have leading zeros: was %v instead of %v", cost, expected)
+ }
+}
+
+func TestMinorNotRequired(t *testing.T) {
+ noMinorHash := []byte("$2$10$XajjQvNhvvRt5GSeFk1xFeyqRrsxkhBkUiQeg0dt.wU1qD4aFDcga")
+ h, err := newFromHash(noMinorHash)
+ if err != nil {
+ t.Fatalf("No minor hash blew up: %s", err)
+ }
+ if h.minor != 0 {
+ t.Errorf("Should leave minor version at 0, but was %d", h.minor)
+ }
+
+ if !bytes.Equal(noMinorHash, h.Hash()) {
+ t.Errorf("Should generate hash %v, but created %v", noMinorHash, h.Hash())
+ }
+}
+
+func BenchmarkEqual(b *testing.B) {
+ b.StopTimer()
+ passwd := []byte("somepasswordyoulike")
+ hash, _ := GenerateFromPassword(passwd, 10)
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ CompareHashAndPassword(hash, passwd)
+ }
+}
+
+func BenchmarkGeneration(b *testing.B) {
+ b.StopTimer()
+ passwd := []byte("mylongpassword1234")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ GenerateFromPassword(passwd, 10)
+ }
+}
diff --git a/libgo/go/crypto/blowfish/block.go b/libgo/go/crypto/blowfish/block.go
index 7fbe7eefb01..326292dfc3c 100644
--- a/libgo/go/crypto/blowfish/block.go
+++ b/libgo/go/crypto/blowfish/block.go
@@ -4,13 +4,12 @@
package blowfish
-func expandKey(key []byte, c *Cipher) {
- copy(c.p[0:], p[0:])
- copy(c.s0[0:], s0[0:])
- copy(c.s1[0:], s1[0:])
- copy(c.s2[0:], s2[0:])
- copy(c.s3[0:], s3[0:])
-
+// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
+// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
+// pi and substitution tables for calls to Encrypt. This is used, primarily,
+// by the bcrypt package to reuse the Blowfish key schedule during its
+// set up. It's unlikely that you need to use this directly.
+func ExpandKey(key []byte, c *Cipher) {
j := 0
for i := 0; i < 18; i++ {
var d uint32
@@ -48,6 +47,98 @@ func expandKey(key []byte, c *Cipher) {
}
}
+// This is similar to ExpandKey, but folds the salt during the key
+// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
+// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
+// and specializing it here is useful.
+func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
+ j := 0
+ expandedKey := make([]uint32, 18)
+ for i := 0; i < 18; i++ {
+ var d uint32
+ for k := 0; k < 4; k++ {
+ d = d<<8 | uint32(key[j])&0x000000FF
+ j++
+ if j >= len(key) {
+ j = 0
+ }
+ }
+ expandedKey[i] = d
+ c.p[i] ^= d
+ }
+
+ j = 0
+ expandedSalt := make([]uint32, 18)
+ for i := 0; i < 18; i++ {
+ var d uint32
+ for k := 0; k < 4; k++ {
+ d = d<<8 | uint32(salt[j])&0x000000FF
+ j++
+ if j >= len(salt) {
+ j = 0
+ }
+ }
+ expandedSalt[i] = d
+ }
+
+ var l, r uint32
+ for i := 0; i < 18; i += 2 {
+ l ^= expandedSalt[i&2]
+ r ^= expandedSalt[(i&2)+1]
+ l, r = encryptBlock(l, r, c)
+ c.p[i], c.p[i+1] = l, r
+ }
+
+ for i := 0; i < 256; i += 4 {
+ l ^= expandedSalt[2]
+ r ^= expandedSalt[3]
+ l, r = encryptBlock(l, r, c)
+ c.s0[i], c.s0[i+1] = l, r
+
+ l ^= expandedSalt[0]
+ r ^= expandedSalt[1]
+ l, r = encryptBlock(l, r, c)
+ c.s0[i+2], c.s0[i+3] = l, r
+
+ }
+
+ for i := 0; i < 256; i += 4 {
+ l ^= expandedSalt[2]
+ r ^= expandedSalt[3]
+ l, r = encryptBlock(l, r, c)
+ c.s1[i], c.s1[i+1] = l, r
+
+ l ^= expandedSalt[0]
+ r ^= expandedSalt[1]
+ l, r = encryptBlock(l, r, c)
+ c.s1[i+2], c.s1[i+3] = l, r
+ }
+
+ for i := 0; i < 256; i += 4 {
+ l ^= expandedSalt[2]
+ r ^= expandedSalt[3]
+ l, r = encryptBlock(l, r, c)
+ c.s2[i], c.s2[i+1] = l, r
+
+ l ^= expandedSalt[0]
+ r ^= expandedSalt[1]
+ l, r = encryptBlock(l, r, c)
+ c.s2[i+2], c.s2[i+3] = l, r
+ }
+
+ for i := 0; i < 256; i += 4 {
+ l ^= expandedSalt[2]
+ r ^= expandedSalt[3]
+ l, r = encryptBlock(l, r, c)
+ c.s3[i], c.s3[i+1] = l, r
+
+ l ^= expandedSalt[0]
+ r ^= expandedSalt[1]
+ l, r = encryptBlock(l, r, c)
+ c.s3[i+2], c.s3[i+3] = l, r
+ }
+}
+
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
xl, xr := l, r
xl ^= c.p[0]
diff --git a/libgo/go/crypto/blowfish/blowfish_test.go b/libgo/go/crypto/blowfish/blowfish_test.go
index 3a7ab6c2a8d..1038d2e39ee 100644
--- a/libgo/go/crypto/blowfish/blowfish_test.go
+++ b/libgo/go/crypto/blowfish/blowfish_test.go
@@ -190,3 +190,21 @@ func TestCipherDecrypt(t *testing.T) {
}
}
}
+
+func TestSaltedCipherKeyLength(t *testing.T) {
+ var key []byte
+ for i := 0; i < 4; i++ {
+ _, err := NewSaltedCipher(key, []byte{'a'})
+ if err != KeySizeError(i) {
+ t.Errorf("NewSaltedCipher with short key, gave error %#v, expected %#v", err, KeySizeError(i))
+ }
+ key = append(key, 'a')
+ }
+
+ // A 57-byte key. One over the typical blowfish restriction.
+ key = []byte("012345678901234567890123456789012345678901234567890123456")
+ _, err := NewSaltedCipher(key, []byte{'a'})
+ if err != nil {
+ t.Errorf("NewSaltedCipher with long key, gave error %#v", err)
+ }
+}
diff --git a/libgo/go/crypto/blowfish/cipher.go b/libgo/go/crypto/blowfish/cipher.go
index 6c37dfe9405..3439825e893 100644
--- a/libgo/go/crypto/blowfish/cipher.go
+++ b/libgo/go/crypto/blowfish/cipher.go
@@ -31,12 +31,28 @@ func (k KeySizeError) String() string {
// NewCipher creates and returns a Cipher.
// The key argument should be the Blowfish key, 4 to 56 bytes.
func NewCipher(key []byte) (*Cipher, os.Error) {
+ var result Cipher
k := len(key)
if k < 4 || k > 56 {
return nil, KeySizeError(k)
}
+ initCipher(key, &result)
+ ExpandKey(key, &result)
+ return &result, nil
+}
+
+// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
+// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
+// sufficient and desirable. For bcrypt compatiblity, the key can be over 56
+// bytes.
+func NewSaltedCipher(key, salt []byte) (*Cipher, os.Error) {
var result Cipher
- expandKey(key, &result)
+ k := len(key)
+ if k < 4 {
+ return nil, KeySizeError(k)
+ }
+ initCipher(key, &result)
+ expandKeyWithSalt(key, salt, &result)
return &result, nil
}
@@ -77,3 +93,11 @@ func (c *Cipher) Reset() {
zero(c.s2[0:])
zero(c.s3[0:])
}
+
+func initCipher(key []byte, c *Cipher) {
+ copy(c.p[0:], p[0:])
+ copy(c.s0[0:], s0[0:])
+ copy(c.s1[0:], s1[0:])
+ copy(c.s2[0:], s2[0:])
+ copy(c.s3[0:], s3[0:])
+}
diff --git a/libgo/go/crypto/elliptic/elliptic_test.go b/libgo/go/crypto/elliptic/elliptic_test.go
index b7e7f035fa5..9578364b58f 100644
--- a/libgo/go/crypto/elliptic/elliptic_test.go
+++ b/libgo/go/crypto/elliptic/elliptic_test.go
@@ -295,7 +295,7 @@ func TestBaseMult(t *testing.T) {
}
x, y := p224.ScalarBaseMult(k.Bytes())
if fmt.Sprintf("%x", x) != e.x || fmt.Sprintf("%x", y) != e.y {
- t.Errorf("%d: bad output for k=%s: got (%x, %s), want (%s, %s)", i, e.k, x, y, e.x, e.y)
+ t.Errorf("%d: bad output for k=%s: got (%x, %s), want (%x, %s)", i, e.k, x, y, e.x, e.y)
}
if testing.Short() && i > 5 {
break
diff --git a/libgo/go/crypto/ocsp/ocsp_test.go b/libgo/go/crypto/ocsp/ocsp_test.go
index f9889790f09..7be37211c10 100644
--- a/libgo/go/crypto/ocsp/ocsp_test.go
+++ b/libgo/go/crypto/ocsp/ocsp_test.go
@@ -15,7 +15,7 @@ func TestOCSPDecode(t *testing.T) {
t.Error(err)
}
- expected := Response{Status: 0, SerialNumber: []byte{0x1, 0xd0, 0xfa}, RevocationReason: 0, ThisUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 15, Minute: 1, Second: 5, Weekday: 0, ZoneOffset: 0, Zone: "UTC"}, NextUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 18, Minute: 35, Second: 17, Weekday: 0, ZoneOffset: 0, Zone: "UTC"}}
+ expected := Response{Status: 0, SerialNumber: []byte{0x1, 0xd0, 0xfa}, RevocationReason: 0, ThisUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 15, Minute: 1, Second: 5, ZoneOffset: 0, Zone: "UTC"}, NextUpdate: &time.Time{Year: 2010, Month: 7, Day: 7, Hour: 18, Minute: 35, Second: 17, ZoneOffset: 0, Zone: "UTC"}}
if !reflect.DeepEqual(resp.ThisUpdate, resp.ThisUpdate) {
t.Errorf("resp.ThisUpdate: got %d, want %d", resp.ThisUpdate, expected.ThisUpdate)
diff --git a/libgo/go/crypto/openpgp/s2k/s2k.go b/libgo/go/crypto/openpgp/s2k/s2k.go
index da926a76ed2..013b15c1497 100644
--- a/libgo/go/crypto/openpgp/s2k/s2k.go
+++ b/libgo/go/crypto/openpgp/s2k/s2k.go
@@ -100,7 +100,7 @@ func Parse(r io.Reader) (f func(out, in []byte), err os.Error) {
}
return f, nil
case 2:
- _, err := io.ReadFull(r, buf[:8])
+ _, err = io.ReadFull(r, buf[:8])
if err != nil {
return
}
@@ -109,7 +109,7 @@ func Parse(r io.Reader) (f func(out, in []byte), err os.Error) {
}
return f, nil
case 3:
- _, err := io.ReadFull(r, buf[:9])
+ _, err = io.ReadFull(r, buf[:9])
if err != nil {
return
}
diff --git a/libgo/go/crypto/rand/rand_unix.go b/libgo/go/crypto/rand/rand_unix.go
index 3a06aa8b148..76a7365b7fe 100644
--- a/libgo/go/crypto/rand/rand_unix.go
+++ b/libgo/go/crypto/rand/rand_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
// Unix cryptographically secure pseudorandom number
// generator.
diff --git a/libgo/go/crypto/tls/cipher_suites.go b/libgo/go/crypto/tls/cipher_suites.go
index bc7b0d32f95..0c62251a7cd 100644
--- a/libgo/go/crypto/tls/cipher_suites.go
+++ b/libgo/go/crypto/tls/cipher_suites.go
@@ -7,8 +7,10 @@ package tls
import (
"crypto/aes"
"crypto/cipher"
+ "crypto/des"
"crypto/hmac"
"crypto/rc4"
+ "crypto/sha1"
"crypto/x509"
"hash"
"os"
@@ -23,7 +25,7 @@ type keyAgreement interface {
// ServerKeyExchange message, generateServerKeyExchange can return nil,
// nil.
generateServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg) (*serverKeyExchangeMsg, os.Error)
- processClientKeyExchange(*Config, *clientKeyExchangeMsg) ([]byte, os.Error)
+ processClientKeyExchange(*Config, *clientKeyExchangeMsg, uint16) ([]byte, os.Error)
// On the client side, the next two methods are called in order.
@@ -46,14 +48,16 @@ type cipherSuite struct {
// and point format that we can handle.
elliptic bool
cipher func(key, iv []byte, isRead bool) interface{}
- mac func(macKey []byte) hash.Hash
+ mac func(version uint16, macKey []byte) macFunction
}
var cipherSuites = map[uint16]*cipherSuite{
- TLS_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, rsaKA, false, cipherRC4, hmacSHA1},
- TLS_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, rsaKA, false, cipherAES, hmacSHA1},
- TLS_ECDHE_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, ecdheRSAKA, true, cipherRC4, hmacSHA1},
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, ecdheRSAKA, true, cipherAES, hmacSHA1},
+ TLS_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, rsaKA, false, cipherRC4, macSHA1},
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA: &cipherSuite{24, 20, 8, rsaKA, false, cipher3DES, macSHA1},
+ TLS_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, rsaKA, false, cipherAES, macSHA1},
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA: &cipherSuite{16, 20, 0, ecdheRSAKA, true, cipherRC4, macSHA1},
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: &cipherSuite{24, 20, 8, ecdheRSAKA, true, cipher3DES, macSHA1},
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: &cipherSuite{16, 20, 16, ecdheRSAKA, true, cipherAES, macSHA1},
}
func cipherRC4(key, iv []byte, isRead bool) interface{} {
@@ -61,6 +65,14 @@ func cipherRC4(key, iv []byte, isRead bool) interface{} {
return cipher
}
+func cipher3DES(key, iv []byte, isRead bool) interface{} {
+ block, _ := des.NewTripleDESCipher(key)
+ if isRead {
+ return cipher.NewCBCDecrypter(block, iv)
+ }
+ return cipher.NewCBCEncrypter(block, iv)
+}
+
func cipherAES(key, iv []byte, isRead bool) interface{} {
block, _ := aes.NewCipher(key)
if isRead {
@@ -69,8 +81,75 @@ func cipherAES(key, iv []byte, isRead bool) interface{} {
return cipher.NewCBCEncrypter(block, iv)
}
-func hmacSHA1(key []byte) hash.Hash {
- return hmac.NewSHA1(key)
+// macSHA1 returns a macFunction for the given protocol version.
+func macSHA1(version uint16, key []byte) macFunction {
+ if version == versionSSL30 {
+ mac := ssl30MAC{
+ h: sha1.New(),
+ key: make([]byte, len(key)),
+ }
+ copy(mac.key, key)
+ return mac
+ }
+ return tls10MAC{hmac.NewSHA1(key)}
+}
+
+type macFunction interface {
+ Size() int
+ MAC(seq, data []byte) []byte
+}
+
+// ssl30MAC implements the SSLv3 MAC function, as defined in
+// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 5.2.3.1
+type ssl30MAC struct {
+ h hash.Hash
+ key []byte
+}
+
+func (s ssl30MAC) Size() int {
+ return s.h.Size()
+}
+
+var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36}
+
+var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c}
+
+func (s ssl30MAC) MAC(seq, record []byte) []byte {
+ padLength := 48
+ if s.h.Size() == 20 {
+ padLength = 40
+ }
+
+ s.h.Reset()
+ s.h.Write(s.key)
+ s.h.Write(ssl30Pad1[:padLength])
+ s.h.Write(seq)
+ s.h.Write(record[:1])
+ s.h.Write(record[3:5])
+ s.h.Write(record[recordHeaderLen:])
+ digest := s.h.Sum()
+
+ s.h.Reset()
+ s.h.Write(s.key)
+ s.h.Write(ssl30Pad2[:padLength])
+ s.h.Write(digest)
+ return s.h.Sum()
+}
+
+// tls10MAC implements the TLS 1.0 MAC function. RFC 2246, section 6.2.3.
+type tls10MAC struct {
+ h hash.Hash
+}
+
+func (s tls10MAC) Size() int {
+ return s.h.Size()
+}
+
+func (s tls10MAC) MAC(seq, record []byte) []byte {
+ s.h.Reset()
+ s.h.Write(seq)
+ s.h.Write(record)
+ return s.h.Sum()
}
func rsaKA() keyAgreement {
@@ -95,8 +174,10 @@ func mutualCipherSuite(have []uint16, want uint16) (suite *cipherSuite, id uint1
// A list of the possible cipher suite ids. Taken from
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
const (
- TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
- TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
- TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
+ TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000a
+ TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002f
+ TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xc011
+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xc012
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xc013
)
diff --git a/libgo/go/crypto/tls/common.go b/libgo/go/crypto/tls/common.go
index 3efac9c13b0..ea520859b82 100644
--- a/libgo/go/crypto/tls/common.go
+++ b/libgo/go/crypto/tls/common.go
@@ -9,7 +9,7 @@ import (
"crypto/rsa"
"crypto/x509"
"io"
- "io/ioutil"
+ "strings"
"sync"
"time"
)
@@ -20,8 +20,11 @@ const (
recordHeaderLen = 5 // record header length
maxHandshake = 65536 // maximum handshake we support (protocol max is 16 MB)
- minVersion = 0x0301 // minimum supported version - TLS 1.0
- maxVersion = 0x0301 // maximum supported version - TLS 1.0
+ versionSSL30 = 0x0300
+ versionTLS10 = 0x0301
+
+ minVersion = versionSSL30
+ maxVersion = versionTLS10
)
// TLS record types.
@@ -98,6 +101,10 @@ type ConnectionState struct {
NegotiatedProtocol string
NegotiatedProtocolIsMutual bool
+ // ServerName contains the server name indicated by the client, if any.
+ // (Only valid for server connections.)
+ ServerName string
+
// the certificate chain that was presented by the other side
PeerCertificates []*x509.Certificate
// the verified certificate chains built from PeerCertificates.
@@ -121,6 +128,14 @@ type Config struct {
// Server configurations must include at least one certificate.
Certificates []Certificate
+ // NameToCertificate maps from a certificate name to an element of
+ // Certificates. Note that a certificate name can be of the form
+ // '*.example.com' and so doesn't have to be a domain name as such.
+ // See Config.BuildNameToCertificate
+ // The nil value causes the first element of Certificates to be used
+ // for all connections.
+ NameToCertificate map[string]*Certificate
+
// RootCAs defines the set of root certificate authorities
// that clients use when verifying server certificates.
// If RootCAs is nil, TLS uses the host's root CA set.
@@ -139,6 +154,14 @@ type Config struct {
// anything more than self-signed.
AuthenticateClient bool
+ // InsecureSkipVerify controls whether a client verifies the
+ // server's certificate chain and host name.
+ // If InsecureSkipVerify is true, TLS accepts any certificate
+ // presented by the server and any host name in that certificate.
+ // In this mode, TLS is susceptible to man-in-the-middle attacks.
+ // This should be used only for testing.
+ InsecureSkipVerify bool
+
// CipherSuites is a list of supported cipher suites. If CipherSuites
// is nil, TLS uses a list of suites supported by the implementation.
CipherSuites []uint16
@@ -176,6 +199,59 @@ func (c *Config) cipherSuites() []uint16 {
return s
}
+// getCertificateForName returns the best certificate for the given name,
+// defaulting to the first element of c.Certificates if there are no good
+// options.
+func (c *Config) getCertificateForName(name string) *Certificate {
+ if len(c.Certificates) == 1 || c.NameToCertificate == nil {
+ // There's only one choice, so no point doing any work.
+ return &c.Certificates[0]
+ }
+
+ name = strings.ToLower(name)
+ for len(name) > 0 && name[len(name)-1] == '.' {
+ name = name[:len(name)-1]
+ }
+
+ if cert, ok := c.NameToCertificate[name]; ok {
+ return cert
+ }
+
+ // try replacing labels in the name with wildcards until we get a
+ // match.
+ labels := strings.Split(name, ".")
+ for i := range labels {
+ labels[i] = "*"
+ candidate := strings.Join(labels, ".")
+ if cert, ok := c.NameToCertificate[candidate]; ok {
+ return cert
+ }
+ }
+
+ // If nothing matches, return the first certificate.
+ return &c.Certificates[0]
+}
+
+// BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
+// from the CommonName and SubjectAlternateName fields of each of the leaf
+// certificates.
+func (c *Config) BuildNameToCertificate() {
+ c.NameToCertificate = make(map[string]*Certificate)
+ for i := range c.Certificates {
+ cert := &c.Certificates[i]
+ x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
+ if err != nil {
+ continue
+ }
+ if len(x509Cert.Subject.CommonName) > 0 {
+ c.NameToCertificate[x509Cert.Subject.CommonName] = cert
+ }
+ for _, san := range x509Cert.DNSNames {
+ c.NameToCertificate[san] = cert
+ }
+ }
+}
+
// A Certificate is a chain of one or more certificates, leaf first.
type Certificate struct {
Certificate [][]byte
@@ -215,15 +291,6 @@ func defaultConfig() *Config {
return &emptyConfig
}
-// Possible certificate files; stop after finding one.
-// On OS X we should really be using the Directory Services keychain
-// but that requires a lot of Mach goo to get at. Instead we use
-// the same root set that curl uses.
-var certFiles = []string{
- "/etc/ssl/certs/ca-certificates.crt", // Linux etc
- "/usr/share/curl/curl-ca-bundle.crt", // OS X
-}
-
var once sync.Once
func defaultRoots() *x509.CertPool {
@@ -241,21 +308,10 @@ func initDefaults() {
initDefaultCipherSuites()
}
-var varDefaultRoots *x509.CertPool
-
-func initDefaultRoots() {
- roots := x509.NewCertPool()
- for _, file := range certFiles {
- data, err := ioutil.ReadFile(file)
- if err == nil {
- roots.AppendCertsFromPEM(data)
- break
- }
- }
- varDefaultRoots = roots
-}
-
-var varDefaultCipherSuites []uint16
+var (
+ varDefaultRoots *x509.CertPool
+ varDefaultCipherSuites []uint16
+)
func initDefaultCipherSuites() {
varDefaultCipherSuites = make([]uint16, len(cipherSuites))
diff --git a/libgo/go/crypto/tls/conn.go b/libgo/go/crypto/tls/conn.go
index fac65afd9cf..9bca7d95d90 100644
--- a/libgo/go/crypto/tls/conn.go
+++ b/libgo/go/crypto/tls/conn.go
@@ -11,7 +11,6 @@ import (
"crypto/cipher"
"crypto/subtle"
"crypto/x509"
- "hash"
"io"
"net"
"os"
@@ -37,6 +36,8 @@ type Conn struct {
// verifiedChains contains the certificate chains that we built, as
// opposed to the ones presented by the server.
verifiedChains [][]*x509.Certificate
+ // serverName contains the server name indicated by the client, if any.
+ serverName string
clientProtocol string
clientProtocolFallback bool
@@ -108,18 +109,20 @@ func (c *Conn) SetWriteTimeout(nsec int64) os.Error {
// connection, either sending or receiving.
type halfConn struct {
sync.Mutex
- cipher interface{} // cipher algorithm
- mac hash.Hash // MAC algorithm
- seq [8]byte // 64-bit sequence number
- bfree *block // list of free blocks
+ version uint16 // protocol version
+ cipher interface{} // cipher algorithm
+ mac macFunction
+ seq [8]byte // 64-bit sequence number
+ bfree *block // list of free blocks
nextCipher interface{} // next encryption state
- nextMac hash.Hash // next MAC algorithm
+ nextMac macFunction // next MAC algorithm
}
// prepareCipherSpec sets the encryption and MAC states
// that a subsequent changeCipherSpec will use.
-func (hc *halfConn) prepareCipherSpec(cipher interface{}, mac hash.Hash) {
+func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) {
+ hc.version = version
hc.nextCipher = cipher
hc.nextMac = mac
}
@@ -197,6 +200,22 @@ func removePadding(payload []byte) ([]byte, byte) {
return payload[:len(payload)-int(toRemove)], good
}
+// removePaddingSSL30 is a replacement for removePadding in the case that the
+// protocol version is SSLv3. In this version, the contents of the padding
+// are random and cannot be checked.
+func removePaddingSSL30(payload []byte) ([]byte, byte) {
+ if len(payload) < 1 {
+ return payload, 0
+ }
+
+ paddingLen := int(payload[len(payload)-1]) + 1
+ if paddingLen > len(payload) {
+ return payload, 0
+ }
+
+ return payload[:len(payload)-paddingLen], 255
+}
+
func roundUp(a, b int) int {
return a + (b-a%b)%b
}
@@ -226,7 +245,11 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
}
c.CryptBlocks(payload, payload)
- payload, paddingGood = removePadding(payload)
+ if hc.version == versionSSL30 {
+ payload, paddingGood = removePaddingSSL30(payload)
+ } else {
+ payload, paddingGood = removePadding(payload)
+ }
b.resize(recordHeaderLen + len(payload))
// note that we still have a timing side-channel in the
@@ -256,13 +279,10 @@ func (hc *halfConn) decrypt(b *block) (bool, alert) {
b.data[4] = byte(n)
b.resize(recordHeaderLen + n)
remoteMAC := payload[n:]
-
- hc.mac.Reset()
- hc.mac.Write(hc.seq[0:])
+ localMAC := hc.mac.MAC(hc.seq[0:], b.data)
hc.incSeq()
- hc.mac.Write(b.data)
- if subtle.ConstantTimeCompare(hc.mac.Sum(), remoteMAC) != 1 || paddingGood != 255 {
+ if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
return false, alertBadRecordMAC
}
}
@@ -291,11 +311,9 @@ func padToBlockSize(payload []byte, blockSize int) (prefix, finalBlock []byte) {
func (hc *halfConn) encrypt(b *block) (bool, alert) {
// mac
if hc.mac != nil {
- hc.mac.Reset()
- hc.mac.Write(hc.seq[0:])
+ mac := hc.mac.MAC(hc.seq[0:], b.data)
hc.incSeq()
- hc.mac.Write(b.data)
- mac := hc.mac.Sum()
+
n := len(b.data)
b.resize(n + len(mac))
copy(b.data[n:], mac)
@@ -470,6 +488,19 @@ Again:
if n > maxCiphertext {
return c.sendAlert(alertRecordOverflow)
}
+ if !c.haveVers {
+ // First message, be extra suspicious:
+ // this might not be a TLS client.
+ // Bail out before reading a full 'body', if possible.
+ // The current max version is 3.1.
+ // If the version is >= 16.0, it's probably not real.
+ // Similarly, a clientHello message encodes in
+ // well under a kilobyte. If the length is >= 12 kB,
+ // it's probably not real.
+ if (typ != recordTypeAlert && typ != want) || vers >= 0x1000 || n >= 0x3000 {
+ return c.sendAlert(alertUnexpectedMessage)
+ }
+ }
if err := b.readFromUntil(c.conn, recordHeaderLen+n); err != nil {
if err == os.EOF {
err = io.ErrUnexpectedEOF
@@ -627,7 +658,9 @@ func (c *Conn) readHandshake() (interface{}, os.Error) {
if c.err != nil {
return nil, c.err
}
- c.readRecord(recordTypeHandshake)
+ if err := c.readRecord(recordTypeHandshake); err != nil {
+ return nil, err
+ }
}
data := c.hand.Bytes()
@@ -640,7 +673,9 @@ func (c *Conn) readHandshake() (interface{}, os.Error) {
if c.err != nil {
return nil, c.err
}
- c.readRecord(recordTypeHandshake)
+ if err := c.readRecord(recordTypeHandshake); err != nil {
+ return nil, err
+ }
}
data = c.hand.Next(4 + n)
var m handshakeMessage
@@ -731,10 +766,18 @@ func (c *Conn) Read(b []byte) (n int, err os.Error) {
// Close closes the connection.
func (c *Conn) Close() os.Error {
- if err := c.Handshake(); err != nil {
+ var alertErr os.Error
+
+ c.handshakeMutex.Lock()
+ defer c.handshakeMutex.Unlock()
+ if c.handshakeComplete {
+ alertErr = c.sendAlert(alertCloseNotify)
+ }
+
+ if err := c.conn.Close(); err != nil {
return err
}
- return c.sendAlert(alertCloseNotify)
+ return alertErr
}
// Handshake runs the client or server handshake
@@ -769,6 +812,7 @@ func (c *Conn) ConnectionState() ConnectionState {
state.CipherSuite = c.cipherSuite
state.PeerCertificates = c.peerCertificates
state.VerifiedChains = c.verifiedChains
+ state.ServerName = c.serverName
}
return state
diff --git a/libgo/go/crypto/tls/conn_test.go b/libgo/go/crypto/tls/conn_test.go
index f44a50bedde..5c555147ca8 100644
--- a/libgo/go/crypto/tls/conn_test.go
+++ b/libgo/go/crypto/tls/conn_test.go
@@ -50,3 +50,57 @@ func TestRemovePadding(t *testing.T) {
}
}
}
+
+var certExampleCom = `308201403081eda003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313138353835325a170d3132303933303138353835325a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31a301830160603551d11040f300d820b6578616d706c652e636f6d300b06092a864886f70d0101050341001a0b419d2c74474c6450654e5f10b32bf426ffdf55cad1c52602e7a9151513a3424c70f5960dcd682db0c33769cc1daa3fcdd3db10809d2392ed4a1bf50ced18`
+
+var certWildcardExampleCom = `308201423081efa003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303034365a170d3132303933303139303034365a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31c301a30180603551d110411300f820d2a2e6578616d706c652e636f6d300b06092a864886f70d0101050341001676f0c9e7c33c1b656ed5a6476c4e2ee9ec8e62df7407accb1875272b2edd0a22096cb2c22598d11604104d604f810eb4b5987ca6bb319c7e6ce48725c54059`
+
+var certFooExampleCom = `308201443081f1a003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303131345a170d3132303933303139303131345a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31e301c301a0603551d1104133011820f666f6f2e6578616d706c652e636f6d300b06092a864886f70d010105034100646a2a51f2aa2477add854b462cf5207ba16d3213ffb5d3d0eed473fbf09935019192d1d5b8ca6a2407b424cf04d97c4cd9197c83ecf81f0eab9464a1109d09f`
+
+var certDoubleWildcardExampleCom = `308201443081f1a003020102020101300b06092a864886f70d010105301e311c301a060355040a131354657374696e67204365727469666963617465301e170d3131313030313139303134315a170d3132303933303139303134315a301e311c301a060355040a131354657374696e67204365727469666963617465305a300b06092a864886f70d010101034b003048024100bced6e32368599eeddf18796bfd03958a154f87e5b084f96e85136a56b886733592f493f0fc68b0d6b3551781cb95e13c5de458b28d6fb60d20a9129313261410203010001a31e301c301a0603551d1104133011820f2a2e2a2e6578616d706c652e636f6d300b06092a864886f70d0101050341001c3de267975f56ef57771c6218ef95ecc65102e57bd1defe6f7efea90d9b26cf40de5bd7ad75e46201c7f2a92aaa3e907451e9409f65e28ddb6db80d726290f6`
+
+func TestCertificateSelection(t *testing.T) {
+ config := Config{
+ Certificates: []Certificate{
+ {
+ Certificate: [][]byte{fromHex(certExampleCom)},
+ },
+ {
+ Certificate: [][]byte{fromHex(certWildcardExampleCom)},
+ },
+ {
+ Certificate: [][]byte{fromHex(certFooExampleCom)},
+ },
+ {
+ Certificate: [][]byte{fromHex(certDoubleWildcardExampleCom)},
+ },
+ },
+ }
+
+ config.BuildNameToCertificate()
+
+ pointerToIndex := func(c *Certificate) int {
+ for i := range config.Certificates {
+ if c == &config.Certificates[i] {
+ return i
+ }
+ }
+ return -1
+ }
+
+ if n := pointerToIndex(config.getCertificateForName("example.com")); n != 0 {
+ t.Errorf("example.com returned certificate %d, not 0", n)
+ }
+ if n := pointerToIndex(config.getCertificateForName("bar.example.com")); n != 1 {
+ t.Errorf("bar.example.com returned certificate %d, not 1", n)
+ }
+ if n := pointerToIndex(config.getCertificateForName("foo.example.com")); n != 2 {
+ t.Errorf("foo.example.com returned certificate %d, not 2", n)
+ }
+ if n := pointerToIndex(config.getCertificateForName("foo.bar.example.com")); n != 3 {
+ t.Errorf("foo.bar.example.com returned certificate %d, not 3", n)
+ }
+ if n := pointerToIndex(config.getCertificateForName("foo.bar.baz.example.com")); n != 0 {
+ t.Errorf("foo.bar.baz.example.com returned certificate %d, not 0", n)
+ }
+}
diff --git a/libgo/go/crypto/tls/handshake_client.go b/libgo/go/crypto/tls/handshake_client.go
index 15604cea7ea..575a121f391 100644
--- a/libgo/go/crypto/tls/handshake_client.go
+++ b/libgo/go/crypto/tls/handshake_client.go
@@ -14,7 +14,7 @@ import (
)
func (c *Conn) clientHandshake() os.Error {
- finishedHash := newFinishedHash()
+ finishedHash := newFinishedHash(versionTLS10)
if c.config == nil {
c.config = defaultConfig()
@@ -97,11 +97,9 @@ func (c *Conn) clientHandshake() os.Error {
certs[i] = cert
}
- // If we don't have a root CA set configured then anything is accepted.
- // TODO(rsc): Find certificates for OS X 10.6.
- if c.config.RootCAs != nil {
+ if !c.config.InsecureSkipVerify {
opts := x509.VerifyOptions{
- Roots: c.config.RootCAs,
+ Roots: c.config.rootCAs(),
CurrentTime: c.config.time(),
DNSName: c.config.ServerName,
Intermediates: x509.NewCertPool(),
@@ -247,11 +245,11 @@ func (c *Conn) clientHandshake() os.Error {
}
masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromPreMasterSecret10(preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
+ keysFromPreMasterSecret(c.vers, preMasterSecret, hello.random, serverHello.random, suite.macLen, suite.keyLen, suite.ivLen)
clientCipher := suite.cipher(clientKey, clientIV, false /* not for reading */ )
- clientHash := suite.mac(clientMAC)
- c.out.prepareCipherSpec(clientCipher, clientHash)
+ clientHash := suite.mac(c.vers, clientMAC)
+ c.out.prepareCipherSpec(c.vers, clientCipher, clientHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
if serverHello.nextProtoNeg {
@@ -271,8 +269,8 @@ func (c *Conn) clientHandshake() os.Error {
c.writeRecord(recordTypeHandshake, finished.marshal())
serverCipher := suite.cipher(serverKey, serverIV, true /* for reading */ )
- serverHash := suite.mac(serverMAC)
- c.in.prepareCipherSpec(serverCipher, serverHash)
+ serverHash := suite.mac(c.vers, serverMAC)
+ c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
c.readRecord(recordTypeChangeCipherSpec)
if c.err != nil {
return c.err
diff --git a/libgo/go/crypto/tls/handshake_client_test.go b/libgo/go/crypto/tls/handshake_client_test.go
index 3f91c7acf1f..c0abcda2001 100644
--- a/libgo/go/crypto/tls/handshake_client_test.go
+++ b/libgo/go/crypto/tls/handshake_client_test.go
@@ -18,6 +18,7 @@ func testClientScript(t *testing.T, name string, clientScript [][]byte, config *
go func() {
cli.Write([]byte("hello\n"))
cli.Close()
+ c.Close()
}()
defer c.Close()
diff --git a/libgo/go/crypto/tls/handshake_messages.go b/libgo/go/crypto/tls/handshake_messages.go
index 6645adce4f2..f11232d8ee5 100644
--- a/libgo/go/crypto/tls/handshake_messages.go
+++ b/libgo/go/crypto/tls/handshake_messages.go
@@ -676,9 +676,9 @@ func (m *finishedMsg) marshal() (x []byte) {
return m.raw
}
- x = make([]byte, 16)
+ x = make([]byte, 4+len(m.verifyData))
x[0] = typeFinished
- x[3] = 12
+ x[3] = byte(len(m.verifyData))
copy(x[4:], m.verifyData)
m.raw = x
return
@@ -686,7 +686,7 @@ func (m *finishedMsg) marshal() (x []byte) {
func (m *finishedMsg) unmarshal(data []byte) bool {
m.raw = data
- if len(data) != 4+12 {
+ if len(data) < 4 {
return false
}
m.verifyData = data[4:]
diff --git a/libgo/go/crypto/tls/handshake_messages_test.go b/libgo/go/crypto/tls/handshake_messages_test.go
index 23f729dd94b..dc68a12239a 100644
--- a/libgo/go/crypto/tls/handshake_messages_test.go
+++ b/libgo/go/crypto/tls/handshake_messages_test.go
@@ -14,13 +14,13 @@ import (
var tests = []interface{}{
&clientHelloMsg{},
&serverHelloMsg{},
+ &finishedMsg{},
&certificateMsg{},
&certificateRequestMsg{},
&certificateVerifyMsg{},
&certificateStatusMsg{},
&clientKeyExchangeMsg{},
- &finishedMsg{},
&nextProtoMsg{},
}
@@ -59,11 +59,12 @@ func TestMarshalUnmarshal(t *testing.T) {
break
}
- if i >= 2 {
- // The first two message types (ClientHello and
- // ServerHello) are allowed to have parsable
- // prefixes because the extension data is
- // optional.
+ if i >= 3 {
+ // The first three message types (ClientHello,
+ // ServerHello and Finished) are allowed to
+ // have parsable prefixes because the extension
+ // data is optional and the length of the
+ // Finished varies across versions.
for j := 0; j < len(marshaled); j++ {
if m2.unmarshal(marshaled[0:j]) {
t.Errorf("#%d unmarshaled a prefix of length %d of %#v", i, j, m1)
diff --git a/libgo/go/crypto/tls/handshake_server.go b/libgo/go/crypto/tls/handshake_server.go
index 44a32404148..ed9a2e6a512 100644
--- a/libgo/go/crypto/tls/handshake_server.go
+++ b/libgo/go/crypto/tls/handshake_server.go
@@ -30,7 +30,7 @@ func (c *Conn) serverHandshake() os.Error {
c.vers = vers
c.haveVers = true
- finishedHash := newFinishedHash()
+ finishedHash := newFinishedHash(vers)
finishedHash.Write(clientHello.marshal())
hello := new(serverHelloMsg)
@@ -115,7 +115,12 @@ FindCipherSuite:
}
certMsg := new(certificateMsg)
- certMsg.certificates = config.Certificates[0].Certificate
+ if len(clientHello.serverName) > 0 {
+ c.serverName = clientHello.serverName
+ certMsg.certificates = config.getCertificateForName(clientHello.serverName).Certificate
+ } else {
+ certMsg.certificates = config.Certificates[0].Certificate
+ }
finishedHash.Write(certMsg.marshal())
c.writeRecord(recordTypeHandshake, certMsg.marshal())
@@ -128,7 +133,6 @@ FindCipherSuite:
}
keyAgreement := suite.ka()
-
skx, err := keyAgreement.generateServerKeyExchange(config, clientHello, hello)
if err != nil {
c.sendAlert(alertHandshakeFailure)
@@ -235,18 +239,18 @@ FindCipherSuite:
finishedHash.Write(certVerify.marshal())
}
- preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx)
+ preMasterSecret, err := keyAgreement.processClientKeyExchange(config, ckx, c.vers)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
- keysFromPreMasterSecret10(preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
+ keysFromPreMasterSecret(c.vers, preMasterSecret, clientHello.random, hello.random, suite.macLen, suite.keyLen, suite.ivLen)
clientCipher := suite.cipher(clientKey, clientIV, true /* for reading */ )
- clientHash := suite.mac(clientMAC)
- c.in.prepareCipherSpec(clientCipher, clientHash)
+ clientHash := suite.mac(c.vers, clientMAC)
+ c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
c.readRecord(recordTypeChangeCipherSpec)
if err := c.error(); err != nil {
return err
@@ -283,8 +287,8 @@ FindCipherSuite:
finishedHash.Write(clientFinished.marshal())
serverCipher := suite.cipher(serverKey, serverIV, false /* not for reading */ )
- serverHash := suite.mac(serverMAC)
- c.out.prepareCipherSpec(serverCipher, serverHash)
+ serverHash := suite.mac(c.vers, serverMAC)
+ c.out.prepareCipherSpec(c.vers, serverCipher, serverHash)
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
finished := new(finishedMsg)
diff --git a/libgo/go/crypto/tls/handshake_server_test.go b/libgo/go/crypto/tls/handshake_server_test.go
index b77646e4383..1939f3dba36 100644
--- a/libgo/go/crypto/tls/handshake_server_test.go
+++ b/libgo/go/crypto/tls/handshake_server_test.go
@@ -13,6 +13,8 @@ import (
"io"
"net"
"os"
+ "strconv"
+ "strings"
"testing"
)
@@ -36,6 +38,7 @@ func init() {
testConfig.Certificates[0].Certificate = [][]byte{testCertificate}
testConfig.Certificates[0].PrivateKey = testPrivateKey
testConfig.CipherSuites = []uint16{TLS_RSA_WITH_RC4_128_SHA}
+ testConfig.InsecureSkipVerify = true
}
func testClientHelloFailure(t *testing.T, m handshakeMessage, expected os.Error) {
@@ -62,7 +65,7 @@ func TestSimpleError(t *testing.T) {
testClientHelloFailure(t, &serverHelloDoneMsg{}, alertUnexpectedMessage)
}
-var badProtocolVersions = []uint16{0x0000, 0x0005, 0x0100, 0x0105, 0x0200, 0x0205, 0x0300}
+var badProtocolVersions = []uint16{0x0000, 0x0005, 0x0100, 0x0105, 0x0200, 0x0205}
func TestRejectBadProtocolVersion(t *testing.T) {
for _, v := range badProtocolVersions {
@@ -112,6 +115,7 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config *
go func() {
srv.Write([]byte("hello, world\n"))
srv.Close()
+ s.Close()
}()
defer c.Close()
@@ -121,9 +125,9 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config *
continue
}
bb := make([]byte, len(b))
- _, err := io.ReadFull(c, bb)
+ n, err := io.ReadFull(c, bb)
if err != nil {
- t.Fatalf("%s #%d: %s", name, i, err)
+ t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", name, i, err, n, len(bb), bb[:n], b)
}
if !bytes.Equal(b, bb) {
t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", name, i, bb, b)
@@ -135,6 +139,13 @@ func TestHandshakeServerRC4(t *testing.T) {
testServerScript(t, "RC4", rc4ServerScript, testConfig)
}
+func TestHandshakeServer3DES(t *testing.T) {
+ des3Config := new(Config)
+ *des3Config = *testConfig
+ des3Config.CipherSuites = []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA}
+ testServerScript(t, "3DES", des3ServerScript, des3Config)
+}
+
func TestHandshakeServerAES(t *testing.T) {
aesConfig := new(Config)
*aesConfig = *testConfig
@@ -142,13 +153,30 @@ func TestHandshakeServerAES(t *testing.T) {
testServerScript(t, "AES", aesServerScript, aesConfig)
}
+func TestHandshakeServerSSLv3(t *testing.T) {
+ testServerScript(t, "SSLv3", sslv3ServerScript, testConfig)
+}
+
var serve = flag.Bool("serve", false, "run a TLS server on :10443")
+var testCipherSuites = flag.String("ciphersuites",
+ "0x"+strconv.Itob(int(TLS_RSA_WITH_RC4_128_SHA), 16),
+ "cipher suites to accept in serving mode")
func TestRunServer(t *testing.T) {
if !*serve {
return
}
+ suites := strings.Split(*testCipherSuites, ",")
+ testConfig.CipherSuites = make([]uint16, len(suites))
+ for i := range suites {
+ suite, err := strconv.Btoui64(suites[i], 0)
+ if err != nil {
+ panic(err)
+ }
+ testConfig.CipherSuites[i] = uint16(suite)
+ }
+
l, err := Listen("tcp", ":10443", testConfig)
if err != nil {
t.Fatal(err)
@@ -356,6 +384,179 @@ var rc4ServerScript = [][]byte{
},
}
+var des3ServerScript = [][]byte{
+ {
+ 0x16, 0x03, 0x02, 0x00, 0x7a, 0x01, 0x00, 0x00,
+ 0x76, 0x03, 0x02, 0x4e, 0x84, 0xf4, 0x3c, 0xe4,
+ 0xb8, 0xc7, 0xa0, 0x30, 0x55, 0x2a, 0xbc, 0xb7,
+ 0x04, 0x6b, 0x6f, 0x87, 0x93, 0x96, 0xbd, 0x1a,
+ 0x7a, 0x1e, 0xce, 0xd2, 0x0d, 0xf3, 0x01, 0x03,
+ 0xbe, 0x7b, 0x17, 0x00, 0x00, 0x34, 0x00, 0x33,
+ 0x00, 0x45, 0x00, 0x39, 0x00, 0x88, 0x00, 0x16,
+ 0x00, 0x32, 0x00, 0x44, 0x00, 0x38, 0x00, 0x87,
+ 0x00, 0x13, 0x00, 0x66, 0x00, 0x90, 0x00, 0x91,
+ 0x00, 0x8f, 0x00, 0x8e, 0x00, 0x2f, 0x00, 0x41,
+ 0x00, 0x35, 0x00, 0x84, 0x00, 0x0a, 0x00, 0x05,
+ 0x00, 0x04, 0x00, 0x8c, 0x00, 0x8d, 0x00, 0x8b,
+ 0x00, 0x8a, 0x01, 0x00, 0x00, 0x19, 0x00, 0x09,
+ 0x00, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x0e, 0x00, 0x0c, 0x00, 0x00, 0x09, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74,
+ },
+
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x2a, 0x02, 0x00, 0x00,
+ 0x26, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x16,
+ 0x03, 0x01, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+ 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+ 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+ 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+ 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+ 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+ 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+ 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+ 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+ 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+ 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+ 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+ 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+ 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+ 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+ 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+ 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+ 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+ 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+ 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+ 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+ 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+ 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+ 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+ 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+ 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+ 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+ 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+ 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+ 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+ 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+ 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+ 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+ 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+ 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+ 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+ 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+ 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+ 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+ 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+ 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+ 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+ 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+ 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+ 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+ 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+ 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+ 0xbd, 0xd9, 0x16, 0x03, 0x01, 0x00, 0x04, 0x0e,
+ 0x00, 0x00, 0x00,
+ },
+
+ {
+ 0x16, 0x03, 0x01, 0x00, 0x86, 0x10, 0x00, 0x00,
+ 0x82, 0x00, 0x80, 0xae, 0xcf, 0x4f, 0x70, 0x0e,
+ 0xe5, 0xe7, 0xba, 0xef, 0x0c, 0x66, 0xe9, 0xae,
+ 0x76, 0xf4, 0xe0, 0xbc, 0x1c, 0x22, 0x5b, 0x72,
+ 0xc9, 0x68, 0x63, 0x44, 0xec, 0x72, 0xc2, 0xca,
+ 0xac, 0xc2, 0xf5, 0x5c, 0x28, 0xa1, 0xaf, 0xd0,
+ 0xc2, 0xf7, 0x79, 0x71, 0x32, 0x73, 0x86, 0xea,
+ 0x39, 0xf6, 0x04, 0x26, 0x19, 0x84, 0x1d, 0x7d,
+ 0xa1, 0x21, 0xa6, 0x88, 0xbf, 0x33, 0x5a, 0x64,
+ 0xb0, 0xc2, 0xcc, 0x19, 0x7a, 0x8b, 0x6e, 0x94,
+ 0x9e, 0x2e, 0x20, 0xbe, 0xdc, 0xe9, 0x8e, 0xae,
+ 0x5c, 0x39, 0xc8, 0xcd, 0x0e, 0x19, 0x9a, 0xa2,
+ 0xfc, 0x3f, 0x61, 0x9a, 0xca, 0x58, 0x69, 0x0d,
+ 0xa8, 0x7b, 0xbe, 0x98, 0x8f, 0xb9, 0x9d, 0x8b,
+ 0x68, 0x65, 0xa9, 0x74, 0xcc, 0x8d, 0x0c, 0xb2,
+ 0xc4, 0x0f, 0xdc, 0x56, 0x3e, 0x44, 0x61, 0x0a,
+ 0x26, 0x93, 0x99, 0xef, 0x67, 0xff, 0x6e, 0x73,
+ 0x01, 0xa1, 0x90, 0x14, 0x03, 0x01, 0x00, 0x01,
+ 0x01, 0x16, 0x03, 0x01, 0x00, 0x60, 0x49, 0x36,
+ 0xc8, 0x38, 0x95, 0xe4, 0x5d, 0x8e, 0x80, 0x10,
+ 0x26, 0x9f, 0x87, 0x7d, 0xcd, 0xb9, 0x32, 0x6c,
+ 0xff, 0xaa, 0xe0, 0x07, 0xec, 0x33, 0xe2, 0x36,
+ 0x9d, 0xd5, 0x83, 0x2c, 0xf0, 0x0a, 0xa0, 0xa8,
+ 0x12, 0x9f, 0xca, 0x72, 0xda, 0x70, 0x7d, 0x76,
+ 0x80, 0x12, 0x88, 0x07, 0xaa, 0x27, 0x62, 0x33,
+ 0xab, 0x55, 0xad, 0x3c, 0x2b, 0x54, 0xc4, 0x1c,
+ 0x91, 0xfd, 0x8f, 0x9c, 0xa7, 0x8b, 0x75, 0x10,
+ 0xa8, 0x6e, 0xfc, 0x30, 0x52, 0x8a, 0x61, 0x02,
+ 0xdb, 0x9c, 0x6f, 0xc8, 0x19, 0x93, 0x5d, 0x41,
+ 0x1d, 0x36, 0x68, 0x0b, 0xec, 0x30, 0xae, 0xfb,
+ 0x90, 0xdb, 0x6d, 0x83, 0xb0, 0xf2,
+ },
+
+ {
+ 0x14, 0x03, 0x01, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x01, 0x00, 0x28, 0x07, 0xf3, 0x33, 0x84, 0xb1,
+ 0x5d, 0x2b, 0x52, 0xa4, 0x63, 0x3c, 0x32, 0xe0,
+ 0x0d, 0x22, 0xf5, 0x23, 0xec, 0xf9, 0xa6, 0xec,
+ 0xc0, 0x12, 0x69, 0x88, 0xf6, 0x7d, 0x37, 0xcd,
+ 0xc2, 0x74, 0x2f, 0xef, 0xf6, 0x49, 0x15, 0xea,
+ 0x88, 0x3f, 0x55, 0x17, 0x03, 0x01, 0x00, 0x28,
+ 0xaf, 0x00, 0x84, 0xff, 0x11, 0x01, 0x6d, 0xba,
+ 0x39, 0x5e, 0x45, 0xe1, 0x52, 0x5e, 0xc1, 0xab,
+ 0xde, 0x5b, 0x16, 0xdd, 0xd6, 0x61, 0x57, 0xb8,
+ 0x66, 0x8b, 0x2d, 0xde, 0x51, 0x41, 0xc5, 0x09,
+ 0xb3, 0x6a, 0x06, 0x43, 0xb4, 0x73, 0x5c, 0xf1,
+ 0x15, 0x03, 0x01, 0x00, 0x18, 0xbd, 0x65, 0xb2,
+ 0xce, 0x77, 0x2e, 0xf9, 0x11, 0xc4, 0x80, 0x43,
+ 0x5a, 0x73, 0x8b, 0x73, 0xdd, 0xf0, 0x54, 0x44,
+ 0x7c, 0x56, 0x19, 0x54, 0xda,
+ },
+}
+
var aesServerScript = [][]byte{
{
0x16, 0x03, 0x02, 0x00, 0x7f, 0x01, 0x00, 0x00,
@@ -515,3 +716,165 @@ var aesServerScript = [][]byte{
0xcd, 0x84, 0xf0,
},
}
+
+var sslv3ServerScript = [][]byte{
+ {
+ 0x16, 0x03, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00,
+ 0x3d, 0x03, 0x00, 0x4e, 0x70, 0xe2, 0x18, 0x86,
+ 0xd6, 0xc6, 0x6f, 0xf3, 0xc8, 0xf4, 0x02, 0xd6,
+ 0x4d, 0xee, 0x17, 0x32, 0x4b, 0xd2, 0x78, 0xd8,
+ 0xa1, 0x03, 0x5d, 0x68, 0x82, 0x89, 0xbe, 0xfd,
+ 0x12, 0xb9, 0x06, 0x00, 0x00, 0x16, 0x00, 0x33,
+ 0x00, 0x39, 0x00, 0x16, 0x00, 0x32, 0x00, 0x38,
+ 0x00, 0x13, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a,
+ 0x00, 0x05, 0x00, 0x04, 0x01, 0x00,
+ },
+
+ {
+ 0x16, 0x03, 0x00, 0x00, 0x2a, 0x02, 0x00, 0x00,
+ 0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x16,
+ 0x03, 0x00, 0x02, 0xbe, 0x0b, 0x00, 0x02, 0xba,
+ 0x00, 0x02, 0xb7, 0x00, 0x02, 0xb4, 0x30, 0x82,
+ 0x02, 0xb0, 0x30, 0x82, 0x02, 0x19, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x85, 0xb0,
+ 0xbb, 0xa4, 0x8a, 0x7f, 0xb8, 0xca, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x45, 0x31,
+ 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53,
+ 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65,
+ 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64,
+ 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79,
+ 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d,
+ 0x31, 0x30, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39,
+ 0x30, 0x39, 0x33, 0x38, 0x5a, 0x17, 0x0d, 0x31,
+ 0x31, 0x30, 0x34, 0x32, 0x34, 0x30, 0x39, 0x30,
+ 0x39, 0x33, 0x38, 0x5a, 0x30, 0x45, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x53, 0x6f,
+ 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
+ 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
+ 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20,
+ 0x4c, 0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d,
+ 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
+ 0xbb, 0x79, 0xd6, 0xf5, 0x17, 0xb5, 0xe5, 0xbf,
+ 0x46, 0x10, 0xd0, 0xdc, 0x69, 0xbe, 0xe6, 0x2b,
+ 0x07, 0x43, 0x5a, 0xd0, 0x03, 0x2d, 0x8a, 0x7a,
+ 0x43, 0x85, 0xb7, 0x14, 0x52, 0xe7, 0xa5, 0x65,
+ 0x4c, 0x2c, 0x78, 0xb8, 0x23, 0x8c, 0xb5, 0xb4,
+ 0x82, 0xe5, 0xde, 0x1f, 0x95, 0x3b, 0x7e, 0x62,
+ 0xa5, 0x2c, 0xa5, 0x33, 0xd6, 0xfe, 0x12, 0x5c,
+ 0x7a, 0x56, 0xfc, 0xf5, 0x06, 0xbf, 0xfa, 0x58,
+ 0x7b, 0x26, 0x3f, 0xb5, 0xcd, 0x04, 0xd3, 0xd0,
+ 0xc9, 0x21, 0x96, 0x4a, 0xc7, 0xf4, 0x54, 0x9f,
+ 0x5a, 0xbf, 0xef, 0x42, 0x71, 0x00, 0xfe, 0x18,
+ 0x99, 0x07, 0x7f, 0x7e, 0x88, 0x7d, 0x7d, 0xf1,
+ 0x04, 0x39, 0xc4, 0xa2, 0x2e, 0xdb, 0x51, 0xc9,
+ 0x7c, 0xe3, 0xc0, 0x4c, 0x3b, 0x32, 0x66, 0x01,
+ 0xcf, 0xaf, 0xb1, 0x1d, 0xb8, 0x71, 0x9a, 0x1d,
+ 0xdb, 0xdb, 0x89, 0x6b, 0xae, 0xda, 0x2d, 0x79,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xa7,
+ 0x30, 0x81, 0xa4, 0x30, 0x1d, 0x06, 0x03, 0x55,
+ 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xb1, 0xad,
+ 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb, 0x69,
+ 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e, 0x18,
+ 0x88, 0x39, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1d,
+ 0x23, 0x04, 0x6e, 0x30, 0x6c, 0x80, 0x14, 0xb1,
+ 0xad, 0xe2, 0x85, 0x5a, 0xcf, 0xcb, 0x28, 0xdb,
+ 0x69, 0xce, 0x23, 0x69, 0xde, 0xd3, 0x26, 0x8e,
+ 0x18, 0x88, 0x39, 0xa1, 0x49, 0xa4, 0x47, 0x30,
+ 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
+ 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x18, 0x49, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
+ 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50,
+ 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x82, 0x09,
+ 0x00, 0x85, 0xb0, 0xbb, 0xa4, 0x8a, 0x7f, 0xb8,
+ 0xca, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x81,
+ 0x81, 0x00, 0x08, 0x6c, 0x45, 0x24, 0xc7, 0x6b,
+ 0xb1, 0x59, 0xab, 0x0c, 0x52, 0xcc, 0xf2, 0xb0,
+ 0x14, 0xd7, 0x87, 0x9d, 0x7a, 0x64, 0x75, 0xb5,
+ 0x5a, 0x95, 0x66, 0xe4, 0xc5, 0x2b, 0x8e, 0xae,
+ 0x12, 0x66, 0x1f, 0xeb, 0x4f, 0x38, 0xb3, 0x6e,
+ 0x60, 0xd3, 0x92, 0xfd, 0xf7, 0x41, 0x08, 0xb5,
+ 0x25, 0x13, 0xb1, 0x18, 0x7a, 0x24, 0xfb, 0x30,
+ 0x1d, 0xba, 0xed, 0x98, 0xb9, 0x17, 0xec, 0xe7,
+ 0xd7, 0x31, 0x59, 0xdb, 0x95, 0xd3, 0x1d, 0x78,
+ 0xea, 0x50, 0x56, 0x5c, 0xd5, 0x82, 0x5a, 0x2d,
+ 0x5a, 0x5f, 0x33, 0xc4, 0xb6, 0xd8, 0xc9, 0x75,
+ 0x90, 0x96, 0x8c, 0x0f, 0x52, 0x98, 0xb5, 0xcd,
+ 0x98, 0x1f, 0x89, 0x20, 0x5f, 0xf2, 0xa0, 0x1c,
+ 0xa3, 0x1b, 0x96, 0x94, 0xdd, 0xa9, 0xfd, 0x57,
+ 0xe9, 0x70, 0xe8, 0x26, 0x6d, 0x71, 0x99, 0x9b,
+ 0x26, 0x6e, 0x38, 0x50, 0x29, 0x6c, 0x90, 0xa7,
+ 0xbd, 0xd9, 0x16, 0x03, 0x00, 0x00, 0x04, 0x0e,
+ 0x00, 0x00, 0x00,
+ },
+
+ {
+ 0x16, 0x03, 0x00, 0x00, 0x84, 0x10, 0x00, 0x00,
+ 0x80, 0x74, 0x0e, 0x3a, 0xcf, 0xba, 0x9f, 0x1a,
+ 0x9b, 0xb2, 0xa4, 0xc7, 0x5d, 0xf3, 0x0c, 0x80,
+ 0x06, 0x80, 0xf3, 0x57, 0xb2, 0xd9, 0x36, 0x24,
+ 0x6a, 0x06, 0x13, 0x40, 0xf9, 0x7c, 0xb9, 0x3e,
+ 0x4b, 0x68, 0x4f, 0x21, 0x90, 0x2d, 0xbd, 0xca,
+ 0xd4, 0x83, 0xf0, 0x7a, 0xeb, 0x7a, 0x74, 0x1b,
+ 0xcd, 0xfe, 0x69, 0xef, 0xc0, 0x86, 0xa0, 0x24,
+ 0x31, 0x65, 0x40, 0xd2, 0xdd, 0x6f, 0xb9, 0xd7,
+ 0x8d, 0xc1, 0x69, 0x60, 0x44, 0x7a, 0x75, 0xfb,
+ 0x42, 0x6a, 0x0f, 0x66, 0x45, 0x10, 0x73, 0xee,
+ 0x87, 0x28, 0x37, 0x83, 0x86, 0xd8, 0x5a, 0xc8,
+ 0x60, 0x87, 0xda, 0x33, 0x87, 0xaf, 0x34, 0x8b,
+ 0xf5, 0x61, 0x63, 0x7a, 0x5c, 0x60, 0x26, 0xb9,
+ 0xdb, 0xa1, 0xb7, 0xe3, 0x60, 0x38, 0x94, 0x5c,
+ 0x83, 0x23, 0xd6, 0x8d, 0xc2, 0x14, 0x4a, 0x0f,
+ 0x0e, 0x4f, 0xf9, 0x4e, 0x7b, 0x15, 0xcd, 0x18,
+ 0x04, 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16,
+ 0x03, 0x00, 0x00, 0x3c, 0xbd, 0xbc, 0xec, 0xdc,
+ 0x79, 0xb1, 0xae, 0x16, 0xc9, 0x26, 0x9a, 0xc0,
+ 0xc0, 0x2c, 0x33, 0x36, 0x13, 0x91, 0x58, 0x5d,
+ 0x7d, 0xee, 0x4e, 0xd8, 0x7e, 0xac, 0x88, 0x87,
+ 0x0a, 0x75, 0x66, 0xb1, 0x44, 0x79, 0x2f, 0x42,
+ 0xe8, 0x92, 0x74, 0x4c, 0xab, 0x36, 0xc8, 0x17,
+ 0x5f, 0x02, 0x8a, 0x20, 0x53, 0xe9, 0x1d, 0xb4,
+ 0xfe, 0x5c, 0x2b, 0xd9, 0x0a, 0xfb, 0xc6, 0x63,
+ },
+
+ {
+ 0x14, 0x03, 0x00, 0x00, 0x01, 0x01, 0x16, 0x03,
+ 0x00, 0x00, 0x3c, 0xaa, 0xa1, 0x98, 0xc4, 0x6b,
+ 0x5a, 0x16, 0x3f, 0x5f, 0xa4, 0x96, 0x3e, 0x78,
+ 0xe4, 0x6f, 0x49, 0x05, 0x47, 0xc4, 0x05, 0x60,
+ 0xeb, 0x0b, 0x45, 0xe3, 0xbc, 0x50, 0x11, 0x24,
+ 0x5f, 0x01, 0xd7, 0xb8, 0x8f, 0x60, 0x63, 0x66,
+ 0xbd, 0x3e, 0xd9, 0xa8, 0x80, 0x43, 0x9f, 0x0b,
+ 0x51, 0x61, 0xed, 0x13, 0xc6, 0x21, 0xd0, 0xfe,
+ 0xbc, 0x17, 0x3c, 0x36, 0xb0, 0x82, 0x7f, 0x17,
+ 0x03, 0x00, 0x00, 0x21, 0xee, 0x44, 0xf3, 0xa6,
+ 0x88, 0x9d, 0x78, 0x44, 0xde, 0xdf, 0xeb, 0xc5,
+ 0xad, 0xc4, 0xcc, 0x56, 0x5c, 0x54, 0x96, 0x52,
+ 0x3f, 0xd9, 0x40, 0x6e, 0x79, 0xd8, 0x58, 0x78,
+ 0x4f, 0x5a, 0xe9, 0x06, 0xef, 0x15, 0x03, 0x00,
+ 0x00, 0x16, 0xd3, 0xc2, 0x52, 0x99, 0x2a, 0x84,
+ 0xc4, 0x52, 0x5f, 0x3b, 0x19, 0xe7, 0xfc, 0x65,
+ 0xaf, 0xd3, 0xb7, 0xa3, 0xcc, 0x4a, 0x1d, 0x2e,
+ },
+}
diff --git a/libgo/go/crypto/tls/key_agreement.go b/libgo/go/crypto/tls/key_agreement.go
index a40d18fd9cd..e347528b581 100644
--- a/libgo/go/crypto/tls/key_agreement.go
+++ b/libgo/go/crypto/tls/key_agreement.go
@@ -24,7 +24,7 @@ func (ka rsaKeyAgreement) generateServerKeyExchange(config *Config, clientHello
return nil, nil
}
-func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) {
+func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, os.Error) {
preMasterSecret := make([]byte, 48)
_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
if err != nil {
@@ -34,11 +34,15 @@ func (ka rsaKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKe
if len(ckx.ciphertext) < 2 {
return nil, os.NewError("bad ClientKeyExchange")
}
- ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
- if ciphertextLen != len(ckx.ciphertext)-2 {
- return nil, os.NewError("bad ClientKeyExchange")
+
+ ciphertext := ckx.ciphertext
+ if version != versionSSL30 {
+ ciphertextLen := int(ckx.ciphertext[0])<<8 | int(ckx.ciphertext[1])
+ if ciphertextLen != len(ckx.ciphertext)-2 {
+ return nil, os.NewError("bad ClientKeyExchange")
+ }
+ ciphertext = ckx.ciphertext[2:]
}
- ciphertext := ckx.ciphertext[2:]
err = rsa.DecryptPKCS1v15SessionKey(config.rand(), config.Certificates[0].PrivateKey, ciphertext, preMasterSecret)
if err != nil {
@@ -159,7 +163,7 @@ Curve:
return skx, nil
}
-func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg) ([]byte, os.Error) {
+func (ka *ecdheRSAKeyAgreement) processClientKeyExchange(config *Config, ckx *clientKeyExchangeMsg, version uint16) ([]byte, os.Error) {
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
return nil, os.NewError("bad ClientKeyExchange")
}
diff --git a/libgo/go/crypto/tls/prf.go b/libgo/go/crypto/tls/prf.go
index 478cf65f91c..2d58dc520dc 100644
--- a/libgo/go/crypto/tls/prf.go
+++ b/libgo/go/crypto/tls/prf.go
@@ -63,6 +63,39 @@ func pRF10(result, secret, label, seed []byte) {
}
}
+// pRF30 implements the SSL 3.0 pseudo-random function, as defined in
+// www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt section 6.
+func pRF30(result, secret, label, seed []byte) {
+ hashSHA1 := sha1.New()
+ hashMD5 := md5.New()
+
+ done := 0
+ i := 0
+ // RFC5246 section 6.3 says that the largest PRF output needed is 128
+ // bytes. Since no more ciphersuites will be added to SSLv3, this will
+ // remain true. Each iteration gives us 16 bytes so 10 iterations will
+ // be sufficient.
+ var b [11]byte
+ for done < len(result) {
+ for j := 0; j <= i; j++ {
+ b[j] = 'A' + byte(i)
+ }
+
+ hashSHA1.Reset()
+ hashSHA1.Write(b[:i+1])
+ hashSHA1.Write(secret)
+ hashSHA1.Write(seed)
+ digest := hashSHA1.Sum()
+
+ hashMD5.Reset()
+ hashMD5.Write(secret)
+ hashMD5.Write(digest)
+
+ done += copy(result[done:], hashMD5.Sum())
+ i++
+ }
+}
+
const (
tlsRandomLength = 32 // Length of a random nonce in TLS 1.1.
masterSecretLength = 48 // Length of a master secret in TLS 1.1.
@@ -77,19 +110,24 @@ var serverFinishedLabel = []byte("server finished")
// keysFromPreMasterSecret generates the connection keys from the pre master
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
// RFC 2246, section 6.3.
-func keysFromPreMasterSecret10(preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+func keysFromPreMasterSecret(version uint16, preMasterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (masterSecret, clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
+ prf := pRF10
+ if version == versionSSL30 {
+ prf = pRF30
+ }
+
var seed [tlsRandomLength * 2]byte
copy(seed[0:len(clientRandom)], clientRandom)
copy(seed[len(clientRandom):], serverRandom)
masterSecret = make([]byte, masterSecretLength)
- pRF10(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
+ prf(masterSecret, preMasterSecret, masterSecretLabel, seed[0:])
copy(seed[0:len(clientRandom)], serverRandom)
copy(seed[len(serverRandom):], clientRandom)
n := 2*macLen + 2*keyLen + 2*ivLen
keyMaterial := make([]byte, n)
- pRF10(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
+ prf(keyMaterial, masterSecret, keyExpansionLabel, seed[0:])
clientMAC = keyMaterial[:macLen]
keyMaterial = keyMaterial[macLen:]
serverMAC = keyMaterial[:macLen]
@@ -104,6 +142,10 @@ func keysFromPreMasterSecret10(preMasterSecret, clientRandom, serverRandom []byt
return
}
+func newFinishedHash(version uint16) finishedHash {
+ return finishedHash{md5.New(), sha1.New(), md5.New(), sha1.New(), version}
+}
+
// A finishedHash calculates the hash of a set of handshake messages suitable
// for including in a Finished message.
type finishedHash struct {
@@ -111,10 +153,7 @@ type finishedHash struct {
clientSHA1 hash.Hash
serverMD5 hash.Hash
serverSHA1 hash.Hash
-}
-
-func newFinishedHash() finishedHash {
- return finishedHash{md5.New(), sha1.New(), md5.New(), sha1.New()}
+ version uint16
}
func (h finishedHash) Write(msg []byte) (n int, err os.Error) {
@@ -125,9 +164,10 @@ func (h finishedHash) Write(msg []byte) (n int, err os.Error) {
return len(msg), nil
}
-// finishedSum calculates the contents of the verify_data member of a Finished
-// message given the MD5 and SHA1 hashes of a set of handshake messages.
-func finishedSum(md5, sha1, label, masterSecret []byte) []byte {
+// finishedSum10 calculates the contents of the verify_data member of a TLSv1
+// Finished message given the MD5 and SHA1 hashes of a set of handshake
+// messages.
+func finishedSum10(md5, sha1, label, masterSecret []byte) []byte {
seed := make([]byte, len(md5)+len(sha1))
copy(seed, md5)
copy(seed[len(md5):], sha1)
@@ -136,18 +176,61 @@ func finishedSum(md5, sha1, label, masterSecret []byte) []byte {
return out
}
+// finishedSum30 calculates the contents of the verify_data member of a SSLv3
+// Finished message given the MD5 and SHA1 hashes of a set of handshake
+// messages.
+func finishedSum30(md5, sha1 hash.Hash, masterSecret []byte, magic [4]byte) []byte {
+ md5.Write(magic[:])
+ md5.Write(masterSecret)
+ md5.Write(ssl30Pad1[:])
+ md5Digest := md5.Sum()
+
+ md5.Reset()
+ md5.Write(masterSecret)
+ md5.Write(ssl30Pad2[:])
+ md5.Write(md5Digest)
+ md5Digest = md5.Sum()
+
+ sha1.Write(magic[:])
+ sha1.Write(masterSecret)
+ sha1.Write(ssl30Pad1[:40])
+ sha1Digest := sha1.Sum()
+
+ sha1.Reset()
+ sha1.Write(masterSecret)
+ sha1.Write(ssl30Pad2[:40])
+ sha1.Write(sha1Digest)
+ sha1Digest = sha1.Sum()
+
+ ret := make([]byte, len(md5Digest)+len(sha1Digest))
+ copy(ret, md5Digest)
+ copy(ret[len(md5Digest):], sha1Digest)
+ return ret
+}
+
+var ssl3ClientFinishedMagic = [4]byte{0x43, 0x4c, 0x4e, 0x54}
+var ssl3ServerFinishedMagic = [4]byte{0x53, 0x52, 0x56, 0x52}
+
// clientSum returns the contents of the verify_data member of a client's
// Finished message.
func (h finishedHash) clientSum(masterSecret []byte) []byte {
+ if h.version == versionSSL30 {
+ return finishedSum30(h.clientMD5, h.clientSHA1, masterSecret, ssl3ClientFinishedMagic)
+ }
+
md5 := h.clientMD5.Sum()
sha1 := h.clientSHA1.Sum()
- return finishedSum(md5, sha1, clientFinishedLabel, masterSecret)
+ return finishedSum10(md5, sha1, clientFinishedLabel, masterSecret)
}
// serverSum returns the contents of the verify_data member of a server's
// Finished message.
func (h finishedHash) serverSum(masterSecret []byte) []byte {
+ if h.version == versionSSL30 {
+ return finishedSum30(h.serverMD5, h.serverSHA1, masterSecret, ssl3ServerFinishedMagic)
+ }
+
md5 := h.serverMD5.Sum()
sha1 := h.serverSHA1.Sum()
- return finishedSum(md5, sha1, serverFinishedLabel, masterSecret)
+ return finishedSum10(md5, sha1, serverFinishedLabel, masterSecret)
}
diff --git a/libgo/go/crypto/tls/prf_test.go b/libgo/go/crypto/tls/prf_test.go
index f8c4acb9d28..a32392cef79 100644
--- a/libgo/go/crypto/tls/prf_test.go
+++ b/libgo/go/crypto/tls/prf_test.go
@@ -34,6 +34,7 @@ func TestSplitPreMasterSecret(t *testing.T) {
}
type testKeysFromTest struct {
+ version uint16
preMasterSecret string
clientRandom, serverRandom string
masterSecret string
@@ -47,7 +48,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
in, _ := hex.DecodeString(test.preMasterSecret)
clientRandom, _ := hex.DecodeString(test.clientRandom)
serverRandom, _ := hex.DecodeString(test.serverRandom)
- master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret10(in, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
+ master, clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromPreMasterSecret(test.version, in, clientRandom, serverRandom, test.macLen, test.keyLen, 0)
masterString := hex.EncodeToString(master)
clientMACString := hex.EncodeToString(clientMAC)
serverMACString := hex.EncodeToString(serverMAC)
@@ -58,7 +59,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
serverMACString != test.serverMAC ||
clientKeyString != test.clientKey ||
serverKeyString != test.serverKey {
- t.Errorf("#%d: got: (%s, %s, %s, %s, %s) want: (%s, %s, %s, %s %s)", i, masterString, clientMACString, serverMACString, clientKeyString, serverMACString, test.masterSecret, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
+ t.Errorf("#%d: got: (%s, %s, %s, %s, %s) want: (%s, %s, %s, %s, %s)", i, masterString, clientMACString, serverMACString, clientKeyString, serverKeyString, test.masterSecret, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey)
}
}
}
@@ -66,6 +67,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
// These test vectors were generated from GnuTLS using `gnutls-cli --insecure -d 9 `
var testKeysFromTests = []testKeysFromTest{
{
+ versionTLS10,
"0302cac83ad4b1db3b9ab49ad05957de2a504a634a386fc600889321e1a971f57479466830ac3e6f468e87f5385fa0c5",
"4ae66303755184a3917fcb44880605fcc53baa01912b22ed94473fc69cebd558",
"4ae663020ec16e6bb5130be918cfcafd4d765979a3136a5d50c593446e4e44db",
@@ -78,6 +80,7 @@ var testKeysFromTests = []testKeysFromTest{
16,
},
{
+ versionTLS10,
"03023f7527316bc12cbcd69e4b9e8275d62c028f27e65c745cfcddc7ce01bd3570a111378b63848127f1c36e5f9e4890",
"4ae66364b5ea56b20ce4e25555aed2d7e67f42788dd03f3fee4adae0459ab106",
"4ae66363ab815cbf6a248b87d6b556184e945e9b97fbdf247858b0bdafacfa1c",
@@ -90,6 +93,7 @@ var testKeysFromTests = []testKeysFromTest{
16,
},
{
+ versionTLS10,
"832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1",
"4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e",
"4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e",
@@ -101,4 +105,17 @@ var testKeysFromTests = []testKeysFromTest{
20,
16,
},
+ {
+ versionSSL30,
+ "832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1",
+ "4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e",
+ "4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e",
+ "a614863e56299dcffeea2938f22c2ba023768dbe4b3f6877bc9c346c6ae529b51d9cb87ff9695ea4d01f2205584405b2",
+ "2c450d5b6f6e2013ac6bea6a0b32200d4e1ffb94",
+ "7a7a7438769536f2fb1ae49a61f0703b79b2dc53",
+ "f8f6b26c10f12855c9aafb1e0e839ccf",
+ "2b9d4b4a60cb7f396780ebff50650419",
+ 20,
+ 16,
+ },
}
diff --git a/libgo/go/crypto/tls/root_darwin.go b/libgo/go/crypto/tls/root_darwin.go
new file mode 100644
index 00000000000..15122416bd1
--- /dev/null
+++ b/libgo/go/crypto/tls/root_darwin.go
@@ -0,0 +1,95 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+/*
+// Note: We disable -Werror here because the code in this file uses a deprecated API to stay
+// compatible with both Mac OS X 10.6 and 10.7. Using a deprecated function on Darwin generates
+// a warning.
+#cgo CFLAGS: -Wno-error
+#cgo LDFLAGS: -framework CoreFoundation -framework Security
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/Security.h>
+
+// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
+//
+// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
+// certificates of the system. On failure, the function returns -1.
+//
+// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
+// we've consumed its content.
+int FetchPEMRoots(CFDataRef *pemRoots) {
+ if (pemRoots == NULL) {
+ return -1;
+ }
+
+ CFArrayRef certs = NULL;
+ OSStatus err = SecTrustCopyAnchorCertificates(&certs);
+ if (err != noErr) {
+ return -1;
+ }
+
+ CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
+ int i, ncerts = CFArrayGetCount(certs);
+ for (i = 0; i < ncerts; i++) {
+ CFDataRef data = NULL;
+ SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
+ if (cert == NULL) {
+ continue;
+ }
+
+ // SecKeychainImportExport is deprecated in >= OS X 10.7, and has been replaced by
+ // SecItemExport. If we're built on a host with a Lion SDK, this code gets conditionally
+ // included in the output, also for binaries meant for 10.6.
+ //
+ // To make sure that we run on both Mac OS X 10.6 and 10.7 we use weak linking
+ // and check whether SecItemExport is available before we attempt to call it. On
+ // 10.6, this won't be the case, and we'll fall back to calling SecKeychainItemExport.
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+ if (SecItemExport) {
+ err = SecItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
+ if (err != noErr) {
+ continue;
+ }
+ } else
+#endif
+ if (data == NULL) {
+ err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
+ if (err != noErr) {
+ continue;
+ }
+ }
+
+ if (data != NULL) {
+ CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
+ CFRelease(data);
+ }
+ }
+
+ CFRelease(certs);
+
+ *pemRoots = combinedData;
+ return 0;
+}
+*/
+import "C"
+import (
+ "crypto/x509"
+ "unsafe"
+)
+
+func initDefaultRoots() {
+ roots := x509.NewCertPool()
+
+ var data C.CFDataRef = nil
+ err := C.FetchPEMRoots(&data)
+ if err != -1 {
+ defer C.CFRelease(C.CFTypeRef(data))
+ buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
+ roots.AppendCertsFromPEM(buf)
+ }
+
+ varDefaultRoots = roots
+}
diff --git a/libgo/go/crypto/tls/root_stub.go b/libgo/go/crypto/tls/root_stub.go
new file mode 100644
index 00000000000..1903eed8138
--- /dev/null
+++ b/libgo/go/crypto/tls/root_stub.go
@@ -0,0 +1,8 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+func initDefaultRoots() {
+}
diff --git a/libgo/go/crypto/tls/root_test.go b/libgo/go/crypto/tls/root_test.go
new file mode 100644
index 00000000000..95a89d843c8
--- /dev/null
+++ b/libgo/go/crypto/tls/root_test.go
@@ -0,0 +1,36 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "testing"
+)
+
+var tlsServers = []string{
+ "google.com:443",
+ "github.com:443",
+ "twitter.com:443",
+}
+
+func TestOSCertBundles(t *testing.T) {
+ defaultRoots()
+
+ if testing.Short() {
+ t.Logf("skipping certificate tests in short mode")
+ return
+ }
+
+ for _, addr := range tlsServers {
+ conn, err := Dial("tcp", addr, nil)
+ if err != nil {
+ t.Errorf("unable to verify %v: %v", addr, err)
+ continue
+ }
+ err = conn.Close()
+ if err != nil {
+ t.Error(err)
+ }
+ }
+}
diff --git a/libgo/go/crypto/tls/root_unix.go b/libgo/go/crypto/tls/root_unix.go
new file mode 100644
index 00000000000..095beec104a
--- /dev/null
+++ b/libgo/go/crypto/tls/root_unix.go
@@ -0,0 +1,29 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "crypto/x509"
+ "io/ioutil"
+)
+
+// Possible certificate files; stop after finding one.
+var certFiles = []string{
+ "/etc/ssl/certs/ca-certificates.crt", // Linux etc
+ "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL
+ "/etc/ssl/ca-bundle.pem", // OpenSUSE
+}
+
+func initDefaultRoots() {
+ roots := x509.NewCertPool()
+ for _, file := range certFiles {
+ data, err := ioutil.ReadFile(file)
+ if err == nil {
+ roots.AppendCertsFromPEM(data)
+ break
+ }
+ }
+ varDefaultRoots = roots
+}
diff --git a/libgo/go/crypto/tls/root_windows.go b/libgo/go/crypto/tls/root_windows.go
new file mode 100644
index 00000000000..b8e27a9a5d2
--- /dev/null
+++ b/libgo/go/crypto/tls/root_windows.go
@@ -0,0 +1,54 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tls
+
+import (
+ "crypto/x509"
+ "reflect"
+ "syscall"
+ "unsafe"
+)
+
+func loadStore(roots *x509.CertPool, name string) {
+ store, errno := syscall.CertOpenSystemStore(syscall.InvalidHandle, syscall.StringToUTF16Ptr(name))
+ if errno != 0 {
+ return
+ }
+
+ var cert *syscall.CertContext
+ for {
+ cert = syscall.CertEnumCertificatesInStore(store, cert)
+ if cert == nil {
+ break
+ }
+
+ var asn1Slice []byte
+ hdrp := (*reflect.SliceHeader)(unsafe.Pointer(&asn1Slice))
+ hdrp.Data = cert.EncodedCert
+ hdrp.Len = int(cert.Length)
+ hdrp.Cap = int(cert.Length)
+
+ buf := make([]byte, len(asn1Slice))
+ copy(buf, asn1Slice)
+
+ if cert, err := x509.ParseCertificate(buf); err == nil {
+ roots.AddCert(cert)
+ }
+ }
+
+ syscall.CertCloseStore(store, 0)
+}
+
+func initDefaultRoots() {
+ roots := x509.NewCertPool()
+
+ // Roots
+ loadStore(roots, "ROOT")
+
+ // Intermediates
+ loadStore(roots, "CA")
+
+ varDefaultRoots = roots
+}
diff --git a/libgo/go/crypto/x509/cert_pool.go b/libgo/go/crypto/x509/cert_pool.go
index 16cd92efc3b..b9196ed46ed 100644
--- a/libgo/go/crypto/x509/cert_pool.go
+++ b/libgo/go/crypto/x509/cert_pool.go
@@ -5,9 +5,7 @@
package x509
import (
- "crypto/x509/pkix"
"encoding/pem"
- "strings"
)
// Roots is a set of certificates.
@@ -26,10 +24,6 @@ func NewCertPool() *CertPool {
}
}
-func nameToKey(name *pkix.Name) string {
- return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
-}
-
// findVerifiedParents attempts to find certificates in s which have signed the
// given certificate. If no such certificate can be found or the signature
// doesn't match, it returns nil.
@@ -40,7 +34,7 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
}
if len(candidates) == 0 {
- candidates = s.byName[nameToKey(&cert.Issuer)]
+ candidates = s.byName[string(cert.RawIssuer)]
}
for _, c := range candidates {
@@ -72,7 +66,7 @@ func (s *CertPool) AddCert(cert *Certificate) {
keyId := string(cert.SubjectKeyId)
s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
}
- name := nameToKey(&cert.Subject)
+ name := string(cert.RawSubject)
s.byName[name] = append(s.byName[name], n)
}
diff --git a/libgo/go/crypto/x509/pkcs1.go b/libgo/go/crypto/x509/pkcs1.go
new file mode 100644
index 00000000000..42afcb4dad6
--- /dev/null
+++ b/libgo/go/crypto/x509/pkcs1.go
@@ -0,0 +1,122 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package x509
+
+import (
+ "asn1"
+ "big"
+ "os"
+ "crypto/rsa"
+)
+
+// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
+type pkcs1PrivateKey struct {
+ Version int
+ N *big.Int
+ E int
+ D *big.Int
+ P *big.Int
+ Q *big.Int
+ // We ignore these values, if present, because rsa will calculate them.
+ Dp *big.Int `asn1:"optional"`
+ Dq *big.Int `asn1:"optional"`
+ Qinv *big.Int `asn1:"optional"`
+
+ AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional"`
+}
+
+type pkcs1AdditionalRSAPrime struct {
+ Prime *big.Int
+
+ // We ignore these values because rsa will calculate them.
+ Exp *big.Int
+ Coeff *big.Int
+}
+
+// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
+func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
+ var priv pkcs1PrivateKey
+ rest, err := asn1.Unmarshal(der, &priv)
+ if len(rest) > 0 {
+ err = asn1.SyntaxError{"trailing data"}
+ return
+ }
+ if err != nil {
+ return
+ }
+
+ if priv.Version > 1 {
+ return nil, os.NewError("x509: unsupported private key version")
+ }
+
+ if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
+ return nil, os.NewError("private key contains zero or negative value")
+ }
+
+ key = new(rsa.PrivateKey)
+ key.PublicKey = rsa.PublicKey{
+ E: priv.E,
+ N: priv.N,
+ }
+
+ key.D = priv.D
+ key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
+ key.Primes[0] = priv.P
+ key.Primes[1] = priv.Q
+ for i, a := range priv.AdditionalPrimes {
+ if a.Prime.Sign() <= 0 {
+ return nil, os.NewError("private key contains zero or negative prime")
+ }
+ key.Primes[i+2] = a.Prime
+ // We ignore the other two values because rsa will calculate
+ // them as needed.
+ }
+
+ err = key.Validate()
+ if err != nil {
+ return nil, err
+ }
+ key.Precompute()
+
+ return
+}
+
+// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
+func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
+ key.Precompute()
+
+ version := 0
+ if len(key.Primes) > 2 {
+ version = 1
+ }
+
+ priv := pkcs1PrivateKey{
+ Version: version,
+ N: key.N,
+ E: key.PublicKey.E,
+ D: key.D,
+ P: key.Primes[0],
+ Q: key.Primes[1],
+ Dp: key.Precomputed.Dp,
+ Dq: key.Precomputed.Dq,
+ Qinv: key.Precomputed.Qinv,
+ }
+
+ priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
+ for i, values := range key.Precomputed.CRTValues {
+ priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
+ priv.AdditionalPrimes[i].Exp = values.Exp
+ priv.AdditionalPrimes[i].Coeff = values.Coeff
+ }
+
+ b, _ := asn1.Marshal(priv)
+ return b
+}
+
+// rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
+type rsaPublicKey struct {
+ N *big.Int
+ E int
+}
diff --git a/libgo/go/crypto/x509/pkix/pkix.go b/libgo/go/crypto/x509/pkix/pkix.go
index 266fd557a52..332a3946212 100644
--- a/libgo/go/crypto/x509/pkix/pkix.go
+++ b/libgo/go/crypto/x509/pkix/pkix.go
@@ -43,6 +43,8 @@ type Name struct {
Locality, Province []string
StreetAddress, PostalCode []string
SerialNumber, CommonName string
+
+ Names []AttributeTypeAndValue
}
func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
@@ -51,6 +53,7 @@ func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
continue
}
atv := rdn[0]
+ n.Names = append(n.Names, atv)
value, ok := atv.Value.(string)
if !ok {
continue
diff --git a/libgo/go/crypto/x509/verify_test.go b/libgo/go/crypto/x509/verify_test.go
index 111f60eb114..eaa8169b0da 100644
--- a/libgo/go/crypto/x509/verify_test.go
+++ b/libgo/go/crypto/x509/verify_test.go
@@ -5,6 +5,7 @@
package x509
import (
+ "crypto/x509/pkix"
"encoding/pem"
"os"
"strings"
@@ -31,7 +32,7 @@ var verifyTests = []verifyTest{
dnsName: "www.google.com",
expectedChains: [][]string{
- []string{"Google", "Thawte", "VeriSign"},
+ {"Google", "Thawte", "VeriSign"},
},
},
{
@@ -68,7 +69,7 @@ var verifyTests = []verifyTest{
dnsName: "www.google.com",
expectedChains: [][]string{
- []string{"Google", "Thawte", "VeriSign"},
+ {"Google", "Thawte", "VeriSign"},
},
},
{
@@ -78,7 +79,7 @@ var verifyTests = []verifyTest{
currentTime: 1302726541,
expectedChains: [][]string{
- []string{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
+ {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
},
},
{
@@ -88,8 +89,8 @@ var verifyTests = []verifyTest{
currentTime: 1302726541,
expectedChains: [][]string{
- []string{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
- []string{"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority", "StartCom Certification Authority"},
+ {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"},
+ {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority", "StartCom Certification Authority"},
},
},
}
@@ -211,6 +212,10 @@ func chainToDebugString(chain []*Certificate) string {
return chainStr
}
+func nameToKey(name *pkix.Name) string {
+ return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
+}
+
const verisignRoot = `-----BEGIN CERTIFICATE-----
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
diff --git a/libgo/go/crypto/x509/x509.go b/libgo/go/crypto/x509/x509.go
index 8fda4715927..4b8ecc56c5e 100644
--- a/libgo/go/crypto/x509/x509.go
+++ b/libgo/go/crypto/x509/x509.go
@@ -20,108 +20,59 @@ import (
"time"
)
-// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
-type pkcs1PrivateKey struct {
- Version int
- N *big.Int
- E int
- D *big.Int
- P *big.Int
- Q *big.Int
- // We ignore these values, if present, because rsa will calculate them.
- Dp *big.Int `asn1:"optional"`
- Dq *big.Int `asn1:"optional"`
- Qinv *big.Int `asn1:"optional"`
-
- AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional"`
+// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo
+// in RFC 3280.
+type pkixPublicKey struct {
+ Algo pkix.AlgorithmIdentifier
+ BitString asn1.BitString
}
-type pkcs1AdditionalRSAPrime struct {
- Prime *big.Int
-
- // We ignore these values because rsa will calculate them.
- Exp *big.Int
- Coeff *big.Int
-}
-
-// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
-func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) {
- var priv pkcs1PrivateKey
- rest, err := asn1.Unmarshal(der, &priv)
- if len(rest) > 0 {
- err = asn1.SyntaxError{"trailing data"}
- return
- }
- if err != nil {
+// ParsePKIXPublicKey parses a DER encoded public key. These values are
+// typically found in PEM blocks with "BEGIN PUBLIC KEY".
+func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err os.Error) {
+ var pki publicKeyInfo
+ if _, err = asn1.Unmarshal(derBytes, &pki); err != nil {
return
}
-
- if priv.Version > 1 {
- return nil, os.NewError("x509: unsupported private key version")
- }
-
- if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
- return nil, os.NewError("private key contains zero or negative value")
- }
-
- key = new(rsa.PrivateKey)
- key.PublicKey = rsa.PublicKey{
- E: priv.E,
- N: priv.N,
+ algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm)
+ if algo == UnknownPublicKeyAlgorithm {
+ return nil, os.NewError("ParsePKIXPublicKey: unknown public key algorithm")
}
-
- key.D = priv.D
- key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
- key.Primes[0] = priv.P
- key.Primes[1] = priv.Q
- for i, a := range priv.AdditionalPrimes {
- if a.Prime.Sign() <= 0 {
- return nil, os.NewError("private key contains zero or negative prime")
- }
- key.Primes[i+2] = a.Prime
- // We ignore the other two values because rsa will calculate
- // them as needed.
- }
-
- err = key.Validate()
- if err != nil {
- return nil, err
- }
- key.Precompute()
-
- return
+ return parsePublicKey(algo, &pki)
}
-// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
-func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
- key.Precompute()
-
- version := 0
- if len(key.Primes) > 2 {
- version = 1
- }
+// MarshalPKIXPublicKey serialises a public key to DER-encoded PKIX format.
+func MarshalPKIXPublicKey(pub interface{}) ([]byte, os.Error) {
+ var pubBytes []byte
- priv := pkcs1PrivateKey{
- Version: version,
- N: key.N,
- E: key.PublicKey.E,
- D: key.D,
- P: key.Primes[0],
- Q: key.Primes[1],
- Dp: key.Precomputed.Dp,
- Dq: key.Precomputed.Dq,
- Qinv: key.Precomputed.Qinv,
+ switch pub := pub.(type) {
+ case *rsa.PublicKey:
+ pubBytes, _ = asn1.Marshal(rsaPublicKey{
+ N: pub.N,
+ E: pub.E,
+ })
+ default:
+ return nil, os.NewError("MarshalPKIXPublicKey: unknown public key type")
}
- priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
- for i, values := range key.Precomputed.CRTValues {
- priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
- priv.AdditionalPrimes[i].Exp = values.Exp
- priv.AdditionalPrimes[i].Coeff = values.Coeff
+ pkix := pkixPublicKey{
+ Algo: pkix.AlgorithmIdentifier{
+ Algorithm: []int{1, 2, 840, 113549, 1, 1, 1},
+ // This is a NULL parameters value which is technically
+ // superfluous, but most other code includes it and, by
+ // doing this, we match their public key hashes.
+ Parameters: asn1.RawValue{
+ Tag: 5,
+ },
+ },
+ BitString: asn1.BitString{
+ Bytes: pubBytes,
+ BitLength: 8 * len(pubBytes),
+ },
}
- b, _ := asn1.Marshal(priv)
- return b
+ ret, _ := asn1.Marshal(pkix)
+ return ret, nil
}
// These structures reflect the ASN.1 structure of X.509 certificates.:
@@ -138,9 +89,9 @@ type tbsCertificate struct {
Version int `asn1:"optional,explicit,default:1,tag:0"`
SerialNumber *big.Int
SignatureAlgorithm pkix.AlgorithmIdentifier
- Issuer pkix.RDNSequence
+ Issuer asn1.RawValue
Validity validity
- Subject pkix.RDNSequence
+ Subject asn1.RawValue
PublicKey publicKeyInfo
UniqueId asn1.BitString `asn1:"optional,tag:1"`
SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"`
@@ -339,6 +290,8 @@ type Certificate struct {
Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content.
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
+ RawSubject []byte // DER encoded Subject
+ RawIssuer []byte // DER encoded Issuer
Signature []byte
SignatureAlgorithm SignatureAlgorithm
@@ -483,11 +436,6 @@ type basicConstraints struct {
MaxPathLen int `asn1:"optional"`
}
-type rsaPublicKey struct {
- N *big.Int
- E int
-}
-
// RFC 5280 4.2.1.4
type policyInformation struct {
Policy asn1.ObjectIdentifier
@@ -556,6 +504,8 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
out.Raw = in.Raw
out.RawTBSCertificate = in.TBSCertificate.Raw
out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw
+ out.RawSubject = in.TBSCertificate.Subject.FullBytes
+ out.RawIssuer = in.TBSCertificate.Issuer.FullBytes
out.Signature = in.SignatureValue.RightAlign()
out.SignatureAlgorithm =
@@ -575,8 +525,18 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
out.Version = in.TBSCertificate.Version + 1
out.SerialNumber = in.TBSCertificate.SerialNumber
- out.Issuer.FillFromRDNSequence(&in.TBSCertificate.Issuer)
- out.Subject.FillFromRDNSequence(&in.TBSCertificate.Subject)
+
+ var issuer, subject pkix.RDNSequence
+ if _, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil {
+ return nil, err
+ }
+ if _, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil {
+ return nil, err
+ }
+
+ out.Issuer.FillFromRDNSequence(&issuer)
+ out.Subject.FillFromRDNSequence(&subject)
+
out.NotBefore = in.TBSCertificate.Validity.NotBefore
out.NotAfter = in.TBSCertificate.Validity.NotAfter
@@ -968,14 +928,23 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
return
}
+ asn1Issuer, err := asn1.Marshal(parent.Issuer.ToRDNSequence())
+ if err != nil {
+ return
+ }
+ asn1Subject, err := asn1.Marshal(parent.Subject.ToRDNSequence())
+ if err != nil {
+ return
+ }
+
encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
c := tbsCertificate{
Version: 2,
SerialNumber: template.SerialNumber,
SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
- Issuer: parent.Subject.ToRDNSequence(),
+ Issuer: asn1.RawValue{FullBytes: asn1Issuer},
Validity: validity{template.NotBefore, template.NotAfter},
- Subject: template.Subject.ToRDNSequence(),
+ Subject: asn1.RawValue{FullBytes: asn1Subject},
PublicKey: publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey},
Extensions: extensions,
}
diff --git a/libgo/go/crypto/x509/x509_test.go b/libgo/go/crypto/x509/x509_test.go
index dc216505efe..dbc5273ca12 100644
--- a/libgo/go/crypto/x509/x509_test.go
+++ b/libgo/go/crypto/x509/x509_test.go
@@ -6,6 +6,7 @@ package x509
import (
"asn1"
+ "bytes"
"big"
"crypto/dsa"
"crypto/rand"
@@ -34,6 +35,40 @@ func TestParsePKCS1PrivateKey(t *testing.T) {
}
}
+func TestParsePKIXPublicKey(t *testing.T) {
+ block, _ := pem.Decode([]byte(pemPublicKey))
+ pub, err := ParsePKIXPublicKey(block.Bytes)
+ if err != nil {
+ t.Errorf("Failed to parse RSA public key: %s", err)
+ return
+ }
+ rsaPub, ok := pub.(*rsa.PublicKey)
+ if !ok {
+ t.Errorf("Value returned from ParsePKIXPublicKey was not an RSA public key")
+ return
+ }
+
+ pubBytes2, err := MarshalPKIXPublicKey(rsaPub)
+ if err != nil {
+ t.Errorf("Failed to marshal RSA public key for the second time: %s", err)
+ return
+ }
+ if !bytes.Equal(pubBytes2, block.Bytes) {
+ t.Errorf("Reserialization of public key didn't match. got %x, want %x", pubBytes2, block.Bytes)
+ }
+}
+
+var pemPublicKey = `-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3VoPN9PKUjKFLMwOge6+
+wnDi8sbETGIx2FKXGgqtAKpzmem53kRGEQg8WeqRmp12wgp74TGpkEXsGae7RS1k
+enJCnma4fii+noGH7R0qKgHvPrI2Bwa9hzsH8tHxpyM3qrXslOmD45EH9SxIDUBJ
+FehNdaPbLP1gFyahKMsdfxFJLUvbUycuZSJ2ZnIgeVxwm4qbSvZInL9Iu4FzuPtg
+fINKcbbovy1qq4KvPIrXzhbY3PWDc6btxCf3SE0JdE1MCPThntB62/bLMSQ7xdDR
+FF53oIpvxe/SCOymfWq/LW849Ytv3Xwod0+wzAP8STXG4HSELS4UedPYeHJJJYcZ
++QIDAQAB
+-----END PUBLIC KEY-----
+`
+
var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
diff --git a/libgo/go/csv/reader.go b/libgo/go/csv/reader.go
index ea2c266a47d..29ceeae85b4 100644
--- a/libgo/go/csv/reader.go
+++ b/libgo/go/csv/reader.go
@@ -267,7 +267,7 @@ func (r *Reader) parseField() (haveField bool, delim int, err os.Error) {
}
if r.TrimLeadingSpace {
- for unicode.IsSpace(rune) {
+ for rune != '\n' && unicode.IsSpace(rune) {
rune, err = r.readRune()
if err != nil {
return false, 0, err
@@ -355,7 +355,7 @@ func (r *Reader) parseField() (haveField bool, delim int, err os.Error) {
c := r.column
rune, err = r.readRune()
if r.TrimLeadingSpace {
- for unicode.IsSpace(rune) {
+ for rune != '\n' && unicode.IsSpace(rune) {
rune, err = r.readRune()
if err != nil {
break
diff --git a/libgo/go/csv/reader_test.go b/libgo/go/csv/reader_test.go
index 0068bad1db6..967f96b8d1b 100644
--- a/libgo/go/csv/reader_test.go
+++ b/libgo/go/csv/reader_test.go
@@ -127,10 +127,9 @@ field"`,
Output: [][]string{{`a""b`, `c`}},
},
{
- Name: "BadDoubleQuotes",
- Input: `a""b,c`,
- Output: [][]string{{`a""b`, `c`}},
- Error: `bare " in non-quoted-field`, Line: 1, Column: 1,
+ Name: "BadDoubleQuotes",
+ Input: `a""b,c`,
+ Error: `bare " in non-quoted-field`, Line: 1, Column: 1,
},
{
Name: "TrimQuote",
@@ -231,6 +230,23 @@ x,,,
{"", "", "", ""},
},
},
+ {
+ Name: "Issue 2366",
+ TrailingComma: true,
+ TrimLeadingSpace: true,
+ Input: "a,b,\nc,d,e",
+ Output: [][]string{
+ {"a", "b", ""},
+ {"c", "d", "e"},
+ },
+ },
+ {
+ Name: "Issue 2366a",
+ TrailingComma: false,
+ TrimLeadingSpace: true,
+ Input: "a,b,\nc,d,e",
+ Error: "extra delimiter at end of line",
+ },
}
func TestRead(t *testing.T) {
diff --git a/libgo/go/debug/dwarf/type.go b/libgo/go/debug/dwarf/type.go
index f35365ebeb0..9fa221b0902 100644
--- a/libgo/go/debug/dwarf/type.go
+++ b/libgo/go/debug/dwarf/type.go
@@ -579,6 +579,6 @@ Error:
// If the parse fails, take the type out of the cache
// so that the next call with this offset doesn't hit
// the cache and return success.
- d.typeCache[off] = nil, false
+ delete(d.typeCache, off)
return nil, err
}
diff --git a/libgo/go/ebnf/ebnf.go b/libgo/go/ebnf/ebnf.go
deleted file mode 100644
index 69da1176725..00000000000
--- a/libgo/go/ebnf/ebnf.go
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package ebnf is a library for EBNF grammars. The input is text ([]byte)
-// satisfying the following grammar (represented itself in EBNF):
-//
-// Production = name "=" [ Expression ] "." .
-// Expression = Alternative { "|" Alternative } .
-// Alternative = Term { Term } .
-// Term = name | token [ "…" token ] | Group | Option | Repetition .
-// Group = "(" Expression ")" .
-// Option = "[" Expression "]" .
-// Repetition = "{" Expression "}" .
-//
-// A name is a Go identifier, a token is a Go string, and comments
-// and white space follow the same rules as for the Go language.
-// Production names starting with an uppercase Unicode letter denote
-// non-terminal productions (i.e., productions which allow white-space
-// and comments between tokens); all other production names denote
-// lexical productions.
-//
-package ebnf
-
-import (
- "go/scanner"
- "go/token"
- "os"
- "unicode"
- "utf8"
-)
-
-// ----------------------------------------------------------------------------
-// Internal representation
-
-type (
- // An Expression node represents a production expression.
- Expression interface {
- // Pos is the position of the first character of the syntactic construct
- Pos() token.Pos
- }
-
- // An Alternative node represents a non-empty list of alternative expressions.
- Alternative []Expression // x | y | z
-
- // A Sequence node represents a non-empty list of sequential expressions.
- Sequence []Expression // x y z
-
- // A Name node represents a production name.
- Name struct {
- StringPos token.Pos
- String string
- }
-
- // A Token node represents a literal.
- Token struct {
- StringPos token.Pos
- String string
- }
-
- // A List node represents a range of characters.
- Range struct {
- Begin, End *Token // begin ... end
- }
-
- // A Group node represents a grouped expression.
- Group struct {
- Lparen token.Pos
- Body Expression // (body)
- }
-
- // An Option node represents an optional expression.
- Option struct {
- Lbrack token.Pos
- Body Expression // [body]
- }
-
- // A Repetition node represents a repeated expression.
- Repetition struct {
- Lbrace token.Pos
- Body Expression // {body}
- }
-
- // A Bad node stands for pieces of source code that lead to a parse error.
- Bad struct {
- TokPos token.Pos
- Error string // parser error message
- }
-
- // A Production node represents an EBNF production.
- Production struct {
- Name *Name
- Expr Expression
- }
-
- // A Grammar is a set of EBNF productions. The map
- // is indexed by production name.
- //
- Grammar map[string]*Production
-)
-
-func (x Alternative) Pos() token.Pos { return x[0].Pos() } // the parser always generates non-empty Alternative
-func (x Sequence) Pos() token.Pos { return x[0].Pos() } // the parser always generates non-empty Sequences
-func (x *Name) Pos() token.Pos { return x.StringPos }
-func (x *Token) Pos() token.Pos { return x.StringPos }
-func (x *Range) Pos() token.Pos { return x.Begin.Pos() }
-func (x *Group) Pos() token.Pos { return x.Lparen }
-func (x *Option) Pos() token.Pos { return x.Lbrack }
-func (x *Repetition) Pos() token.Pos { return x.Lbrace }
-func (x *Bad) Pos() token.Pos { return x.TokPos }
-func (x *Production) Pos() token.Pos { return x.Name.Pos() }
-
-// ----------------------------------------------------------------------------
-// Grammar verification
-
-func isLexical(name string) bool {
- ch, _ := utf8.DecodeRuneInString(name)
- return !unicode.IsUpper(ch)
-}
-
-type verifier struct {
- fset *token.FileSet
- scanner.ErrorVector
- worklist []*Production
- reached Grammar // set of productions reached from (and including) the root production
- grammar Grammar
-}
-
-func (v *verifier) error(pos token.Pos, msg string) {
- v.Error(v.fset.Position(pos), msg)
-}
-
-func (v *verifier) push(prod *Production) {
- name := prod.Name.String
- if _, found := v.reached[name]; !found {
- v.worklist = append(v.worklist, prod)
- v.reached[name] = prod
- }
-}
-
-func (v *verifier) verifyChar(x *Token) int {
- s := x.String
- if utf8.RuneCountInString(s) != 1 {
- v.error(x.Pos(), "single char expected, found "+s)
- return 0
- }
- ch, _ := utf8.DecodeRuneInString(s)
- return ch
-}
-
-func (v *verifier) verifyExpr(expr Expression, lexical bool) {
- switch x := expr.(type) {
- case nil:
- // empty expression
- case Alternative:
- for _, e := range x {
- v.verifyExpr(e, lexical)
- }
- case Sequence:
- for _, e := range x {
- v.verifyExpr(e, lexical)
- }
- case *Name:
- // a production with this name must exist;
- // add it to the worklist if not yet processed
- if prod, found := v.grammar[x.String]; found {
- v.push(prod)
- } else {
- v.error(x.Pos(), "missing production "+x.String)
- }
- // within a lexical production references
- // to non-lexical productions are invalid
- if lexical && !isLexical(x.String) {
- v.error(x.Pos(), "reference to non-lexical production "+x.String)
- }
- case *Token:
- // nothing to do for now
- case *Range:
- i := v.verifyChar(x.Begin)
- j := v.verifyChar(x.End)
- if i >= j {
- v.error(x.Pos(), "decreasing character range")
- }
- case *Group:
- v.verifyExpr(x.Body, lexical)
- case *Option:
- v.verifyExpr(x.Body, lexical)
- case *Repetition:
- v.verifyExpr(x.Body, lexical)
- default:
- panic("unreachable")
- }
-}
-
-func (v *verifier) verify(fset *token.FileSet, grammar Grammar, start string) {
- // find root production
- root, found := grammar[start]
- if !found {
- // token.NoPos doesn't require a file set;
- // ok to set v.fset only afterwards
- v.error(token.NoPos, "no start production "+start)
- return
- }
-
- // initialize verifier
- v.fset = fset
- v.ErrorVector.Reset()
- v.worklist = v.worklist[0:0]
- v.reached = make(Grammar)
- v.grammar = grammar
-
- // work through the worklist
- v.push(root)
- for {
- n := len(v.worklist) - 1
- if n < 0 {
- break
- }
- prod := v.worklist[n]
- v.worklist = v.worklist[0:n]
- v.verifyExpr(prod.Expr, isLexical(prod.Name.String))
- }
-
- // check if all productions were reached
- if len(v.reached) < len(v.grammar) {
- for name, prod := range v.grammar {
- if _, found := v.reached[name]; !found {
- v.error(prod.Pos(), name+" is unreachable")
- }
- }
- }
-}
-
-// Verify checks that:
-// - all productions used are defined
-// - all productions defined are used when beginning at start
-// - lexical productions refer only to other lexical productions
-//
-// Position information is interpreted relative to the file set fset.
-//
-func Verify(fset *token.FileSet, grammar Grammar, start string) os.Error {
- var v verifier
- v.verify(fset, grammar, start)
- return v.GetError(scanner.Sorted)
-}
diff --git a/libgo/go/ebnf/ebnf_test.go b/libgo/go/ebnf/ebnf_test.go
deleted file mode 100644
index b086facc3ed..00000000000
--- a/libgo/go/ebnf/ebnf_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ebnf
-
-import (
- "go/token"
- "io/ioutil"
- "testing"
-)
-
-var fset = token.NewFileSet()
-
-var goodGrammars = []string{
- `Program = .`,
-
- `Program = foo .
- foo = "foo" .`,
-
- `Program = "a" | "b" "c" .`,
-
- `Program = "a" … "z" .`,
-
- `Program = Song .
- Song = { Note } .
- Note = Do | (Re | Mi | Fa | So | La) | Ti .
- Do = "c" .
- Re = "d" .
- Mi = "e" .
- Fa = "f" .
- So = "g" .
- La = "a" .
- Ti = ti .
- ti = "b" .`,
-}
-
-var badGrammars = []string{
- `Program = | .`,
- `Program = | b .`,
- `Program = a … b .`,
- `Program = "a" … .`,
- `Program = … "b" .`,
- `Program = () .`,
- `Program = [] .`,
- `Program = {} .`,
-}
-
-func checkGood(t *testing.T, filename string, src []byte) {
- grammar, err := Parse(fset, filename, src)
- if err != nil {
- t.Errorf("Parse(%s) failed: %v", src, err)
- }
- if err = Verify(fset, grammar, "Program"); err != nil {
- t.Errorf("Verify(%s) failed: %v", src, err)
- }
-}
-
-func checkBad(t *testing.T, filename string, src []byte) {
- _, err := Parse(fset, filename, src)
- if err == nil {
- t.Errorf("Parse(%s) should have failed", src)
- }
-}
-
-func TestGrammars(t *testing.T) {
- for _, src := range goodGrammars {
- checkGood(t, "", []byte(src))
- }
- for _, src := range badGrammars {
- checkBad(t, "", []byte(src))
- }
-}
-
-var files = []string{
-// TODO(gri) add some test files
-}
-
-func TestFiles(t *testing.T) {
- for _, filename := range files {
- src, err := ioutil.ReadFile(filename)
- if err != nil {
- t.Fatal(err)
- }
- checkGood(t, filename, src)
- }
-}
diff --git a/libgo/go/ebnf/parser.go b/libgo/go/ebnf/parser.go
deleted file mode 100644
index ef2fac0000f..00000000000
--- a/libgo/go/ebnf/parser.go
+++ /dev/null
@@ -1,197 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ebnf
-
-import (
- "go/scanner"
- "go/token"
- "os"
- "strconv"
-)
-
-type parser struct {
- fset *token.FileSet
- scanner.ErrorVector
- scanner scanner.Scanner
- pos token.Pos // token position
- tok token.Token // one token look-ahead
- lit string // token literal
-}
-
-func (p *parser) next() {
- p.pos, p.tok, p.lit = p.scanner.Scan()
- if p.tok.IsKeyword() {
- // TODO Should keyword mapping always happen outside scanner?
- // Or should there be a flag to scanner to enable keyword mapping?
- p.tok = token.IDENT
- }
-}
-
-func (p *parser) error(pos token.Pos, msg string) {
- p.Error(p.fset.Position(pos), msg)
-}
-
-func (p *parser) errorExpected(pos token.Pos, msg string) {
- msg = "expected " + msg
- if pos == p.pos {
- // the error happened at the current position;
- // make the error message more specific
- msg += ", found '" + p.tok.String() + "'"
- if p.tok.IsLiteral() {
- msg += " " + p.lit
- }
- }
- p.error(pos, msg)
-}
-
-func (p *parser) expect(tok token.Token) token.Pos {
- pos := p.pos
- if p.tok != tok {
- p.errorExpected(pos, "'"+tok.String()+"'")
- }
- p.next() // make progress in any case
- return pos
-}
-
-func (p *parser) parseIdentifier() *Name {
- pos := p.pos
- name := p.lit
- p.expect(token.IDENT)
- return &Name{pos, name}
-}
-
-func (p *parser) parseToken() *Token {
- pos := p.pos
- value := ""
- if p.tok == token.STRING {
- value, _ = strconv.Unquote(p.lit)
- // Unquote may fail with an error, but only if the scanner found
- // an illegal string in the first place. In this case the error
- // has already been reported.
- p.next()
- } else {
- p.expect(token.STRING)
- }
- return &Token{pos, value}
-}
-
-// ParseTerm returns nil if no term was found.
-func (p *parser) parseTerm() (x Expression) {
- pos := p.pos
-
- switch p.tok {
- case token.IDENT:
- x = p.parseIdentifier()
-
- case token.STRING:
- tok := p.parseToken()
- x = tok
- const ellipsis = "…" // U+2026, the horizontal ellipsis character
- if p.tok == token.ILLEGAL && p.lit == ellipsis {
- p.next()
- x = &Range{tok, p.parseToken()}
- }
-
- case token.LPAREN:
- p.next()
- x = &Group{pos, p.parseExpression()}
- p.expect(token.RPAREN)
-
- case token.LBRACK:
- p.next()
- x = &Option{pos, p.parseExpression()}
- p.expect(token.RBRACK)
-
- case token.LBRACE:
- p.next()
- x = &Repetition{pos, p.parseExpression()}
- p.expect(token.RBRACE)
- }
-
- return x
-}
-
-func (p *parser) parseSequence() Expression {
- var list Sequence
-
- for x := p.parseTerm(); x != nil; x = p.parseTerm() {
- list = append(list, x)
- }
-
- // no need for a sequence if list.Len() < 2
- switch len(list) {
- case 0:
- p.errorExpected(p.pos, "term")
- return &Bad{p.pos, "term expected"}
- case 1:
- return list[0]
- }
-
- return list
-}
-
-func (p *parser) parseExpression() Expression {
- var list Alternative
-
- for {
- list = append(list, p.parseSequence())
- if p.tok != token.OR {
- break
- }
- p.next()
- }
- // len(list) > 0
-
- // no need for an Alternative node if list.Len() < 2
- if len(list) == 1 {
- return list[0]
- }
-
- return list
-}
-
-func (p *parser) parseProduction() *Production {
- name := p.parseIdentifier()
- p.expect(token.ASSIGN)
- var expr Expression
- if p.tok != token.PERIOD {
- expr = p.parseExpression()
- }
- p.expect(token.PERIOD)
- return &Production{name, expr}
-}
-
-func (p *parser) parse(fset *token.FileSet, filename string, src []byte) Grammar {
- // initialize parser
- p.fset = fset
- p.ErrorVector.Reset()
- p.scanner.Init(fset.AddFile(filename, fset.Base(), len(src)), src, p, scanner.AllowIllegalChars)
- p.next() // initializes pos, tok, lit
-
- grammar := make(Grammar)
- for p.tok != token.EOF {
- prod := p.parseProduction()
- name := prod.Name.String
- if _, found := grammar[name]; !found {
- grammar[name] = prod
- } else {
- p.error(prod.Pos(), name+" declared already")
- }
- }
-
- return grammar
-}
-
-// Parse parses a set of EBNF productions from source src.
-// It returns a set of productions. Errors are reported
-// for incorrect syntax and if a production is declared
-// more than once. Position information is recorded relative
-// to the file set fset.
-//
-func Parse(fset *token.FileSet, filename string, src []byte) (Grammar, os.Error) {
- var p parser
- grammar := p.parse(fset, filename, src)
- return grammar, p.GetError(scanner.Sorted)
-}
diff --git a/libgo/go/encoding/binary/binary.go b/libgo/go/encoding/binary/binary.go
index 8e55cb23b7c..c58f73694b8 100644
--- a/libgo/go/encoding/binary/binary.go
+++ b/libgo/go/encoding/binary/binary.go
@@ -17,9 +17,9 @@ import (
// A ByteOrder specifies how to convert byte sequences into
// 16-, 32-, or 64-bit unsigned integers.
type ByteOrder interface {
- Uint16(b []byte) uint16
- Uint32(b []byte) uint32
- Uint64(b []byte) uint64
+ Uint16([]byte) uint16
+ Uint32([]byte) uint32
+ Uint64([]byte) uint64
PutUint16([]byte, uint16)
PutUint32([]byte, uint32)
PutUint64([]byte, uint64)
diff --git a/libgo/go/encoding/binary/varint.go b/libgo/go/encoding/binary/varint.go
new file mode 100644
index 00000000000..c98e0e2bf57
--- /dev/null
+++ b/libgo/go/encoding/binary/varint.go
@@ -0,0 +1,149 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package binary
+
+// This file implements "varint" encoding of 64-bit integers.
+// The encoding is:
+// - unsigned integers are serialized 7 bits at a time, starting with the
+// least significant bits
+// - the most significant bit (msb) in each output byte indicates if there
+// is a continuation byte (msb = 1)
+// - signed integers are mapped to unsigned integers using "zig-zag"
+// encoding: Positive values x are written as 2*x + 0, negative values
+// are written as 2*(^x) + 1; that is, negative numbers are complemented
+// and whether to complement is encoded in bit 0.
+//
+// Design note:
+// At most 10 bytes are needed for 64-bit values. The encoding could
+// be more dense: a full 64-bit value needs an extra byte just to hold bit 63.
+// Instead, the msb of the previous byte could be used to hold bit 63 since we
+// know there can't be more than 64 bits. This is a trivial improvement and
+// would reduce the maximum encoding length to 9 bytes. However, it breaks the
+// invariant that the msb is always the "continuation bit" and thus makes the
+// format incompatible with a varint encoding for larger numbers (say 128-bit).
+
+import (
+ "io"
+ "os"
+)
+
+// MaxVarintLenN is the maximum length of a varint-encoded N-bit integer.
+const (
+ MaxVarintLen16 = 3
+ MaxVarintLen32 = 5
+ MaxVarintLen64 = 10
+)
+
+// PutUvarint encodes a uint64 into buf and returns the number of bytes written.
+func PutUvarint(buf []byte, x uint64) int {
+ i := 0
+ for x >= 0x80 {
+ buf[i] = byte(x) | 0x80
+ x >>= 7
+ i++
+ }
+ buf[i] = byte(x)
+ return i + 1
+}
+
+// Uvarint decodes a uint64 from buf and returns that value and the
+// number of bytes read (> 0). If an error occurred, the value is 0
+// and the number of bytes n is <= 0 meaning:
+//
+// n == 0: buf too small
+// n < 0: value larger than 64 bits (overflow)
+// and -n is the number of bytes read
+//
+func Uvarint(buf []byte) (uint64, int) {
+ var x uint64
+ var s uint
+ for i, b := range buf {
+ if b < 0x80 {
+ if i > 9 || i == 9 && b > 1 {
+ return 0, -(i + 1) // overflow
+ }
+ return x | uint64(b)<<s, i + 1
+ }
+ x |= uint64(b&0x7f) << s
+ s += 7
+ }
+ return 0, 0
+}
+
+// PutVarint encodes an int64 into buf and returns the number of bytes written.
+func PutVarint(buf []byte, x int64) int {
+ ux := uint64(x) << 1
+ if x < 0 {
+ ux = ^ux
+ }
+ return PutUvarint(buf, ux)
+}
+
+// Varint decodes an int64 from buf and returns that value and the
+// number of bytes read (> 0). If an error occurred, the value is 0
+// and the number of bytes n is <= 0 with the following meaning:
+//
+// n == 0: buf too small
+// n < 0: value larger than 64 bits (overflow)
+// and -n is the number of bytes read
+//
+func Varint(buf []byte) (int64, int) {
+ ux, n := Uvarint(buf) // ok to continue in presence of error
+ x := int64(ux >> 1)
+ if ux&1 != 0 {
+ x = ^x
+ }
+ return x, n
+}
+
+// WriteUvarint encodes x and writes the result to w.
+func WriteUvarint(w io.Writer, x uint64) os.Error {
+ var buf [MaxVarintLen64]byte
+ n := PutUvarint(buf[:], x)
+ _, err := w.Write(buf[0:n])
+ return err
+}
+
+var overflow = os.NewError("binary: varint overflows a 64-bit integer")
+
+// ReadUvarint reads an encoded unsigned integer from r and returns it as a uint64.
+func ReadUvarint(r io.ByteReader) (uint64, os.Error) {
+ var x uint64
+ var s uint
+ for i := 0; ; i++ {
+ b, err := r.ReadByte()
+ if err != nil {
+ return x, err
+ }
+ if b < 0x80 {
+ if i > 9 || i == 9 && b > 1 {
+ return x, overflow
+ }
+ return x | uint64(b)<<s, nil
+ }
+ x |= uint64(b&0x7f) << s
+ s += 7
+ }
+ panic("unreachable")
+}
+
+// WriteVarint encodes x and writes the result to w.
+func WriteVarint(w io.Writer, x int64) os.Error {
+ ux := uint64(x) << 1
+ if x < 0 {
+ ux = ^ux
+ }
+ return WriteUvarint(w, ux)
+}
+
+// ReadVarint reads an encoded unsigned integer from r and returns it as a uint64.
+func ReadVarint(r io.ByteReader) (int64, os.Error) {
+ ux, err := ReadUvarint(r) // ok to continue in presence of error
+ x := int64(ux >> 1)
+ if ux&1 != 0 {
+ x = ^x
+ }
+ return x, err
+}
diff --git a/libgo/go/encoding/binary/varint_test.go b/libgo/go/encoding/binary/varint_test.go
new file mode 100644
index 00000000000..ef51f09293b
--- /dev/null
+++ b/libgo/go/encoding/binary/varint_test.go
@@ -0,0 +1,182 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package binary
+
+import (
+ "bytes"
+ "os"
+ "testing"
+)
+
+func testConstant(t *testing.T, w uint, max int) {
+ buf := make([]byte, MaxVarintLen64)
+ n := PutUvarint(buf, 1<<w-1)
+ if n != max {
+ t.Errorf("MaxVarintLen%d = %d; want %d", w, max, n)
+ }
+}
+
+func TestConstants(t *testing.T) {
+ testConstant(t, 16, MaxVarintLen16)
+ testConstant(t, 32, MaxVarintLen32)
+ testConstant(t, 64, MaxVarintLen64)
+}
+
+func testVarint(t *testing.T, x int64) {
+ buf1 := make([]byte, MaxVarintLen64)
+ n := PutVarint(buf1[:], x)
+ y, m := Varint(buf1[0:n])
+ if x != y {
+ t.Errorf("Varint(%d): got %d", x, y)
+ }
+ if n != m {
+ t.Errorf("Varint(%d): got n = %d; want %d", x, m, n)
+ }
+
+ var buf2 bytes.Buffer
+ err := WriteVarint(&buf2, x)
+ if err != nil {
+ t.Errorf("WriteVarint(%d): %s", x, err)
+ }
+ if n != buf2.Len() {
+ t.Errorf("WriteVarint(%d): got n = %d; want %d", x, buf2.Len(), n)
+ }
+ y, err = ReadVarint(&buf2)
+ if err != nil {
+ t.Errorf("ReadVarint(%d): %s", x, err)
+ }
+ if x != y {
+ t.Errorf("ReadVarint(%d): got %d", x, y)
+ }
+}
+
+func testUvarint(t *testing.T, x uint64) {
+ buf1 := make([]byte, MaxVarintLen64)
+ n := PutUvarint(buf1[:], x)
+ y, m := Uvarint(buf1[0:n])
+ if x != y {
+ t.Errorf("Uvarint(%d): got %d", x, y)
+ }
+ if n != m {
+ t.Errorf("Uvarint(%d): got n = %d; want %d", x, m, n)
+ }
+
+ var buf2 bytes.Buffer
+ err := WriteUvarint(&buf2, x)
+ if err != nil {
+ t.Errorf("WriteUvarint(%d): %s", x, err)
+ }
+ if n != buf2.Len() {
+ t.Errorf("WriteUvarint(%d): got n = %d; want %d", x, buf2.Len(), n)
+ }
+ y, err = ReadUvarint(&buf2)
+ if err != nil {
+ t.Errorf("ReadUvarint(%d): %s", x, err)
+ }
+ if x != y {
+ t.Errorf("ReadUvarint(%d): got %d", x, y)
+ }
+}
+
+var tests = []int64{
+ -1 << 63,
+ -1<<63 + 1,
+ -1,
+ 0,
+ 1,
+ 2,
+ 10,
+ 20,
+ 63,
+ 64,
+ 65,
+ 127,
+ 128,
+ 129,
+ 255,
+ 256,
+ 257,
+ 1<<63 - 1,
+}
+
+func TestVarint(t *testing.T) {
+ for _, x := range tests {
+ testVarint(t, x)
+ testVarint(t, -x)
+ }
+ for x := int64(0x7); x != 0; x <<= 1 {
+ testVarint(t, x)
+ testVarint(t, -x)
+ }
+}
+
+func TestUvarint(t *testing.T) {
+ for _, x := range tests {
+ testUvarint(t, uint64(x))
+ }
+ for x := uint64(0x7); x != 0; x <<= 1 {
+ testUvarint(t, x)
+ }
+}
+
+func TestBufferTooSmall(t *testing.T) {
+ buf := []byte{0x80, 0x80, 0x80, 0x80}
+ for i := 0; i <= len(buf); i++ {
+ buf := buf[0:i]
+ x, n := Uvarint(buf)
+ if x != 0 || n != 0 {
+ t.Errorf("Uvarint(%v): got x = %d, n = %d", buf, x, n)
+ }
+
+ x, err := ReadUvarint(bytes.NewBuffer(buf))
+ if x != 0 || err != os.EOF {
+ t.Errorf("ReadUvarint(%v): got x = %d, err = %s", buf, x, err)
+ }
+ }
+}
+
+func testOverflow(t *testing.T, buf []byte, n0 int, err0 os.Error) {
+ x, n := Uvarint(buf)
+ if x != 0 || n != n0 {
+ t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, %d", buf, x, n, n0)
+ }
+
+ x, err := ReadUvarint(bytes.NewBuffer(buf))
+ if x != 0 || err != err0 {
+ t.Errorf("ReadUvarint(%v): got x = %d, err = %s; want 0, %s", buf, x, err, err0)
+ }
+}
+
+func TestOverflow(t *testing.T) {
+ testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x2}, -10, overflow)
+ testOverflow(t, []byte{0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x1, 0, 0}, -13, overflow)
+}
+
+func TestNonCanonicalZero(t *testing.T) {
+ buf := []byte{0x80, 0x80, 0x80, 0}
+ x, n := Uvarint(buf)
+ if x != 0 || n != 4 {
+ t.Errorf("Uvarint(%v): got x = %d, n = %d; want 0, 4", buf, x, n)
+
+ }
+}
+
+func BenchmarkPutUvarint32(b *testing.B) {
+ buf := make([]byte, MaxVarintLen32)
+ for i := 0; i < b.N; i++ {
+ for j := uint(0); j < MaxVarintLen32; j++ {
+ PutUvarint(buf, 1<<(j*7))
+ }
+ }
+}
+
+func BenchmarkPutUvarint64(b *testing.B) {
+ buf := make([]byte, MaxVarintLen64)
+ for i := 0; i < b.N; i++ {
+ for j := uint(0); j < MaxVarintLen64; j++ {
+ PutUvarint(buf, 1<<(j*7))
+ }
+ }
+}
diff --git a/libgo/go/exec/exec.go b/libgo/go/exec/exec.go
index 3b20f2008ca..aaad50846ea 100644
--- a/libgo/go/exec/exec.go
+++ b/libgo/go/exec/exec.go
@@ -63,6 +63,11 @@ type Cmd struct {
Stdout io.Writer
Stderr io.Writer
+ // ExtraFiles specifies additional open files to be inherited by the
+ // new process. It does not include standard input, standard output, or
+ // standard error. If non-nil, entry i becomes file descriptor 3+i.
+ ExtraFiles []*os.File
+
// SysProcAttr holds optional, operating system-specific attributes.
// Run passes it to os.StartProcess as the os.ProcAttr's Sys field.
SysProcAttr *syscall.SysProcAttr
@@ -224,6 +229,7 @@ func (c *Cmd) Start() os.Error {
}
c.childFiles = append(c.childFiles, fd)
}
+ c.childFiles = append(c.childFiles, c.ExtraFiles...)
var err os.Error
c.Process, err = os.StartProcess(c.Path, c.argv(), &os.ProcAttr{
diff --git a/libgo/go/exec/exec_test.go b/libgo/go/exec/exec_test.go
index 242120faab5..2b36e2535a4 100644
--- a/libgo/go/exec/exec_test.go
+++ b/libgo/go/exec/exec_test.go
@@ -9,8 +9,10 @@ import (
"bytes"
"fmt"
"io"
+ "io/ioutil"
"testing"
"os"
+ "runtime"
"strconv"
"strings"
)
@@ -139,6 +141,39 @@ func TestPipes(t *testing.T) {
check("Wait", err)
}
+func TestExtraFiles(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ t.Logf("no operating system support; skipping")
+ return
+ }
+ tf, err := ioutil.TempFile("", "")
+ if err != nil {
+ t.Fatalf("TempFile: %v", err)
+ }
+ defer os.Remove(tf.Name())
+ defer tf.Close()
+
+ const text = "Hello, fd 3!"
+ _, err = tf.Write([]byte(text))
+ if err != nil {
+ t.Fatalf("Write: %v", err)
+ }
+ _, err = tf.Seek(0, os.SEEK_SET)
+ if err != nil {
+ t.Fatalf("Seek: %v", err)
+ }
+
+ c := helperCommand("read3")
+ c.ExtraFiles = []*os.File{tf}
+ bs, err := c.CombinedOutput()
+ if err != nil {
+ t.Fatalf("CombinedOutput: %v", err)
+ }
+ if string(bs) != text {
+ t.Errorf("got %q; want %q", string(bs), text)
+ }
+}
+
// TestHelperProcess isn't a real test. It's used as a helper process
// for TestParameterRun.
func TestHelperProcess(*testing.T) {
@@ -204,6 +239,14 @@ func TestHelperProcess(*testing.T) {
os.Exit(1)
}
}
+ case "read3": // read fd 3
+ fd3 := os.NewFile(3, "fd3")
+ bs, err := ioutil.ReadAll(fd3)
+ if err != nil {
+ fmt.Printf("ReadAll from fd 3: %v", err)
+ os.Exit(1)
+ }
+ os.Stderr.Write(bs)
case "exit":
n, _ := strconv.Atoi(args[0])
os.Exit(n)
diff --git a/libgo/go/exec/lp_unix.go b/libgo/go/exec/lp_unix.go
index 008fb11a81c..0cd19e7ac90 100644
--- a/libgo/go/exec/lp_unix.go
+++ b/libgo/go/exec/lp_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package exec
import (
diff --git a/libgo/go/exp/datafmt/datafmt.go b/libgo/go/exp/datafmt/datafmt.go
deleted file mode 100644
index 6d7e7644276..00000000000
--- a/libgo/go/exp/datafmt/datafmt.go
+++ /dev/null
@@ -1,710 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/* Package datafmt implements syntax-directed, type-driven formatting
- of arbitrary data structures. Formatting a data structure consists of
- two phases: first, a parser reads a format specification and builds a
- "compiled" format. Then, the format can be applied repeatedly to
- arbitrary values. Applying a format to a value evaluates to a []byte
- containing the formatted value bytes, or nil.
-
- A format specification is a set of package declarations and format rules:
-
- Format = [ Entry { ";" Entry } [ ";" ] ] .
- Entry = PackageDecl | FormatRule .
-
- (The syntax of a format specification is presented in the same EBNF
- notation as used in the Go language specification. The syntax of white
- space, comments, identifiers, and string literals is the same as in Go.)
-
- A package declaration binds a package name (such as 'ast') to a
- package import path (such as '"go/ast"'). Each package used (in
- a type name, see below) must be declared once before use.
-
- PackageDecl = PackageName ImportPath .
- PackageName = identifier .
- ImportPath = string .
-
- A format rule binds a rule name to a format expression. A rule name
- may be a type name or one of the special names 'default' or '/'.
- A type name may be the name of a predeclared type (for example, 'int',
- 'float32', etc.), the package-qualified name of a user-defined type
- (for example, 'ast.MapType'), or an identifier indicating the structure
- of unnamed composite types ('array', 'chan', 'func', 'interface', 'map',
- or 'ptr'). Each rule must have a unique name; rules can be declared in
- any order.
-
- FormatRule = RuleName "=" Expression .
- RuleName = TypeName | "default" | "/" .
- TypeName = [ PackageName "." ] identifier .
-
- To format a value, the value's type name is used to select the format rule
- (there is an override mechanism, see below). The format expression of the
- selected rule specifies how the value is formatted. Each format expression,
- when applied to a value, evaluates to a byte sequence or nil.
-
- In its most general form, a format expression is a list of alternatives,
- each of which is a sequence of operands:
-
- Expression = [ Sequence ] { "|" [ Sequence ] } .
- Sequence = Operand { Operand } .
-
- The formatted result produced by an expression is the result of the first
- alternative sequence that evaluates to a non-nil result; if there is no
- such alternative, the expression evaluates to nil. The result produced by
- an operand sequence is the concatenation of the results of its operands.
- If any operand in the sequence evaluates to nil, the entire sequence
- evaluates to nil.
-
- There are five kinds of operands:
-
- Operand = Literal | Field | Group | Option | Repetition .
-
- Literals evaluate to themselves, with two substitutions. First,
- %-formats expand in the manner of fmt.Printf, with the current value
- passed as the parameter. Second, the current indentation (see below)
- is inserted after every newline or form feed character.
-
- Literal = string .
-
- This table shows string literals applied to the value 42 and the
- corresponding formatted result:
-
- "foo" foo
- "%x" 2a
- "x = %d" x = 42
- "%#x = %d" 0x2a = 42
-
- A field operand is a field name optionally followed by an alternate
- rule name. The field name may be an identifier or one of the special
- names @ or *.
-
- Field = FieldName [ ":" RuleName ] .
- FieldName = identifier | "@" | "*" .
-
- If the field name is an identifier, the current value must be a struct,
- and there must be a field with that name in the struct. The same lookup
- rules apply as in the Go language (for instance, the name of an anonymous
- field is the unqualified type name). The field name denotes the field
- value in the struct. If the field is not found, formatting is aborted
- and an error message is returned. (TODO consider changing the semantics
- such that if a field is not found, it evaluates to nil).
-
- The special name '@' denotes the current value.
-
- The meaning of the special name '*' depends on the type of the current
- value:
-
- array, slice types array, slice element (inside {} only, see below)
- interfaces value stored in interface
- pointers value pointed to by pointer
-
- (Implementation restriction: channel, function and map types are not
- supported due to missing reflection support).
-
- Fields are evaluated as follows: If the field value is nil, or an array
- or slice element does not exist, the result is nil (see below for details
- on array/slice elements). If the value is not nil the field value is
- formatted (recursively) using the rule corresponding to its type name,
- or the alternate rule name, if given.
-
- The following example shows a complete format specification for a
- struct 'myPackage.Point'. Assume the package
-
- package myPackage // in directory myDir/myPackage
- type Point struct {
- name string;
- x, y int;
- }
-
- Applying the format specification
-
- myPackage "myDir/myPackage";
- int = "%d";
- hexInt = "0x%x";
- string = "---%s---";
- myPackage.Point = name "{" x ", " y:hexInt "}";
-
- to the value myPackage.Point{"foo", 3, 15} results in
-
- ---foo---{3, 0xf}
-
- Finally, an operand may be a grouped, optional, or repeated expression.
- A grouped expression ("group") groups a more complex expression (body)
- so that it can be used in place of a single operand:
-
- Group = "(" [ Indentation ">>" ] Body ")" .
- Indentation = Expression .
- Body = Expression .
-
- A group body may be prefixed by an indentation expression followed by '>>'.
- The indentation expression is applied to the current value like any other
- expression and the result, if not nil, is appended to the current indentation
- during the evaluation of the body (see also formatting state, below).
-
- An optional expression ("option") is enclosed in '[]' brackets.
-
- Option = "[" Body "]" .
-
- An option evaluates to its body, except that if the body evaluates to nil,
- the option expression evaluates to an empty []byte. Thus an option's purpose
- is to protect the expression containing the option from a nil operand.
-
- A repeated expression ("repetition") is enclosed in '{}' braces.
-
- Repetition = "{" Body [ "/" Separator ] "}" .
- Separator = Expression .
-
- A repeated expression is evaluated as follows: The body is evaluated
- repeatedly and its results are concatenated until the body evaluates
- to nil. The result of the repetition is the (possibly empty) concatenation,
- but it is never nil. An implicit index is supplied for the evaluation of
- the body: that index is used to address elements of arrays or slices. If
- the corresponding elements do not exist, the field denoting the element
- evaluates to nil (which in turn may terminate the repetition).
-
- The body of a repetition may be followed by a '/' and a "separator"
- expression. If the separator is present, it is invoked between repetitions
- of the body.
-
- The following example shows a complete format specification for formatting
- a slice of unnamed type. Applying the specification
-
- int = "%b";
- array = { * / ", " }; // array is the type name for an unnamed slice
-
- to the value '[]int{2, 3, 5, 7}' results in
-
- 10, 11, 101, 111
-
- Default rule: If a format rule named 'default' is present, it is used for
- formatting a value if no other rule was found. A common default rule is
-
- default = "%v"
-
- to provide default formatting for basic types without having to specify
- a specific rule for each basic type.
-
- Global separator rule: If a format rule named '/' is present, it is
- invoked with the current value between literals. If the separator
- expression evaluates to nil, it is ignored.
-
- For instance, a global separator rule may be used to punctuate a sequence
- of values with commas. The rules:
-
- default = "%v";
- / = ", ";
-
- will format an argument list by printing each one in its default format,
- separated by a comma and a space.
-*/
-package datafmt
-
-import (
- "bytes"
- "fmt"
- "go/token"
- "io"
- "os"
- "reflect"
- "runtime"
-)
-
-// ----------------------------------------------------------------------------
-// Format representation
-
-// Custom formatters implement the Formatter function type.
-// A formatter is invoked with the current formatting state, the
-// value to format, and the rule name under which the formatter
-// was installed (the same formatter function may be installed
-// under different names). The formatter may access the current state
-// to guide formatting and use State.Write to append to the state's
-// output.
-//
-// A formatter must return a boolean value indicating if it evaluated
-// to a non-nil value (true), or a nil value (false).
-//
-type Formatter func(state *State, value interface{}, ruleName string) bool
-
-// A FormatterMap is a set of custom formatters.
-// It maps a rule name to a formatter function.
-//
-type FormatterMap map[string]Formatter
-
-// A parsed format expression is built from the following nodes.
-//
-type (
- expr interface{}
-
- alternatives []expr // x | y | z
-
- sequence []expr // x y z
-
- literal [][]byte // a list of string segments, possibly starting with '%'
-
- field struct {
- fieldName string // including "@", "*"
- ruleName string // "" if no rule name specified
- }
-
- group struct {
- indent, body expr // (indent >> body)
- }
-
- option struct {
- body expr // [body]
- }
-
- repetition struct {
- body, separator expr // {body / separator}
- }
-
- custom struct {
- ruleName string
- fun Formatter
- }
-)
-
-// A Format is the result of parsing a format specification.
-// The format may be applied repeatedly to format values.
-//
-type Format map[string]expr
-
-// ----------------------------------------------------------------------------
-// Formatting
-
-// An application-specific environment may be provided to Format.Apply;
-// the environment is available inside custom formatters via State.Env().
-// Environments must implement copying; the Copy method must return an
-// complete copy of the receiver. This is necessary so that the formatter
-// can save and restore an environment (in case of an absent expression).
-//
-// If the Environment doesn't change during formatting (this is under
-// control of the custom formatters), the Copy function can simply return
-// the receiver, and thus can be very light-weight.
-//
-type Environment interface {
- Copy() Environment
-}
-
-// State represents the current formatting state.
-// It is provided as argument to custom formatters.
-//
-type State struct {
- fmt Format // format in use
- env Environment // user-supplied environment
- errors chan os.Error // not chan *Error (errors <- nil would be wrong!)
- hasOutput bool // true after the first literal has been written
- indent bytes.Buffer // current indentation
- output bytes.Buffer // format output
- linePos token.Position // position of line beginning (Column == 0)
- default_ expr // possibly nil
- separator expr // possibly nil
-}
-
-func newState(fmt Format, env Environment, errors chan os.Error) *State {
- s := new(State)
- s.fmt = fmt
- s.env = env
- s.errors = errors
- s.linePos = token.Position{Line: 1}
-
- // if we have a default rule, cache its expression for fast access
- if x, found := fmt["default"]; found {
- s.default_ = x
- }
-
- // if we have a global separator rule, cache its expression for fast access
- if x, found := fmt["/"]; found {
- s.separator = x
- }
-
- return s
-}
-
-// Env returns the environment passed to Format.Apply.
-func (s *State) Env() interface{} { return s.env }
-
-// LinePos returns the position of the current line beginning
-// in the state's output buffer. Line numbers start at 1.
-//
-func (s *State) LinePos() token.Position { return s.linePos }
-
-// Pos returns the position of the next byte to be written to the
-// output buffer. Line numbers start at 1.
-//
-func (s *State) Pos() token.Position {
- offs := s.output.Len()
- return token.Position{Line: s.linePos.Line, Column: offs - s.linePos.Offset, Offset: offs}
-}
-
-// Write writes data to the output buffer, inserting the indentation
-// string after each newline or form feed character. It cannot return an error.
-//
-func (s *State) Write(data []byte) (int, os.Error) {
- n := 0
- i0 := 0
- for i, ch := range data {
- if ch == '\n' || ch == '\f' {
- // write text segment and indentation
- n1, _ := s.output.Write(data[i0 : i+1])
- n2, _ := s.output.Write(s.indent.Bytes())
- n += n1 + n2
- i0 = i + 1
- s.linePos.Offset = s.output.Len()
- s.linePos.Line++
- }
- }
- n3, _ := s.output.Write(data[i0:])
- return n + n3, nil
-}
-
-type checkpoint struct {
- env Environment
- hasOutput bool
- outputLen int
- linePos token.Position
-}
-
-func (s *State) save() checkpoint {
- saved := checkpoint{nil, s.hasOutput, s.output.Len(), s.linePos}
- if s.env != nil {
- saved.env = s.env.Copy()
- }
- return saved
-}
-
-func (s *State) restore(m checkpoint) {
- s.env = m.env
- s.output.Truncate(m.outputLen)
-}
-
-func (s *State) error(msg string) {
- s.errors <- os.NewError(msg)
- runtime.Goexit()
-}
-
-// TODO At the moment, unnamed types are simply mapped to the default
-// names below. For instance, all unnamed arrays are mapped to
-// 'array' which is not really sufficient. Eventually one may want
-// to be able to specify rules for say an unnamed slice of T.
-//
-
-func typename(typ reflect.Type) string {
- switch typ.Kind() {
- case reflect.Array:
- return "array"
- case reflect.Slice:
- return "array"
- case reflect.Chan:
- return "chan"
- case reflect.Func:
- return "func"
- case reflect.Interface:
- return "interface"
- case reflect.Map:
- return "map"
- case reflect.Ptr:
- return "ptr"
- }
- return typ.String()
-}
-
-func (s *State) getFormat(name string) expr {
- if fexpr, found := s.fmt[name]; found {
- return fexpr
- }
-
- if s.default_ != nil {
- return s.default_
- }
-
- s.error(fmt.Sprintf("no format rule for type: '%s'", name))
- return nil
-}
-
-// eval applies a format expression fexpr to a value. If the expression
-// evaluates internally to a non-nil []byte, that slice is appended to
-// the state's output buffer and eval returns true. Otherwise, eval
-// returns false and the state remains unchanged.
-//
-func (s *State) eval(fexpr expr, value reflect.Value, index int) bool {
- // an empty format expression always evaluates
- // to a non-nil (but empty) []byte
- if fexpr == nil {
- return true
- }
-
- switch t := fexpr.(type) {
- case alternatives:
- // append the result of the first alternative that evaluates to
- // a non-nil []byte to the state's output
- mark := s.save()
- for _, x := range t {
- if s.eval(x, value, index) {
- return true
- }
- s.restore(mark)
- }
- return false
-
- case sequence:
- // append the result of all operands to the state's output
- // unless a nil result is encountered
- mark := s.save()
- for _, x := range t {
- if !s.eval(x, value, index) {
- s.restore(mark)
- return false
- }
- }
- return true
-
- case literal:
- // write separator, if any
- if s.hasOutput {
- // not the first literal
- if s.separator != nil {
- sep := s.separator // save current separator
- s.separator = nil // and disable it (avoid recursion)
- mark := s.save()
- if !s.eval(sep, value, index) {
- s.restore(mark)
- }
- s.separator = sep // enable it again
- }
- }
- s.hasOutput = true
- // write literal segments
- for _, lit := range t {
- if len(lit) > 1 && lit[0] == '%' {
- // segment contains a %-format at the beginning
- if lit[1] == '%' {
- // "%%" is printed as a single "%"
- s.Write(lit[1:])
- } else {
- // use s instead of s.output to get indentation right
- fmt.Fprintf(s, string(lit), value.Interface())
- }
- } else {
- // segment contains no %-formats
- s.Write(lit)
- }
- }
- return true // a literal never evaluates to nil
-
- case *field:
- // determine field value
- switch t.fieldName {
- case "@":
- // field value is current value
-
- case "*":
- // indirection: operation is type-specific
- switch v := value; v.Kind() {
- case reflect.Array:
- if v.Len() <= index {
- return false
- }
- value = v.Index(index)
-
- case reflect.Slice:
- if v.IsNil() || v.Len() <= index {
- return false
- }
- value = v.Index(index)
-
- case reflect.Map:
- s.error("reflection support for maps incomplete")
-
- case reflect.Ptr:
- if v.IsNil() {
- return false
- }
- value = v.Elem()
-
- case reflect.Interface:
- if v.IsNil() {
- return false
- }
- value = v.Elem()
-
- case reflect.Chan:
- s.error("reflection support for chans incomplete")
-
- case reflect.Func:
- s.error("reflection support for funcs incomplete")
-
- default:
- s.error(fmt.Sprintf("error: * does not apply to `%s`", value.Type()))
- }
-
- default:
- // value is value of named field
- var field reflect.Value
- if sval := value; sval.Kind() == reflect.Struct {
- field = sval.FieldByName(t.fieldName)
- if !field.IsValid() {
- // TODO consider just returning false in this case
- s.error(fmt.Sprintf("error: no field `%s` in `%s`", t.fieldName, value.Type()))
- }
- }
- value = field
- }
-
- // determine rule
- ruleName := t.ruleName
- if ruleName == "" {
- // no alternate rule name, value type determines rule
- ruleName = typename(value.Type())
- }
- fexpr = s.getFormat(ruleName)
-
- mark := s.save()
- if !s.eval(fexpr, value, index) {
- s.restore(mark)
- return false
- }
- return true
-
- case *group:
- // remember current indentation
- indentLen := s.indent.Len()
-
- // update current indentation
- mark := s.save()
- s.eval(t.indent, value, index)
- // if the indentation evaluates to nil, the state's output buffer
- // didn't change - either way it's ok to append the difference to
- // the current indentation
- s.indent.Write(s.output.Bytes()[mark.outputLen:s.output.Len()])
- s.restore(mark)
-
- // format group body
- mark = s.save()
- b := true
- if !s.eval(t.body, value, index) {
- s.restore(mark)
- b = false
- }
-
- // reset indentation
- s.indent.Truncate(indentLen)
- return b
-
- case *option:
- // evaluate the body and append the result to the state's output
- // buffer unless the result is nil
- mark := s.save()
- if !s.eval(t.body, value, 0) { // TODO is 0 index correct?
- s.restore(mark)
- }
- return true // an option never evaluates to nil
-
- case *repetition:
- // evaluate the body and append the result to the state's output
- // buffer until a result is nil
- for i := 0; ; i++ {
- mark := s.save()
- // write separator, if any
- if i > 0 && t.separator != nil {
- // nil result from separator is ignored
- mark := s.save()
- if !s.eval(t.separator, value, i) {
- s.restore(mark)
- }
- }
- if !s.eval(t.body, value, i) {
- s.restore(mark)
- break
- }
- }
- return true // a repetition never evaluates to nil
-
- case *custom:
- // invoke the custom formatter to obtain the result
- mark := s.save()
- if !t.fun(s, value.Interface(), t.ruleName) {
- s.restore(mark)
- return false
- }
- return true
- }
-
- panic("unreachable")
- return false
-}
-
-// Eval formats each argument according to the format
-// f and returns the resulting []byte and os.Error. If
-// an error occurred, the []byte contains the partially
-// formatted result. An environment env may be passed
-// in which is available in custom formatters through
-// the state parameter.
-//
-func (f Format) Eval(env Environment, args ...interface{}) ([]byte, os.Error) {
- if f == nil {
- return nil, os.NewError("format is nil")
- }
-
- errors := make(chan os.Error)
- s := newState(f, env, errors)
-
- go func() {
- for _, v := range args {
- fld := reflect.ValueOf(v)
- if !fld.IsValid() {
- errors <- os.NewError("nil argument")
- return
- }
- mark := s.save()
- if !s.eval(s.getFormat(typename(fld.Type())), fld, 0) { // TODO is 0 index correct?
- s.restore(mark)
- }
- }
- errors <- nil // no errors
- }()
-
- err := <-errors
- return s.output.Bytes(), err
-}
-
-// ----------------------------------------------------------------------------
-// Convenience functions
-
-// Fprint formats each argument according to the format f
-// and writes to w. The result is the total number of bytes
-// written and an os.Error, if any.
-//
-func (f Format) Fprint(w io.Writer, env Environment, args ...interface{}) (int, os.Error) {
- data, err := f.Eval(env, args...)
- if err != nil {
- // TODO should we print partial result in case of error?
- return 0, err
- }
- return w.Write(data)
-}
-
-// Print formats each argument according to the format f
-// and writes to standard output. The result is the total
-// number of bytes written and an os.Error, if any.
-//
-func (f Format) Print(args ...interface{}) (int, os.Error) {
- return f.Fprint(os.Stdout, nil, args...)
-}
-
-// Sprint formats each argument according to the format f
-// and returns the resulting string. If an error occurs
-// during formatting, the result string contains the
-// partially formatted result followed by an error message.
-//
-func (f Format) Sprint(args ...interface{}) string {
- var buf bytes.Buffer
- _, err := f.Fprint(&buf, nil, args...)
- if err != nil {
- var i interface{} = args
- fmt.Fprintf(&buf, "--- Sprint(%s) failed: %v", fmt.Sprint(i), err)
- }
- return buf.String()
-}
diff --git a/libgo/go/exp/datafmt/datafmt_test.go b/libgo/go/exp/datafmt/datafmt_test.go
deleted file mode 100644
index 87d07165933..00000000000
--- a/libgo/go/exp/datafmt/datafmt_test.go
+++ /dev/null
@@ -1,330 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package datafmt
-
-import (
- "fmt"
- "testing"
- "go/token"
-)
-
-var fset = token.NewFileSet()
-
-func parse(t *testing.T, form string, fmap FormatterMap) Format {
- f, err := Parse(fset, "", []byte(form), fmap)
- if err != nil {
- t.Errorf("Parse(%s): %v", form, err)
- return nil
- }
- return f
-}
-
-func verify(t *testing.T, f Format, expected string, args ...interface{}) {
- if f == nil {
- return // allow other tests to run
- }
- result := f.Sprint(args...)
- if result != expected {
- t.Errorf(
- "result : `%s`\nexpected: `%s`\n\n",
- result, expected)
- }
-}
-
-func formatter(s *State, value interface{}, rule_name string) bool {
- switch rule_name {
- case "/":
- fmt.Fprintf(s, "%d %d %d", s.Pos().Line, s.LinePos().Column, s.Pos().Column)
- return true
- case "blank":
- s.Write([]byte{' '})
- return true
- case "int":
- if value.(int)&1 == 0 {
- fmt.Fprint(s, "even ")
- } else {
- fmt.Fprint(s, "odd ")
- }
- return true
- case "nil":
- return false
- case "testing.T":
- s.Write([]byte("testing.T"))
- return true
- }
- panic("unreachable")
- return false
-}
-
-func TestCustomFormatters(t *testing.T) {
- fmap0 := FormatterMap{"/": formatter}
- fmap1 := FormatterMap{"int": formatter, "blank": formatter, "nil": formatter}
- fmap2 := FormatterMap{"testing.T": formatter}
-
- f := parse(t, `int=`, fmap0)
- verify(t, f, ``, 1, 2, 3)
-
- f = parse(t, `int="#"`, nil)
- verify(t, f, `###`, 1, 2, 3)
-
- f = parse(t, `int="#";string="%s"`, fmap0)
- verify(t, f, "#1 0 1#1 0 7#1 0 13\n2 0 0foo2 0 8\n", 1, 2, 3, "\n", "foo", "\n")
-
- f = parse(t, ``, fmap1)
- verify(t, f, `even odd even odd `, 0, 1, 2, 3)
-
- f = parse(t, `/ =@:blank; float64="#"`, fmap1)
- verify(t, f, `# # #`, 0.0, 1.0, 2.0)
-
- f = parse(t, `float64=@:nil`, fmap1)
- verify(t, f, ``, 0.0, 1.0, 2.0)
-
- f = parse(t, `testing "testing"; ptr=*`, fmap2)
- verify(t, f, `testing.T`, t)
-
- // TODO needs more tests
-}
-
-// ----------------------------------------------------------------------------
-// Formatting of basic and simple composite types
-
-func check(t *testing.T, form, expected string, args ...interface{}) {
- f := parse(t, form, nil)
- if f == nil {
- return // allow other tests to run
- }
- result := f.Sprint(args...)
- if result != expected {
- t.Errorf(
- "format : %s\nresult : `%s`\nexpected: `%s`\n\n",
- form, result, expected)
- }
-}
-
-func TestBasicTypes(t *testing.T) {
- check(t, ``, ``)
- check(t, `bool=":%v"`, `:true:false`, true, false)
- check(t, `int="%b %d %o 0x%x"`, `101010 42 52 0x2a`, 42)
-
- check(t, `int="%"`, `%`, 42)
- check(t, `int="%%"`, `%`, 42)
- check(t, `int="**%%**"`, `**%**`, 42)
- check(t, `int="%%%%%%"`, `%%%`, 42)
- check(t, `int="%%%d%%"`, `%42%`, 42)
-
- const i = -42
- const is = `-42`
- check(t, `int ="%d"`, is, i)
- check(t, `int8 ="%d"`, is, int8(i))
- check(t, `int16="%d"`, is, int16(i))
- check(t, `int32="%d"`, is, int32(i))
- check(t, `int64="%d"`, is, int64(i))
-
- const u = 42
- const us = `42`
- check(t, `uint ="%d"`, us, uint(u))
- check(t, `uint8 ="%d"`, us, uint8(u))
- check(t, `uint16="%d"`, us, uint16(u))
- check(t, `uint32="%d"`, us, uint32(u))
- check(t, `uint64="%d"`, us, uint64(u))
-
- const f = 3.141592
- const fs = `3.141592`
- check(t, `float64="%g"`, fs, f)
- check(t, `float32="%g"`, fs, float32(f))
- check(t, `float64="%g"`, fs, float64(f))
-}
-
-func TestArrayTypes(t *testing.T) {
- var a0 [10]int
- check(t, `array="array";`, `array`, a0)
-
- a1 := [...]int{1, 2, 3}
- check(t, `array="array";`, `array`, a1)
- check(t, `array={*}; int="%d";`, `123`, a1)
- check(t, `array={* / ", "}; int="%d";`, `1, 2, 3`, a1)
- check(t, `array={* / *}; int="%d";`, `12233`, a1)
-
- a2 := []interface{}{42, "foo", 3.14}
- check(t, `array={* / ", "}; interface=*; string="bar"; default="%v";`, `42, bar, 3.14`, a2)
-}
-
-func TestChanTypes(t *testing.T) {
- var c0 chan int
- check(t, `chan="chan"`, `chan`, c0)
-
- c1 := make(chan int)
- go func() { c1 <- 42 }()
- check(t, `chan="chan"`, `chan`, c1)
- // check(t, `chan=*`, `42`, c1); // reflection support for chans incomplete
-}
-
-func TestFuncTypes(t *testing.T) {
- var f0 func() int
- check(t, `func="func"`, `func`, f0)
-
- f1 := func() int { return 42 }
- check(t, `func="func"`, `func`, f1)
- // check(t, `func=*`, `42`, f1); // reflection support for funcs incomplete
-}
-
-func TestMapTypes(t *testing.T) {
- var m0 map[string]int
- check(t, `map="map"`, `map`, m0)
-
- m1 := map[string]int{}
- check(t, `map="map"`, `map`, m1)
- // check(t, `map=*`, ``, m1); // reflection support for maps incomplete
-}
-
-func TestPointerTypes(t *testing.T) {
- var p0 *int
- check(t, `ptr="ptr"`, `ptr`, p0)
- check(t, `ptr=*`, ``, p0)
- check(t, `ptr=*|"nil"`, `nil`, p0)
-
- x := 99991
- p1 := &x
- check(t, `ptr="ptr"`, `ptr`, p1)
- check(t, `ptr=*; int="%d"`, `99991`, p1)
-}
-
-func TestDefaultRule(t *testing.T) {
- check(t, `default="%v"`, `42foo3.14`, 42, "foo", 3.14)
- check(t, `default="%v"; int="%x"`, `abcdef`, 10, 11, 12, 13, 14, 15)
- check(t, `default="%v"; int="%x"`, `ab**ef`, 10, 11, "**", 14, 15)
- check(t, `default="%x"; int=@:default`, `abcdef`, 10, 11, 12, 13, 14, 15)
-}
-
-func TestGlobalSeparatorRule(t *testing.T) {
- check(t, `int="%d"; / ="-"`, `1-2-3-4`, 1, 2, 3, 4)
- check(t, `int="%x%x"; / ="*"`, `aa*aa`, 10, 10)
-}
-
-// ----------------------------------------------------------------------------
-// Formatting of a struct
-
-type T1 struct {
- a int
-}
-
-const F1 = `datafmt "datafmt";` +
- `int = "%d";` +
- `datafmt.T1 = "<" a ">";`
-
-func TestStruct1(t *testing.T) { check(t, F1, "<42>", T1{42}) }
-
-// ----------------------------------------------------------------------------
-// Formatting of a struct with an optional field (ptr)
-
-type T2 struct {
- s string
- p *T1
-}
-
-const F2a = F1 +
- `string = "%s";` +
- `ptr = *;` +
- `datafmt.T2 = s ["-" p "-"];`
-
-const F2b = F1 +
- `string = "%s";` +
- `ptr = *;` +
- `datafmt.T2 = s ("-" p "-" | "empty");`
-
-func TestStruct2(t *testing.T) {
- check(t, F2a, "foo", T2{"foo", nil})
- check(t, F2a, "bar-<17>-", T2{"bar", &T1{17}})
- check(t, F2b, "fooempty", T2{"foo", nil})
-}
-
-// ----------------------------------------------------------------------------
-// Formatting of a struct with a repetitive field (slice)
-
-type T3 struct {
- s string
- a []int
-}
-
-const F3a = `datafmt "datafmt";` +
- `default = "%v";` +
- `array = *;` +
- `datafmt.T3 = s {" " a a / ","};`
-
-const F3b = `datafmt "datafmt";` +
- `int = "%d";` +
- `string = "%s";` +
- `array = *;` +
- `nil = ;` +
- `empty = *:nil;` +
- `datafmt.T3 = s [a:empty ": " {a / "-"}]`
-
-func TestStruct3(t *testing.T) {
- check(t, F3a, "foo", T3{"foo", nil})
- check(t, F3a, "foo 00, 11, 22", T3{"foo", []int{0, 1, 2}})
- check(t, F3b, "bar", T3{"bar", nil})
- check(t, F3b, "bal: 2-3-5", T3{"bal", []int{2, 3, 5}})
-}
-
-// ----------------------------------------------------------------------------
-// Formatting of a struct with alternative field
-
-type T4 struct {
- x *int
- a []int
-}
-
-const F4a = `datafmt "datafmt";` +
- `int = "%d";` +
- `ptr = *;` +
- `array = *;` +
- `nil = ;` +
- `empty = *:nil;` +
- `datafmt.T4 = "<" (x:empty x | "-") ">" `
-
-const F4b = `datafmt "datafmt";` +
- `int = "%d";` +
- `ptr = *;` +
- `array = *;` +
- `nil = ;` +
- `empty = *:nil;` +
- `datafmt.T4 = "<" (a:empty {a / ", "} | "-") ">" `
-
-func TestStruct4(t *testing.T) {
- x := 7
- check(t, F4a, "<->", T4{nil, nil})
- check(t, F4a, "<7>", T4{&x, nil})
- check(t, F4b, "<->", T4{nil, nil})
- check(t, F4b, "<2, 3, 7>", T4{nil, []int{2, 3, 7}})
-}
-
-// ----------------------------------------------------------------------------
-// Formatting a struct (documentation example)
-
-type Point struct {
- name string
- x, y int
-}
-
-const FPoint = `datafmt "datafmt";` +
- `int = "%d";` +
- `hexInt = "0x%x";` +
- `string = "---%s---";` +
- `datafmt.Point = name "{" x ", " y:hexInt "}";`
-
-func TestStructPoint(t *testing.T) {
- p := Point{"foo", 3, 15}
- check(t, FPoint, "---foo---{3, 0xf}", p)
-}
-
-// ----------------------------------------------------------------------------
-// Formatting a slice (documentation example)
-
-const FSlice = `int = "%b";` +
- `array = { * / ", " }`
-
-func TestSlice(t *testing.T) { check(t, FSlice, "10, 11, 101, 111", []int{2, 3, 5, 7}) }
-
-// TODO add more tests
diff --git a/libgo/go/exp/datafmt/parser.go b/libgo/go/exp/datafmt/parser.go
deleted file mode 100644
index a2ddd389723..00000000000
--- a/libgo/go/exp/datafmt/parser.go
+++ /dev/null
@@ -1,368 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package datafmt
-
-import (
- "go/scanner"
- "go/token"
- "os"
- "strconv"
- "strings"
-)
-
-// ----------------------------------------------------------------------------
-// Parsing
-
-type parser struct {
- scanner.ErrorVector
- scanner scanner.Scanner
- file *token.File
- pos token.Pos // token position
- tok token.Token // one token look-ahead
- lit string // token literal
-
- packs map[string]string // PackageName -> ImportPath
- rules map[string]expr // RuleName -> Expression
-}
-
-func (p *parser) next() {
- p.pos, p.tok, p.lit = p.scanner.Scan()
- switch p.tok {
- case token.CHAN, token.FUNC, token.INTERFACE, token.MAP, token.STRUCT:
- // Go keywords for composite types are type names
- // returned by reflect. Accept them as identifiers.
- p.tok = token.IDENT // p.lit is already set correctly
- }
-}
-
-func (p *parser) init(fset *token.FileSet, filename string, src []byte) {
- p.ErrorVector.Reset()
- p.file = fset.AddFile(filename, fset.Base(), len(src))
- p.scanner.Init(p.file, src, p, scanner.AllowIllegalChars) // return '@' as token.ILLEGAL w/o error message
- p.next() // initializes pos, tok, lit
- p.packs = make(map[string]string)
- p.rules = make(map[string]expr)
-}
-
-func (p *parser) error(pos token.Pos, msg string) {
- p.Error(p.file.Position(pos), msg)
-}
-
-func (p *parser) errorExpected(pos token.Pos, msg string) {
- msg = "expected " + msg
- if pos == p.pos {
- // the error happened at the current position;
- // make the error message more specific
- msg += ", found '" + p.tok.String() + "'"
- if p.tok.IsLiteral() {
- msg += " " + p.lit
- }
- }
- p.error(pos, msg)
-}
-
-func (p *parser) expect(tok token.Token) token.Pos {
- pos := p.pos
- if p.tok != tok {
- p.errorExpected(pos, "'"+tok.String()+"'")
- }
- p.next() // make progress in any case
- return pos
-}
-
-func (p *parser) parseIdentifier() string {
- name := p.lit
- p.expect(token.IDENT)
- return name
-}
-
-func (p *parser) parseTypeName() (string, bool) {
- pos := p.pos
- name, isIdent := p.parseIdentifier(), true
- if p.tok == token.PERIOD {
- // got a package name, lookup package
- if importPath, found := p.packs[name]; found {
- name = importPath
- } else {
- p.error(pos, "package not declared: "+name)
- }
- p.next()
- name, isIdent = name+"."+p.parseIdentifier(), false
- }
- return name, isIdent
-}
-
-// Parses a rule name and returns it. If the rule name is
-// a package-qualified type name, the package name is resolved.
-// The 2nd result value is true iff the rule name consists of a
-// single identifier only (and thus could be a package name).
-//
-func (p *parser) parseRuleName() (string, bool) {
- name, isIdent := "", false
- switch p.tok {
- case token.IDENT:
- name, isIdent = p.parseTypeName()
- case token.DEFAULT:
- name = "default"
- p.next()
- case token.QUO:
- name = "/"
- p.next()
- default:
- p.errorExpected(p.pos, "rule name")
- p.next() // make progress in any case
- }
- return name, isIdent
-}
-
-func (p *parser) parseString() string {
- s := ""
- if p.tok == token.STRING {
- s, _ = strconv.Unquote(p.lit)
- // Unquote may fail with an error, but only if the scanner found
- // an illegal string in the first place. In this case the error
- // has already been reported.
- p.next()
- return s
- } else {
- p.expect(token.STRING)
- }
- return s
-}
-
-func (p *parser) parseLiteral() literal {
- s := []byte(p.parseString())
-
- // A string literal may contain %-format specifiers. To simplify
- // and speed up printing of the literal, split it into segments
- // that start with "%" possibly followed by a last segment that
- // starts with some other character.
- var list []interface{}
- i0 := 0
- for i := 0; i < len(s); i++ {
- if s[i] == '%' && i+1 < len(s) {
- // the next segment starts with a % format
- if i0 < i {
- // the current segment is not empty, split it off
- list = append(list, s[i0:i])
- i0 = i
- }
- i++ // skip %; let loop skip over char after %
- }
- }
- // the final segment may start with any character
- // (it is empty iff the string is empty)
- list = append(list, s[i0:])
-
- // convert list into a literal
- lit := make(literal, len(list))
- for i := 0; i < len(list); i++ {
- lit[i] = list[i].([]byte)
- }
-
- return lit
-}
-
-func (p *parser) parseField() expr {
- var fname string
- switch p.tok {
- case token.ILLEGAL:
- if p.lit != "@" {
- return nil
- }
- fname = "@"
- p.next()
- case token.MUL:
- fname = "*"
- p.next()
- case token.IDENT:
- fname = p.parseIdentifier()
- default:
- return nil
- }
-
- var ruleName string
- if p.tok == token.COLON {
- p.next()
- ruleName, _ = p.parseRuleName()
- }
-
- return &field{fname, ruleName}
-}
-
-func (p *parser) parseOperand() (x expr) {
- switch p.tok {
- case token.STRING:
- x = p.parseLiteral()
-
- case token.LPAREN:
- p.next()
- x = p.parseExpression()
- if p.tok == token.SHR {
- p.next()
- x = &group{x, p.parseExpression()}
- }
- p.expect(token.RPAREN)
-
- case token.LBRACK:
- p.next()
- x = &option{p.parseExpression()}
- p.expect(token.RBRACK)
-
- case token.LBRACE:
- p.next()
- x = p.parseExpression()
- var div expr
- if p.tok == token.QUO {
- p.next()
- div = p.parseExpression()
- }
- x = &repetition{x, div}
- p.expect(token.RBRACE)
-
- default:
- x = p.parseField() // may be nil
- }
-
- return x
-}
-
-func (p *parser) parseSequence() expr {
- var list []interface{}
-
- for x := p.parseOperand(); x != nil; x = p.parseOperand() {
- list = append(list, x)
- }
-
- // no need for a sequence if list.Len() < 2
- switch len(list) {
- case 0:
- return nil
- case 1:
- return list[0].(expr)
- }
-
- // convert list into a sequence
- seq := make(sequence, len(list))
- for i := 0; i < len(list); i++ {
- seq[i] = list[i].(expr)
- }
- return seq
-}
-
-func (p *parser) parseExpression() expr {
- var list []interface{}
-
- for {
- x := p.parseSequence()
- if x != nil {
- list = append(list, x)
- }
- if p.tok != token.OR {
- break
- }
- p.next()
- }
-
- // no need for an alternatives if list.Len() < 2
- switch len(list) {
- case 0:
- return nil
- case 1:
- return list[0].(expr)
- }
-
- // convert list into a alternatives
- alt := make(alternatives, len(list))
- for i := 0; i < len(list); i++ {
- alt[i] = list[i].(expr)
- }
- return alt
-}
-
-func (p *parser) parseFormat() {
- for p.tok != token.EOF {
- pos := p.pos
-
- name, isIdent := p.parseRuleName()
- switch p.tok {
- case token.STRING:
- // package declaration
- importPath := p.parseString()
-
- // add package declaration
- if !isIdent {
- p.error(pos, "illegal package name: "+name)
- } else if _, found := p.packs[name]; !found {
- p.packs[name] = importPath
- } else {
- p.error(pos, "package already declared: "+name)
- }
-
- case token.ASSIGN:
- // format rule
- p.next()
- x := p.parseExpression()
-
- // add rule
- if _, found := p.rules[name]; !found {
- p.rules[name] = x
- } else {
- p.error(pos, "format rule already declared: "+name)
- }
-
- default:
- p.errorExpected(p.pos, "package declaration or format rule")
- p.next() // make progress in any case
- }
-
- if p.tok == token.SEMICOLON {
- p.next()
- } else {
- break
- }
- }
- p.expect(token.EOF)
-}
-
-func remap(p *parser, name string) string {
- i := strings.Index(name, ".")
- if i >= 0 {
- packageName, suffix := name[0:i], name[i:]
- // lookup package
- if importPath, found := p.packs[packageName]; found {
- name = importPath + suffix
- } else {
- var invalidPos token.Position
- p.Error(invalidPos, "package not declared: "+packageName)
- }
- }
- return name
-}
-
-// Parse parses a set of format productions from source src. Custom
-// formatters may be provided via a map of formatter functions. If
-// there are no errors, the result is a Format and the error is nil.
-// Otherwise the format is nil and a non-empty ErrorList is returned.
-//
-func Parse(fset *token.FileSet, filename string, src []byte, fmap FormatterMap) (Format, os.Error) {
- // parse source
- var p parser
- p.init(fset, filename, src)
- p.parseFormat()
-
- // add custom formatters, if any
- for name, form := range fmap {
- name = remap(&p, name)
- if _, found := p.rules[name]; !found {
- p.rules[name] = &custom{name, form}
- } else {
- var invalidPos token.Position
- p.Error(invalidPos, "formatter already declared: "+name)
- }
- }
-
- return p.rules, p.GetError(scanner.NoMultiples)
-}
diff --git a/libgo/go/exp/ebnf/ebnf.go b/libgo/go/exp/ebnf/ebnf.go
new file mode 100644
index 00000000000..2ec7f00800d
--- /dev/null
+++ b/libgo/go/exp/ebnf/ebnf.go
@@ -0,0 +1,269 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package ebnf is a library for EBNF grammars. The input is text ([]byte)
+// satisfying the following grammar (represented itself in EBNF):
+//
+// Production = name "=" [ Expression ] "." .
+// Expression = Alternative { "|" Alternative } .
+// Alternative = Term { Term } .
+// Term = name | token [ "…" token ] | Group | Option | Repetition .
+// Group = "(" Expression ")" .
+// Option = "[" Expression "]" .
+// Repetition = "{" Expression "}" .
+//
+// A name is a Go identifier, a token is a Go string, and comments
+// and white space follow the same rules as for the Go language.
+// Production names starting with an uppercase Unicode letter denote
+// non-terminal productions (i.e., productions which allow white-space
+// and comments between tokens); all other production names denote
+// lexical productions.
+//
+package ebnf
+
+import (
+ "fmt"
+ "os"
+ "scanner"
+ "unicode"
+ "utf8"
+)
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+type errorList []os.Error
+
+func (list errorList) Error() os.Error {
+ if len(list) == 0 {
+ return nil
+ }
+ return list
+}
+
+func (list errorList) String() string {
+ switch len(list) {
+ case 0:
+ return "no errors"
+ case 1:
+ return list[0].String()
+ }
+ return fmt.Sprintf("%s (and %d more errors)", list[0], len(list)-1)
+}
+
+func newError(pos scanner.Position, msg string) os.Error {
+ return os.NewError(fmt.Sprintf("%s: %s", pos, msg))
+}
+
+// ----------------------------------------------------------------------------
+// Internal representation
+
+type (
+ // An Expression node represents a production expression.
+ Expression interface {
+ // Pos is the position of the first character of the syntactic construct
+ Pos() scanner.Position
+ }
+
+ // An Alternative node represents a non-empty list of alternative expressions.
+ Alternative []Expression // x | y | z
+
+ // A Sequence node represents a non-empty list of sequential expressions.
+ Sequence []Expression // x y z
+
+ // A Name node represents a production name.
+ Name struct {
+ StringPos scanner.Position
+ String string
+ }
+
+ // A Token node represents a literal.
+ Token struct {
+ StringPos scanner.Position
+ String string
+ }
+
+ // A List node represents a range of characters.
+ Range struct {
+ Begin, End *Token // begin ... end
+ }
+
+ // A Group node represents a grouped expression.
+ Group struct {
+ Lparen scanner.Position
+ Body Expression // (body)
+ }
+
+ // An Option node represents an optional expression.
+ Option struct {
+ Lbrack scanner.Position
+ Body Expression // [body]
+ }
+
+ // A Repetition node represents a repeated expression.
+ Repetition struct {
+ Lbrace scanner.Position
+ Body Expression // {body}
+ }
+
+ // A Production node represents an EBNF production.
+ Production struct {
+ Name *Name
+ Expr Expression
+ }
+
+ // A Bad node stands for pieces of source code that lead to a parse error.
+ Bad struct {
+ TokPos scanner.Position
+ Error string // parser error message
+ }
+
+ // A Grammar is a set of EBNF productions. The map
+ // is indexed by production name.
+ //
+ Grammar map[string]*Production
+)
+
+func (x Alternative) Pos() scanner.Position { return x[0].Pos() } // the parser always generates non-empty Alternative
+func (x Sequence) Pos() scanner.Position { return x[0].Pos() } // the parser always generates non-empty Sequences
+func (x *Name) Pos() scanner.Position { return x.StringPos }
+func (x *Token) Pos() scanner.Position { return x.StringPos }
+func (x *Range) Pos() scanner.Position { return x.Begin.Pos() }
+func (x *Group) Pos() scanner.Position { return x.Lparen }
+func (x *Option) Pos() scanner.Position { return x.Lbrack }
+func (x *Repetition) Pos() scanner.Position { return x.Lbrace }
+func (x *Production) Pos() scanner.Position { return x.Name.Pos() }
+func (x *Bad) Pos() scanner.Position { return x.TokPos }
+
+// ----------------------------------------------------------------------------
+// Grammar verification
+
+func isLexical(name string) bool {
+ ch, _ := utf8.DecodeRuneInString(name)
+ return !unicode.IsUpper(ch)
+}
+
+type verifier struct {
+ errors errorList
+ worklist []*Production
+ reached Grammar // set of productions reached from (and including) the root production
+ grammar Grammar
+}
+
+func (v *verifier) error(pos scanner.Position, msg string) {
+ v.errors = append(v.errors, newError(pos, msg))
+}
+
+func (v *verifier) push(prod *Production) {
+ name := prod.Name.String
+ if _, found := v.reached[name]; !found {
+ v.worklist = append(v.worklist, prod)
+ v.reached[name] = prod
+ }
+}
+
+func (v *verifier) verifyChar(x *Token) int {
+ s := x.String
+ if utf8.RuneCountInString(s) != 1 {
+ v.error(x.Pos(), "single char expected, found "+s)
+ return 0
+ }
+ ch, _ := utf8.DecodeRuneInString(s)
+ return ch
+}
+
+func (v *verifier) verifyExpr(expr Expression, lexical bool) {
+ switch x := expr.(type) {
+ case nil:
+ // empty expression
+ case Alternative:
+ for _, e := range x {
+ v.verifyExpr(e, lexical)
+ }
+ case Sequence:
+ for _, e := range x {
+ v.verifyExpr(e, lexical)
+ }
+ case *Name:
+ // a production with this name must exist;
+ // add it to the worklist if not yet processed
+ if prod, found := v.grammar[x.String]; found {
+ v.push(prod)
+ } else {
+ v.error(x.Pos(), "missing production "+x.String)
+ }
+ // within a lexical production references
+ // to non-lexical productions are invalid
+ if lexical && !isLexical(x.String) {
+ v.error(x.Pos(), "reference to non-lexical production "+x.String)
+ }
+ case *Token:
+ // nothing to do for now
+ case *Range:
+ i := v.verifyChar(x.Begin)
+ j := v.verifyChar(x.End)
+ if i >= j {
+ v.error(x.Pos(), "decreasing character range")
+ }
+ case *Group:
+ v.verifyExpr(x.Body, lexical)
+ case *Option:
+ v.verifyExpr(x.Body, lexical)
+ case *Repetition:
+ v.verifyExpr(x.Body, lexical)
+ case *Bad:
+ v.error(x.Pos(), x.Error)
+ default:
+ panic(fmt.Sprintf("internal error: unexpected type %T", expr))
+ }
+}
+
+func (v *verifier) verify(grammar Grammar, start string) {
+ // find root production
+ root, found := grammar[start]
+ if !found {
+ var noPos scanner.Position
+ v.error(noPos, "no start production "+start)
+ return
+ }
+
+ // initialize verifier
+ v.worklist = v.worklist[0:0]
+ v.reached = make(Grammar)
+ v.grammar = grammar
+
+ // work through the worklist
+ v.push(root)
+ for {
+ n := len(v.worklist) - 1
+ if n < 0 {
+ break
+ }
+ prod := v.worklist[n]
+ v.worklist = v.worklist[0:n]
+ v.verifyExpr(prod.Expr, isLexical(prod.Name.String))
+ }
+
+ // check if all productions were reached
+ if len(v.reached) < len(v.grammar) {
+ for name, prod := range v.grammar {
+ if _, found := v.reached[name]; !found {
+ v.error(prod.Pos(), name+" is unreachable")
+ }
+ }
+ }
+}
+
+// Verify checks that:
+// - all productions used are defined
+// - all productions defined are used when beginning at start
+// - lexical productions refer only to other lexical productions
+//
+// Position information is interpreted relative to the file set fset.
+//
+func Verify(grammar Grammar, start string) os.Error {
+ var v verifier
+ v.verify(grammar, start)
+ return v.errors.Error()
+}
diff --git a/libgo/go/exp/ebnf/ebnf_test.go b/libgo/go/exp/ebnf/ebnf_test.go
new file mode 100644
index 00000000000..8cfd6b9c370
--- /dev/null
+++ b/libgo/go/exp/ebnf/ebnf_test.go
@@ -0,0 +1,71 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ebnf
+
+import (
+ "bytes"
+ "testing"
+)
+
+var goodGrammars = []string{
+ `Program = .`,
+
+ `Program = foo .
+ foo = "foo" .`,
+
+ `Program = "a" | "b" "c" .`,
+
+ `Program = "a" … "z" .`,
+
+ `Program = Song .
+ Song = { Note } .
+ Note = Do | (Re | Mi | Fa | So | La) | Ti .
+ Do = "c" .
+ Re = "d" .
+ Mi = "e" .
+ Fa = "f" .
+ So = "g" .
+ La = "a" .
+ Ti = ti .
+ ti = "b" .`,
+}
+
+var badGrammars = []string{
+ `Program = | .`,
+ `Program = | b .`,
+ `Program = a … b .`,
+ `Program = "a" … .`,
+ `Program = … "b" .`,
+ `Program = () .`,
+ `Program = [] .`,
+ `Program = {} .`,
+}
+
+func checkGood(t *testing.T, src string) {
+ grammar, err := Parse("", bytes.NewBuffer([]byte(src)))
+ if err != nil {
+ t.Errorf("Parse(%s) failed: %v", src, err)
+ return
+ }
+ if err = Verify(grammar, "Program"); err != nil {
+ t.Errorf("Verify(%s) failed: %v", src, err)
+ }
+}
+
+func checkBad(t *testing.T, src string) {
+ _, err := Parse("", bytes.NewBuffer([]byte(src)))
+ if err == nil {
+ t.Errorf("Parse(%s) should have failed", src)
+ }
+}
+
+func TestGrammars(t *testing.T) {
+ for _, src := range goodGrammars {
+ checkGood(t, src)
+ }
+ for _, src := range badGrammars {
+ checkBad(t, src)
+ }
+}
diff --git a/libgo/go/exp/ebnf/parser.go b/libgo/go/exp/ebnf/parser.go
new file mode 100644
index 00000000000..2dbbefb7519
--- /dev/null
+++ b/libgo/go/exp/ebnf/parser.go
@@ -0,0 +1,191 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ebnf
+
+import (
+ "io"
+ "os"
+ "scanner"
+ "strconv"
+)
+
+type parser struct {
+ errors errorList
+ scanner scanner.Scanner
+ pos scanner.Position // token position
+ tok int // one token look-ahead
+ lit string // token literal
+}
+
+func (p *parser) next() {
+ p.tok = p.scanner.Scan()
+ p.pos = p.scanner.Position
+ p.lit = p.scanner.TokenText()
+}
+
+func (p *parser) error(pos scanner.Position, msg string) {
+ p.errors = append(p.errors, newError(pos, msg))
+}
+
+func (p *parser) errorExpected(pos scanner.Position, msg string) {
+ msg = `expected "` + msg + `"`
+ if pos.Offset == p.pos.Offset {
+ // the error happened at the current position;
+ // make the error message more specific
+ msg += ", found " + scanner.TokenString(p.tok)
+ if p.tok < 0 {
+ msg += " " + p.lit
+ }
+ }
+ p.error(pos, msg)
+}
+
+func (p *parser) expect(tok int) scanner.Position {
+ pos := p.pos
+ if p.tok != tok {
+ p.errorExpected(pos, scanner.TokenString(tok))
+ }
+ p.next() // make progress in any case
+ return pos
+}
+
+func (p *parser) parseIdentifier() *Name {
+ pos := p.pos
+ name := p.lit
+ p.expect(scanner.Ident)
+ return &Name{pos, name}
+}
+
+func (p *parser) parseToken() *Token {
+ pos := p.pos
+ value := ""
+ if p.tok == scanner.String {
+ value, _ = strconv.Unquote(p.lit)
+ // Unquote may fail with an error, but only if the scanner found
+ // an illegal string in the first place. In this case the error
+ // has already been reported.
+ p.next()
+ } else {
+ p.expect(scanner.String)
+ }
+ return &Token{pos, value}
+}
+
+// ParseTerm returns nil if no term was found.
+func (p *parser) parseTerm() (x Expression) {
+ pos := p.pos
+
+ switch p.tok {
+ case scanner.Ident:
+ x = p.parseIdentifier()
+
+ case scanner.String:
+ tok := p.parseToken()
+ x = tok
+ const ellipsis = '…' // U+2026, the horizontal ellipsis character
+ if p.tok == ellipsis {
+ p.next()
+ x = &Range{tok, p.parseToken()}
+ }
+
+ case '(':
+ p.next()
+ x = &Group{pos, p.parseExpression()}
+ p.expect(')')
+
+ case '[':
+ p.next()
+ x = &Option{pos, p.parseExpression()}
+ p.expect(']')
+
+ case '{':
+ p.next()
+ x = &Repetition{pos, p.parseExpression()}
+ p.expect('}')
+ }
+
+ return x
+}
+
+func (p *parser) parseSequence() Expression {
+ var list Sequence
+
+ for x := p.parseTerm(); x != nil; x = p.parseTerm() {
+ list = append(list, x)
+ }
+
+ // no need for a sequence if list.Len() < 2
+ switch len(list) {
+ case 0:
+ p.errorExpected(p.pos, "term")
+ return &Bad{p.pos, "term expected"}
+ case 1:
+ return list[0]
+ }
+
+ return list
+}
+
+func (p *parser) parseExpression() Expression {
+ var list Alternative
+
+ for {
+ list = append(list, p.parseSequence())
+ if p.tok != '|' {
+ break
+ }
+ p.next()
+ }
+ // len(list) > 0
+
+ // no need for an Alternative node if list.Len() < 2
+ if len(list) == 1 {
+ return list[0]
+ }
+
+ return list
+}
+
+func (p *parser) parseProduction() *Production {
+ name := p.parseIdentifier()
+ p.expect('=')
+ var expr Expression
+ if p.tok != '.' {
+ expr = p.parseExpression()
+ }
+ p.expect('.')
+ return &Production{name, expr}
+}
+
+func (p *parser) parse(filename string, src io.Reader) Grammar {
+ p.scanner.Init(src)
+ p.scanner.Filename = filename
+ p.next() // initializes pos, tok, lit
+
+ grammar := make(Grammar)
+ for p.tok != scanner.EOF {
+ prod := p.parseProduction()
+ name := prod.Name.String
+ if _, found := grammar[name]; !found {
+ grammar[name] = prod
+ } else {
+ p.error(prod.Pos(), name+" declared already")
+ }
+ }
+
+ return grammar
+}
+
+// Parse parses a set of EBNF productions from source src.
+// It returns a set of productions. Errors are reported
+// for incorrect syntax and if a production is declared
+// more than once; the filename is used only for error
+// positions.
+//
+func Parse(filename string, src io.Reader) (Grammar, os.Error) {
+ var p parser
+ grammar := p.parse(filename, src)
+ return grammar, p.errors.Error()
+}
diff --git a/libgo/go/exp/ebnflint/doc.go b/libgo/go/exp/ebnflint/doc.go
new file mode 100644
index 00000000000..f35976eea73
--- /dev/null
+++ b/libgo/go/exp/ebnflint/doc.go
@@ -0,0 +1,22 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+
+Ebnflint verifies that EBNF productions are consistent and gramatically correct.
+It reads them from an HTML document such as the Go specification.
+
+Grammar productions are grouped in boxes demarcated by the HTML elements
+ <pre class="ebnf">
+ </pre>
+
+
+Usage:
+ ebnflint [--start production] [file]
+
+The --start flag specifies the name of the start production for
+the grammar; it defaults to "Start".
+
+*/
+package documentation
diff --git a/libgo/go/exp/ebnflint/ebnflint.go b/libgo/go/exp/ebnflint/ebnflint.go
new file mode 100644
index 00000000000..c827716c44c
--- /dev/null
+++ b/libgo/go/exp/ebnflint/ebnflint.go
@@ -0,0 +1,109 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "exp/ebnf"
+ "flag"
+ "fmt"
+ "go/scanner"
+ "go/token"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+)
+
+var fset = token.NewFileSet()
+var start = flag.String("start", "Start", "name of start production")
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: ebnflint [flags] [filename]\n")
+ flag.PrintDefaults()
+ os.Exit(1)
+}
+
+// Markers around EBNF sections in .html files
+var (
+ open = []byte(`<pre class="ebnf">`)
+ close = []byte(`</pre>`)
+)
+
+func report(err os.Error) {
+ scanner.PrintError(os.Stderr, err)
+ os.Exit(1)
+}
+
+func extractEBNF(src []byte) []byte {
+ var buf bytes.Buffer
+
+ for {
+ // i = beginning of EBNF text
+ i := bytes.Index(src, open)
+ if i < 0 {
+ break // no EBNF found - we are done
+ }
+ i += len(open)
+
+ // write as many newlines as found in the excluded text
+ // to maintain correct line numbers in error messages
+ for _, ch := range src[0:i] {
+ if ch == '\n' {
+ buf.WriteByte('\n')
+ }
+ }
+
+ // j = end of EBNF text (or end of source)
+ j := bytes.Index(src[i:], close) // close marker
+ if j < 0 {
+ j = len(src) - i
+ }
+ j += i
+
+ // copy EBNF text
+ buf.Write(src[i:j])
+
+ // advance
+ src = src[j:]
+ }
+
+ return buf.Bytes()
+}
+
+func main() {
+ flag.Parse()
+
+ var (
+ filename string
+ src []byte
+ err os.Error
+ )
+ switch flag.NArg() {
+ case 0:
+ filename = "<stdin>"
+ src, err = ioutil.ReadAll(os.Stdin)
+ case 1:
+ filename = flag.Arg(0)
+ src, err = ioutil.ReadFile(filename)
+ default:
+ usage()
+ }
+ if err != nil {
+ report(err)
+ }
+
+ if filepath.Ext(filename) == ".html" || bytes.Index(src, open) >= 0 {
+ src = extractEBNF(src)
+ }
+
+ grammar, err := ebnf.Parse(filename, bytes.NewBuffer(src))
+ if err != nil {
+ report(err)
+ }
+
+ if err = ebnf.Verify(grammar, *start); err != nil {
+ report(err)
+ }
+}
diff --git a/libgo/go/exp/gotype/doc.go b/libgo/go/exp/gotype/doc.go
new file mode 100644
index 00000000000..1aa0faa751a
--- /dev/null
+++ b/libgo/go/exp/gotype/doc.go
@@ -0,0 +1,61 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+The gotype command does syntactic and semantic analysis of Go files
+and packages similar to the analysis performed by the front-end of
+a Go compiler. Errors are reported if the analysis fails; otherwise
+gotype is quiet (unless -v is set).
+
+Without a list of paths, gotype processes the standard input, which must
+be the source of a single package file.
+
+Given a list of file names, each file must be a source file belonging to
+the same package unless the package name is explicitly specified with the
+-p flag.
+
+Given a directory name, gotype collects all .go files in the directory
+and processes them as if they were provided as an explicit list of file
+names. Each directory is processed independently. Files starting with .
+or not ending in .go are ignored.
+
+Usage:
+ gotype [flags] [path ...]
+
+The flags are:
+ -e
+ Print all (including spurious) errors.
+ -p pkgName
+ Process only those files in package pkgName.
+ -r
+ Recursively process subdirectories.
+ -v
+ Verbose mode.
+
+Debugging flags:
+ -ast
+ Print AST (disables concurrent parsing).
+ -trace
+ Print parse trace (disables concurrent parsing).
+
+
+Examples
+
+To check the files file.go, old.saved, and .ignored:
+
+ gotype file.go old.saved .ignored
+
+To check all .go files belonging to package main in the current directory
+and recursively in all subdirectories:
+
+ gotype -p main -r .
+
+To verify the output of a pipe:
+
+ echo "package foo" | gotype
+
+*/
+package documentation
+
+// BUG(gri): At the moment, only single-file scope analysis is performed.
diff --git a/libgo/go/exp/gotype/gotype.go b/libgo/go/exp/gotype/gotype.go
new file mode 100644
index 00000000000..91992130077
--- /dev/null
+++ b/libgo/go/exp/gotype/gotype.go
@@ -0,0 +1,192 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "exp/types"
+ "flag"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/scanner"
+ "go/token"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+)
+
+var (
+ // main operation modes
+ pkgName = flag.String("p", "", "process only those files in package pkgName")
+ recursive = flag.Bool("r", false, "recursively process subdirectories")
+ verbose = flag.Bool("v", false, "verbose mode")
+ allErrors = flag.Bool("e", false, "print all (including spurious) errors")
+
+ // debugging support
+ printTrace = flag.Bool("trace", false, "print parse trace")
+ printAST = flag.Bool("ast", false, "print AST")
+)
+
+var exitCode = 0
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: gotype [flags] [path ...]\n")
+ flag.PrintDefaults()
+ os.Exit(2)
+}
+
+func report(err os.Error) {
+ scanner.PrintError(os.Stderr, err)
+ exitCode = 2
+}
+
+// parse returns the AST for the Go source src.
+// The filename is for error reporting only.
+// The result is nil if there were errors or if
+// the file does not belong to the -p package.
+func parse(fset *token.FileSet, filename string, src []byte) *ast.File {
+ if *verbose {
+ fmt.Println(filename)
+ }
+
+ // ignore files with different package name
+ if *pkgName != "" {
+ file, err := parser.ParseFile(fset, filename, src, parser.PackageClauseOnly)
+ if err != nil {
+ report(err)
+ return nil
+ }
+ if file.Name.Name != *pkgName {
+ if *verbose {
+ fmt.Printf("\tignored (package %s)\n", file.Name.Name)
+ }
+ return nil
+ }
+ }
+
+ // parse entire file
+ mode := parser.DeclarationErrors
+ if *allErrors {
+ mode |= parser.SpuriousErrors
+ }
+ if *printTrace {
+ mode |= parser.Trace
+ }
+ file, err := parser.ParseFile(fset, filename, src, mode)
+ if err != nil {
+ report(err)
+ return nil
+ }
+ if *printAST {
+ ast.Print(fset, file)
+ }
+
+ return file
+}
+
+func parseStdin(fset *token.FileSet) (files map[string]*ast.File) {
+ files = make(map[string]*ast.File)
+ src, err := ioutil.ReadAll(os.Stdin)
+ if err != nil {
+ report(err)
+ return
+ }
+ const filename = "<standard input>"
+ if file := parse(fset, filename, src); file != nil {
+ files[filename] = file
+ }
+ return
+}
+
+func parseFiles(fset *token.FileSet, filenames []string) (files map[string]*ast.File) {
+ files = make(map[string]*ast.File)
+ for _, filename := range filenames {
+ src, err := ioutil.ReadFile(filename)
+ if err != nil {
+ report(err)
+ continue
+ }
+ if file := parse(fset, filename, src); file != nil {
+ if files[filename] != nil {
+ report(os.NewError(fmt.Sprintf("%q: duplicate file", filename)))
+ continue
+ }
+ files[filename] = file
+ }
+ }
+ return
+}
+
+func isGoFilename(filename string) bool {
+ // ignore non-Go files
+ return !strings.HasPrefix(filename, ".") && strings.HasSuffix(filename, ".go")
+}
+
+func processDirectory(dirname string) {
+ f, err := os.Open(dirname)
+ if err != nil {
+ report(err)
+ return
+ }
+ filenames, err := f.Readdirnames(-1)
+ f.Close()
+ if err != nil {
+ report(err)
+ // continue since filenames may not be empty
+ }
+ for i, filename := range filenames {
+ filenames[i] = filepath.Join(dirname, filename)
+ }
+ processFiles(filenames, false)
+}
+
+func processFiles(filenames []string, allFiles bool) {
+ i := 0
+ for _, filename := range filenames {
+ switch info, err := os.Stat(filename); {
+ case err != nil:
+ report(err)
+ case info.IsRegular():
+ if allFiles || isGoFilename(info.Name) {
+ filenames[i] = filename
+ i++
+ }
+ case info.IsDirectory():
+ if allFiles || *recursive {
+ processDirectory(filename)
+ }
+ }
+ }
+ fset := token.NewFileSet()
+ processPackage(fset, parseFiles(fset, filenames[0:i]))
+}
+
+func processPackage(fset *token.FileSet, files map[string]*ast.File) {
+ // make a package (resolve all identifiers)
+ pkg, err := ast.NewPackage(fset, files, types.GcImporter, types.Universe)
+ if err != nil {
+ report(err)
+ return
+ }
+ _, err = types.Check(fset, pkg)
+ if err != nil {
+ report(err)
+ }
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+
+ if flag.NArg() == 0 {
+ fset := token.NewFileSet()
+ processPackage(fset, parseStdin(fset))
+ } else {
+ processFiles(flag.Args(), true)
+ }
+
+ os.Exit(exitCode)
+}
diff --git a/libgo/go/exp/gotype/gotype_test.go b/libgo/go/exp/gotype/gotype_test.go
new file mode 100644
index 00000000000..8732d4c5aa8
--- /dev/null
+++ b/libgo/go/exp/gotype/gotype_test.go
@@ -0,0 +1,49 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "path/filepath"
+ "runtime"
+ "testing"
+)
+
+func runTest(t *testing.T, path, pkg string) {
+ exitCode = 0
+ *pkgName = pkg
+ *recursive = false
+
+ if pkg == "" {
+ processFiles([]string{path}, true)
+ } else {
+ processDirectory(path)
+ }
+
+ if exitCode != 0 {
+ t.Errorf("processing %s failed: exitCode = %d", path, exitCode)
+ }
+}
+
+var tests = []struct {
+ path string
+ pkg string
+}{
+ // individual files
+ {"testdata/test1.go", ""},
+
+ // directories
+ {filepath.Join(runtime.GOROOT(), "src/pkg/go/ast"), "ast"},
+ {filepath.Join(runtime.GOROOT(), "src/pkg/go/doc"), "doc"},
+ {filepath.Join(runtime.GOROOT(), "src/pkg/go/token"), "scanner"},
+ {filepath.Join(runtime.GOROOT(), "src/pkg/go/scanner"), "scanner"},
+ {filepath.Join(runtime.GOROOT(), "src/pkg/go/parser"), "parser"},
+ {filepath.Join(runtime.GOROOT(), "src/pkg/exp/types"), "types"},
+}
+
+func Test(t *testing.T) {
+ for _, test := range tests {
+ runTest(t, test.path, test.pkg)
+ }
+}
diff --git a/libgo/go/exp/gotype/testdata/test1.go b/libgo/go/exp/gotype/testdata/test1.go
new file mode 100644
index 00000000000..a3298e6e5fe
--- /dev/null
+++ b/libgo/go/exp/gotype/testdata/test1.go
@@ -0,0 +1,23 @@
+package p
+
+func _() {
+ // the scope of a local type declaration starts immediately after the type name
+ type T struct{ _ *T }
+}
+
+func _(x interface{}) {
+ // the variable defined by a TypeSwitchGuard is declared in each TypeCaseClause
+ switch t := x.(type) {
+ case int:
+ _ = t
+ case float32:
+ _ = t
+ default:
+ _ = t
+ }
+
+ // the variable defined by a TypeSwitchGuard must not conflict with other
+ // variables declared in the initial simple statement
+ switch t := 0; t := x.(type) {
+ }
+}
diff --git a/libgo/go/exp/gui/x11/auth.go b/libgo/go/exp/gui/x11/auth.go
index d48936ac178..732f103d669 100644
--- a/libgo/go/exp/gui/x11/auth.go
+++ b/libgo/go/exp/gui/x11/auth.go
@@ -65,23 +65,25 @@ func readAuth(displayStr string) (name, data string, err os.Error) {
return
}
for {
- family, err := readU16BE(br, b[0:2])
+ var family uint16
+ var addr, disp, name0, data0 string
+ family, err = readU16BE(br, b[0:2])
if err != nil {
return
}
- addr, err := readStr(br, b[0:])
+ addr, err = readStr(br, b[0:])
if err != nil {
return
}
- disp, err := readStr(br, b[0:])
+ disp, err = readStr(br, b[0:])
if err != nil {
return
}
- name0, err := readStr(br, b[0:])
+ name0, err = readStr(br, b[0:])
if err != nil {
return
}
- data0, err := readStr(br, b[0:])
+ data0, err = readStr(br, b[0:])
if err != nil {
return
}
diff --git a/libgo/go/exp/gui/x11/conn.go b/libgo/go/exp/gui/x11/conn.go
index 1d237816abf..bf94bcaabb4 100644
--- a/libgo/go/exp/gui/x11/conn.go
+++ b/libgo/go/exp/gui/x11/conn.go
@@ -391,12 +391,13 @@ func checkPixmapFormats(r io.Reader, b []byte, n int) (agree bool, err os.Error)
// checkDepths checks that we have an agreeable X Depth (i.e. one that has an agreeable X VisualType).
func checkDepths(r io.Reader, b []byte, n int, visual uint32) (agree bool, err os.Error) {
for i := 0; i < n; i++ {
- depth, err := readU16LE(r, b)
+ var depth, visualsLen uint16
+ depth, err = readU16LE(r, b)
if err != nil {
return
}
depth &= 0xff
- visualsLen, err := readU16LE(r, b)
+ visualsLen, err = readU16LE(r, b)
if err != nil {
return
}
@@ -408,11 +409,11 @@ func checkDepths(r io.Reader, b []byte, n int, visual uint32) (agree bool, err o
for j := 0; j < int(visualsLen); j++ {
// Read 24 bytes: visual(4), class(1), bits per rgb value(1), colormap entries(2),
// red mask(4), green mask(4), blue mask(4), padding(4).
- v, err := readU32LE(r, b)
- _, err = readU32LE(r, b)
- rm, err := readU32LE(r, b)
- gm, err := readU32LE(r, b)
- bm, err := readU32LE(r, b)
+ v, _ := readU32LE(r, b)
+ _, _ = readU32LE(r, b)
+ rm, _ := readU32LE(r, b)
+ gm, _ := readU32LE(r, b)
+ bm, _ := readU32LE(r, b)
_, err = readU32LE(r, b)
if err != nil {
return
@@ -428,7 +429,8 @@ func checkDepths(r io.Reader, b []byte, n int, visual uint32) (agree bool, err o
// checkScreens checks that we have an agreeable X Screen.
func checkScreens(r io.Reader, b []byte, n int) (root, visual uint32, err os.Error) {
for i := 0; i < n; i++ {
- root0, err := readU32LE(r, b)
+ var root0, visual0, x uint32
+ root0, err = readU32LE(r, b)
if err != nil {
return
}
@@ -438,17 +440,18 @@ func checkScreens(r io.Reader, b []byte, n int) (root, visual uint32, err os.Err
if err != nil {
return
}
- visual0, err := readU32LE(r, b)
+ visual0, err = readU32LE(r, b)
if err != nil {
return
}
// Next 4 bytes: backing stores, save unders, root depth, allowed depths length.
- x, err := readU32LE(r, b)
+ x, err = readU32LE(r, b)
if err != nil {
return
}
nDepths := int(x >> 24)
- agree, err := checkDepths(r, b, nDepths, visual0)
+ var agree bool
+ agree, err = checkDepths(r, b, nDepths, visual0)
if err != nil {
return
}
@@ -618,7 +621,7 @@ func NewWindowDisplay(display string) (gui.Window, os.Error) {
return nil, err
}
- c.img = image.NewRGBA(windowWidth, windowHeight)
+ c.img = image.NewRGBA(image.Rect(0, 0, windowWidth, windowHeight))
c.eventc = make(chan interface{}, 16)
c.flush = make(chan bool, 1)
go c.readSocket()
diff --git a/libgo/go/exp/norm/composition.go b/libgo/go/exp/norm/composition.go
index b2d2abaf63b..1d722230d6f 100644
--- a/libgo/go/exp/norm/composition.go
+++ b/libgo/go/exp/norm/composition.go
@@ -7,27 +7,46 @@ package norm
import "utf8"
const (
- maxCombiningChars = 30 + 2 // +2 to hold CGJ and Hangul overflow.
+ maxCombiningChars = 30
+ maxBufferSize = maxCombiningChars + 2 // +1 to hold starter +1 to hold CGJ
maxBackRunes = maxCombiningChars - 1
maxNFCExpansion = 3 // NFC(0x1D160)
maxNFKCExpansion = 18 // NFKC(0xFDFA)
- maxRuneSizeInDecomp = 4
- // Need to multiply by 2 as we don't reuse byte buffer space for recombining.
- maxByteBufferSize = 2 * maxRuneSizeInDecomp * maxCombiningChars // 256
+ maxByteBufferSize = utf8.UTFMax * maxBufferSize // 128
)
// reorderBuffer is used to normalize a single segment. Characters inserted with
-// insert() are decomposed and reordered based on CCC. The compose() method can
+// insert are decomposed and reordered based on CCC. The compose method can
// be used to recombine characters. Note that the byte buffer does not hold
// the UTF-8 characters in order. Only the rune array is maintained in sorted
-// order. flush() writes the resulting segment to a byte array.
+// order. flush writes the resulting segment to a byte array.
type reorderBuffer struct {
- rune [maxCombiningChars]runeInfo // Per character info.
- byte [maxByteBufferSize]byte // UTF-8 buffer. Referenced by runeInfo.pos.
- nrune int // Number of runeInfos.
- nbyte uint8 // Number or bytes.
+ rune [maxBufferSize]runeInfo // Per character info.
+ byte [maxByteBufferSize]byte // UTF-8 buffer. Referenced by runeInfo.pos.
+ nrune int // Number of runeInfos.
+ nbyte uint8 // Number or bytes.
f formInfo
+
+ src input
+ nsrc int
+ srcBytes inputBytes
+ srcString inputString
+ tmpBytes inputBytes
+}
+
+func (rb *reorderBuffer) init(f Form, src []byte) {
+ rb.f = *formTable[f]
+ rb.srcBytes = inputBytes(src)
+ rb.src = &rb.srcBytes
+ rb.nsrc = len(src)
+}
+
+func (rb *reorderBuffer) initString(f Form, src string) {
+ rb.f = *formTable[f]
+ rb.srcString = inputString(src)
+ rb.src = &rb.srcString
+ rb.nsrc = len(src)
}
// reset discards all characters from the buffer.
@@ -49,10 +68,10 @@ func (rb *reorderBuffer) flush(out []byte) []byte {
// insertOrdered inserts a rune in the buffer, ordered by Canonical Combining Class.
// It returns false if the buffer is not large enough to hold the rune.
-// It is used internally by insert.
+// It is used internally by insert and insertString only.
func (rb *reorderBuffer) insertOrdered(info runeInfo) bool {
n := rb.nrune
- if n >= maxCombiningChars {
+ if n >= maxCombiningChars+1 {
return false
}
b := rb.rune[:]
@@ -68,7 +87,7 @@ func (rb *reorderBuffer) insertOrdered(info runeInfo) bool {
}
rb.nrune += 1
pos := uint8(rb.nbyte)
- rb.nbyte += info.size
+ rb.nbyte += utf8.UTFMax
info.pos = pos
b[n] = info
return true
@@ -76,53 +95,32 @@ func (rb *reorderBuffer) insertOrdered(info runeInfo) bool {
// insert inserts the given rune in the buffer ordered by CCC.
// It returns true if the buffer was large enough to hold the decomposed rune.
-func (rb *reorderBuffer) insert(src []byte, info runeInfo) bool {
- if info.size == 3 && isHangul(src) {
- rune, _ := utf8.DecodeRune(src)
- return rb.decomposeHangul(uint32(rune))
- }
- pos := rb.nbyte
- if info.flags.hasDecomposition() {
- dcomp := rb.f.decompose(src)
- for i := 0; i < len(dcomp); i += int(info.size) {
- info = rb.f.info(dcomp[i:])
- if !rb.insertOrdered(info) {
- return false
- }
- }
- copy(rb.byte[pos:], dcomp)
- } else {
- if !rb.insertOrdered(info) {
- return false
+func (rb *reorderBuffer) insert(src input, i int, info runeInfo) bool {
+ if info.size == 3 {
+ if rune := src.hangul(i); rune != 0 {
+ return rb.decomposeHangul(uint32(rune))
}
- copy(rb.byte[pos:], src[:info.size])
}
- return true
-}
-
-// insertString inserts the given rune in the buffer ordered by CCC.
-// It returns true if the buffer was large enough to hold the decomposed rune.
-func (rb *reorderBuffer) insertString(src string, info runeInfo) bool {
- if info.size == 3 && isHangulString(src) {
- rune, _ := utf8.DecodeRuneInString(src)
- return rb.decomposeHangul(uint32(rune))
- }
- pos := rb.nbyte
- dcomp := rb.f.decomposeString(src)
- dn := len(dcomp)
- if dn != 0 {
- for i := 0; i < dn; i += int(info.size) {
- info = rb.f.info(dcomp[i:])
+ if info.flags.hasDecomposition() {
+ dcomp := rb.f.decompose(src, i)
+ rb.tmpBytes = inputBytes(dcomp)
+ for i := 0; i < len(dcomp); {
+ info = rb.f.info(&rb.tmpBytes, i)
+ pos := rb.nbyte
if !rb.insertOrdered(info) {
return false
}
+ end := i + int(info.size)
+ copy(rb.byte[pos:], dcomp[i:end])
+ i = end
}
- copy(rb.byte[pos:], dcomp)
} else {
+ // insertOrder changes nbyte
+ pos := rb.nbyte
if !rb.insertOrdered(info) {
return false
}
- copy(rb.byte[pos:], src[:info.size])
+ src.copySlice(rb.byte[pos:], i, i+int(info.size))
}
return true
}
@@ -131,17 +129,16 @@ func (rb *reorderBuffer) insertString(src string, info runeInfo) bool {
func (rb *reorderBuffer) appendRune(rune uint32) {
bn := rb.nbyte
sz := utf8.EncodeRune(rb.byte[bn:], int(rune))
- rb.nbyte += uint8(sz)
+ rb.nbyte += utf8.UTFMax
rb.rune[rb.nrune] = runeInfo{bn, uint8(sz), 0, 0}
rb.nrune++
}
// assignRune sets a rune at position pos. It is used for Hangul and recomposition.
func (rb *reorderBuffer) assignRune(pos int, rune uint32) {
- bn := rb.nbyte
+ bn := rb.rune[pos].pos
sz := utf8.EncodeRune(rb.byte[bn:], int(rune))
rb.rune[pos] = runeInfo{bn, uint8(sz), 0, 0}
- rb.nbyte += uint8(sz)
}
// runeAt returns the rune at position n. It is used for Hangul and recomposition.
@@ -259,11 +256,10 @@ func (rb *reorderBuffer) decomposeHangul(rune uint32) bool {
// combineHangul algorithmically combines Jamo character components into Hangul.
// See http://unicode.org/reports/tr15/#Hangul for details on combining Hangul.
-func (rb *reorderBuffer) combineHangul() {
- k := 1
+func (rb *reorderBuffer) combineHangul(s, i, k int) {
b := rb.rune[:]
bn := rb.nrune
- for s, i := 0, 1; i < bn; i++ {
+ for ; i < bn; i++ {
cccB := b[k-1].ccc
cccC := b[i].ccc
if cccB == 0 {
@@ -305,14 +301,17 @@ func (rb *reorderBuffer) compose() {
// blocked from S if and only if there is some character B between S
// and C, and either B is a starter or it has the same or higher
// combining class as C."
+ bn := rb.nrune
+ if bn == 0 {
+ return
+ }
k := 1
b := rb.rune[:]
- bn := rb.nrune
for s, i := 0, 1; i < bn; i++ {
if isJamoVT(rb.bytesAt(i)) {
// Redo from start in Hangul mode. Necessary to support
// U+320E..U+321E in NFKC mode.
- rb.combineHangul()
+ rb.combineHangul(s, i, k)
return
}
ii := b[i]
diff --git a/libgo/go/exp/norm/composition_test.go b/libgo/go/exp/norm/composition_test.go
index 195a0c1e8e9..ce9caaff160 100644
--- a/libgo/go/exp/norm/composition_test.go
+++ b/libgo/go/exp/norm/composition_test.go
@@ -15,21 +15,19 @@ type TestCase struct {
type insertFunc func(rb *reorderBuffer, rune int) bool
func insert(rb *reorderBuffer, rune int) bool {
- b := []byte(string(rune))
- return rb.insert(b, rb.f.info(b))
+ src := inputString(string(rune))
+ return rb.insert(src, 0, rb.f.info(src, 0))
}
-func insertString(rb *reorderBuffer, rune int) bool {
- s := string(rune)
- return rb.insertString(s, rb.f.infoString(s))
-}
-
-func runTests(t *testing.T, name string, rb *reorderBuffer, f insertFunc, tests []TestCase) {
+func runTests(t *testing.T, name string, fm Form, f insertFunc, tests []TestCase) {
+ rb := reorderBuffer{}
+ rb.init(fm, nil)
for i, test := range tests {
rb.reset()
for j, rune := range test.in {
b := []byte(string(rune))
- if !rb.insert(b, rb.f.info(b)) {
+ src := inputBytes(b)
+ if !rb.insert(src, 0, rb.f.info(src, 0)) {
t.Errorf("%s:%d: insert failed for rune %d", name, i, j)
}
}
@@ -50,7 +48,8 @@ func runTests(t *testing.T, name string, rb *reorderBuffer, f insertFunc, tests
}
func TestFlush(t *testing.T) {
- rb := &reorderBuffer{f: *formTable[NFC]}
+ rb := reorderBuffer{}
+ rb.init(NFC, nil)
out := make([]byte, 0)
out = rb.flush(out)
@@ -59,7 +58,7 @@ func TestFlush(t *testing.T) {
}
for _, r := range []int("world!") {
- insert(rb, r)
+ insert(&rb, r)
}
out = []byte("Hello ")
@@ -88,13 +87,7 @@ var insertTests = []TestCase{
}
func TestInsert(t *testing.T) {
- rb := &reorderBuffer{f: *formTable[NFD]}
- runTests(t, "TestInsert", rb, insert, insertTests)
-}
-
-func TestInsertString(t *testing.T) {
- rb := &reorderBuffer{f: *formTable[NFD]}
- runTests(t, "TestInsertString", rb, insertString, insertTests)
+ runTests(t, "TestInsert", NFD, insert, insertTests)
}
var decompositionNFDTest = []TestCase{
@@ -113,11 +106,8 @@ var decompositionNFKDTest = []TestCase{
}
func TestDecomposition(t *testing.T) {
- rb := &reorderBuffer{}
- rb.f = *formTable[NFD]
- runTests(t, "TestDecompositionNFD", rb, insert, decompositionNFDTest)
- rb.f = *formTable[NFKD]
- runTests(t, "TestDecompositionNFKD", rb, insert, decompositionNFKDTest)
+ runTests(t, "TestDecompositionNFD", NFD, insert, decompositionNFDTest)
+ runTests(t, "TestDecompositionNFKD", NFKD, insert, decompositionNFKDTest)
}
var compositionTest = []TestCase{
@@ -133,6 +123,5 @@ var compositionTest = []TestCase{
}
func TestComposition(t *testing.T) {
- rb := &reorderBuffer{f: *formTable[NFC]}
- runTests(t, "TestComposition", rb, insert, compositionTest)
+ runTests(t, "TestComposition", NFC, insert, compositionTest)
}
diff --git a/libgo/go/exp/norm/forminfo.go b/libgo/go/exp/norm/forminfo.go
index ee3edb8ea7d..d06a00602f8 100644
--- a/libgo/go/exp/norm/forminfo.go
+++ b/libgo/go/exp/norm/forminfo.go
@@ -15,10 +15,8 @@ type runeInfo struct {
// functions dispatchable per form
type boundaryFunc func(f *formInfo, info runeInfo) bool
-type lookupFunc func(b []byte) runeInfo
-type lookupFuncString func(s string) runeInfo
-type decompFunc func(b []byte) []byte
-type decompFuncString func(s string) []byte
+type lookupFunc func(b input, i int) runeInfo
+type decompFunc func(b input, i int) []byte
// formInfo holds Form-specific functions and tables.
type formInfo struct {
@@ -26,12 +24,10 @@ type formInfo struct {
composing, compatibility bool // form type
- decompose decompFunc
- decomposeString decompFuncString
- info lookupFunc
- infoString lookupFuncString
- boundaryBefore boundaryFunc
- boundaryAfter boundaryFunc
+ decompose decompFunc
+ info lookupFunc
+ boundaryBefore boundaryFunc
+ boundaryAfter boundaryFunc
}
var formTable []*formInfo
@@ -46,14 +42,10 @@ func init() {
if Form(i) == NFKD || Form(i) == NFKC {
f.compatibility = true
f.decompose = decomposeNFKC
- f.decomposeString = decomposeStringNFKC
f.info = lookupInfoNFKC
- f.infoString = lookupInfoStringNFKC
} else {
f.decompose = decomposeNFC
- f.decomposeString = decomposeStringNFC
f.info = lookupInfoNFC
- f.infoString = lookupInfoStringNFC
}
if Form(i) == NFC || Form(i) == NFKC {
f.composing = true
@@ -77,7 +69,7 @@ func decompBoundary(f *formInfo, info runeInfo) bool {
}
func compBoundaryBefore(f *formInfo, info runeInfo) bool {
- if info.ccc == 0 && info.flags.isYesC() {
+ if info.ccc == 0 && !info.flags.combinesBackward() {
return true
}
// We assume that the CCC of the first character in a decomposition
@@ -89,9 +81,7 @@ func compBoundaryBefore(f *formInfo, info runeInfo) bool {
func compBoundaryAfter(f *formInfo, info runeInfo) bool {
// This misses values where the last char in a decomposition is a
// boundary such as Hangul with JamoT.
- // TODO(mpvl): verify this does not lead to segments that do
- // not fit in the reorderBuffer.
- return info.flags.isInert()
+ return info.isInert()
}
// We pack quick check data in 4 bits:
@@ -110,41 +100,30 @@ func (i qcInfo) isNoC() bool { return i&0x6 == 0x2 }
func (i qcInfo) isMaybe() bool { return i&0x4 != 0 }
func (i qcInfo) isYesD() bool { return i&0x1 == 0 }
func (i qcInfo) isNoD() bool { return i&0x1 != 0 }
-func (i qcInfo) isInert() bool { return i&0xf == 0 }
func (i qcInfo) combinesForward() bool { return i&0x8 != 0 }
func (i qcInfo) combinesBackward() bool { return i&0x4 != 0 } // == isMaybe
func (i qcInfo) hasDecomposition() bool { return i&0x1 != 0 } // == isNoD
+func (r runeInfo) isInert() bool {
+ return r.flags&0xf == 0 && r.ccc == 0
+}
+
// Wrappers for tables.go
// The 16-bit value of the decompostion tries is an index into a byte
// array of UTF-8 decomposition sequences. The first byte is the number
// of bytes in the decomposition (excluding this length byte). The actual
// sequence starts at the offset+1.
-func decomposeNFC(b []byte) []byte {
- p := nfcDecompTrie.lookupUnsafe(b)
- n := decomps[p]
- p++
- return decomps[p : p+uint16(n)]
-}
-
-func decomposeNFKC(b []byte) []byte {
- p := nfkcDecompTrie.lookupUnsafe(b)
- n := decomps[p]
- p++
- return decomps[p : p+uint16(n)]
-}
-
-func decomposeStringNFC(s string) []byte {
- p := nfcDecompTrie.lookupStringUnsafe(s)
+func decomposeNFC(s input, i int) []byte {
+ p := s.decomposeNFC(i)
n := decomps[p]
p++
return decomps[p : p+uint16(n)]
}
-func decomposeStringNFKC(s string) []byte {
- p := nfkcDecompTrie.lookupStringUnsafe(s)
+func decomposeNFKC(s input, i int) []byte {
+ p := s.decomposeNFKC(i)
n := decomps[p]
p++
return decomps[p : p+uint16(n)]
@@ -167,22 +146,12 @@ func combine(a, b uint32) uint32 {
// 0..7 CCC value.
// 8..11 qcInfo for NFC/NFD
// 12..15 qcInfo for NFKC/NFKD
-func lookupInfoNFC(b []byte) runeInfo {
- v, sz := charInfoTrie.lookup(b)
+func lookupInfoNFC(b input, i int) runeInfo {
+ v, sz := b.charinfo(i)
return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 8)}
}
-func lookupInfoStringNFC(s string) runeInfo {
- v, sz := charInfoTrie.lookupString(s)
- return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 8)}
-}
-
-func lookupInfoNFKC(b []byte) runeInfo {
- v, sz := charInfoTrie.lookup(b)
- return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 12)}
-}
-
-func lookupInfoStringNFKC(s string) runeInfo {
- v, sz := charInfoTrie.lookupString(s)
+func lookupInfoNFKC(b input, i int) runeInfo {
+ v, sz := b.charinfo(i)
return runeInfo{0, uint8(sz), uint8(v), qcInfo(v >> 12)}
}
diff --git a/libgo/go/exp/norm/input.go b/libgo/go/exp/norm/input.go
new file mode 100644
index 00000000000..12360a8fda1
--- /dev/null
+++ b/libgo/go/exp/norm/input.go
@@ -0,0 +1,107 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import "utf8"
+
+type input interface {
+ skipASCII(p int) int
+ skipNonStarter() int
+ appendSlice(buf []byte, s, e int) []byte
+ copySlice(buf []byte, s, e int)
+ charinfo(p int) (uint16, int)
+ decomposeNFC(p int) uint16
+ decomposeNFKC(p int) uint16
+ hangul(p int) uint32
+}
+
+type inputString string
+
+func (s inputString) skipASCII(p int) int {
+ for ; p < len(s) && s[p] < utf8.RuneSelf; p++ {
+ }
+ return p
+}
+
+func (s inputString) skipNonStarter() int {
+ p := 0
+ for ; p < len(s) && !utf8.RuneStart(s[p]); p++ {
+ }
+ return p
+}
+
+func (s inputString) appendSlice(buf []byte, b, e int) []byte {
+ for i := b; i < e; i++ {
+ buf = append(buf, s[i])
+ }
+ return buf
+}
+
+func (s inputString) copySlice(buf []byte, b, e int) {
+ copy(buf, s[b:e])
+}
+
+func (s inputString) charinfo(p int) (uint16, int) {
+ return charInfoTrie.lookupString(string(s[p:]))
+}
+
+func (s inputString) decomposeNFC(p int) uint16 {
+ return nfcDecompTrie.lookupStringUnsafe(string(s[p:]))
+}
+
+func (s inputString) decomposeNFKC(p int) uint16 {
+ return nfkcDecompTrie.lookupStringUnsafe(string(s[p:]))
+}
+
+func (s inputString) hangul(p int) uint32 {
+ if !isHangulString(string(s[p:])) {
+ return 0
+ }
+ rune, _ := utf8.DecodeRuneInString(string(s[p:]))
+ return uint32(rune)
+}
+
+type inputBytes []byte
+
+func (s inputBytes) skipASCII(p int) int {
+ for ; p < len(s) && s[p] < utf8.RuneSelf; p++ {
+ }
+ return p
+}
+
+func (s inputBytes) skipNonStarter() int {
+ p := 0
+ for ; p < len(s) && !utf8.RuneStart(s[p]); p++ {
+ }
+ return p
+}
+
+func (s inputBytes) appendSlice(buf []byte, b, e int) []byte {
+ return append(buf, s[b:e]...)
+}
+
+func (s inputBytes) copySlice(buf []byte, b, e int) {
+ copy(buf, s[b:e])
+}
+
+func (s inputBytes) charinfo(p int) (uint16, int) {
+ return charInfoTrie.lookup(s[p:])
+}
+
+func (s inputBytes) decomposeNFC(p int) uint16 {
+ return nfcDecompTrie.lookupUnsafe(s[p:])
+}
+
+func (s inputBytes) decomposeNFKC(p int) uint16 {
+ return nfkcDecompTrie.lookupUnsafe(s[p:])
+}
+
+func (s inputBytes) hangul(p int) uint32 {
+ if !isHangul(s[p:]) {
+ return 0
+ }
+ rune, _ := utf8.DecodeRune(s[p:])
+ return uint32(rune)
+}
diff --git a/libgo/go/exp/norm/maketables.go b/libgo/go/exp/norm/maketables.go
index e3e5700a64e..14718c5cd22 100644
--- a/libgo/go/exp/norm/maketables.go
+++ b/libgo/go/exp/norm/maketables.go
@@ -515,9 +515,13 @@ func completeCharFields(form int) {
f.quickCheck[MComposed] = QCNo
case (i & 0xffff00) == JamoLBase:
f.quickCheck[MComposed] = QCYes
+ if JamoLBase <= i && i < JamoLEnd {
+ f.combinesForward = true
+ }
if JamoVBase <= i && i < JamoVEnd {
f.quickCheck[MComposed] = QCMaybe
f.combinesBackward = true
+ f.combinesForward = true
}
if JamoTBase <= i && i < JamoTEnd {
f.quickCheck[MComposed] = QCMaybe
@@ -562,7 +566,7 @@ func makeEntry(f *FormInfo) uint16 {
case QCMaybe:
e |= 0x6
default:
- log.Fatalf("Illegal quickcheck value %d.", f.quickCheck[MComposed])
+ log.Fatalf("Illegal quickcheck value %v.", f.quickCheck[MComposed])
}
return e
}
diff --git a/libgo/go/exp/norm/maketesttables.go b/libgo/go/exp/norm/maketesttables.go
index c5f6a64368d..fdcc114be23 100644
--- a/libgo/go/exp/norm/maketesttables.go
+++ b/libgo/go/exp/norm/maketesttables.go
@@ -21,6 +21,7 @@ var testRunes = []int{
0x80, 0x100, 0x7FF, // 2-byte sequences
0x800, 0x999, 0xFFFF, // 3-byte sequences
0x10000, 0x10101, 0x10FFFF, // 4-byte sequences
+ 0x200, 0x201, 0x202, 0x210, 0x215, // five entries in one sparse block
}
const fileHeader = `// Generated by running
diff --git a/libgo/go/exp/norm/normalize.go b/libgo/go/exp/norm/normalize.go
index e9d18dd9ea9..391bc4184f2 100644
--- a/libgo/go/exp/norm/normalize.go
+++ b/libgo/go/exp/norm/normalize.go
@@ -5,6 +5,8 @@
// Package norm contains types and functions for normalizing Unicode strings.
package norm
+import "utf8"
+
// A Form denotes a canonical representation of Unicode code points.
// The Unicode-defined normalization and equivalence forms are:
//
@@ -32,68 +34,431 @@ const (
// Bytes returns f(b). May return b if f(b) = b.
func (f Form) Bytes(b []byte) []byte {
- panic("not implemented")
+ n := f.QuickSpan(b)
+ if n == len(b) {
+ return b
+ }
+ out := make([]byte, n, len(b))
+ copy(out, b[0:n])
+ return f.Append(out, b[n:]...)
}
// String returns f(s).
func (f Form) String(s string) string {
- panic("not implemented")
+ n := f.QuickSpanString(s)
+ if n == len(s) {
+ return s
+ }
+ out := make([]byte, 0, len(s))
+ copy(out, s[0:n])
+ return string(f.AppendString(out, s[n:]))
}
// IsNormal returns true if b == f(b).
func (f Form) IsNormal(b []byte) bool {
- panic("not implemented")
+ rb := reorderBuffer{}
+ rb.init(f, b)
+ bp := quickSpan(&rb, 0)
+ if bp == len(b) {
+ return true
+ }
+ for bp < len(b) {
+ decomposeSegment(&rb, bp)
+ if rb.f.composing {
+ rb.compose()
+ }
+ for i := 0; i < rb.nrune; i++ {
+ info := rb.rune[i]
+ if bp+int(info.size) > len(b) {
+ return false
+ }
+ p := info.pos
+ pe := p + info.size
+ for ; p < pe; p++ {
+ if b[bp] != rb.byte[p] {
+ return false
+ }
+ bp++
+ }
+ }
+ rb.reset()
+ bp = quickSpan(&rb, bp)
+ }
+ return true
}
// IsNormalString returns true if s == f(s).
func (f Form) IsNormalString(s string) bool {
- panic("not implemented")
+ rb := reorderBuffer{}
+ rb.initString(f, s)
+ bp := quickSpan(&rb, 0)
+ if bp == len(s) {
+ return true
+ }
+ for bp < len(s) {
+ decomposeSegment(&rb, bp)
+ if rb.f.composing {
+ rb.compose()
+ }
+ for i := 0; i < rb.nrune; i++ {
+ info := rb.rune[i]
+ if bp+int(info.size) > len(s) {
+ return false
+ }
+ p := info.pos
+ pe := p + info.size
+ for ; p < pe; p++ {
+ if s[bp] != rb.byte[p] {
+ return false
+ }
+ bp++
+ }
+ }
+ rb.reset()
+ bp = quickSpan(&rb, bp)
+ }
+ return true
+}
+
+// patchTail fixes a case where a rune may be incorrectly normalized
+// if it is followed by illegal continuation bytes. It returns the
+// patched buffer and the number of trailing continuation bytes that
+// have been dropped.
+func patchTail(rb *reorderBuffer, buf []byte) ([]byte, int) {
+ info, p := lastRuneStart(&rb.f, buf)
+ if p == -1 || info.size == 0 {
+ return buf, 0
+ }
+ end := p + int(info.size)
+ extra := len(buf) - end
+ if extra > 0 {
+ buf = decomposeToLastBoundary(rb, buf[:end])
+ if rb.f.composing {
+ rb.compose()
+ }
+ return rb.flush(buf), extra
+ }
+ return buf, 0
+}
+
+func appendQuick(rb *reorderBuffer, dst []byte, i int) ([]byte, int) {
+ if rb.nsrc == i {
+ return dst, i
+ }
+ end := quickSpan(rb, i)
+ return rb.src.appendSlice(dst, i, end), end
}
// Append returns f(append(out, b...)).
-// The buffer out must be empty or equal to f(out).
-func (f Form) Append(out, b []byte) []byte {
- panic("not implemented")
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) Append(out []byte, src ...byte) []byte {
+ if len(src) == 0 {
+ return out
+ }
+ rb := reorderBuffer{}
+ rb.init(f, src)
+ return doAppend(&rb, out)
+}
+
+func doAppend(rb *reorderBuffer, out []byte) []byte {
+ src, n := rb.src, rb.nsrc
+ doMerge := len(out) > 0
+ p := 0
+ if p = src.skipNonStarter(); p > 0 {
+ // Move leading non-starters to destination.
+ out = src.appendSlice(out, 0, p)
+ buf, ndropped := patchTail(rb, out)
+ if ndropped > 0 {
+ out = src.appendSlice(buf, p-ndropped, p)
+ doMerge = false // no need to merge, ends with illegal UTF-8
+ } else {
+ out = decomposeToLastBoundary(rb, buf) // force decomposition
+ }
+ }
+ fd := &rb.f
+ if doMerge {
+ var info runeInfo
+ if p < n {
+ info = fd.info(src, p)
+ if p == 0 && !fd.boundaryBefore(fd, info) {
+ out = decomposeToLastBoundary(rb, out)
+ }
+ }
+ if info.size == 0 || fd.boundaryBefore(fd, info) {
+ if fd.composing {
+ rb.compose()
+ }
+ out = rb.flush(out)
+ if info.size == 0 {
+ // Append incomplete UTF-8 encoding.
+ return src.appendSlice(out, p, n)
+ }
+ }
+ }
+ if rb.nrune == 0 {
+ out, p = appendQuick(rb, out, p)
+ }
+ for p < n {
+ p = decomposeSegment(rb, p)
+ if fd.composing {
+ rb.compose()
+ }
+ out = rb.flush(out)
+ out, p = appendQuick(rb, out, p)
+ }
+ return out
}
// AppendString returns f(append(out, []byte(s))).
-// The buffer out must be empty or equal to f(out).
-func (f Form) AppendString(out []byte, s string) []byte {
- panic("not implemented")
+// The buffer out must be nil, empty, or equal to f(out).
+func (f Form) AppendString(out []byte, src string) []byte {
+ if len(src) == 0 {
+ return out
+ }
+ rb := reorderBuffer{}
+ rb.initString(f, src)
+ return doAppend(&rb, out)
}
// QuickSpan returns a boundary n such that b[0:n] == f(b[0:n]).
// It is not guaranteed to return the largest such n.
func (f Form) QuickSpan(b []byte) int {
- panic("not implemented")
+ rb := reorderBuffer{}
+ rb.init(f, b)
+ return quickSpan(&rb, 0)
+}
+
+func quickSpan(rb *reorderBuffer, i int) int {
+ var lastCC uint8
+ var nc int
+ lastSegStart := i
+ src, n := rb.src, rb.nsrc
+ for i < n {
+ if j := src.skipASCII(i); i != j {
+ i = j
+ lastSegStart = i - 1
+ lastCC = 0
+ nc = 0
+ continue
+ }
+ info := rb.f.info(src, i)
+ if info.size == 0 {
+ // include incomplete runes
+ return n
+ }
+ cc := info.ccc
+ if rb.f.composing {
+ if !info.flags.isYesC() {
+ break
+ }
+ } else {
+ if !info.flags.isYesD() {
+ break
+ }
+ }
+ if cc == 0 {
+ lastSegStart = i
+ nc = 0
+ } else {
+ if nc >= maxCombiningChars {
+ lastSegStart = i
+ lastCC = cc
+ nc = 1
+ } else {
+ if lastCC > cc {
+ return lastSegStart
+ }
+ nc++
+ }
+ }
+ lastCC = cc
+ i += int(info.size)
+ }
+ if i == n {
+ return n
+ }
+ if rb.f.composing {
+ return lastSegStart
+ }
+ return i
}
// QuickSpanString returns a boundary n such that b[0:n] == f(s[0:n]).
// It is not guaranteed to return the largest such n.
func (f Form) QuickSpanString(s string) int {
- panic("not implemented")
+ rb := reorderBuffer{}
+ rb.initString(f, s)
+ return quickSpan(&rb, 0)
+}
+
+// FirstBoundary returns the position i of the first boundary in b
+// or -1 if b contains no boundary.
+func (f Form) FirstBoundary(b []byte) int {
+ rb := reorderBuffer{}
+ rb.init(f, b)
+ return firstBoundary(&rb)
+}
+
+func firstBoundary(rb *reorderBuffer) int {
+ src, nsrc := rb.src, rb.nsrc
+ i := src.skipNonStarter()
+ if i >= nsrc {
+ return -1
+ }
+ fd := &rb.f
+ info := fd.info(src, i)
+ for n := 0; info.size != 0 && !fd.boundaryBefore(fd, info); {
+ i += int(info.size)
+ if n++; n >= maxCombiningChars {
+ return i
+ }
+ if i >= nsrc {
+ if !fd.boundaryAfter(fd, info) {
+ return -1
+ }
+ return nsrc
+ }
+ info = fd.info(src, i)
+ }
+ if info.size == 0 {
+ return -1
+ }
+ return i
+}
+
+// FirstBoundaryInString returns the position i of the first boundary in s
+// or -1 if s contains no boundary.
+func (f Form) FirstBoundaryInString(s string) int {
+ rb := reorderBuffer{}
+ rb.initString(f, s)
+ return firstBoundary(&rb)
+}
+
+// LastBoundary returns the position i of the last boundary in b
+// or -1 if b contains no boundary.
+func (f Form) LastBoundary(b []byte) int {
+ return lastBoundary(formTable[f], b)
}
-// FirstBoundary returns the position i of the first boundary in b.
-// It returns len(b), false if b contains no boundaries.
-func (f Form) FirstBoundary(b []byte) (i int, ok bool) {
- panic("not implemented")
+func lastBoundary(fd *formInfo, b []byte) int {
+ i := len(b)
+ info, p := lastRuneStart(fd, b)
+ if p == -1 {
+ return -1
+ }
+ if info.size == 0 { // ends with incomplete rune
+ if p == 0 { // starts wtih incomplete rune
+ return -1
+ }
+ i = p
+ info, p = lastRuneStart(fd, b[:i])
+ if p == -1 { // incomplete UTF-8 encoding or non-starter bytes without a starter
+ return i
+ }
+ }
+ if p+int(info.size) != i { // trailing non-starter bytes: illegal UTF-8
+ return i
+ }
+ if fd.boundaryAfter(fd, info) {
+ return i
+ }
+ i = p
+ for n := 0; i >= 0 && !fd.boundaryBefore(fd, info); {
+ info, p = lastRuneStart(fd, b[:i])
+ if n++; n >= maxCombiningChars {
+ return len(b)
+ }
+ if p+int(info.size) != i {
+ if p == -1 { // no boundary found
+ return -1
+ }
+ return i // boundary after an illegal UTF-8 encoding
+ }
+ i = p
+ }
+ return i
}
-// FirstBoundaryInString return the position i of the first boundary in s.
-// It returns len(s), false if s contains no boundaries.
-func (f Form) FirstBoundaryInString(s string) (i int, ok bool) {
- panic("not implemented")
+// decomposeSegment scans the first segment in src into rb.
+// It returns the number of bytes consumed from src.
+// TODO(mpvl): consider inserting U+034f (Combining Grapheme Joiner)
+// when we detect a sequence of 30+ non-starter chars.
+func decomposeSegment(rb *reorderBuffer, sp int) int {
+ // Force one character to be consumed.
+ info := rb.f.info(rb.src, sp)
+ if info.size == 0 {
+ return 0
+ }
+ for rb.insert(rb.src, sp, info) {
+ sp += int(info.size)
+ if sp >= rb.nsrc {
+ break
+ }
+ info = rb.f.info(rb.src, sp)
+ bound := rb.f.boundaryBefore(&rb.f, info)
+ if bound || info.size == 0 {
+ break
+ }
+ }
+ return sp
}
-// LastBoundaryIn returns the position i of the last boundary in b.
-// It returns 0, false if b contains no boundary.
-func (f Form) LastBoundary(b []byte) (i int, ok bool) {
- panic("not implemented")
+// lastRuneStart returns the runeInfo and position of the last
+// rune in buf or the zero runeInfo and -1 if no rune was found.
+func lastRuneStart(fd *formInfo, buf []byte) (runeInfo, int) {
+ p := len(buf) - 1
+ for ; p >= 0 && !utf8.RuneStart(buf[p]); p-- {
+ }
+ if p < 0 {
+ return runeInfo{0, 0, 0, 0}, -1
+ }
+ return fd.info(inputBytes(buf), p), p
}
-// LastBoundaryInString returns the position i of the last boundary in s.
-// It returns 0, false if s contains no boundary.
-func (f Form) LastBoundaryInString(s string) (i int, ok bool) {
- panic("not implemented")
+// decomposeToLastBoundary finds an open segment at the end of the buffer
+// and scans it into rb. Returns the buffer minus the last segment.
+func decomposeToLastBoundary(rb *reorderBuffer, buf []byte) []byte {
+ fd := &rb.f
+ info, i := lastRuneStart(fd, buf)
+ if int(info.size) != len(buf)-i {
+ // illegal trailing continuation bytes
+ return buf
+ }
+ if rb.f.boundaryAfter(fd, info) {
+ return buf
+ }
+ var add [maxBackRunes]runeInfo // stores runeInfo in reverse order
+ add[0] = info
+ padd := 1
+ n := 1
+ p := len(buf) - int(info.size)
+ for ; p >= 0 && !rb.f.boundaryBefore(fd, info); p -= int(info.size) {
+ info, i = lastRuneStart(fd, buf[:p])
+ if int(info.size) != p-i {
+ break
+ }
+ // Check that decomposition doesn't result in overflow.
+ if info.flags.hasDecomposition() {
+ dcomp := rb.f.decompose(inputBytes(buf), p-int(info.size))
+ for i := 0; i < len(dcomp); {
+ inf := rb.f.info(inputBytes(dcomp), i)
+ i += int(inf.size)
+ n++
+ }
+ } else {
+ n++
+ }
+ if n > maxBackRunes {
+ break
+ }
+ add[padd] = info
+ padd++
+ }
+ pp := p
+ for padd--; padd >= 0; padd-- {
+ info = add[padd]
+ rb.insert(inputBytes(buf), pp, info)
+ pp += int(info.size)
+ }
+ return buf[:p]
}
diff --git a/libgo/go/exp/norm/normalize_test.go b/libgo/go/exp/norm/normalize_test.go
new file mode 100644
index 00000000000..e374edf0abb
--- /dev/null
+++ b/libgo/go/exp/norm/normalize_test.go
@@ -0,0 +1,644 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import (
+ "strings"
+ "testing"
+)
+
+type PositionTest struct {
+ input string
+ pos int
+ buffer string // expected contents of reorderBuffer, if applicable
+}
+
+type positionFunc func(rb *reorderBuffer, s string) int
+
+func runPosTests(t *testing.T, name string, f Form, fn positionFunc, tests []PositionTest) {
+ rb := reorderBuffer{}
+ rb.init(f, nil)
+ for i, test := range tests {
+ rb.reset()
+ rb.src = inputString(test.input)
+ rb.nsrc = len(test.input)
+ pos := fn(&rb, test.input)
+ if pos != test.pos {
+ t.Errorf("%s:%d: position is %d; want %d", name, i, pos, test.pos)
+ }
+ runes := []int(test.buffer)
+ if rb.nrune != len(runes) {
+ t.Errorf("%s:%d: reorder buffer lenght is %d; want %d", name, i, rb.nrune, len(runes))
+ continue
+ }
+ for j, want := range runes {
+ found := int(rb.runeAt(j))
+ if found != want {
+ t.Errorf("%s:%d: rune at %d is %U; want %U", name, i, j, found, want)
+ }
+ }
+ }
+}
+
+var decomposeSegmentTests = []PositionTest{
+ // illegal runes
+ {"\xC0", 0, ""},
+ {"\u00E0\x80", 2, "\u0061\u0300"},
+ // starter
+ {"a", 1, "a"},
+ {"ab", 1, "a"},
+ // starter + composing
+ {"a\u0300", 3, "a\u0300"},
+ {"a\u0300b", 3, "a\u0300"},
+ // with decomposition
+ {"\u00C0", 2, "A\u0300"},
+ {"\u00C0b", 2, "A\u0300"},
+ // long
+ {strings.Repeat("\u0300", 31), 62, strings.Repeat("\u0300", 31)},
+ // ends with incomplete UTF-8 encoding
+ {"\xCC", 0, ""},
+ {"\u0300\xCC", 2, "\u0300"},
+}
+
+func decomposeSegmentF(rb *reorderBuffer, s string) int {
+ rb.src = inputString(s)
+ rb.nsrc = len(s)
+ return decomposeSegment(rb, 0)
+}
+
+func TestDecomposeSegment(t *testing.T) {
+ runPosTests(t, "TestDecomposeSegment", NFC, decomposeSegmentF, decomposeSegmentTests)
+}
+
+var firstBoundaryTests = []PositionTest{
+ // no boundary
+ {"", -1, ""},
+ {"\u0300", -1, ""},
+ {"\x80\x80", -1, ""},
+ // illegal runes
+ {"\xff", 0, ""},
+ {"\u0300\xff", 2, ""},
+ {"\u0300\xc0\x80\x80", 2, ""},
+ // boundaries
+ {"a", 0, ""},
+ {"\u0300a", 2, ""},
+ // Hangul
+ {"\u1103\u1161", 0, ""},
+ {"\u110B\u1173\u11B7", 0, ""},
+ {"\u1161\u110B\u1173\u11B7", 3, ""},
+ {"\u1173\u11B7\u1103\u1161", 6, ""},
+ // too many combining characters.
+ {strings.Repeat("\u0300", maxCombiningChars-1), -1, ""},
+ {strings.Repeat("\u0300", maxCombiningChars), 60, ""},
+ {strings.Repeat("\u0300", maxCombiningChars+1), 60, ""},
+}
+
+func firstBoundaryF(rb *reorderBuffer, s string) int {
+ return rb.f.form.FirstBoundary([]byte(s))
+}
+
+func firstBoundaryStringF(rb *reorderBuffer, s string) int {
+ return rb.f.form.FirstBoundaryInString(s)
+}
+
+func TestFirstBoundary(t *testing.T) {
+ runPosTests(t, "TestFirstBoundary", NFC, firstBoundaryF, firstBoundaryTests)
+ runPosTests(t, "TestFirstBoundaryInString", NFC, firstBoundaryStringF, firstBoundaryTests)
+}
+
+var decomposeToLastTests = []PositionTest{
+ // ends with inert character
+ {"Hello!", 6, ""},
+ {"\u0632", 2, ""},
+ {"a\u0301\u0635", 5, ""},
+ // ends with non-inert starter
+ {"a", 0, "a"},
+ {"a\u0301a", 3, "a"},
+ {"a\u0301\u03B9", 3, "\u03B9"},
+ {"a\u0327", 0, "a\u0327"},
+ // illegal runes
+ {"\xFF", 1, ""},
+ {"aa\xFF", 3, ""},
+ {"\xC0\x80\x80", 3, ""},
+ {"\xCC\x80\x80", 3, ""},
+ // ends with incomplete UTF-8 encoding
+ {"a\xCC", 2, ""},
+ // ends with combining characters
+ {"\u0300\u0301", 0, "\u0300\u0301"},
+ {"a\u0300\u0301", 0, "a\u0300\u0301"},
+ {"a\u0301\u0308", 0, "a\u0301\u0308"},
+ {"a\u0308\u0301", 0, "a\u0308\u0301"},
+ {"aaaa\u0300\u0301", 3, "a\u0300\u0301"},
+ {"\u0300a\u0300\u0301", 2, "a\u0300\u0301"},
+ {"\u00C0", 0, "A\u0300"},
+ {"a\u00C0", 1, "A\u0300"},
+ // decomposing
+ {"a\u0300\uFDC0", 3, "\u0645\u062C\u064A"},
+ {"\uFDC0" + strings.Repeat("\u0300", 26), 0, "\u0645\u062C\u064A" + strings.Repeat("\u0300", 26)},
+ // Hangul
+ {"a\u1103", 1, "\u1103"},
+ {"a\u110B", 1, "\u110B"},
+ {"a\u110B\u1173", 1, "\u110B\u1173"},
+ // See comment in composition.go:compBoundaryAfter.
+ {"a\u110B\u1173\u11B7", 1, "\u110B\u1173\u11B7"},
+ {"a\uC73C", 1, "\u110B\u1173"},
+ {"다ìŒ", 3, "\u110B\u1173\u11B7"},
+ {"다", 0, "\u1103\u1161"},
+ {"\u1103\u1161\u110B\u1173\u11B7", 6, "\u110B\u1173\u11B7"},
+ {"\u110B\u1173\u11B7\u1103\u1161", 9, "\u1103\u1161"},
+ {"다ìŒìŒ", 6, "\u110B\u1173\u11B7"},
+ {"ìŒë‹¤ë‹¤", 6, "\u1103\u1161"},
+ // buffer overflow
+ {"a" + strings.Repeat("\u0300", 30), 3, strings.Repeat("\u0300", 29)},
+ {"\uFDFA" + strings.Repeat("\u0300", 14), 3, strings.Repeat("\u0300", 14)},
+ // weird UTF-8
+ {"a\u0300\u11B7", 0, "a\u0300\u11B7"},
+}
+
+func decomposeToLast(rb *reorderBuffer, s string) int {
+ buf := decomposeToLastBoundary(rb, []byte(s))
+ return len(buf)
+}
+
+func TestDecomposeToLastBoundary(t *testing.T) {
+ runPosTests(t, "TestDecomposeToLastBoundary", NFKC, decomposeToLast, decomposeToLastTests)
+}
+
+var lastBoundaryTests = []PositionTest{
+ // ends with inert character
+ {"Hello!", 6, ""},
+ {"\u0632", 2, ""},
+ // ends with non-inert starter
+ {"a", 0, ""},
+ // illegal runes
+ {"\xff", 1, ""},
+ {"aa\xff", 3, ""},
+ {"a\xff\u0300", 1, ""},
+ {"\xc0\x80\x80", 3, ""},
+ {"\xc0\x80\x80\u0300", 3, ""},
+ // ends with incomplete UTF-8 encoding
+ {"\xCC", -1, ""},
+ {"\xE0\x80", -1, ""},
+ {"\xF0\x80\x80", -1, ""},
+ {"a\xCC", 0, ""},
+ {"\x80\xCC", 1, ""},
+ {"\xCC\xCC", 1, ""},
+ // ends with combining characters
+ {"a\u0300\u0301", 0, ""},
+ {"aaaa\u0300\u0301", 3, ""},
+ {"\u0300a\u0300\u0301", 2, ""},
+ {"\u00C0", 0, ""},
+ {"a\u00C0", 1, ""},
+ // decomposition may recombine
+ {"\u0226", 0, ""},
+ // no boundary
+ {"", -1, ""},
+ {"\u0300\u0301", -1, ""},
+ {"\u0300", -1, ""},
+ {"\x80\x80", -1, ""},
+ {"\x80\x80\u0301", -1, ""},
+ // Hangul
+ {"다ìŒ", 3, ""},
+ {"다", 0, ""},
+ {"\u1103\u1161\u110B\u1173\u11B7", 6, ""},
+ {"\u110B\u1173\u11B7\u1103\u1161", 9, ""},
+ // too many combining characters.
+ {strings.Repeat("\u0300", maxCombiningChars-1), -1, ""},
+ {strings.Repeat("\u0300", maxCombiningChars), 60, ""},
+ {strings.Repeat("\u0300", maxCombiningChars+1), 62, ""},
+}
+
+func lastBoundaryF(rb *reorderBuffer, s string) int {
+ return rb.f.form.LastBoundary([]byte(s))
+}
+
+func TestLastBoundary(t *testing.T) {
+ runPosTests(t, "TestLastBoundary", NFC, lastBoundaryF, lastBoundaryTests)
+}
+
+var quickSpanTests = []PositionTest{
+ {"", 0, ""},
+ // starters
+ {"a", 1, ""},
+ {"abc", 3, ""},
+ {"\u043Eb", 3, ""},
+ // incomplete last rune.
+ {"\xCC", 1, ""},
+ {"a\xCC", 2, ""},
+ // incorrectly ordered combining characters
+ {"\u0300\u0316", 0, ""},
+ {"\u0300\u0316cd", 0, ""},
+ // have a maximum number of combining characters.
+ {strings.Repeat("\u035D", 30) + "\u035B", 62, ""},
+ {"a" + strings.Repeat("\u035D", 30) + "\u035B", 63, ""},
+ {"ÆŸ" + strings.Repeat("\u035D", 30) + "\u035B", 64, ""},
+ {"aa" + strings.Repeat("\u035D", 30) + "\u035B", 64, ""},
+}
+
+var quickSpanNFDTests = []PositionTest{
+ // needs decomposing
+ {"\u00C0", 0, ""},
+ {"abc\u00C0", 3, ""},
+ // correctly ordered combining characters
+ {"\u0300", 2, ""},
+ {"ab\u0300", 4, ""},
+ {"ab\u0300cd", 6, ""},
+ {"\u0300cd", 4, ""},
+ {"\u0316\u0300", 4, ""},
+ {"ab\u0316\u0300", 6, ""},
+ {"ab\u0316\u0300cd", 8, ""},
+ {"ab\u0316\u0300\u00C0", 6, ""},
+ {"\u0316\u0300cd", 6, ""},
+ {"\u043E\u0308b", 5, ""},
+ // incorrectly ordered combining characters
+ {"ab\u0300\u0316", 1, ""}, // TODO(mpvl): we could skip 'b' as well.
+ {"ab\u0300\u0316cd", 1, ""},
+ // Hangul
+ {"ê°™ì€", 0, ""},
+}
+
+var quickSpanNFCTests = []PositionTest{
+ // okay composed
+ {"\u00C0", 2, ""},
+ {"abc\u00C0", 5, ""},
+ // correctly ordered combining characters
+ {"ab\u0300", 1, ""},
+ {"ab\u0300cd", 1, ""},
+ {"ab\u0316\u0300", 1, ""},
+ {"ab\u0316\u0300cd", 1, ""},
+ {"\u00C0\u035D", 4, ""},
+ // we do not special case leading combining characters
+ {"\u0300cd", 0, ""},
+ {"\u0300", 0, ""},
+ {"\u0316\u0300", 0, ""},
+ {"\u0316\u0300cd", 0, ""},
+ // incorrectly ordered combining characters
+ {"ab\u0300\u0316", 1, ""},
+ {"ab\u0300\u0316cd", 1, ""},
+ // Hangul
+ {"ê°™ì€", 6, ""},
+}
+
+func doQuickSpan(rb *reorderBuffer, s string) int {
+ return rb.f.form.QuickSpan([]byte(s))
+}
+
+func doQuickSpanString(rb *reorderBuffer, s string) int {
+ return rb.f.form.QuickSpanString(s)
+}
+
+func TestQuickSpan(t *testing.T) {
+ runPosTests(t, "TestQuickSpanNFD1", NFD, doQuickSpan, quickSpanTests)
+ runPosTests(t, "TestQuickSpanNFD2", NFD, doQuickSpan, quickSpanNFDTests)
+ runPosTests(t, "TestQuickSpanNFC1", NFC, doQuickSpan, quickSpanTests)
+ runPosTests(t, "TestQuickSpanNFC2", NFC, doQuickSpan, quickSpanNFCTests)
+
+ runPosTests(t, "TestQuickSpanStringNFD1", NFD, doQuickSpanString, quickSpanTests)
+ runPosTests(t, "TestQuickSpanStringNFD2", NFD, doQuickSpanString, quickSpanNFDTests)
+ runPosTests(t, "TestQuickSpanStringNFC1", NFC, doQuickSpanString, quickSpanTests)
+ runPosTests(t, "TestQuickSpanStringNFC2", NFC, doQuickSpanString, quickSpanNFCTests)
+}
+
+var isNormalTests = []PositionTest{
+ {"", 1, ""},
+ // illegal runes
+ {"\xff", 1, ""},
+ // starters
+ {"a", 1, ""},
+ {"abc", 1, ""},
+ {"\u043Eb", 1, ""},
+ // incorrectly ordered combining characters
+ {"\u0300\u0316", 0, ""},
+ {"ab\u0300\u0316", 0, ""},
+ {"ab\u0300\u0316cd", 0, ""},
+ {"\u0300\u0316cd", 0, ""},
+}
+var isNormalNFDTests = []PositionTest{
+ // needs decomposing
+ {"\u00C0", 0, ""},
+ {"abc\u00C0", 0, ""},
+ // correctly ordered combining characters
+ {"\u0300", 1, ""},
+ {"ab\u0300", 1, ""},
+ {"ab\u0300cd", 1, ""},
+ {"\u0300cd", 1, ""},
+ {"\u0316\u0300", 1, ""},
+ {"ab\u0316\u0300", 1, ""},
+ {"ab\u0316\u0300cd", 1, ""},
+ {"\u0316\u0300cd", 1, ""},
+ {"\u043E\u0308b", 1, ""},
+ // Hangul
+ {"ê°™ì€", 0, ""},
+}
+var isNormalNFCTests = []PositionTest{
+ // okay composed
+ {"\u00C0", 1, ""},
+ {"abc\u00C0", 1, ""},
+ // need reordering
+ {"a\u0300", 0, ""},
+ {"a\u0300cd", 0, ""},
+ {"a\u0316\u0300", 0, ""},
+ {"a\u0316\u0300cd", 0, ""},
+ // correctly ordered combining characters
+ {"ab\u0300", 1, ""},
+ {"ab\u0300cd", 1, ""},
+ {"ab\u0316\u0300", 1, ""},
+ {"ab\u0316\u0300cd", 1, ""},
+ {"\u00C0\u035D", 1, ""},
+ {"\u0300", 1, ""},
+ {"\u0316\u0300cd", 1, ""},
+ // Hangul
+ {"ê°™ì€", 1, ""},
+}
+
+func isNormalF(rb *reorderBuffer, s string) int {
+ if rb.f.form.IsNormal([]byte(s)) {
+ return 1
+ }
+ return 0
+}
+
+func TestIsNormal(t *testing.T) {
+ runPosTests(t, "TestIsNormalNFD1", NFD, isNormalF, isNormalTests)
+ runPosTests(t, "TestIsNormalNFD2", NFD, isNormalF, isNormalNFDTests)
+ runPosTests(t, "TestIsNormalNFC1", NFC, isNormalF, isNormalTests)
+ runPosTests(t, "TestIsNormalNFC2", NFC, isNormalF, isNormalNFCTests)
+}
+
+type AppendTest struct {
+ left string
+ right string
+ out string
+}
+
+type appendFunc func(f Form, out []byte, s string) []byte
+
+func runAppendTests(t *testing.T, name string, f Form, fn appendFunc, tests []AppendTest) {
+ for i, test := range tests {
+ out := []byte(test.left)
+ out = fn(f, out, test.right)
+ outs := string(out)
+ if len(outs) != len(test.out) {
+ t.Errorf("%s:%d: length is %d; want %d", name, i, len(outs), len(test.out))
+ }
+ if outs != test.out {
+ // Find first rune that differs and show context.
+ ir := []int(outs)
+ ig := []int(test.out)
+ for j := 0; j < len(ir) && j < len(ig); j++ {
+ if ir[j] == ig[j] {
+ continue
+ }
+ if j -= 3; j < 0 {
+ j = 0
+ }
+ for e := j + 7; j < e && j < len(ir) && j < len(ig); j++ {
+ t.Errorf("%s:%d: runeAt(%d) = %U; want %U", name, i, j, ir[j], ig[j])
+ }
+ break
+ }
+ }
+ }
+}
+
+var appendTests = []AppendTest{
+ // empty buffers
+ {"", "", ""},
+ {"a", "", "a"},
+ {"", "a", "a"},
+ {"", "\u0041\u0307\u0304", "\u01E0"},
+ // segment split across buffers
+ {"", "a\u0300b", "\u00E0b"},
+ {"a", "\u0300b", "\u00E0b"},
+ {"a", "\u0300\u0316", "\u00E0\u0316"},
+ {"a", "\u0316\u0300", "\u00E0\u0316"},
+ {"a", "\u0300a\u0300", "\u00E0\u00E0"},
+ {"a", "\u0300a\u0300a\u0300", "\u00E0\u00E0\u00E0"},
+ {"a", "\u0300aaa\u0300aaa\u0300", "\u00E0aa\u00E0aa\u00E0"},
+ {"a\u0300", "\u0327", "\u00E0\u0327"},
+ {"a\u0327", "\u0300", "\u00E0\u0327"},
+ {"a\u0316", "\u0300", "\u00E0\u0316"},
+ {"\u0041\u0307", "\u0304", "\u01E0"},
+ // Hangul
+ {"", "\u110B\u1173", "\uC73C"},
+ {"", "\u1103\u1161", "\uB2E4"},
+ {"", "\u110B\u1173\u11B7", "\uC74C"},
+ {"", "\u320E", "\x28\uAC00\x29"},
+ {"", "\x28\u1100\u1161\x29", "\x28\uAC00\x29"},
+ {"\u1103", "\u1161", "\uB2E4"},
+ {"\u110B", "\u1173\u11B7", "\uC74C"},
+ {"\u110B\u1173", "\u11B7", "\uC74C"},
+ {"\uC73C", "\u11B7", "\uC74C"},
+ // UTF-8 encoding split across buffers
+ {"a\xCC", "\x80", "\u00E0"},
+ {"a\xCC", "\x80b", "\u00E0b"},
+ {"a\xCC", "\x80a\u0300", "\u00E0\u00E0"},
+ {"a\xCC", "\x80\x80", "\u00E0\x80"},
+ {"a\xCC", "\x80\xCC", "\u00E0\xCC"},
+ {"a\u0316\xCC", "\x80a\u0316\u0300", "\u00E0\u0316\u00E0\u0316"},
+ // ending in incomplete UTF-8 encoding
+ {"", "\xCC", "\xCC"},
+ {"a", "\xCC", "a\xCC"},
+ {"a", "b\xCC", "ab\xCC"},
+ {"\u0226", "\xCC", "\u0226\xCC"},
+ // illegal runes
+ {"", "\x80", "\x80"},
+ {"", "\x80\x80\x80", "\x80\x80\x80"},
+ {"", "\xCC\x80\x80\x80", "\xCC\x80\x80\x80"},
+ {"", "a\x80", "a\x80"},
+ {"", "a\x80\x80\x80", "a\x80\x80\x80"},
+ {"", "a\x80\x80\x80\x80\x80\x80", "a\x80\x80\x80\x80\x80\x80"},
+ {"a", "\x80\x80\x80", "a\x80\x80\x80"},
+ // overflow
+ {"", strings.Repeat("\x80", 33), strings.Repeat("\x80", 33)},
+ {strings.Repeat("\x80", 33), "", strings.Repeat("\x80", 33)},
+ {strings.Repeat("\x80", 33), strings.Repeat("\x80", 33), strings.Repeat("\x80", 66)},
+ // overflow of combining characters
+ {strings.Repeat("\u0300", 33), "", strings.Repeat("\u0300", 33)},
+ // weird UTF-8
+ {"\u00E0\xE1", "\x86", "\u00E0\xE1\x86"},
+ {"a\u0300\u11B7", "\u0300", "\u00E0\u11B7\u0300"},
+ {"a\u0300\u11B7\u0300", "\u0300", "\u00E0\u11B7\u0300\u0300"},
+ {"\u0300", "\xF8\x80\x80\x80\x80\u0300", "\u0300\xF8\x80\x80\x80\x80\u0300"},
+ {"\u0300", "\xFC\x80\x80\x80\x80\x80\u0300", "\u0300\xFC\x80\x80\x80\x80\x80\u0300"},
+ {"\xF8\x80\x80\x80\x80\u0300", "\u0300", "\xF8\x80\x80\x80\x80\u0300\u0300"},
+ {"\xFC\x80\x80\x80\x80\x80\u0300", "\u0300", "\xFC\x80\x80\x80\x80\x80\u0300\u0300"},
+}
+
+func appendF(f Form, out []byte, s string) []byte {
+ return f.Append(out, []byte(s)...)
+}
+
+func appendStringF(f Form, out []byte, s string) []byte {
+ return f.AppendString(out, s)
+}
+
+func TestAppend(t *testing.T) {
+ runAppendTests(t, "TestAppend", NFKC, appendF, appendTests)
+ runAppendTests(t, "TestAppendString", NFKC, appendStringF, appendTests)
+}
+
+func doFormBenchmark(b *testing.B, f Form, s string) {
+ b.StopTimer()
+ in := []byte(s)
+ buf := make([]byte, 2*len(in))
+ b.SetBytes(int64(len(s)))
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ buf = f.Append(buf[0:0], in...)
+ buf = buf[0:0]
+ }
+}
+
+var ascii = strings.Repeat("There is nothing to change here! ", 500)
+
+func BenchmarkNormalizeAsciiNFC(b *testing.B) {
+ doFormBenchmark(b, NFC, ascii)
+}
+func BenchmarkNormalizeAsciiNFD(b *testing.B) {
+ doFormBenchmark(b, NFD, ascii)
+}
+func BenchmarkNormalizeAsciiNFKC(b *testing.B) {
+ doFormBenchmark(b, NFKC, ascii)
+}
+func BenchmarkNormalizeAsciiNFKD(b *testing.B) {
+ doFormBenchmark(b, NFKD, ascii)
+}
+
+func doTextBenchmark(b *testing.B, s string) {
+ b.StopTimer()
+ b.SetBytes(int64(len(s)) * 4)
+ in := []byte(s)
+ var buf = make([]byte, 0, 2*len(in))
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ NFC.Append(buf, in...)
+ NFD.Append(buf, in...)
+ NFKC.Append(buf, in...)
+ NFKD.Append(buf, in...)
+ }
+}
+
+func BenchmarkCanonicalOrdering(b *testing.B) {
+ doTextBenchmark(b, txt_canon)
+}
+func BenchmarkExtendedLatin(b *testing.B) {
+ doTextBenchmark(b, txt_vn)
+}
+func BenchmarkMiscTwoByteUtf8(b *testing.B) {
+ doTextBenchmark(b, twoByteUtf8)
+}
+func BenchmarkMiscThreeByteUtf8(b *testing.B) {
+ doTextBenchmark(b, threeByteUtf8)
+}
+func BenchmarkHangul(b *testing.B) {
+ doTextBenchmark(b, txt_kr)
+}
+func BenchmarkJapanese(b *testing.B) {
+ doTextBenchmark(b, txt_jp)
+}
+func BenchmarkChinese(b *testing.B) {
+ doTextBenchmark(b, txt_cn)
+}
+
+// Tests sampled from the Canonical ordering tests (Part 2) of
+// http://unicode.org/Public/UNIDATA/NormalizationTest.txt
+const txt_canon = `\u0061\u0315\u0300\u05AE\u0300\u0062 \u0061\u0300\u0315\u0300\u05AE\u0062
+\u0061\u0302\u0315\u0300\u05AE\u0062 \u0061\u0307\u0315\u0300\u05AE\u0062
+\u0061\u0315\u0300\u05AE\u030A\u0062 \u0061\u059A\u0316\u302A\u031C\u0062
+\u0061\u032E\u059A\u0316\u302A\u0062 \u0061\u0338\u093C\u0334\u0062
+\u0061\u059A\u0316\u302A\u0339 \u0061\u0341\u0315\u0300\u05AE\u0062
+\u0061\u0348\u059A\u0316\u302A\u0062 \u0061\u0361\u0345\u035D\u035C\u0062
+\u0061\u0366\u0315\u0300\u05AE\u0062 \u0061\u0315\u0300\u05AE\u0486\u0062
+\u0061\u05A4\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0613\u0062
+\u0061\u0315\u0300\u05AE\u0615\u0062 \u0061\u0617\u0315\u0300\u05AE\u0062
+\u0061\u0619\u0618\u064D\u064E\u0062 \u0061\u0315\u0300\u05AE\u0654\u0062
+\u0061\u0315\u0300\u05AE\u06DC\u0062 \u0061\u0733\u0315\u0300\u05AE\u0062
+\u0061\u0744\u059A\u0316\u302A\u0062 \u0061\u0315\u0300\u05AE\u0745\u0062
+\u0061\u09CD\u05B0\u094D\u3099\u0062 \u0061\u0E38\u0E48\u0E38\u0C56\u0062
+\u0061\u0EB8\u0E48\u0E38\u0E49\u0062 \u0061\u0F72\u0F71\u0EC8\u0F71\u0062
+\u0061\u1039\u05B0\u094D\u3099\u0062 \u0061\u05B0\u094D\u3099\u1A60\u0062
+\u0061\u3099\u093C\u0334\u1BE6\u0062 \u0061\u3099\u093C\u0334\u1C37\u0062
+\u0061\u1CD9\u059A\u0316\u302A\u0062 \u0061\u2DED\u0315\u0300\u05AE\u0062
+\u0061\u2DEF\u0315\u0300\u05AE\u0062 \u0061\u302D\u302E\u059A\u0316\u0062`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/vn/
+const txt_vn = `Vá»›i các Ä‘iá»u kiện sau: Ghi nhận công của tác giả.
+Nếu bạn sử dụng, chuyển đổi, hoặc xây dựng dự án từ
+nội dung được chia sẻ này, bạn phải áp dụng giấy phép này hoặc
+má»™t giấy phép khác có các Ä‘iá»u khoản tÆ°Æ¡ng tá»± nhÆ° giấy phép này
+cho dá»± án của bạn. Hiểu rằng: Miá»…n — Bất kỳ các Ä‘iá»u kiện nào
+trên đây cũng có thể được miễn bỠnếu bạn được sự cho phép của
+ngÆ°á»i sở hữu bản quyá»n. Phạm vi công chúng — Khi tác phẩm hoặc
+bất kỳ chương nào của tác phẩm đã trong vùng dành cho công
+chúng theo quy định của pháp luật thì tình trạng của nó không
+bị ảnh hưởng bởi giấy phép trong bất kỳ trÆ°á»ng hợp nào.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/1.0/deed.ru
+const txt_ru = `При обÑзательном Ñоблюдении Ñледующих уÑловий:
+Attribution — Вы должны атрибутировать произведение (указывать
+автора и иÑточник) в порÑдке, предуÑмотренном автором или
+лицензиаром (но только так, чтобы никоим образом не подразумевалоÑÑŒ,
+что они поддерживают Ð²Ð°Ñ Ð¸Ð»Ð¸ иÑпользование вами данного произведениÑ).
+Υπό τις ακόλουθες Ï€Ïοϋποθέσεις:`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/gr/
+const txt_gr = `ΑναφοÏά ΔημιουÏÎ³Î¿Ï â€” Θα Ï€Ïέπει να κάνετε την αναφοÏά στο έÏγο με τον
+Ï„Ïόπο που έχει οÏιστεί από το δημιουÏγό ή το χοÏηγοÏντο την άδεια
+(χωÏίς όμως να εννοείται με οποιονδήποτε Ï„Ïόπο ότι εγκÏίνουν εσάς ή
+τη χÏήση του έÏγου από εσάς). ΠαÏόμοια Διανομή — Εάν αλλοιώσετε,
+Ï„Ïοποποιήσετε ή δημιουÏγήσετε πεÏαιτέÏω βασισμένοι στο έÏγο θα
+μποÏείτε να διανέμετε το έÏγο που θα Ï€ÏοκÏψει μόνο με την ίδια ή
+παÏόμοια άδεια.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/deed.ar
+const txt_ar = `بموجب الشروط التالية نسب المصن٠— يجب عليك أن
+تنسب العمل بالطريقة التي تحددها المؤل٠أو المرخص (ولكن ليس بأي حال من
+الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل).
+المشاركة على قدم المساواة — إذا كنت يعدل ØŒ والتغيير ØŒ أو الاستÙادة
+من هذا العمل ØŒ قد ينتج عن توزيع العمل إلا ÙÙŠ ظل تشابه او تطابق ÙÙ‰ واحد
+لهذا الترخيص.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/1.0/il/
+const txt_il = `בכפוף לתנ××™× ×”×‘××™×: ייחוס — עליך לייחס ×ת היצירה (לתת קרדיט) ב×ופן
+המצויין על-ידי היוצר ×ו מעניק הרישיון (×ך ×œ× ×‘×©×•× ×ופן המרמז על כך
+×©×”× ×ª×•×ž×›×™× ×‘×š ×ו בשימוש שלך ביצירה). שיתוף ×–×”×” — ×× ×ª×—×œ×™×˜/×™ לשנות,
+לעבד ×ו ליצור יצירה נגזרת בהסתמך על יצירה זו, תוכל/×™ להפיץ ×ת יצירתך
+החדשה רק תחת ×ותו הרישיון ×ו רישיון דומה לרישיון ×–×”.`
+
+const twoByteUtf8 = txt_ru + txt_gr + txt_ar + txt_il
+
+// Taken from http://creativecommons.org/licenses/by-sa/2.0/kr/
+const txt_kr = `다ìŒê³¼ ê°™ì€ ì¡°ê±´ì„ ë”°ë¼ì•¼ 합니다: 저작ìží‘œì‹œ
+(Attribution) — 저작ìžë‚˜ ì´ìš©í—ˆë½ìžê°€ ì •í•œ 방법으로 저작물ì˜
+ì›ì €ìž‘ìžë¥¼ 표시하여야 합니다(그러나 ì›ì €ìž‘ìžê°€ ì´ìš©ìžë‚˜ ì´ìš©ìžì˜
+ì´ìš©ì„ ë³´ì¦í•˜ê±°ë‚˜ 추천한다는 ì˜ë¯¸ë¡œ 표시해서는 안ë©ë‹ˆë‹¤).
+ë™ì¼ì¡°ê±´ë³€ê²½í—ˆë½ — ì´ ì €ìž‘ë¬¼ì„ ì´ìš©í•˜ì—¬ 만든 ì´ì°¨ì  저작물ì—는 본
+ë¼ì´ì„ ìŠ¤ì™€ ë™ì¼í•œ ë¼ì´ì„ ìŠ¤ë¥¼ ì ìš©í•´ì•¼ 합니다.`
+
+// Taken from http://creativecommons.org/licenses/by-sa/3.0/th/
+const txt_th = `ภายใต้เงื่อนไข ดังต่อไปนี้ : à¹à¸ªà¸”งที่มา — คุณต้องà¹à¸ªà¸”งที่
+มาของงานดังà¸à¸¥à¹ˆà¸²à¸§ ตามรูปà¹à¸šà¸šà¸—ี่ผู้สร้างสรรค์หรือผู้อนุà¸à¸²à¸•à¸à¸³à¸«à¸™à¸” (à¹à¸•à¹ˆ
+ไม่ใช่ในลัà¸à¸©à¸“ะที่ว่า พวà¸à¹€à¸‚าสนับสนุนคุณหรือสนับสนุนà¸à¸²à¸£à¸—ี่
+คุณนำงานไปใช้) อนุà¸à¸²à¸•à¹à¸šà¸šà¹€à¸”ียวà¸à¸±à¸™ — หาà¸à¸„ุณดัดà¹à¸›à¸¥à¸‡ เปลี่ยนรูป หรื
+อต่อเติมงานนี้ คุณต้องใช้สัà¸à¸à¸²à¸­à¸™à¸¸à¸à¸²à¸•à¹à¸šà¸šà¹€à¸”ียวà¸à¸±à¸™à¸«à¸£à¸·à¸­à¹à¸šà¸šà¸—ี่เหมื
+อนà¸à¸±à¸šà¸ªà¸±à¸à¸à¸²à¸­à¸™à¸¸à¸à¸²à¸•à¸—ี่ใช้à¸à¸±à¸šà¸‡à¸²à¸™à¸™à¸µà¹‰à¹€à¸—่านั้น`
+
+const threeByteUtf8 = txt_th
+
+// Taken from http://creativecommons.org/licenses/by-sa/2.0/jp/
+const txt_jp = `ã‚ãªãŸã®å¾“ã†ã¹ãæ¡ä»¶ã¯ä»¥ä¸‹ã®é€šã‚Šã§ã™ã€‚
+表示 — ã‚ãªãŸã¯åŽŸè‘—作者ã®ã‚¯ãƒ¬ã‚¸ãƒƒãƒˆã‚’表示ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。
+継承 — ã‚‚ã—ã‚ãªãŸãŒã“ã®ä½œå“を改変ã€å¤‰å½¢ã¾ãŸã¯åŠ å·¥ã—ãŸå ´åˆã€
+ã‚ãªãŸã¯ãã®çµæžœç”Ÿã˜ãŸä½œå“ã‚’ã“ã®ä½œå“ã¨åŒä¸€ã®è¨±è«¾æ¡ä»¶ã®ä¸‹ã§ã®ã¿
+頒布ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚`
+
+// http://creativecommons.org/licenses/by-sa/2.5/cn/
+const txt_cn = `您å¯ä»¥è‡ªç”±ï¼š å¤åˆ¶ã€å‘è¡Œã€å±•è§ˆã€è¡¨æ¼”ã€æ”¾æ˜ ã€
+广播或通过信æ¯ç½‘ç»œä¼ æ’­æœ¬ä½œå“ åˆ›ä½œæ¼”ç»Žä½œå“
+对本作å“进行商业性使用 惟须éµå®ˆä¸‹åˆ—æ¡ä»¶ï¼š
+ç½²å — 您必须按照作者或者许å¯äººæŒ‡å®šçš„æ–¹å¼å¯¹ä½œå“进行署å。
+相åŒæ–¹å¼å…±äº« — 如果您改å˜ã€è½¬æ¢æœ¬ä½œå“或者以本作å“为基础进行创作,
+您åªèƒ½é‡‡ç”¨ä¸Žæœ¬å议相åŒçš„许å¯åè®®å‘布基于本作å“的演绎作å“。`
diff --git a/libgo/go/exp/norm/normregtest.go b/libgo/go/exp/norm/normregtest.go
new file mode 100644
index 00000000000..cbd73ffa759
--- /dev/null
+++ b/libgo/go/exp/norm/normregtest.go
@@ -0,0 +1,295 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bufio"
+ "bytes"
+ "exp/norm"
+ "flag"
+ "fmt"
+ "http"
+ "log"
+ "os"
+ "path"
+ "regexp"
+ "runtime"
+ "strings"
+ "strconv"
+ "time"
+ "utf8"
+)
+
+func main() {
+ flag.Parse()
+ loadTestData()
+ CharacterByCharacterTests()
+ StandardTests()
+ PerformanceTest()
+ if errorCount == 0 {
+ fmt.Println("PASS")
+ }
+}
+
+const file = "NormalizationTest.txt"
+
+var url = flag.String("url",
+ "http://www.unicode.org/Public/6.0.0/ucd/"+file,
+ "URL of Unicode database directory")
+var localFiles = flag.Bool("local",
+ false,
+ "data files have been copied to the current directory; for debugging only")
+
+var logger = log.New(os.Stderr, "", log.Lshortfile)
+
+// This regression test runs the test set in NormalizationTest.txt
+// (taken from http://www.unicode.org/Public/6.0.0/ucd/).
+//
+// NormalizationTest.txt has form:
+// @Part0 # Specific cases
+// #
+// 1E0A;1E0A;0044 0307;1E0A;0044 0307; # (Ḋ; Ḋ; D◌̇; Ḋ; D◌̇; ) LATIN CAPITAL LETTER D WITH DOT ABOVE
+// 1E0C;1E0C;0044 0323;1E0C;0044 0323; # (Ḍ; Ḍ; D◌̣; Ḍ; D◌̣; ) LATIN CAPITAL LETTER D WITH DOT BELOW
+//
+// Each test has 5 columns (c1, c2, c3, c4, c5), where
+// (c1, c2, c3, c4, c5) == (c1, NFC(c1), NFD(c1), NFKC(c1), NFKD(c1))
+//
+// CONFORMANCE:
+// 1. The following invariants must be true for all conformant implementations
+//
+// NFC
+// c2 == NFC(c1) == NFC(c2) == NFC(c3)
+// c4 == NFC(c4) == NFC(c5)
+//
+// NFD
+// c3 == NFD(c1) == NFD(c2) == NFD(c3)
+// c5 == NFD(c4) == NFD(c5)
+//
+// NFKC
+// c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5)
+//
+// NFKD
+// c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5)
+//
+// 2. For every code point X assigned in this version of Unicode that is not
+// specifically listed in Part 1, the following invariants must be true
+// for all conformant implementations:
+//
+// X == NFC(X) == NFD(X) == NFKC(X) == NFKD(X)
+//
+
+// Column types.
+const (
+ cRaw = iota
+ cNFC
+ cNFD
+ cNFKC
+ cNFKD
+ cMaxColumns
+)
+
+// Holds data from NormalizationTest.txt
+var part []Part
+
+type Part struct {
+ name string
+ number int
+ tests []Test
+}
+
+type Test struct {
+ name string
+ partnr int
+ number int
+ rune int // used for character by character test
+ cols [cMaxColumns]string // Each has 5 entries, see below.
+}
+
+func (t Test) Name() string {
+ if t.number < 0 {
+ return part[t.partnr].name
+ }
+ return fmt.Sprintf("%s:%d", part[t.partnr].name, t.number)
+}
+
+var partRe = regexp.MustCompile(`@Part(\d) # (.*)\n$`)
+var testRe = regexp.MustCompile(`^` + strings.Repeat(`([\dA-F ]+);`, 5) + ` # (.*)\n?$`)
+
+var counter int
+
+// Load the data form NormalizationTest.txt
+func loadTestData() {
+ if *localFiles {
+ pwd, _ := os.Getwd()
+ *url = "file://" + path.Join(pwd, file)
+ }
+ t := &http.Transport{}
+ t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
+ c := &http.Client{Transport: t}
+ resp, err := c.Get(*url)
+ if err != nil {
+ logger.Fatal(err)
+ }
+ if resp.StatusCode != 200 {
+ logger.Fatal("bad GET status for "+file, resp.Status)
+ }
+ f := resp.Body
+ defer f.Close()
+ input := bufio.NewReader(f)
+ for {
+ line, err := input.ReadString('\n')
+ if err != nil {
+ if err == os.EOF {
+ break
+ }
+ logger.Fatal(err)
+ }
+ if len(line) == 0 || line[0] == '#' {
+ continue
+ }
+ m := partRe.FindStringSubmatch(line)
+ if m != nil {
+ if len(m) < 3 {
+ logger.Fatal("Failed to parse Part: ", line)
+ }
+ i, err := strconv.Atoi(m[1])
+ if err != nil {
+ logger.Fatal(err)
+ }
+ name := m[2]
+ part = append(part, Part{name: name[:len(name)-1], number: i})
+ continue
+ }
+ m = testRe.FindStringSubmatch(line)
+ if m == nil || len(m) < 7 {
+ logger.Fatalf(`Failed to parse: "%s" result: %#v`, line, m)
+ }
+ test := Test{name: m[6], partnr: len(part) - 1, number: counter}
+ counter++
+ for j := 1; j < len(m)-1; j++ {
+ for _, split := range strings.Split(m[j], " ") {
+ r, err := strconv.Btoui64(split, 16)
+ if err != nil {
+ logger.Fatal(err)
+ }
+ if test.rune == 0 {
+ // save for CharacterByCharacterTests
+ test.rune = int(r)
+ }
+ var buf [utf8.UTFMax]byte
+ sz := utf8.EncodeRune(buf[:], int(r))
+ test.cols[j-1] += string(buf[:sz])
+ }
+ }
+ part := &part[len(part)-1]
+ part.tests = append(part.tests, test)
+ }
+}
+
+var fstr = []string{"NFC", "NFD", "NFKC", "NFKD"}
+
+var errorCount int
+
+func cmpResult(t *Test, name string, f norm.Form, gold, test, result string) {
+ if gold != result {
+ errorCount++
+ if errorCount > 20 {
+ return
+ }
+ st, sr, sg := []int(test), []int(result), []int(gold)
+ logger.Printf("%s:%s: %s(%X)=%X; want:%X: %s",
+ t.Name(), name, fstr[f], st, sr, sg, t.name)
+ }
+}
+
+func cmpIsNormal(t *Test, name string, f norm.Form, test string, result, want bool) {
+ if result != want {
+ errorCount++
+ if errorCount > 20 {
+ return
+ }
+ logger.Printf("%s:%s: %s(%X)=%v; want: %v", t.Name(), name, fstr[f], []int(test), result, want)
+ }
+}
+
+func doTest(t *Test, f norm.Form, gold, test string) {
+ result := f.Bytes([]byte(test))
+ cmpResult(t, "Bytes", f, gold, test, string(result))
+ for i := range test {
+ out := f.Append(f.Bytes([]byte(test[:i])), []byte(test[i:])...)
+ cmpResult(t, fmt.Sprintf(":Append:%d", i), f, gold, test, string(out))
+ }
+ cmpIsNormal(t, "IsNormal", f, test, f.IsNormal([]byte(test)), test == gold)
+}
+
+func doConformanceTests(t *Test, partn int) {
+ for i := 0; i <= 2; i++ {
+ doTest(t, norm.NFC, t.cols[1], t.cols[i])
+ doTest(t, norm.NFD, t.cols[2], t.cols[i])
+ doTest(t, norm.NFKC, t.cols[3], t.cols[i])
+ doTest(t, norm.NFKD, t.cols[4], t.cols[i])
+ }
+ for i := 3; i <= 4; i++ {
+ doTest(t, norm.NFC, t.cols[3], t.cols[i])
+ doTest(t, norm.NFD, t.cols[4], t.cols[i])
+ doTest(t, norm.NFKC, t.cols[3], t.cols[i])
+ doTest(t, norm.NFKD, t.cols[4], t.cols[i])
+ }
+}
+
+func CharacterByCharacterTests() {
+ tests := part[1].tests
+ last := 0
+ for i := 0; i <= len(tests); i++ { // last one is special case
+ var rune int
+ if i == len(tests) {
+ rune = 0x2FA1E // Don't have to go to 0x10FFFF
+ } else {
+ rune = tests[i].rune
+ }
+ for last++; last < rune; last++ {
+ // Check all characters that were not explicitly listed in the test.
+ t := &Test{partnr: 1, number: -1}
+ char := string(last)
+ doTest(t, norm.NFC, char, char)
+ doTest(t, norm.NFD, char, char)
+ doTest(t, norm.NFKC, char, char)
+ doTest(t, norm.NFKD, char, char)
+ }
+ if i < len(tests) {
+ doConformanceTests(&tests[i], 1)
+ }
+ }
+}
+
+func StandardTests() {
+ for _, j := range []int{0, 2, 3} {
+ for _, test := range part[j].tests {
+ doConformanceTests(&test, j)
+ }
+ }
+}
+
+// PerformanceTest verifies that normalization is O(n). If any of the
+// code does not properly check for maxCombiningChars, normalization
+// may exhibit O(n**2) behavior.
+func PerformanceTest() {
+ runtime.GOMAXPROCS(2)
+ success := make(chan bool, 1)
+ go func() {
+ buf := bytes.Repeat([]byte("\u035D"), 1024*1024)
+ buf = append(buf, "\u035B"...)
+ norm.NFC.Append(nil, buf...)
+ success <- true
+ }()
+ timeout := time.After(1e9)
+ select {
+ case <-success:
+ // test completed before the timeout
+ case <-timeout:
+ errorCount++
+ logger.Printf(`unexpectedly long time to complete PerformanceTest`)
+ }
+}
diff --git a/libgo/go/exp/norm/readwriter.go b/libgo/go/exp/norm/readwriter.go
new file mode 100644
index 00000000000..48ae1356201
--- /dev/null
+++ b/libgo/go/exp/norm/readwriter.go
@@ -0,0 +1,129 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import (
+ "io"
+ "os"
+)
+
+type normWriter struct {
+ rb reorderBuffer
+ w io.Writer
+ buf []byte
+}
+
+// Write implements the standard write interface. If the last characters are
+// not at a normalization boundary, the bytes will be buffered for the next
+// write. The remaining bytes will be written on close.
+func (w *normWriter) Write(data []byte) (n int, err os.Error) {
+ // Process data in pieces to keep w.buf size bounded.
+ const chunk = 4000
+
+ for len(data) > 0 {
+ // Normalize into w.buf.
+ m := len(data)
+ if m > chunk {
+ m = chunk
+ }
+ w.rb.src = inputBytes(data[:m])
+ w.rb.nsrc = m
+ w.buf = doAppend(&w.rb, w.buf)
+ data = data[m:]
+ n += m
+
+ // Write out complete prefix, save remainder.
+ // Note that lastBoundary looks back at most 30 runes.
+ i := lastBoundary(&w.rb.f, w.buf)
+ if i == -1 {
+ i = 0
+ }
+ if i > 0 {
+ if _, err = w.w.Write(w.buf[:i]); err != nil {
+ break
+ }
+ bn := copy(w.buf, w.buf[i:])
+ w.buf = w.buf[:bn]
+ }
+ }
+ return n, err
+}
+
+// Close forces data that remains in the buffer to be written.
+func (w *normWriter) Close() os.Error {
+ if len(w.buf) > 0 {
+ _, err := w.w.Write(w.buf)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// Writer returns a new writer that implements Write(b)
+// by writing f(b) to w. The returned writer may use an
+// an internal buffer to maintain state across Write calls.
+// Calling its Close method writes any buffered data to w.
+func (f Form) Writer(w io.Writer) io.WriteCloser {
+ wr := &normWriter{rb: reorderBuffer{}, w: w}
+ wr.rb.init(f, nil)
+ return wr
+}
+
+type normReader struct {
+ rb reorderBuffer
+ r io.Reader
+ inbuf []byte
+ outbuf []byte
+ bufStart int
+ lastBoundary int
+ err os.Error
+}
+
+// Read implements the standard read interface.
+func (r *normReader) Read(p []byte) (int, os.Error) {
+ for {
+ if r.lastBoundary-r.bufStart > 0 {
+ n := copy(p, r.outbuf[r.bufStart:r.lastBoundary])
+ r.bufStart += n
+ if r.lastBoundary-r.bufStart > 0 {
+ return n, nil
+ }
+ return n, r.err
+ }
+ if r.err != nil {
+ return 0, r.err
+ }
+ outn := copy(r.outbuf, r.outbuf[r.lastBoundary:])
+ r.outbuf = r.outbuf[0:outn]
+ r.bufStart = 0
+
+ n, err := r.r.Read(r.inbuf)
+ r.rb.src = inputBytes(r.inbuf[0:n])
+ r.rb.nsrc, r.err = n, err
+ if n > 0 {
+ r.outbuf = doAppend(&r.rb, r.outbuf)
+ }
+ if err == os.EOF {
+ r.lastBoundary = len(r.outbuf)
+ } else {
+ r.lastBoundary = lastBoundary(&r.rb.f, r.outbuf)
+ if r.lastBoundary == -1 {
+ r.lastBoundary = 0
+ }
+ }
+ }
+ panic("should not reach here")
+}
+
+// Reader returns a new reader that implements Read
+// by reading data from r and returning f(data).
+func (f Form) Reader(r io.Reader) io.Reader {
+ const chunk = 4000
+ buf := make([]byte, chunk)
+ rr := &normReader{rb: reorderBuffer{}, r: r, inbuf: buf}
+ rr.rb.init(f, buf)
+ return rr
+}
diff --git a/libgo/go/exp/norm/readwriter_test.go b/libgo/go/exp/norm/readwriter_test.go
new file mode 100644
index 00000000000..68652efa65b
--- /dev/null
+++ b/libgo/go/exp/norm/readwriter_test.go
@@ -0,0 +1,69 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package norm
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "strings"
+ "testing"
+)
+
+var ioTests = []AppendTest{
+ {"", strings.Repeat("a\u0316\u0300", 6), strings.Repeat("\u00E0\u0316", 6)},
+ {"", strings.Repeat("a\u0300\u0316", 4000), strings.Repeat("\u00E0\u0316", 4000)},
+ {"", strings.Repeat("\x80\x80", 4000), strings.Repeat("\x80\x80", 4000)},
+ {"", "\u0041\u0307\u0304", "\u01E0"},
+}
+
+var bufSizes = []int{1, 2, 3, 4, 5, 6, 7, 8, 100, 101, 102, 103, 4000, 4001, 4002, 4003}
+
+func readFunc(size int) appendFunc {
+ return func(f Form, out []byte, s string) []byte {
+ out = append(out, s...)
+ r := f.Reader(bytes.NewBuffer(out))
+ buf := make([]byte, size)
+ result := []byte{}
+ for n, err := 0, os.Error(nil); err == nil; {
+ n, err = r.Read(buf)
+ result = append(result, buf[:n]...)
+ }
+ return result
+ }
+}
+
+func TestReader(t *testing.T) {
+ for _, s := range bufSizes {
+ name := fmt.Sprintf("TestReader%da", s)
+ runAppendTests(t, name, NFKC, readFunc(s), appendTests)
+ name = fmt.Sprintf("TestReader%db", s)
+ runAppendTests(t, name, NFKC, readFunc(s), ioTests)
+ }
+}
+
+func writeFunc(size int) appendFunc {
+ return func(f Form, out []byte, s string) []byte {
+ in := append(out, s...)
+ result := new(bytes.Buffer)
+ w := f.Writer(result)
+ buf := make([]byte, size)
+ for n := 0; len(in) > 0; in = in[n:] {
+ n = copy(buf, in)
+ _, _ = w.Write(buf[:n])
+ }
+ w.Close()
+ return result.Bytes()
+ }
+}
+
+func TestWriter(t *testing.T) {
+ for _, s := range bufSizes {
+ name := fmt.Sprintf("TestWriter%da", s)
+ runAppendTests(t, name, NFKC, writeFunc(s), appendTests)
+ name = fmt.Sprintf("TestWriter%db", s)
+ runAppendTests(t, name, NFKC, writeFunc(s), ioTests)
+ }
+}
diff --git a/libgo/go/exp/norm/tables.go b/libgo/go/exp/norm/tables.go
index 76995c2fa18..55ff052dcbc 100644
--- a/libgo/go/exp/norm/tables.go
+++ b/libgo/go/exp/norm/tables.go
@@ -2490,545 +2490,632 @@ var decomps = [...]byte{
0x98, 0x80,
}
-// nfcDecompValues: 4992 entries, 9984 bytes
+// nfcDecompValues: 1408 entries, 2816 bytes
// Block 2 is the null block.
-var nfcDecompValues = [4992]uint16{
+var nfcDecompValues = [1408]uint16{
// Block 0x0, offset 0x0
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x00c0: 0x0032, 0x00c1: 0x0036, 0x00c2: 0x003a, 0x00c3: 0x003e, 0x00c4: 0x0042, 0x00c5: 0x0046,
- 0x00c7: 0x004a, 0x00c8: 0x004e, 0x00c9: 0x0052, 0x00ca: 0x0056, 0x00cb: 0x005a,
- 0x00cc: 0x005e, 0x00cd: 0x0062, 0x00ce: 0x0066, 0x00cf: 0x006a, 0x00d1: 0x006e,
- 0x00d2: 0x0072, 0x00d3: 0x0076, 0x00d4: 0x007a, 0x00d5: 0x007e, 0x00d6: 0x0082,
- 0x00d9: 0x0086, 0x00da: 0x008a, 0x00db: 0x008e, 0x00dc: 0x0092, 0x00dd: 0x0096,
- 0x00e0: 0x009a, 0x00e1: 0x009e, 0x00e2: 0x00a2, 0x00e3: 0x00a6,
- 0x00e4: 0x00aa, 0x00e5: 0x00ae, 0x00e7: 0x00b2, 0x00e8: 0x00b6, 0x00e9: 0x00ba,
- 0x00ea: 0x00be, 0x00eb: 0x00c2, 0x00ec: 0x00c6, 0x00ed: 0x00ca, 0x00ee: 0x00ce, 0x00ef: 0x00d2,
- 0x00f1: 0x00d6, 0x00f2: 0x00da, 0x00f3: 0x00de, 0x00f4: 0x00e2, 0x00f5: 0x00e6,
- 0x00f6: 0x00ea, 0x00f9: 0x00ee, 0x00fa: 0x00f2, 0x00fb: 0x00f6,
- 0x00fc: 0x00fa, 0x00fd: 0x00fe, 0x00ff: 0x0102,
+ 0x00cd: 0x02fb, 0x00ce: 0x02ff, 0x00cf: 0x0303, 0x00d0: 0x0307, 0x00d1: 0x030b,
+ 0x00d2: 0x030f, 0x00d3: 0x0313, 0x00d4: 0x0317, 0x00d5: 0x031b, 0x00d6: 0x0321, 0x00d7: 0x0327,
+ 0x00d8: 0x032d, 0x00d9: 0x0333, 0x00da: 0x0339, 0x00db: 0x033f, 0x00dc: 0x0345,
+ 0x00de: 0x034b, 0x00df: 0x0351, 0x00e0: 0x0357, 0x00e1: 0x035d, 0x00e2: 0x0363, 0x00e3: 0x0368,
+ 0x00e6: 0x036d, 0x00e7: 0x0371, 0x00e8: 0x0375, 0x00e9: 0x0379,
+ 0x00ea: 0x037d, 0x00eb: 0x0381, 0x00ec: 0x0385, 0x00ed: 0x038b, 0x00ee: 0x0391, 0x00ef: 0x0396,
+ 0x00f0: 0x039b, 0x00f4: 0x03a8, 0x00f5: 0x03ac,
+ 0x00f8: 0x03b0, 0x00f9: 0x03b4, 0x00fa: 0x03b8, 0x00fb: 0x03be,
+ 0x00fc: 0x03c4, 0x00fd: 0x03c9, 0x00fe: 0x03ce, 0x00ff: 0x03d3,
// Block 0x4, offset 0x100
- 0x0100: 0x0106, 0x0101: 0x010a, 0x0102: 0x010e, 0x0103: 0x0112, 0x0104: 0x0116, 0x0105: 0x011a,
- 0x0106: 0x011e, 0x0107: 0x0122, 0x0108: 0x0126, 0x0109: 0x012a, 0x010a: 0x012e, 0x010b: 0x0132,
- 0x010c: 0x0136, 0x010d: 0x013a, 0x010e: 0x013e, 0x010f: 0x0142,
- 0x0112: 0x0146, 0x0113: 0x014a, 0x0114: 0x014e, 0x0115: 0x0152, 0x0116: 0x0156, 0x0117: 0x015a,
- 0x0118: 0x015e, 0x0119: 0x0162, 0x011a: 0x0166, 0x011b: 0x016a, 0x011c: 0x016e, 0x011d: 0x0172,
- 0x011e: 0x0176, 0x011f: 0x017a, 0x0120: 0x017e, 0x0121: 0x0182, 0x0122: 0x0186, 0x0123: 0x018a,
- 0x0124: 0x018e, 0x0125: 0x0192, 0x0128: 0x0196, 0x0129: 0x019a,
- 0x012a: 0x019e, 0x012b: 0x01a2, 0x012c: 0x01a6, 0x012d: 0x01aa, 0x012e: 0x01ae, 0x012f: 0x01b2,
- 0x0130: 0x01b6, 0x0134: 0x01c0, 0x0135: 0x01c4,
- 0x0136: 0x01c8, 0x0137: 0x01cc, 0x0139: 0x01d0, 0x013a: 0x01d4, 0x013b: 0x01d8,
- 0x013c: 0x01dc, 0x013d: 0x01e0, 0x013e: 0x01e4,
+ 0x0100: 0x0b02, 0x0101: 0x0b06, 0x0102: 0x0b0a, 0x0103: 0x0b0e, 0x0104: 0x0b12, 0x0105: 0x0b16,
+ 0x0106: 0x0b1a, 0x0107: 0x0b1e, 0x0108: 0x0b22, 0x0109: 0x0b26, 0x010a: 0x0b2a, 0x010b: 0x0b2e,
+ 0x010c: 0x0b32, 0x010d: 0x0b38, 0x010e: 0x0b3e, 0x010f: 0x0b44, 0x0110: 0x0b4a, 0x0111: 0x0b50,
+ 0x0112: 0x0b56, 0x0113: 0x0b5c, 0x0114: 0x0b62, 0x0115: 0x0b66, 0x0116: 0x0b6a, 0x0117: 0x0b6e,
+ 0x0118: 0x0b72, 0x0119: 0x0b76, 0x011a: 0x0b7a, 0x011b: 0x0b7e, 0x011c: 0x0b82, 0x011d: 0x0b88,
+ 0x011e: 0x0b8e, 0x011f: 0x0b92, 0x0120: 0x0b96, 0x0121: 0x0b9a, 0x0122: 0x0b9e, 0x0123: 0x0ba2,
+ 0x0124: 0x0ba6, 0x0125: 0x0bac, 0x0126: 0x0bb2, 0x0127: 0x0bb8, 0x0128: 0x0bbe, 0x0129: 0x0bc4,
+ 0x012a: 0x0bca, 0x012b: 0x0bce, 0x012c: 0x0bd2, 0x012d: 0x0bd6, 0x012e: 0x0bda, 0x012f: 0x0bde,
+ 0x0130: 0x0be2, 0x0131: 0x0be6, 0x0132: 0x0bea, 0x0133: 0x0bee, 0x0134: 0x0bf2, 0x0135: 0x0bf6,
+ 0x0136: 0x0bfa, 0x0137: 0x0bfe, 0x0138: 0x0c02, 0x0139: 0x0c08, 0x013a: 0x0c0e, 0x013b: 0x0c14,
+ 0x013c: 0x0c1a, 0x013d: 0x0c1e, 0x013e: 0x0c22, 0x013f: 0x0c26,
// Block 0x5, offset 0x140
- 0x0143: 0x01f0, 0x0144: 0x01f4, 0x0145: 0x01f8,
- 0x0146: 0x01fc, 0x0147: 0x0200, 0x0148: 0x0204,
- 0x014c: 0x020c, 0x014d: 0x0210, 0x014e: 0x0214, 0x014f: 0x0218, 0x0150: 0x021c, 0x0151: 0x0220,
- 0x0154: 0x0224, 0x0155: 0x0228, 0x0156: 0x022c, 0x0157: 0x0230,
- 0x0158: 0x0234, 0x0159: 0x0238, 0x015a: 0x023c, 0x015b: 0x0240, 0x015c: 0x0244, 0x015d: 0x0248,
- 0x015e: 0x024c, 0x015f: 0x0250, 0x0160: 0x0254, 0x0161: 0x0258, 0x0162: 0x025c, 0x0163: 0x0260,
- 0x0164: 0x0264, 0x0165: 0x0268, 0x0168: 0x026c, 0x0169: 0x0270,
- 0x016a: 0x0274, 0x016b: 0x0278, 0x016c: 0x027c, 0x016d: 0x0280, 0x016e: 0x0284, 0x016f: 0x0288,
- 0x0170: 0x028c, 0x0171: 0x0290, 0x0172: 0x0294, 0x0173: 0x0298, 0x0174: 0x029c, 0x0175: 0x02a0,
- 0x0176: 0x02a4, 0x0177: 0x02a8, 0x0178: 0x02ac, 0x0179: 0x02b0, 0x017a: 0x02b4, 0x017b: 0x02b8,
- 0x017c: 0x02bc, 0x017d: 0x02c0, 0x017e: 0x02c4,
+ 0x0140: 0x0c2a, 0x0141: 0x0c2e, 0x0142: 0x0c32, 0x0143: 0x0c36, 0x0144: 0x0c3a, 0x0145: 0x0c3e,
+ 0x0146: 0x0c42, 0x0147: 0x0c46, 0x0148: 0x0c4a, 0x0149: 0x0c4e, 0x014a: 0x0c52, 0x014b: 0x0c56,
+ 0x014c: 0x0c5a, 0x014d: 0x0c5e, 0x014e: 0x0c62, 0x014f: 0x0c66, 0x0150: 0x0c6a, 0x0151: 0x0c6e,
+ 0x0152: 0x0c72, 0x0153: 0x0c76, 0x0154: 0x0c7a, 0x0155: 0x0c7e, 0x0156: 0x0c82, 0x0157: 0x0c86,
+ 0x0158: 0x0c8a, 0x0159: 0x0c8e, 0x015b: 0x0c96,
+ 0x0160: 0x0c9b, 0x0161: 0x0c9f, 0x0162: 0x0ca3, 0x0163: 0x0ca7,
+ 0x0164: 0x0cab, 0x0165: 0x0cb1, 0x0166: 0x0cb7, 0x0167: 0x0cbd, 0x0168: 0x0cc3, 0x0169: 0x0cc9,
+ 0x016a: 0x0ccf, 0x016b: 0x0cd5, 0x016c: 0x0cdb, 0x016d: 0x0ce1, 0x016e: 0x0ce7, 0x016f: 0x0ced,
+ 0x0170: 0x0cf3, 0x0171: 0x0cf9, 0x0172: 0x0cff, 0x0173: 0x0d05, 0x0174: 0x0d0b, 0x0175: 0x0d11,
+ 0x0176: 0x0d17, 0x0177: 0x0d1d, 0x0178: 0x0d23, 0x0179: 0x0d27, 0x017a: 0x0d2b, 0x017b: 0x0d2f,
+ 0x017c: 0x0d33, 0x017d: 0x0d37, 0x017e: 0x0d3b, 0x017f: 0x0d41,
// Block 0x6, offset 0x180
- 0x01a0: 0x02ca, 0x01a1: 0x02ce,
- 0x01af: 0x02d2,
- 0x01b0: 0x02d6,
+ 0x0180: 0x0d47, 0x0181: 0x0d4d, 0x0182: 0x0d53, 0x0183: 0x0d59, 0x0184: 0x0d5f, 0x0185: 0x0d65,
+ 0x0186: 0x0d6b, 0x0187: 0x0d71, 0x0188: 0x0d77, 0x0189: 0x0d7b, 0x018a: 0x0d7f, 0x018b: 0x0d83,
+ 0x018c: 0x0d87, 0x018d: 0x0d8b, 0x018e: 0x0d8f, 0x018f: 0x0d93, 0x0190: 0x0d97, 0x0191: 0x0d9d,
+ 0x0192: 0x0da3, 0x0193: 0x0da9, 0x0194: 0x0daf, 0x0195: 0x0db5, 0x0196: 0x0dbb, 0x0197: 0x0dc1,
+ 0x0198: 0x0dc7, 0x0199: 0x0dcd, 0x019a: 0x0dd3, 0x019b: 0x0dd9, 0x019c: 0x0ddf, 0x019d: 0x0de5,
+ 0x019e: 0x0deb, 0x019f: 0x0df1, 0x01a0: 0x0df7, 0x01a1: 0x0dfd, 0x01a2: 0x0e03, 0x01a3: 0x0e09,
+ 0x01a4: 0x0e0f, 0x01a5: 0x0e13, 0x01a6: 0x0e17, 0x01a7: 0x0e1b, 0x01a8: 0x0e1f, 0x01a9: 0x0e25,
+ 0x01aa: 0x0e2b, 0x01ab: 0x0e31, 0x01ac: 0x0e37, 0x01ad: 0x0e3d, 0x01ae: 0x0e43, 0x01af: 0x0e49,
+ 0x01b0: 0x0e4f, 0x01b1: 0x0e55, 0x01b2: 0x0e5b, 0x01b3: 0x0e5f, 0x01b4: 0x0e63, 0x01b5: 0x0e67,
+ 0x01b6: 0x0e6b, 0x01b7: 0x0e6f, 0x01b8: 0x0e73, 0x01b9: 0x0e77,
// Block 0x7, offset 0x1c0
- 0x01cd: 0x02fb, 0x01ce: 0x02ff, 0x01cf: 0x0303, 0x01d0: 0x0307, 0x01d1: 0x030b,
- 0x01d2: 0x030f, 0x01d3: 0x0313, 0x01d4: 0x0317, 0x01d5: 0x031b, 0x01d6: 0x0321, 0x01d7: 0x0327,
- 0x01d8: 0x032d, 0x01d9: 0x0333, 0x01da: 0x0339, 0x01db: 0x033f, 0x01dc: 0x0345,
- 0x01de: 0x034b, 0x01df: 0x0351, 0x01e0: 0x0357, 0x01e1: 0x035d, 0x01e2: 0x0363, 0x01e3: 0x0368,
- 0x01e6: 0x036d, 0x01e7: 0x0371, 0x01e8: 0x0375, 0x01e9: 0x0379,
- 0x01ea: 0x037d, 0x01eb: 0x0381, 0x01ec: 0x0385, 0x01ed: 0x038b, 0x01ee: 0x0391, 0x01ef: 0x0396,
- 0x01f0: 0x039b, 0x01f4: 0x03a8, 0x01f5: 0x03ac,
- 0x01f8: 0x03b0, 0x01f9: 0x03b4, 0x01fa: 0x03b8, 0x01fb: 0x03be,
- 0x01fc: 0x03c4, 0x01fd: 0x03c9, 0x01fe: 0x03ce, 0x01ff: 0x03d3,
+ 0x01c0: 0x0e7b, 0x01c1: 0x0e80, 0x01c2: 0x0e85, 0x01c3: 0x0e8c, 0x01c4: 0x0e93, 0x01c5: 0x0e9a,
+ 0x01c6: 0x0ea1, 0x01c7: 0x0ea8, 0x01c8: 0x0eaf, 0x01c9: 0x0eb4, 0x01ca: 0x0eb9, 0x01cb: 0x0ec0,
+ 0x01cc: 0x0ec7, 0x01cd: 0x0ece, 0x01ce: 0x0ed5, 0x01cf: 0x0edc, 0x01d0: 0x0ee3, 0x01d1: 0x0ee8,
+ 0x01d2: 0x0eed, 0x01d3: 0x0ef4, 0x01d4: 0x0efb, 0x01d5: 0x0f02,
+ 0x01d8: 0x0f09, 0x01d9: 0x0f0e, 0x01da: 0x0f13, 0x01db: 0x0f1a, 0x01dc: 0x0f21, 0x01dd: 0x0f28,
+ 0x01e0: 0x0f2f, 0x01e1: 0x0f34, 0x01e2: 0x0f39, 0x01e3: 0x0f40,
+ 0x01e4: 0x0f47, 0x01e5: 0x0f4e, 0x01e6: 0x0f55, 0x01e7: 0x0f5c, 0x01e8: 0x0f63, 0x01e9: 0x0f68,
+ 0x01ea: 0x0f6d, 0x01eb: 0x0f74, 0x01ec: 0x0f7b, 0x01ed: 0x0f82, 0x01ee: 0x0f89, 0x01ef: 0x0f90,
+ 0x01f0: 0x0f97, 0x01f1: 0x0f9c, 0x01f2: 0x0fa1, 0x01f3: 0x0fa8, 0x01f4: 0x0faf, 0x01f5: 0x0fb6,
+ 0x01f6: 0x0fbd, 0x01f7: 0x0fc4, 0x01f8: 0x0fcb, 0x01f9: 0x0fd0, 0x01fa: 0x0fd5, 0x01fb: 0x0fdc,
+ 0x01fc: 0x0fe3, 0x01fd: 0x0fea, 0x01fe: 0x0ff1, 0x01ff: 0x0ff8,
// Block 0x8, offset 0x200
- 0x0200: 0x03d8, 0x0201: 0x03dc, 0x0202: 0x03e0, 0x0203: 0x03e4, 0x0204: 0x03e8, 0x0205: 0x03ec,
- 0x0206: 0x03f0, 0x0207: 0x03f4, 0x0208: 0x03f8, 0x0209: 0x03fc, 0x020a: 0x0400, 0x020b: 0x0404,
- 0x020c: 0x0408, 0x020d: 0x040c, 0x020e: 0x0410, 0x020f: 0x0414, 0x0210: 0x0418, 0x0211: 0x041c,
- 0x0212: 0x0420, 0x0213: 0x0424, 0x0214: 0x0428, 0x0215: 0x042c, 0x0216: 0x0430, 0x0217: 0x0434,
- 0x0218: 0x0438, 0x0219: 0x043c, 0x021a: 0x0440, 0x021b: 0x0444,
- 0x021e: 0x0448, 0x021f: 0x044c,
- 0x0226: 0x0450, 0x0227: 0x0454, 0x0228: 0x0458, 0x0229: 0x045c,
- 0x022a: 0x0460, 0x022b: 0x0466, 0x022c: 0x046c, 0x022d: 0x0472, 0x022e: 0x0478, 0x022f: 0x047c,
- 0x0230: 0x0480, 0x0231: 0x0486, 0x0232: 0x048c, 0x0233: 0x0490,
+ 0x0200: 0x0fff, 0x0201: 0x1004, 0x0202: 0x1009, 0x0203: 0x1010, 0x0204: 0x1017, 0x0205: 0x101e,
+ 0x0208: 0x1025, 0x0209: 0x102a, 0x020a: 0x102f, 0x020b: 0x1036,
+ 0x020c: 0x103d, 0x020d: 0x1044, 0x0210: 0x104b, 0x0211: 0x1050,
+ 0x0212: 0x1055, 0x0213: 0x105c, 0x0214: 0x1063, 0x0215: 0x106a, 0x0216: 0x1071, 0x0217: 0x1078,
+ 0x0219: 0x107f, 0x021b: 0x1084, 0x021d: 0x108b,
+ 0x021f: 0x1092, 0x0220: 0x1099, 0x0221: 0x109e, 0x0222: 0x10a3, 0x0223: 0x10aa,
+ 0x0224: 0x10b1, 0x0225: 0x10b8, 0x0226: 0x10bf, 0x0227: 0x10c6, 0x0228: 0x10cd, 0x0229: 0x10d2,
+ 0x022a: 0x10d7, 0x022b: 0x10de, 0x022c: 0x10e5, 0x022d: 0x10ec, 0x022e: 0x10f3, 0x022f: 0x10fa,
+ 0x0230: 0x1101, 0x0231: 0x0525, 0x0232: 0x1106, 0x0233: 0x052a, 0x0234: 0x110b, 0x0235: 0x052f,
+ 0x0236: 0x1110, 0x0237: 0x0534, 0x0238: 0x1115, 0x0239: 0x054a, 0x023a: 0x111a, 0x023b: 0x054f,
+ 0x023c: 0x111f, 0x023d: 0x0554,
// Block 0x9, offset 0x240
- 0x0240: 0x04cc, 0x0241: 0x04cf, 0x0243: 0x04d2, 0x0244: 0x04d5,
- 0x0274: 0x04da,
- 0x027e: 0x04e1,
+ 0x0240: 0x1124, 0x0241: 0x112b, 0x0242: 0x1132, 0x0243: 0x113b, 0x0244: 0x1144, 0x0245: 0x114d,
+ 0x0246: 0x1156, 0x0247: 0x115f, 0x0248: 0x1168, 0x0249: 0x116f, 0x024a: 0x1176, 0x024b: 0x117f,
+ 0x024c: 0x1188, 0x024d: 0x1191, 0x024e: 0x119a, 0x024f: 0x11a3, 0x0250: 0x11ac, 0x0251: 0x11b3,
+ 0x0252: 0x11ba, 0x0253: 0x11c3, 0x0254: 0x11cc, 0x0255: 0x11d5, 0x0256: 0x11de, 0x0257: 0x11e7,
+ 0x0258: 0x11f0, 0x0259: 0x11f7, 0x025a: 0x11fe, 0x025b: 0x1207, 0x025c: 0x1210, 0x025d: 0x1219,
+ 0x025e: 0x1222, 0x025f: 0x122b, 0x0260: 0x1234, 0x0261: 0x123b, 0x0262: 0x1242, 0x0263: 0x124b,
+ 0x0264: 0x1254, 0x0265: 0x125d, 0x0266: 0x1266, 0x0267: 0x126f, 0x0268: 0x1278, 0x0269: 0x127f,
+ 0x026a: 0x1286, 0x026b: 0x128f, 0x026c: 0x1298, 0x026d: 0x12a1, 0x026e: 0x12aa, 0x026f: 0x12b3,
+ 0x0270: 0x12bc, 0x0271: 0x12c1, 0x0272: 0x12c6, 0x0273: 0x12cd, 0x0274: 0x12d2,
+ 0x0276: 0x12d9, 0x0277: 0x12de, 0x0278: 0x12e5, 0x0279: 0x12ea, 0x027a: 0x12ef, 0x027b: 0x04ee,
+ 0x027c: 0x12f4, 0x027e: 0x12fd,
// Block 0xa, offset 0x280
- 0x0285: 0x04e3,
- 0x0286: 0x04ee, 0x0287: 0x04f3, 0x0288: 0x04f6, 0x0289: 0x04fb, 0x028a: 0x0500,
- 0x028c: 0x0505, 0x028e: 0x050a, 0x028f: 0x050f, 0x0290: 0x0514,
- 0x02aa: 0x051b, 0x02ab: 0x0520, 0x02ac: 0x0525, 0x02ad: 0x052a, 0x02ae: 0x052f, 0x02af: 0x0534,
- 0x02b0: 0x0539,
+ 0x0281: 0x1304, 0x0282: 0x130f, 0x0283: 0x1316, 0x0284: 0x131b,
+ 0x0286: 0x1322, 0x0287: 0x1327, 0x0288: 0x132e, 0x0289: 0x04f6, 0x028a: 0x1333, 0x028b: 0x04fb,
+ 0x028c: 0x1338, 0x028d: 0x133d, 0x028e: 0x1349, 0x028f: 0x1355, 0x0290: 0x1361, 0x0291: 0x1366,
+ 0x0292: 0x136b, 0x0293: 0x0514, 0x0296: 0x1372, 0x0297: 0x1377,
+ 0x0298: 0x137e, 0x0299: 0x1383, 0x029a: 0x1388, 0x029b: 0x0500, 0x029d: 0x138d,
+ 0x029e: 0x1399, 0x029f: 0x13a5, 0x02a0: 0x13b1, 0x02a1: 0x13b6, 0x02a2: 0x13bb, 0x02a3: 0x0539,
+ 0x02a4: 0x13c2, 0x02a5: 0x13c7, 0x02a6: 0x13cc, 0x02a7: 0x13d1, 0x02a8: 0x13d8, 0x02a9: 0x13dd,
+ 0x02aa: 0x13e2, 0x02ab: 0x050a, 0x02ac: 0x13e7, 0x02ad: 0x13ec, 0x02ae: 0x04e3, 0x02af: 0x13f7,
+ 0x02b2: 0x13f9, 0x02b3: 0x1400, 0x02b4: 0x1405,
+ 0x02b6: 0x140c, 0x02b7: 0x1411, 0x02b8: 0x1418, 0x02b9: 0x0505, 0x02ba: 0x141d, 0x02bb: 0x050f,
+ 0x02bc: 0x1422, 0x02bd: 0x1427,
// Block 0xb, offset 0x2c0
- 0x02ca: 0x0540, 0x02cb: 0x0545,
- 0x02cc: 0x054a, 0x02cd: 0x054f, 0x02ce: 0x0554,
- 0x02d3: 0x0562, 0x02d4: 0x0567,
+ 0x02cc: 0x1b8a, 0x02ce: 0x1b91, 0x02d0: 0x1b98,
+ 0x02d2: 0x1b9f, 0x02d4: 0x1ba6, 0x02d6: 0x1bad,
+ 0x02d8: 0x1bb4, 0x02da: 0x1bbb, 0x02dc: 0x1bc2,
+ 0x02de: 0x1bc9, 0x02e0: 0x1bd0, 0x02e2: 0x1bd7,
+ 0x02e5: 0x1bde, 0x02e7: 0x1be5, 0x02e9: 0x1bec,
+ 0x02f0: 0x1bf3, 0x02f1: 0x1bfa, 0x02f3: 0x1c01, 0x02f4: 0x1c08,
+ 0x02f6: 0x1c0f, 0x02f7: 0x1c16, 0x02f9: 0x1c1d, 0x02fa: 0x1c24,
+ 0x02fc: 0x1c2b, 0x02fd: 0x1c32,
// Block 0xc, offset 0x300
- 0x0300: 0x0584, 0x0301: 0x0589, 0x0303: 0x058e,
- 0x0307: 0x0593,
- 0x030c: 0x0598, 0x030d: 0x059d, 0x030e: 0x05a2,
- 0x0319: 0x05a7,
- 0x0339: 0x05ac,
+ 0x0300: 0x2fce, 0x0301: 0x2fd2, 0x0302: 0x2fd6, 0x0303: 0x2fda, 0x0304: 0x2fde, 0x0305: 0x2fe2,
+ 0x0306: 0x2fe6, 0x0307: 0x2fea, 0x0308: 0x2fee, 0x0309: 0x2eed, 0x030a: 0x2ff2, 0x030b: 0x2ef1,
+ 0x030c: 0x2ff6, 0x030d: 0x2ffa, 0x030e: 0x2ffe, 0x030f: 0x3002, 0x0310: 0x3006, 0x0311: 0x2e6d,
+ 0x0312: 0x2b15, 0x0313: 0x300a, 0x0314: 0x300e, 0x0315: 0x195a, 0x0316: 0x2c25, 0x0317: 0x2d71,
+ 0x0318: 0x3012, 0x0319: 0x3016, 0x031a: 0x2f0d, 0x031b: 0x301a, 0x031c: 0x2f11, 0x031d: 0x301e,
+ 0x031e: 0x3022, 0x031f: 0x3026, 0x0320: 0x2e75, 0x0321: 0x302a, 0x0322: 0x302e, 0x0323: 0x3032,
+ 0x0324: 0x3036, 0x0325: 0x303a, 0x0326: 0x2e79, 0x0327: 0x303e, 0x0328: 0x3042, 0x0329: 0x3046,
+ 0x032a: 0x304a, 0x032b: 0x304e, 0x032c: 0x3052, 0x032d: 0x2f41, 0x032e: 0x3056, 0x032f: 0x305a,
+ 0x0330: 0x2cb1, 0x0331: 0x305e, 0x0332: 0x2f51, 0x0333: 0x3062, 0x0334: 0x3066, 0x0335: 0x306a,
+ 0x0336: 0x306e, 0x0337: 0x3072, 0x0338: 0x2f65, 0x0339: 0x3076, 0x033a: 0x2e99, 0x033b: 0x307a,
+ 0x033c: 0x2f69, 0x033d: 0x2bd9, 0x033e: 0x307e, 0x033f: 0x2f6d,
// Block 0xd, offset 0x340
- 0x0350: 0x05b1, 0x0351: 0x05b6,
- 0x0353: 0x05bb, 0x0357: 0x05c0,
- 0x035c: 0x05c5, 0x035d: 0x05ca,
- 0x035e: 0x05cf,
- 0x0376: 0x05d4, 0x0377: 0x05d9,
+ 0x0340: 0x3082, 0x0341: 0x2f75, 0x0342: 0x3086, 0x0343: 0x308a, 0x0344: 0x308e, 0x0345: 0x3092,
+ 0x0346: 0x3096, 0x0347: 0x2f7d, 0x0348: 0x2e8d, 0x0349: 0x309a, 0x034a: 0x2f81, 0x034b: 0x309e,
+ 0x034c: 0x2f85, 0x034d: 0x30a2, 0x034e: 0x1b76, 0x034f: 0x30a6, 0x0350: 0x30ab, 0x0351: 0x30b0,
+ 0x0352: 0x30b5, 0x0353: 0x30b9, 0x0354: 0x30bd, 0x0355: 0x30c1, 0x0356: 0x30c6, 0x0357: 0x30cb,
+ 0x0358: 0x30d0, 0x0359: 0x30d4,
// Block 0xe, offset 0x380
- 0x0381: 0x05de, 0x0382: 0x05e3,
- 0x0390: 0x05e8, 0x0391: 0x05ed,
- 0x0392: 0x05f2, 0x0393: 0x05f7, 0x0396: 0x05fc, 0x0397: 0x0601,
- 0x039a: 0x0606, 0x039b: 0x060b, 0x039c: 0x0610, 0x039d: 0x0615,
- 0x039e: 0x061a, 0x039f: 0x061f, 0x03a2: 0x0624, 0x03a3: 0x0629,
- 0x03a4: 0x062e, 0x03a5: 0x0633, 0x03a6: 0x0638, 0x03a7: 0x063d,
- 0x03aa: 0x0642, 0x03ab: 0x0647, 0x03ac: 0x064c, 0x03ad: 0x0651, 0x03ae: 0x0656, 0x03af: 0x065b,
- 0x03b0: 0x0660, 0x03b1: 0x0665, 0x03b2: 0x066a, 0x03b3: 0x066f, 0x03b4: 0x0674, 0x03b5: 0x0679,
- 0x03b8: 0x067e, 0x03b9: 0x0683,
+ 0x0380: 0x3d23, 0x0381: 0x3d27, 0x0382: 0x3d2b, 0x0383: 0x3d2f, 0x0384: 0x3d34, 0x0385: 0x2eb5,
+ 0x0386: 0x3d38, 0x0387: 0x3d3c, 0x0388: 0x3d40, 0x0389: 0x3d44, 0x038a: 0x2eb9, 0x038b: 0x3d48,
+ 0x038c: 0x3d4c, 0x038d: 0x3d50, 0x038e: 0x2ebd, 0x038f: 0x3d55, 0x0390: 0x3d59, 0x0391: 0x3d5d,
+ 0x0392: 0x3d61, 0x0393: 0x3d66, 0x0394: 0x3d6a, 0x0395: 0x3c71, 0x0396: 0x3d6e, 0x0397: 0x3d73,
+ 0x0398: 0x3d77, 0x0399: 0x3d7b, 0x039a: 0x3d7f, 0x039b: 0x2f9a, 0x039c: 0x3d83, 0x039d: 0x1866,
+ 0x039e: 0x3d88, 0x039f: 0x3d8c, 0x03a0: 0x3d90, 0x03a1: 0x3d94, 0x03a2: 0x3cb9, 0x03a3: 0x3d98,
+ 0x03a4: 0x3d9c, 0x03a5: 0x2fae, 0x03a6: 0x2ec1, 0x03a7: 0x2ec5, 0x03a8: 0x2fb2, 0x03a9: 0x3da0,
+ 0x03aa: 0x3da4, 0x03ab: 0x2bf1, 0x03ac: 0x3da8, 0x03ad: 0x2ec9, 0x03ae: 0x3dac, 0x03af: 0x3db0,
+ 0x03b0: 0x3db4, 0x03b1: 0x3db8, 0x03b2: 0x3db8, 0x03b3: 0x3db8, 0x03b4: 0x3dbc, 0x03b5: 0x3dc1,
+ 0x03b6: 0x3dc5, 0x03b7: 0x3dc9, 0x03b8: 0x3dcd, 0x03b9: 0x3dd2, 0x03ba: 0x3dd6, 0x03bb: 0x3dda,
+ 0x03bc: 0x3dde, 0x03bd: 0x3de2, 0x03be: 0x3de6, 0x03bf: 0x3dea,
// Block 0xf, offset 0x3c0
- 0x03e2: 0x068d, 0x03e3: 0x0692,
- 0x03e4: 0x0697, 0x03e5: 0x069c, 0x03e6: 0x06a1,
+ 0x03c0: 0x3dee, 0x03c1: 0x3df2, 0x03c2: 0x3df6, 0x03c3: 0x3dfa, 0x03c4: 0x3dfe, 0x03c5: 0x3e02,
+ 0x03c6: 0x3e02, 0x03c7: 0x2fba, 0x03c8: 0x3e06, 0x03c9: 0x3e0a, 0x03ca: 0x3e0e, 0x03cb: 0x3e12,
+ 0x03cc: 0x2ed1, 0x03cd: 0x3e16, 0x03ce: 0x3e1a, 0x03cf: 0x3e1e, 0x03d0: 0x2e39, 0x03d1: 0x3e22,
+ 0x03d2: 0x3e26, 0x03d3: 0x3e2a, 0x03d4: 0x3e2e, 0x03d5: 0x3e32, 0x03d6: 0x3e36, 0x03d7: 0x3e3a,
+ 0x03d8: 0x3e3e, 0x03d9: 0x3e42, 0x03da: 0x3e47, 0x03db: 0x3e4b, 0x03dc: 0x3e4f, 0x03dd: 0x3c55,
+ 0x03de: 0x3e53, 0x03df: 0x3e57, 0x03e0: 0x3e5b, 0x03e1: 0x3e60, 0x03e2: 0x3e65, 0x03e3: 0x3e69,
+ 0x03e4: 0x3e6d, 0x03e5: 0x3e71, 0x03e6: 0x3e75, 0x03e7: 0x3e79, 0x03e8: 0x3e7d, 0x03e9: 0x3e81,
+ 0x03ea: 0x3e85, 0x03eb: 0x3e85, 0x03ec: 0x3e89, 0x03ed: 0x3e8e, 0x03ee: 0x3e92, 0x03ef: 0x2be1,
+ 0x03f0: 0x3e96, 0x03f1: 0x3e9a, 0x03f2: 0x3e9f, 0x03f3: 0x3ea3, 0x03f4: 0x3ea7, 0x03f5: 0x18ce,
+ 0x03f6: 0x3eab, 0x03f7: 0x3eaf, 0x03f8: 0x18d6, 0x03f9: 0x3eb3, 0x03fa: 0x3eb7, 0x03fb: 0x3ebb,
+ 0x03fc: 0x3ec0, 0x03fd: 0x3ec4, 0x03fe: 0x3ec9, 0x03ff: 0x3ecd,
// Block 0x10, offset 0x400
- 0x0400: 0x06ba, 0x0402: 0x06bf,
- 0x0413: 0x06c4,
+ 0x0400: 0x3ed1, 0x0401: 0x3ed5, 0x0402: 0x3ed9, 0x0403: 0x3edd, 0x0404: 0x3ee1, 0x0405: 0x3ee5,
+ 0x0406: 0x3ee9, 0x0407: 0x3eed, 0x0408: 0x3ef1, 0x0409: 0x3ef5, 0x040a: 0x3efa, 0x040b: 0x3efe,
+ 0x040c: 0x3f02, 0x040d: 0x3f06, 0x040e: 0x2b11, 0x040f: 0x3f0a, 0x0410: 0x18fe, 0x0411: 0x3f0f,
+ 0x0412: 0x3f0f, 0x0413: 0x3f14, 0x0414: 0x3f18, 0x0415: 0x3f18, 0x0416: 0x3f1c, 0x0417: 0x3f20,
+ 0x0418: 0x3f25, 0x0419: 0x3f2a, 0x041a: 0x3f2e, 0x041b: 0x3f32, 0x041c: 0x3f36, 0x041d: 0x3f3a,
+ 0x041e: 0x3f3e, 0x041f: 0x3f42, 0x0420: 0x3f46, 0x0421: 0x3f4a, 0x0422: 0x3f4e, 0x0423: 0x2ee5,
+ 0x0424: 0x3f52, 0x0425: 0x3f57, 0x0426: 0x3f5b, 0x0427: 0x3f5f, 0x0428: 0x2fea, 0x0429: 0x3f5f,
+ 0x042a: 0x3f63, 0x042b: 0x2eed, 0x042c: 0x3f67, 0x042d: 0x3f6b, 0x042e: 0x3f6f, 0x042f: 0x3f73,
+ 0x0430: 0x2ef1, 0x0431: 0x2aa5, 0x0432: 0x3f77, 0x0433: 0x3f7b, 0x0434: 0x3f7f, 0x0435: 0x3f83,
+ 0x0436: 0x3f87, 0x0437: 0x3f8b, 0x0438: 0x3f8f, 0x0439: 0x3f94, 0x043a: 0x3f98, 0x043b: 0x3f9c,
+ 0x043c: 0x3fa0, 0x043d: 0x3fa4, 0x043e: 0x3fa8, 0x043f: 0x3fad,
// Block 0x11, offset 0x440
- 0x0469: 0x06c9,
- 0x0471: 0x06d0, 0x0474: 0x06d7,
+ 0x0440: 0x3fb1, 0x0441: 0x3fb5, 0x0442: 0x3fb9, 0x0443: 0x3fbd, 0x0444: 0x3fc1, 0x0445: 0x3fc5,
+ 0x0446: 0x3fc9, 0x0447: 0x3fcd, 0x0448: 0x2ef5, 0x0449: 0x3fd1, 0x044a: 0x3fd5, 0x044b: 0x3fda,
+ 0x044c: 0x3fde, 0x044d: 0x3fe2, 0x044e: 0x3fe6, 0x044f: 0x2efd, 0x0450: 0x3fea, 0x0451: 0x3fee,
+ 0x0452: 0x3ff2, 0x0453: 0x3ff6, 0x0454: 0x3ffa, 0x0455: 0x3ffe, 0x0456: 0x4002, 0x0457: 0x4006,
+ 0x0458: 0x2b15, 0x0459: 0x300a, 0x045a: 0x400a, 0x045b: 0x400e, 0x045c: 0x4012, 0x045d: 0x4016,
+ 0x045e: 0x401b, 0x045f: 0x401f, 0x0460: 0x4023, 0x0461: 0x4027, 0x0462: 0x2f01, 0x0463: 0x402b,
+ 0x0464: 0x4030, 0x0465: 0x4034, 0x0466: 0x4038, 0x0467: 0x30b5, 0x0468: 0x403c, 0x0469: 0x4040,
+ 0x046a: 0x4044, 0x046b: 0x4048, 0x046c: 0x404c, 0x046d: 0x4051, 0x046e: 0x4055, 0x046f: 0x4059,
+ 0x0470: 0x405d, 0x0471: 0x4062, 0x0472: 0x4066, 0x0473: 0x406a, 0x0474: 0x406e, 0x0475: 0x2c25,
+ 0x0476: 0x4072, 0x0477: 0x4076, 0x0478: 0x407b, 0x0479: 0x4080, 0x047a: 0x4085, 0x047b: 0x4089,
+ 0x047c: 0x408e, 0x047d: 0x4092, 0x047e: 0x4096, 0x047f: 0x409a,
// Block 0x12, offset 0x480
- 0x0498: 0x06de, 0x0499: 0x06e5, 0x049a: 0x06ec, 0x049b: 0x06f3, 0x049c: 0x06fa, 0x049d: 0x0701,
- 0x049e: 0x0708, 0x049f: 0x070f,
+ 0x0480: 0x409e, 0x0481: 0x2f05, 0x0482: 0x2d71, 0x0483: 0x40a2, 0x0484: 0x40a6, 0x0485: 0x40aa,
+ 0x0486: 0x40ae, 0x0487: 0x40b3, 0x0488: 0x40b7, 0x0489: 0x40bb, 0x048a: 0x40bf, 0x048b: 0x3016,
+ 0x048c: 0x40c3, 0x048d: 0x40c7, 0x048e: 0x40cc, 0x048f: 0x40d0, 0x0490: 0x40d4, 0x0491: 0x40d9,
+ 0x0492: 0x40de, 0x0493: 0x40e2, 0x0494: 0x301a, 0x0495: 0x40e6, 0x0496: 0x40ea, 0x0497: 0x40ee,
+ 0x0498: 0x40f2, 0x0499: 0x40f6, 0x049a: 0x40fa, 0x049b: 0x40fe, 0x049c: 0x4103, 0x049d: 0x4107,
+ 0x049e: 0x410c, 0x049f: 0x4110, 0x04a0: 0x4115, 0x04a1: 0x3022, 0x04a2: 0x4119, 0x04a3: 0x411d,
+ 0x04a4: 0x4122, 0x04a5: 0x4126, 0x04a6: 0x412a, 0x04a7: 0x412f, 0x04a8: 0x4134, 0x04a9: 0x4138,
+ 0x04aa: 0x413c, 0x04ab: 0x4140, 0x04ac: 0x4144, 0x04ad: 0x4144, 0x04ae: 0x4148, 0x04af: 0x414c,
+ 0x04b0: 0x302a, 0x04b1: 0x4150, 0x04b2: 0x4154, 0x04b3: 0x4158, 0x04b4: 0x415c, 0x04b5: 0x4160,
+ 0x04b6: 0x4165, 0x04b7: 0x4169, 0x04b8: 0x2bed, 0x04b9: 0x416e, 0x04ba: 0x4173, 0x04bb: 0x4177,
+ 0x04bc: 0x417c, 0x04bd: 0x4181, 0x04be: 0x4186, 0x04bf: 0x418a,
// Block 0x13, offset 0x4c0
- 0x04cb: 0x0716,
- 0x04cc: 0x071d,
- 0x04dc: 0x0724, 0x04dd: 0x072b,
- 0x04df: 0x0732,
+ 0x04c0: 0x3042, 0x04c1: 0x418e, 0x04c2: 0x4193, 0x04c3: 0x4198, 0x04c4: 0x419d, 0x04c5: 0x41a2,
+ 0x04c6: 0x41a6, 0x04c7: 0x41a6, 0x04c8: 0x3046, 0x04c9: 0x30bd, 0x04ca: 0x41aa, 0x04cb: 0x41ae,
+ 0x04cc: 0x41b2, 0x04cd: 0x41b6, 0x04ce: 0x41bb, 0x04cf: 0x2b59, 0x04d0: 0x304e, 0x04d1: 0x41bf,
+ 0x04d2: 0x41c3, 0x04d3: 0x2f2d, 0x04d4: 0x41c8, 0x04d5: 0x41cd, 0x04d6: 0x2e89, 0x04d7: 0x41d2,
+ 0x04d8: 0x41d6, 0x04d9: 0x2f39, 0x04da: 0x41da, 0x04db: 0x41de, 0x04dc: 0x41e2, 0x04dd: 0x41e7,
+ 0x04de: 0x41e7, 0x04df: 0x41ec, 0x04e0: 0x41f0, 0x04e1: 0x41f4, 0x04e2: 0x41f9, 0x04e3: 0x41fd,
+ 0x04e4: 0x4201, 0x04e5: 0x4205, 0x04e6: 0x420a, 0x04e7: 0x420e, 0x04e8: 0x4212, 0x04e9: 0x4216,
+ 0x04ea: 0x421a, 0x04eb: 0x421e, 0x04ec: 0x4223, 0x04ed: 0x4227, 0x04ee: 0x422b, 0x04ef: 0x422f,
+ 0x04f0: 0x4233, 0x04f1: 0x4237, 0x04f2: 0x423b, 0x04f3: 0x4240, 0x04f4: 0x4245, 0x04f5: 0x4249,
+ 0x04f6: 0x424e, 0x04f7: 0x4252, 0x04f8: 0x4257, 0x04f9: 0x425b, 0x04fa: 0x2f51, 0x04fb: 0x425f,
+ 0x04fc: 0x4264, 0x04fd: 0x4269, 0x04fe: 0x426d, 0x04ff: 0x4272,
// Block 0x14, offset 0x500
- 0x0533: 0x0739,
- 0x0536: 0x0740,
+ 0x0500: 0x4276, 0x0501: 0x427b, 0x0502: 0x427f, 0x0503: 0x4283, 0x0504: 0x4287, 0x0505: 0x428b,
+ 0x0506: 0x428f, 0x0507: 0x4293, 0x0508: 0x4298, 0x0509: 0x429d, 0x050a: 0x42a2, 0x050b: 0x3f14,
+ 0x050c: 0x42a7, 0x050d: 0x42ab, 0x050e: 0x42af, 0x050f: 0x42b3, 0x0510: 0x42b7, 0x0511: 0x42bb,
+ 0x0512: 0x42bf, 0x0513: 0x42c3, 0x0514: 0x42c7, 0x0515: 0x42cb, 0x0516: 0x42cf, 0x0517: 0x42d3,
+ 0x0518: 0x2c31, 0x0519: 0x42d8, 0x051a: 0x42dc, 0x051b: 0x42e0, 0x051c: 0x42e4, 0x051d: 0x42e8,
+ 0x051e: 0x42ec, 0x051f: 0x2f5d, 0x0520: 0x42f0, 0x0521: 0x42f4, 0x0522: 0x42f8, 0x0523: 0x42fc,
+ 0x0524: 0x4300, 0x0525: 0x4305, 0x0526: 0x430a, 0x0527: 0x430f, 0x0528: 0x4313, 0x0529: 0x4317,
+ 0x052a: 0x431b, 0x052b: 0x431f, 0x052c: 0x4324, 0x052d: 0x4328, 0x052e: 0x432d, 0x052f: 0x4331,
+ 0x0530: 0x4335, 0x0531: 0x433a, 0x0532: 0x433f, 0x0533: 0x4343, 0x0534: 0x2b45, 0x0535: 0x4347,
+ 0x0536: 0x434b, 0x0537: 0x434f, 0x0538: 0x4353, 0x0539: 0x4357, 0x053a: 0x435b, 0x053b: 0x306a,
+ 0x053c: 0x435f, 0x053d: 0x4363, 0x053e: 0x4367, 0x053f: 0x436b,
// Block 0x15, offset 0x540
- 0x0559: 0x0747, 0x055a: 0x074e, 0x055b: 0x0755,
- 0x055e: 0x075c,
- // Block 0x16, offset 0x580
- 0x0588: 0x0763, 0x058b: 0x076a,
- 0x058c: 0x0771,
- 0x059c: 0x0778, 0x059d: 0x077f,
- // Block 0x17, offset 0x5c0
- 0x05d4: 0x0786,
- // Block 0x18, offset 0x600
- 0x060a: 0x078d, 0x060b: 0x0794,
- 0x060c: 0x079b,
- // Block 0x19, offset 0x640
- 0x0648: 0x07a2,
- // Block 0x1a, offset 0x680
- 0x0680: 0x07a9,
- 0x0687: 0x07b0, 0x0688: 0x07b7, 0x068a: 0x07be, 0x068b: 0x07c5,
- // Block 0x1b, offset 0x6c0
- 0x06ca: 0x07cf, 0x06cb: 0x07d6,
- 0x06cc: 0x07dd,
- // Block 0x1c, offset 0x700
- 0x071a: 0x07e4, 0x071c: 0x07eb, 0x071d: 0x07f2,
- 0x071e: 0x07fc,
- // Block 0x1d, offset 0x740
- 0x0743: 0x0823,
- 0x074d: 0x082a,
- 0x0752: 0x0831, 0x0757: 0x0838,
- 0x075c: 0x083f,
- 0x0769: 0x0846,
- 0x0773: 0x084d, 0x0775: 0x0854,
- 0x0776: 0x085b, 0x0778: 0x086c,
- // Block 0x1e, offset 0x780
- 0x0781: 0x087d,
- 0x0793: 0x0884,
- 0x079d: 0x088b,
- 0x07a2: 0x0892,
- 0x07a7: 0x0899,
- 0x07ac: 0x08a0,
- 0x07b9: 0x08a7,
- // Block 0x1f, offset 0x7c0
- 0x07e6: 0x08ae,
- // Block 0x20, offset 0x800
- 0x0806: 0x08b9, 0x0808: 0x08c0, 0x080a: 0x08c7,
- 0x080c: 0x08ce, 0x080e: 0x08d5,
- 0x0812: 0x08dc,
- 0x083b: 0x08e3,
- 0x083d: 0x08ea,
- // Block 0x21, offset 0x840
- 0x0840: 0x08f1, 0x0841: 0x08f8, 0x0843: 0x08ff,
- // Block 0x22, offset 0x880
- 0x0880: 0x09ea, 0x0881: 0x09ee, 0x0882: 0x09f2, 0x0883: 0x09f6, 0x0884: 0x09fa, 0x0885: 0x09fe,
- 0x0886: 0x0a02, 0x0887: 0x0a06, 0x0888: 0x0a0a, 0x0889: 0x0a10, 0x088a: 0x0a16, 0x088b: 0x0a1a,
- 0x088c: 0x0a1e, 0x088d: 0x0a22, 0x088e: 0x0a26, 0x088f: 0x0a2a, 0x0890: 0x0a2e, 0x0891: 0x0a32,
- 0x0892: 0x0a36, 0x0893: 0x0a3a, 0x0894: 0x0a3e, 0x0895: 0x0a44, 0x0896: 0x0a4a, 0x0897: 0x0a50,
- 0x0898: 0x0a56, 0x0899: 0x0a5a, 0x089a: 0x0a5e, 0x089b: 0x0a62, 0x089c: 0x0a66, 0x089d: 0x0a6c,
- 0x089e: 0x0a72, 0x089f: 0x0a76, 0x08a0: 0x0a7a, 0x08a1: 0x0a7e, 0x08a2: 0x0a82, 0x08a3: 0x0a86,
- 0x08a4: 0x0a8a, 0x08a5: 0x0a8e, 0x08a6: 0x0a92, 0x08a7: 0x0a96, 0x08a8: 0x0a9a, 0x08a9: 0x0a9e,
- 0x08aa: 0x0aa2, 0x08ab: 0x0aa6, 0x08ac: 0x0aaa, 0x08ad: 0x0aae, 0x08ae: 0x0ab2, 0x08af: 0x0ab8,
- 0x08b0: 0x0abe, 0x08b1: 0x0ac2, 0x08b2: 0x0ac6, 0x08b3: 0x0aca, 0x08b4: 0x0ace, 0x08b5: 0x0ad2,
- 0x08b6: 0x0ad6, 0x08b7: 0x0ada, 0x08b8: 0x0ade, 0x08b9: 0x0ae4, 0x08ba: 0x0aea, 0x08bb: 0x0aee,
- 0x08bc: 0x0af2, 0x08bd: 0x0af6, 0x08be: 0x0afa, 0x08bf: 0x0afe,
- // Block 0x23, offset 0x8c0
- 0x08c0: 0x0b02, 0x08c1: 0x0b06, 0x08c2: 0x0b0a, 0x08c3: 0x0b0e, 0x08c4: 0x0b12, 0x08c5: 0x0b16,
- 0x08c6: 0x0b1a, 0x08c7: 0x0b1e, 0x08c8: 0x0b22, 0x08c9: 0x0b26, 0x08ca: 0x0b2a, 0x08cb: 0x0b2e,
- 0x08cc: 0x0b32, 0x08cd: 0x0b38, 0x08ce: 0x0b3e, 0x08cf: 0x0b44, 0x08d0: 0x0b4a, 0x08d1: 0x0b50,
- 0x08d2: 0x0b56, 0x08d3: 0x0b5c, 0x08d4: 0x0b62, 0x08d5: 0x0b66, 0x08d6: 0x0b6a, 0x08d7: 0x0b6e,
- 0x08d8: 0x0b72, 0x08d9: 0x0b76, 0x08da: 0x0b7a, 0x08db: 0x0b7e, 0x08dc: 0x0b82, 0x08dd: 0x0b88,
- 0x08de: 0x0b8e, 0x08df: 0x0b92, 0x08e0: 0x0b96, 0x08e1: 0x0b9a, 0x08e2: 0x0b9e, 0x08e3: 0x0ba2,
- 0x08e4: 0x0ba6, 0x08e5: 0x0bac, 0x08e6: 0x0bb2, 0x08e7: 0x0bb8, 0x08e8: 0x0bbe, 0x08e9: 0x0bc4,
- 0x08ea: 0x0bca, 0x08eb: 0x0bce, 0x08ec: 0x0bd2, 0x08ed: 0x0bd6, 0x08ee: 0x0bda, 0x08ef: 0x0bde,
- 0x08f0: 0x0be2, 0x08f1: 0x0be6, 0x08f2: 0x0bea, 0x08f3: 0x0bee, 0x08f4: 0x0bf2, 0x08f5: 0x0bf6,
- 0x08f6: 0x0bfa, 0x08f7: 0x0bfe, 0x08f8: 0x0c02, 0x08f9: 0x0c08, 0x08fa: 0x0c0e, 0x08fb: 0x0c14,
- 0x08fc: 0x0c1a, 0x08fd: 0x0c1e, 0x08fe: 0x0c22, 0x08ff: 0x0c26,
- // Block 0x24, offset 0x900
- 0x0900: 0x0c2a, 0x0901: 0x0c2e, 0x0902: 0x0c32, 0x0903: 0x0c36, 0x0904: 0x0c3a, 0x0905: 0x0c3e,
- 0x0906: 0x0c42, 0x0907: 0x0c46, 0x0908: 0x0c4a, 0x0909: 0x0c4e, 0x090a: 0x0c52, 0x090b: 0x0c56,
- 0x090c: 0x0c5a, 0x090d: 0x0c5e, 0x090e: 0x0c62, 0x090f: 0x0c66, 0x0910: 0x0c6a, 0x0911: 0x0c6e,
- 0x0912: 0x0c72, 0x0913: 0x0c76, 0x0914: 0x0c7a, 0x0915: 0x0c7e, 0x0916: 0x0c82, 0x0917: 0x0c86,
- 0x0918: 0x0c8a, 0x0919: 0x0c8e, 0x091b: 0x0c96,
- 0x0920: 0x0c9b, 0x0921: 0x0c9f, 0x0922: 0x0ca3, 0x0923: 0x0ca7,
- 0x0924: 0x0cab, 0x0925: 0x0cb1, 0x0926: 0x0cb7, 0x0927: 0x0cbd, 0x0928: 0x0cc3, 0x0929: 0x0cc9,
- 0x092a: 0x0ccf, 0x092b: 0x0cd5, 0x092c: 0x0cdb, 0x092d: 0x0ce1, 0x092e: 0x0ce7, 0x092f: 0x0ced,
- 0x0930: 0x0cf3, 0x0931: 0x0cf9, 0x0932: 0x0cff, 0x0933: 0x0d05, 0x0934: 0x0d0b, 0x0935: 0x0d11,
- 0x0936: 0x0d17, 0x0937: 0x0d1d, 0x0938: 0x0d23, 0x0939: 0x0d27, 0x093a: 0x0d2b, 0x093b: 0x0d2f,
- 0x093c: 0x0d33, 0x093d: 0x0d37, 0x093e: 0x0d3b, 0x093f: 0x0d41,
- // Block 0x25, offset 0x940
- 0x0940: 0x0d47, 0x0941: 0x0d4d, 0x0942: 0x0d53, 0x0943: 0x0d59, 0x0944: 0x0d5f, 0x0945: 0x0d65,
- 0x0946: 0x0d6b, 0x0947: 0x0d71, 0x0948: 0x0d77, 0x0949: 0x0d7b, 0x094a: 0x0d7f, 0x094b: 0x0d83,
- 0x094c: 0x0d87, 0x094d: 0x0d8b, 0x094e: 0x0d8f, 0x094f: 0x0d93, 0x0950: 0x0d97, 0x0951: 0x0d9d,
- 0x0952: 0x0da3, 0x0953: 0x0da9, 0x0954: 0x0daf, 0x0955: 0x0db5, 0x0956: 0x0dbb, 0x0957: 0x0dc1,
- 0x0958: 0x0dc7, 0x0959: 0x0dcd, 0x095a: 0x0dd3, 0x095b: 0x0dd9, 0x095c: 0x0ddf, 0x095d: 0x0de5,
- 0x095e: 0x0deb, 0x095f: 0x0df1, 0x0960: 0x0df7, 0x0961: 0x0dfd, 0x0962: 0x0e03, 0x0963: 0x0e09,
- 0x0964: 0x0e0f, 0x0965: 0x0e13, 0x0966: 0x0e17, 0x0967: 0x0e1b, 0x0968: 0x0e1f, 0x0969: 0x0e25,
- 0x096a: 0x0e2b, 0x096b: 0x0e31, 0x096c: 0x0e37, 0x096d: 0x0e3d, 0x096e: 0x0e43, 0x096f: 0x0e49,
- 0x0970: 0x0e4f, 0x0971: 0x0e55, 0x0972: 0x0e5b, 0x0973: 0x0e5f, 0x0974: 0x0e63, 0x0975: 0x0e67,
- 0x0976: 0x0e6b, 0x0977: 0x0e6f, 0x0978: 0x0e73, 0x0979: 0x0e77,
- // Block 0x26, offset 0x980
- 0x0980: 0x0e7b, 0x0981: 0x0e80, 0x0982: 0x0e85, 0x0983: 0x0e8c, 0x0984: 0x0e93, 0x0985: 0x0e9a,
- 0x0986: 0x0ea1, 0x0987: 0x0ea8, 0x0988: 0x0eaf, 0x0989: 0x0eb4, 0x098a: 0x0eb9, 0x098b: 0x0ec0,
- 0x098c: 0x0ec7, 0x098d: 0x0ece, 0x098e: 0x0ed5, 0x098f: 0x0edc, 0x0990: 0x0ee3, 0x0991: 0x0ee8,
- 0x0992: 0x0eed, 0x0993: 0x0ef4, 0x0994: 0x0efb, 0x0995: 0x0f02,
- 0x0998: 0x0f09, 0x0999: 0x0f0e, 0x099a: 0x0f13, 0x099b: 0x0f1a, 0x099c: 0x0f21, 0x099d: 0x0f28,
- 0x09a0: 0x0f2f, 0x09a1: 0x0f34, 0x09a2: 0x0f39, 0x09a3: 0x0f40,
- 0x09a4: 0x0f47, 0x09a5: 0x0f4e, 0x09a6: 0x0f55, 0x09a7: 0x0f5c, 0x09a8: 0x0f63, 0x09a9: 0x0f68,
- 0x09aa: 0x0f6d, 0x09ab: 0x0f74, 0x09ac: 0x0f7b, 0x09ad: 0x0f82, 0x09ae: 0x0f89, 0x09af: 0x0f90,
- 0x09b0: 0x0f97, 0x09b1: 0x0f9c, 0x09b2: 0x0fa1, 0x09b3: 0x0fa8, 0x09b4: 0x0faf, 0x09b5: 0x0fb6,
- 0x09b6: 0x0fbd, 0x09b7: 0x0fc4, 0x09b8: 0x0fcb, 0x09b9: 0x0fd0, 0x09ba: 0x0fd5, 0x09bb: 0x0fdc,
- 0x09bc: 0x0fe3, 0x09bd: 0x0fea, 0x09be: 0x0ff1, 0x09bf: 0x0ff8,
- // Block 0x27, offset 0x9c0
- 0x09c0: 0x0fff, 0x09c1: 0x1004, 0x09c2: 0x1009, 0x09c3: 0x1010, 0x09c4: 0x1017, 0x09c5: 0x101e,
- 0x09c8: 0x1025, 0x09c9: 0x102a, 0x09ca: 0x102f, 0x09cb: 0x1036,
- 0x09cc: 0x103d, 0x09cd: 0x1044, 0x09d0: 0x104b, 0x09d1: 0x1050,
- 0x09d2: 0x1055, 0x09d3: 0x105c, 0x09d4: 0x1063, 0x09d5: 0x106a, 0x09d6: 0x1071, 0x09d7: 0x1078,
- 0x09d9: 0x107f, 0x09db: 0x1084, 0x09dd: 0x108b,
- 0x09df: 0x1092, 0x09e0: 0x1099, 0x09e1: 0x109e, 0x09e2: 0x10a3, 0x09e3: 0x10aa,
- 0x09e4: 0x10b1, 0x09e5: 0x10b8, 0x09e6: 0x10bf, 0x09e7: 0x10c6, 0x09e8: 0x10cd, 0x09e9: 0x10d2,
- 0x09ea: 0x10d7, 0x09eb: 0x10de, 0x09ec: 0x10e5, 0x09ed: 0x10ec, 0x09ee: 0x10f3, 0x09ef: 0x10fa,
- 0x09f0: 0x1101, 0x09f1: 0x0525, 0x09f2: 0x1106, 0x09f3: 0x052a, 0x09f4: 0x110b, 0x09f5: 0x052f,
- 0x09f6: 0x1110, 0x09f7: 0x0534, 0x09f8: 0x1115, 0x09f9: 0x054a, 0x09fa: 0x111a, 0x09fb: 0x054f,
- 0x09fc: 0x111f, 0x09fd: 0x0554,
- // Block 0x28, offset 0xa00
- 0x0a00: 0x1124, 0x0a01: 0x112b, 0x0a02: 0x1132, 0x0a03: 0x113b, 0x0a04: 0x1144, 0x0a05: 0x114d,
- 0x0a06: 0x1156, 0x0a07: 0x115f, 0x0a08: 0x1168, 0x0a09: 0x116f, 0x0a0a: 0x1176, 0x0a0b: 0x117f,
- 0x0a0c: 0x1188, 0x0a0d: 0x1191, 0x0a0e: 0x119a, 0x0a0f: 0x11a3, 0x0a10: 0x11ac, 0x0a11: 0x11b3,
- 0x0a12: 0x11ba, 0x0a13: 0x11c3, 0x0a14: 0x11cc, 0x0a15: 0x11d5, 0x0a16: 0x11de, 0x0a17: 0x11e7,
- 0x0a18: 0x11f0, 0x0a19: 0x11f7, 0x0a1a: 0x11fe, 0x0a1b: 0x1207, 0x0a1c: 0x1210, 0x0a1d: 0x1219,
- 0x0a1e: 0x1222, 0x0a1f: 0x122b, 0x0a20: 0x1234, 0x0a21: 0x123b, 0x0a22: 0x1242, 0x0a23: 0x124b,
- 0x0a24: 0x1254, 0x0a25: 0x125d, 0x0a26: 0x1266, 0x0a27: 0x126f, 0x0a28: 0x1278, 0x0a29: 0x127f,
- 0x0a2a: 0x1286, 0x0a2b: 0x128f, 0x0a2c: 0x1298, 0x0a2d: 0x12a1, 0x0a2e: 0x12aa, 0x0a2f: 0x12b3,
- 0x0a30: 0x12bc, 0x0a31: 0x12c1, 0x0a32: 0x12c6, 0x0a33: 0x12cd, 0x0a34: 0x12d2,
- 0x0a36: 0x12d9, 0x0a37: 0x12de, 0x0a38: 0x12e5, 0x0a39: 0x12ea, 0x0a3a: 0x12ef, 0x0a3b: 0x04ee,
- 0x0a3c: 0x12f4, 0x0a3e: 0x12fd,
- // Block 0x29, offset 0xa40
- 0x0a41: 0x1304, 0x0a42: 0x130f, 0x0a43: 0x1316, 0x0a44: 0x131b,
- 0x0a46: 0x1322, 0x0a47: 0x1327, 0x0a48: 0x132e, 0x0a49: 0x04f6, 0x0a4a: 0x1333, 0x0a4b: 0x04fb,
- 0x0a4c: 0x1338, 0x0a4d: 0x133d, 0x0a4e: 0x1349, 0x0a4f: 0x1355, 0x0a50: 0x1361, 0x0a51: 0x1366,
- 0x0a52: 0x136b, 0x0a53: 0x0514, 0x0a56: 0x1372, 0x0a57: 0x1377,
- 0x0a58: 0x137e, 0x0a59: 0x1383, 0x0a5a: 0x1388, 0x0a5b: 0x0500, 0x0a5d: 0x138d,
- 0x0a5e: 0x1399, 0x0a5f: 0x13a5, 0x0a60: 0x13b1, 0x0a61: 0x13b6, 0x0a62: 0x13bb, 0x0a63: 0x0539,
- 0x0a64: 0x13c2, 0x0a65: 0x13c7, 0x0a66: 0x13cc, 0x0a67: 0x13d1, 0x0a68: 0x13d8, 0x0a69: 0x13dd,
- 0x0a6a: 0x13e2, 0x0a6b: 0x050a, 0x0a6c: 0x13e7, 0x0a6d: 0x13ec, 0x0a6e: 0x04e3, 0x0a6f: 0x13f7,
- 0x0a72: 0x13f9, 0x0a73: 0x1400, 0x0a74: 0x1405,
- 0x0a76: 0x140c, 0x0a77: 0x1411, 0x0a78: 0x1418, 0x0a79: 0x0505, 0x0a7a: 0x141d, 0x0a7b: 0x050f,
- 0x0a7c: 0x1422, 0x0a7d: 0x1427,
- // Block 0x2a, offset 0xa80
- 0x0a80: 0x142e, 0x0a81: 0x1432,
- // Block 0x2b, offset 0xac0
- 0x0ae6: 0x14d6,
- 0x0aea: 0x091c, 0x0aeb: 0x0046,
- // Block 0x2c, offset 0xb00
- 0x0b1a: 0x159f, 0x0b1b: 0x15a5,
- 0x0b2e: 0x15ab,
- // Block 0x2d, offset 0xb40
- 0x0b4d: 0x15b1, 0x0b4e: 0x15b7, 0x0b4f: 0x15bd,
- // Block 0x2e, offset 0xb80
- 0x0b84: 0x15c3,
- 0x0b89: 0x15c9,
- 0x0b8c: 0x15cf,
- 0x0ba4: 0x15d5, 0x0ba6: 0x15db,
- // Block 0x2f, offset 0xbc0
- 0x0bc1: 0x1603, 0x0bc4: 0x1609,
- 0x0bc7: 0x160f, 0x0bc9: 0x1615,
- 0x0be0: 0x161b, 0x0be2: 0x161f,
- 0x0bed: 0x1625, 0x0bee: 0x162b, 0x0bef: 0x162f,
- 0x0bf0: 0x1633, 0x0bf1: 0x1639, 0x0bf4: 0x163f, 0x0bf5: 0x1645,
- 0x0bf8: 0x164b, 0x0bf9: 0x1651,
- // Block 0x30, offset 0xc00
- 0x0c00: 0x1657, 0x0c01: 0x165d, 0x0c04: 0x1663, 0x0c05: 0x1669,
- 0x0c08: 0x166f, 0x0c09: 0x1675,
- 0x0c2c: 0x167b, 0x0c2d: 0x1681, 0x0c2e: 0x1687, 0x0c2f: 0x168d,
- // Block 0x31, offset 0xc40
- 0x0c60: 0x1693, 0x0c61: 0x1699, 0x0c62: 0x169f, 0x0c63: 0x16a5,
- 0x0c6a: 0x16ab, 0x0c6b: 0x16b1, 0x0c6c: 0x16b7, 0x0c6d: 0x16bd,
- // Block 0x32, offset 0xc80
- 0x0ca9: 0x16c3,
- 0x0caa: 0x16c7,
- // Block 0x33, offset 0xcc0
- 0x0cdc: 0x1814,
- // Block 0x34, offset 0xd00
- 0x0d0c: 0x1b8a, 0x0d0e: 0x1b91, 0x0d10: 0x1b98,
- 0x0d12: 0x1b9f, 0x0d14: 0x1ba6, 0x0d16: 0x1bad,
- 0x0d18: 0x1bb4, 0x0d1a: 0x1bbb, 0x0d1c: 0x1bc2,
- 0x0d1e: 0x1bc9, 0x0d20: 0x1bd0, 0x0d22: 0x1bd7,
- 0x0d25: 0x1bde, 0x0d27: 0x1be5, 0x0d29: 0x1bec,
- 0x0d30: 0x1bf3, 0x0d31: 0x1bfa, 0x0d33: 0x1c01, 0x0d34: 0x1c08,
- 0x0d36: 0x1c0f, 0x0d37: 0x1c16, 0x0d39: 0x1c1d, 0x0d3a: 0x1c24,
- 0x0d3c: 0x1c2b, 0x0d3d: 0x1c32,
- // Block 0x35, offset 0xd40
- 0x0d54: 0x1c39,
- 0x0d5e: 0x1c4a,
- 0x0d6c: 0x1c58, 0x0d6e: 0x1c5f,
- 0x0d70: 0x1c66, 0x0d72: 0x1c6d, 0x0d74: 0x1c74,
- 0x0d76: 0x1c7b, 0x0d78: 0x1c82, 0x0d7a: 0x1c89,
- 0x0d7c: 0x1c90, 0x0d7e: 0x1c97,
- // Block 0x36, offset 0xd80
- 0x0d80: 0x1c9e, 0x0d82: 0x1ca5, 0x0d85: 0x1cac,
- 0x0d87: 0x1cb3, 0x0d89: 0x1cba,
- 0x0d90: 0x1cc1, 0x0d91: 0x1cc8,
- 0x0d93: 0x1ccf, 0x0d94: 0x1cd6, 0x0d96: 0x1cdd, 0x0d97: 0x1ce4,
- 0x0d99: 0x1ceb, 0x0d9a: 0x1cf2, 0x0d9c: 0x1cf9, 0x0d9d: 0x1d00,
- 0x0db4: 0x1d07,
- 0x0db7: 0x1d0e, 0x0db8: 0x1d15, 0x0db9: 0x1d1c, 0x0dba: 0x1d23,
- 0x0dbe: 0x1d2a,
- // Block 0x37, offset 0xdc0
- 0x0dc0: 0x2a81, 0x0dc1: 0x2a85, 0x0dc2: 0x1a9e, 0x0dc3: 0x2a89, 0x0dc4: 0x2a8d, 0x0dc5: 0x2a91,
- 0x0dc6: 0x2a95, 0x0dc7: 0x1b76, 0x0dc8: 0x1b76, 0x0dc9: 0x2a99, 0x0dca: 0x1abe, 0x0dcb: 0x2a9d,
- 0x0dcc: 0x2aa1, 0x0dcd: 0x2aa5, 0x0dce: 0x2aa9, 0x0dcf: 0x2aad, 0x0dd0: 0x2ab1, 0x0dd1: 0x2ab5,
- 0x0dd2: 0x2ab9, 0x0dd3: 0x2abd, 0x0dd4: 0x2ac1, 0x0dd5: 0x2ac5, 0x0dd6: 0x2ac9, 0x0dd7: 0x2acd,
- 0x0dd8: 0x2ad1, 0x0dd9: 0x2ad5, 0x0dda: 0x2ad9, 0x0ddb: 0x2add, 0x0ddc: 0x2ae1, 0x0ddd: 0x2ae5,
- 0x0dde: 0x2ae9, 0x0ddf: 0x2aed, 0x0de0: 0x2af1, 0x0de1: 0x2af5, 0x0de2: 0x2af9, 0x0de3: 0x2afd,
- 0x0de4: 0x2b01, 0x0de5: 0x2b05, 0x0de6: 0x2b09, 0x0de7: 0x2b0d, 0x0de8: 0x2b11, 0x0de9: 0x2b15,
- 0x0dea: 0x2b19, 0x0deb: 0x2b1d, 0x0dec: 0x2b21, 0x0ded: 0x2b25, 0x0dee: 0x2b29, 0x0def: 0x2b2d,
- 0x0df0: 0x2b31, 0x0df1: 0x2b35, 0x0df2: 0x2b39, 0x0df3: 0x2b3d, 0x0df4: 0x1a16, 0x0df5: 0x2b41,
- 0x0df6: 0x2b45, 0x0df7: 0x2b49, 0x0df8: 0x2b4d, 0x0df9: 0x2b51, 0x0dfa: 0x2b55, 0x0dfb: 0x2b59,
- 0x0dfc: 0x2b5d, 0x0dfd: 0x2b61, 0x0dfe: 0x2b65, 0x0dff: 0x2b69,
- // Block 0x38, offset 0xe00
- 0x0e00: 0x1b3a, 0x0e01: 0x2b6d, 0x0e02: 0x2b71, 0x0e03: 0x2b75, 0x0e04: 0x2b79, 0x0e05: 0x2b7d,
- 0x0e06: 0x2b81, 0x0e07: 0x2b85, 0x0e08: 0x2b89, 0x0e09: 0x2b8d, 0x0e0a: 0x2b91, 0x0e0b: 0x2b95,
- 0x0e0c: 0x2b99, 0x0e0d: 0x2b9d, 0x0e0e: 0x2ba1, 0x0e0f: 0x2ba5, 0x0e10: 0x2ba9, 0x0e11: 0x2bad,
- 0x0e12: 0x2bb1, 0x0e13: 0x2bb5, 0x0e14: 0x2bb9, 0x0e15: 0x2bbd, 0x0e16: 0x2bc1, 0x0e17: 0x2bc5,
- 0x0e18: 0x2bc9, 0x0e19: 0x2bcd, 0x0e1a: 0x2bd1, 0x0e1b: 0x2bd5, 0x0e1c: 0x2ac1, 0x0e1d: 0x2bd9,
- 0x0e1e: 0x2bdd, 0x0e1f: 0x2be1, 0x0e20: 0x2be5, 0x0e21: 0x2be9, 0x0e22: 0x2bed, 0x0e23: 0x2bf1,
- 0x0e24: 0x2bf5, 0x0e25: 0x2bf9, 0x0e26: 0x2bfd, 0x0e27: 0x2c01, 0x0e28: 0x2c05, 0x0e29: 0x2c09,
- 0x0e2a: 0x2c0d, 0x0e2b: 0x2c11, 0x0e2c: 0x2c15, 0x0e2d: 0x2c19, 0x0e2e: 0x2c1d, 0x0e2f: 0x2c21,
- 0x0e30: 0x2c25, 0x0e31: 0x1aa6, 0x0e32: 0x2c29, 0x0e33: 0x2c2d, 0x0e34: 0x2c31, 0x0e35: 0x2c35,
- 0x0e36: 0x2c39, 0x0e37: 0x2c3d, 0x0e38: 0x2c41, 0x0e39: 0x2c45, 0x0e3a: 0x2c49, 0x0e3b: 0x2c4d,
- 0x0e3c: 0x2c51, 0x0e3d: 0x2c55, 0x0e3e: 0x2c59, 0x0e3f: 0x2c5d,
- // Block 0x39, offset 0xe40
- 0x0e40: 0x2c61, 0x0e41: 0x18ba, 0x0e42: 0x2c65, 0x0e43: 0x2c69, 0x0e44: 0x2c6d, 0x0e45: 0x2c71,
- 0x0e46: 0x2c75, 0x0e47: 0x2c79, 0x0e48: 0x2c7d, 0x0e49: 0x2c81, 0x0e4a: 0x186e, 0x0e4b: 0x2c85,
- 0x0e4c: 0x2c89, 0x0e4d: 0x2c8d, 0x0e4e: 0x2c91, 0x0e4f: 0x2c95, 0x0e50: 0x2c99, 0x0e51: 0x2c9d,
- 0x0e52: 0x2ca1, 0x0e53: 0x2ca5, 0x0e54: 0x2ca9, 0x0e55: 0x2cad, 0x0e56: 0x2cb1, 0x0e57: 0x2cb5,
- 0x0e58: 0x2cb9, 0x0e59: 0x2cbd, 0x0e5a: 0x2cc1, 0x0e5b: 0x2cc5, 0x0e5c: 0x2cc9, 0x0e5d: 0x2ccd,
- 0x0e5e: 0x2cd1, 0x0e5f: 0x2cd5, 0x0e60: 0x2cd9, 0x0e61: 0x2c21, 0x0e62: 0x2cdd, 0x0e63: 0x2ce1,
- 0x0e64: 0x2ce5, 0x0e65: 0x2ce9, 0x0e66: 0x2ced, 0x0e67: 0x2cf1, 0x0e68: 0x2cf5, 0x0e69: 0x2cf9,
- 0x0e6a: 0x2be1, 0x0e6b: 0x2cfd, 0x0e6c: 0x2d01, 0x0e6d: 0x2d05, 0x0e6e: 0x2d09, 0x0e6f: 0x2d0d,
- 0x0e70: 0x2d11, 0x0e71: 0x2d15, 0x0e72: 0x2d19, 0x0e73: 0x2d1d, 0x0e74: 0x2d21, 0x0e75: 0x2d25,
- 0x0e76: 0x2d29, 0x0e77: 0x2d2d, 0x0e78: 0x2d31, 0x0e79: 0x2d35, 0x0e7a: 0x2d39, 0x0e7b: 0x2d3d,
- 0x0e7c: 0x2d41, 0x0e7d: 0x2d45, 0x0e7e: 0x2d49, 0x0e7f: 0x2ac1,
- // Block 0x3a, offset 0xe80
- 0x0e80: 0x2d4d, 0x0e81: 0x2d51, 0x0e82: 0x2d55, 0x0e83: 0x2d59, 0x0e84: 0x1b72, 0x0e85: 0x2d5d,
- 0x0e86: 0x2d61, 0x0e87: 0x2d65, 0x0e88: 0x2d69, 0x0e89: 0x2d6d, 0x0e8a: 0x2d71, 0x0e8b: 0x2d75,
- 0x0e8c: 0x2d79, 0x0e8d: 0x2d7d, 0x0e8e: 0x2d81, 0x0e8f: 0x2d85, 0x0e90: 0x2d89, 0x0e91: 0x2173,
- 0x0e92: 0x2d8d, 0x0e93: 0x2d91, 0x0e94: 0x2d95, 0x0e95: 0x2d99, 0x0e96: 0x2d9d, 0x0e97: 0x2da1,
- 0x0e98: 0x2da5, 0x0e99: 0x2da9, 0x0e9a: 0x2dad, 0x0e9b: 0x2be9, 0x0e9c: 0x2db1, 0x0e9d: 0x2db5,
- 0x0e9e: 0x2db9, 0x0e9f: 0x2dbd, 0x0ea0: 0x2dc1, 0x0ea1: 0x2dc5, 0x0ea2: 0x2dc9, 0x0ea3: 0x2dcd,
- 0x0ea4: 0x2dd1, 0x0ea5: 0x2dd5, 0x0ea6: 0x2dd9, 0x0ea7: 0x2ddd, 0x0ea8: 0x2de1, 0x0ea9: 0x1aba,
- 0x0eaa: 0x2de5, 0x0eab: 0x2de9, 0x0eac: 0x2ded, 0x0ead: 0x2df1, 0x0eae: 0x2df5, 0x0eaf: 0x2df9,
- 0x0eb0: 0x2dfd, 0x0eb1: 0x2e01, 0x0eb2: 0x2e05, 0x0eb3: 0x2e09, 0x0eb4: 0x2e0d, 0x0eb5: 0x2e11,
- 0x0eb6: 0x2e15, 0x0eb7: 0x19f6, 0x0eb8: 0x2e19, 0x0eb9: 0x2e1d, 0x0eba: 0x2e21, 0x0ebb: 0x2e25,
- 0x0ebc: 0x2e29, 0x0ebd: 0x2e2d, 0x0ebe: 0x2e31, 0x0ebf: 0x2e35,
- // Block 0x3b, offset 0xec0
- 0x0ec0: 0x2e39, 0x0ec1: 0x2e3d, 0x0ec2: 0x2e41, 0x0ec3: 0x2e45, 0x0ec4: 0x2e49, 0x0ec5: 0x2e4d,
- 0x0ec6: 0x2e51, 0x0ec7: 0x2e55, 0x0ec8: 0x1a62, 0x0ec9: 0x2e59, 0x0eca: 0x1a6e, 0x0ecb: 0x2e5d,
- 0x0ecc: 0x2e61, 0x0ecd: 0x2e65, 0x0ed0: 0x2e69,
- 0x0ed2: 0x2e6d, 0x0ed5: 0x2e71, 0x0ed6: 0x2e75, 0x0ed7: 0x2e79,
- 0x0ed8: 0x2e7d, 0x0ed9: 0x2e81, 0x0eda: 0x2e85, 0x0edb: 0x2e89, 0x0edc: 0x2e8d, 0x0edd: 0x2e91,
- 0x0ede: 0x1a12, 0x0ee0: 0x2e95, 0x0ee2: 0x2e99,
- 0x0ee5: 0x2e9d, 0x0ee6: 0x2ea1,
- 0x0eea: 0x2ea5, 0x0eeb: 0x2ea9, 0x0eec: 0x2ead, 0x0eed: 0x2eb1,
- 0x0ef0: 0x2eb5, 0x0ef1: 0x2eb9, 0x0ef2: 0x2ebd, 0x0ef3: 0x2ec1, 0x0ef4: 0x2ec5, 0x0ef5: 0x2ec9,
- 0x0ef6: 0x2ecd, 0x0ef7: 0x2ed1, 0x0ef8: 0x2ed5, 0x0ef9: 0x2ed9, 0x0efa: 0x2edd, 0x0efb: 0x2ee1,
- 0x0efc: 0x18d6, 0x0efd: 0x2ee5, 0x0efe: 0x2ee9, 0x0eff: 0x2eed,
- // Block 0x3c, offset 0xf00
- 0x0f00: 0x2ef1, 0x0f01: 0x2ef5, 0x0f02: 0x2ef9, 0x0f03: 0x2efd, 0x0f04: 0x2f01, 0x0f05: 0x2f05,
- 0x0f06: 0x2f09, 0x0f07: 0x2f0d, 0x0f08: 0x2f11, 0x0f09: 0x2f15, 0x0f0a: 0x2f19, 0x0f0b: 0x2f1d,
- 0x0f0c: 0x2187, 0x0f0d: 0x2f21, 0x0f0e: 0x2f25, 0x0f0f: 0x2f29, 0x0f10: 0x2f2d, 0x0f11: 0x2197,
- 0x0f12: 0x2f31, 0x0f13: 0x2f35, 0x0f14: 0x2f39, 0x0f15: 0x2f3d, 0x0f16: 0x2f41, 0x0f17: 0x2cb1,
- 0x0f18: 0x2f45, 0x0f19: 0x2f49, 0x0f1a: 0x2f4d, 0x0f1b: 0x2f51, 0x0f1c: 0x2f55, 0x0f1d: 0x2f59,
- 0x0f1e: 0x2f59, 0x0f1f: 0x2f5d, 0x0f20: 0x2f61, 0x0f21: 0x2f65, 0x0f22: 0x2f69, 0x0f23: 0x2f6d,
- 0x0f24: 0x2f71, 0x0f25: 0x2f75, 0x0f26: 0x2f79, 0x0f27: 0x2e9d, 0x0f28: 0x2f7d, 0x0f29: 0x2f81,
- 0x0f2a: 0x2f85, 0x0f2b: 0x2f89, 0x0f2c: 0x2f8d, 0x0f2d: 0x2f92,
- 0x0f30: 0x2f96, 0x0f31: 0x2f9a, 0x0f32: 0x2f9e, 0x0f33: 0x2fa2, 0x0f34: 0x2fa6, 0x0f35: 0x2faa,
- 0x0f36: 0x2fae, 0x0f37: 0x2fb2, 0x0f38: 0x2ecd, 0x0f39: 0x2fb6, 0x0f3a: 0x2fba, 0x0f3b: 0x2fbe,
- 0x0f3c: 0x2e69, 0x0f3d: 0x2fc2, 0x0f3e: 0x2fc6, 0x0f3f: 0x2fca,
- // Block 0x3d, offset 0xf40
- 0x0f40: 0x2fce, 0x0f41: 0x2fd2, 0x0f42: 0x2fd6, 0x0f43: 0x2fda, 0x0f44: 0x2fde, 0x0f45: 0x2fe2,
- 0x0f46: 0x2fe6, 0x0f47: 0x2fea, 0x0f48: 0x2fee, 0x0f49: 0x2eed, 0x0f4a: 0x2ff2, 0x0f4b: 0x2ef1,
- 0x0f4c: 0x2ff6, 0x0f4d: 0x2ffa, 0x0f4e: 0x2ffe, 0x0f4f: 0x3002, 0x0f50: 0x3006, 0x0f51: 0x2e6d,
- 0x0f52: 0x2b15, 0x0f53: 0x300a, 0x0f54: 0x300e, 0x0f55: 0x195a, 0x0f56: 0x2c25, 0x0f57: 0x2d71,
- 0x0f58: 0x3012, 0x0f59: 0x3016, 0x0f5a: 0x2f0d, 0x0f5b: 0x301a, 0x0f5c: 0x2f11, 0x0f5d: 0x301e,
- 0x0f5e: 0x3022, 0x0f5f: 0x3026, 0x0f60: 0x2e75, 0x0f61: 0x302a, 0x0f62: 0x302e, 0x0f63: 0x3032,
- 0x0f64: 0x3036, 0x0f65: 0x303a, 0x0f66: 0x2e79, 0x0f67: 0x303e, 0x0f68: 0x3042, 0x0f69: 0x3046,
- 0x0f6a: 0x304a, 0x0f6b: 0x304e, 0x0f6c: 0x3052, 0x0f6d: 0x2f41, 0x0f6e: 0x3056, 0x0f6f: 0x305a,
- 0x0f70: 0x2cb1, 0x0f71: 0x305e, 0x0f72: 0x2f51, 0x0f73: 0x3062, 0x0f74: 0x3066, 0x0f75: 0x306a,
- 0x0f76: 0x306e, 0x0f77: 0x3072, 0x0f78: 0x2f65, 0x0f79: 0x3076, 0x0f7a: 0x2e99, 0x0f7b: 0x307a,
- 0x0f7c: 0x2f69, 0x0f7d: 0x2bd9, 0x0f7e: 0x307e, 0x0f7f: 0x2f6d,
- // Block 0x3e, offset 0xf80
- 0x0f80: 0x3082, 0x0f81: 0x2f75, 0x0f82: 0x3086, 0x0f83: 0x308a, 0x0f84: 0x308e, 0x0f85: 0x3092,
- 0x0f86: 0x3096, 0x0f87: 0x2f7d, 0x0f88: 0x2e8d, 0x0f89: 0x309a, 0x0f8a: 0x2f81, 0x0f8b: 0x309e,
- 0x0f8c: 0x2f85, 0x0f8d: 0x30a2, 0x0f8e: 0x1b76, 0x0f8f: 0x30a6, 0x0f90: 0x30ab, 0x0f91: 0x30b0,
- 0x0f92: 0x30b5, 0x0f93: 0x30b9, 0x0f94: 0x30bd, 0x0f95: 0x30c1, 0x0f96: 0x30c6, 0x0f97: 0x30cb,
- 0x0f98: 0x30d0, 0x0f99: 0x30d4,
- // Block 0x3f, offset 0xfc0
- 0x0fdd: 0x3105,
- 0x0fdf: 0x310a,
- 0x0fea: 0x3124, 0x0feb: 0x3129, 0x0fec: 0x312e, 0x0fed: 0x3135, 0x0fee: 0x313c, 0x0fef: 0x3141,
- 0x0ff0: 0x3146, 0x0ff1: 0x314b, 0x0ff2: 0x3150, 0x0ff3: 0x3155, 0x0ff4: 0x315a, 0x0ff5: 0x315f,
- 0x0ff6: 0x3164, 0x0ff8: 0x3169, 0x0ff9: 0x316e, 0x0ffa: 0x3173, 0x0ffb: 0x3178,
- 0x0ffc: 0x317d, 0x0ffe: 0x3182,
- // Block 0x40, offset 0x1000
- 0x1000: 0x3187, 0x1001: 0x318c, 0x1003: 0x3191, 0x1004: 0x3196,
- 0x1006: 0x319b, 0x1007: 0x31a0, 0x1008: 0x31a5, 0x1009: 0x31aa, 0x100a: 0x31af, 0x100b: 0x31b4,
- 0x100c: 0x31b9, 0x100d: 0x31be, 0x100e: 0x31c3,
- // Block 0x41, offset 0x1040
- 0x105a: 0x3a73, 0x105c: 0x3a7c,
- 0x106b: 0x3a85,
- // Block 0x42, offset 0x1080
- 0x109e: 0x3a8e, 0x109f: 0x3a97, 0x10a0: 0x3aa0, 0x10a1: 0x3aad, 0x10a2: 0x3aba, 0x10a3: 0x3ac7,
- 0x10a4: 0x3ad4,
- // Block 0x43, offset 0x10c0
- 0x10fb: 0x3ae1,
- 0x10fc: 0x3aea, 0x10fd: 0x3af3, 0x10fe: 0x3b00, 0x10ff: 0x3b0d,
- // Block 0x44, offset 0x1100
- 0x1100: 0x3b1a,
- // Block 0x45, offset 0x1140
- 0x1140: 0x3d23, 0x1141: 0x3d27, 0x1142: 0x3d2b, 0x1143: 0x3d2f, 0x1144: 0x3d34, 0x1145: 0x2eb5,
- 0x1146: 0x3d38, 0x1147: 0x3d3c, 0x1148: 0x3d40, 0x1149: 0x3d44, 0x114a: 0x2eb9, 0x114b: 0x3d48,
- 0x114c: 0x3d4c, 0x114d: 0x3d50, 0x114e: 0x2ebd, 0x114f: 0x3d55, 0x1150: 0x3d59, 0x1151: 0x3d5d,
- 0x1152: 0x3d61, 0x1153: 0x3d66, 0x1154: 0x3d6a, 0x1155: 0x3c71, 0x1156: 0x3d6e, 0x1157: 0x3d73,
- 0x1158: 0x3d77, 0x1159: 0x3d7b, 0x115a: 0x3d7f, 0x115b: 0x2f9a, 0x115c: 0x3d83, 0x115d: 0x1866,
- 0x115e: 0x3d88, 0x115f: 0x3d8c, 0x1160: 0x3d90, 0x1161: 0x3d94, 0x1162: 0x3cb9, 0x1163: 0x3d98,
- 0x1164: 0x3d9c, 0x1165: 0x2fae, 0x1166: 0x2ec1, 0x1167: 0x2ec5, 0x1168: 0x2fb2, 0x1169: 0x3da0,
- 0x116a: 0x3da4, 0x116b: 0x2bf1, 0x116c: 0x3da8, 0x116d: 0x2ec9, 0x116e: 0x3dac, 0x116f: 0x3db0,
- 0x1170: 0x3db4, 0x1171: 0x3db8, 0x1172: 0x3db8, 0x1173: 0x3db8, 0x1174: 0x3dbc, 0x1175: 0x3dc1,
- 0x1176: 0x3dc5, 0x1177: 0x3dc9, 0x1178: 0x3dcd, 0x1179: 0x3dd2, 0x117a: 0x3dd6, 0x117b: 0x3dda,
- 0x117c: 0x3dde, 0x117d: 0x3de2, 0x117e: 0x3de6, 0x117f: 0x3dea,
- // Block 0x46, offset 0x1180
- 0x1180: 0x3dee, 0x1181: 0x3df2, 0x1182: 0x3df6, 0x1183: 0x3dfa, 0x1184: 0x3dfe, 0x1185: 0x3e02,
- 0x1186: 0x3e02, 0x1187: 0x2fba, 0x1188: 0x3e06, 0x1189: 0x3e0a, 0x118a: 0x3e0e, 0x118b: 0x3e12,
- 0x118c: 0x2ed1, 0x118d: 0x3e16, 0x118e: 0x3e1a, 0x118f: 0x3e1e, 0x1190: 0x2e39, 0x1191: 0x3e22,
- 0x1192: 0x3e26, 0x1193: 0x3e2a, 0x1194: 0x3e2e, 0x1195: 0x3e32, 0x1196: 0x3e36, 0x1197: 0x3e3a,
- 0x1198: 0x3e3e, 0x1199: 0x3e42, 0x119a: 0x3e47, 0x119b: 0x3e4b, 0x119c: 0x3e4f, 0x119d: 0x3c55,
- 0x119e: 0x3e53, 0x119f: 0x3e57, 0x11a0: 0x3e5b, 0x11a1: 0x3e60, 0x11a2: 0x3e65, 0x11a3: 0x3e69,
- 0x11a4: 0x3e6d, 0x11a5: 0x3e71, 0x11a6: 0x3e75, 0x11a7: 0x3e79, 0x11a8: 0x3e7d, 0x11a9: 0x3e81,
- 0x11aa: 0x3e85, 0x11ab: 0x3e85, 0x11ac: 0x3e89, 0x11ad: 0x3e8e, 0x11ae: 0x3e92, 0x11af: 0x2be1,
- 0x11b0: 0x3e96, 0x11b1: 0x3e9a, 0x11b2: 0x3e9f, 0x11b3: 0x3ea3, 0x11b4: 0x3ea7, 0x11b5: 0x18ce,
- 0x11b6: 0x3eab, 0x11b7: 0x3eaf, 0x11b8: 0x18d6, 0x11b9: 0x3eb3, 0x11ba: 0x3eb7, 0x11bb: 0x3ebb,
- 0x11bc: 0x3ec0, 0x11bd: 0x3ec4, 0x11be: 0x3ec9, 0x11bf: 0x3ecd,
- // Block 0x47, offset 0x11c0
- 0x11c0: 0x3ed1, 0x11c1: 0x3ed5, 0x11c2: 0x3ed9, 0x11c3: 0x3edd, 0x11c4: 0x3ee1, 0x11c5: 0x3ee5,
- 0x11c6: 0x3ee9, 0x11c7: 0x3eed, 0x11c8: 0x3ef1, 0x11c9: 0x3ef5, 0x11ca: 0x3efa, 0x11cb: 0x3efe,
- 0x11cc: 0x3f02, 0x11cd: 0x3f06, 0x11ce: 0x2b11, 0x11cf: 0x3f0a, 0x11d0: 0x18fe, 0x11d1: 0x3f0f,
- 0x11d2: 0x3f0f, 0x11d3: 0x3f14, 0x11d4: 0x3f18, 0x11d5: 0x3f18, 0x11d6: 0x3f1c, 0x11d7: 0x3f20,
- 0x11d8: 0x3f25, 0x11d9: 0x3f2a, 0x11da: 0x3f2e, 0x11db: 0x3f32, 0x11dc: 0x3f36, 0x11dd: 0x3f3a,
- 0x11de: 0x3f3e, 0x11df: 0x3f42, 0x11e0: 0x3f46, 0x11e1: 0x3f4a, 0x11e2: 0x3f4e, 0x11e3: 0x2ee5,
- 0x11e4: 0x3f52, 0x11e5: 0x3f57, 0x11e6: 0x3f5b, 0x11e7: 0x3f5f, 0x11e8: 0x2fea, 0x11e9: 0x3f5f,
- 0x11ea: 0x3f63, 0x11eb: 0x2eed, 0x11ec: 0x3f67, 0x11ed: 0x3f6b, 0x11ee: 0x3f6f, 0x11ef: 0x3f73,
- 0x11f0: 0x2ef1, 0x11f1: 0x2aa5, 0x11f2: 0x3f77, 0x11f3: 0x3f7b, 0x11f4: 0x3f7f, 0x11f5: 0x3f83,
- 0x11f6: 0x3f87, 0x11f7: 0x3f8b, 0x11f8: 0x3f8f, 0x11f9: 0x3f94, 0x11fa: 0x3f98, 0x11fb: 0x3f9c,
- 0x11fc: 0x3fa0, 0x11fd: 0x3fa4, 0x11fe: 0x3fa8, 0x11ff: 0x3fad,
- // Block 0x48, offset 0x1200
- 0x1200: 0x3fb1, 0x1201: 0x3fb5, 0x1202: 0x3fb9, 0x1203: 0x3fbd, 0x1204: 0x3fc1, 0x1205: 0x3fc5,
- 0x1206: 0x3fc9, 0x1207: 0x3fcd, 0x1208: 0x2ef5, 0x1209: 0x3fd1, 0x120a: 0x3fd5, 0x120b: 0x3fda,
- 0x120c: 0x3fde, 0x120d: 0x3fe2, 0x120e: 0x3fe6, 0x120f: 0x2efd, 0x1210: 0x3fea, 0x1211: 0x3fee,
- 0x1212: 0x3ff2, 0x1213: 0x3ff6, 0x1214: 0x3ffa, 0x1215: 0x3ffe, 0x1216: 0x4002, 0x1217: 0x4006,
- 0x1218: 0x2b15, 0x1219: 0x300a, 0x121a: 0x400a, 0x121b: 0x400e, 0x121c: 0x4012, 0x121d: 0x4016,
- 0x121e: 0x401b, 0x121f: 0x401f, 0x1220: 0x4023, 0x1221: 0x4027, 0x1222: 0x2f01, 0x1223: 0x402b,
- 0x1224: 0x4030, 0x1225: 0x4034, 0x1226: 0x4038, 0x1227: 0x30b5, 0x1228: 0x403c, 0x1229: 0x4040,
- 0x122a: 0x4044, 0x122b: 0x4048, 0x122c: 0x404c, 0x122d: 0x4051, 0x122e: 0x4055, 0x122f: 0x4059,
- 0x1230: 0x405d, 0x1231: 0x4062, 0x1232: 0x4066, 0x1233: 0x406a, 0x1234: 0x406e, 0x1235: 0x2c25,
- 0x1236: 0x4072, 0x1237: 0x4076, 0x1238: 0x407b, 0x1239: 0x4080, 0x123a: 0x4085, 0x123b: 0x4089,
- 0x123c: 0x408e, 0x123d: 0x4092, 0x123e: 0x4096, 0x123f: 0x409a,
- // Block 0x49, offset 0x1240
- 0x1240: 0x409e, 0x1241: 0x2f05, 0x1242: 0x2d71, 0x1243: 0x40a2, 0x1244: 0x40a6, 0x1245: 0x40aa,
- 0x1246: 0x40ae, 0x1247: 0x40b3, 0x1248: 0x40b7, 0x1249: 0x40bb, 0x124a: 0x40bf, 0x124b: 0x3016,
- 0x124c: 0x40c3, 0x124d: 0x40c7, 0x124e: 0x40cc, 0x124f: 0x40d0, 0x1250: 0x40d4, 0x1251: 0x40d9,
- 0x1252: 0x40de, 0x1253: 0x40e2, 0x1254: 0x301a, 0x1255: 0x40e6, 0x1256: 0x40ea, 0x1257: 0x40ee,
- 0x1258: 0x40f2, 0x1259: 0x40f6, 0x125a: 0x40fa, 0x125b: 0x40fe, 0x125c: 0x4103, 0x125d: 0x4107,
- 0x125e: 0x410c, 0x125f: 0x4110, 0x1260: 0x4115, 0x1261: 0x3022, 0x1262: 0x4119, 0x1263: 0x411d,
- 0x1264: 0x4122, 0x1265: 0x4126, 0x1266: 0x412a, 0x1267: 0x412f, 0x1268: 0x4134, 0x1269: 0x4138,
- 0x126a: 0x413c, 0x126b: 0x4140, 0x126c: 0x4144, 0x126d: 0x4144, 0x126e: 0x4148, 0x126f: 0x414c,
- 0x1270: 0x302a, 0x1271: 0x4150, 0x1272: 0x4154, 0x1273: 0x4158, 0x1274: 0x415c, 0x1275: 0x4160,
- 0x1276: 0x4165, 0x1277: 0x4169, 0x1278: 0x2bed, 0x1279: 0x416e, 0x127a: 0x4173, 0x127b: 0x4177,
- 0x127c: 0x417c, 0x127d: 0x4181, 0x127e: 0x4186, 0x127f: 0x418a,
- // Block 0x4a, offset 0x1280
- 0x1280: 0x3042, 0x1281: 0x418e, 0x1282: 0x4193, 0x1283: 0x4198, 0x1284: 0x419d, 0x1285: 0x41a2,
- 0x1286: 0x41a6, 0x1287: 0x41a6, 0x1288: 0x3046, 0x1289: 0x30bd, 0x128a: 0x41aa, 0x128b: 0x41ae,
- 0x128c: 0x41b2, 0x128d: 0x41b6, 0x128e: 0x41bb, 0x128f: 0x2b59, 0x1290: 0x304e, 0x1291: 0x41bf,
- 0x1292: 0x41c3, 0x1293: 0x2f2d, 0x1294: 0x41c8, 0x1295: 0x41cd, 0x1296: 0x2e89, 0x1297: 0x41d2,
- 0x1298: 0x41d6, 0x1299: 0x2f39, 0x129a: 0x41da, 0x129b: 0x41de, 0x129c: 0x41e2, 0x129d: 0x41e7,
- 0x129e: 0x41e7, 0x129f: 0x41ec, 0x12a0: 0x41f0, 0x12a1: 0x41f4, 0x12a2: 0x41f9, 0x12a3: 0x41fd,
- 0x12a4: 0x4201, 0x12a5: 0x4205, 0x12a6: 0x420a, 0x12a7: 0x420e, 0x12a8: 0x4212, 0x12a9: 0x4216,
- 0x12aa: 0x421a, 0x12ab: 0x421e, 0x12ac: 0x4223, 0x12ad: 0x4227, 0x12ae: 0x422b, 0x12af: 0x422f,
- 0x12b0: 0x4233, 0x12b1: 0x4237, 0x12b2: 0x423b, 0x12b3: 0x4240, 0x12b4: 0x4245, 0x12b5: 0x4249,
- 0x12b6: 0x424e, 0x12b7: 0x4252, 0x12b8: 0x4257, 0x12b9: 0x425b, 0x12ba: 0x2f51, 0x12bb: 0x425f,
- 0x12bc: 0x4264, 0x12bd: 0x4269, 0x12be: 0x426d, 0x12bf: 0x4272,
- // Block 0x4b, offset 0x12c0
- 0x12c0: 0x4276, 0x12c1: 0x427b, 0x12c2: 0x427f, 0x12c3: 0x4283, 0x12c4: 0x4287, 0x12c5: 0x428b,
- 0x12c6: 0x428f, 0x12c7: 0x4293, 0x12c8: 0x4298, 0x12c9: 0x429d, 0x12ca: 0x42a2, 0x12cb: 0x3f14,
- 0x12cc: 0x42a7, 0x12cd: 0x42ab, 0x12ce: 0x42af, 0x12cf: 0x42b3, 0x12d0: 0x42b7, 0x12d1: 0x42bb,
- 0x12d2: 0x42bf, 0x12d3: 0x42c3, 0x12d4: 0x42c7, 0x12d5: 0x42cb, 0x12d6: 0x42cf, 0x12d7: 0x42d3,
- 0x12d8: 0x2c31, 0x12d9: 0x42d8, 0x12da: 0x42dc, 0x12db: 0x42e0, 0x12dc: 0x42e4, 0x12dd: 0x42e8,
- 0x12de: 0x42ec, 0x12df: 0x2f5d, 0x12e0: 0x42f0, 0x12e1: 0x42f4, 0x12e2: 0x42f8, 0x12e3: 0x42fc,
- 0x12e4: 0x4300, 0x12e5: 0x4305, 0x12e6: 0x430a, 0x12e7: 0x430f, 0x12e8: 0x4313, 0x12e9: 0x4317,
- 0x12ea: 0x431b, 0x12eb: 0x431f, 0x12ec: 0x4324, 0x12ed: 0x4328, 0x12ee: 0x432d, 0x12ef: 0x4331,
- 0x12f0: 0x4335, 0x12f1: 0x433a, 0x12f2: 0x433f, 0x12f3: 0x4343, 0x12f4: 0x2b45, 0x12f5: 0x4347,
- 0x12f6: 0x434b, 0x12f7: 0x434f, 0x12f8: 0x4353, 0x12f9: 0x4357, 0x12fa: 0x435b, 0x12fb: 0x306a,
- 0x12fc: 0x435f, 0x12fd: 0x4363, 0x12fe: 0x4367, 0x12ff: 0x436b,
- // Block 0x4c, offset 0x1300
- 0x1300: 0x436f, 0x1301: 0x4373, 0x1302: 0x4377, 0x1303: 0x437b, 0x1304: 0x1a66, 0x1305: 0x437f,
- 0x1306: 0x4384, 0x1307: 0x4388, 0x1308: 0x438c, 0x1309: 0x4390, 0x130a: 0x4394, 0x130b: 0x4398,
- 0x130c: 0x439d, 0x130d: 0x43a2, 0x130e: 0x43a6, 0x130f: 0x43aa, 0x1310: 0x307e, 0x1311: 0x3082,
- 0x1312: 0x1a82, 0x1313: 0x43ae, 0x1314: 0x43b3, 0x1315: 0x43b7, 0x1316: 0x43bb, 0x1317: 0x43bf,
- 0x1318: 0x43c3, 0x1319: 0x43c8, 0x131a: 0x43cd, 0x131b: 0x43d1, 0x131c: 0x43d5, 0x131d: 0x43d9,
- 0x131e: 0x43de, 0x131f: 0x3086, 0x1320: 0x43e2, 0x1321: 0x43e7, 0x1322: 0x43ec, 0x1323: 0x43f0,
- 0x1324: 0x43f4, 0x1325: 0x43f8, 0x1326: 0x43fd, 0x1327: 0x4401, 0x1328: 0x4405, 0x1329: 0x4409,
- 0x132a: 0x440d, 0x132b: 0x4411, 0x132c: 0x4415, 0x132d: 0x4419, 0x132e: 0x441e, 0x132f: 0x4422,
- 0x1330: 0x4426, 0x1331: 0x442a, 0x1332: 0x442f, 0x1333: 0x4433, 0x1334: 0x4437, 0x1335: 0x443b,
- 0x1336: 0x443f, 0x1337: 0x4444, 0x1338: 0x4449, 0x1339: 0x444d, 0x133a: 0x4451, 0x133b: 0x4455,
- 0x133c: 0x445a, 0x133d: 0x445e, 0x133e: 0x309e, 0x133f: 0x309e,
- // Block 0x4d, offset 0x1340
- 0x1340: 0x4463, 0x1341: 0x4467, 0x1342: 0x446c, 0x1343: 0x4470, 0x1344: 0x4474, 0x1345: 0x4478,
- 0x1346: 0x447c, 0x1347: 0x4480, 0x1348: 0x4484, 0x1349: 0x4488, 0x134a: 0x30a2, 0x134b: 0x448d,
- 0x134c: 0x4491, 0x134d: 0x4495, 0x134e: 0x4499, 0x134f: 0x449d, 0x1350: 0x44a1, 0x1351: 0x44a6,
- 0x1352: 0x44aa, 0x1353: 0x44af, 0x1354: 0x44b4, 0x1355: 0x1b42, 0x1356: 0x44b9, 0x1357: 0x1b52,
- 0x1358: 0x44bd, 0x1359: 0x44c1, 0x135a: 0x44c5, 0x135b: 0x44c9, 0x135c: 0x1b66, 0x135d: 0x44cd,
+ 0x0540: 0x436f, 0x0541: 0x4373, 0x0542: 0x4377, 0x0543: 0x437b, 0x0544: 0x1a66, 0x0545: 0x437f,
+ 0x0546: 0x4384, 0x0547: 0x4388, 0x0548: 0x438c, 0x0549: 0x4390, 0x054a: 0x4394, 0x054b: 0x4398,
+ 0x054c: 0x439d, 0x054d: 0x43a2, 0x054e: 0x43a6, 0x054f: 0x43aa, 0x0550: 0x307e, 0x0551: 0x3082,
+ 0x0552: 0x1a82, 0x0553: 0x43ae, 0x0554: 0x43b3, 0x0555: 0x43b7, 0x0556: 0x43bb, 0x0557: 0x43bf,
+ 0x0558: 0x43c3, 0x0559: 0x43c8, 0x055a: 0x43cd, 0x055b: 0x43d1, 0x055c: 0x43d5, 0x055d: 0x43d9,
+ 0x055e: 0x43de, 0x055f: 0x3086, 0x0560: 0x43e2, 0x0561: 0x43e7, 0x0562: 0x43ec, 0x0563: 0x43f0,
+ 0x0564: 0x43f4, 0x0565: 0x43f8, 0x0566: 0x43fd, 0x0567: 0x4401, 0x0568: 0x4405, 0x0569: 0x4409,
+ 0x056a: 0x440d, 0x056b: 0x4411, 0x056c: 0x4415, 0x056d: 0x4419, 0x056e: 0x441e, 0x056f: 0x4422,
+ 0x0570: 0x4426, 0x0571: 0x442a, 0x0572: 0x442f, 0x0573: 0x4433, 0x0574: 0x4437, 0x0575: 0x443b,
+ 0x0576: 0x443f, 0x0577: 0x4444, 0x0578: 0x4449, 0x0579: 0x444d, 0x057a: 0x4451, 0x057b: 0x4455,
+ 0x057c: 0x445a, 0x057d: 0x445e, 0x057e: 0x309e, 0x057f: 0x309e,
+}
+
+// nfcDecompSparseOffset: 56 entries, 112 bytes
+var nfcDecompSparseOffset = []uint16{0x0, 0xa, 0x10, 0x15, 0x18, 0x22, 0x27, 0x2e, 0x31, 0x38, 0x3e, 0x46, 0x48, 0x4c, 0x50, 0x52, 0x56, 0x59, 0x5c, 0x60, 0x62, 0x64, 0x66, 0x6a, 0x6c, 0x70, 0x7a, 0x82, 0x84, 0x8d, 0x90, 0x9e, 0xa0, 0xa4, 0xa7, 0xa9, 0xaf, 0xbb, 0xc0, 0xc3, 0xc5, 0xc7, 0xd4, 0xe2, 0xed, 0xf4, 0xff, 0x10b, 0x11c, 0x12d, 0x135, 0x139, 0x13d, 0x141, 0x145, 0x147}
+
+// nfcDecompSparseValues: 341 entries, 1364 bytes
+var nfcDecompSparseValues = [341]valueRange{
+ // Block 0x0, offset 0x1
+ {value: 0x0004, lo: 0x09},
+ {value: 0x0032, lo: 0x80, hi: 0x85},
+ {value: 0x004a, lo: 0x87, hi: 0x8f},
+ {value: 0x006e, lo: 0x91, hi: 0x96},
+ {value: 0x0086, lo: 0x99, hi: 0x9d},
+ {value: 0x009a, lo: 0xa0, hi: 0xa5},
+ {value: 0x00b2, lo: 0xa7, hi: 0xaf},
+ {value: 0x00d6, lo: 0xb1, hi: 0xb6},
+ {value: 0x00ee, lo: 0xb9, hi: 0xbd},
+ {value: 0x0102, lo: 0xbf, hi: 0xbf},
+ // Block 0x1, offset 0x2
+ {value: 0x0004, lo: 0x05},
+ {value: 0x0106, lo: 0x80, hi: 0x8f},
+ {value: 0x0146, lo: 0x92, hi: 0xa5},
+ {value: 0x0196, lo: 0xa8, hi: 0xb0},
+ {value: 0x01c0, lo: 0xb4, hi: 0xb7},
+ {value: 0x01d0, lo: 0xb9, hi: 0xbe},
+ // Block 0x2, offset 0x3
+ {value: 0x0004, lo: 0x04},
+ {value: 0x01f0, lo: 0x83, hi: 0x88},
+ {value: 0x020c, lo: 0x8c, hi: 0x91},
+ {value: 0x0224, lo: 0x94, hi: 0xa5},
+ {value: 0x026c, lo: 0xa8, hi: 0xbe},
+ // Block 0x3, offset 0x4
+ {value: 0x0004, lo: 0x02},
+ {value: 0x02ca, lo: 0xa0, hi: 0xa1},
+ {value: 0x02d2, lo: 0xaf, hi: 0xb0},
+ // Block 0x4, offset 0x5
+ {value: 0x0004, lo: 0x09},
+ {value: 0x03d8, lo: 0x80, hi: 0x9b},
+ {value: 0x0448, lo: 0x9e, hi: 0x9f},
+ {value: 0x0450, lo: 0xa6, hi: 0xaa},
+ {value: 0x0466, lo: 0xab, hi: 0xab},
+ {value: 0x046c, lo: 0xac, hi: 0xac},
+ {value: 0x0472, lo: 0xad, hi: 0xad},
+ {value: 0x0478, lo: 0xae, hi: 0xb0},
+ {value: 0x0486, lo: 0xb1, hi: 0xb1},
+ {value: 0x048c, lo: 0xb2, hi: 0xb3},
+ // Block 0x5, offset 0x6
+ {value: 0x0003, lo: 0x04},
+ {value: 0x04cc, lo: 0x80, hi: 0x81},
+ {value: 0x04d2, lo: 0x83, hi: 0x84},
+ {value: 0x04da, lo: 0xb4, hi: 0xb4},
+ {value: 0x04e1, lo: 0xbe, hi: 0xbe},
+ // Block 0x6, offset 0x7
+ {value: 0x0005, lo: 0x06},
+ {value: 0x04e3, lo: 0x85, hi: 0x85},
+ {value: 0x04ee, lo: 0x86, hi: 0x87},
+ {value: 0x04f6, lo: 0x88, hi: 0x8a},
+ {value: 0x0505, lo: 0x8c, hi: 0x8c},
+ {value: 0x050a, lo: 0x8e, hi: 0x90},
+ {value: 0x051b, lo: 0xaa, hi: 0xb0},
+ // Block 0x7, offset 0x8
+ {value: 0x0005, lo: 0x02},
+ {value: 0x0540, lo: 0x8a, hi: 0x8e},
+ {value: 0x0562, lo: 0x93, hi: 0x94},
+ // Block 0x8, offset 0x9
+ {value: 0x0005, lo: 0x06},
+ {value: 0x0584, lo: 0x80, hi: 0x81},
+ {value: 0x058e, lo: 0x83, hi: 0x83},
+ {value: 0x0593, lo: 0x87, hi: 0x87},
+ {value: 0x0598, lo: 0x8c, hi: 0x8e},
+ {value: 0x05a7, lo: 0x99, hi: 0x99},
+ {value: 0x05ac, lo: 0xb9, hi: 0xb9},
+ // Block 0x9, offset 0xa
+ {value: 0x0005, lo: 0x05},
+ {value: 0x05b1, lo: 0x90, hi: 0x91},
+ {value: 0x05bb, lo: 0x93, hi: 0x93},
+ {value: 0x05c0, lo: 0x97, hi: 0x97},
+ {value: 0x05c5, lo: 0x9c, hi: 0x9e},
+ {value: 0x05d4, lo: 0xb6, hi: 0xb7},
+ // Block 0xa, offset 0xb
+ {value: 0x0005, lo: 0x07},
+ {value: 0x05de, lo: 0x81, hi: 0x82},
+ {value: 0x05e8, lo: 0x90, hi: 0x93},
+ {value: 0x05fc, lo: 0x96, hi: 0x97},
+ {value: 0x0606, lo: 0x9a, hi: 0x9f},
+ {value: 0x0624, lo: 0xa2, hi: 0xa7},
+ {value: 0x0642, lo: 0xaa, hi: 0xb5},
+ {value: 0x067e, lo: 0xb8, hi: 0xb9},
+ // Block 0xb, offset 0xc
+ {value: 0x0005, lo: 0x01},
+ {value: 0x068d, lo: 0xa2, hi: 0xa6},
+ // Block 0xc, offset 0xd
+ {value: 0x0005, lo: 0x03},
+ {value: 0x06ba, lo: 0x80, hi: 0x80},
+ {value: 0x06bf, lo: 0x82, hi: 0x82},
+ {value: 0x06c4, lo: 0x93, hi: 0x93},
+ // Block 0xd, offset 0xe
+ {value: 0x0007, lo: 0x03},
+ {value: 0x06c9, lo: 0xa9, hi: 0xa9},
+ {value: 0x06d0, lo: 0xb1, hi: 0xb1},
+ {value: 0x06d7, lo: 0xb4, hi: 0xb4},
+ // Block 0xe, offset 0xf
+ {value: 0x0007, lo: 0x01},
+ {value: 0x06de, lo: 0x98, hi: 0x9f},
+ // Block 0xf, offset 0x10
+ {value: 0x0007, lo: 0x03},
+ {value: 0x0716, lo: 0x8b, hi: 0x8c},
+ {value: 0x0724, lo: 0x9c, hi: 0x9d},
+ {value: 0x0732, lo: 0x9f, hi: 0x9f},
+ // Block 0x10, offset 0x11
+ {value: 0x0007, lo: 0x02},
+ {value: 0x0739, lo: 0xb3, hi: 0xb3},
+ {value: 0x0740, lo: 0xb6, hi: 0xb6},
+ // Block 0x11, offset 0x12
+ {value: 0x0007, lo: 0x02},
+ {value: 0x0747, lo: 0x99, hi: 0x9b},
+ {value: 0x075c, lo: 0x9e, hi: 0x9e},
+ // Block 0x12, offset 0x13
+ {value: 0x0007, lo: 0x03},
+ {value: 0x0763, lo: 0x88, hi: 0x88},
+ {value: 0x076a, lo: 0x8b, hi: 0x8c},
+ {value: 0x0778, lo: 0x9c, hi: 0x9d},
+ // Block 0x13, offset 0x14
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0786, lo: 0x94, hi: 0x94},
+ // Block 0x14, offset 0x15
+ {value: 0x0007, lo: 0x01},
+ {value: 0x078d, lo: 0x8a, hi: 0x8c},
+ // Block 0x15, offset 0x16
+ {value: 0x0000, lo: 0x01},
+ {value: 0x07a2, lo: 0x88, hi: 0x88},
+ // Block 0x16, offset 0x17
+ {value: 0x0007, lo: 0x03},
+ {value: 0x07a9, lo: 0x80, hi: 0x80},
+ {value: 0x07b0, lo: 0x87, hi: 0x88},
+ {value: 0x07be, lo: 0x8a, hi: 0x8b},
+ // Block 0x17, offset 0x18
+ {value: 0x0007, lo: 0x01},
+ {value: 0x07cf, lo: 0x8a, hi: 0x8c},
+ // Block 0x18, offset 0x19
+ {value: 0x0007, lo: 0x03},
+ {value: 0x07e4, lo: 0x9a, hi: 0x9a},
+ {value: 0x07eb, lo: 0x9c, hi: 0x9d},
+ {value: 0x07fc, lo: 0x9e, hi: 0x9e},
+ // Block 0x19, offset 0x1a
+ {value: 0x0007, lo: 0x09},
+ {value: 0x0823, lo: 0x83, hi: 0x83},
+ {value: 0x082a, lo: 0x8d, hi: 0x8d},
+ {value: 0x0831, lo: 0x92, hi: 0x92},
+ {value: 0x0838, lo: 0x97, hi: 0x97},
+ {value: 0x083f, lo: 0x9c, hi: 0x9c},
+ {value: 0x0846, lo: 0xa9, hi: 0xa9},
+ {value: 0x084d, lo: 0xb3, hi: 0xb3},
+ {value: 0x0854, lo: 0xb5, hi: 0xb6},
+ {value: 0x086c, lo: 0xb8, hi: 0xb8},
+ // Block 0x1a, offset 0x1b
+ {value: 0x0007, lo: 0x07},
+ {value: 0x087d, lo: 0x81, hi: 0x81},
+ {value: 0x0884, lo: 0x93, hi: 0x93},
+ {value: 0x088b, lo: 0x9d, hi: 0x9d},
+ {value: 0x0892, lo: 0xa2, hi: 0xa2},
+ {value: 0x0899, lo: 0xa7, hi: 0xa7},
+ {value: 0x08a0, lo: 0xac, hi: 0xac},
+ {value: 0x08a7, lo: 0xb9, hi: 0xb9},
+ // Block 0x1b, offset 0x1c
+ {value: 0x0000, lo: 0x01},
+ {value: 0x08ae, lo: 0xa6, hi: 0xa6},
+ // Block 0x1c, offset 0x1d
+ {value: 0x0007, lo: 0x08},
+ {value: 0x08b9, lo: 0x86, hi: 0x86},
+ {value: 0x08c0, lo: 0x88, hi: 0x88},
+ {value: 0x08c7, lo: 0x8a, hi: 0x8a},
+ {value: 0x08ce, lo: 0x8c, hi: 0x8c},
+ {value: 0x08d5, lo: 0x8e, hi: 0x8e},
+ {value: 0x08dc, lo: 0x92, hi: 0x92},
+ {value: 0x08e3, lo: 0xbb, hi: 0xbb},
+ {value: 0x08ea, lo: 0xbd, hi: 0xbd},
+ // Block 0x1d, offset 0x1e
+ {value: 0x0007, lo: 0x02},
+ {value: 0x08f1, lo: 0x80, hi: 0x81},
+ {value: 0x08ff, lo: 0x83, hi: 0x83},
+ // Block 0x1e, offset 0x1f
+ {value: 0x0004, lo: 0x0d},
+ {value: 0x09ea, lo: 0x80, hi: 0x88},
+ {value: 0x0a10, lo: 0x89, hi: 0x89},
+ {value: 0x0a16, lo: 0x8a, hi: 0x94},
+ {value: 0x0a44, lo: 0x95, hi: 0x95},
+ {value: 0x0a4a, lo: 0x96, hi: 0x96},
+ {value: 0x0a50, lo: 0x97, hi: 0x97},
+ {value: 0x0a56, lo: 0x98, hi: 0x9c},
+ {value: 0x0a6c, lo: 0x9d, hi: 0x9d},
+ {value: 0x0a72, lo: 0x9e, hi: 0xae},
+ {value: 0x0ab8, lo: 0xaf, hi: 0xaf},
+ {value: 0x0abe, lo: 0xb0, hi: 0xb8},
+ {value: 0x0ae4, lo: 0xb9, hi: 0xb9},
+ {value: 0x0aea, lo: 0xba, hi: 0xbf},
+ // Block 0x1f, offset 0x20
+ {value: 0x0004, lo: 0x01},
+ {value: 0x142e, lo: 0x80, hi: 0x81},
+ // Block 0x20, offset 0x21
+ {value: 0x0000, lo: 0x03},
+ {value: 0x14d6, lo: 0xa6, hi: 0xa6},
+ {value: 0x091c, lo: 0xaa, hi: 0xaa},
+ {value: 0x0046, lo: 0xab, hi: 0xab},
+ // Block 0x21, offset 0x22
+ {value: 0x0006, lo: 0x02},
+ {value: 0x159f, lo: 0x9a, hi: 0x9b},
+ {value: 0x15ab, lo: 0xae, hi: 0xae},
+ // Block 0x22, offset 0x23
+ {value: 0x0006, lo: 0x01},
+ {value: 0x15b1, lo: 0x8d, hi: 0x8f},
+ // Block 0x23, offset 0x24
+ {value: 0x0006, lo: 0x05},
+ {value: 0x15c3, lo: 0x84, hi: 0x84},
+ {value: 0x15c9, lo: 0x89, hi: 0x89},
+ {value: 0x15cf, lo: 0x8c, hi: 0x8c},
+ {value: 0x15d5, lo: 0xa4, hi: 0xa4},
+ {value: 0x15db, lo: 0xa6, hi: 0xa6},
+ // Block 0x24, offset 0x25
+ {value: 0x0006, lo: 0x0b},
+ {value: 0x1603, lo: 0x81, hi: 0x81},
+ {value: 0x1609, lo: 0x84, hi: 0x84},
+ {value: 0x160f, lo: 0x87, hi: 0x87},
+ {value: 0x1615, lo: 0x89, hi: 0x89},
+ {value: 0x161b, lo: 0xa0, hi: 0xa0},
+ {value: 0x161f, lo: 0xa2, hi: 0xa2},
+ {value: 0x1625, lo: 0xad, hi: 0xae},
+ {value: 0x162f, lo: 0xaf, hi: 0xaf},
+ {value: 0x1633, lo: 0xb0, hi: 0xb1},
+ {value: 0x163f, lo: 0xb4, hi: 0xb5},
+ {value: 0x164b, lo: 0xb8, hi: 0xb9},
+ // Block 0x25, offset 0x26
+ {value: 0x0006, lo: 0x04},
+ {value: 0x1657, lo: 0x80, hi: 0x81},
+ {value: 0x1663, lo: 0x84, hi: 0x85},
+ {value: 0x166f, lo: 0x88, hi: 0x89},
+ {value: 0x167b, lo: 0xac, hi: 0xaf},
+ // Block 0x26, offset 0x27
+ {value: 0x0006, lo: 0x02},
+ {value: 0x1693, lo: 0xa0, hi: 0xa3},
+ {value: 0x16ab, lo: 0xaa, hi: 0xad},
+ // Block 0x27, offset 0x28
+ {value: 0x0004, lo: 0x01},
+ {value: 0x16c3, lo: 0xa9, hi: 0xaa},
+ // Block 0x28, offset 0x29
+ {value: 0x0000, lo: 0x01},
+ {value: 0x1814, lo: 0x9c, hi: 0x9c},
+ // Block 0x29, offset 0x2a
+ {value: 0x0007, lo: 0x0c},
+ {value: 0x1c39, lo: 0x94, hi: 0x94},
+ {value: 0x1c4a, lo: 0x9e, hi: 0x9e},
+ {value: 0x1c58, lo: 0xac, hi: 0xac},
+ {value: 0x1c5f, lo: 0xae, hi: 0xae},
+ {value: 0x1c66, lo: 0xb0, hi: 0xb0},
+ {value: 0x1c6d, lo: 0xb2, hi: 0xb2},
+ {value: 0x1c74, lo: 0xb4, hi: 0xb4},
+ {value: 0x1c7b, lo: 0xb6, hi: 0xb6},
+ {value: 0x1c82, lo: 0xb8, hi: 0xb8},
+ {value: 0x1c89, lo: 0xba, hi: 0xba},
+ {value: 0x1c90, lo: 0xbc, hi: 0xbc},
+ {value: 0x1c97, lo: 0xbe, hi: 0xbe},
+ // Block 0x2a, offset 0x2b
+ {value: 0x0007, lo: 0x0d},
+ {value: 0x1c9e, lo: 0x80, hi: 0x80},
+ {value: 0x1ca5, lo: 0x82, hi: 0x82},
+ {value: 0x1cac, lo: 0x85, hi: 0x85},
+ {value: 0x1cb3, lo: 0x87, hi: 0x87},
+ {value: 0x1cba, lo: 0x89, hi: 0x89},
+ {value: 0x1cc1, lo: 0x90, hi: 0x91},
+ {value: 0x1ccf, lo: 0x93, hi: 0x94},
+ {value: 0x1cdd, lo: 0x96, hi: 0x97},
+ {value: 0x1ceb, lo: 0x99, hi: 0x9a},
+ {value: 0x1cf9, lo: 0x9c, hi: 0x9d},
+ {value: 0x1d07, lo: 0xb4, hi: 0xb4},
+ {value: 0x1d0e, lo: 0xb7, hi: 0xba},
+ {value: 0x1d2a, lo: 0xbe, hi: 0xbe},
+ // Block 0x2b, offset 0x2c
+ {value: 0x0004, lo: 0x0a},
+ {value: 0x2a81, lo: 0x80, hi: 0x81},
+ {value: 0x1a9e, lo: 0x82, hi: 0x82},
+ {value: 0x2a89, lo: 0x83, hi: 0x86},
+ {value: 0x1b76, lo: 0x87, hi: 0x87},
+ {value: 0x1b76, lo: 0x88, hi: 0x88},
+ {value: 0x2a99, lo: 0x89, hi: 0x89},
+ {value: 0x1abe, lo: 0x8a, hi: 0x8a},
+ {value: 0x2a9d, lo: 0x8b, hi: 0xb3},
+ {value: 0x1a16, lo: 0xb4, hi: 0xb4},
+ {value: 0x2b41, lo: 0xb5, hi: 0xbf},
+ // Block 0x2c, offset 0x2d
+ {value: 0x0004, lo: 0x06},
+ {value: 0x1b3a, lo: 0x80, hi: 0x80},
+ {value: 0x2b6d, lo: 0x81, hi: 0x9b},
+ {value: 0x2ac1, lo: 0x9c, hi: 0x9c},
+ {value: 0x2bd9, lo: 0x9d, hi: 0xb0},
+ {value: 0x1aa6, lo: 0xb1, hi: 0xb1},
+ {value: 0x2c29, lo: 0xb2, hi: 0xbf},
+ // Block 0x2d, offset 0x2e
+ {value: 0x0004, lo: 0x0a},
+ {value: 0x2c61, lo: 0x80, hi: 0x80},
+ {value: 0x18ba, lo: 0x81, hi: 0x81},
+ {value: 0x2c65, lo: 0x82, hi: 0x89},
+ {value: 0x186e, lo: 0x8a, hi: 0x8a},
+ {value: 0x2c85, lo: 0x8b, hi: 0xa0},
+ {value: 0x2c21, lo: 0xa1, hi: 0xa1},
+ {value: 0x2cdd, lo: 0xa2, hi: 0xa9},
+ {value: 0x2be1, lo: 0xaa, hi: 0xaa},
+ {value: 0x2cfd, lo: 0xab, hi: 0xbe},
+ {value: 0x2ac1, lo: 0xbf, hi: 0xbf},
+ // Block 0x2e, offset 0x2f
+ {value: 0x0004, lo: 0x0b},
+ {value: 0x2d4d, lo: 0x80, hi: 0x83},
+ {value: 0x1b72, lo: 0x84, hi: 0x84},
+ {value: 0x2d5d, lo: 0x85, hi: 0x90},
+ {value: 0x2173, lo: 0x91, hi: 0x91},
+ {value: 0x2d8d, lo: 0x92, hi: 0x9a},
+ {value: 0x2be9, lo: 0x9b, hi: 0x9b},
+ {value: 0x2db1, lo: 0x9c, hi: 0xa8},
+ {value: 0x1aba, lo: 0xa9, hi: 0xa9},
+ {value: 0x2de5, lo: 0xaa, hi: 0xb6},
+ {value: 0x19f6, lo: 0xb7, hi: 0xb7},
+ {value: 0x2e19, lo: 0xb8, hi: 0xbf},
+ // Block 0x2f, offset 0x30
+ {value: 0x0004, lo: 0x10},
+ {value: 0x2e39, lo: 0x80, hi: 0x87},
+ {value: 0x1a62, lo: 0x88, hi: 0x88},
+ {value: 0x2e59, lo: 0x89, hi: 0x89},
+ {value: 0x1a6e, lo: 0x8a, hi: 0x8a},
+ {value: 0x2e5d, lo: 0x8b, hi: 0x8d},
+ {value: 0x2e69, lo: 0x90, hi: 0x90},
+ {value: 0x2e6d, lo: 0x92, hi: 0x92},
+ {value: 0x2e71, lo: 0x95, hi: 0x9d},
+ {value: 0x1a12, lo: 0x9e, hi: 0x9e},
+ {value: 0x2e95, lo: 0xa0, hi: 0xa0},
+ {value: 0x2e99, lo: 0xa2, hi: 0xa2},
+ {value: 0x2e9d, lo: 0xa5, hi: 0xa6},
+ {value: 0x2ea5, lo: 0xaa, hi: 0xad},
+ {value: 0x2eb5, lo: 0xb0, hi: 0xbb},
+ {value: 0x18d6, lo: 0xbc, hi: 0xbc},
+ {value: 0x2ee5, lo: 0xbd, hi: 0xbf},
+ // Block 0x30, offset 0x31
+ {value: 0x0004, lo: 0x10},
+ {value: 0x2ef1, lo: 0x80, hi: 0x8b},
+ {value: 0x2187, lo: 0x8c, hi: 0x8c},
+ {value: 0x2f21, lo: 0x8d, hi: 0x90},
+ {value: 0x2197, lo: 0x91, hi: 0x91},
+ {value: 0x2f31, lo: 0x92, hi: 0x96},
+ {value: 0x2cb1, lo: 0x97, hi: 0x97},
+ {value: 0x2f45, lo: 0x98, hi: 0x9d},
+ {value: 0x2f59, lo: 0x9e, hi: 0xa6},
+ {value: 0x2e9d, lo: 0xa7, hi: 0xa7},
+ {value: 0x2f7d, lo: 0xa8, hi: 0xac},
+ {value: 0x2f92, lo: 0xad, hi: 0xad},
+ {value: 0x2f96, lo: 0xb0, hi: 0xb7},
+ {value: 0x2ecd, lo: 0xb8, hi: 0xb8},
+ {value: 0x2fb6, lo: 0xb9, hi: 0xbb},
+ {value: 0x2e69, lo: 0xbc, hi: 0xbc},
+ {value: 0x2fc2, lo: 0xbd, hi: 0xbf},
+ // Block 0x31, offset 0x32
+ {value: 0x0005, lo: 0x07},
+ {value: 0x3105, lo: 0x9d, hi: 0x9d},
+ {value: 0x310a, lo: 0x9f, hi: 0x9f},
+ {value: 0x3124, lo: 0xaa, hi: 0xac},
+ {value: 0x3135, lo: 0xad, hi: 0xad},
+ {value: 0x313c, lo: 0xae, hi: 0xb6},
+ {value: 0x3169, lo: 0xb8, hi: 0xbc},
+ {value: 0x3182, lo: 0xbe, hi: 0xbe},
+ // Block 0x32, offset 0x33
+ {value: 0x0005, lo: 0x03},
+ {value: 0x3187, lo: 0x80, hi: 0x81},
+ {value: 0x3191, lo: 0x83, hi: 0x84},
+ {value: 0x319b, lo: 0x86, hi: 0x8e},
+ // Block 0x33, offset 0x34
+ {value: 0x0009, lo: 0x03},
+ {value: 0x3a73, lo: 0x9a, hi: 0x9a},
+ {value: 0x3a7c, lo: 0x9c, hi: 0x9c},
+ {value: 0x3a85, lo: 0xab, hi: 0xab},
+ // Block 0x34, offset 0x35
+ {value: 0x000d, lo: 0x03},
+ {value: 0x3a8e, lo: 0x9e, hi: 0x9e},
+ {value: 0x3a97, lo: 0x9f, hi: 0x9f},
+ {value: 0x3aa0, lo: 0xa0, hi: 0xa4},
+ // Block 0x35, offset 0x36
+ {value: 0x0009, lo: 0x03},
+ {value: 0x3ae1, lo: 0xbb, hi: 0xbd},
+ {value: 0x3b00, lo: 0xbe, hi: 0xbe},
+ {value: 0x3b0d, lo: 0xbf, hi: 0xbf},
+ // Block 0x36, offset 0x37
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3b1a, lo: 0x80, hi: 0x80},
+ // Block 0x37, offset 0x38
+ {value: 0x0004, lo: 0x0d},
+ {value: 0x4463, lo: 0x80, hi: 0x81},
+ {value: 0x446c, lo: 0x82, hi: 0x89},
+ {value: 0x30a2, lo: 0x8a, hi: 0x8a},
+ {value: 0x448d, lo: 0x8b, hi: 0x90},
+ {value: 0x44a6, lo: 0x91, hi: 0x92},
+ {value: 0x44af, lo: 0x93, hi: 0x93},
+ {value: 0x44b4, lo: 0x94, hi: 0x94},
+ {value: 0x1b42, lo: 0x95, hi: 0x95},
+ {value: 0x44b9, lo: 0x96, hi: 0x96},
+ {value: 0x1b52, lo: 0x97, hi: 0x97},
+ {value: 0x44bd, lo: 0x98, hi: 0x9b},
+ {value: 0x1b66, lo: 0x9c, hi: 0x9c},
+ {value: 0x44cd, lo: 0x9d, hi: 0x9d},
}
// nfcDecompLookup: 832 bytes
@@ -3038,37 +3125,37 @@ var nfcDecompLookup = [832]uint8{
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x0c3: 0x03, 0x0c4: 0x04, 0x0c5: 0x05, 0x0c6: 0x06, 0x0c7: 0x07,
- 0x0c8: 0x08, 0x0cd: 0x09, 0x0ce: 0x0a, 0x0cf: 0x0b,
- 0x0d0: 0x0c, 0x0d1: 0x0d, 0x0d3: 0x0e,
- 0x0d8: 0x0f, 0x0db: 0x10,
+ 0x0c3: 0x16, 0x0c4: 0x17, 0x0c5: 0x18, 0x0c6: 0x19, 0x0c7: 0x03,
+ 0x0c8: 0x1a, 0x0cd: 0x1b, 0x0ce: 0x1c, 0x0cf: 0x1d,
+ 0x0d0: 0x1e, 0x0d1: 0x1f, 0x0d3: 0x20,
+ 0x0d8: 0x21, 0x0db: 0x22,
0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07,
0x0ef: 0x08,
0x0f0: 0x0c,
// Block 0x4, offset 0x100
- 0x124: 0x11, 0x125: 0x12, 0x127: 0x13,
- 0x128: 0x14, 0x129: 0x15, 0x12d: 0x16, 0x12e: 0x17, 0x12f: 0x18,
- 0x131: 0x19, 0x133: 0x1a, 0x135: 0x1b, 0x137: 0x1c,
- 0x13d: 0x1d, 0x13e: 0x1e,
+ 0x124: 0x23, 0x125: 0x24, 0x127: 0x25,
+ 0x128: 0x26, 0x129: 0x27, 0x12d: 0x28, 0x12e: 0x29, 0x12f: 0x2a,
+ 0x131: 0x2b, 0x133: 0x2c, 0x135: 0x2d, 0x137: 0x2e,
+ 0x13d: 0x2f, 0x13e: 0x30,
// Block 0x5, offset 0x140
- 0x140: 0x1f,
- 0x16c: 0x20, 0x16d: 0x21,
- 0x178: 0x22, 0x179: 0x23, 0x17a: 0x24, 0x17b: 0x25, 0x17c: 0x26, 0x17d: 0x27, 0x17e: 0x28, 0x17f: 0x29,
+ 0x140: 0x31,
+ 0x16c: 0x32, 0x16d: 0x33,
+ 0x178: 0x34, 0x179: 0x04, 0x17a: 0x05, 0x17b: 0x06, 0x17c: 0x07, 0x17d: 0x08, 0x17e: 0x09, 0x17f: 0x0a,
// Block 0x6, offset 0x180
- 0x180: 0x2a, 0x184: 0x2b, 0x186: 0x2c, 0x187: 0x2d,
- 0x188: 0x2e, 0x189: 0x2f, 0x18a: 0x30, 0x18b: 0x31, 0x18c: 0x32,
- 0x1ab: 0x33,
+ 0x180: 0x35, 0x184: 0x36, 0x186: 0x37, 0x187: 0x38,
+ 0x188: 0x39, 0x189: 0x3a, 0x18a: 0x3b, 0x18b: 0x3c, 0x18c: 0x3d,
+ 0x1ab: 0x3e,
// Block 0x7, offset 0x1c0
- 0x1c1: 0x34, 0x1c2: 0x35, 0x1c3: 0x36,
+ 0x1c1: 0x0b, 0x1c2: 0x3f, 0x1c3: 0x40,
// Block 0x8, offset 0x200
- 0x224: 0x37, 0x225: 0x38, 0x226: 0x39, 0x227: 0x3a,
- 0x228: 0x3b, 0x229: 0x3c, 0x22a: 0x3d, 0x22b: 0x3e, 0x22c: 0x3f, 0x22d: 0x40,
+ 0x224: 0x41, 0x225: 0x42, 0x226: 0x43, 0x227: 0x44,
+ 0x228: 0x45, 0x229: 0x46, 0x22a: 0x0c, 0x22b: 0x0d, 0x22c: 0x47, 0x22d: 0x48,
// Block 0x9, offset 0x240
- 0x242: 0x41,
+ 0x242: 0x49,
// Block 0xa, offset 0x280
- 0x285: 0x42, 0x286: 0x43, 0x287: 0x44,
+ 0x285: 0x4a, 0x286: 0x4b, 0x287: 0x4c,
// Block 0xb, offset 0x2c0
- 0x2e0: 0x45, 0x2e1: 0x46, 0x2e2: 0x47, 0x2e3: 0x48, 0x2e4: 0x49, 0x2e5: 0x4a, 0x2e6: 0x4b, 0x2e7: 0x4c,
+ 0x2e0: 0x0e, 0x2e1: 0x0f, 0x2e2: 0x10, 0x2e3: 0x11, 0x2e4: 0x12, 0x2e5: 0x13, 0x2e6: 0x14, 0x2e7: 0x15,
0x2e8: 0x4d,
// Block 0xc, offset 0x300
0x311: 0x09,
@@ -3076,1288 +3163,1442 @@ var nfcDecompLookup = [832]uint8{
0x32f: 0x0b,
}
-var nfcDecompTrie = trie{nfcDecompLookup[:], nfcDecompValues[:]}
+var nfcDecompTrie = trie{nfcDecompLookup[:], nfcDecompValues[:], nfcDecompSparseValues[:], nfcDecompSparseOffset[:], 22}
-// nfkcDecompValues: 10176 entries, 20352 bytes
+// nfkcDecompValues: 4224 entries, 8448 bytes
// Block 2 is the null block.
-var nfkcDecompValues = [10176]uint16{
+var nfkcDecompValues = [4224]uint16{
// Block 0x0, offset 0x0
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x00e0: 0x0001,
- 0x00e8: 0x0003,
- 0x00ea: 0x0007, 0x00ef: 0x0009,
- 0x00f2: 0x000d, 0x00f3: 0x000f, 0x00f4: 0x0011, 0x00f5: 0x0015,
- 0x00f8: 0x0018, 0x00f9: 0x001c, 0x00fa: 0x001e,
- 0x00fc: 0x0020, 0x00fd: 0x0026, 0x00fe: 0x002c,
+ 0x00c4: 0x02da, 0x00c5: 0x02df,
+ 0x00c6: 0x02e4, 0x00c7: 0x02e9, 0x00c8: 0x02ec, 0x00c9: 0x02ef, 0x00ca: 0x02f2, 0x00cb: 0x02f5,
+ 0x00cc: 0x02f8, 0x00cd: 0x02fb, 0x00ce: 0x02ff, 0x00cf: 0x0303, 0x00d0: 0x0307, 0x00d1: 0x030b,
+ 0x00d2: 0x030f, 0x00d3: 0x0313, 0x00d4: 0x0317, 0x00d5: 0x031b, 0x00d6: 0x0321, 0x00d7: 0x0327,
+ 0x00d8: 0x032d, 0x00d9: 0x0333, 0x00da: 0x0339, 0x00db: 0x033f, 0x00dc: 0x0345,
+ 0x00de: 0x034b, 0x00df: 0x0351, 0x00e0: 0x0357, 0x00e1: 0x035d, 0x00e2: 0x0363, 0x00e3: 0x0368,
+ 0x00e6: 0x036d, 0x00e7: 0x0371, 0x00e8: 0x0375, 0x00e9: 0x0379,
+ 0x00ea: 0x037d, 0x00eb: 0x0381, 0x00ec: 0x0385, 0x00ed: 0x038b, 0x00ee: 0x0391, 0x00ef: 0x0396,
+ 0x00f0: 0x039b, 0x00f1: 0x039f, 0x00f2: 0x03a2, 0x00f3: 0x03a5, 0x00f4: 0x03a8, 0x00f5: 0x03ac,
+ 0x00f8: 0x03b0, 0x00f9: 0x03b4, 0x00fa: 0x03b8, 0x00fb: 0x03be,
+ 0x00fc: 0x03c4, 0x00fd: 0x03c9, 0x00fe: 0x03ce, 0x00ff: 0x03d3,
// Block 0x4, offset 0x100
- 0x0100: 0x0032, 0x0101: 0x0036, 0x0102: 0x003a, 0x0103: 0x003e, 0x0104: 0x0042, 0x0105: 0x0046,
- 0x0107: 0x004a, 0x0108: 0x004e, 0x0109: 0x0052, 0x010a: 0x0056, 0x010b: 0x005a,
- 0x010c: 0x005e, 0x010d: 0x0062, 0x010e: 0x0066, 0x010f: 0x006a, 0x0111: 0x006e,
- 0x0112: 0x0072, 0x0113: 0x0076, 0x0114: 0x007a, 0x0115: 0x007e, 0x0116: 0x0082,
- 0x0119: 0x0086, 0x011a: 0x008a, 0x011b: 0x008e, 0x011c: 0x0092, 0x011d: 0x0096,
- 0x0120: 0x009a, 0x0121: 0x009e, 0x0122: 0x00a2, 0x0123: 0x00a6,
- 0x0124: 0x00aa, 0x0125: 0x00ae, 0x0127: 0x00b2, 0x0128: 0x00b6, 0x0129: 0x00ba,
- 0x012a: 0x00be, 0x012b: 0x00c2, 0x012c: 0x00c6, 0x012d: 0x00ca, 0x012e: 0x00ce, 0x012f: 0x00d2,
- 0x0131: 0x00d6, 0x0132: 0x00da, 0x0133: 0x00de, 0x0134: 0x00e2, 0x0135: 0x00e6,
- 0x0136: 0x00ea, 0x0139: 0x00ee, 0x013a: 0x00f2, 0x013b: 0x00f6,
- 0x013c: 0x00fa, 0x013d: 0x00fe, 0x013f: 0x0102,
+ 0x0100: 0x092d, 0x0101: 0x092f, 0x0102: 0x0931, 0x0103: 0x0007, 0x0104: 0x0933, 0x0105: 0x0936,
+ 0x0106: 0x0939, 0x0107: 0x093d, 0x0108: 0x093f, 0x0109: 0x0941, 0x010a: 0x0943, 0x010b: 0x0946,
+ 0x010c: 0x0949, 0x010d: 0x094c, 0x010f: 0x094e, 0x0110: 0x0950, 0x0111: 0x0952,
+ 0x0112: 0x001e, 0x0113: 0x0955, 0x0114: 0x0958, 0x0115: 0x095c, 0x0116: 0x0960, 0x0117: 0x0962,
+ 0x0118: 0x0964, 0x0119: 0x0966, 0x011a: 0x096a, 0x011b: 0x096d, 0x011c: 0x096f, 0x011d: 0x0559,
+ 0x011e: 0x0973, 0x011f: 0x0976, 0x0120: 0x056c, 0x0121: 0x0979, 0x0122: 0x097c, 0x0123: 0x049b,
+ 0x0124: 0x0964, 0x0125: 0x096d, 0x0126: 0x0559, 0x0127: 0x0973, 0x0128: 0x0575, 0x0129: 0x056c,
+ 0x012a: 0x0979,
+ 0x0138: 0x097e,
// Block 0x5, offset 0x140
- 0x0140: 0x0106, 0x0141: 0x010a, 0x0142: 0x010e, 0x0143: 0x0112, 0x0144: 0x0116, 0x0145: 0x011a,
- 0x0146: 0x011e, 0x0147: 0x0122, 0x0148: 0x0126, 0x0149: 0x012a, 0x014a: 0x012e, 0x014b: 0x0132,
- 0x014c: 0x0136, 0x014d: 0x013a, 0x014e: 0x013e, 0x014f: 0x0142,
- 0x0152: 0x0146, 0x0153: 0x014a, 0x0154: 0x014e, 0x0155: 0x0152, 0x0156: 0x0156, 0x0157: 0x015a,
- 0x0158: 0x015e, 0x0159: 0x0162, 0x015a: 0x0166, 0x015b: 0x016a, 0x015c: 0x016e, 0x015d: 0x0172,
- 0x015e: 0x0176, 0x015f: 0x017a, 0x0160: 0x017e, 0x0161: 0x0182, 0x0162: 0x0186, 0x0163: 0x018a,
- 0x0164: 0x018e, 0x0165: 0x0192, 0x0168: 0x0196, 0x0169: 0x019a,
- 0x016a: 0x019e, 0x016b: 0x01a2, 0x016c: 0x01a6, 0x016d: 0x01aa, 0x016e: 0x01ae, 0x016f: 0x01b2,
- 0x0170: 0x01b6, 0x0172: 0x01ba, 0x0173: 0x01bd, 0x0174: 0x01c0, 0x0175: 0x01c4,
- 0x0176: 0x01c8, 0x0177: 0x01cc, 0x0179: 0x01d0, 0x017a: 0x01d4, 0x017b: 0x01d8,
- 0x017c: 0x01dc, 0x017d: 0x01e0, 0x017e: 0x01e4, 0x017f: 0x01e8,
+ 0x0140: 0x0b02, 0x0141: 0x0b06, 0x0142: 0x0b0a, 0x0143: 0x0b0e, 0x0144: 0x0b12, 0x0145: 0x0b16,
+ 0x0146: 0x0b1a, 0x0147: 0x0b1e, 0x0148: 0x0b22, 0x0149: 0x0b26, 0x014a: 0x0b2a, 0x014b: 0x0b2e,
+ 0x014c: 0x0b32, 0x014d: 0x0b38, 0x014e: 0x0b3e, 0x014f: 0x0b44, 0x0150: 0x0b4a, 0x0151: 0x0b50,
+ 0x0152: 0x0b56, 0x0153: 0x0b5c, 0x0154: 0x0b62, 0x0155: 0x0b66, 0x0156: 0x0b6a, 0x0157: 0x0b6e,
+ 0x0158: 0x0b72, 0x0159: 0x0b76, 0x015a: 0x0b7a, 0x015b: 0x0b7e, 0x015c: 0x0b82, 0x015d: 0x0b88,
+ 0x015e: 0x0b8e, 0x015f: 0x0b92, 0x0160: 0x0b96, 0x0161: 0x0b9a, 0x0162: 0x0b9e, 0x0163: 0x0ba2,
+ 0x0164: 0x0ba6, 0x0165: 0x0bac, 0x0166: 0x0bb2, 0x0167: 0x0bb8, 0x0168: 0x0bbe, 0x0169: 0x0bc4,
+ 0x016a: 0x0bca, 0x016b: 0x0bce, 0x016c: 0x0bd2, 0x016d: 0x0bd6, 0x016e: 0x0bda, 0x016f: 0x0bde,
+ 0x0170: 0x0be2, 0x0171: 0x0be6, 0x0172: 0x0bea, 0x0173: 0x0bee, 0x0174: 0x0bf2, 0x0175: 0x0bf6,
+ 0x0176: 0x0bfa, 0x0177: 0x0bfe, 0x0178: 0x0c02, 0x0179: 0x0c08, 0x017a: 0x0c0e, 0x017b: 0x0c14,
+ 0x017c: 0x0c1a, 0x017d: 0x0c1e, 0x017e: 0x0c22, 0x017f: 0x0c26,
// Block 0x6, offset 0x180
- 0x0180: 0x01ec, 0x0183: 0x01f0, 0x0184: 0x01f4, 0x0185: 0x01f8,
- 0x0186: 0x01fc, 0x0187: 0x0200, 0x0188: 0x0204, 0x0189: 0x0208,
- 0x018c: 0x020c, 0x018d: 0x0210, 0x018e: 0x0214, 0x018f: 0x0218, 0x0190: 0x021c, 0x0191: 0x0220,
- 0x0194: 0x0224, 0x0195: 0x0228, 0x0196: 0x022c, 0x0197: 0x0230,
- 0x0198: 0x0234, 0x0199: 0x0238, 0x019a: 0x023c, 0x019b: 0x0240, 0x019c: 0x0244, 0x019d: 0x0248,
- 0x019e: 0x024c, 0x019f: 0x0250, 0x01a0: 0x0254, 0x01a1: 0x0258, 0x01a2: 0x025c, 0x01a3: 0x0260,
- 0x01a4: 0x0264, 0x01a5: 0x0268, 0x01a8: 0x026c, 0x01a9: 0x0270,
- 0x01aa: 0x0274, 0x01ab: 0x0278, 0x01ac: 0x027c, 0x01ad: 0x0280, 0x01ae: 0x0284, 0x01af: 0x0288,
- 0x01b0: 0x028c, 0x01b1: 0x0290, 0x01b2: 0x0294, 0x01b3: 0x0298, 0x01b4: 0x029c, 0x01b5: 0x02a0,
- 0x01b6: 0x02a4, 0x01b7: 0x02a8, 0x01b8: 0x02ac, 0x01b9: 0x02b0, 0x01ba: 0x02b4, 0x01bb: 0x02b8,
- 0x01bc: 0x02bc, 0x01bd: 0x02c0, 0x01be: 0x02c4, 0x01bf: 0x02c8,
+ 0x0180: 0x0c2a, 0x0181: 0x0c2e, 0x0182: 0x0c32, 0x0183: 0x0c36, 0x0184: 0x0c3a, 0x0185: 0x0c3e,
+ 0x0186: 0x0c42, 0x0187: 0x0c46, 0x0188: 0x0c4a, 0x0189: 0x0c4e, 0x018a: 0x0c52, 0x018b: 0x0c56,
+ 0x018c: 0x0c5a, 0x018d: 0x0c5e, 0x018e: 0x0c62, 0x018f: 0x0c66, 0x0190: 0x0c6a, 0x0191: 0x0c6e,
+ 0x0192: 0x0c72, 0x0193: 0x0c76, 0x0194: 0x0c7a, 0x0195: 0x0c7e, 0x0196: 0x0c82, 0x0197: 0x0c86,
+ 0x0198: 0x0c8a, 0x0199: 0x0c8e, 0x019a: 0x0c92, 0x019b: 0x0b9a,
+ 0x01a0: 0x0c9b, 0x01a1: 0x0c9f, 0x01a2: 0x0ca3, 0x01a3: 0x0ca7,
+ 0x01a4: 0x0cab, 0x01a5: 0x0cb1, 0x01a6: 0x0cb7, 0x01a7: 0x0cbd, 0x01a8: 0x0cc3, 0x01a9: 0x0cc9,
+ 0x01aa: 0x0ccf, 0x01ab: 0x0cd5, 0x01ac: 0x0cdb, 0x01ad: 0x0ce1, 0x01ae: 0x0ce7, 0x01af: 0x0ced,
+ 0x01b0: 0x0cf3, 0x01b1: 0x0cf9, 0x01b2: 0x0cff, 0x01b3: 0x0d05, 0x01b4: 0x0d0b, 0x01b5: 0x0d11,
+ 0x01b6: 0x0d17, 0x01b7: 0x0d1d, 0x01b8: 0x0d23, 0x01b9: 0x0d27, 0x01ba: 0x0d2b, 0x01bb: 0x0d2f,
+ 0x01bc: 0x0d33, 0x01bd: 0x0d37, 0x01be: 0x0d3b, 0x01bf: 0x0d41,
// Block 0x7, offset 0x1c0
- 0x01e0: 0x02ca, 0x01e1: 0x02ce,
- 0x01ef: 0x02d2,
- 0x01f0: 0x02d6,
+ 0x01c0: 0x0d47, 0x01c1: 0x0d4d, 0x01c2: 0x0d53, 0x01c3: 0x0d59, 0x01c4: 0x0d5f, 0x01c5: 0x0d65,
+ 0x01c6: 0x0d6b, 0x01c7: 0x0d71, 0x01c8: 0x0d77, 0x01c9: 0x0d7b, 0x01ca: 0x0d7f, 0x01cb: 0x0d83,
+ 0x01cc: 0x0d87, 0x01cd: 0x0d8b, 0x01ce: 0x0d8f, 0x01cf: 0x0d93, 0x01d0: 0x0d97, 0x01d1: 0x0d9d,
+ 0x01d2: 0x0da3, 0x01d3: 0x0da9, 0x01d4: 0x0daf, 0x01d5: 0x0db5, 0x01d6: 0x0dbb, 0x01d7: 0x0dc1,
+ 0x01d8: 0x0dc7, 0x01d9: 0x0dcd, 0x01da: 0x0dd3, 0x01db: 0x0dd9, 0x01dc: 0x0ddf, 0x01dd: 0x0de5,
+ 0x01de: 0x0deb, 0x01df: 0x0df1, 0x01e0: 0x0df7, 0x01e1: 0x0dfd, 0x01e2: 0x0e03, 0x01e3: 0x0e09,
+ 0x01e4: 0x0e0f, 0x01e5: 0x0e13, 0x01e6: 0x0e17, 0x01e7: 0x0e1b, 0x01e8: 0x0e1f, 0x01e9: 0x0e25,
+ 0x01ea: 0x0e2b, 0x01eb: 0x0e31, 0x01ec: 0x0e37, 0x01ed: 0x0e3d, 0x01ee: 0x0e43, 0x01ef: 0x0e49,
+ 0x01f0: 0x0e4f, 0x01f1: 0x0e55, 0x01f2: 0x0e5b, 0x01f3: 0x0e5f, 0x01f4: 0x0e63, 0x01f5: 0x0e67,
+ 0x01f6: 0x0e6b, 0x01f7: 0x0e6f, 0x01f8: 0x0e73, 0x01f9: 0x0e77,
// Block 0x8, offset 0x200
- 0x0204: 0x02da, 0x0205: 0x02df,
- 0x0206: 0x02e4, 0x0207: 0x02e9, 0x0208: 0x02ec, 0x0209: 0x02ef, 0x020a: 0x02f2, 0x020b: 0x02f5,
- 0x020c: 0x02f8, 0x020d: 0x02fb, 0x020e: 0x02ff, 0x020f: 0x0303, 0x0210: 0x0307, 0x0211: 0x030b,
- 0x0212: 0x030f, 0x0213: 0x0313, 0x0214: 0x0317, 0x0215: 0x031b, 0x0216: 0x0321, 0x0217: 0x0327,
- 0x0218: 0x032d, 0x0219: 0x0333, 0x021a: 0x0339, 0x021b: 0x033f, 0x021c: 0x0345,
- 0x021e: 0x034b, 0x021f: 0x0351, 0x0220: 0x0357, 0x0221: 0x035d, 0x0222: 0x0363, 0x0223: 0x0368,
- 0x0226: 0x036d, 0x0227: 0x0371, 0x0228: 0x0375, 0x0229: 0x0379,
- 0x022a: 0x037d, 0x022b: 0x0381, 0x022c: 0x0385, 0x022d: 0x038b, 0x022e: 0x0391, 0x022f: 0x0396,
- 0x0230: 0x039b, 0x0231: 0x039f, 0x0232: 0x03a2, 0x0233: 0x03a5, 0x0234: 0x03a8, 0x0235: 0x03ac,
- 0x0238: 0x03b0, 0x0239: 0x03b4, 0x023a: 0x03b8, 0x023b: 0x03be,
- 0x023c: 0x03c4, 0x023d: 0x03c9, 0x023e: 0x03ce, 0x023f: 0x03d3,
+ 0x0200: 0x0e7b, 0x0201: 0x0e80, 0x0202: 0x0e85, 0x0203: 0x0e8c, 0x0204: 0x0e93, 0x0205: 0x0e9a,
+ 0x0206: 0x0ea1, 0x0207: 0x0ea8, 0x0208: 0x0eaf, 0x0209: 0x0eb4, 0x020a: 0x0eb9, 0x020b: 0x0ec0,
+ 0x020c: 0x0ec7, 0x020d: 0x0ece, 0x020e: 0x0ed5, 0x020f: 0x0edc, 0x0210: 0x0ee3, 0x0211: 0x0ee8,
+ 0x0212: 0x0eed, 0x0213: 0x0ef4, 0x0214: 0x0efb, 0x0215: 0x0f02,
+ 0x0218: 0x0f09, 0x0219: 0x0f0e, 0x021a: 0x0f13, 0x021b: 0x0f1a, 0x021c: 0x0f21, 0x021d: 0x0f28,
+ 0x0220: 0x0f2f, 0x0221: 0x0f34, 0x0222: 0x0f39, 0x0223: 0x0f40,
+ 0x0224: 0x0f47, 0x0225: 0x0f4e, 0x0226: 0x0f55, 0x0227: 0x0f5c, 0x0228: 0x0f63, 0x0229: 0x0f68,
+ 0x022a: 0x0f6d, 0x022b: 0x0f74, 0x022c: 0x0f7b, 0x022d: 0x0f82, 0x022e: 0x0f89, 0x022f: 0x0f90,
+ 0x0230: 0x0f97, 0x0231: 0x0f9c, 0x0232: 0x0fa1, 0x0233: 0x0fa8, 0x0234: 0x0faf, 0x0235: 0x0fb6,
+ 0x0236: 0x0fbd, 0x0237: 0x0fc4, 0x0238: 0x0fcb, 0x0239: 0x0fd0, 0x023a: 0x0fd5, 0x023b: 0x0fdc,
+ 0x023c: 0x0fe3, 0x023d: 0x0fea, 0x023e: 0x0ff1, 0x023f: 0x0ff8,
// Block 0x9, offset 0x240
- 0x0240: 0x03d8, 0x0241: 0x03dc, 0x0242: 0x03e0, 0x0243: 0x03e4, 0x0244: 0x03e8, 0x0245: 0x03ec,
- 0x0246: 0x03f0, 0x0247: 0x03f4, 0x0248: 0x03f8, 0x0249: 0x03fc, 0x024a: 0x0400, 0x024b: 0x0404,
- 0x024c: 0x0408, 0x024d: 0x040c, 0x024e: 0x0410, 0x024f: 0x0414, 0x0250: 0x0418, 0x0251: 0x041c,
- 0x0252: 0x0420, 0x0253: 0x0424, 0x0254: 0x0428, 0x0255: 0x042c, 0x0256: 0x0430, 0x0257: 0x0434,
- 0x0258: 0x0438, 0x0259: 0x043c, 0x025a: 0x0440, 0x025b: 0x0444,
- 0x025e: 0x0448, 0x025f: 0x044c,
- 0x0266: 0x0450, 0x0267: 0x0454, 0x0268: 0x0458, 0x0269: 0x045c,
- 0x026a: 0x0460, 0x026b: 0x0466, 0x026c: 0x046c, 0x026d: 0x0472, 0x026e: 0x0478, 0x026f: 0x047c,
- 0x0270: 0x0480, 0x0271: 0x0486, 0x0272: 0x048c, 0x0273: 0x0490,
+ 0x0240: 0x0fff, 0x0241: 0x1004, 0x0242: 0x1009, 0x0243: 0x1010, 0x0244: 0x1017, 0x0245: 0x101e,
+ 0x0248: 0x1025, 0x0249: 0x102a, 0x024a: 0x102f, 0x024b: 0x1036,
+ 0x024c: 0x103d, 0x024d: 0x1044, 0x0250: 0x104b, 0x0251: 0x1050,
+ 0x0252: 0x1055, 0x0253: 0x105c, 0x0254: 0x1063, 0x0255: 0x106a, 0x0256: 0x1071, 0x0257: 0x1078,
+ 0x0259: 0x107f, 0x025b: 0x1084, 0x025d: 0x108b,
+ 0x025f: 0x1092, 0x0260: 0x1099, 0x0261: 0x109e, 0x0262: 0x10a3, 0x0263: 0x10aa,
+ 0x0264: 0x10b1, 0x0265: 0x10b8, 0x0266: 0x10bf, 0x0267: 0x10c6, 0x0268: 0x10cd, 0x0269: 0x10d2,
+ 0x026a: 0x10d7, 0x026b: 0x10de, 0x026c: 0x10e5, 0x026d: 0x10ec, 0x026e: 0x10f3, 0x026f: 0x10fa,
+ 0x0270: 0x1101, 0x0271: 0x0525, 0x0272: 0x1106, 0x0273: 0x052a, 0x0274: 0x110b, 0x0275: 0x052f,
+ 0x0276: 0x1110, 0x0277: 0x0534, 0x0278: 0x1115, 0x0279: 0x054a, 0x027a: 0x111a, 0x027b: 0x054f,
+ 0x027c: 0x111f, 0x027d: 0x0554,
// Block 0xa, offset 0x280
- 0x02b0: 0x0494, 0x02b1: 0x0496, 0x02b2: 0x0499, 0x02b3: 0x049b, 0x02b4: 0x049d, 0x02b5: 0x04a0,
- 0x02b6: 0x04a3, 0x02b7: 0x04a6, 0x02b8: 0x04a8,
+ 0x0280: 0x1124, 0x0281: 0x112b, 0x0282: 0x1132, 0x0283: 0x113b, 0x0284: 0x1144, 0x0285: 0x114d,
+ 0x0286: 0x1156, 0x0287: 0x115f, 0x0288: 0x1168, 0x0289: 0x116f, 0x028a: 0x1176, 0x028b: 0x117f,
+ 0x028c: 0x1188, 0x028d: 0x1191, 0x028e: 0x119a, 0x028f: 0x11a3, 0x0290: 0x11ac, 0x0291: 0x11b3,
+ 0x0292: 0x11ba, 0x0293: 0x11c3, 0x0294: 0x11cc, 0x0295: 0x11d5, 0x0296: 0x11de, 0x0297: 0x11e7,
+ 0x0298: 0x11f0, 0x0299: 0x11f7, 0x029a: 0x11fe, 0x029b: 0x1207, 0x029c: 0x1210, 0x029d: 0x1219,
+ 0x029e: 0x1222, 0x029f: 0x122b, 0x02a0: 0x1234, 0x02a1: 0x123b, 0x02a2: 0x1242, 0x02a3: 0x124b,
+ 0x02a4: 0x1254, 0x02a5: 0x125d, 0x02a6: 0x1266, 0x02a7: 0x126f, 0x02a8: 0x1278, 0x02a9: 0x127f,
+ 0x02aa: 0x1286, 0x02ab: 0x128f, 0x02ac: 0x1298, 0x02ad: 0x12a1, 0x02ae: 0x12aa, 0x02af: 0x12b3,
+ 0x02b0: 0x12bc, 0x02b1: 0x12c1, 0x02b2: 0x12c6, 0x02b3: 0x12cd, 0x02b4: 0x12d2,
+ 0x02b6: 0x12d9, 0x02b7: 0x12de, 0x02b8: 0x12e5, 0x02b9: 0x12ea, 0x02ba: 0x12ef, 0x02bb: 0x04ee,
+ 0x02bc: 0x12f4, 0x02bd: 0x12f9, 0x02be: 0x12fd, 0x02bf: 0x12f9,
// Block 0xb, offset 0x2c0
- 0x02d8: 0x04aa, 0x02d9: 0x04ae, 0x02da: 0x04b2, 0x02db: 0x04b6, 0x02dc: 0x04ba, 0x02dd: 0x04be,
- 0x02e0: 0x04c2, 0x02e1: 0x04c5, 0x02e2: 0x02c8, 0x02e3: 0x04c7,
- 0x02e4: 0x04c9,
+ 0x02c0: 0x1300, 0x02c1: 0x1309, 0x02c2: 0x130f, 0x02c3: 0x1316, 0x02c4: 0x131b,
+ 0x02c6: 0x1322, 0x02c7: 0x1327, 0x02c8: 0x132e, 0x02c9: 0x04f6, 0x02ca: 0x1333, 0x02cb: 0x04fb,
+ 0x02cc: 0x1338, 0x02cd: 0x1343, 0x02ce: 0x134f, 0x02cf: 0x135b, 0x02d0: 0x1361, 0x02d1: 0x1366,
+ 0x02d2: 0x136b, 0x02d3: 0x0514, 0x02d6: 0x1372, 0x02d7: 0x1377,
+ 0x02d8: 0x137e, 0x02d9: 0x1383, 0x02da: 0x1388, 0x02db: 0x0500, 0x02dd: 0x1393,
+ 0x02de: 0x139f, 0x02df: 0x13ab, 0x02e0: 0x13b1, 0x02e1: 0x13b6, 0x02e2: 0x13bb, 0x02e3: 0x0539,
+ 0x02e4: 0x13c2, 0x02e5: 0x13c7, 0x02e6: 0x13cc, 0x02e7: 0x13d1, 0x02e8: 0x13d8, 0x02e9: 0x13dd,
+ 0x02ea: 0x13e2, 0x02eb: 0x050a, 0x02ec: 0x13e7, 0x02ed: 0x13f1, 0x02ee: 0x04e8, 0x02ef: 0x13f7,
+ 0x02f2: 0x13f9, 0x02f3: 0x1400, 0x02f4: 0x1405,
+ 0x02f6: 0x140c, 0x02f7: 0x1411, 0x02f8: 0x1418, 0x02f9: 0x0505, 0x02fa: 0x141d, 0x02fb: 0x050f,
+ 0x02fc: 0x1422, 0x02fd: 0x0011, 0x02fe: 0x142a,
// Block 0xc, offset 0x300
- 0x0300: 0x04cc, 0x0301: 0x04cf, 0x0303: 0x04d2, 0x0304: 0x04d5,
- 0x0334: 0x04da,
- 0x033a: 0x04dd,
- 0x033e: 0x04e1,
+ 0x0300: 0x1486, 0x0301: 0x001c, 0x0302: 0x000d, 0x0303: 0x000f, 0x0304: 0x1488, 0x0305: 0x148a,
+ 0x0306: 0x148c, 0x0307: 0x148e, 0x0308: 0x1490, 0x0309: 0x1492, 0x030a: 0x1494, 0x030b: 0x1496,
+ 0x030c: 0x149a, 0x030d: 0x149c, 0x030e: 0x149e, 0x0310: 0x0007, 0x0311: 0x0941,
+ 0x0312: 0x001e, 0x0313: 0x04c7, 0x0314: 0x0943, 0x0315: 0x0494, 0x0316: 0x094e, 0x0317: 0x04c5,
+ 0x0318: 0x0950, 0x0319: 0x14a0, 0x031a: 0x0960, 0x031b: 0x02c8, 0x031c: 0x0962,
+ 0x0328: 0x14a2,
// Block 0xd, offset 0x340
- 0x0344: 0x0011, 0x0345: 0x04e8,
- 0x0346: 0x04ee, 0x0347: 0x04f3, 0x0348: 0x04f6, 0x0349: 0x04fb, 0x034a: 0x0500,
- 0x034c: 0x0505, 0x034e: 0x050a, 0x034f: 0x050f, 0x0350: 0x0514,
- 0x036a: 0x051b, 0x036b: 0x0520, 0x036c: 0x0525, 0x036d: 0x052a, 0x036e: 0x052f, 0x036f: 0x0534,
- 0x0370: 0x0539,
+ 0x0340: 0x14a5, 0x0341: 0x14a9, 0x0342: 0x14ad, 0x0343: 0x14af, 0x0345: 0x14b3,
+ 0x0346: 0x14b7, 0x0347: 0x14bb, 0x0349: 0x14be, 0x034a: 0x094c, 0x034b: 0x0916,
+ 0x034c: 0x0916, 0x034d: 0x0916, 0x034e: 0x0494, 0x034f: 0x14c2, 0x0350: 0x0918, 0x0351: 0x0918,
+ 0x0352: 0x091e, 0x0353: 0x04c5, 0x0355: 0x0922, 0x0356: 0x14c5,
+ 0x0359: 0x0929, 0x035a: 0x14c8, 0x035b: 0x092b, 0x035c: 0x092b, 0x035d: 0x092b,
+ 0x0360: 0x14ca, 0x0361: 0x14cd, 0x0362: 0x14d1,
+ 0x0364: 0x14d4, 0x0366: 0x14d6, 0x0368: 0x14d4,
+ 0x036a: 0x091c, 0x036b: 0x0046, 0x036c: 0x090b, 0x036d: 0x14ad, 0x036f: 0x0941,
+ 0x0370: 0x090f, 0x0371: 0x14d9, 0x0373: 0x0920, 0x0374: 0x001e, 0x0375: 0x14db,
+ 0x0376: 0x14de, 0x0377: 0x14e1, 0x0378: 0x14e4, 0x0379: 0x097c, 0x037b: 0x14e7,
+ 0x037c: 0x056f, 0x037d: 0x0973, 0x037e: 0x14eb, 0x037f: 0x14ee,
// Block 0xe, offset 0x380
- 0x038a: 0x0540, 0x038b: 0x0545,
- 0x038c: 0x054a, 0x038d: 0x054f, 0x038e: 0x0554, 0x0390: 0x0559, 0x0391: 0x055c,
- 0x0392: 0x055f, 0x0393: 0x050a, 0x0394: 0x0520, 0x0395: 0x056c, 0x0396: 0x056f,
- 0x03b0: 0x0572, 0x03b1: 0x0575, 0x03b2: 0x0578, 0x03b4: 0x057b, 0x03b5: 0x057e,
- 0x03b9: 0x0581,
+ 0x0380: 0x14f1, 0x0385: 0x090d,
+ 0x0386: 0x093f, 0x0387: 0x0941, 0x0388: 0x097c, 0x0389: 0x0499,
+ 0x0390: 0x14f5, 0x0391: 0x14fb,
+ 0x0392: 0x1501, 0x0393: 0x1508, 0x0394: 0x150e, 0x0395: 0x1514, 0x0396: 0x151a, 0x0397: 0x1520,
+ 0x0398: 0x1526, 0x0399: 0x152c, 0x039a: 0x1532, 0x039b: 0x1538, 0x039c: 0x153e, 0x039d: 0x1544,
+ 0x039e: 0x154a, 0x039f: 0x1550, 0x03a0: 0x0918, 0x03a1: 0x1555, 0x03a2: 0x1558, 0x03a3: 0x155c,
+ 0x03a4: 0x155f, 0x03a5: 0x1561, 0x03a6: 0x1564, 0x03a7: 0x1568, 0x03a8: 0x156d, 0x03a9: 0x1570,
+ 0x03aa: 0x1572, 0x03ab: 0x1575, 0x03ac: 0x091e, 0x03ad: 0x14ad, 0x03ae: 0x090d, 0x03af: 0x0920,
+ 0x03b0: 0x097c, 0x03b1: 0x1579, 0x03b2: 0x157c, 0x03b3: 0x1580, 0x03b4: 0x096d, 0x03b5: 0x1583,
+ 0x03b6: 0x1586, 0x03b7: 0x158a, 0x03b8: 0x158f, 0x03b9: 0x04c7, 0x03ba: 0x1592, 0x03bb: 0x1595,
+ 0x03bc: 0x04c5, 0x03bd: 0x0984, 0x03be: 0x093f, 0x03bf: 0x0950,
// Block 0xf, offset 0x3c0
- 0x03c0: 0x0584, 0x03c1: 0x0589, 0x03c3: 0x058e,
- 0x03c7: 0x0593,
- 0x03cc: 0x0598, 0x03cd: 0x059d, 0x03ce: 0x05a2,
- 0x03d9: 0x05a7,
- 0x03f9: 0x05ac,
+ 0x03e0: 0x001c, 0x03e1: 0x000d, 0x03e2: 0x000f, 0x03e3: 0x1488,
+ 0x03e4: 0x148a, 0x03e5: 0x148c, 0x03e6: 0x148e, 0x03e7: 0x1490, 0x03e8: 0x1492, 0x03e9: 0x16cb,
+ 0x03ea: 0x16ce, 0x03eb: 0x16d1, 0x03ec: 0x16d4, 0x03ed: 0x16d7, 0x03ee: 0x16da, 0x03ef: 0x16dd,
+ 0x03f0: 0x16e0, 0x03f1: 0x16e3, 0x03f2: 0x16e6, 0x03f3: 0x16e9, 0x03f4: 0x16ec, 0x03f5: 0x16f0,
+ 0x03f6: 0x16f4, 0x03f7: 0x16f8, 0x03f8: 0x16fc, 0x03f9: 0x1700, 0x03fa: 0x1704, 0x03fb: 0x1708,
+ 0x03fc: 0x170c, 0x03fd: 0x1710, 0x03fe: 0x1715, 0x03ff: 0x171a,
// Block 0x10, offset 0x400
- 0x0410: 0x05b1, 0x0411: 0x05b6,
- 0x0413: 0x05bb, 0x0417: 0x05c0,
- 0x041c: 0x05c5, 0x041d: 0x05ca,
- 0x041e: 0x05cf,
- 0x0436: 0x05d4, 0x0437: 0x05d9,
+ 0x0400: 0x171f, 0x0401: 0x1724, 0x0402: 0x1729, 0x0403: 0x172e, 0x0404: 0x1733, 0x0405: 0x1738,
+ 0x0406: 0x173d, 0x0407: 0x1742, 0x0408: 0x1747, 0x0409: 0x174a, 0x040a: 0x174d, 0x040b: 0x1750,
+ 0x040c: 0x1753, 0x040d: 0x1756, 0x040e: 0x1759, 0x040f: 0x175c, 0x0410: 0x175f, 0x0411: 0x1762,
+ 0x0412: 0x1766, 0x0413: 0x176a, 0x0414: 0x176e, 0x0415: 0x1772, 0x0416: 0x1776, 0x0417: 0x177a,
+ 0x0418: 0x177e, 0x0419: 0x1782, 0x041a: 0x1786, 0x041b: 0x178a, 0x041c: 0x178e, 0x041d: 0x1792,
+ 0x041e: 0x1796, 0x041f: 0x179a, 0x0420: 0x179e, 0x0421: 0x17a2, 0x0422: 0x17a6, 0x0423: 0x17aa,
+ 0x0424: 0x17ae, 0x0425: 0x17b2, 0x0426: 0x17b6, 0x0427: 0x17ba, 0x0428: 0x17be, 0x0429: 0x17c2,
+ 0x042a: 0x17c6, 0x042b: 0x17ca, 0x042c: 0x17ce, 0x042d: 0x17d2, 0x042e: 0x17d6, 0x042f: 0x17da,
+ 0x0430: 0x17de, 0x0431: 0x17e2, 0x0432: 0x17e6, 0x0433: 0x17ea, 0x0434: 0x17ee, 0x0435: 0x17f2,
+ 0x0436: 0x0906, 0x0437: 0x090b, 0x0438: 0x14ad, 0x0439: 0x090d, 0x043a: 0x090f, 0x043b: 0x14d9,
+ 0x043c: 0x0914, 0x043d: 0x0916, 0x043e: 0x0918, 0x043f: 0x091a,
// Block 0x11, offset 0x440
- 0x0441: 0x05de, 0x0442: 0x05e3,
- 0x0450: 0x05e8, 0x0451: 0x05ed,
- 0x0452: 0x05f2, 0x0453: 0x05f7, 0x0456: 0x05fc, 0x0457: 0x0601,
- 0x045a: 0x0606, 0x045b: 0x060b, 0x045c: 0x0610, 0x045d: 0x0615,
- 0x045e: 0x061a, 0x045f: 0x061f, 0x0462: 0x0624, 0x0463: 0x0629,
- 0x0464: 0x062e, 0x0465: 0x0633, 0x0466: 0x0638, 0x0467: 0x063d,
- 0x046a: 0x0642, 0x046b: 0x0647, 0x046c: 0x064c, 0x046d: 0x0651, 0x046e: 0x0656, 0x046f: 0x065b,
- 0x0470: 0x0660, 0x0471: 0x0665, 0x0472: 0x066a, 0x0473: 0x066f, 0x0474: 0x0674, 0x0475: 0x0679,
- 0x0478: 0x067e, 0x0479: 0x0683,
+ 0x0440: 0x091c, 0x0441: 0x091e, 0x0442: 0x0920, 0x0443: 0x0922, 0x0444: 0x0924, 0x0445: 0x0929,
+ 0x0446: 0x14c8, 0x0447: 0x092b, 0x0448: 0x17f6, 0x0449: 0x092d, 0x044a: 0x092f, 0x044b: 0x155f,
+ 0x044c: 0x0931, 0x044d: 0x1570, 0x044e: 0x17f8, 0x044f: 0x14d4, 0x0450: 0x0007, 0x0451: 0x093d,
+ 0x0452: 0x0984, 0x0453: 0x093f, 0x0454: 0x0941, 0x0455: 0x098c, 0x0456: 0x094c, 0x0457: 0x0494,
+ 0x0458: 0x097c, 0x0459: 0x0499, 0x045a: 0x094e, 0x045b: 0x04c5, 0x045c: 0x0950, 0x045d: 0x14a0,
+ 0x045e: 0x001e, 0x045f: 0x0960, 0x0460: 0x17fa, 0x0461: 0x049b, 0x0462: 0x02c8, 0x0463: 0x0962,
+ 0x0464: 0x0964, 0x0465: 0x096d, 0x0466: 0x04a6, 0x0467: 0x04c7, 0x0468: 0x04a8, 0x0469: 0x09df,
+ 0x046a: 0x1486,
// Block 0x12, offset 0x480
- 0x0487: 0x0688,
+ 0x048c: 0x1b8a, 0x048e: 0x1b91, 0x0490: 0x1b98,
+ 0x0492: 0x1b9f, 0x0494: 0x1ba6, 0x0496: 0x1bad,
+ 0x0498: 0x1bb4, 0x049a: 0x1bbb, 0x049c: 0x1bc2,
+ 0x049e: 0x1bc9, 0x04a0: 0x1bd0, 0x04a2: 0x1bd7,
+ 0x04a5: 0x1bde, 0x04a7: 0x1be5, 0x04a9: 0x1bec,
+ 0x04b0: 0x1bf3, 0x04b1: 0x1bfa, 0x04b3: 0x1c01, 0x04b4: 0x1c08,
+ 0x04b6: 0x1c0f, 0x04b7: 0x1c16, 0x04b9: 0x1c1d, 0x04ba: 0x1c24,
+ 0x04bc: 0x1c2b, 0x04bd: 0x1c32,
// Block 0x13, offset 0x4c0
- 0x04e2: 0x068d, 0x04e3: 0x0692,
- 0x04e4: 0x0697, 0x04e5: 0x069c, 0x04e6: 0x06a1,
+ 0x04c0: 0x1ed8, 0x04c1: 0x1ede, 0x04c2: 0x1ee4, 0x04c3: 0x1eea, 0x04c4: 0x1ef0, 0x04c5: 0x1ef6,
+ 0x04c6: 0x1efc, 0x04c7: 0x1f02, 0x04c8: 0x1f08, 0x04c9: 0x1f0e, 0x04ca: 0x1f14, 0x04cb: 0x1f1a,
+ 0x04cc: 0x1f20, 0x04cd: 0x1f26, 0x04ce: 0x1f2c, 0x04cf: 0x1f35, 0x04d0: 0x1f3e, 0x04d1: 0x1f47,
+ 0x04d2: 0x1f50, 0x04d3: 0x1f59, 0x04d4: 0x1f62, 0x04d5: 0x1f6b, 0x04d6: 0x1f74, 0x04d7: 0x1f7d,
+ 0x04d8: 0x1f86, 0x04d9: 0x1f8f, 0x04da: 0x1f98, 0x04db: 0x1fa1, 0x04dc: 0x1faa, 0x04dd: 0x1fb3,
+ 0x04de: 0x1fc5, 0x04e0: 0x1fd4, 0x04e1: 0x1fda, 0x04e2: 0x1fe0, 0x04e3: 0x1fe6,
+ 0x04e4: 0x1fec, 0x04e5: 0x1ff2, 0x04e6: 0x1ff8, 0x04e7: 0x1ffe, 0x04e8: 0x2004, 0x04e9: 0x200a,
+ 0x04ea: 0x2010, 0x04eb: 0x2016, 0x04ec: 0x201c, 0x04ed: 0x2022, 0x04ee: 0x2028, 0x04ef: 0x202e,
+ 0x04f0: 0x2034, 0x04f1: 0x203a, 0x04f2: 0x2040, 0x04f3: 0x2046, 0x04f4: 0x204c, 0x04f5: 0x2052,
+ 0x04f6: 0x2058, 0x04f7: 0x205e, 0x04f8: 0x2064, 0x04f9: 0x206a, 0x04fa: 0x2070, 0x04fb: 0x2076,
+ 0x04fc: 0x207c, 0x04fd: 0x2082, 0x04fe: 0x2088, 0x04ff: 0x208e,
// Block 0x14, offset 0x500
- 0x0535: 0x06a6,
- 0x0536: 0x06ab, 0x0537: 0x06b0, 0x0538: 0x06b5,
+ 0x0500: 0x2094, 0x0501: 0x209a, 0x0502: 0x20a0, 0x0503: 0x20a6, 0x0504: 0x20ac, 0x0505: 0x20b0,
+ 0x0506: 0x192e, 0x0507: 0x20b4,
+ 0x0510: 0x20b8, 0x0511: 0x20bc,
+ 0x0512: 0x20bf, 0x0513: 0x20c2, 0x0514: 0x20c5, 0x0515: 0x20c8, 0x0516: 0x20cb, 0x0517: 0x20ce,
+ 0x0518: 0x20d1, 0x0519: 0x20d4, 0x051a: 0x20d7, 0x051b: 0x20da, 0x051c: 0x20dd, 0x051d: 0x20e0,
+ 0x051e: 0x20e3, 0x051f: 0x20e6, 0x0520: 0x1d38, 0x0521: 0x1d44, 0x0522: 0x1d50, 0x0523: 0x1d58,
+ 0x0524: 0x1d78, 0x0525: 0x1d7c, 0x0526: 0x1d88, 0x0527: 0x1d90, 0x0528: 0x1d94, 0x0529: 0x1d9c,
+ 0x052a: 0x1da0, 0x052b: 0x1da4, 0x052c: 0x1da8, 0x052d: 0x1dac, 0x052e: 0x20e9, 0x052f: 0x20f0,
+ 0x0530: 0x20f7, 0x0531: 0x20fe, 0x0532: 0x2105, 0x0533: 0x210c, 0x0534: 0x2113, 0x0535: 0x211a,
+ 0x0536: 0x2121, 0x0537: 0x2128, 0x0538: 0x212f, 0x0539: 0x2136, 0x053a: 0x213d, 0x053b: 0x2144,
+ 0x053c: 0x214b, 0x053d: 0x215b, 0x053e: 0x2168,
// Block 0x15, offset 0x540
- 0x0540: 0x06ba, 0x0542: 0x06bf,
- 0x0553: 0x06c4,
+ 0x0540: 0x1826, 0x0541: 0x183e, 0x0542: 0x1eb0, 0x0543: 0x1eb4, 0x0544: 0x216f, 0x0545: 0x2173,
+ 0x0546: 0x2177, 0x0547: 0x1852, 0x0548: 0x217b, 0x0549: 0x1882, 0x054a: 0x194a, 0x054b: 0x197a,
+ 0x054c: 0x1976, 0x054d: 0x194e, 0x054e: 0x1abe, 0x054f: 0x18a2, 0x0550: 0x1942, 0x0551: 0x217f,
+ 0x0552: 0x2183, 0x0553: 0x2187, 0x0554: 0x218b, 0x0555: 0x218f, 0x0556: 0x2193, 0x0557: 0x2197,
+ 0x0558: 0x219b, 0x0559: 0x219f, 0x055a: 0x21a3, 0x055b: 0x18ba, 0x055c: 0x21a7, 0x055d: 0x21ab,
+ 0x055e: 0x21af, 0x055f: 0x21b3, 0x0560: 0x21b7, 0x0561: 0x21bb, 0x0562: 0x21bf, 0x0563: 0x21c3,
+ 0x0564: 0x1eb8, 0x0565: 0x1ebc, 0x0566: 0x1ec0, 0x0567: 0x21c7, 0x0568: 0x21cb, 0x0569: 0x21cf,
+ 0x056a: 0x21d3, 0x056b: 0x21d7, 0x056c: 0x21db, 0x056d: 0x21df, 0x056e: 0x21e3, 0x056f: 0x21e7,
+ 0x0570: 0x21eb, 0x0571: 0x21ef, 0x0572: 0x21f2, 0x0573: 0x21f5, 0x0574: 0x21f8, 0x0575: 0x21fb,
+ 0x0576: 0x21fe, 0x0577: 0x2201, 0x0578: 0x2204, 0x0579: 0x2207, 0x057a: 0x220a, 0x057b: 0x220d,
+ 0x057c: 0x2210, 0x057d: 0x2213, 0x057e: 0x2216, 0x057f: 0x2219,
// Block 0x16, offset 0x580
- 0x05a9: 0x06c9,
- 0x05b1: 0x06d0, 0x05b4: 0x06d7,
+ 0x0580: 0x2325, 0x0581: 0x2335, 0x0582: 0x2342, 0x0583: 0x2352, 0x0584: 0x235c, 0x0585: 0x236c,
+ 0x0586: 0x2376, 0x0587: 0x2380, 0x0588: 0x2393, 0x0589: 0x23a0, 0x058a: 0x23aa, 0x058b: 0x23b4,
+ 0x058c: 0x23be, 0x058d: 0x23cb, 0x058e: 0x23d8, 0x058f: 0x23e5, 0x0590: 0x23f2, 0x0591: 0x23ff,
+ 0x0592: 0x240c, 0x0593: 0x2419, 0x0594: 0x242c, 0x0595: 0x2433, 0x0596: 0x2446, 0x0597: 0x2459,
+ 0x0598: 0x2469, 0x0599: 0x2476, 0x059a: 0x2489, 0x059b: 0x249c, 0x059c: 0x24a9, 0x059d: 0x24b3,
+ 0x059e: 0x24bd, 0x059f: 0x24ca, 0x05a0: 0x24d7, 0x05a1: 0x24e7, 0x05a2: 0x24f7, 0x05a3: 0x2501,
+ 0x05a4: 0x250b, 0x05a5: 0x2518, 0x05a6: 0x2522, 0x05a7: 0x252c, 0x05a8: 0x2533, 0x05a9: 0x253a,
+ 0x05aa: 0x2544, 0x05ab: 0x254e, 0x05ac: 0x2561, 0x05ad: 0x256e, 0x05ae: 0x257e, 0x05af: 0x2591,
+ 0x05b0: 0x259e, 0x05b1: 0x25a8, 0x05b2: 0x25b2, 0x05b3: 0x25c5, 0x05b4: 0x25d2, 0x05b5: 0x25e5,
+ 0x05b6: 0x25ef, 0x05b7: 0x25ff, 0x05b8: 0x2609, 0x05b9: 0x2616, 0x05ba: 0x2620, 0x05bb: 0x262d,
+ 0x05bc: 0x263d, 0x05bd: 0x264a, 0x05be: 0x265a, 0x05bf: 0x2667,
// Block 0x17, offset 0x5c0
- 0x05d8: 0x06de, 0x05d9: 0x06e5, 0x05da: 0x06ec, 0x05db: 0x06f3, 0x05dc: 0x06fa, 0x05dd: 0x0701,
- 0x05de: 0x0708, 0x05df: 0x070f,
+ 0x05c0: 0x266e, 0x05c1: 0x267e, 0x05c2: 0x2688, 0x05c3: 0x2692, 0x05c4: 0x269f, 0x05c5: 0x26a9,
+ 0x05c6: 0x26b3, 0x05c7: 0x26bd, 0x05c8: 0x26cd, 0x05c9: 0x26da, 0x05ca: 0x26e1, 0x05cb: 0x26f4,
+ 0x05cc: 0x26fe, 0x05cd: 0x270e, 0x05ce: 0x271b, 0x05cf: 0x2728, 0x05d0: 0x2732, 0x05d1: 0x273c,
+ 0x05d2: 0x2749, 0x05d3: 0x2750, 0x05d4: 0x275d, 0x05d5: 0x276d, 0x05d6: 0x2774, 0x05d7: 0x2787,
+ 0x05d8: 0x2791, 0x05d9: 0x2796, 0x05da: 0x279b, 0x05db: 0x27a0, 0x05dc: 0x27a5, 0x05dd: 0x27aa,
+ 0x05de: 0x27af, 0x05df: 0x27b4, 0x05e0: 0x27b9, 0x05e1: 0x27be, 0x05e2: 0x27c3, 0x05e3: 0x27c9,
+ 0x05e4: 0x27cf, 0x05e5: 0x27d5, 0x05e6: 0x27db, 0x05e7: 0x27e1, 0x05e8: 0x27e7, 0x05e9: 0x27ed,
+ 0x05ea: 0x27f3, 0x05eb: 0x27f9, 0x05ec: 0x27ff, 0x05ed: 0x2805, 0x05ee: 0x280b, 0x05ef: 0x2811,
+ 0x05f0: 0x2817, 0x05f1: 0x281d, 0x05f2: 0x2821, 0x05f3: 0x2824, 0x05f4: 0x2827, 0x05f5: 0x282b,
+ 0x05f6: 0x282e, 0x05f7: 0x2831, 0x05f8: 0x2834, 0x05f9: 0x2838, 0x05fa: 0x283c, 0x05fb: 0x283f,
+ 0x05fc: 0x2846, 0x05fd: 0x284d, 0x05fe: 0x2854, 0x05ff: 0x285b,
// Block 0x18, offset 0x600
- 0x060b: 0x0716,
- 0x060c: 0x071d,
- 0x061c: 0x0724, 0x061d: 0x072b,
- 0x061f: 0x0732,
+ 0x0600: 0x2868, 0x0601: 0x286b, 0x0602: 0x286e, 0x0603: 0x2872, 0x0604: 0x2875, 0x0605: 0x2878,
+ 0x0606: 0x287b, 0x0607: 0x287e, 0x0608: 0x2881, 0x0609: 0x2885, 0x060a: 0x288a, 0x060b: 0x288d,
+ 0x060c: 0x2890, 0x060d: 0x2894, 0x060e: 0x2898, 0x060f: 0x289b, 0x0610: 0x289e, 0x0611: 0x28a1,
+ 0x0612: 0x28a5, 0x0613: 0x28a9, 0x0614: 0x28ad, 0x0615: 0x28b1, 0x0616: 0x28b5, 0x0617: 0x28b8,
+ 0x0618: 0x28bb, 0x0619: 0x28be, 0x061a: 0x28c1, 0x061b: 0x28c4, 0x061c: 0x28c8, 0x061d: 0x28cb,
+ 0x061e: 0x28ce, 0x061f: 0x28d1, 0x0620: 0x28d5, 0x0621: 0x28d9, 0x0622: 0x28dc, 0x0623: 0x28e0,
+ 0x0624: 0x28e4, 0x0625: 0x28e8, 0x0626: 0x28eb, 0x0627: 0x28ef, 0x0628: 0x28f5, 0x0629: 0x28fc,
+ 0x062a: 0x28ff, 0x062b: 0x2903, 0x062c: 0x2907, 0x062d: 0x290b, 0x062e: 0x290f, 0x062f: 0x2917,
+ 0x0630: 0x2920, 0x0631: 0x2923, 0x0632: 0x2926, 0x0633: 0x292a, 0x0634: 0x292d, 0x0635: 0x2930,
+ 0x0636: 0x2933, 0x0637: 0x2937, 0x0638: 0x293a, 0x0639: 0x293d, 0x063a: 0x2940, 0x063b: 0x2943,
+ 0x063c: 0x2946, 0x063d: 0x294a, 0x063e: 0x294d, 0x063f: 0x2950,
// Block 0x19, offset 0x640
- 0x0673: 0x0739,
- 0x0676: 0x0740,
+ 0x0640: 0x2953, 0x0641: 0x2957, 0x0642: 0x295b, 0x0643: 0x2960, 0x0644: 0x2963, 0x0645: 0x2966,
+ 0x0646: 0x2969, 0x0647: 0x2970, 0x0648: 0x2974, 0x0649: 0x2977, 0x064a: 0x297a, 0x064b: 0x297d,
+ 0x064c: 0x2980, 0x064d: 0x2983, 0x064e: 0x2986, 0x064f: 0x2989, 0x0650: 0x298c, 0x0651: 0x298f,
+ 0x0652: 0x2992, 0x0653: 0x2996, 0x0654: 0x2999, 0x0655: 0x299c, 0x0656: 0x29a0, 0x0657: 0x29a4,
+ 0x0658: 0x29a7, 0x0659: 0x29ac, 0x065a: 0x29b0, 0x065b: 0x29b3, 0x065c: 0x29b6, 0x065d: 0x29b9,
+ 0x065e: 0x29bc, 0x065f: 0x29c2, 0x0660: 0x29c8, 0x0661: 0x29cd, 0x0662: 0x29d2, 0x0663: 0x29d7,
+ 0x0664: 0x29dc, 0x0665: 0x29e1, 0x0666: 0x29e6, 0x0667: 0x29eb, 0x0668: 0x29f0, 0x0669: 0x29f5,
+ 0x066a: 0x29fb, 0x066b: 0x2a01, 0x066c: 0x2a07, 0x066d: 0x2a0d, 0x066e: 0x2a13, 0x066f: 0x2a19,
+ 0x0670: 0x2a1f, 0x0671: 0x2a25, 0x0672: 0x2a2b, 0x0673: 0x2a31, 0x0674: 0x2a37, 0x0675: 0x2a3d,
+ 0x0676: 0x2a43, 0x0677: 0x2a49, 0x0678: 0x2a4f, 0x0679: 0x2a55, 0x067a: 0x2a5b, 0x067b: 0x2a61,
+ 0x067c: 0x2a67, 0x067d: 0x2a6d, 0x067e: 0x2a73, 0x067f: 0x2a79,
// Block 0x1a, offset 0x680
- 0x0699: 0x0747, 0x069a: 0x074e, 0x069b: 0x0755,
- 0x069e: 0x075c,
+ 0x0680: 0x2fce, 0x0681: 0x2fd2, 0x0682: 0x2fd6, 0x0683: 0x2fda, 0x0684: 0x2fde, 0x0685: 0x2fe2,
+ 0x0686: 0x2fe6, 0x0687: 0x2fea, 0x0688: 0x2fee, 0x0689: 0x2eed, 0x068a: 0x2ff2, 0x068b: 0x2ef1,
+ 0x068c: 0x2ff6, 0x068d: 0x2ffa, 0x068e: 0x2ffe, 0x068f: 0x3002, 0x0690: 0x3006, 0x0691: 0x2e6d,
+ 0x0692: 0x2b15, 0x0693: 0x300a, 0x0694: 0x300e, 0x0695: 0x195a, 0x0696: 0x2c25, 0x0697: 0x2d71,
+ 0x0698: 0x3012, 0x0699: 0x3016, 0x069a: 0x2f0d, 0x069b: 0x301a, 0x069c: 0x2f11, 0x069d: 0x301e,
+ 0x069e: 0x3022, 0x069f: 0x3026, 0x06a0: 0x2e75, 0x06a1: 0x302a, 0x06a2: 0x302e, 0x06a3: 0x3032,
+ 0x06a4: 0x3036, 0x06a5: 0x303a, 0x06a6: 0x2e79, 0x06a7: 0x303e, 0x06a8: 0x3042, 0x06a9: 0x3046,
+ 0x06aa: 0x304a, 0x06ab: 0x304e, 0x06ac: 0x3052, 0x06ad: 0x2f41, 0x06ae: 0x3056, 0x06af: 0x305a,
+ 0x06b0: 0x2cb1, 0x06b1: 0x305e, 0x06b2: 0x2f51, 0x06b3: 0x3062, 0x06b4: 0x3066, 0x06b5: 0x306a,
+ 0x06b6: 0x306e, 0x06b7: 0x3072, 0x06b8: 0x2f65, 0x06b9: 0x3076, 0x06ba: 0x2e99, 0x06bb: 0x307a,
+ 0x06bc: 0x2f69, 0x06bd: 0x2bd9, 0x06be: 0x307e, 0x06bf: 0x2f6d,
// Block 0x1b, offset 0x6c0
- 0x06c8: 0x0763, 0x06cb: 0x076a,
- 0x06cc: 0x0771,
- 0x06dc: 0x0778, 0x06dd: 0x077f,
+ 0x06c0: 0x3082, 0x06c1: 0x2f75, 0x06c2: 0x3086, 0x06c3: 0x308a, 0x06c4: 0x308e, 0x06c5: 0x3092,
+ 0x06c6: 0x3096, 0x06c7: 0x2f7d, 0x06c8: 0x2e8d, 0x06c9: 0x309a, 0x06ca: 0x2f81, 0x06cb: 0x309e,
+ 0x06cc: 0x2f85, 0x06cd: 0x30a2, 0x06ce: 0x1b76, 0x06cf: 0x30a6, 0x06d0: 0x30ab, 0x06d1: 0x30b0,
+ 0x06d2: 0x30b5, 0x06d3: 0x30b9, 0x06d4: 0x30bd, 0x06d5: 0x30c1, 0x06d6: 0x30c6, 0x06d7: 0x30cb,
+ 0x06d8: 0x30d0, 0x06d9: 0x30d4,
// Block 0x1c, offset 0x700
- 0x0714: 0x0786,
+ 0x0700: 0x30d8, 0x0701: 0x30db, 0x0702: 0x30de, 0x0703: 0x30e1, 0x0704: 0x30e5, 0x0705: 0x30e9,
+ 0x0706: 0x30e9,
+ 0x0713: 0x30ec, 0x0714: 0x30f1, 0x0715: 0x30f6, 0x0716: 0x30fb, 0x0717: 0x3100,
+ 0x071d: 0x3105,
+ 0x071f: 0x310a, 0x0720: 0x310f, 0x0721: 0x14db, 0x0722: 0x14e4, 0x0723: 0x3112,
+ 0x0724: 0x3115, 0x0725: 0x3118, 0x0726: 0x311b, 0x0727: 0x311e, 0x0728: 0x3121, 0x0729: 0x1494,
+ 0x072a: 0x3124, 0x072b: 0x3129, 0x072c: 0x312e, 0x072d: 0x3135, 0x072e: 0x313c, 0x072f: 0x3141,
+ 0x0730: 0x3146, 0x0731: 0x314b, 0x0732: 0x3150, 0x0733: 0x3155, 0x0734: 0x315a, 0x0735: 0x315f,
+ 0x0736: 0x3164, 0x0738: 0x3169, 0x0739: 0x316e, 0x073a: 0x3173, 0x073b: 0x3178,
+ 0x073c: 0x317d, 0x073e: 0x3182,
// Block 0x1d, offset 0x740
- 0x074a: 0x078d, 0x074b: 0x0794,
- 0x074c: 0x079b,
+ 0x0740: 0x3187, 0x0741: 0x318c, 0x0743: 0x3191, 0x0744: 0x3196,
+ 0x0746: 0x319b, 0x0747: 0x31a0, 0x0748: 0x31a5, 0x0749: 0x31aa, 0x074a: 0x31af, 0x074b: 0x31b4,
+ 0x074c: 0x31b9, 0x074d: 0x31be, 0x074e: 0x31c3, 0x074f: 0x31c8, 0x0750: 0x31cd, 0x0751: 0x31cd,
+ 0x0752: 0x31d0, 0x0753: 0x31d0, 0x0754: 0x31d0, 0x0755: 0x31d0, 0x0756: 0x31d3, 0x0757: 0x31d3,
+ 0x0758: 0x31d3, 0x0759: 0x31d3, 0x075a: 0x31d6, 0x075b: 0x31d6, 0x075c: 0x31d6, 0x075d: 0x31d6,
+ 0x075e: 0x31d9, 0x075f: 0x31d9, 0x0760: 0x31d9, 0x0761: 0x31d9, 0x0762: 0x31dc, 0x0763: 0x31dc,
+ 0x0764: 0x31dc, 0x0765: 0x31dc, 0x0766: 0x31df, 0x0767: 0x31df, 0x0768: 0x31df, 0x0769: 0x31df,
+ 0x076a: 0x31e2, 0x076b: 0x31e2, 0x076c: 0x31e2, 0x076d: 0x31e2, 0x076e: 0x31e5, 0x076f: 0x31e5,
+ 0x0770: 0x31e5, 0x0771: 0x31e5, 0x0772: 0x31e8, 0x0773: 0x31e8, 0x0774: 0x31e8, 0x0775: 0x31e8,
+ 0x0776: 0x31eb, 0x0777: 0x31eb, 0x0778: 0x31eb, 0x0779: 0x31eb, 0x077a: 0x31ee, 0x077b: 0x31ee,
+ 0x077c: 0x31ee, 0x077d: 0x31ee, 0x077e: 0x31f1, 0x077f: 0x31f1,
// Block 0x1e, offset 0x780
- 0x0788: 0x07a2,
+ 0x0780: 0x31f1, 0x0781: 0x31f1, 0x0782: 0x31f4, 0x0783: 0x31f4, 0x0784: 0x31f7, 0x0785: 0x31f7,
+ 0x0786: 0x31fa, 0x0787: 0x31fa, 0x0788: 0x31fd, 0x0789: 0x31fd, 0x078a: 0x3200, 0x078b: 0x3200,
+ 0x078c: 0x3203, 0x078d: 0x3203, 0x078e: 0x3206, 0x078f: 0x3206, 0x0790: 0x3206, 0x0791: 0x3206,
+ 0x0792: 0x3209, 0x0793: 0x3209, 0x0794: 0x3209, 0x0795: 0x3209, 0x0796: 0x320c, 0x0797: 0x320c,
+ 0x0798: 0x320c, 0x0799: 0x320c, 0x079a: 0x320f, 0x079b: 0x320f, 0x079c: 0x320f, 0x079d: 0x320f,
+ 0x079e: 0x3212, 0x079f: 0x3212, 0x07a0: 0x3215, 0x07a1: 0x3215, 0x07a2: 0x3215, 0x07a3: 0x3215,
+ 0x07a4: 0x06ba, 0x07a5: 0x06ba, 0x07a6: 0x3218, 0x07a7: 0x3218, 0x07a8: 0x3218, 0x07a9: 0x3218,
+ 0x07aa: 0x321b, 0x07ab: 0x321b, 0x07ac: 0x321b, 0x07ad: 0x321b, 0x07ae: 0x321e, 0x07af: 0x321e,
+ 0x07b0: 0x06c4, 0x07b1: 0x06c4,
// Block 0x1f, offset 0x7c0
- 0x07c0: 0x07a9,
- 0x07c7: 0x07b0, 0x07c8: 0x07b7, 0x07ca: 0x07be, 0x07cb: 0x07c5,
+ 0x07d3: 0x3221, 0x07d4: 0x3221, 0x07d5: 0x3221, 0x07d6: 0x3221, 0x07d7: 0x3224,
+ 0x07d8: 0x3224, 0x07d9: 0x3227, 0x07da: 0x3227, 0x07db: 0x322a, 0x07dc: 0x322a, 0x07dd: 0x06b0,
+ 0x07de: 0x322d, 0x07df: 0x322d, 0x07e0: 0x3230, 0x07e1: 0x3230, 0x07e2: 0x3233, 0x07e3: 0x3233,
+ 0x07e4: 0x3236, 0x07e5: 0x3236, 0x07e6: 0x3236, 0x07e7: 0x3236, 0x07e8: 0x3239, 0x07e9: 0x3239,
+ 0x07ea: 0x323c, 0x07eb: 0x323c, 0x07ec: 0x3243, 0x07ed: 0x3243, 0x07ee: 0x324a, 0x07ef: 0x324a,
+ 0x07f0: 0x3251, 0x07f1: 0x3251, 0x07f2: 0x3258, 0x07f3: 0x3258, 0x07f4: 0x325f, 0x07f5: 0x325f,
+ 0x07f6: 0x3266, 0x07f7: 0x3266, 0x07f8: 0x3266, 0x07f9: 0x326d, 0x07fa: 0x326d, 0x07fb: 0x326d,
+ 0x07fc: 0x3274, 0x07fd: 0x3274, 0x07fe: 0x3274, 0x07ff: 0x3274,
// Block 0x20, offset 0x800
- 0x080a: 0x07cf, 0x080b: 0x07d6,
- 0x080c: 0x07dd,
+ 0x0800: 0x33ba, 0x0801: 0x33bf, 0x0802: 0x33c4, 0x0803: 0x33c9, 0x0804: 0x33ce, 0x0805: 0x33d3,
+ 0x0806: 0x33d8, 0x0807: 0x33dd, 0x0808: 0x33e2, 0x0809: 0x33e7, 0x080a: 0x33ec, 0x080b: 0x33f1,
+ 0x080c: 0x33f6, 0x080d: 0x33fb, 0x080e: 0x3400, 0x080f: 0x3405, 0x0810: 0x340a, 0x0811: 0x340f,
+ 0x0812: 0x3414, 0x0813: 0x3419, 0x0814: 0x341e, 0x0815: 0x3423, 0x0816: 0x3428, 0x0817: 0x342d,
+ 0x0818: 0x3432, 0x0819: 0x3437, 0x081a: 0x343c, 0x081b: 0x3441, 0x081c: 0x3446, 0x081d: 0x344b,
+ 0x081e: 0x3450, 0x081f: 0x3456, 0x0820: 0x345c, 0x0821: 0x3462, 0x0822: 0x3468, 0x0823: 0x346e,
+ 0x0824: 0x3474, 0x0825: 0x347b, 0x0826: 0x3285, 0x0827: 0x3482, 0x0828: 0x326d, 0x0829: 0x328c,
+ 0x082a: 0x3489, 0x082b: 0x348e, 0x082c: 0x32a2, 0x082d: 0x3493, 0x082e: 0x32a7, 0x082f: 0x32ac,
+ 0x0830: 0x3498, 0x0831: 0x349d, 0x0832: 0x32c0, 0x0833: 0x34a2, 0x0834: 0x32c5, 0x0835: 0x32ca,
+ 0x0836: 0x34a7, 0x0837: 0x34ac, 0x0838: 0x32d4, 0x0839: 0x34b1, 0x083a: 0x32d9, 0x083b: 0x32de,
+ 0x083c: 0x336f, 0x083d: 0x3374, 0x083e: 0x3383, 0x083f: 0x3388,
// Block 0x21, offset 0x840
- 0x085a: 0x07e4, 0x085c: 0x07eb, 0x085d: 0x07f2,
- 0x085e: 0x07fc,
+ 0x0840: 0x338d, 0x0841: 0x33a1, 0x0842: 0x33a6, 0x0843: 0x33ab, 0x0844: 0x33b0, 0x0845: 0x33c4,
+ 0x0846: 0x33c9, 0x0847: 0x33ce, 0x0848: 0x34b6, 0x0849: 0x33e2, 0x084a: 0x34bb, 0x084b: 0x34c0,
+ 0x084c: 0x3400, 0x084d: 0x34c5, 0x084e: 0x3405, 0x084f: 0x340a, 0x0850: 0x344b, 0x0851: 0x34ca,
+ 0x0852: 0x34cf, 0x0853: 0x3432, 0x0854: 0x34d4, 0x0855: 0x3437, 0x0856: 0x343c, 0x0857: 0x3277,
+ 0x0858: 0x327e, 0x0859: 0x34d9, 0x085a: 0x3285, 0x085b: 0x34e0, 0x085c: 0x3293, 0x085d: 0x3298,
+ 0x085e: 0x329d, 0x085f: 0x32a2, 0x0860: 0x34e7, 0x0861: 0x32b1, 0x0862: 0x32b6, 0x0863: 0x32bb,
+ 0x0864: 0x32c0, 0x0865: 0x34ec, 0x0866: 0x32d4, 0x0867: 0x32e3, 0x0868: 0x32e8, 0x0869: 0x32ed,
+ 0x086a: 0x32f2, 0x086b: 0x32f7, 0x086c: 0x3301, 0x086d: 0x3306, 0x086e: 0x330b, 0x086f: 0x3310,
+ 0x0870: 0x3315, 0x0871: 0x331a, 0x0872: 0x34f1, 0x0873: 0x331f, 0x0874: 0x3324, 0x0875: 0x3329,
+ 0x0876: 0x332e, 0x0877: 0x3333, 0x0878: 0x3338, 0x0879: 0x3342, 0x087a: 0x3347, 0x087b: 0x334c,
+ 0x087c: 0x3351, 0x087d: 0x3356, 0x087e: 0x335b, 0x087f: 0x3360,
// Block 0x22, offset 0x880
- 0x08b3: 0x0803,
+ 0x0880: 0x3365, 0x0881: 0x336a, 0x0882: 0x3379, 0x0883: 0x337e, 0x0884: 0x3392, 0x0885: 0x3397,
+ 0x0886: 0x339c, 0x0887: 0x33a1, 0x0888: 0x33a6, 0x0889: 0x33b5, 0x088a: 0x33ba, 0x088b: 0x33bf,
+ 0x088c: 0x33c4, 0x088d: 0x34f6, 0x088e: 0x33d3, 0x088f: 0x33d8, 0x0890: 0x33dd, 0x0891: 0x33e2,
+ 0x0892: 0x33f1, 0x0893: 0x33f6, 0x0894: 0x33fb, 0x0895: 0x3400, 0x0896: 0x34fb, 0x0897: 0x340f,
+ 0x0898: 0x3414, 0x0899: 0x3500, 0x089a: 0x3423, 0x089b: 0x3428, 0x089c: 0x342d, 0x089d: 0x3432,
+ 0x089e: 0x3505, 0x089f: 0x3285, 0x08a0: 0x34e0, 0x08a1: 0x32a2, 0x08a2: 0x34e7, 0x08a3: 0x32c0,
+ 0x08a4: 0x34ec, 0x08a5: 0x32d4, 0x08a6: 0x350a, 0x08a7: 0x3315, 0x08a8: 0x350f, 0x08a9: 0x3514,
+ 0x08aa: 0x3519, 0x08ab: 0x33a1, 0x08ac: 0x33a6, 0x08ad: 0x33c4, 0x08ae: 0x3400, 0x08af: 0x34fb,
+ 0x08b0: 0x3432, 0x08b1: 0x3505, 0x08b2: 0x351e, 0x08b3: 0x3525, 0x08b4: 0x352c, 0x08b5: 0x3533,
+ 0x08b6: 0x3538, 0x08b7: 0x353d, 0x08b8: 0x3542, 0x08b9: 0x3547, 0x08ba: 0x354c, 0x08bb: 0x3551,
+ 0x08bc: 0x3556, 0x08bd: 0x355b, 0x08be: 0x3560, 0x08bf: 0x3565,
// Block 0x23, offset 0x8c0
- 0x08f3: 0x080a,
+ 0x08c0: 0x16c7, 0x08c1: 0x391e, 0x08c2: 0x3922, 0x08c3: 0x3926, 0x08c4: 0x392a,
+ 0x08c7: 0x392e, 0x08c8: 0x3930, 0x08c9: 0x146c, 0x08ca: 0x146c, 0x08cb: 0x146c,
+ 0x08cc: 0x146c, 0x08cd: 0x3900, 0x08ce: 0x3900, 0x08cf: 0x3900, 0x08d0: 0x38e0, 0x08d1: 0x38e2,
+ 0x08d2: 0x143e, 0x08d4: 0x04e1, 0x08d5: 0x38ea, 0x08d6: 0x38ee, 0x08d7: 0x38ec,
+ 0x08d8: 0x38f8, 0x08d9: 0x149c, 0x08da: 0x149e, 0x08db: 0x3902, 0x08dc: 0x3904, 0x08dd: 0x3906,
+ 0x08de: 0x390a, 0x08df: 0x3932, 0x08e0: 0x3934, 0x08e1: 0x3936, 0x08e2: 0x1494, 0x08e3: 0x3938,
+ 0x08e4: 0x393a, 0x08e5: 0x393c, 0x08e6: 0x149a, 0x08e8: 0x393e, 0x08e9: 0x3940,
+ 0x08ea: 0x3942, 0x08eb: 0x3944,
+ 0x08f0: 0x3946, 0x08f1: 0x394a, 0x08f2: 0x394f, 0x08f4: 0x3953,
+ 0x08f6: 0x3957, 0x08f7: 0x395b, 0x08f8: 0x3960, 0x08f9: 0x3964, 0x08fa: 0x3969, 0x08fb: 0x396d,
+ 0x08fc: 0x3972, 0x08fd: 0x3976, 0x08fe: 0x397b, 0x08ff: 0x397f,
// Block 0x24, offset 0x900
- 0x091c: 0x0811, 0x091d: 0x0818,
+ 0x0900: 0x3984, 0x0901: 0x068d, 0x0902: 0x068d, 0x0903: 0x0692, 0x0904: 0x0692, 0x0905: 0x0697,
+ 0x0906: 0x0697, 0x0907: 0x069c, 0x0908: 0x069c, 0x0909: 0x06a1, 0x090a: 0x06a1, 0x090b: 0x06a1,
+ 0x090c: 0x06a1, 0x090d: 0x3987, 0x090e: 0x3987, 0x090f: 0x398a, 0x0910: 0x398a, 0x0911: 0x398a,
+ 0x0912: 0x398a, 0x0913: 0x398d, 0x0914: 0x398d, 0x0915: 0x3990, 0x0916: 0x3990, 0x0917: 0x3990,
+ 0x0918: 0x3990, 0x0919: 0x3993, 0x091a: 0x3993, 0x091b: 0x3993, 0x091c: 0x3993, 0x091d: 0x3996,
+ 0x091e: 0x3996, 0x091f: 0x3996, 0x0920: 0x3996, 0x0921: 0x3999, 0x0922: 0x3999, 0x0923: 0x3999,
+ 0x0924: 0x3999, 0x0925: 0x399c, 0x0926: 0x399c, 0x0927: 0x399c, 0x0928: 0x399c, 0x0929: 0x399f,
+ 0x092a: 0x399f, 0x092b: 0x39a2, 0x092c: 0x39a2, 0x092d: 0x39a5, 0x092e: 0x39a5, 0x092f: 0x39a8,
+ 0x0930: 0x39a8, 0x0931: 0x39ab, 0x0932: 0x39ab, 0x0933: 0x39ab, 0x0934: 0x39ab, 0x0935: 0x39ae,
+ 0x0936: 0x39ae, 0x0937: 0x39ae, 0x0938: 0x39ae, 0x0939: 0x39b1, 0x093a: 0x39b1, 0x093b: 0x39b1,
+ 0x093c: 0x39b1, 0x093d: 0x39b4, 0x093e: 0x39b4, 0x093f: 0x39b4,
// Block 0x25, offset 0x940
- 0x094c: 0x081f,
+ 0x0940: 0x39b4, 0x0941: 0x39b7, 0x0942: 0x39b7, 0x0943: 0x39b7, 0x0944: 0x39b7, 0x0945: 0x39ba,
+ 0x0946: 0x39ba, 0x0947: 0x39ba, 0x0948: 0x39ba, 0x0949: 0x39bd, 0x094a: 0x39bd, 0x094b: 0x39bd,
+ 0x094c: 0x39bd, 0x094d: 0x39c0, 0x094e: 0x39c0, 0x094f: 0x39c0, 0x0950: 0x39c0, 0x0951: 0x39c3,
+ 0x0952: 0x39c3, 0x0953: 0x39c3, 0x0954: 0x39c3, 0x0955: 0x39c6, 0x0956: 0x39c6, 0x0957: 0x39c6,
+ 0x0958: 0x39c6, 0x0959: 0x39c9, 0x095a: 0x39c9, 0x095b: 0x39c9, 0x095c: 0x39c9, 0x095d: 0x39cc,
+ 0x095e: 0x39cc, 0x095f: 0x39cc, 0x0960: 0x39cc, 0x0961: 0x39cf, 0x0962: 0x39cf, 0x0963: 0x39cf,
+ 0x0964: 0x39cf, 0x0965: 0x39d2, 0x0966: 0x39d2, 0x0967: 0x39d2, 0x0968: 0x39d2, 0x0969: 0x39d5,
+ 0x096a: 0x39d5, 0x096b: 0x39d5, 0x096c: 0x39d5, 0x096d: 0x39d8, 0x096e: 0x39d8, 0x096f: 0x3239,
+ 0x0970: 0x3239, 0x0971: 0x39db, 0x0972: 0x39db, 0x0973: 0x39db, 0x0974: 0x39db, 0x0975: 0x39de,
+ 0x0976: 0x39de, 0x0977: 0x39e5, 0x0978: 0x39e5, 0x0979: 0x39ec, 0x097a: 0x39ec, 0x097b: 0x39f3,
+ 0x097c: 0x39f3,
// Block 0x26, offset 0x980
- 0x0983: 0x0823,
- 0x098d: 0x082a,
- 0x0992: 0x0831, 0x0997: 0x0838,
- 0x099c: 0x083f,
- 0x09a9: 0x0846,
- 0x09b3: 0x084d, 0x09b5: 0x0854,
- 0x09b6: 0x085b, 0x09b7: 0x0862, 0x09b8: 0x086c, 0x09b9: 0x0873,
+ 0x0981: 0x38ec, 0x0982: 0x39f8, 0x0983: 0x3932, 0x0984: 0x3940, 0x0985: 0x3942,
+ 0x0986: 0x3934, 0x0987: 0x39fa, 0x0988: 0x149c, 0x0989: 0x149e, 0x098a: 0x3936, 0x098b: 0x1494,
+ 0x098c: 0x38e0, 0x098d: 0x3938, 0x098e: 0x143e, 0x098f: 0x39fc, 0x0990: 0x1486, 0x0991: 0x001c,
+ 0x0992: 0x000d, 0x0993: 0x000f, 0x0994: 0x1488, 0x0995: 0x148a, 0x0996: 0x148c, 0x0997: 0x148e,
+ 0x0998: 0x1490, 0x0999: 0x1492, 0x099a: 0x38ea, 0x099b: 0x04e1, 0x099c: 0x393a, 0x099d: 0x149a,
+ 0x099e: 0x393c, 0x099f: 0x38ee, 0x09a0: 0x3944, 0x09a1: 0x0906, 0x09a2: 0x090b, 0x09a3: 0x14ad,
+ 0x09a4: 0x090d, 0x09a5: 0x090f, 0x09a6: 0x14d9, 0x09a7: 0x0914, 0x09a8: 0x0916, 0x09a9: 0x0918,
+ 0x09aa: 0x091a, 0x09ab: 0x091c, 0x09ac: 0x091e, 0x09ad: 0x0920, 0x09ae: 0x0922, 0x09af: 0x0924,
+ 0x09b0: 0x0929, 0x09b1: 0x14c8, 0x09b2: 0x092b, 0x09b3: 0x17f6, 0x09b4: 0x092d, 0x09b5: 0x092f,
+ 0x09b6: 0x155f, 0x09b7: 0x0931, 0x09b8: 0x1570, 0x09b9: 0x17f8, 0x09ba: 0x14d4, 0x09bb: 0x392e,
+ 0x09bc: 0x393e, 0x09bd: 0x3930, 0x09be: 0x39fe, 0x09bf: 0x3900,
// Block 0x27, offset 0x9c0
- 0x09c1: 0x087d,
- 0x09d3: 0x0884,
- 0x09dd: 0x088b,
- 0x09e2: 0x0892,
- 0x09e7: 0x0899,
- 0x09ec: 0x08a0,
- 0x09f9: 0x08a7,
+ 0x09c0: 0x13f7, 0x09c1: 0x0007, 0x09c2: 0x093d, 0x09c3: 0x0984, 0x09c4: 0x093f, 0x09c5: 0x0941,
+ 0x09c6: 0x098c, 0x09c7: 0x094c, 0x09c8: 0x0494, 0x09c9: 0x097c, 0x09ca: 0x0499, 0x09cb: 0x094e,
+ 0x09cc: 0x04c5, 0x09cd: 0x0950, 0x09ce: 0x14a0, 0x09cf: 0x001e, 0x09d0: 0x0960, 0x09d1: 0x17fa,
+ 0x09d2: 0x049b, 0x09d3: 0x02c8, 0x09d4: 0x0962, 0x09d5: 0x0964, 0x09d6: 0x096d, 0x09d7: 0x04a6,
+ 0x09d8: 0x04c7, 0x09d9: 0x04a8, 0x09da: 0x09df, 0x09db: 0x3902, 0x09dc: 0x3a00, 0x09dd: 0x3904,
+ 0x09de: 0x3a02, 0x09df: 0x3a04, 0x09e0: 0x3a08, 0x09e1: 0x38e6, 0x09e2: 0x391e, 0x09e3: 0x3922,
+ 0x09e4: 0x38e2, 0x09e5: 0x3a0c, 0x09e6: 0x2321, 0x09e7: 0x3a10, 0x09e8: 0x3a14, 0x09e9: 0x3a18,
+ 0x09ea: 0x3a1c, 0x09eb: 0x3a20, 0x09ec: 0x3a24, 0x09ed: 0x3a28, 0x09ee: 0x3a2c, 0x09ef: 0x3a30,
+ 0x09f0: 0x3a34, 0x09f1: 0x2269, 0x09f2: 0x226d, 0x09f3: 0x2271, 0x09f4: 0x2275, 0x09f5: 0x2279,
+ 0x09f6: 0x227d, 0x09f7: 0x2281, 0x09f8: 0x2285, 0x09f9: 0x2289, 0x09fa: 0x228d, 0x09fb: 0x2291,
+ 0x09fc: 0x2295, 0x09fd: 0x2299, 0x09fe: 0x229d, 0x09ff: 0x22a1,
// Block 0x28, offset 0xa00
- 0x0a26: 0x08ae,
+ 0x0a00: 0x0906, 0x0a01: 0x090b, 0x0a02: 0x14ad, 0x0a03: 0x090d, 0x0a04: 0x090f, 0x0a05: 0x14d9,
+ 0x0a06: 0x0914, 0x0a07: 0x0916, 0x0a08: 0x0918, 0x0a09: 0x091a, 0x0a0a: 0x091c, 0x0a0b: 0x091e,
+ 0x0a0c: 0x0920, 0x0a0d: 0x0922, 0x0a0e: 0x0924, 0x0a0f: 0x0929, 0x0a10: 0x14c8, 0x0a11: 0x092b,
+ 0x0a12: 0x17f6, 0x0a13: 0x092d, 0x0a14: 0x092f, 0x0a15: 0x155f, 0x0a16: 0x0931, 0x0a17: 0x1570,
+ 0x0a18: 0x17f8, 0x0a19: 0x14d4, 0x0a1a: 0x0007, 0x0a1b: 0x093d, 0x0a1c: 0x0984, 0x0a1d: 0x093f,
+ 0x0a1e: 0x0941, 0x0a1f: 0x098c, 0x0a20: 0x094c, 0x0a21: 0x0494, 0x0a22: 0x097c, 0x0a23: 0x0499,
+ 0x0a24: 0x094e, 0x0a25: 0x04c5, 0x0a26: 0x0950, 0x0a27: 0x14a0, 0x0a28: 0x001e, 0x0a29: 0x0960,
+ 0x0a2a: 0x17fa, 0x0a2b: 0x049b, 0x0a2c: 0x02c8, 0x0a2d: 0x0962, 0x0a2e: 0x0964, 0x0a2f: 0x096d,
+ 0x0a30: 0x04a6, 0x0a31: 0x04c7, 0x0a32: 0x04a8, 0x0a33: 0x09df, 0x0a34: 0x0906, 0x0a35: 0x090b,
+ 0x0a36: 0x14ad, 0x0a37: 0x090d, 0x0a38: 0x090f, 0x0a39: 0x14d9, 0x0a3a: 0x0914, 0x0a3b: 0x0916,
+ 0x0a3c: 0x0918, 0x0a3d: 0x091a, 0x0a3e: 0x091c, 0x0a3f: 0x091e,
// Block 0x29, offset 0xa40
- 0x0a7c: 0x08b5,
+ 0x0a40: 0x0920, 0x0a41: 0x0922, 0x0a42: 0x0924, 0x0a43: 0x0929, 0x0a44: 0x14c8, 0x0a45: 0x092b,
+ 0x0a46: 0x17f6, 0x0a47: 0x092d, 0x0a48: 0x092f, 0x0a49: 0x155f, 0x0a4a: 0x0931, 0x0a4b: 0x1570,
+ 0x0a4c: 0x17f8, 0x0a4d: 0x14d4, 0x0a4e: 0x0007, 0x0a4f: 0x093d, 0x0a50: 0x0984, 0x0a51: 0x093f,
+ 0x0a52: 0x0941, 0x0a53: 0x098c, 0x0a54: 0x094c, 0x0a56: 0x097c, 0x0a57: 0x0499,
+ 0x0a58: 0x094e, 0x0a59: 0x04c5, 0x0a5a: 0x0950, 0x0a5b: 0x14a0, 0x0a5c: 0x001e, 0x0a5d: 0x0960,
+ 0x0a5e: 0x17fa, 0x0a5f: 0x049b, 0x0a60: 0x02c8, 0x0a61: 0x0962, 0x0a62: 0x0964, 0x0a63: 0x096d,
+ 0x0a64: 0x04a6, 0x0a65: 0x04c7, 0x0a66: 0x04a8, 0x0a67: 0x09df, 0x0a68: 0x0906, 0x0a69: 0x090b,
+ 0x0a6a: 0x14ad, 0x0a6b: 0x090d, 0x0a6c: 0x090f, 0x0a6d: 0x14d9, 0x0a6e: 0x0914, 0x0a6f: 0x0916,
+ 0x0a70: 0x0918, 0x0a71: 0x091a, 0x0a72: 0x091c, 0x0a73: 0x091e, 0x0a74: 0x0920, 0x0a75: 0x0922,
+ 0x0a76: 0x0924, 0x0a77: 0x0929, 0x0a78: 0x14c8, 0x0a79: 0x092b, 0x0a7a: 0x17f6, 0x0a7b: 0x092d,
+ 0x0a7c: 0x092f, 0x0a7d: 0x155f, 0x0a7e: 0x0931, 0x0a7f: 0x1570,
// Block 0x2a, offset 0xa80
- 0x0a86: 0x08b9, 0x0a88: 0x08c0, 0x0a8a: 0x08c7,
- 0x0a8c: 0x08ce, 0x0a8e: 0x08d5,
- 0x0a92: 0x08dc,
- 0x0abb: 0x08e3,
- 0x0abd: 0x08ea,
+ 0x0a80: 0x17f8, 0x0a81: 0x14d4, 0x0a82: 0x0007, 0x0a83: 0x093d, 0x0a84: 0x0984, 0x0a85: 0x093f,
+ 0x0a86: 0x0941, 0x0a87: 0x098c, 0x0a88: 0x094c, 0x0a89: 0x0494, 0x0a8a: 0x097c, 0x0a8b: 0x0499,
+ 0x0a8c: 0x094e, 0x0a8d: 0x04c5, 0x0a8e: 0x0950, 0x0a8f: 0x14a0, 0x0a90: 0x001e, 0x0a91: 0x0960,
+ 0x0a92: 0x17fa, 0x0a93: 0x049b, 0x0a94: 0x02c8, 0x0a95: 0x0962, 0x0a96: 0x0964, 0x0a97: 0x096d,
+ 0x0a98: 0x04a6, 0x0a99: 0x04c7, 0x0a9a: 0x04a8, 0x0a9b: 0x09df, 0x0a9c: 0x0906,
+ 0x0a9e: 0x14ad, 0x0a9f: 0x090d, 0x0aa2: 0x0914,
+ 0x0aa5: 0x091a, 0x0aa6: 0x091c, 0x0aa9: 0x0922,
+ 0x0aaa: 0x0924, 0x0aab: 0x0929, 0x0aac: 0x14c8, 0x0aae: 0x17f6, 0x0aaf: 0x092d,
+ 0x0ab0: 0x092f, 0x0ab1: 0x155f, 0x0ab2: 0x0931, 0x0ab3: 0x1570, 0x0ab4: 0x17f8, 0x0ab5: 0x14d4,
+ 0x0ab6: 0x0007, 0x0ab7: 0x093d, 0x0ab8: 0x0984, 0x0ab9: 0x093f, 0x0abb: 0x098c,
+ 0x0abd: 0x0494, 0x0abe: 0x097c, 0x0abf: 0x0499,
// Block 0x2b, offset 0xac0
- 0x0ac0: 0x08f1, 0x0ac1: 0x08f8, 0x0ac3: 0x08ff,
+ 0x0ac0: 0x094e, 0x0ac1: 0x04c5, 0x0ac2: 0x0950, 0x0ac3: 0x14a0, 0x0ac5: 0x0960,
+ 0x0ac6: 0x17fa, 0x0ac7: 0x049b, 0x0ac8: 0x02c8, 0x0ac9: 0x0962, 0x0aca: 0x0964, 0x0acb: 0x096d,
+ 0x0acc: 0x04a6, 0x0acd: 0x04c7, 0x0ace: 0x04a8, 0x0acf: 0x09df, 0x0ad0: 0x0906, 0x0ad1: 0x090b,
+ 0x0ad2: 0x14ad, 0x0ad3: 0x090d, 0x0ad4: 0x090f, 0x0ad5: 0x14d9, 0x0ad6: 0x0914, 0x0ad7: 0x0916,
+ 0x0ad8: 0x0918, 0x0ad9: 0x091a, 0x0ada: 0x091c, 0x0adb: 0x091e, 0x0adc: 0x0920, 0x0add: 0x0922,
+ 0x0ade: 0x0924, 0x0adf: 0x0929, 0x0ae0: 0x14c8, 0x0ae1: 0x092b, 0x0ae2: 0x17f6, 0x0ae3: 0x092d,
+ 0x0ae4: 0x092f, 0x0ae5: 0x155f, 0x0ae6: 0x0931, 0x0ae7: 0x1570, 0x0ae8: 0x17f8, 0x0ae9: 0x14d4,
+ 0x0aea: 0x0007, 0x0aeb: 0x093d, 0x0aec: 0x0984, 0x0aed: 0x093f, 0x0aee: 0x0941, 0x0aef: 0x098c,
+ 0x0af0: 0x094c, 0x0af1: 0x0494, 0x0af2: 0x097c, 0x0af3: 0x0499, 0x0af4: 0x094e, 0x0af5: 0x04c5,
+ 0x0af6: 0x0950, 0x0af7: 0x14a0, 0x0af8: 0x001e, 0x0af9: 0x0960, 0x0afa: 0x17fa, 0x0afb: 0x049b,
+ 0x0afc: 0x02c8, 0x0afd: 0x0962, 0x0afe: 0x0964, 0x0aff: 0x096d,
// Block 0x2c, offset 0xb00
- 0x0b2c: 0x0906, 0x0b2d: 0x0908, 0x0b2e: 0x090b,
- 0x0b30: 0x090d, 0x0b31: 0x090f, 0x0b32: 0x0911, 0x0b33: 0x0914, 0x0b34: 0x0916, 0x0b35: 0x0918,
- 0x0b36: 0x091a, 0x0b37: 0x091c, 0x0b38: 0x091e, 0x0b39: 0x0920, 0x0b3a: 0x0922,
- 0x0b3c: 0x0924, 0x0b3d: 0x0926, 0x0b3e: 0x0929, 0x0b3f: 0x092b,
+ 0x0b00: 0x04a6, 0x0b01: 0x04c7, 0x0b02: 0x04a8, 0x0b03: 0x09df, 0x0b04: 0x0906, 0x0b05: 0x090b,
+ 0x0b07: 0x090d, 0x0b08: 0x090f, 0x0b09: 0x14d9, 0x0b0a: 0x0914,
+ 0x0b0d: 0x091a, 0x0b0e: 0x091c, 0x0b0f: 0x091e, 0x0b10: 0x0920, 0x0b11: 0x0922,
+ 0x0b12: 0x0924, 0x0b13: 0x0929, 0x0b14: 0x14c8, 0x0b16: 0x17f6, 0x0b17: 0x092d,
+ 0x0b18: 0x092f, 0x0b19: 0x155f, 0x0b1a: 0x0931, 0x0b1b: 0x1570, 0x0b1c: 0x17f8,
+ 0x0b1e: 0x0007, 0x0b1f: 0x093d, 0x0b20: 0x0984, 0x0b21: 0x093f, 0x0b22: 0x0941, 0x0b23: 0x098c,
+ 0x0b24: 0x094c, 0x0b25: 0x0494, 0x0b26: 0x097c, 0x0b27: 0x0499, 0x0b28: 0x094e, 0x0b29: 0x04c5,
+ 0x0b2a: 0x0950, 0x0b2b: 0x14a0, 0x0b2c: 0x001e, 0x0b2d: 0x0960, 0x0b2e: 0x17fa, 0x0b2f: 0x049b,
+ 0x0b30: 0x02c8, 0x0b31: 0x0962, 0x0b32: 0x0964, 0x0b33: 0x096d, 0x0b34: 0x04a6, 0x0b35: 0x04c7,
+ 0x0b36: 0x04a8, 0x0b37: 0x09df, 0x0b38: 0x0906, 0x0b39: 0x090b, 0x0b3b: 0x090d,
+ 0x0b3c: 0x090f, 0x0b3d: 0x14d9, 0x0b3e: 0x0914,
// Block 0x2d, offset 0xb40
- 0x0b40: 0x092d, 0x0b41: 0x092f, 0x0b42: 0x0931, 0x0b43: 0x0007, 0x0b44: 0x0933, 0x0b45: 0x0936,
- 0x0b46: 0x0939, 0x0b47: 0x093d, 0x0b48: 0x093f, 0x0b49: 0x0941, 0x0b4a: 0x0943, 0x0b4b: 0x0946,
- 0x0b4c: 0x0949, 0x0b4d: 0x094c, 0x0b4f: 0x094e, 0x0b50: 0x0950, 0x0b51: 0x0952,
- 0x0b52: 0x001e, 0x0b53: 0x0955, 0x0b54: 0x0958, 0x0b55: 0x095c, 0x0b56: 0x0960, 0x0b57: 0x0962,
- 0x0b58: 0x0964, 0x0b59: 0x0966, 0x0b5a: 0x096a, 0x0b5b: 0x096d, 0x0b5c: 0x096f, 0x0b5d: 0x0559,
- 0x0b5e: 0x0973, 0x0b5f: 0x0976, 0x0b60: 0x056c, 0x0b61: 0x0979, 0x0b62: 0x097c, 0x0b63: 0x049b,
- 0x0b64: 0x0964, 0x0b65: 0x096d, 0x0b66: 0x0559, 0x0b67: 0x0973, 0x0b68: 0x0575, 0x0b69: 0x056c,
- 0x0b6a: 0x0979,
- 0x0b78: 0x097e,
+ 0x0b40: 0x0918, 0x0b41: 0x091a, 0x0b42: 0x091c, 0x0b43: 0x091e, 0x0b44: 0x0920,
+ 0x0b46: 0x0924, 0x0b4a: 0x17f6, 0x0b4b: 0x092d,
+ 0x0b4c: 0x092f, 0x0b4d: 0x155f, 0x0b4e: 0x0931, 0x0b4f: 0x1570, 0x0b50: 0x17f8,
+ 0x0b52: 0x0007, 0x0b53: 0x093d, 0x0b54: 0x0984, 0x0b55: 0x093f, 0x0b56: 0x0941, 0x0b57: 0x098c,
+ 0x0b58: 0x094c, 0x0b59: 0x0494, 0x0b5a: 0x097c, 0x0b5b: 0x0499, 0x0b5c: 0x094e, 0x0b5d: 0x04c5,
+ 0x0b5e: 0x0950, 0x0b5f: 0x14a0, 0x0b60: 0x001e, 0x0b61: 0x0960, 0x0b62: 0x17fa, 0x0b63: 0x049b,
+ 0x0b64: 0x02c8, 0x0b65: 0x0962, 0x0b66: 0x0964, 0x0b67: 0x096d, 0x0b68: 0x04a6, 0x0b69: 0x04c7,
+ 0x0b6a: 0x04a8, 0x0b6b: 0x09df, 0x0b6c: 0x0906, 0x0b6d: 0x090b, 0x0b6e: 0x14ad, 0x0b6f: 0x090d,
+ 0x0b70: 0x090f, 0x0b71: 0x14d9, 0x0b72: 0x0914, 0x0b73: 0x0916, 0x0b74: 0x0918, 0x0b75: 0x091a,
+ 0x0b76: 0x091c, 0x0b77: 0x091e, 0x0b78: 0x0920, 0x0b79: 0x0922, 0x0b7a: 0x0924, 0x0b7b: 0x0929,
+ 0x0b7c: 0x14c8, 0x0b7d: 0x092b, 0x0b7e: 0x17f6, 0x0b7f: 0x092d,
// Block 0x2e, offset 0xb80
- 0x0b9b: 0x0981, 0x0b9c: 0x0984, 0x0b9d: 0x0986,
- 0x0b9e: 0x0989, 0x0b9f: 0x0949, 0x0ba0: 0x098c, 0x0ba1: 0x098e, 0x0ba2: 0x0991, 0x0ba3: 0x0994,
- 0x0ba4: 0x0997, 0x0ba5: 0x099a, 0x0ba6: 0x099d, 0x0ba7: 0x09a0, 0x0ba8: 0x09a4, 0x0ba9: 0x09a7,
- 0x0baa: 0x09aa, 0x0bab: 0x09ae, 0x0bac: 0x09b1, 0x0bad: 0x09b4, 0x0bae: 0x09b7, 0x0baf: 0x09ba,
- 0x0bb0: 0x09bd, 0x0bb1: 0x09c0, 0x0bb2: 0x09c3, 0x0bb3: 0x09c6, 0x0bb4: 0x09c9, 0x0bb5: 0x09cc,
- 0x0bb6: 0x09cf, 0x0bb7: 0x09d2, 0x0bb8: 0x09d5, 0x0bb9: 0x09d9, 0x0bba: 0x09dc, 0x0bbb: 0x09df,
- 0x0bbc: 0x09e1, 0x0bbd: 0x09e4, 0x0bbe: 0x09e7, 0x0bbf: 0x055c,
+ 0x0b80: 0x092f, 0x0b81: 0x155f, 0x0b82: 0x0931, 0x0b83: 0x1570, 0x0b84: 0x17f8, 0x0b85: 0x14d4,
+ 0x0b86: 0x0007, 0x0b87: 0x093d, 0x0b88: 0x0984, 0x0b89: 0x093f, 0x0b8a: 0x0941, 0x0b8b: 0x098c,
+ 0x0b8c: 0x094c, 0x0b8d: 0x0494, 0x0b8e: 0x097c, 0x0b8f: 0x0499, 0x0b90: 0x094e, 0x0b91: 0x04c5,
+ 0x0b92: 0x0950, 0x0b93: 0x14a0, 0x0b94: 0x001e, 0x0b95: 0x0960, 0x0b96: 0x17fa, 0x0b97: 0x049b,
+ 0x0b98: 0x02c8, 0x0b99: 0x0962, 0x0b9a: 0x0964, 0x0b9b: 0x096d, 0x0b9c: 0x04a6, 0x0b9d: 0x04c7,
+ 0x0b9e: 0x04a8, 0x0b9f: 0x09df, 0x0ba0: 0x0906, 0x0ba1: 0x090b, 0x0ba2: 0x14ad, 0x0ba3: 0x090d,
+ 0x0ba4: 0x090f, 0x0ba5: 0x14d9, 0x0ba6: 0x0914, 0x0ba7: 0x0916, 0x0ba8: 0x0918, 0x0ba9: 0x091a,
+ 0x0baa: 0x091c, 0x0bab: 0x091e, 0x0bac: 0x0920, 0x0bad: 0x0922, 0x0bae: 0x0924, 0x0baf: 0x0929,
+ 0x0bb0: 0x14c8, 0x0bb1: 0x092b, 0x0bb2: 0x17f6, 0x0bb3: 0x092d, 0x0bb4: 0x092f, 0x0bb5: 0x155f,
+ 0x0bb6: 0x0931, 0x0bb7: 0x1570, 0x0bb8: 0x17f8, 0x0bb9: 0x14d4, 0x0bba: 0x0007, 0x0bbb: 0x093d,
+ 0x0bbc: 0x0984, 0x0bbd: 0x093f, 0x0bbe: 0x0941, 0x0bbf: 0x098c,
// Block 0x2f, offset 0xbc0
- 0x0bc0: 0x09ea, 0x0bc1: 0x09ee, 0x0bc2: 0x09f2, 0x0bc3: 0x09f6, 0x0bc4: 0x09fa, 0x0bc5: 0x09fe,
- 0x0bc6: 0x0a02, 0x0bc7: 0x0a06, 0x0bc8: 0x0a0a, 0x0bc9: 0x0a10, 0x0bca: 0x0a16, 0x0bcb: 0x0a1a,
- 0x0bcc: 0x0a1e, 0x0bcd: 0x0a22, 0x0bce: 0x0a26, 0x0bcf: 0x0a2a, 0x0bd0: 0x0a2e, 0x0bd1: 0x0a32,
- 0x0bd2: 0x0a36, 0x0bd3: 0x0a3a, 0x0bd4: 0x0a3e, 0x0bd5: 0x0a44, 0x0bd6: 0x0a4a, 0x0bd7: 0x0a50,
- 0x0bd8: 0x0a56, 0x0bd9: 0x0a5a, 0x0bda: 0x0a5e, 0x0bdb: 0x0a62, 0x0bdc: 0x0a66, 0x0bdd: 0x0a6c,
- 0x0bde: 0x0a72, 0x0bdf: 0x0a76, 0x0be0: 0x0a7a, 0x0be1: 0x0a7e, 0x0be2: 0x0a82, 0x0be3: 0x0a86,
- 0x0be4: 0x0a8a, 0x0be5: 0x0a8e, 0x0be6: 0x0a92, 0x0be7: 0x0a96, 0x0be8: 0x0a9a, 0x0be9: 0x0a9e,
- 0x0bea: 0x0aa2, 0x0beb: 0x0aa6, 0x0bec: 0x0aaa, 0x0bed: 0x0aae, 0x0bee: 0x0ab2, 0x0bef: 0x0ab8,
- 0x0bf0: 0x0abe, 0x0bf1: 0x0ac2, 0x0bf2: 0x0ac6, 0x0bf3: 0x0aca, 0x0bf4: 0x0ace, 0x0bf5: 0x0ad2,
- 0x0bf6: 0x0ad6, 0x0bf7: 0x0ada, 0x0bf8: 0x0ade, 0x0bf9: 0x0ae4, 0x0bfa: 0x0aea, 0x0bfb: 0x0aee,
- 0x0bfc: 0x0af2, 0x0bfd: 0x0af6, 0x0bfe: 0x0afa, 0x0bff: 0x0afe,
+ 0x0bc0: 0x094c, 0x0bc1: 0x0494, 0x0bc2: 0x097c, 0x0bc3: 0x0499, 0x0bc4: 0x094e, 0x0bc5: 0x04c5,
+ 0x0bc6: 0x0950, 0x0bc7: 0x14a0, 0x0bc8: 0x001e, 0x0bc9: 0x0960, 0x0bca: 0x17fa, 0x0bcb: 0x049b,
+ 0x0bcc: 0x02c8, 0x0bcd: 0x0962, 0x0bce: 0x0964, 0x0bcf: 0x096d, 0x0bd0: 0x04a6, 0x0bd1: 0x04c7,
+ 0x0bd2: 0x04a8, 0x0bd3: 0x09df, 0x0bd4: 0x0906, 0x0bd5: 0x090b, 0x0bd6: 0x14ad, 0x0bd7: 0x090d,
+ 0x0bd8: 0x090f, 0x0bd9: 0x14d9, 0x0bda: 0x0914, 0x0bdb: 0x0916, 0x0bdc: 0x0918, 0x0bdd: 0x091a,
+ 0x0bde: 0x091c, 0x0bdf: 0x091e, 0x0be0: 0x0920, 0x0be1: 0x0922, 0x0be2: 0x0924, 0x0be3: 0x0929,
+ 0x0be4: 0x14c8, 0x0be5: 0x092b, 0x0be6: 0x17f6, 0x0be7: 0x092d, 0x0be8: 0x092f, 0x0be9: 0x155f,
+ 0x0bea: 0x0931, 0x0beb: 0x1570, 0x0bec: 0x17f8, 0x0bed: 0x14d4, 0x0bee: 0x0007, 0x0bef: 0x093d,
+ 0x0bf0: 0x0984, 0x0bf1: 0x093f, 0x0bf2: 0x0941, 0x0bf3: 0x098c, 0x0bf4: 0x094c, 0x0bf5: 0x0494,
+ 0x0bf6: 0x097c, 0x0bf7: 0x0499, 0x0bf8: 0x094e, 0x0bf9: 0x04c5, 0x0bfa: 0x0950, 0x0bfb: 0x14a0,
+ 0x0bfc: 0x001e, 0x0bfd: 0x0960, 0x0bfe: 0x17fa, 0x0bff: 0x049b,
// Block 0x30, offset 0xc00
- 0x0c00: 0x0b02, 0x0c01: 0x0b06, 0x0c02: 0x0b0a, 0x0c03: 0x0b0e, 0x0c04: 0x0b12, 0x0c05: 0x0b16,
- 0x0c06: 0x0b1a, 0x0c07: 0x0b1e, 0x0c08: 0x0b22, 0x0c09: 0x0b26, 0x0c0a: 0x0b2a, 0x0c0b: 0x0b2e,
- 0x0c0c: 0x0b32, 0x0c0d: 0x0b38, 0x0c0e: 0x0b3e, 0x0c0f: 0x0b44, 0x0c10: 0x0b4a, 0x0c11: 0x0b50,
- 0x0c12: 0x0b56, 0x0c13: 0x0b5c, 0x0c14: 0x0b62, 0x0c15: 0x0b66, 0x0c16: 0x0b6a, 0x0c17: 0x0b6e,
- 0x0c18: 0x0b72, 0x0c19: 0x0b76, 0x0c1a: 0x0b7a, 0x0c1b: 0x0b7e, 0x0c1c: 0x0b82, 0x0c1d: 0x0b88,
- 0x0c1e: 0x0b8e, 0x0c1f: 0x0b92, 0x0c20: 0x0b96, 0x0c21: 0x0b9a, 0x0c22: 0x0b9e, 0x0c23: 0x0ba2,
- 0x0c24: 0x0ba6, 0x0c25: 0x0bac, 0x0c26: 0x0bb2, 0x0c27: 0x0bb8, 0x0c28: 0x0bbe, 0x0c29: 0x0bc4,
- 0x0c2a: 0x0bca, 0x0c2b: 0x0bce, 0x0c2c: 0x0bd2, 0x0c2d: 0x0bd6, 0x0c2e: 0x0bda, 0x0c2f: 0x0bde,
- 0x0c30: 0x0be2, 0x0c31: 0x0be6, 0x0c32: 0x0bea, 0x0c33: 0x0bee, 0x0c34: 0x0bf2, 0x0c35: 0x0bf6,
- 0x0c36: 0x0bfa, 0x0c37: 0x0bfe, 0x0c38: 0x0c02, 0x0c39: 0x0c08, 0x0c3a: 0x0c0e, 0x0c3b: 0x0c14,
- 0x0c3c: 0x0c1a, 0x0c3d: 0x0c1e, 0x0c3e: 0x0c22, 0x0c3f: 0x0c26,
+ 0x0c00: 0x02c8, 0x0c01: 0x0962, 0x0c02: 0x0964, 0x0c03: 0x096d, 0x0c04: 0x04a6, 0x0c05: 0x04c7,
+ 0x0c06: 0x04a8, 0x0c07: 0x09df, 0x0c08: 0x0906, 0x0c09: 0x090b, 0x0c0a: 0x14ad, 0x0c0b: 0x090d,
+ 0x0c0c: 0x090f, 0x0c0d: 0x14d9, 0x0c0e: 0x0914, 0x0c0f: 0x0916, 0x0c10: 0x0918, 0x0c11: 0x091a,
+ 0x0c12: 0x091c, 0x0c13: 0x091e, 0x0c14: 0x0920, 0x0c15: 0x0922, 0x0c16: 0x0924, 0x0c17: 0x0929,
+ 0x0c18: 0x14c8, 0x0c19: 0x092b, 0x0c1a: 0x17f6, 0x0c1b: 0x092d, 0x0c1c: 0x092f, 0x0c1d: 0x155f,
+ 0x0c1e: 0x0931, 0x0c1f: 0x1570, 0x0c20: 0x17f8, 0x0c21: 0x14d4, 0x0c22: 0x0007, 0x0c23: 0x093d,
+ 0x0c24: 0x0984, 0x0c25: 0x093f, 0x0c26: 0x0941, 0x0c27: 0x098c, 0x0c28: 0x094c, 0x0c29: 0x0494,
+ 0x0c2a: 0x097c, 0x0c2b: 0x0499, 0x0c2c: 0x094e, 0x0c2d: 0x04c5, 0x0c2e: 0x0950, 0x0c2f: 0x14a0,
+ 0x0c30: 0x001e, 0x0c31: 0x0960, 0x0c32: 0x17fa, 0x0c33: 0x049b, 0x0c34: 0x02c8, 0x0c35: 0x0962,
+ 0x0c36: 0x0964, 0x0c37: 0x096d, 0x0c38: 0x04a6, 0x0c39: 0x04c7, 0x0c3a: 0x04a8, 0x0c3b: 0x09df,
+ 0x0c3c: 0x0906, 0x0c3d: 0x090b, 0x0c3e: 0x14ad, 0x0c3f: 0x090d,
// Block 0x31, offset 0xc40
- 0x0c40: 0x0c2a, 0x0c41: 0x0c2e, 0x0c42: 0x0c32, 0x0c43: 0x0c36, 0x0c44: 0x0c3a, 0x0c45: 0x0c3e,
- 0x0c46: 0x0c42, 0x0c47: 0x0c46, 0x0c48: 0x0c4a, 0x0c49: 0x0c4e, 0x0c4a: 0x0c52, 0x0c4b: 0x0c56,
- 0x0c4c: 0x0c5a, 0x0c4d: 0x0c5e, 0x0c4e: 0x0c62, 0x0c4f: 0x0c66, 0x0c50: 0x0c6a, 0x0c51: 0x0c6e,
- 0x0c52: 0x0c72, 0x0c53: 0x0c76, 0x0c54: 0x0c7a, 0x0c55: 0x0c7e, 0x0c56: 0x0c82, 0x0c57: 0x0c86,
- 0x0c58: 0x0c8a, 0x0c59: 0x0c8e, 0x0c5a: 0x0c92, 0x0c5b: 0x0b9a,
- 0x0c60: 0x0c9b, 0x0c61: 0x0c9f, 0x0c62: 0x0ca3, 0x0c63: 0x0ca7,
- 0x0c64: 0x0cab, 0x0c65: 0x0cb1, 0x0c66: 0x0cb7, 0x0c67: 0x0cbd, 0x0c68: 0x0cc3, 0x0c69: 0x0cc9,
- 0x0c6a: 0x0ccf, 0x0c6b: 0x0cd5, 0x0c6c: 0x0cdb, 0x0c6d: 0x0ce1, 0x0c6e: 0x0ce7, 0x0c6f: 0x0ced,
- 0x0c70: 0x0cf3, 0x0c71: 0x0cf9, 0x0c72: 0x0cff, 0x0c73: 0x0d05, 0x0c74: 0x0d0b, 0x0c75: 0x0d11,
- 0x0c76: 0x0d17, 0x0c77: 0x0d1d, 0x0c78: 0x0d23, 0x0c79: 0x0d27, 0x0c7a: 0x0d2b, 0x0c7b: 0x0d2f,
- 0x0c7c: 0x0d33, 0x0c7d: 0x0d37, 0x0c7e: 0x0d3b, 0x0c7f: 0x0d41,
+ 0x0c40: 0x090f, 0x0c41: 0x14d9, 0x0c42: 0x0914, 0x0c43: 0x0916, 0x0c44: 0x0918, 0x0c45: 0x091a,
+ 0x0c46: 0x091c, 0x0c47: 0x091e, 0x0c48: 0x0920, 0x0c49: 0x0922, 0x0c4a: 0x0924, 0x0c4b: 0x0929,
+ 0x0c4c: 0x14c8, 0x0c4d: 0x092b, 0x0c4e: 0x17f6, 0x0c4f: 0x092d, 0x0c50: 0x092f, 0x0c51: 0x155f,
+ 0x0c52: 0x0931, 0x0c53: 0x1570, 0x0c54: 0x17f8, 0x0c55: 0x14d4, 0x0c56: 0x0007, 0x0c57: 0x093d,
+ 0x0c58: 0x0984, 0x0c59: 0x093f, 0x0c5a: 0x0941, 0x0c5b: 0x098c, 0x0c5c: 0x094c, 0x0c5d: 0x0494,
+ 0x0c5e: 0x097c, 0x0c5f: 0x0499, 0x0c60: 0x094e, 0x0c61: 0x04c5, 0x0c62: 0x0950, 0x0c63: 0x14a0,
+ 0x0c64: 0x001e, 0x0c65: 0x0960, 0x0c66: 0x17fa, 0x0c67: 0x049b, 0x0c68: 0x02c8, 0x0c69: 0x0962,
+ 0x0c6a: 0x0964, 0x0c6b: 0x096d, 0x0c6c: 0x04a6, 0x0c6d: 0x04c7, 0x0c6e: 0x04a8, 0x0c6f: 0x09df,
+ 0x0c70: 0x0906, 0x0c71: 0x090b, 0x0c72: 0x14ad, 0x0c73: 0x090d, 0x0c74: 0x090f, 0x0c75: 0x14d9,
+ 0x0c76: 0x0914, 0x0c77: 0x0916, 0x0c78: 0x0918, 0x0c79: 0x091a, 0x0c7a: 0x091c, 0x0c7b: 0x091e,
+ 0x0c7c: 0x0920, 0x0c7d: 0x0922, 0x0c7e: 0x0924, 0x0c7f: 0x0929,
// Block 0x32, offset 0xc80
- 0x0c80: 0x0d47, 0x0c81: 0x0d4d, 0x0c82: 0x0d53, 0x0c83: 0x0d59, 0x0c84: 0x0d5f, 0x0c85: 0x0d65,
- 0x0c86: 0x0d6b, 0x0c87: 0x0d71, 0x0c88: 0x0d77, 0x0c89: 0x0d7b, 0x0c8a: 0x0d7f, 0x0c8b: 0x0d83,
- 0x0c8c: 0x0d87, 0x0c8d: 0x0d8b, 0x0c8e: 0x0d8f, 0x0c8f: 0x0d93, 0x0c90: 0x0d97, 0x0c91: 0x0d9d,
- 0x0c92: 0x0da3, 0x0c93: 0x0da9, 0x0c94: 0x0daf, 0x0c95: 0x0db5, 0x0c96: 0x0dbb, 0x0c97: 0x0dc1,
- 0x0c98: 0x0dc7, 0x0c99: 0x0dcd, 0x0c9a: 0x0dd3, 0x0c9b: 0x0dd9, 0x0c9c: 0x0ddf, 0x0c9d: 0x0de5,
- 0x0c9e: 0x0deb, 0x0c9f: 0x0df1, 0x0ca0: 0x0df7, 0x0ca1: 0x0dfd, 0x0ca2: 0x0e03, 0x0ca3: 0x0e09,
- 0x0ca4: 0x0e0f, 0x0ca5: 0x0e13, 0x0ca6: 0x0e17, 0x0ca7: 0x0e1b, 0x0ca8: 0x0e1f, 0x0ca9: 0x0e25,
- 0x0caa: 0x0e2b, 0x0cab: 0x0e31, 0x0cac: 0x0e37, 0x0cad: 0x0e3d, 0x0cae: 0x0e43, 0x0caf: 0x0e49,
- 0x0cb0: 0x0e4f, 0x0cb1: 0x0e55, 0x0cb2: 0x0e5b, 0x0cb3: 0x0e5f, 0x0cb4: 0x0e63, 0x0cb5: 0x0e67,
- 0x0cb6: 0x0e6b, 0x0cb7: 0x0e6f, 0x0cb8: 0x0e73, 0x0cb9: 0x0e77,
+ 0x0c80: 0x14c8, 0x0c81: 0x092b, 0x0c82: 0x17f6, 0x0c83: 0x092d, 0x0c84: 0x092f, 0x0c85: 0x155f,
+ 0x0c86: 0x0931, 0x0c87: 0x1570, 0x0c88: 0x17f8, 0x0c89: 0x14d4, 0x0c8a: 0x0007, 0x0c8b: 0x093d,
+ 0x0c8c: 0x0984, 0x0c8d: 0x093f, 0x0c8e: 0x0941, 0x0c8f: 0x098c, 0x0c90: 0x094c, 0x0c91: 0x0494,
+ 0x0c92: 0x097c, 0x0c93: 0x0499, 0x0c94: 0x094e, 0x0c95: 0x04c5, 0x0c96: 0x0950, 0x0c97: 0x14a0,
+ 0x0c98: 0x001e, 0x0c99: 0x0960, 0x0c9a: 0x17fa, 0x0c9b: 0x049b, 0x0c9c: 0x02c8, 0x0c9d: 0x0962,
+ 0x0c9e: 0x0964, 0x0c9f: 0x096d, 0x0ca0: 0x04a6, 0x0ca1: 0x04c7, 0x0ca2: 0x04a8, 0x0ca3: 0x09df,
+ 0x0ca4: 0x3b27, 0x0ca5: 0x3b2a, 0x0ca8: 0x3b2d, 0x0ca9: 0x3b30,
+ 0x0caa: 0x14eb, 0x0cab: 0x3b33, 0x0cac: 0x3b36, 0x0cad: 0x3b39, 0x0cae: 0x3b3c, 0x0caf: 0x057b,
+ 0x0cb0: 0x3b3f, 0x0cb1: 0x3b42, 0x0cb2: 0x3b45, 0x0cb3: 0x3b48, 0x0cb4: 0x3b4b, 0x0cb5: 0x3b4e,
+ 0x0cb6: 0x3b51, 0x0cb7: 0x14ee, 0x0cb8: 0x3b54, 0x0cb9: 0x057b, 0x0cba: 0x0581, 0x0cbb: 0x3b57,
+ 0x0cbc: 0x055f, 0x0cbd: 0x3b5a, 0x0cbe: 0x3b5d, 0x0cbf: 0x3b60,
// Block 0x33, offset 0xcc0
- 0x0cc0: 0x0e7b, 0x0cc1: 0x0e80, 0x0cc2: 0x0e85, 0x0cc3: 0x0e8c, 0x0cc4: 0x0e93, 0x0cc5: 0x0e9a,
- 0x0cc6: 0x0ea1, 0x0cc7: 0x0ea8, 0x0cc8: 0x0eaf, 0x0cc9: 0x0eb4, 0x0cca: 0x0eb9, 0x0ccb: 0x0ec0,
- 0x0ccc: 0x0ec7, 0x0ccd: 0x0ece, 0x0cce: 0x0ed5, 0x0ccf: 0x0edc, 0x0cd0: 0x0ee3, 0x0cd1: 0x0ee8,
- 0x0cd2: 0x0eed, 0x0cd3: 0x0ef4, 0x0cd4: 0x0efb, 0x0cd5: 0x0f02,
- 0x0cd8: 0x0f09, 0x0cd9: 0x0f0e, 0x0cda: 0x0f13, 0x0cdb: 0x0f1a, 0x0cdc: 0x0f21, 0x0cdd: 0x0f28,
- 0x0ce0: 0x0f2f, 0x0ce1: 0x0f34, 0x0ce2: 0x0f39, 0x0ce3: 0x0f40,
- 0x0ce4: 0x0f47, 0x0ce5: 0x0f4e, 0x0ce6: 0x0f55, 0x0ce7: 0x0f5c, 0x0ce8: 0x0f63, 0x0ce9: 0x0f68,
- 0x0cea: 0x0f6d, 0x0ceb: 0x0f74, 0x0cec: 0x0f7b, 0x0ced: 0x0f82, 0x0cee: 0x0f89, 0x0cef: 0x0f90,
- 0x0cf0: 0x0f97, 0x0cf1: 0x0f9c, 0x0cf2: 0x0fa1, 0x0cf3: 0x0fa8, 0x0cf4: 0x0faf, 0x0cf5: 0x0fb6,
- 0x0cf6: 0x0fbd, 0x0cf7: 0x0fc4, 0x0cf8: 0x0fcb, 0x0cf9: 0x0fd0, 0x0cfa: 0x0fd5, 0x0cfb: 0x0fdc,
- 0x0cfc: 0x0fe3, 0x0cfd: 0x0fea, 0x0cfe: 0x0ff1, 0x0cff: 0x0ff8,
+ 0x0cc0: 0x14d6, 0x0cc1: 0x3b63, 0x0cc2: 0x3b67, 0x0cc3: 0x0559, 0x0cc4: 0x0973, 0x0cc5: 0x0976,
+ 0x0cc6: 0x057e, 0x0cc7: 0x3b6a, 0x0cc8: 0x3b6d, 0x0cc9: 0x055c, 0x0cca: 0x12fd, 0x0ccb: 0x0572,
+ 0x0ccc: 0x3b70, 0x0ccd: 0x0015, 0x0cce: 0x3b73, 0x0ccf: 0x3b76, 0x0cd0: 0x3b79, 0x0cd1: 0x056f,
+ 0x0cd2: 0x0575, 0x0cd3: 0x0578, 0x0cd4: 0x3b7c, 0x0cd5: 0x3b7f, 0x0cd6: 0x3b82, 0x0cd7: 0x056c,
+ 0x0cd8: 0x0979, 0x0cd9: 0x3b85, 0x0cda: 0x3b88, 0x0cdb: 0x3b8b, 0x0cdc: 0x057e, 0x0cdd: 0x055c,
+ 0x0cde: 0x0572, 0x0cdf: 0x056c, 0x0ce0: 0x0575, 0x0ce1: 0x056f, 0x0ce2: 0x3b2d, 0x0ce3: 0x3b30,
+ 0x0ce4: 0x14eb, 0x0ce5: 0x3b33, 0x0ce6: 0x3b36, 0x0ce7: 0x3b39, 0x0ce8: 0x3b3c, 0x0ce9: 0x057b,
+ 0x0cea: 0x3b3f, 0x0ceb: 0x3b42, 0x0cec: 0x3b45, 0x0ced: 0x3b48, 0x0cee: 0x3b4b, 0x0cef: 0x3b4e,
+ 0x0cf0: 0x3b51, 0x0cf1: 0x14ee, 0x0cf2: 0x3b54, 0x0cf3: 0x057b, 0x0cf4: 0x0581, 0x0cf5: 0x3b57,
+ 0x0cf6: 0x055f, 0x0cf7: 0x3b5a, 0x0cf8: 0x3b5d, 0x0cf9: 0x3b60, 0x0cfa: 0x14d6, 0x0cfb: 0x3b63,
+ 0x0cfc: 0x3b67, 0x0cfd: 0x0559, 0x0cfe: 0x0973, 0x0cff: 0x0976,
// Block 0x34, offset 0xd00
- 0x0d00: 0x0fff, 0x0d01: 0x1004, 0x0d02: 0x1009, 0x0d03: 0x1010, 0x0d04: 0x1017, 0x0d05: 0x101e,
- 0x0d08: 0x1025, 0x0d09: 0x102a, 0x0d0a: 0x102f, 0x0d0b: 0x1036,
- 0x0d0c: 0x103d, 0x0d0d: 0x1044, 0x0d10: 0x104b, 0x0d11: 0x1050,
- 0x0d12: 0x1055, 0x0d13: 0x105c, 0x0d14: 0x1063, 0x0d15: 0x106a, 0x0d16: 0x1071, 0x0d17: 0x1078,
- 0x0d19: 0x107f, 0x0d1b: 0x1084, 0x0d1d: 0x108b,
- 0x0d1f: 0x1092, 0x0d20: 0x1099, 0x0d21: 0x109e, 0x0d22: 0x10a3, 0x0d23: 0x10aa,
- 0x0d24: 0x10b1, 0x0d25: 0x10b8, 0x0d26: 0x10bf, 0x0d27: 0x10c6, 0x0d28: 0x10cd, 0x0d29: 0x10d2,
- 0x0d2a: 0x10d7, 0x0d2b: 0x10de, 0x0d2c: 0x10e5, 0x0d2d: 0x10ec, 0x0d2e: 0x10f3, 0x0d2f: 0x10fa,
- 0x0d30: 0x1101, 0x0d31: 0x0525, 0x0d32: 0x1106, 0x0d33: 0x052a, 0x0d34: 0x110b, 0x0d35: 0x052f,
- 0x0d36: 0x1110, 0x0d37: 0x0534, 0x0d38: 0x1115, 0x0d39: 0x054a, 0x0d3a: 0x111a, 0x0d3b: 0x054f,
- 0x0d3c: 0x111f, 0x0d3d: 0x0554,
+ 0x0d00: 0x057e, 0x0d01: 0x3b6a, 0x0d02: 0x3b6d, 0x0d03: 0x055c, 0x0d04: 0x12fd, 0x0d05: 0x0572,
+ 0x0d06: 0x3b70, 0x0d07: 0x0015, 0x0d08: 0x3b73, 0x0d09: 0x3b76, 0x0d0a: 0x3b79, 0x0d0b: 0x056f,
+ 0x0d0c: 0x0575, 0x0d0d: 0x0578, 0x0d0e: 0x3b7c, 0x0d0f: 0x3b7f, 0x0d10: 0x3b82, 0x0d11: 0x056c,
+ 0x0d12: 0x0979, 0x0d13: 0x3b85, 0x0d14: 0x3b88, 0x0d15: 0x3b8b, 0x0d16: 0x057e, 0x0d17: 0x055c,
+ 0x0d18: 0x0572, 0x0d19: 0x056c, 0x0d1a: 0x0575, 0x0d1b: 0x056f, 0x0d1c: 0x3b2d, 0x0d1d: 0x3b30,
+ 0x0d1e: 0x14eb, 0x0d1f: 0x3b33, 0x0d20: 0x3b36, 0x0d21: 0x3b39, 0x0d22: 0x3b3c, 0x0d23: 0x057b,
+ 0x0d24: 0x3b3f, 0x0d25: 0x3b42, 0x0d26: 0x3b45, 0x0d27: 0x3b48, 0x0d28: 0x3b4b, 0x0d29: 0x3b4e,
+ 0x0d2a: 0x3b51, 0x0d2b: 0x14ee, 0x0d2c: 0x3b54, 0x0d2d: 0x057b, 0x0d2e: 0x0581, 0x0d2f: 0x3b57,
+ 0x0d30: 0x055f, 0x0d31: 0x3b5a, 0x0d32: 0x3b5d, 0x0d33: 0x3b60, 0x0d34: 0x14d6, 0x0d35: 0x3b63,
+ 0x0d36: 0x3b67, 0x0d37: 0x0559, 0x0d38: 0x0973, 0x0d39: 0x0976, 0x0d3a: 0x057e, 0x0d3b: 0x3b6a,
+ 0x0d3c: 0x3b6d, 0x0d3d: 0x055c, 0x0d3e: 0x12fd, 0x0d3f: 0x0572,
// Block 0x35, offset 0xd40
- 0x0d40: 0x1124, 0x0d41: 0x112b, 0x0d42: 0x1132, 0x0d43: 0x113b, 0x0d44: 0x1144, 0x0d45: 0x114d,
- 0x0d46: 0x1156, 0x0d47: 0x115f, 0x0d48: 0x1168, 0x0d49: 0x116f, 0x0d4a: 0x1176, 0x0d4b: 0x117f,
- 0x0d4c: 0x1188, 0x0d4d: 0x1191, 0x0d4e: 0x119a, 0x0d4f: 0x11a3, 0x0d50: 0x11ac, 0x0d51: 0x11b3,
- 0x0d52: 0x11ba, 0x0d53: 0x11c3, 0x0d54: 0x11cc, 0x0d55: 0x11d5, 0x0d56: 0x11de, 0x0d57: 0x11e7,
- 0x0d58: 0x11f0, 0x0d59: 0x11f7, 0x0d5a: 0x11fe, 0x0d5b: 0x1207, 0x0d5c: 0x1210, 0x0d5d: 0x1219,
- 0x0d5e: 0x1222, 0x0d5f: 0x122b, 0x0d60: 0x1234, 0x0d61: 0x123b, 0x0d62: 0x1242, 0x0d63: 0x124b,
- 0x0d64: 0x1254, 0x0d65: 0x125d, 0x0d66: 0x1266, 0x0d67: 0x126f, 0x0d68: 0x1278, 0x0d69: 0x127f,
- 0x0d6a: 0x1286, 0x0d6b: 0x128f, 0x0d6c: 0x1298, 0x0d6d: 0x12a1, 0x0d6e: 0x12aa, 0x0d6f: 0x12b3,
- 0x0d70: 0x12bc, 0x0d71: 0x12c1, 0x0d72: 0x12c6, 0x0d73: 0x12cd, 0x0d74: 0x12d2,
- 0x0d76: 0x12d9, 0x0d77: 0x12de, 0x0d78: 0x12e5, 0x0d79: 0x12ea, 0x0d7a: 0x12ef, 0x0d7b: 0x04ee,
- 0x0d7c: 0x12f4, 0x0d7d: 0x12f9, 0x0d7e: 0x12fd, 0x0d7f: 0x12f9,
+ 0x0d40: 0x3b70, 0x0d41: 0x0015, 0x0d42: 0x3b73, 0x0d43: 0x3b76, 0x0d44: 0x3b79, 0x0d45: 0x056f,
+ 0x0d46: 0x0575, 0x0d47: 0x0578, 0x0d48: 0x3b7c, 0x0d49: 0x3b7f, 0x0d4a: 0x3b82, 0x0d4b: 0x056c,
+ 0x0d4c: 0x0979, 0x0d4d: 0x3b85, 0x0d4e: 0x3b88, 0x0d4f: 0x3b8b, 0x0d50: 0x057e, 0x0d51: 0x055c,
+ 0x0d52: 0x0572, 0x0d53: 0x056c, 0x0d54: 0x0575, 0x0d55: 0x056f, 0x0d56: 0x3b2d, 0x0d57: 0x3b30,
+ 0x0d58: 0x14eb, 0x0d59: 0x3b33, 0x0d5a: 0x3b36, 0x0d5b: 0x3b39, 0x0d5c: 0x3b3c, 0x0d5d: 0x057b,
+ 0x0d5e: 0x3b3f, 0x0d5f: 0x3b42, 0x0d60: 0x3b45, 0x0d61: 0x3b48, 0x0d62: 0x3b4b, 0x0d63: 0x3b4e,
+ 0x0d64: 0x3b51, 0x0d65: 0x14ee, 0x0d66: 0x3b54, 0x0d67: 0x057b, 0x0d68: 0x0581, 0x0d69: 0x3b57,
+ 0x0d6a: 0x055f, 0x0d6b: 0x3b5a, 0x0d6c: 0x3b5d, 0x0d6d: 0x3b60, 0x0d6e: 0x14d6, 0x0d6f: 0x3b63,
+ 0x0d70: 0x3b67, 0x0d71: 0x0559, 0x0d72: 0x0973, 0x0d73: 0x0976, 0x0d74: 0x057e, 0x0d75: 0x3b6a,
+ 0x0d76: 0x3b6d, 0x0d77: 0x055c, 0x0d78: 0x12fd, 0x0d79: 0x0572, 0x0d7a: 0x3b70, 0x0d7b: 0x0015,
+ 0x0d7c: 0x3b73, 0x0d7d: 0x3b76, 0x0d7e: 0x3b79, 0x0d7f: 0x056f,
// Block 0x36, offset 0xd80
- 0x0d80: 0x1300, 0x0d81: 0x1309, 0x0d82: 0x130f, 0x0d83: 0x1316, 0x0d84: 0x131b,
- 0x0d86: 0x1322, 0x0d87: 0x1327, 0x0d88: 0x132e, 0x0d89: 0x04f6, 0x0d8a: 0x1333, 0x0d8b: 0x04fb,
- 0x0d8c: 0x1338, 0x0d8d: 0x1343, 0x0d8e: 0x134f, 0x0d8f: 0x135b, 0x0d90: 0x1361, 0x0d91: 0x1366,
- 0x0d92: 0x136b, 0x0d93: 0x0514, 0x0d96: 0x1372, 0x0d97: 0x1377,
- 0x0d98: 0x137e, 0x0d99: 0x1383, 0x0d9a: 0x1388, 0x0d9b: 0x0500, 0x0d9d: 0x1393,
- 0x0d9e: 0x139f, 0x0d9f: 0x13ab, 0x0da0: 0x13b1, 0x0da1: 0x13b6, 0x0da2: 0x13bb, 0x0da3: 0x0539,
- 0x0da4: 0x13c2, 0x0da5: 0x13c7, 0x0da6: 0x13cc, 0x0da7: 0x13d1, 0x0da8: 0x13d8, 0x0da9: 0x13dd,
- 0x0daa: 0x13e2, 0x0dab: 0x050a, 0x0dac: 0x13e7, 0x0dad: 0x13f1, 0x0dae: 0x04e8, 0x0daf: 0x13f7,
- 0x0db2: 0x13f9, 0x0db3: 0x1400, 0x0db4: 0x1405,
- 0x0db6: 0x140c, 0x0db7: 0x1411, 0x0db8: 0x1418, 0x0db9: 0x0505, 0x0dba: 0x141d, 0x0dbb: 0x050f,
- 0x0dbc: 0x1422, 0x0dbd: 0x0011, 0x0dbe: 0x142a,
+ 0x0d80: 0x0575, 0x0d81: 0x0578, 0x0d82: 0x3b7c, 0x0d83: 0x3b7f, 0x0d84: 0x3b82, 0x0d85: 0x056c,
+ 0x0d86: 0x0979, 0x0d87: 0x3b85, 0x0d88: 0x3b88, 0x0d89: 0x3b8b, 0x0d8a: 0x057e, 0x0d8b: 0x055c,
+ 0x0d8c: 0x0572, 0x0d8d: 0x056c, 0x0d8e: 0x0575, 0x0d8f: 0x056f, 0x0d90: 0x3b2d, 0x0d91: 0x3b30,
+ 0x0d92: 0x14eb, 0x0d93: 0x3b33, 0x0d94: 0x3b36, 0x0d95: 0x3b39, 0x0d96: 0x3b3c, 0x0d97: 0x057b,
+ 0x0d98: 0x3b3f, 0x0d99: 0x3b42, 0x0d9a: 0x3b45, 0x0d9b: 0x3b48, 0x0d9c: 0x3b4b, 0x0d9d: 0x3b4e,
+ 0x0d9e: 0x3b51, 0x0d9f: 0x14ee, 0x0da0: 0x3b54, 0x0da1: 0x057b, 0x0da2: 0x0581, 0x0da3: 0x3b57,
+ 0x0da4: 0x055f, 0x0da5: 0x3b5a, 0x0da6: 0x3b5d, 0x0da7: 0x3b60, 0x0da8: 0x14d6, 0x0da9: 0x3b63,
+ 0x0daa: 0x3b67, 0x0dab: 0x0559, 0x0dac: 0x0973, 0x0dad: 0x0976, 0x0dae: 0x057e, 0x0daf: 0x3b6a,
+ 0x0db0: 0x3b6d, 0x0db1: 0x055c, 0x0db2: 0x12fd, 0x0db3: 0x0572, 0x0db4: 0x3b70, 0x0db5: 0x0015,
+ 0x0db6: 0x3b73, 0x0db7: 0x3b76, 0x0db8: 0x3b79, 0x0db9: 0x056f, 0x0dba: 0x0575, 0x0dbb: 0x0578,
+ 0x0dbc: 0x3b7c, 0x0dbd: 0x3b7f, 0x0dbe: 0x3b82, 0x0dbf: 0x056c,
// Block 0x37, offset 0xdc0
- 0x0dc0: 0x0001, 0x0dc1: 0x0001, 0x0dc2: 0x0001, 0x0dc3: 0x0001, 0x0dc4: 0x0001, 0x0dc5: 0x0001,
- 0x0dc6: 0x0001, 0x0dc7: 0x0001, 0x0dc8: 0x0001, 0x0dc9: 0x0001, 0x0dca: 0x0001,
- 0x0dd1: 0x1436,
- 0x0dd7: 0x143a,
- 0x0de4: 0x143e, 0x0de5: 0x1440, 0x0de6: 0x1443,
- 0x0def: 0x0001,
- 0x0df3: 0x1447, 0x0df4: 0x144e,
- 0x0df6: 0x1458, 0x0df7: 0x145f,
- 0x0dfc: 0x1469, 0x0dfe: 0x146c,
+ 0x0dc0: 0x0979, 0x0dc1: 0x3b85, 0x0dc2: 0x3b88, 0x0dc3: 0x3b8b, 0x0dc4: 0x057e, 0x0dc5: 0x055c,
+ 0x0dc6: 0x0572, 0x0dc7: 0x056c, 0x0dc8: 0x0575, 0x0dc9: 0x056f, 0x0dca: 0x3b8f, 0x0dcb: 0x3b92,
+ 0x0dce: 0x1486, 0x0dcf: 0x001c, 0x0dd0: 0x000d, 0x0dd1: 0x000f,
+ 0x0dd2: 0x1488, 0x0dd3: 0x148a, 0x0dd4: 0x148c, 0x0dd5: 0x148e, 0x0dd6: 0x1490, 0x0dd7: 0x1492,
+ 0x0dd8: 0x1486, 0x0dd9: 0x001c, 0x0dda: 0x000d, 0x0ddb: 0x000f, 0x0ddc: 0x1488, 0x0ddd: 0x148a,
+ 0x0dde: 0x148c, 0x0ddf: 0x148e, 0x0de0: 0x1490, 0x0de1: 0x1492, 0x0de2: 0x1486, 0x0de3: 0x001c,
+ 0x0de4: 0x000d, 0x0de5: 0x000f, 0x0de6: 0x1488, 0x0de7: 0x148a, 0x0de8: 0x148c, 0x0de9: 0x148e,
+ 0x0dea: 0x1490, 0x0deb: 0x1492, 0x0dec: 0x1486, 0x0ded: 0x001c, 0x0dee: 0x000d, 0x0def: 0x000f,
+ 0x0df0: 0x1488, 0x0df1: 0x148a, 0x0df2: 0x148c, 0x0df3: 0x148e, 0x0df4: 0x1490, 0x0df5: 0x1492,
+ 0x0df6: 0x1486, 0x0df7: 0x001c, 0x0df8: 0x000d, 0x0df9: 0x000f, 0x0dfa: 0x1488, 0x0dfb: 0x148a,
+ 0x0dfc: 0x148c, 0x0dfd: 0x148e, 0x0dfe: 0x1490, 0x0dff: 0x1492,
// Block 0x38, offset 0xe00
- 0x0e07: 0x1470, 0x0e08: 0x1473, 0x0e09: 0x1476,
- 0x0e17: 0x1479,
- 0x0e1f: 0x0001,
- 0x0e30: 0x1486, 0x0e31: 0x097c, 0x0e34: 0x1488, 0x0e35: 0x148a,
- 0x0e36: 0x148c, 0x0e37: 0x148e, 0x0e38: 0x1490, 0x0e39: 0x1492, 0x0e3a: 0x1494, 0x0e3b: 0x1496,
- 0x0e3c: 0x149a, 0x0e3d: 0x149c, 0x0e3e: 0x149e, 0x0e3f: 0x14a0,
+ 0x0e00: 0x3b95, 0x0e01: 0x3b98, 0x0e02: 0x3b9b, 0x0e03: 0x3b9e, 0x0e04: 0x3ba1, 0x0e05: 0x3ba4,
+ 0x0e06: 0x3ba7, 0x0e07: 0x3baa, 0x0e08: 0x3bad, 0x0e09: 0x3bb0, 0x0e0a: 0x3bb3,
+ 0x0e10: 0x3bb6, 0x0e11: 0x3bba,
+ 0x0e12: 0x3bbe, 0x0e13: 0x3bc2, 0x0e14: 0x3bc6, 0x0e15: 0x3bca, 0x0e16: 0x3bce, 0x0e17: 0x3bd2,
+ 0x0e18: 0x3bd6, 0x0e19: 0x3bda, 0x0e1a: 0x3bde, 0x0e1b: 0x3be2, 0x0e1c: 0x3be6, 0x0e1d: 0x3bea,
+ 0x0e1e: 0x3bee, 0x0e1f: 0x3bf2, 0x0e20: 0x3bf6, 0x0e21: 0x3bfa, 0x0e22: 0x3bfe, 0x0e23: 0x3c02,
+ 0x0e24: 0x3c06, 0x0e25: 0x3c0a, 0x0e26: 0x3c0e, 0x0e27: 0x3c12, 0x0e28: 0x3c16, 0x0e29: 0x3c1a,
+ 0x0e2a: 0x3c1e, 0x0e2b: 0x14ad, 0x0e2c: 0x092b, 0x0e2d: 0x3c26, 0x0e2e: 0x3c29,
+ 0x0e30: 0x0906, 0x0e31: 0x090b, 0x0e32: 0x14ad, 0x0e33: 0x090d, 0x0e34: 0x090f, 0x0e35: 0x14d9,
+ 0x0e36: 0x0914, 0x0e37: 0x0916, 0x0e38: 0x0918, 0x0e39: 0x091a, 0x0e3a: 0x091c, 0x0e3b: 0x091e,
+ 0x0e3c: 0x0920, 0x0e3d: 0x0922, 0x0e3e: 0x0924, 0x0e3f: 0x0929,
// Block 0x39, offset 0xe40
- 0x0e40: 0x1486, 0x0e41: 0x001c, 0x0e42: 0x000d, 0x0e43: 0x000f, 0x0e44: 0x1488, 0x0e45: 0x148a,
- 0x0e46: 0x148c, 0x0e47: 0x148e, 0x0e48: 0x1490, 0x0e49: 0x1492, 0x0e4a: 0x1494, 0x0e4b: 0x1496,
- 0x0e4c: 0x149a, 0x0e4d: 0x149c, 0x0e4e: 0x149e, 0x0e50: 0x0007, 0x0e51: 0x0941,
- 0x0e52: 0x001e, 0x0e53: 0x04c7, 0x0e54: 0x0943, 0x0e55: 0x0494, 0x0e56: 0x094e, 0x0e57: 0x04c5,
- 0x0e58: 0x0950, 0x0e59: 0x14a0, 0x0e5a: 0x0960, 0x0e5b: 0x02c8, 0x0e5c: 0x0962,
- 0x0e68: 0x14a2,
+ 0x0e40: 0x3c3f, 0x0e41: 0x3c46, 0x0e42: 0x2291,
+ 0x0e50: 0x1922, 0x0e51: 0x3c4d,
+ 0x0e52: 0x3c51, 0x0e53: 0x1cb3, 0x0e54: 0x183e, 0x0e55: 0x3c55, 0x0e56: 0x3c59, 0x0e57: 0x1ed0,
+ 0x0e58: 0x3c5d, 0x0e59: 0x3c61, 0x0e5a: 0x3c65, 0x0e5b: 0x2d49, 0x0e5c: 0x3c69, 0x0e5d: 0x3c6d,
+ 0x0e5e: 0x3c71, 0x0e5f: 0x3c75, 0x0e60: 0x3c79, 0x0e61: 0x3c7d, 0x0e62: 0x19b2, 0x0e63: 0x3c81,
+ 0x0e64: 0x3c85, 0x0e65: 0x3c89, 0x0e66: 0x3c8d, 0x0e67: 0x3c91, 0x0e68: 0x3c95, 0x0e69: 0x1826,
+ 0x0e6a: 0x1eb0, 0x0e6b: 0x3c99, 0x0e6c: 0x21c7, 0x0e6d: 0x1ebc, 0x0e6e: 0x21cb, 0x0e6f: 0x3c9d,
+ 0x0e70: 0x1a92, 0x0e71: 0x3ca1, 0x0e72: 0x3ca5, 0x0e73: 0x3ca9, 0x0e74: 0x3cad, 0x0e75: 0x3cb1,
+ 0x0e76: 0x2183, 0x0e77: 0x194a, 0x0e78: 0x3cb5, 0x0e79: 0x3cb9, 0x0e7a: 0x3cbd,
// Block 0x3a, offset 0xe80
- 0x0e80: 0x14a5, 0x0e81: 0x14a9, 0x0e82: 0x14ad, 0x0e83: 0x14af, 0x0e85: 0x14b3,
- 0x0e86: 0x14b7, 0x0e87: 0x14bb, 0x0e89: 0x14be, 0x0e8a: 0x094c, 0x0e8b: 0x0916,
- 0x0e8c: 0x0916, 0x0e8d: 0x0916, 0x0e8e: 0x0494, 0x0e8f: 0x14c2, 0x0e90: 0x0918, 0x0e91: 0x0918,
- 0x0e92: 0x091e, 0x0e93: 0x04c5, 0x0e95: 0x0922, 0x0e96: 0x14c5,
- 0x0e99: 0x0929, 0x0e9a: 0x14c8, 0x0e9b: 0x092b, 0x0e9c: 0x092b, 0x0e9d: 0x092b,
- 0x0ea0: 0x14ca, 0x0ea1: 0x14cd, 0x0ea2: 0x14d1,
- 0x0ea4: 0x14d4, 0x0ea6: 0x14d6, 0x0ea8: 0x14d4,
- 0x0eaa: 0x091c, 0x0eab: 0x0046, 0x0eac: 0x090b, 0x0ead: 0x14ad, 0x0eaf: 0x0941,
- 0x0eb0: 0x090f, 0x0eb1: 0x14d9, 0x0eb3: 0x0920, 0x0eb4: 0x001e, 0x0eb5: 0x14db,
- 0x0eb6: 0x14de, 0x0eb7: 0x14e1, 0x0eb8: 0x14e4, 0x0eb9: 0x097c, 0x0ebb: 0x14e7,
- 0x0ebc: 0x056f, 0x0ebd: 0x0973, 0x0ebe: 0x14eb, 0x0ebf: 0x14ee,
+ 0x0e80: 0x3d23, 0x0e81: 0x3d27, 0x0e82: 0x3d2b, 0x0e83: 0x3d2f, 0x0e84: 0x3d34, 0x0e85: 0x2eb5,
+ 0x0e86: 0x3d38, 0x0e87: 0x3d3c, 0x0e88: 0x3d40, 0x0e89: 0x3d44, 0x0e8a: 0x2eb9, 0x0e8b: 0x3d48,
+ 0x0e8c: 0x3d4c, 0x0e8d: 0x3d50, 0x0e8e: 0x2ebd, 0x0e8f: 0x3d55, 0x0e90: 0x3d59, 0x0e91: 0x3d5d,
+ 0x0e92: 0x3d61, 0x0e93: 0x3d66, 0x0e94: 0x3d6a, 0x0e95: 0x3c71, 0x0e96: 0x3d6e, 0x0e97: 0x3d73,
+ 0x0e98: 0x3d77, 0x0e99: 0x3d7b, 0x0e9a: 0x3d7f, 0x0e9b: 0x2f9a, 0x0e9c: 0x3d83, 0x0e9d: 0x1866,
+ 0x0e9e: 0x3d88, 0x0e9f: 0x3d8c, 0x0ea0: 0x3d90, 0x0ea1: 0x3d94, 0x0ea2: 0x3cb9, 0x0ea3: 0x3d98,
+ 0x0ea4: 0x3d9c, 0x0ea5: 0x2fae, 0x0ea6: 0x2ec1, 0x0ea7: 0x2ec5, 0x0ea8: 0x2fb2, 0x0ea9: 0x3da0,
+ 0x0eaa: 0x3da4, 0x0eab: 0x2bf1, 0x0eac: 0x3da8, 0x0ead: 0x2ec9, 0x0eae: 0x3dac, 0x0eaf: 0x3db0,
+ 0x0eb0: 0x3db4, 0x0eb1: 0x3db8, 0x0eb2: 0x3db8, 0x0eb3: 0x3db8, 0x0eb4: 0x3dbc, 0x0eb5: 0x3dc1,
+ 0x0eb6: 0x3dc5, 0x0eb7: 0x3dc9, 0x0eb8: 0x3dcd, 0x0eb9: 0x3dd2, 0x0eba: 0x3dd6, 0x0ebb: 0x3dda,
+ 0x0ebc: 0x3dde, 0x0ebd: 0x3de2, 0x0ebe: 0x3de6, 0x0ebf: 0x3dea,
// Block 0x3b, offset 0xec0
- 0x0ec0: 0x14f1, 0x0ec5: 0x090d,
- 0x0ec6: 0x093f, 0x0ec7: 0x0941, 0x0ec8: 0x097c, 0x0ec9: 0x0499,
- 0x0ed0: 0x14f5, 0x0ed1: 0x14fb,
- 0x0ed2: 0x1501, 0x0ed3: 0x1508, 0x0ed4: 0x150e, 0x0ed5: 0x1514, 0x0ed6: 0x151a, 0x0ed7: 0x1520,
- 0x0ed8: 0x1526, 0x0ed9: 0x152c, 0x0eda: 0x1532, 0x0edb: 0x1538, 0x0edc: 0x153e, 0x0edd: 0x1544,
- 0x0ede: 0x154a, 0x0edf: 0x1550, 0x0ee0: 0x0918, 0x0ee1: 0x1555, 0x0ee2: 0x1558, 0x0ee3: 0x155c,
- 0x0ee4: 0x155f, 0x0ee5: 0x1561, 0x0ee6: 0x1564, 0x0ee7: 0x1568, 0x0ee8: 0x156d, 0x0ee9: 0x1570,
- 0x0eea: 0x1572, 0x0eeb: 0x1575, 0x0eec: 0x091e, 0x0eed: 0x14ad, 0x0eee: 0x090d, 0x0eef: 0x0920,
- 0x0ef0: 0x097c, 0x0ef1: 0x1579, 0x0ef2: 0x157c, 0x0ef3: 0x1580, 0x0ef4: 0x096d, 0x0ef5: 0x1583,
- 0x0ef6: 0x1586, 0x0ef7: 0x158a, 0x0ef8: 0x158f, 0x0ef9: 0x04c7, 0x0efa: 0x1592, 0x0efb: 0x1595,
- 0x0efc: 0x04c5, 0x0efd: 0x0984, 0x0efe: 0x093f, 0x0eff: 0x0950,
+ 0x0ec0: 0x3dee, 0x0ec1: 0x3df2, 0x0ec2: 0x3df6, 0x0ec3: 0x3dfa, 0x0ec4: 0x3dfe, 0x0ec5: 0x3e02,
+ 0x0ec6: 0x3e02, 0x0ec7: 0x2fba, 0x0ec8: 0x3e06, 0x0ec9: 0x3e0a, 0x0eca: 0x3e0e, 0x0ecb: 0x3e12,
+ 0x0ecc: 0x2ed1, 0x0ecd: 0x3e16, 0x0ece: 0x3e1a, 0x0ecf: 0x3e1e, 0x0ed0: 0x2e39, 0x0ed1: 0x3e22,
+ 0x0ed2: 0x3e26, 0x0ed3: 0x3e2a, 0x0ed4: 0x3e2e, 0x0ed5: 0x3e32, 0x0ed6: 0x3e36, 0x0ed7: 0x3e3a,
+ 0x0ed8: 0x3e3e, 0x0ed9: 0x3e42, 0x0eda: 0x3e47, 0x0edb: 0x3e4b, 0x0edc: 0x3e4f, 0x0edd: 0x3c55,
+ 0x0ede: 0x3e53, 0x0edf: 0x3e57, 0x0ee0: 0x3e5b, 0x0ee1: 0x3e60, 0x0ee2: 0x3e65, 0x0ee3: 0x3e69,
+ 0x0ee4: 0x3e6d, 0x0ee5: 0x3e71, 0x0ee6: 0x3e75, 0x0ee7: 0x3e79, 0x0ee8: 0x3e7d, 0x0ee9: 0x3e81,
+ 0x0eea: 0x3e85, 0x0eeb: 0x3e85, 0x0eec: 0x3e89, 0x0eed: 0x3e8e, 0x0eee: 0x3e92, 0x0eef: 0x2be1,
+ 0x0ef0: 0x3e96, 0x0ef1: 0x3e9a, 0x0ef2: 0x3e9f, 0x0ef3: 0x3ea3, 0x0ef4: 0x3ea7, 0x0ef5: 0x18ce,
+ 0x0ef6: 0x3eab, 0x0ef7: 0x3eaf, 0x0ef8: 0x18d6, 0x0ef9: 0x3eb3, 0x0efa: 0x3eb7, 0x0efb: 0x3ebb,
+ 0x0efc: 0x3ec0, 0x0efd: 0x3ec4, 0x0efe: 0x3ec9, 0x0eff: 0x3ecd,
// Block 0x3c, offset 0xf00
- 0x0f09: 0x1599,
- 0x0f1a: 0x159f, 0x0f1b: 0x15a5,
- 0x0f2e: 0x15ab,
+ 0x0f00: 0x3ed1, 0x0f01: 0x3ed5, 0x0f02: 0x3ed9, 0x0f03: 0x3edd, 0x0f04: 0x3ee1, 0x0f05: 0x3ee5,
+ 0x0f06: 0x3ee9, 0x0f07: 0x3eed, 0x0f08: 0x3ef1, 0x0f09: 0x3ef5, 0x0f0a: 0x3efa, 0x0f0b: 0x3efe,
+ 0x0f0c: 0x3f02, 0x0f0d: 0x3f06, 0x0f0e: 0x2b11, 0x0f0f: 0x3f0a, 0x0f10: 0x18fe, 0x0f11: 0x3f0f,
+ 0x0f12: 0x3f0f, 0x0f13: 0x3f14, 0x0f14: 0x3f18, 0x0f15: 0x3f18, 0x0f16: 0x3f1c, 0x0f17: 0x3f20,
+ 0x0f18: 0x3f25, 0x0f19: 0x3f2a, 0x0f1a: 0x3f2e, 0x0f1b: 0x3f32, 0x0f1c: 0x3f36, 0x0f1d: 0x3f3a,
+ 0x0f1e: 0x3f3e, 0x0f1f: 0x3f42, 0x0f20: 0x3f46, 0x0f21: 0x3f4a, 0x0f22: 0x3f4e, 0x0f23: 0x2ee5,
+ 0x0f24: 0x3f52, 0x0f25: 0x3f57, 0x0f26: 0x3f5b, 0x0f27: 0x3f5f, 0x0f28: 0x2fea, 0x0f29: 0x3f5f,
+ 0x0f2a: 0x3f63, 0x0f2b: 0x2eed, 0x0f2c: 0x3f67, 0x0f2d: 0x3f6b, 0x0f2e: 0x3f6f, 0x0f2f: 0x3f73,
+ 0x0f30: 0x2ef1, 0x0f31: 0x2aa5, 0x0f32: 0x3f77, 0x0f33: 0x3f7b, 0x0f34: 0x3f7f, 0x0f35: 0x3f83,
+ 0x0f36: 0x3f87, 0x0f37: 0x3f8b, 0x0f38: 0x3f8f, 0x0f39: 0x3f94, 0x0f3a: 0x3f98, 0x0f3b: 0x3f9c,
+ 0x0f3c: 0x3fa0, 0x0f3d: 0x3fa4, 0x0f3e: 0x3fa8, 0x0f3f: 0x3fad,
// Block 0x3d, offset 0xf40
- 0x0f4d: 0x15b1, 0x0f4e: 0x15b7, 0x0f4f: 0x15bd,
+ 0x0f40: 0x3fb1, 0x0f41: 0x3fb5, 0x0f42: 0x3fb9, 0x0f43: 0x3fbd, 0x0f44: 0x3fc1, 0x0f45: 0x3fc5,
+ 0x0f46: 0x3fc9, 0x0f47: 0x3fcd, 0x0f48: 0x2ef5, 0x0f49: 0x3fd1, 0x0f4a: 0x3fd5, 0x0f4b: 0x3fda,
+ 0x0f4c: 0x3fde, 0x0f4d: 0x3fe2, 0x0f4e: 0x3fe6, 0x0f4f: 0x2efd, 0x0f50: 0x3fea, 0x0f51: 0x3fee,
+ 0x0f52: 0x3ff2, 0x0f53: 0x3ff6, 0x0f54: 0x3ffa, 0x0f55: 0x3ffe, 0x0f56: 0x4002, 0x0f57: 0x4006,
+ 0x0f58: 0x2b15, 0x0f59: 0x300a, 0x0f5a: 0x400a, 0x0f5b: 0x400e, 0x0f5c: 0x4012, 0x0f5d: 0x4016,
+ 0x0f5e: 0x401b, 0x0f5f: 0x401f, 0x0f60: 0x4023, 0x0f61: 0x4027, 0x0f62: 0x2f01, 0x0f63: 0x402b,
+ 0x0f64: 0x4030, 0x0f65: 0x4034, 0x0f66: 0x4038, 0x0f67: 0x30b5, 0x0f68: 0x403c, 0x0f69: 0x4040,
+ 0x0f6a: 0x4044, 0x0f6b: 0x4048, 0x0f6c: 0x404c, 0x0f6d: 0x4051, 0x0f6e: 0x4055, 0x0f6f: 0x4059,
+ 0x0f70: 0x405d, 0x0f71: 0x4062, 0x0f72: 0x4066, 0x0f73: 0x406a, 0x0f74: 0x406e, 0x0f75: 0x2c25,
+ 0x0f76: 0x4072, 0x0f77: 0x4076, 0x0f78: 0x407b, 0x0f79: 0x4080, 0x0f7a: 0x4085, 0x0f7b: 0x4089,
+ 0x0f7c: 0x408e, 0x0f7d: 0x4092, 0x0f7e: 0x4096, 0x0f7f: 0x409a,
// Block 0x3e, offset 0xf80
- 0x0f84: 0x15c3,
- 0x0f89: 0x15c9,
- 0x0f8c: 0x15cf,
- 0x0fa4: 0x15d5, 0x0fa6: 0x15db,
- 0x0fac: 0x15e1, 0x0fad: 0x15e8, 0x0faf: 0x15f2,
- 0x0fb0: 0x15f9,
+ 0x0f80: 0x409e, 0x0f81: 0x2f05, 0x0f82: 0x2d71, 0x0f83: 0x40a2, 0x0f84: 0x40a6, 0x0f85: 0x40aa,
+ 0x0f86: 0x40ae, 0x0f87: 0x40b3, 0x0f88: 0x40b7, 0x0f89: 0x40bb, 0x0f8a: 0x40bf, 0x0f8b: 0x3016,
+ 0x0f8c: 0x40c3, 0x0f8d: 0x40c7, 0x0f8e: 0x40cc, 0x0f8f: 0x40d0, 0x0f90: 0x40d4, 0x0f91: 0x40d9,
+ 0x0f92: 0x40de, 0x0f93: 0x40e2, 0x0f94: 0x301a, 0x0f95: 0x40e6, 0x0f96: 0x40ea, 0x0f97: 0x40ee,
+ 0x0f98: 0x40f2, 0x0f99: 0x40f6, 0x0f9a: 0x40fa, 0x0f9b: 0x40fe, 0x0f9c: 0x4103, 0x0f9d: 0x4107,
+ 0x0f9e: 0x410c, 0x0f9f: 0x4110, 0x0fa0: 0x4115, 0x0fa1: 0x3022, 0x0fa2: 0x4119, 0x0fa3: 0x411d,
+ 0x0fa4: 0x4122, 0x0fa5: 0x4126, 0x0fa6: 0x412a, 0x0fa7: 0x412f, 0x0fa8: 0x4134, 0x0fa9: 0x4138,
+ 0x0faa: 0x413c, 0x0fab: 0x4140, 0x0fac: 0x4144, 0x0fad: 0x4144, 0x0fae: 0x4148, 0x0faf: 0x414c,
+ 0x0fb0: 0x302a, 0x0fb1: 0x4150, 0x0fb2: 0x4154, 0x0fb3: 0x4158, 0x0fb4: 0x415c, 0x0fb5: 0x4160,
+ 0x0fb6: 0x4165, 0x0fb7: 0x4169, 0x0fb8: 0x2bed, 0x0fb9: 0x416e, 0x0fba: 0x4173, 0x0fbb: 0x4177,
+ 0x0fbc: 0x417c, 0x0fbd: 0x4181, 0x0fbe: 0x4186, 0x0fbf: 0x418a,
// Block 0x3f, offset 0xfc0
- 0x0fc1: 0x1603, 0x0fc4: 0x1609,
- 0x0fc7: 0x160f, 0x0fc9: 0x1615,
- 0x0fe0: 0x161b, 0x0fe2: 0x161f,
- 0x0fed: 0x1625, 0x0fee: 0x162b, 0x0fef: 0x162f,
- 0x0ff0: 0x1633, 0x0ff1: 0x1639, 0x0ff4: 0x163f, 0x0ff5: 0x1645,
- 0x0ff8: 0x164b, 0x0ff9: 0x1651,
+ 0x0fc0: 0x3042, 0x0fc1: 0x418e, 0x0fc2: 0x4193, 0x0fc3: 0x4198, 0x0fc4: 0x419d, 0x0fc5: 0x41a2,
+ 0x0fc6: 0x41a6, 0x0fc7: 0x41a6, 0x0fc8: 0x3046, 0x0fc9: 0x30bd, 0x0fca: 0x41aa, 0x0fcb: 0x41ae,
+ 0x0fcc: 0x41b2, 0x0fcd: 0x41b6, 0x0fce: 0x41bb, 0x0fcf: 0x2b59, 0x0fd0: 0x304e, 0x0fd1: 0x41bf,
+ 0x0fd2: 0x41c3, 0x0fd3: 0x2f2d, 0x0fd4: 0x41c8, 0x0fd5: 0x41cd, 0x0fd6: 0x2e89, 0x0fd7: 0x41d2,
+ 0x0fd8: 0x41d6, 0x0fd9: 0x2f39, 0x0fda: 0x41da, 0x0fdb: 0x41de, 0x0fdc: 0x41e2, 0x0fdd: 0x41e7,
+ 0x0fde: 0x41e7, 0x0fdf: 0x41ec, 0x0fe0: 0x41f0, 0x0fe1: 0x41f4, 0x0fe2: 0x41f9, 0x0fe3: 0x41fd,
+ 0x0fe4: 0x4201, 0x0fe5: 0x4205, 0x0fe6: 0x420a, 0x0fe7: 0x420e, 0x0fe8: 0x4212, 0x0fe9: 0x4216,
+ 0x0fea: 0x421a, 0x0feb: 0x421e, 0x0fec: 0x4223, 0x0fed: 0x4227, 0x0fee: 0x422b, 0x0fef: 0x422f,
+ 0x0ff0: 0x4233, 0x0ff1: 0x4237, 0x0ff2: 0x423b, 0x0ff3: 0x4240, 0x0ff4: 0x4245, 0x0ff5: 0x4249,
+ 0x0ff6: 0x424e, 0x0ff7: 0x4252, 0x0ff8: 0x4257, 0x0ff9: 0x425b, 0x0ffa: 0x2f51, 0x0ffb: 0x425f,
+ 0x0ffc: 0x4264, 0x0ffd: 0x4269, 0x0ffe: 0x426d, 0x0fff: 0x4272,
// Block 0x40, offset 0x1000
- 0x1000: 0x1657, 0x1001: 0x165d, 0x1004: 0x1663, 0x1005: 0x1669,
- 0x1008: 0x166f, 0x1009: 0x1675,
- 0x102c: 0x167b, 0x102d: 0x1681, 0x102e: 0x1687, 0x102f: 0x168d,
+ 0x1000: 0x4276, 0x1001: 0x427b, 0x1002: 0x427f, 0x1003: 0x4283, 0x1004: 0x4287, 0x1005: 0x428b,
+ 0x1006: 0x428f, 0x1007: 0x4293, 0x1008: 0x4298, 0x1009: 0x429d, 0x100a: 0x42a2, 0x100b: 0x3f14,
+ 0x100c: 0x42a7, 0x100d: 0x42ab, 0x100e: 0x42af, 0x100f: 0x42b3, 0x1010: 0x42b7, 0x1011: 0x42bb,
+ 0x1012: 0x42bf, 0x1013: 0x42c3, 0x1014: 0x42c7, 0x1015: 0x42cb, 0x1016: 0x42cf, 0x1017: 0x42d3,
+ 0x1018: 0x2c31, 0x1019: 0x42d8, 0x101a: 0x42dc, 0x101b: 0x42e0, 0x101c: 0x42e4, 0x101d: 0x42e8,
+ 0x101e: 0x42ec, 0x101f: 0x2f5d, 0x1020: 0x42f0, 0x1021: 0x42f4, 0x1022: 0x42f8, 0x1023: 0x42fc,
+ 0x1024: 0x4300, 0x1025: 0x4305, 0x1026: 0x430a, 0x1027: 0x430f, 0x1028: 0x4313, 0x1029: 0x4317,
+ 0x102a: 0x431b, 0x102b: 0x431f, 0x102c: 0x4324, 0x102d: 0x4328, 0x102e: 0x432d, 0x102f: 0x4331,
+ 0x1030: 0x4335, 0x1031: 0x433a, 0x1032: 0x433f, 0x1033: 0x4343, 0x1034: 0x2b45, 0x1035: 0x4347,
+ 0x1036: 0x434b, 0x1037: 0x434f, 0x1038: 0x4353, 0x1039: 0x4357, 0x103a: 0x435b, 0x103b: 0x306a,
+ 0x103c: 0x435f, 0x103d: 0x4363, 0x103e: 0x4367, 0x103f: 0x436b,
// Block 0x41, offset 0x1040
- 0x1060: 0x1693, 0x1061: 0x1699, 0x1062: 0x169f, 0x1063: 0x16a5,
- 0x106a: 0x16ab, 0x106b: 0x16b1, 0x106c: 0x16b7, 0x106d: 0x16bd,
- // Block 0x42, offset 0x1080
- 0x10a9: 0x16c3,
- 0x10aa: 0x16c7,
- // Block 0x43, offset 0x10c0
- 0x10e0: 0x001c, 0x10e1: 0x000d, 0x10e2: 0x000f, 0x10e3: 0x1488,
- 0x10e4: 0x148a, 0x10e5: 0x148c, 0x10e6: 0x148e, 0x10e7: 0x1490, 0x10e8: 0x1492, 0x10e9: 0x16cb,
- 0x10ea: 0x16ce, 0x10eb: 0x16d1, 0x10ec: 0x16d4, 0x10ed: 0x16d7, 0x10ee: 0x16da, 0x10ef: 0x16dd,
- 0x10f0: 0x16e0, 0x10f1: 0x16e3, 0x10f2: 0x16e6, 0x10f3: 0x16e9, 0x10f4: 0x16ec, 0x10f5: 0x16f0,
- 0x10f6: 0x16f4, 0x10f7: 0x16f8, 0x10f8: 0x16fc, 0x10f9: 0x1700, 0x10fa: 0x1704, 0x10fb: 0x1708,
- 0x10fc: 0x170c, 0x10fd: 0x1710, 0x10fe: 0x1715, 0x10ff: 0x171a,
- // Block 0x44, offset 0x1100
- 0x1100: 0x171f, 0x1101: 0x1724, 0x1102: 0x1729, 0x1103: 0x172e, 0x1104: 0x1733, 0x1105: 0x1738,
- 0x1106: 0x173d, 0x1107: 0x1742, 0x1108: 0x1747, 0x1109: 0x174a, 0x110a: 0x174d, 0x110b: 0x1750,
- 0x110c: 0x1753, 0x110d: 0x1756, 0x110e: 0x1759, 0x110f: 0x175c, 0x1110: 0x175f, 0x1111: 0x1762,
- 0x1112: 0x1766, 0x1113: 0x176a, 0x1114: 0x176e, 0x1115: 0x1772, 0x1116: 0x1776, 0x1117: 0x177a,
- 0x1118: 0x177e, 0x1119: 0x1782, 0x111a: 0x1786, 0x111b: 0x178a, 0x111c: 0x178e, 0x111d: 0x1792,
- 0x111e: 0x1796, 0x111f: 0x179a, 0x1120: 0x179e, 0x1121: 0x17a2, 0x1122: 0x17a6, 0x1123: 0x17aa,
- 0x1124: 0x17ae, 0x1125: 0x17b2, 0x1126: 0x17b6, 0x1127: 0x17ba, 0x1128: 0x17be, 0x1129: 0x17c2,
- 0x112a: 0x17c6, 0x112b: 0x17ca, 0x112c: 0x17ce, 0x112d: 0x17d2, 0x112e: 0x17d6, 0x112f: 0x17da,
- 0x1130: 0x17de, 0x1131: 0x17e2, 0x1132: 0x17e6, 0x1133: 0x17ea, 0x1134: 0x17ee, 0x1135: 0x17f2,
- 0x1136: 0x0906, 0x1137: 0x090b, 0x1138: 0x14ad, 0x1139: 0x090d, 0x113a: 0x090f, 0x113b: 0x14d9,
- 0x113c: 0x0914, 0x113d: 0x0916, 0x113e: 0x0918, 0x113f: 0x091a,
- // Block 0x45, offset 0x1140
- 0x1140: 0x091c, 0x1141: 0x091e, 0x1142: 0x0920, 0x1143: 0x0922, 0x1144: 0x0924, 0x1145: 0x0929,
- 0x1146: 0x14c8, 0x1147: 0x092b, 0x1148: 0x17f6, 0x1149: 0x092d, 0x114a: 0x092f, 0x114b: 0x155f,
- 0x114c: 0x0931, 0x114d: 0x1570, 0x114e: 0x17f8, 0x114f: 0x14d4, 0x1150: 0x0007, 0x1151: 0x093d,
- 0x1152: 0x0984, 0x1153: 0x093f, 0x1154: 0x0941, 0x1155: 0x098c, 0x1156: 0x094c, 0x1157: 0x0494,
- 0x1158: 0x097c, 0x1159: 0x0499, 0x115a: 0x094e, 0x115b: 0x04c5, 0x115c: 0x0950, 0x115d: 0x14a0,
- 0x115e: 0x001e, 0x115f: 0x0960, 0x1160: 0x17fa, 0x1161: 0x049b, 0x1162: 0x02c8, 0x1163: 0x0962,
- 0x1164: 0x0964, 0x1165: 0x096d, 0x1166: 0x04a6, 0x1167: 0x04c7, 0x1168: 0x04a8, 0x1169: 0x09df,
- 0x116a: 0x1486,
- // Block 0x46, offset 0x1180
- 0x118c: 0x17fc,
- // Block 0x47, offset 0x11c0
- 0x11f4: 0x1809, 0x11f5: 0x180d,
- 0x11f6: 0x1810,
- // Block 0x48, offset 0x1200
- 0x121c: 0x1814,
- // Block 0x49, offset 0x1240
- 0x127c: 0x0499, 0x127d: 0x155f,
- // Block 0x4a, offset 0x1280
- 0x12af: 0x181a,
- // Block 0x4b, offset 0x12c0
- 0x12df: 0x181e,
- // Block 0x4c, offset 0x1300
- 0x1333: 0x1822,
- // Block 0x4d, offset 0x1340
- 0x1340: 0x1826, 0x1341: 0x182a, 0x1342: 0x182e, 0x1343: 0x1832, 0x1344: 0x1836, 0x1345: 0x183a,
- 0x1346: 0x183e, 0x1347: 0x1842, 0x1348: 0x1846, 0x1349: 0x184a, 0x134a: 0x184e, 0x134b: 0x1852,
- 0x134c: 0x1856, 0x134d: 0x185a, 0x134e: 0x185e, 0x134f: 0x1862, 0x1350: 0x1866, 0x1351: 0x186a,
- 0x1352: 0x186e, 0x1353: 0x1872, 0x1354: 0x1876, 0x1355: 0x187a, 0x1356: 0x187e, 0x1357: 0x1882,
- 0x1358: 0x1886, 0x1359: 0x188a, 0x135a: 0x188e, 0x135b: 0x1892, 0x135c: 0x1896, 0x135d: 0x189a,
- 0x135e: 0x189e, 0x135f: 0x18a2, 0x1360: 0x18a6, 0x1361: 0x18aa, 0x1362: 0x18ae, 0x1363: 0x18b2,
- 0x1364: 0x18b6, 0x1365: 0x18ba, 0x1366: 0x18be, 0x1367: 0x18c2, 0x1368: 0x18c6, 0x1369: 0x18ca,
- 0x136a: 0x18ce, 0x136b: 0x18d2, 0x136c: 0x18d6, 0x136d: 0x18da, 0x136e: 0x18de, 0x136f: 0x18e2,
- 0x1370: 0x18e6, 0x1371: 0x18ea, 0x1372: 0x18ee, 0x1373: 0x18f2, 0x1374: 0x18f6, 0x1375: 0x18fa,
- 0x1376: 0x18fe, 0x1377: 0x1902, 0x1378: 0x1906, 0x1379: 0x190a, 0x137a: 0x190e, 0x137b: 0x1912,
- 0x137c: 0x1916, 0x137d: 0x191a, 0x137e: 0x191e, 0x137f: 0x1922,
- // Block 0x4e, offset 0x1380
- 0x1380: 0x1926, 0x1381: 0x192a, 0x1382: 0x192e, 0x1383: 0x1932, 0x1384: 0x1936, 0x1385: 0x193a,
- 0x1386: 0x193e, 0x1387: 0x1942, 0x1388: 0x1946, 0x1389: 0x194a, 0x138a: 0x194e, 0x138b: 0x1952,
- 0x138c: 0x1956, 0x138d: 0x195a, 0x138e: 0x195e, 0x138f: 0x1962, 0x1390: 0x1966, 0x1391: 0x196a,
- 0x1392: 0x196e, 0x1393: 0x1972, 0x1394: 0x1976, 0x1395: 0x197a, 0x1396: 0x197e, 0x1397: 0x1982,
- 0x1398: 0x1986, 0x1399: 0x198a, 0x139a: 0x198e, 0x139b: 0x1992, 0x139c: 0x1996, 0x139d: 0x199a,
- 0x139e: 0x199e, 0x139f: 0x19a2, 0x13a0: 0x19a6, 0x13a1: 0x19aa, 0x13a2: 0x19ae, 0x13a3: 0x19b2,
- 0x13a4: 0x19b6, 0x13a5: 0x19ba, 0x13a6: 0x19be, 0x13a7: 0x19c2, 0x13a8: 0x19c6, 0x13a9: 0x19ca,
- 0x13aa: 0x19ce, 0x13ab: 0x19d2, 0x13ac: 0x19d6, 0x13ad: 0x19da, 0x13ae: 0x19de, 0x13af: 0x19e2,
- 0x13b0: 0x19e6, 0x13b1: 0x19ea, 0x13b2: 0x19ee, 0x13b3: 0x19f2, 0x13b4: 0x19f6, 0x13b5: 0x19fa,
- 0x13b6: 0x19fe, 0x13b7: 0x1a02, 0x13b8: 0x1a06, 0x13b9: 0x1a0a, 0x13ba: 0x1a0e, 0x13bb: 0x1a12,
- 0x13bc: 0x1a16, 0x13bd: 0x1a1a, 0x13be: 0x1a1e, 0x13bf: 0x1a22,
- // Block 0x4f, offset 0x13c0
- 0x13c0: 0x1a26, 0x13c1: 0x1a2a, 0x13c2: 0x1a2e, 0x13c3: 0x1a32, 0x13c4: 0x1a36, 0x13c5: 0x1a3a,
- 0x13c6: 0x1a3e, 0x13c7: 0x1a42, 0x13c8: 0x1a46, 0x13c9: 0x1a4a, 0x13ca: 0x1a4e, 0x13cb: 0x1a52,
- 0x13cc: 0x1a56, 0x13cd: 0x1a5a, 0x13ce: 0x1a5e, 0x13cf: 0x1a62, 0x13d0: 0x1a66, 0x13d1: 0x1a6a,
- 0x13d2: 0x1a6e, 0x13d3: 0x1a72, 0x13d4: 0x1a76, 0x13d5: 0x1a7a, 0x13d6: 0x1a7e, 0x13d7: 0x1a82,
- 0x13d8: 0x1a86, 0x13d9: 0x1a8a, 0x13da: 0x1a8e, 0x13db: 0x1a92, 0x13dc: 0x1a96, 0x13dd: 0x1a9a,
- 0x13de: 0x1a9e, 0x13df: 0x1aa2, 0x13e0: 0x1aa6, 0x13e1: 0x1aaa, 0x13e2: 0x1aae, 0x13e3: 0x1ab2,
- 0x13e4: 0x1ab6, 0x13e5: 0x1aba, 0x13e6: 0x1abe, 0x13e7: 0x1ac2, 0x13e8: 0x1ac6, 0x13e9: 0x1aca,
- 0x13ea: 0x1ace, 0x13eb: 0x1ad2, 0x13ec: 0x1ad6, 0x13ed: 0x1ada, 0x13ee: 0x1ade, 0x13ef: 0x1ae2,
- 0x13f0: 0x1ae6, 0x13f1: 0x1aea, 0x13f2: 0x1aee, 0x13f3: 0x1af2, 0x13f4: 0x1af6, 0x13f5: 0x1afa,
- 0x13f6: 0x1afe, 0x13f7: 0x1b02, 0x13f8: 0x1b06, 0x13f9: 0x1b0a, 0x13fa: 0x1b0e, 0x13fb: 0x1b12,
- 0x13fc: 0x1b16, 0x13fd: 0x1b1a, 0x13fe: 0x1b1e, 0x13ff: 0x1b22,
- // Block 0x50, offset 0x1400
- 0x1400: 0x1b26, 0x1401: 0x1b2a, 0x1402: 0x1b2e, 0x1403: 0x1b32, 0x1404: 0x1b36, 0x1405: 0x1b3a,
- 0x1406: 0x1b3e, 0x1407: 0x1b42, 0x1408: 0x1b46, 0x1409: 0x1b4a, 0x140a: 0x1b4e, 0x140b: 0x1b52,
- 0x140c: 0x1b56, 0x140d: 0x1b5a, 0x140e: 0x1b5e, 0x140f: 0x1b62, 0x1410: 0x1b66, 0x1411: 0x1b6a,
- 0x1412: 0x1b6e, 0x1413: 0x1b72, 0x1414: 0x1b76, 0x1415: 0x1b7a,
- // Block 0x51, offset 0x1440
- 0x1440: 0x0001,
- 0x1476: 0x1b7e, 0x1478: 0x1882, 0x1479: 0x1b82, 0x147a: 0x1b86,
- // Block 0x52, offset 0x1480
- 0x148c: 0x1b8a, 0x148e: 0x1b91, 0x1490: 0x1b98,
- 0x1492: 0x1b9f, 0x1494: 0x1ba6, 0x1496: 0x1bad,
- 0x1498: 0x1bb4, 0x149a: 0x1bbb, 0x149c: 0x1bc2,
- 0x149e: 0x1bc9, 0x14a0: 0x1bd0, 0x14a2: 0x1bd7,
- 0x14a5: 0x1bde, 0x14a7: 0x1be5, 0x14a9: 0x1bec,
- 0x14b0: 0x1bf3, 0x14b1: 0x1bfa, 0x14b3: 0x1c01, 0x14b4: 0x1c08,
- 0x14b6: 0x1c0f, 0x14b7: 0x1c16, 0x14b9: 0x1c1d, 0x14ba: 0x1c24,
- 0x14bc: 0x1c2b, 0x14bd: 0x1c32,
- // Block 0x53, offset 0x14c0
- 0x14d4: 0x1c39,
- 0x14db: 0x1c40, 0x14dc: 0x1c45,
- 0x14de: 0x1c4a, 0x14df: 0x1c51,
- 0x14ec: 0x1c58, 0x14ee: 0x1c5f,
- 0x14f0: 0x1c66, 0x14f2: 0x1c6d, 0x14f4: 0x1c74,
- 0x14f6: 0x1c7b, 0x14f8: 0x1c82, 0x14fa: 0x1c89,
- 0x14fc: 0x1c90, 0x14fe: 0x1c97,
- // Block 0x54, offset 0x1500
- 0x1500: 0x1c9e, 0x1502: 0x1ca5, 0x1505: 0x1cac,
- 0x1507: 0x1cb3, 0x1509: 0x1cba,
- 0x1510: 0x1cc1, 0x1511: 0x1cc8,
- 0x1513: 0x1ccf, 0x1514: 0x1cd6, 0x1516: 0x1cdd, 0x1517: 0x1ce4,
- 0x1519: 0x1ceb, 0x151a: 0x1cf2, 0x151c: 0x1cf9, 0x151d: 0x1d00,
- 0x1534: 0x1d07,
- 0x1537: 0x1d0e, 0x1538: 0x1d15, 0x1539: 0x1d1c, 0x153a: 0x1d23,
- 0x153e: 0x1d2a, 0x153f: 0x1d31,
- // Block 0x55, offset 0x1540
- 0x1571: 0x1d38, 0x1572: 0x1d3c, 0x1573: 0x1d40, 0x1574: 0x1d44, 0x1575: 0x1d48,
- 0x1576: 0x1d4c, 0x1577: 0x1d50, 0x1578: 0x1d54, 0x1579: 0x1d58, 0x157a: 0x1d5c, 0x157b: 0x1d60,
- 0x157c: 0x1d64, 0x157d: 0x1d68, 0x157e: 0x1d6c, 0x157f: 0x1d70,
- // Block 0x56, offset 0x1580
- 0x1580: 0x1d74, 0x1581: 0x1d78, 0x1582: 0x1d7c, 0x1583: 0x1d80, 0x1584: 0x1d84, 0x1585: 0x1d88,
- 0x1586: 0x1d8c, 0x1587: 0x1d90, 0x1588: 0x1d94, 0x1589: 0x1d98, 0x158a: 0x1d9c, 0x158b: 0x1da0,
- 0x158c: 0x1da4, 0x158d: 0x1da8, 0x158e: 0x1dac, 0x158f: 0x1db0, 0x1590: 0x1db4, 0x1591: 0x1db8,
- 0x1592: 0x1dbc, 0x1593: 0x1dc0, 0x1594: 0x1dc4, 0x1595: 0x1dc8, 0x1596: 0x1dcc, 0x1597: 0x1dd0,
- 0x1598: 0x1dd4, 0x1599: 0x1dd8, 0x159a: 0x1ddc, 0x159b: 0x1de0, 0x159c: 0x1de4, 0x159d: 0x1de8,
- 0x159e: 0x1dec, 0x159f: 0x1df0, 0x15a0: 0x1df4, 0x15a1: 0x1df8, 0x15a2: 0x1dfc, 0x15a3: 0x1e00,
- 0x15a4: 0x1e04, 0x15a5: 0x1e08, 0x15a6: 0x1e0c, 0x15a7: 0x1e10, 0x15a8: 0x1e14, 0x15a9: 0x1e18,
- 0x15aa: 0x1e1c, 0x15ab: 0x1e20, 0x15ac: 0x1e24, 0x15ad: 0x1e28, 0x15ae: 0x1e2c, 0x15af: 0x1e30,
- 0x15b0: 0x1e34, 0x15b1: 0x1e38, 0x15b2: 0x1e3c, 0x15b3: 0x1e40, 0x15b4: 0x1e44, 0x15b5: 0x1e48,
- 0x15b6: 0x1e4c, 0x15b7: 0x1e50, 0x15b8: 0x1e54, 0x15b9: 0x1e58, 0x15ba: 0x1e5c, 0x15bb: 0x1e60,
- 0x15bc: 0x1e64, 0x15bd: 0x1e68, 0x15be: 0x1e6c, 0x15bf: 0x1e70,
- // Block 0x57, offset 0x15c0
- 0x15c0: 0x1e74, 0x15c1: 0x1e78, 0x15c2: 0x1e7c, 0x15c3: 0x1e80, 0x15c4: 0x1e84, 0x15c5: 0x1e88,
- 0x15c6: 0x1e8c, 0x15c7: 0x1e90, 0x15c8: 0x1e94, 0x15c9: 0x1e98, 0x15ca: 0x1e9c, 0x15cb: 0x1ea0,
- 0x15cc: 0x1ea4, 0x15cd: 0x1ea8, 0x15ce: 0x1eac,
- 0x15d2: 0x1826, 0x15d3: 0x183e, 0x15d4: 0x1eb0, 0x15d5: 0x1eb4, 0x15d6: 0x1eb8, 0x15d7: 0x1ebc,
- 0x15d8: 0x1ec0, 0x15d9: 0x1ec4, 0x15da: 0x1836, 0x15db: 0x1ec8, 0x15dc: 0x1ecc, 0x15dd: 0x1ed0,
- 0x15de: 0x1ed4, 0x15df: 0x1846,
- // Block 0x58, offset 0x1600
- 0x1600: 0x1ed8, 0x1601: 0x1ede, 0x1602: 0x1ee4, 0x1603: 0x1eea, 0x1604: 0x1ef0, 0x1605: 0x1ef6,
- 0x1606: 0x1efc, 0x1607: 0x1f02, 0x1608: 0x1f08, 0x1609: 0x1f0e, 0x160a: 0x1f14, 0x160b: 0x1f1a,
- 0x160c: 0x1f20, 0x160d: 0x1f26, 0x160e: 0x1f2c, 0x160f: 0x1f35, 0x1610: 0x1f3e, 0x1611: 0x1f47,
- 0x1612: 0x1f50, 0x1613: 0x1f59, 0x1614: 0x1f62, 0x1615: 0x1f6b, 0x1616: 0x1f74, 0x1617: 0x1f7d,
- 0x1618: 0x1f86, 0x1619: 0x1f8f, 0x161a: 0x1f98, 0x161b: 0x1fa1, 0x161c: 0x1faa, 0x161d: 0x1fb3,
- 0x161e: 0x1fc5, 0x1620: 0x1fd4, 0x1621: 0x1fda, 0x1622: 0x1fe0, 0x1623: 0x1fe6,
- 0x1624: 0x1fec, 0x1625: 0x1ff2, 0x1626: 0x1ff8, 0x1627: 0x1ffe, 0x1628: 0x2004, 0x1629: 0x200a,
- 0x162a: 0x2010, 0x162b: 0x2016, 0x162c: 0x201c, 0x162d: 0x2022, 0x162e: 0x2028, 0x162f: 0x202e,
- 0x1630: 0x2034, 0x1631: 0x203a, 0x1632: 0x2040, 0x1633: 0x2046, 0x1634: 0x204c, 0x1635: 0x2052,
- 0x1636: 0x2058, 0x1637: 0x205e, 0x1638: 0x2064, 0x1639: 0x206a, 0x163a: 0x2070, 0x163b: 0x2076,
- 0x163c: 0x207c, 0x163d: 0x2082, 0x163e: 0x2088, 0x163f: 0x208e,
- // Block 0x59, offset 0x1640
- 0x1640: 0x2094, 0x1641: 0x209a, 0x1642: 0x20a0, 0x1643: 0x20a6, 0x1644: 0x20ac, 0x1645: 0x20b0,
- 0x1646: 0x192e, 0x1647: 0x20b4,
- 0x1650: 0x20b8, 0x1651: 0x20bc,
- 0x1652: 0x20bf, 0x1653: 0x20c2, 0x1654: 0x20c5, 0x1655: 0x20c8, 0x1656: 0x20cb, 0x1657: 0x20ce,
- 0x1658: 0x20d1, 0x1659: 0x20d4, 0x165a: 0x20d7, 0x165b: 0x20da, 0x165c: 0x20dd, 0x165d: 0x20e0,
- 0x165e: 0x20e3, 0x165f: 0x20e6, 0x1660: 0x1d38, 0x1661: 0x1d44, 0x1662: 0x1d50, 0x1663: 0x1d58,
- 0x1664: 0x1d78, 0x1665: 0x1d7c, 0x1666: 0x1d88, 0x1667: 0x1d90, 0x1668: 0x1d94, 0x1669: 0x1d9c,
- 0x166a: 0x1da0, 0x166b: 0x1da4, 0x166c: 0x1da8, 0x166d: 0x1dac, 0x166e: 0x20e9, 0x166f: 0x20f0,
- 0x1670: 0x20f7, 0x1671: 0x20fe, 0x1672: 0x2105, 0x1673: 0x210c, 0x1674: 0x2113, 0x1675: 0x211a,
- 0x1676: 0x2121, 0x1677: 0x2128, 0x1678: 0x212f, 0x1679: 0x2136, 0x167a: 0x213d, 0x167b: 0x2144,
- 0x167c: 0x214b, 0x167d: 0x215b, 0x167e: 0x2168,
- // Block 0x5a, offset 0x1680
- 0x1680: 0x1826, 0x1681: 0x183e, 0x1682: 0x1eb0, 0x1683: 0x1eb4, 0x1684: 0x216f, 0x1685: 0x2173,
- 0x1686: 0x2177, 0x1687: 0x1852, 0x1688: 0x217b, 0x1689: 0x1882, 0x168a: 0x194a, 0x168b: 0x197a,
- 0x168c: 0x1976, 0x168d: 0x194e, 0x168e: 0x1abe, 0x168f: 0x18a2, 0x1690: 0x1942, 0x1691: 0x217f,
- 0x1692: 0x2183, 0x1693: 0x2187, 0x1694: 0x218b, 0x1695: 0x218f, 0x1696: 0x2193, 0x1697: 0x2197,
- 0x1698: 0x219b, 0x1699: 0x219f, 0x169a: 0x21a3, 0x169b: 0x18ba, 0x169c: 0x21a7, 0x169d: 0x21ab,
- 0x169e: 0x21af, 0x169f: 0x21b3, 0x16a0: 0x21b7, 0x16a1: 0x21bb, 0x16a2: 0x21bf, 0x16a3: 0x21c3,
- 0x16a4: 0x1eb8, 0x16a5: 0x1ebc, 0x16a6: 0x1ec0, 0x16a7: 0x21c7, 0x16a8: 0x21cb, 0x16a9: 0x21cf,
- 0x16aa: 0x21d3, 0x16ab: 0x21d7, 0x16ac: 0x21db, 0x16ad: 0x21df, 0x16ae: 0x21e3, 0x16af: 0x21e7,
- 0x16b0: 0x21eb, 0x16b1: 0x21ef, 0x16b2: 0x21f2, 0x16b3: 0x21f5, 0x16b4: 0x21f8, 0x16b5: 0x21fb,
- 0x16b6: 0x21fe, 0x16b7: 0x2201, 0x16b8: 0x2204, 0x16b9: 0x2207, 0x16ba: 0x220a, 0x16bb: 0x220d,
- 0x16bc: 0x2210, 0x16bd: 0x2213, 0x16be: 0x2216, 0x16bf: 0x2219,
- // Block 0x5b, offset 0x16c0
- 0x16c0: 0x221c, 0x16c1: 0x2221, 0x16c2: 0x2226, 0x16c3: 0x222b, 0x16c4: 0x2230, 0x16c5: 0x2235,
- 0x16c6: 0x223a, 0x16c7: 0x223f, 0x16c8: 0x2244, 0x16c9: 0x2249, 0x16ca: 0x224f, 0x16cb: 0x2255,
- 0x16cc: 0x225b, 0x16cd: 0x225e, 0x16ce: 0x2262, 0x16cf: 0x2265, 0x16d0: 0x2269, 0x16d1: 0x226d,
- 0x16d2: 0x2271, 0x16d3: 0x2275, 0x16d4: 0x2279, 0x16d5: 0x227d, 0x16d6: 0x2281, 0x16d7: 0x2285,
- 0x16d8: 0x2289, 0x16d9: 0x228d, 0x16da: 0x2291, 0x16db: 0x2295, 0x16dc: 0x2299, 0x16dd: 0x229d,
- 0x16de: 0x22a1, 0x16df: 0x22a5, 0x16e0: 0x22a9, 0x16e1: 0x22ad, 0x16e2: 0x22b1, 0x16e3: 0x22b5,
- 0x16e4: 0x22b9, 0x16e5: 0x22bd, 0x16e6: 0x22c1, 0x16e7: 0x22c5, 0x16e8: 0x22c9, 0x16e9: 0x22cd,
- 0x16ea: 0x22d1, 0x16eb: 0x22d5, 0x16ec: 0x22d9, 0x16ed: 0x22dd, 0x16ee: 0x22e1, 0x16ef: 0x22e5,
- 0x16f0: 0x22e9, 0x16f1: 0x22ed, 0x16f2: 0x22f1, 0x16f3: 0x22f5, 0x16f4: 0x22f9, 0x16f5: 0x22fd,
- 0x16f6: 0x2301, 0x16f7: 0x2305, 0x16f8: 0x2309, 0x16f9: 0x230d, 0x16fa: 0x2311, 0x16fb: 0x2315,
- 0x16fc: 0x2319, 0x16fd: 0x231d, 0x16fe: 0x2321,
- // Block 0x5c, offset 0x1700
- 0x1700: 0x2325, 0x1701: 0x2335, 0x1702: 0x2342, 0x1703: 0x2352, 0x1704: 0x235c, 0x1705: 0x236c,
- 0x1706: 0x2376, 0x1707: 0x2380, 0x1708: 0x2393, 0x1709: 0x23a0, 0x170a: 0x23aa, 0x170b: 0x23b4,
- 0x170c: 0x23be, 0x170d: 0x23cb, 0x170e: 0x23d8, 0x170f: 0x23e5, 0x1710: 0x23f2, 0x1711: 0x23ff,
- 0x1712: 0x240c, 0x1713: 0x2419, 0x1714: 0x242c, 0x1715: 0x2433, 0x1716: 0x2446, 0x1717: 0x2459,
- 0x1718: 0x2469, 0x1719: 0x2476, 0x171a: 0x2489, 0x171b: 0x249c, 0x171c: 0x24a9, 0x171d: 0x24b3,
- 0x171e: 0x24bd, 0x171f: 0x24ca, 0x1720: 0x24d7, 0x1721: 0x24e7, 0x1722: 0x24f7, 0x1723: 0x2501,
- 0x1724: 0x250b, 0x1725: 0x2518, 0x1726: 0x2522, 0x1727: 0x252c, 0x1728: 0x2533, 0x1729: 0x253a,
- 0x172a: 0x2544, 0x172b: 0x254e, 0x172c: 0x2561, 0x172d: 0x256e, 0x172e: 0x257e, 0x172f: 0x2591,
- 0x1730: 0x259e, 0x1731: 0x25a8, 0x1732: 0x25b2, 0x1733: 0x25c5, 0x1734: 0x25d2, 0x1735: 0x25e5,
- 0x1736: 0x25ef, 0x1737: 0x25ff, 0x1738: 0x2609, 0x1739: 0x2616, 0x173a: 0x2620, 0x173b: 0x262d,
- 0x173c: 0x263d, 0x173d: 0x264a, 0x173e: 0x265a, 0x173f: 0x2667,
- // Block 0x5d, offset 0x1740
- 0x1740: 0x266e, 0x1741: 0x267e, 0x1742: 0x2688, 0x1743: 0x2692, 0x1744: 0x269f, 0x1745: 0x26a9,
- 0x1746: 0x26b3, 0x1747: 0x26bd, 0x1748: 0x26cd, 0x1749: 0x26da, 0x174a: 0x26e1, 0x174b: 0x26f4,
- 0x174c: 0x26fe, 0x174d: 0x270e, 0x174e: 0x271b, 0x174f: 0x2728, 0x1750: 0x2732, 0x1751: 0x273c,
- 0x1752: 0x2749, 0x1753: 0x2750, 0x1754: 0x275d, 0x1755: 0x276d, 0x1756: 0x2774, 0x1757: 0x2787,
- 0x1758: 0x2791, 0x1759: 0x2796, 0x175a: 0x279b, 0x175b: 0x27a0, 0x175c: 0x27a5, 0x175d: 0x27aa,
- 0x175e: 0x27af, 0x175f: 0x27b4, 0x1760: 0x27b9, 0x1761: 0x27be, 0x1762: 0x27c3, 0x1763: 0x27c9,
- 0x1764: 0x27cf, 0x1765: 0x27d5, 0x1766: 0x27db, 0x1767: 0x27e1, 0x1768: 0x27e7, 0x1769: 0x27ed,
- 0x176a: 0x27f3, 0x176b: 0x27f9, 0x176c: 0x27ff, 0x176d: 0x2805, 0x176e: 0x280b, 0x176f: 0x2811,
- 0x1770: 0x2817, 0x1771: 0x281d, 0x1772: 0x2821, 0x1773: 0x2824, 0x1774: 0x2827, 0x1775: 0x282b,
- 0x1776: 0x282e, 0x1777: 0x2831, 0x1778: 0x2834, 0x1779: 0x2838, 0x177a: 0x283c, 0x177b: 0x283f,
- 0x177c: 0x2846, 0x177d: 0x284d, 0x177e: 0x2854, 0x177f: 0x285b,
- // Block 0x5e, offset 0x1780
- 0x1780: 0x2868, 0x1781: 0x286b, 0x1782: 0x286e, 0x1783: 0x2872, 0x1784: 0x2875, 0x1785: 0x2878,
- 0x1786: 0x287b, 0x1787: 0x287e, 0x1788: 0x2881, 0x1789: 0x2885, 0x178a: 0x288a, 0x178b: 0x288d,
- 0x178c: 0x2890, 0x178d: 0x2894, 0x178e: 0x2898, 0x178f: 0x289b, 0x1790: 0x289e, 0x1791: 0x28a1,
- 0x1792: 0x28a5, 0x1793: 0x28a9, 0x1794: 0x28ad, 0x1795: 0x28b1, 0x1796: 0x28b5, 0x1797: 0x28b8,
- 0x1798: 0x28bb, 0x1799: 0x28be, 0x179a: 0x28c1, 0x179b: 0x28c4, 0x179c: 0x28c8, 0x179d: 0x28cb,
- 0x179e: 0x28ce, 0x179f: 0x28d1, 0x17a0: 0x28d5, 0x17a1: 0x28d9, 0x17a2: 0x28dc, 0x17a3: 0x28e0,
- 0x17a4: 0x28e4, 0x17a5: 0x28e8, 0x17a6: 0x28eb, 0x17a7: 0x28ef, 0x17a8: 0x28f5, 0x17a9: 0x28fc,
- 0x17aa: 0x28ff, 0x17ab: 0x2903, 0x17ac: 0x2907, 0x17ad: 0x290b, 0x17ae: 0x290f, 0x17af: 0x2917,
- 0x17b0: 0x2920, 0x17b1: 0x2923, 0x17b2: 0x2926, 0x17b3: 0x292a, 0x17b4: 0x292d, 0x17b5: 0x2930,
- 0x17b6: 0x2933, 0x17b7: 0x2937, 0x17b8: 0x293a, 0x17b9: 0x293d, 0x17ba: 0x2940, 0x17bb: 0x2943,
- 0x17bc: 0x2946, 0x17bd: 0x294a, 0x17be: 0x294d, 0x17bf: 0x2950,
- // Block 0x5f, offset 0x17c0
- 0x17c0: 0x2953, 0x17c1: 0x2957, 0x17c2: 0x295b, 0x17c3: 0x2960, 0x17c4: 0x2963, 0x17c5: 0x2966,
- 0x17c6: 0x2969, 0x17c7: 0x2970, 0x17c8: 0x2974, 0x17c9: 0x2977, 0x17ca: 0x297a, 0x17cb: 0x297d,
- 0x17cc: 0x2980, 0x17cd: 0x2983, 0x17ce: 0x2986, 0x17cf: 0x2989, 0x17d0: 0x298c, 0x17d1: 0x298f,
- 0x17d2: 0x2992, 0x17d3: 0x2996, 0x17d4: 0x2999, 0x17d5: 0x299c, 0x17d6: 0x29a0, 0x17d7: 0x29a4,
- 0x17d8: 0x29a7, 0x17d9: 0x29ac, 0x17da: 0x29b0, 0x17db: 0x29b3, 0x17dc: 0x29b6, 0x17dd: 0x29b9,
- 0x17de: 0x29bc, 0x17df: 0x29c2, 0x17e0: 0x29c8, 0x17e1: 0x29cd, 0x17e2: 0x29d2, 0x17e3: 0x29d7,
- 0x17e4: 0x29dc, 0x17e5: 0x29e1, 0x17e6: 0x29e6, 0x17e7: 0x29eb, 0x17e8: 0x29f0, 0x17e9: 0x29f5,
- 0x17ea: 0x29fb, 0x17eb: 0x2a01, 0x17ec: 0x2a07, 0x17ed: 0x2a0d, 0x17ee: 0x2a13, 0x17ef: 0x2a19,
- 0x17f0: 0x2a1f, 0x17f1: 0x2a25, 0x17f2: 0x2a2b, 0x17f3: 0x2a31, 0x17f4: 0x2a37, 0x17f5: 0x2a3d,
- 0x17f6: 0x2a43, 0x17f7: 0x2a49, 0x17f8: 0x2a4f, 0x17f9: 0x2a55, 0x17fa: 0x2a5b, 0x17fb: 0x2a61,
- 0x17fc: 0x2a67, 0x17fd: 0x2a6d, 0x17fe: 0x2a73, 0x17ff: 0x2a79,
- // Block 0x60, offset 0x1800
- 0x1830: 0x2a7d,
- // Block 0x61, offset 0x1840
- 0x1840: 0x2a81, 0x1841: 0x2a85, 0x1842: 0x1a9e, 0x1843: 0x2a89, 0x1844: 0x2a8d, 0x1845: 0x2a91,
- 0x1846: 0x2a95, 0x1847: 0x1b76, 0x1848: 0x1b76, 0x1849: 0x2a99, 0x184a: 0x1abe, 0x184b: 0x2a9d,
- 0x184c: 0x2aa1, 0x184d: 0x2aa5, 0x184e: 0x2aa9, 0x184f: 0x2aad, 0x1850: 0x2ab1, 0x1851: 0x2ab5,
- 0x1852: 0x2ab9, 0x1853: 0x2abd, 0x1854: 0x2ac1, 0x1855: 0x2ac5, 0x1856: 0x2ac9, 0x1857: 0x2acd,
- 0x1858: 0x2ad1, 0x1859: 0x2ad5, 0x185a: 0x2ad9, 0x185b: 0x2add, 0x185c: 0x2ae1, 0x185d: 0x2ae5,
- 0x185e: 0x2ae9, 0x185f: 0x2aed, 0x1860: 0x2af1, 0x1861: 0x2af5, 0x1862: 0x2af9, 0x1863: 0x2afd,
- 0x1864: 0x2b01, 0x1865: 0x2b05, 0x1866: 0x2b09, 0x1867: 0x2b0d, 0x1868: 0x2b11, 0x1869: 0x2b15,
- 0x186a: 0x2b19, 0x186b: 0x2b1d, 0x186c: 0x2b21, 0x186d: 0x2b25, 0x186e: 0x2b29, 0x186f: 0x2b2d,
- 0x1870: 0x2b31, 0x1871: 0x2b35, 0x1872: 0x2b39, 0x1873: 0x2b3d, 0x1874: 0x1a16, 0x1875: 0x2b41,
- 0x1876: 0x2b45, 0x1877: 0x2b49, 0x1878: 0x2b4d, 0x1879: 0x2b51, 0x187a: 0x2b55, 0x187b: 0x2b59,
- 0x187c: 0x2b5d, 0x187d: 0x2b61, 0x187e: 0x2b65, 0x187f: 0x2b69,
- // Block 0x62, offset 0x1880
- 0x1880: 0x1b3a, 0x1881: 0x2b6d, 0x1882: 0x2b71, 0x1883: 0x2b75, 0x1884: 0x2b79, 0x1885: 0x2b7d,
- 0x1886: 0x2b81, 0x1887: 0x2b85, 0x1888: 0x2b89, 0x1889: 0x2b8d, 0x188a: 0x2b91, 0x188b: 0x2b95,
- 0x188c: 0x2b99, 0x188d: 0x2b9d, 0x188e: 0x2ba1, 0x188f: 0x2ba5, 0x1890: 0x2ba9, 0x1891: 0x2bad,
- 0x1892: 0x2bb1, 0x1893: 0x2bb5, 0x1894: 0x2bb9, 0x1895: 0x2bbd, 0x1896: 0x2bc1, 0x1897: 0x2bc5,
- 0x1898: 0x2bc9, 0x1899: 0x2bcd, 0x189a: 0x2bd1, 0x189b: 0x2bd5, 0x189c: 0x2ac1, 0x189d: 0x2bd9,
- 0x189e: 0x2bdd, 0x189f: 0x2be1, 0x18a0: 0x2be5, 0x18a1: 0x2be9, 0x18a2: 0x2bed, 0x18a3: 0x2bf1,
- 0x18a4: 0x2bf5, 0x18a5: 0x2bf9, 0x18a6: 0x2bfd, 0x18a7: 0x2c01, 0x18a8: 0x2c05, 0x18a9: 0x2c09,
- 0x18aa: 0x2c0d, 0x18ab: 0x2c11, 0x18ac: 0x2c15, 0x18ad: 0x2c19, 0x18ae: 0x2c1d, 0x18af: 0x2c21,
- 0x18b0: 0x2c25, 0x18b1: 0x1aa6, 0x18b2: 0x2c29, 0x18b3: 0x2c2d, 0x18b4: 0x2c31, 0x18b5: 0x2c35,
- 0x18b6: 0x2c39, 0x18b7: 0x2c3d, 0x18b8: 0x2c41, 0x18b9: 0x2c45, 0x18ba: 0x2c49, 0x18bb: 0x2c4d,
- 0x18bc: 0x2c51, 0x18bd: 0x2c55, 0x18be: 0x2c59, 0x18bf: 0x2c5d,
- // Block 0x63, offset 0x18c0
- 0x18c0: 0x2c61, 0x18c1: 0x18ba, 0x18c2: 0x2c65, 0x18c3: 0x2c69, 0x18c4: 0x2c6d, 0x18c5: 0x2c71,
- 0x18c6: 0x2c75, 0x18c7: 0x2c79, 0x18c8: 0x2c7d, 0x18c9: 0x2c81, 0x18ca: 0x186e, 0x18cb: 0x2c85,
- 0x18cc: 0x2c89, 0x18cd: 0x2c8d, 0x18ce: 0x2c91, 0x18cf: 0x2c95, 0x18d0: 0x2c99, 0x18d1: 0x2c9d,
- 0x18d2: 0x2ca1, 0x18d3: 0x2ca5, 0x18d4: 0x2ca9, 0x18d5: 0x2cad, 0x18d6: 0x2cb1, 0x18d7: 0x2cb5,
- 0x18d8: 0x2cb9, 0x18d9: 0x2cbd, 0x18da: 0x2cc1, 0x18db: 0x2cc5, 0x18dc: 0x2cc9, 0x18dd: 0x2ccd,
- 0x18de: 0x2cd1, 0x18df: 0x2cd5, 0x18e0: 0x2cd9, 0x18e1: 0x2c21, 0x18e2: 0x2cdd, 0x18e3: 0x2ce1,
- 0x18e4: 0x2ce5, 0x18e5: 0x2ce9, 0x18e6: 0x2ced, 0x18e7: 0x2cf1, 0x18e8: 0x2cf5, 0x18e9: 0x2cf9,
- 0x18ea: 0x2be1, 0x18eb: 0x2cfd, 0x18ec: 0x2d01, 0x18ed: 0x2d05, 0x18ee: 0x2d09, 0x18ef: 0x2d0d,
- 0x18f0: 0x2d11, 0x18f1: 0x2d15, 0x18f2: 0x2d19, 0x18f3: 0x2d1d, 0x18f4: 0x2d21, 0x18f5: 0x2d25,
- 0x18f6: 0x2d29, 0x18f7: 0x2d2d, 0x18f8: 0x2d31, 0x18f9: 0x2d35, 0x18fa: 0x2d39, 0x18fb: 0x2d3d,
- 0x18fc: 0x2d41, 0x18fd: 0x2d45, 0x18fe: 0x2d49, 0x18ff: 0x2ac1,
- // Block 0x64, offset 0x1900
- 0x1900: 0x2d4d, 0x1901: 0x2d51, 0x1902: 0x2d55, 0x1903: 0x2d59, 0x1904: 0x1b72, 0x1905: 0x2d5d,
- 0x1906: 0x2d61, 0x1907: 0x2d65, 0x1908: 0x2d69, 0x1909: 0x2d6d, 0x190a: 0x2d71, 0x190b: 0x2d75,
- 0x190c: 0x2d79, 0x190d: 0x2d7d, 0x190e: 0x2d81, 0x190f: 0x2d85, 0x1910: 0x2d89, 0x1911: 0x2173,
- 0x1912: 0x2d8d, 0x1913: 0x2d91, 0x1914: 0x2d95, 0x1915: 0x2d99, 0x1916: 0x2d9d, 0x1917: 0x2da1,
- 0x1918: 0x2da5, 0x1919: 0x2da9, 0x191a: 0x2dad, 0x191b: 0x2be9, 0x191c: 0x2db1, 0x191d: 0x2db5,
- 0x191e: 0x2db9, 0x191f: 0x2dbd, 0x1920: 0x2dc1, 0x1921: 0x2dc5, 0x1922: 0x2dc9, 0x1923: 0x2dcd,
- 0x1924: 0x2dd1, 0x1925: 0x2dd5, 0x1926: 0x2dd9, 0x1927: 0x2ddd, 0x1928: 0x2de1, 0x1929: 0x1aba,
- 0x192a: 0x2de5, 0x192b: 0x2de9, 0x192c: 0x2ded, 0x192d: 0x2df1, 0x192e: 0x2df5, 0x192f: 0x2df9,
- 0x1930: 0x2dfd, 0x1931: 0x2e01, 0x1932: 0x2e05, 0x1933: 0x2e09, 0x1934: 0x2e0d, 0x1935: 0x2e11,
- 0x1936: 0x2e15, 0x1937: 0x19f6, 0x1938: 0x2e19, 0x1939: 0x2e1d, 0x193a: 0x2e21, 0x193b: 0x2e25,
- 0x193c: 0x2e29, 0x193d: 0x2e2d, 0x193e: 0x2e31, 0x193f: 0x2e35,
- // Block 0x65, offset 0x1940
- 0x1940: 0x2e39, 0x1941: 0x2e3d, 0x1942: 0x2e41, 0x1943: 0x2e45, 0x1944: 0x2e49, 0x1945: 0x2e4d,
- 0x1946: 0x2e51, 0x1947: 0x2e55, 0x1948: 0x1a62, 0x1949: 0x2e59, 0x194a: 0x1a6e, 0x194b: 0x2e5d,
- 0x194c: 0x2e61, 0x194d: 0x2e65, 0x1950: 0x2e69,
- 0x1952: 0x2e6d, 0x1955: 0x2e71, 0x1956: 0x2e75, 0x1957: 0x2e79,
- 0x1958: 0x2e7d, 0x1959: 0x2e81, 0x195a: 0x2e85, 0x195b: 0x2e89, 0x195c: 0x2e8d, 0x195d: 0x2e91,
- 0x195e: 0x1a12, 0x1960: 0x2e95, 0x1962: 0x2e99,
- 0x1965: 0x2e9d, 0x1966: 0x2ea1,
- 0x196a: 0x2ea5, 0x196b: 0x2ea9, 0x196c: 0x2ead, 0x196d: 0x2eb1,
- 0x1970: 0x2eb5, 0x1971: 0x2eb9, 0x1972: 0x2ebd, 0x1973: 0x2ec1, 0x1974: 0x2ec5, 0x1975: 0x2ec9,
- 0x1976: 0x2ecd, 0x1977: 0x2ed1, 0x1978: 0x2ed5, 0x1979: 0x2ed9, 0x197a: 0x2edd, 0x197b: 0x2ee1,
- 0x197c: 0x18d6, 0x197d: 0x2ee5, 0x197e: 0x2ee9, 0x197f: 0x2eed,
- // Block 0x66, offset 0x1980
- 0x1980: 0x2ef1, 0x1981: 0x2ef5, 0x1982: 0x2ef9, 0x1983: 0x2efd, 0x1984: 0x2f01, 0x1985: 0x2f05,
- 0x1986: 0x2f09, 0x1987: 0x2f0d, 0x1988: 0x2f11, 0x1989: 0x2f15, 0x198a: 0x2f19, 0x198b: 0x2f1d,
- 0x198c: 0x2187, 0x198d: 0x2f21, 0x198e: 0x2f25, 0x198f: 0x2f29, 0x1990: 0x2f2d, 0x1991: 0x2197,
- 0x1992: 0x2f31, 0x1993: 0x2f35, 0x1994: 0x2f39, 0x1995: 0x2f3d, 0x1996: 0x2f41, 0x1997: 0x2cb1,
- 0x1998: 0x2f45, 0x1999: 0x2f49, 0x199a: 0x2f4d, 0x199b: 0x2f51, 0x199c: 0x2f55, 0x199d: 0x2f59,
- 0x199e: 0x2f59, 0x199f: 0x2f5d, 0x19a0: 0x2f61, 0x19a1: 0x2f65, 0x19a2: 0x2f69, 0x19a3: 0x2f6d,
- 0x19a4: 0x2f71, 0x19a5: 0x2f75, 0x19a6: 0x2f79, 0x19a7: 0x2e9d, 0x19a8: 0x2f7d, 0x19a9: 0x2f81,
- 0x19aa: 0x2f85, 0x19ab: 0x2f89, 0x19ac: 0x2f8d, 0x19ad: 0x2f92,
- 0x19b0: 0x2f96, 0x19b1: 0x2f9a, 0x19b2: 0x2f9e, 0x19b3: 0x2fa2, 0x19b4: 0x2fa6, 0x19b5: 0x2faa,
- 0x19b6: 0x2fae, 0x19b7: 0x2fb2, 0x19b8: 0x2ecd, 0x19b9: 0x2fb6, 0x19ba: 0x2fba, 0x19bb: 0x2fbe,
- 0x19bc: 0x2e69, 0x19bd: 0x2fc2, 0x19be: 0x2fc6, 0x19bf: 0x2fca,
- // Block 0x67, offset 0x19c0
- 0x19c0: 0x2fce, 0x19c1: 0x2fd2, 0x19c2: 0x2fd6, 0x19c3: 0x2fda, 0x19c4: 0x2fde, 0x19c5: 0x2fe2,
- 0x19c6: 0x2fe6, 0x19c7: 0x2fea, 0x19c8: 0x2fee, 0x19c9: 0x2eed, 0x19ca: 0x2ff2, 0x19cb: 0x2ef1,
- 0x19cc: 0x2ff6, 0x19cd: 0x2ffa, 0x19ce: 0x2ffe, 0x19cf: 0x3002, 0x19d0: 0x3006, 0x19d1: 0x2e6d,
- 0x19d2: 0x2b15, 0x19d3: 0x300a, 0x19d4: 0x300e, 0x19d5: 0x195a, 0x19d6: 0x2c25, 0x19d7: 0x2d71,
- 0x19d8: 0x3012, 0x19d9: 0x3016, 0x19da: 0x2f0d, 0x19db: 0x301a, 0x19dc: 0x2f11, 0x19dd: 0x301e,
- 0x19de: 0x3022, 0x19df: 0x3026, 0x19e0: 0x2e75, 0x19e1: 0x302a, 0x19e2: 0x302e, 0x19e3: 0x3032,
- 0x19e4: 0x3036, 0x19e5: 0x303a, 0x19e6: 0x2e79, 0x19e7: 0x303e, 0x19e8: 0x3042, 0x19e9: 0x3046,
- 0x19ea: 0x304a, 0x19eb: 0x304e, 0x19ec: 0x3052, 0x19ed: 0x2f41, 0x19ee: 0x3056, 0x19ef: 0x305a,
- 0x19f0: 0x2cb1, 0x19f1: 0x305e, 0x19f2: 0x2f51, 0x19f3: 0x3062, 0x19f4: 0x3066, 0x19f5: 0x306a,
- 0x19f6: 0x306e, 0x19f7: 0x3072, 0x19f8: 0x2f65, 0x19f9: 0x3076, 0x19fa: 0x2e99, 0x19fb: 0x307a,
- 0x19fc: 0x2f69, 0x19fd: 0x2bd9, 0x19fe: 0x307e, 0x19ff: 0x2f6d,
- // Block 0x68, offset 0x1a00
- 0x1a00: 0x3082, 0x1a01: 0x2f75, 0x1a02: 0x3086, 0x1a03: 0x308a, 0x1a04: 0x308e, 0x1a05: 0x3092,
- 0x1a06: 0x3096, 0x1a07: 0x2f7d, 0x1a08: 0x2e8d, 0x1a09: 0x309a, 0x1a0a: 0x2f81, 0x1a0b: 0x309e,
- 0x1a0c: 0x2f85, 0x1a0d: 0x30a2, 0x1a0e: 0x1b76, 0x1a0f: 0x30a6, 0x1a10: 0x30ab, 0x1a11: 0x30b0,
- 0x1a12: 0x30b5, 0x1a13: 0x30b9, 0x1a14: 0x30bd, 0x1a15: 0x30c1, 0x1a16: 0x30c6, 0x1a17: 0x30cb,
- 0x1a18: 0x30d0, 0x1a19: 0x30d4,
- // Block 0x69, offset 0x1a40
- 0x1a40: 0x30d8, 0x1a41: 0x30db, 0x1a42: 0x30de, 0x1a43: 0x30e1, 0x1a44: 0x30e5, 0x1a45: 0x30e9,
- 0x1a46: 0x30e9,
- 0x1a53: 0x30ec, 0x1a54: 0x30f1, 0x1a55: 0x30f6, 0x1a56: 0x30fb, 0x1a57: 0x3100,
- 0x1a5d: 0x3105,
- 0x1a5f: 0x310a, 0x1a60: 0x310f, 0x1a61: 0x14db, 0x1a62: 0x14e4, 0x1a63: 0x3112,
- 0x1a64: 0x3115, 0x1a65: 0x3118, 0x1a66: 0x311b, 0x1a67: 0x311e, 0x1a68: 0x3121, 0x1a69: 0x1494,
- 0x1a6a: 0x3124, 0x1a6b: 0x3129, 0x1a6c: 0x312e, 0x1a6d: 0x3135, 0x1a6e: 0x313c, 0x1a6f: 0x3141,
- 0x1a70: 0x3146, 0x1a71: 0x314b, 0x1a72: 0x3150, 0x1a73: 0x3155, 0x1a74: 0x315a, 0x1a75: 0x315f,
- 0x1a76: 0x3164, 0x1a78: 0x3169, 0x1a79: 0x316e, 0x1a7a: 0x3173, 0x1a7b: 0x3178,
- 0x1a7c: 0x317d, 0x1a7e: 0x3182,
- // Block 0x6a, offset 0x1a80
- 0x1a80: 0x3187, 0x1a81: 0x318c, 0x1a83: 0x3191, 0x1a84: 0x3196,
- 0x1a86: 0x319b, 0x1a87: 0x31a0, 0x1a88: 0x31a5, 0x1a89: 0x31aa, 0x1a8a: 0x31af, 0x1a8b: 0x31b4,
- 0x1a8c: 0x31b9, 0x1a8d: 0x31be, 0x1a8e: 0x31c3, 0x1a8f: 0x31c8, 0x1a90: 0x31cd, 0x1a91: 0x31cd,
- 0x1a92: 0x31d0, 0x1a93: 0x31d0, 0x1a94: 0x31d0, 0x1a95: 0x31d0, 0x1a96: 0x31d3, 0x1a97: 0x31d3,
- 0x1a98: 0x31d3, 0x1a99: 0x31d3, 0x1a9a: 0x31d6, 0x1a9b: 0x31d6, 0x1a9c: 0x31d6, 0x1a9d: 0x31d6,
- 0x1a9e: 0x31d9, 0x1a9f: 0x31d9, 0x1aa0: 0x31d9, 0x1aa1: 0x31d9, 0x1aa2: 0x31dc, 0x1aa3: 0x31dc,
- 0x1aa4: 0x31dc, 0x1aa5: 0x31dc, 0x1aa6: 0x31df, 0x1aa7: 0x31df, 0x1aa8: 0x31df, 0x1aa9: 0x31df,
- 0x1aaa: 0x31e2, 0x1aab: 0x31e2, 0x1aac: 0x31e2, 0x1aad: 0x31e2, 0x1aae: 0x31e5, 0x1aaf: 0x31e5,
- 0x1ab0: 0x31e5, 0x1ab1: 0x31e5, 0x1ab2: 0x31e8, 0x1ab3: 0x31e8, 0x1ab4: 0x31e8, 0x1ab5: 0x31e8,
- 0x1ab6: 0x31eb, 0x1ab7: 0x31eb, 0x1ab8: 0x31eb, 0x1ab9: 0x31eb, 0x1aba: 0x31ee, 0x1abb: 0x31ee,
- 0x1abc: 0x31ee, 0x1abd: 0x31ee, 0x1abe: 0x31f1, 0x1abf: 0x31f1,
- // Block 0x6b, offset 0x1ac0
- 0x1ac0: 0x31f1, 0x1ac1: 0x31f1, 0x1ac2: 0x31f4, 0x1ac3: 0x31f4, 0x1ac4: 0x31f7, 0x1ac5: 0x31f7,
- 0x1ac6: 0x31fa, 0x1ac7: 0x31fa, 0x1ac8: 0x31fd, 0x1ac9: 0x31fd, 0x1aca: 0x3200, 0x1acb: 0x3200,
- 0x1acc: 0x3203, 0x1acd: 0x3203, 0x1ace: 0x3206, 0x1acf: 0x3206, 0x1ad0: 0x3206, 0x1ad1: 0x3206,
- 0x1ad2: 0x3209, 0x1ad3: 0x3209, 0x1ad4: 0x3209, 0x1ad5: 0x3209, 0x1ad6: 0x320c, 0x1ad7: 0x320c,
- 0x1ad8: 0x320c, 0x1ad9: 0x320c, 0x1ada: 0x320f, 0x1adb: 0x320f, 0x1adc: 0x320f, 0x1add: 0x320f,
- 0x1ade: 0x3212, 0x1adf: 0x3212, 0x1ae0: 0x3215, 0x1ae1: 0x3215, 0x1ae2: 0x3215, 0x1ae3: 0x3215,
- 0x1ae4: 0x06ba, 0x1ae5: 0x06ba, 0x1ae6: 0x3218, 0x1ae7: 0x3218, 0x1ae8: 0x3218, 0x1ae9: 0x3218,
- 0x1aea: 0x321b, 0x1aeb: 0x321b, 0x1aec: 0x321b, 0x1aed: 0x321b, 0x1aee: 0x321e, 0x1aef: 0x321e,
- 0x1af0: 0x06c4, 0x1af1: 0x06c4,
- // Block 0x6c, offset 0x1b00
- 0x1b13: 0x3221, 0x1b14: 0x3221, 0x1b15: 0x3221, 0x1b16: 0x3221, 0x1b17: 0x3224,
- 0x1b18: 0x3224, 0x1b19: 0x3227, 0x1b1a: 0x3227, 0x1b1b: 0x322a, 0x1b1c: 0x322a, 0x1b1d: 0x06b0,
- 0x1b1e: 0x322d, 0x1b1f: 0x322d, 0x1b20: 0x3230, 0x1b21: 0x3230, 0x1b22: 0x3233, 0x1b23: 0x3233,
- 0x1b24: 0x3236, 0x1b25: 0x3236, 0x1b26: 0x3236, 0x1b27: 0x3236, 0x1b28: 0x3239, 0x1b29: 0x3239,
- 0x1b2a: 0x323c, 0x1b2b: 0x323c, 0x1b2c: 0x3243, 0x1b2d: 0x3243, 0x1b2e: 0x324a, 0x1b2f: 0x324a,
- 0x1b30: 0x3251, 0x1b31: 0x3251, 0x1b32: 0x3258, 0x1b33: 0x3258, 0x1b34: 0x325f, 0x1b35: 0x325f,
- 0x1b36: 0x3266, 0x1b37: 0x3266, 0x1b38: 0x3266, 0x1b39: 0x326d, 0x1b3a: 0x326d, 0x1b3b: 0x326d,
- 0x1b3c: 0x3274, 0x1b3d: 0x3274, 0x1b3e: 0x3274, 0x1b3f: 0x3274,
- // Block 0x6d, offset 0x1b40
- 0x1b40: 0x3277, 0x1b41: 0x327e, 0x1b42: 0x3285, 0x1b43: 0x326d, 0x1b44: 0x328c, 0x1b45: 0x3293,
- 0x1b46: 0x3298, 0x1b47: 0x329d, 0x1b48: 0x32a2, 0x1b49: 0x32a7, 0x1b4a: 0x32ac, 0x1b4b: 0x32b1,
- 0x1b4c: 0x32b6, 0x1b4d: 0x32bb, 0x1b4e: 0x32c0, 0x1b4f: 0x32c5, 0x1b50: 0x32ca, 0x1b51: 0x32cf,
- 0x1b52: 0x32d4, 0x1b53: 0x32d9, 0x1b54: 0x32de, 0x1b55: 0x32e3, 0x1b56: 0x32e8, 0x1b57: 0x32ed,
- 0x1b58: 0x32f2, 0x1b59: 0x32f7, 0x1b5a: 0x32fc, 0x1b5b: 0x3301, 0x1b5c: 0x3306, 0x1b5d: 0x330b,
- 0x1b5e: 0x3310, 0x1b5f: 0x3315, 0x1b60: 0x331a, 0x1b61: 0x331f, 0x1b62: 0x3324, 0x1b63: 0x3329,
- 0x1b64: 0x332e, 0x1b65: 0x3333, 0x1b66: 0x3338, 0x1b67: 0x333d, 0x1b68: 0x3342, 0x1b69: 0x3347,
- 0x1b6a: 0x334c, 0x1b6b: 0x3351, 0x1b6c: 0x3356, 0x1b6d: 0x335b, 0x1b6e: 0x3360, 0x1b6f: 0x3365,
- 0x1b70: 0x336a, 0x1b71: 0x336f, 0x1b72: 0x3374, 0x1b73: 0x3379, 0x1b74: 0x337e, 0x1b75: 0x3383,
- 0x1b76: 0x3388, 0x1b77: 0x338d, 0x1b78: 0x3392, 0x1b79: 0x3397, 0x1b7a: 0x339c, 0x1b7b: 0x33a1,
- 0x1b7c: 0x33a6, 0x1b7d: 0x33ab, 0x1b7e: 0x33b0, 0x1b7f: 0x33b5,
- // Block 0x6e, offset 0x1b80
- 0x1b80: 0x33ba, 0x1b81: 0x33bf, 0x1b82: 0x33c4, 0x1b83: 0x33c9, 0x1b84: 0x33ce, 0x1b85: 0x33d3,
- 0x1b86: 0x33d8, 0x1b87: 0x33dd, 0x1b88: 0x33e2, 0x1b89: 0x33e7, 0x1b8a: 0x33ec, 0x1b8b: 0x33f1,
- 0x1b8c: 0x33f6, 0x1b8d: 0x33fb, 0x1b8e: 0x3400, 0x1b8f: 0x3405, 0x1b90: 0x340a, 0x1b91: 0x340f,
- 0x1b92: 0x3414, 0x1b93: 0x3419, 0x1b94: 0x341e, 0x1b95: 0x3423, 0x1b96: 0x3428, 0x1b97: 0x342d,
- 0x1b98: 0x3432, 0x1b99: 0x3437, 0x1b9a: 0x343c, 0x1b9b: 0x3441, 0x1b9c: 0x3446, 0x1b9d: 0x344b,
- 0x1b9e: 0x3450, 0x1b9f: 0x3456, 0x1ba0: 0x345c, 0x1ba1: 0x3462, 0x1ba2: 0x3468, 0x1ba3: 0x346e,
- 0x1ba4: 0x3474, 0x1ba5: 0x347b, 0x1ba6: 0x3285, 0x1ba7: 0x3482, 0x1ba8: 0x326d, 0x1ba9: 0x328c,
- 0x1baa: 0x3489, 0x1bab: 0x348e, 0x1bac: 0x32a2, 0x1bad: 0x3493, 0x1bae: 0x32a7, 0x1baf: 0x32ac,
- 0x1bb0: 0x3498, 0x1bb1: 0x349d, 0x1bb2: 0x32c0, 0x1bb3: 0x34a2, 0x1bb4: 0x32c5, 0x1bb5: 0x32ca,
- 0x1bb6: 0x34a7, 0x1bb7: 0x34ac, 0x1bb8: 0x32d4, 0x1bb9: 0x34b1, 0x1bba: 0x32d9, 0x1bbb: 0x32de,
- 0x1bbc: 0x336f, 0x1bbd: 0x3374, 0x1bbe: 0x3383, 0x1bbf: 0x3388,
- // Block 0x6f, offset 0x1bc0
- 0x1bc0: 0x338d, 0x1bc1: 0x33a1, 0x1bc2: 0x33a6, 0x1bc3: 0x33ab, 0x1bc4: 0x33b0, 0x1bc5: 0x33c4,
- 0x1bc6: 0x33c9, 0x1bc7: 0x33ce, 0x1bc8: 0x34b6, 0x1bc9: 0x33e2, 0x1bca: 0x34bb, 0x1bcb: 0x34c0,
- 0x1bcc: 0x3400, 0x1bcd: 0x34c5, 0x1bce: 0x3405, 0x1bcf: 0x340a, 0x1bd0: 0x344b, 0x1bd1: 0x34ca,
- 0x1bd2: 0x34cf, 0x1bd3: 0x3432, 0x1bd4: 0x34d4, 0x1bd5: 0x3437, 0x1bd6: 0x343c, 0x1bd7: 0x3277,
- 0x1bd8: 0x327e, 0x1bd9: 0x34d9, 0x1bda: 0x3285, 0x1bdb: 0x34e0, 0x1bdc: 0x3293, 0x1bdd: 0x3298,
- 0x1bde: 0x329d, 0x1bdf: 0x32a2, 0x1be0: 0x34e7, 0x1be1: 0x32b1, 0x1be2: 0x32b6, 0x1be3: 0x32bb,
- 0x1be4: 0x32c0, 0x1be5: 0x34ec, 0x1be6: 0x32d4, 0x1be7: 0x32e3, 0x1be8: 0x32e8, 0x1be9: 0x32ed,
- 0x1bea: 0x32f2, 0x1beb: 0x32f7, 0x1bec: 0x3301, 0x1bed: 0x3306, 0x1bee: 0x330b, 0x1bef: 0x3310,
- 0x1bf0: 0x3315, 0x1bf1: 0x331a, 0x1bf2: 0x34f1, 0x1bf3: 0x331f, 0x1bf4: 0x3324, 0x1bf5: 0x3329,
- 0x1bf6: 0x332e, 0x1bf7: 0x3333, 0x1bf8: 0x3338, 0x1bf9: 0x3342, 0x1bfa: 0x3347, 0x1bfb: 0x334c,
- 0x1bfc: 0x3351, 0x1bfd: 0x3356, 0x1bfe: 0x335b, 0x1bff: 0x3360,
- // Block 0x70, offset 0x1c00
- 0x1c00: 0x3365, 0x1c01: 0x336a, 0x1c02: 0x3379, 0x1c03: 0x337e, 0x1c04: 0x3392, 0x1c05: 0x3397,
- 0x1c06: 0x339c, 0x1c07: 0x33a1, 0x1c08: 0x33a6, 0x1c09: 0x33b5, 0x1c0a: 0x33ba, 0x1c0b: 0x33bf,
- 0x1c0c: 0x33c4, 0x1c0d: 0x34f6, 0x1c0e: 0x33d3, 0x1c0f: 0x33d8, 0x1c10: 0x33dd, 0x1c11: 0x33e2,
- 0x1c12: 0x33f1, 0x1c13: 0x33f6, 0x1c14: 0x33fb, 0x1c15: 0x3400, 0x1c16: 0x34fb, 0x1c17: 0x340f,
- 0x1c18: 0x3414, 0x1c19: 0x3500, 0x1c1a: 0x3423, 0x1c1b: 0x3428, 0x1c1c: 0x342d, 0x1c1d: 0x3432,
- 0x1c1e: 0x3505, 0x1c1f: 0x3285, 0x1c20: 0x34e0, 0x1c21: 0x32a2, 0x1c22: 0x34e7, 0x1c23: 0x32c0,
- 0x1c24: 0x34ec, 0x1c25: 0x32d4, 0x1c26: 0x350a, 0x1c27: 0x3315, 0x1c28: 0x350f, 0x1c29: 0x3514,
- 0x1c2a: 0x3519, 0x1c2b: 0x33a1, 0x1c2c: 0x33a6, 0x1c2d: 0x33c4, 0x1c2e: 0x3400, 0x1c2f: 0x34fb,
- 0x1c30: 0x3432, 0x1c31: 0x3505, 0x1c32: 0x351e, 0x1c33: 0x3525, 0x1c34: 0x352c, 0x1c35: 0x3533,
- 0x1c36: 0x3538, 0x1c37: 0x353d, 0x1c38: 0x3542, 0x1c39: 0x3547, 0x1c3a: 0x354c, 0x1c3b: 0x3551,
- 0x1c3c: 0x3556, 0x1c3d: 0x355b, 0x1c3e: 0x3560, 0x1c3f: 0x3565,
- // Block 0x71, offset 0x1c40
- 0x1c40: 0x356a, 0x1c41: 0x356f, 0x1c42: 0x3574, 0x1c43: 0x3579, 0x1c44: 0x357e, 0x1c45: 0x3583,
- 0x1c46: 0x3588, 0x1c47: 0x358d, 0x1c48: 0x3592, 0x1c49: 0x3597, 0x1c4a: 0x359c, 0x1c4b: 0x35a1,
- 0x1c4c: 0x3514, 0x1c4d: 0x35a6, 0x1c4e: 0x35ab, 0x1c4f: 0x35b0, 0x1c50: 0x35b5, 0x1c51: 0x3533,
- 0x1c52: 0x3538, 0x1c53: 0x353d, 0x1c54: 0x3542, 0x1c55: 0x3547, 0x1c56: 0x354c, 0x1c57: 0x3551,
- 0x1c58: 0x3556, 0x1c59: 0x355b, 0x1c5a: 0x3560, 0x1c5b: 0x3565, 0x1c5c: 0x356a, 0x1c5d: 0x356f,
- 0x1c5e: 0x3574, 0x1c5f: 0x3579, 0x1c60: 0x357e, 0x1c61: 0x3583, 0x1c62: 0x3588, 0x1c63: 0x358d,
- 0x1c64: 0x3592, 0x1c65: 0x3597, 0x1c66: 0x359c, 0x1c67: 0x35a1, 0x1c68: 0x3514, 0x1c69: 0x35a6,
- 0x1c6a: 0x35ab, 0x1c6b: 0x35b0, 0x1c6c: 0x35b5, 0x1c6d: 0x3597, 0x1c6e: 0x359c, 0x1c6f: 0x35a1,
- 0x1c70: 0x3514, 0x1c71: 0x350f, 0x1c72: 0x3519, 0x1c73: 0x333d, 0x1c74: 0x3306, 0x1c75: 0x330b,
- 0x1c76: 0x3310, 0x1c77: 0x3597, 0x1c78: 0x359c, 0x1c79: 0x35a1, 0x1c7a: 0x333d, 0x1c7b: 0x3342,
- 0x1c7c: 0x35ba, 0x1c7d: 0x35ba,
- // Block 0x72, offset 0x1c80
- 0x1c90: 0x35bf, 0x1c91: 0x35c6,
- 0x1c92: 0x35c6, 0x1c93: 0x35cd, 0x1c94: 0x35d4, 0x1c95: 0x35db, 0x1c96: 0x35e2, 0x1c97: 0x35e9,
- 0x1c98: 0x35f0, 0x1c99: 0x35f0, 0x1c9a: 0x35f7, 0x1c9b: 0x35fe, 0x1c9c: 0x3605, 0x1c9d: 0x360c,
- 0x1c9e: 0x3613, 0x1c9f: 0x361a, 0x1ca0: 0x361a, 0x1ca1: 0x3621, 0x1ca2: 0x3628, 0x1ca3: 0x3628,
- 0x1ca4: 0x362f, 0x1ca5: 0x362f, 0x1ca6: 0x3636, 0x1ca7: 0x363d, 0x1ca8: 0x363d, 0x1ca9: 0x3644,
- 0x1caa: 0x364b, 0x1cab: 0x364b, 0x1cac: 0x3652, 0x1cad: 0x3652, 0x1cae: 0x3659, 0x1caf: 0x3660,
- 0x1cb0: 0x3660, 0x1cb1: 0x3667, 0x1cb2: 0x3667, 0x1cb3: 0x366e, 0x1cb4: 0x3675, 0x1cb5: 0x367c,
- 0x1cb6: 0x3683, 0x1cb7: 0x3683, 0x1cb8: 0x368a, 0x1cb9: 0x3691, 0x1cba: 0x3698, 0x1cbb: 0x369f,
- 0x1cbc: 0x36a6, 0x1cbd: 0x36a6, 0x1cbe: 0x36ad, 0x1cbf: 0x36b4,
- // Block 0x73, offset 0x1cc0
- 0x1cc0: 0x36bb, 0x1cc1: 0x36c2, 0x1cc2: 0x36c9, 0x1cc3: 0x36d0, 0x1cc4: 0x36d0, 0x1cc5: 0x36d7,
- 0x1cc6: 0x36d7, 0x1cc7: 0x36de, 0x1cc8: 0x36de, 0x1cc9: 0x36e5, 0x1cca: 0x36ec, 0x1ccb: 0x36f3,
- 0x1ccc: 0x36fa, 0x1ccd: 0x3701, 0x1cce: 0x3708, 0x1ccf: 0x370f,
- 0x1cd2: 0x3716, 0x1cd3: 0x371d, 0x1cd4: 0x3724, 0x1cd5: 0x372b, 0x1cd6: 0x3732, 0x1cd7: 0x3739,
- 0x1cd8: 0x3739, 0x1cd9: 0x3740, 0x1cda: 0x3747, 0x1cdb: 0x374e, 0x1cdc: 0x3755, 0x1cdd: 0x3755,
- 0x1cde: 0x375c, 0x1cdf: 0x3763, 0x1ce0: 0x376a, 0x1ce1: 0x3771, 0x1ce2: 0x3778, 0x1ce3: 0x377f,
- 0x1ce4: 0x3786, 0x1ce5: 0x378d, 0x1ce6: 0x3794, 0x1ce7: 0x379b, 0x1ce8: 0x37a2, 0x1ce9: 0x37a9,
- 0x1cea: 0x37b0, 0x1ceb: 0x37b7, 0x1cec: 0x37be, 0x1ced: 0x37c5, 0x1cee: 0x37cc, 0x1cef: 0x37d3,
- 0x1cf0: 0x37da, 0x1cf1: 0x37e1, 0x1cf2: 0x37e8, 0x1cf3: 0x37ef, 0x1cf4: 0x36ad, 0x1cf5: 0x36bb,
- 0x1cf6: 0x37f6, 0x1cf7: 0x37fd, 0x1cf8: 0x3804, 0x1cf9: 0x380b, 0x1cfa: 0x3812, 0x1cfb: 0x3819,
- 0x1cfc: 0x3812, 0x1cfd: 0x3804, 0x1cfe: 0x3820, 0x1cff: 0x3827,
- // Block 0x74, offset 0x1d00
- 0x1d00: 0x382e, 0x1d01: 0x3835, 0x1d02: 0x383c, 0x1d03: 0x3819, 0x1d04: 0x367c, 0x1d05: 0x3636,
- 0x1d06: 0x3843, 0x1d07: 0x384a,
- 0x1d30: 0x3851, 0x1d31: 0x3858, 0x1d32: 0x385f, 0x1d33: 0x3868, 0x1d34: 0x3871, 0x1d35: 0x387a,
- 0x1d36: 0x3883, 0x1d37: 0x388c, 0x1d38: 0x3895, 0x1d39: 0x389e, 0x1d3a: 0x38a5, 0x1d3b: 0x38c7,
- 0x1d3c: 0x38d7,
- // Block 0x75, offset 0x1d40
- 0x1d50: 0x38e0, 0x1d51: 0x38e2,
- 0x1d52: 0x38e6, 0x1d53: 0x38ea, 0x1d54: 0x04e1, 0x1d55: 0x38ec, 0x1d56: 0x38ee, 0x1d57: 0x38f0,
- 0x1d58: 0x38f4, 0x1d59: 0x1443,
- 0x1d70: 0x1440, 0x1d71: 0x38f8, 0x1d72: 0x38fc, 0x1d73: 0x3900, 0x1d74: 0x3900, 0x1d75: 0x149c,
- 0x1d76: 0x149e, 0x1d77: 0x3902, 0x1d78: 0x3904, 0x1d79: 0x3906, 0x1d7a: 0x390a, 0x1d7b: 0x390e,
- 0x1d7c: 0x3912, 0x1d7d: 0x3916, 0x1d7e: 0x391a, 0x1d7f: 0x16c3,
- // Block 0x76, offset 0x1d80
- 0x1d80: 0x16c7, 0x1d81: 0x391e, 0x1d82: 0x3922, 0x1d83: 0x3926, 0x1d84: 0x392a,
- 0x1d87: 0x392e, 0x1d88: 0x3930, 0x1d89: 0x146c, 0x1d8a: 0x146c, 0x1d8b: 0x146c,
- 0x1d8c: 0x146c, 0x1d8d: 0x3900, 0x1d8e: 0x3900, 0x1d8f: 0x3900, 0x1d90: 0x38e0, 0x1d91: 0x38e2,
- 0x1d92: 0x143e, 0x1d94: 0x04e1, 0x1d95: 0x38ea, 0x1d96: 0x38ee, 0x1d97: 0x38ec,
- 0x1d98: 0x38f8, 0x1d99: 0x149c, 0x1d9a: 0x149e, 0x1d9b: 0x3902, 0x1d9c: 0x3904, 0x1d9d: 0x3906,
- 0x1d9e: 0x390a, 0x1d9f: 0x3932, 0x1da0: 0x3934, 0x1da1: 0x3936, 0x1da2: 0x1494, 0x1da3: 0x3938,
- 0x1da4: 0x393a, 0x1da5: 0x393c, 0x1da6: 0x149a, 0x1da8: 0x393e, 0x1da9: 0x3940,
- 0x1daa: 0x3942, 0x1dab: 0x3944,
- 0x1db0: 0x3946, 0x1db1: 0x394a, 0x1db2: 0x394f, 0x1db4: 0x3953,
- 0x1db6: 0x3957, 0x1db7: 0x395b, 0x1db8: 0x3960, 0x1db9: 0x3964, 0x1dba: 0x3969, 0x1dbb: 0x396d,
- 0x1dbc: 0x3972, 0x1dbd: 0x3976, 0x1dbe: 0x397b, 0x1dbf: 0x397f,
- // Block 0x77, offset 0x1dc0
- 0x1dc0: 0x3984, 0x1dc1: 0x068d, 0x1dc2: 0x068d, 0x1dc3: 0x0692, 0x1dc4: 0x0692, 0x1dc5: 0x0697,
- 0x1dc6: 0x0697, 0x1dc7: 0x069c, 0x1dc8: 0x069c, 0x1dc9: 0x06a1, 0x1dca: 0x06a1, 0x1dcb: 0x06a1,
- 0x1dcc: 0x06a1, 0x1dcd: 0x3987, 0x1dce: 0x3987, 0x1dcf: 0x398a, 0x1dd0: 0x398a, 0x1dd1: 0x398a,
- 0x1dd2: 0x398a, 0x1dd3: 0x398d, 0x1dd4: 0x398d, 0x1dd5: 0x3990, 0x1dd6: 0x3990, 0x1dd7: 0x3990,
- 0x1dd8: 0x3990, 0x1dd9: 0x3993, 0x1dda: 0x3993, 0x1ddb: 0x3993, 0x1ddc: 0x3993, 0x1ddd: 0x3996,
- 0x1dde: 0x3996, 0x1ddf: 0x3996, 0x1de0: 0x3996, 0x1de1: 0x3999, 0x1de2: 0x3999, 0x1de3: 0x3999,
- 0x1de4: 0x3999, 0x1de5: 0x399c, 0x1de6: 0x399c, 0x1de7: 0x399c, 0x1de8: 0x399c, 0x1de9: 0x399f,
- 0x1dea: 0x399f, 0x1deb: 0x39a2, 0x1dec: 0x39a2, 0x1ded: 0x39a5, 0x1dee: 0x39a5, 0x1def: 0x39a8,
- 0x1df0: 0x39a8, 0x1df1: 0x39ab, 0x1df2: 0x39ab, 0x1df3: 0x39ab, 0x1df4: 0x39ab, 0x1df5: 0x39ae,
- 0x1df6: 0x39ae, 0x1df7: 0x39ae, 0x1df8: 0x39ae, 0x1df9: 0x39b1, 0x1dfa: 0x39b1, 0x1dfb: 0x39b1,
- 0x1dfc: 0x39b1, 0x1dfd: 0x39b4, 0x1dfe: 0x39b4, 0x1dff: 0x39b4,
- // Block 0x78, offset 0x1e00
- 0x1e00: 0x39b4, 0x1e01: 0x39b7, 0x1e02: 0x39b7, 0x1e03: 0x39b7, 0x1e04: 0x39b7, 0x1e05: 0x39ba,
- 0x1e06: 0x39ba, 0x1e07: 0x39ba, 0x1e08: 0x39ba, 0x1e09: 0x39bd, 0x1e0a: 0x39bd, 0x1e0b: 0x39bd,
- 0x1e0c: 0x39bd, 0x1e0d: 0x39c0, 0x1e0e: 0x39c0, 0x1e0f: 0x39c0, 0x1e10: 0x39c0, 0x1e11: 0x39c3,
- 0x1e12: 0x39c3, 0x1e13: 0x39c3, 0x1e14: 0x39c3, 0x1e15: 0x39c6, 0x1e16: 0x39c6, 0x1e17: 0x39c6,
- 0x1e18: 0x39c6, 0x1e19: 0x39c9, 0x1e1a: 0x39c9, 0x1e1b: 0x39c9, 0x1e1c: 0x39c9, 0x1e1d: 0x39cc,
- 0x1e1e: 0x39cc, 0x1e1f: 0x39cc, 0x1e20: 0x39cc, 0x1e21: 0x39cf, 0x1e22: 0x39cf, 0x1e23: 0x39cf,
- 0x1e24: 0x39cf, 0x1e25: 0x39d2, 0x1e26: 0x39d2, 0x1e27: 0x39d2, 0x1e28: 0x39d2, 0x1e29: 0x39d5,
- 0x1e2a: 0x39d5, 0x1e2b: 0x39d5, 0x1e2c: 0x39d5, 0x1e2d: 0x39d8, 0x1e2e: 0x39d8, 0x1e2f: 0x3239,
- 0x1e30: 0x3239, 0x1e31: 0x39db, 0x1e32: 0x39db, 0x1e33: 0x39db, 0x1e34: 0x39db, 0x1e35: 0x39de,
- 0x1e36: 0x39de, 0x1e37: 0x39e5, 0x1e38: 0x39e5, 0x1e39: 0x39ec, 0x1e3a: 0x39ec, 0x1e3b: 0x39f3,
- 0x1e3c: 0x39f3,
- // Block 0x79, offset 0x1e40
- 0x1e41: 0x38ec, 0x1e42: 0x39f8, 0x1e43: 0x3932, 0x1e44: 0x3940, 0x1e45: 0x3942,
- 0x1e46: 0x3934, 0x1e47: 0x39fa, 0x1e48: 0x149c, 0x1e49: 0x149e, 0x1e4a: 0x3936, 0x1e4b: 0x1494,
- 0x1e4c: 0x38e0, 0x1e4d: 0x3938, 0x1e4e: 0x143e, 0x1e4f: 0x39fc, 0x1e50: 0x1486, 0x1e51: 0x001c,
- 0x1e52: 0x000d, 0x1e53: 0x000f, 0x1e54: 0x1488, 0x1e55: 0x148a, 0x1e56: 0x148c, 0x1e57: 0x148e,
- 0x1e58: 0x1490, 0x1e59: 0x1492, 0x1e5a: 0x38ea, 0x1e5b: 0x04e1, 0x1e5c: 0x393a, 0x1e5d: 0x149a,
- 0x1e5e: 0x393c, 0x1e5f: 0x38ee, 0x1e60: 0x3944, 0x1e61: 0x0906, 0x1e62: 0x090b, 0x1e63: 0x14ad,
- 0x1e64: 0x090d, 0x1e65: 0x090f, 0x1e66: 0x14d9, 0x1e67: 0x0914, 0x1e68: 0x0916, 0x1e69: 0x0918,
- 0x1e6a: 0x091a, 0x1e6b: 0x091c, 0x1e6c: 0x091e, 0x1e6d: 0x0920, 0x1e6e: 0x0922, 0x1e6f: 0x0924,
- 0x1e70: 0x0929, 0x1e71: 0x14c8, 0x1e72: 0x092b, 0x1e73: 0x17f6, 0x1e74: 0x092d, 0x1e75: 0x092f,
- 0x1e76: 0x155f, 0x1e77: 0x0931, 0x1e78: 0x1570, 0x1e79: 0x17f8, 0x1e7a: 0x14d4, 0x1e7b: 0x392e,
- 0x1e7c: 0x393e, 0x1e7d: 0x3930, 0x1e7e: 0x39fe, 0x1e7f: 0x3900,
- // Block 0x7a, offset 0x1e80
- 0x1e80: 0x13f7, 0x1e81: 0x0007, 0x1e82: 0x093d, 0x1e83: 0x0984, 0x1e84: 0x093f, 0x1e85: 0x0941,
- 0x1e86: 0x098c, 0x1e87: 0x094c, 0x1e88: 0x0494, 0x1e89: 0x097c, 0x1e8a: 0x0499, 0x1e8b: 0x094e,
- 0x1e8c: 0x04c5, 0x1e8d: 0x0950, 0x1e8e: 0x14a0, 0x1e8f: 0x001e, 0x1e90: 0x0960, 0x1e91: 0x17fa,
- 0x1e92: 0x049b, 0x1e93: 0x02c8, 0x1e94: 0x0962, 0x1e95: 0x0964, 0x1e96: 0x096d, 0x1e97: 0x04a6,
- 0x1e98: 0x04c7, 0x1e99: 0x04a8, 0x1e9a: 0x09df, 0x1e9b: 0x3902, 0x1e9c: 0x3a00, 0x1e9d: 0x3904,
- 0x1e9e: 0x3a02, 0x1e9f: 0x3a04, 0x1ea0: 0x3a08, 0x1ea1: 0x38e6, 0x1ea2: 0x391e, 0x1ea3: 0x3922,
- 0x1ea4: 0x38e2, 0x1ea5: 0x3a0c, 0x1ea6: 0x2321, 0x1ea7: 0x3a10, 0x1ea8: 0x3a14, 0x1ea9: 0x3a18,
- 0x1eaa: 0x3a1c, 0x1eab: 0x3a20, 0x1eac: 0x3a24, 0x1ead: 0x3a28, 0x1eae: 0x3a2c, 0x1eaf: 0x3a30,
- 0x1eb0: 0x3a34, 0x1eb1: 0x2269, 0x1eb2: 0x226d, 0x1eb3: 0x2271, 0x1eb4: 0x2275, 0x1eb5: 0x2279,
- 0x1eb6: 0x227d, 0x1eb7: 0x2281, 0x1eb8: 0x2285, 0x1eb9: 0x2289, 0x1eba: 0x228d, 0x1ebb: 0x2291,
- 0x1ebc: 0x2295, 0x1ebd: 0x2299, 0x1ebe: 0x229d, 0x1ebf: 0x22a1,
- // Block 0x7b, offset 0x1ec0
- 0x1ec0: 0x22a5, 0x1ec1: 0x22a9, 0x1ec2: 0x22ad, 0x1ec3: 0x22b1, 0x1ec4: 0x22b5, 0x1ec5: 0x22b9,
- 0x1ec6: 0x22bd, 0x1ec7: 0x22c1, 0x1ec8: 0x22c5, 0x1ec9: 0x22c9, 0x1eca: 0x22cd, 0x1ecb: 0x22d1,
- 0x1ecc: 0x22d5, 0x1ecd: 0x22d9, 0x1ece: 0x22dd, 0x1ecf: 0x22e1, 0x1ed0: 0x22e5, 0x1ed1: 0x22e9,
- 0x1ed2: 0x22ed, 0x1ed3: 0x22f1, 0x1ed4: 0x22f5, 0x1ed5: 0x22f9, 0x1ed6: 0x22fd, 0x1ed7: 0x2301,
- 0x1ed8: 0x2305, 0x1ed9: 0x2309, 0x1eda: 0x230d, 0x1edb: 0x2311, 0x1edc: 0x2315, 0x1edd: 0x3a38,
- 0x1ede: 0x3a3c, 0x1edf: 0x3a40, 0x1ee0: 0x1e04, 0x1ee1: 0x1d38, 0x1ee2: 0x1d3c, 0x1ee3: 0x1d40,
- 0x1ee4: 0x1d44, 0x1ee5: 0x1d48, 0x1ee6: 0x1d4c, 0x1ee7: 0x1d50, 0x1ee8: 0x1d54, 0x1ee9: 0x1d58,
- 0x1eea: 0x1d5c, 0x1eeb: 0x1d60, 0x1eec: 0x1d64, 0x1eed: 0x1d68, 0x1eee: 0x1d6c, 0x1eef: 0x1d70,
- 0x1ef0: 0x1d74, 0x1ef1: 0x1d78, 0x1ef2: 0x1d7c, 0x1ef3: 0x1d80, 0x1ef4: 0x1d84, 0x1ef5: 0x1d88,
- 0x1ef6: 0x1d8c, 0x1ef7: 0x1d90, 0x1ef8: 0x1d94, 0x1ef9: 0x1d98, 0x1efa: 0x1d9c, 0x1efb: 0x1da0,
- 0x1efc: 0x1da4, 0x1efd: 0x1da8, 0x1efe: 0x1dac,
- // Block 0x7c, offset 0x1f00
- 0x1f02: 0x1db0, 0x1f03: 0x1db4, 0x1f04: 0x1db8, 0x1f05: 0x1dbc,
- 0x1f06: 0x1dc0, 0x1f07: 0x1dc4, 0x1f0a: 0x1dc8, 0x1f0b: 0x1dcc,
- 0x1f0c: 0x1dd0, 0x1f0d: 0x1dd4, 0x1f0e: 0x1dd8, 0x1f0f: 0x1ddc,
- 0x1f12: 0x1de0, 0x1f13: 0x1de4, 0x1f14: 0x1de8, 0x1f15: 0x1dec, 0x1f16: 0x1df0, 0x1f17: 0x1df4,
- 0x1f1a: 0x1df8, 0x1f1b: 0x1dfc, 0x1f1c: 0x1e00,
- 0x1f20: 0x3a44, 0x1f21: 0x3a47, 0x1f22: 0x3a4a, 0x1f23: 0x0009,
- 0x1f24: 0x3a4d, 0x1f25: 0x3a50, 0x1f26: 0x3a53, 0x1f28: 0x3a57, 0x1f29: 0x3a5b,
- 0x1f2a: 0x3a5f, 0x1f2b: 0x3a63, 0x1f2c: 0x3a67, 0x1f2d: 0x3a6b, 0x1f2e: 0x3a6f,
- // Block 0x7d, offset 0x1f40
- 0x1f5a: 0x3a73, 0x1f5c: 0x3a7c,
- 0x1f6b: 0x3a85,
- // Block 0x7e, offset 0x1f80
- 0x1f9e: 0x3a8e, 0x1f9f: 0x3a97, 0x1fa0: 0x3aa0, 0x1fa1: 0x3aad, 0x1fa2: 0x3aba, 0x1fa3: 0x3ac7,
- 0x1fa4: 0x3ad4,
- // Block 0x7f, offset 0x1fc0
- 0x1ffb: 0x3ae1,
- 0x1ffc: 0x3aea, 0x1ffd: 0x3af3, 0x1ffe: 0x3b00, 0x1fff: 0x3b0d,
- // Block 0x80, offset 0x2000
- 0x2000: 0x3b1a,
- // Block 0x81, offset 0x2040
- 0x2040: 0x0906, 0x2041: 0x090b, 0x2042: 0x14ad, 0x2043: 0x090d, 0x2044: 0x090f, 0x2045: 0x14d9,
- 0x2046: 0x0914, 0x2047: 0x0916, 0x2048: 0x0918, 0x2049: 0x091a, 0x204a: 0x091c, 0x204b: 0x091e,
- 0x204c: 0x0920, 0x204d: 0x0922, 0x204e: 0x0924, 0x204f: 0x0929, 0x2050: 0x14c8, 0x2051: 0x092b,
- 0x2052: 0x17f6, 0x2053: 0x092d, 0x2054: 0x092f, 0x2055: 0x155f, 0x2056: 0x0931, 0x2057: 0x1570,
- 0x2058: 0x17f8, 0x2059: 0x14d4, 0x205a: 0x0007, 0x205b: 0x093d, 0x205c: 0x0984, 0x205d: 0x093f,
- 0x205e: 0x0941, 0x205f: 0x098c, 0x2060: 0x094c, 0x2061: 0x0494, 0x2062: 0x097c, 0x2063: 0x0499,
- 0x2064: 0x094e, 0x2065: 0x04c5, 0x2066: 0x0950, 0x2067: 0x14a0, 0x2068: 0x001e, 0x2069: 0x0960,
- 0x206a: 0x17fa, 0x206b: 0x049b, 0x206c: 0x02c8, 0x206d: 0x0962, 0x206e: 0x0964, 0x206f: 0x096d,
- 0x2070: 0x04a6, 0x2071: 0x04c7, 0x2072: 0x04a8, 0x2073: 0x09df, 0x2074: 0x0906, 0x2075: 0x090b,
- 0x2076: 0x14ad, 0x2077: 0x090d, 0x2078: 0x090f, 0x2079: 0x14d9, 0x207a: 0x0914, 0x207b: 0x0916,
- 0x207c: 0x0918, 0x207d: 0x091a, 0x207e: 0x091c, 0x207f: 0x091e,
- // Block 0x82, offset 0x2080
- 0x2080: 0x0920, 0x2081: 0x0922, 0x2082: 0x0924, 0x2083: 0x0929, 0x2084: 0x14c8, 0x2085: 0x092b,
- 0x2086: 0x17f6, 0x2087: 0x092d, 0x2088: 0x092f, 0x2089: 0x155f, 0x208a: 0x0931, 0x208b: 0x1570,
- 0x208c: 0x17f8, 0x208d: 0x14d4, 0x208e: 0x0007, 0x208f: 0x093d, 0x2090: 0x0984, 0x2091: 0x093f,
- 0x2092: 0x0941, 0x2093: 0x098c, 0x2094: 0x094c, 0x2096: 0x097c, 0x2097: 0x0499,
- 0x2098: 0x094e, 0x2099: 0x04c5, 0x209a: 0x0950, 0x209b: 0x14a0, 0x209c: 0x001e, 0x209d: 0x0960,
- 0x209e: 0x17fa, 0x209f: 0x049b, 0x20a0: 0x02c8, 0x20a1: 0x0962, 0x20a2: 0x0964, 0x20a3: 0x096d,
- 0x20a4: 0x04a6, 0x20a5: 0x04c7, 0x20a6: 0x04a8, 0x20a7: 0x09df, 0x20a8: 0x0906, 0x20a9: 0x090b,
- 0x20aa: 0x14ad, 0x20ab: 0x090d, 0x20ac: 0x090f, 0x20ad: 0x14d9, 0x20ae: 0x0914, 0x20af: 0x0916,
- 0x20b0: 0x0918, 0x20b1: 0x091a, 0x20b2: 0x091c, 0x20b3: 0x091e, 0x20b4: 0x0920, 0x20b5: 0x0922,
- 0x20b6: 0x0924, 0x20b7: 0x0929, 0x20b8: 0x14c8, 0x20b9: 0x092b, 0x20ba: 0x17f6, 0x20bb: 0x092d,
- 0x20bc: 0x092f, 0x20bd: 0x155f, 0x20be: 0x0931, 0x20bf: 0x1570,
- // Block 0x83, offset 0x20c0
- 0x20c0: 0x17f8, 0x20c1: 0x14d4, 0x20c2: 0x0007, 0x20c3: 0x093d, 0x20c4: 0x0984, 0x20c5: 0x093f,
- 0x20c6: 0x0941, 0x20c7: 0x098c, 0x20c8: 0x094c, 0x20c9: 0x0494, 0x20ca: 0x097c, 0x20cb: 0x0499,
- 0x20cc: 0x094e, 0x20cd: 0x04c5, 0x20ce: 0x0950, 0x20cf: 0x14a0, 0x20d0: 0x001e, 0x20d1: 0x0960,
- 0x20d2: 0x17fa, 0x20d3: 0x049b, 0x20d4: 0x02c8, 0x20d5: 0x0962, 0x20d6: 0x0964, 0x20d7: 0x096d,
- 0x20d8: 0x04a6, 0x20d9: 0x04c7, 0x20da: 0x04a8, 0x20db: 0x09df, 0x20dc: 0x0906,
- 0x20de: 0x14ad, 0x20df: 0x090d, 0x20e2: 0x0914,
- 0x20e5: 0x091a, 0x20e6: 0x091c, 0x20e9: 0x0922,
- 0x20ea: 0x0924, 0x20eb: 0x0929, 0x20ec: 0x14c8, 0x20ee: 0x17f6, 0x20ef: 0x092d,
- 0x20f0: 0x092f, 0x20f1: 0x155f, 0x20f2: 0x0931, 0x20f3: 0x1570, 0x20f4: 0x17f8, 0x20f5: 0x14d4,
- 0x20f6: 0x0007, 0x20f7: 0x093d, 0x20f8: 0x0984, 0x20f9: 0x093f, 0x20fb: 0x098c,
- 0x20fd: 0x0494, 0x20fe: 0x097c, 0x20ff: 0x0499,
- // Block 0x84, offset 0x2100
- 0x2100: 0x094e, 0x2101: 0x04c5, 0x2102: 0x0950, 0x2103: 0x14a0, 0x2105: 0x0960,
- 0x2106: 0x17fa, 0x2107: 0x049b, 0x2108: 0x02c8, 0x2109: 0x0962, 0x210a: 0x0964, 0x210b: 0x096d,
- 0x210c: 0x04a6, 0x210d: 0x04c7, 0x210e: 0x04a8, 0x210f: 0x09df, 0x2110: 0x0906, 0x2111: 0x090b,
- 0x2112: 0x14ad, 0x2113: 0x090d, 0x2114: 0x090f, 0x2115: 0x14d9, 0x2116: 0x0914, 0x2117: 0x0916,
- 0x2118: 0x0918, 0x2119: 0x091a, 0x211a: 0x091c, 0x211b: 0x091e, 0x211c: 0x0920, 0x211d: 0x0922,
- 0x211e: 0x0924, 0x211f: 0x0929, 0x2120: 0x14c8, 0x2121: 0x092b, 0x2122: 0x17f6, 0x2123: 0x092d,
- 0x2124: 0x092f, 0x2125: 0x155f, 0x2126: 0x0931, 0x2127: 0x1570, 0x2128: 0x17f8, 0x2129: 0x14d4,
- 0x212a: 0x0007, 0x212b: 0x093d, 0x212c: 0x0984, 0x212d: 0x093f, 0x212e: 0x0941, 0x212f: 0x098c,
- 0x2130: 0x094c, 0x2131: 0x0494, 0x2132: 0x097c, 0x2133: 0x0499, 0x2134: 0x094e, 0x2135: 0x04c5,
- 0x2136: 0x0950, 0x2137: 0x14a0, 0x2138: 0x001e, 0x2139: 0x0960, 0x213a: 0x17fa, 0x213b: 0x049b,
- 0x213c: 0x02c8, 0x213d: 0x0962, 0x213e: 0x0964, 0x213f: 0x096d,
- // Block 0x85, offset 0x2140
- 0x2140: 0x04a6, 0x2141: 0x04c7, 0x2142: 0x04a8, 0x2143: 0x09df, 0x2144: 0x0906, 0x2145: 0x090b,
- 0x2147: 0x090d, 0x2148: 0x090f, 0x2149: 0x14d9, 0x214a: 0x0914,
- 0x214d: 0x091a, 0x214e: 0x091c, 0x214f: 0x091e, 0x2150: 0x0920, 0x2151: 0x0922,
- 0x2152: 0x0924, 0x2153: 0x0929, 0x2154: 0x14c8, 0x2156: 0x17f6, 0x2157: 0x092d,
- 0x2158: 0x092f, 0x2159: 0x155f, 0x215a: 0x0931, 0x215b: 0x1570, 0x215c: 0x17f8,
- 0x215e: 0x0007, 0x215f: 0x093d, 0x2160: 0x0984, 0x2161: 0x093f, 0x2162: 0x0941, 0x2163: 0x098c,
- 0x2164: 0x094c, 0x2165: 0x0494, 0x2166: 0x097c, 0x2167: 0x0499, 0x2168: 0x094e, 0x2169: 0x04c5,
- 0x216a: 0x0950, 0x216b: 0x14a0, 0x216c: 0x001e, 0x216d: 0x0960, 0x216e: 0x17fa, 0x216f: 0x049b,
- 0x2170: 0x02c8, 0x2171: 0x0962, 0x2172: 0x0964, 0x2173: 0x096d, 0x2174: 0x04a6, 0x2175: 0x04c7,
- 0x2176: 0x04a8, 0x2177: 0x09df, 0x2178: 0x0906, 0x2179: 0x090b, 0x217b: 0x090d,
- 0x217c: 0x090f, 0x217d: 0x14d9, 0x217e: 0x0914,
- // Block 0x86, offset 0x2180
- 0x2180: 0x0918, 0x2181: 0x091a, 0x2182: 0x091c, 0x2183: 0x091e, 0x2184: 0x0920,
- 0x2186: 0x0924, 0x218a: 0x17f6, 0x218b: 0x092d,
- 0x218c: 0x092f, 0x218d: 0x155f, 0x218e: 0x0931, 0x218f: 0x1570, 0x2190: 0x17f8,
- 0x2192: 0x0007, 0x2193: 0x093d, 0x2194: 0x0984, 0x2195: 0x093f, 0x2196: 0x0941, 0x2197: 0x098c,
- 0x2198: 0x094c, 0x2199: 0x0494, 0x219a: 0x097c, 0x219b: 0x0499, 0x219c: 0x094e, 0x219d: 0x04c5,
- 0x219e: 0x0950, 0x219f: 0x14a0, 0x21a0: 0x001e, 0x21a1: 0x0960, 0x21a2: 0x17fa, 0x21a3: 0x049b,
- 0x21a4: 0x02c8, 0x21a5: 0x0962, 0x21a6: 0x0964, 0x21a7: 0x096d, 0x21a8: 0x04a6, 0x21a9: 0x04c7,
- 0x21aa: 0x04a8, 0x21ab: 0x09df, 0x21ac: 0x0906, 0x21ad: 0x090b, 0x21ae: 0x14ad, 0x21af: 0x090d,
- 0x21b0: 0x090f, 0x21b1: 0x14d9, 0x21b2: 0x0914, 0x21b3: 0x0916, 0x21b4: 0x0918, 0x21b5: 0x091a,
- 0x21b6: 0x091c, 0x21b7: 0x091e, 0x21b8: 0x0920, 0x21b9: 0x0922, 0x21ba: 0x0924, 0x21bb: 0x0929,
- 0x21bc: 0x14c8, 0x21bd: 0x092b, 0x21be: 0x17f6, 0x21bf: 0x092d,
- // Block 0x87, offset 0x21c0
- 0x21c0: 0x092f, 0x21c1: 0x155f, 0x21c2: 0x0931, 0x21c3: 0x1570, 0x21c4: 0x17f8, 0x21c5: 0x14d4,
- 0x21c6: 0x0007, 0x21c7: 0x093d, 0x21c8: 0x0984, 0x21c9: 0x093f, 0x21ca: 0x0941, 0x21cb: 0x098c,
- 0x21cc: 0x094c, 0x21cd: 0x0494, 0x21ce: 0x097c, 0x21cf: 0x0499, 0x21d0: 0x094e, 0x21d1: 0x04c5,
- 0x21d2: 0x0950, 0x21d3: 0x14a0, 0x21d4: 0x001e, 0x21d5: 0x0960, 0x21d6: 0x17fa, 0x21d7: 0x049b,
- 0x21d8: 0x02c8, 0x21d9: 0x0962, 0x21da: 0x0964, 0x21db: 0x096d, 0x21dc: 0x04a6, 0x21dd: 0x04c7,
- 0x21de: 0x04a8, 0x21df: 0x09df, 0x21e0: 0x0906, 0x21e1: 0x090b, 0x21e2: 0x14ad, 0x21e3: 0x090d,
- 0x21e4: 0x090f, 0x21e5: 0x14d9, 0x21e6: 0x0914, 0x21e7: 0x0916, 0x21e8: 0x0918, 0x21e9: 0x091a,
- 0x21ea: 0x091c, 0x21eb: 0x091e, 0x21ec: 0x0920, 0x21ed: 0x0922, 0x21ee: 0x0924, 0x21ef: 0x0929,
- 0x21f0: 0x14c8, 0x21f1: 0x092b, 0x21f2: 0x17f6, 0x21f3: 0x092d, 0x21f4: 0x092f, 0x21f5: 0x155f,
- 0x21f6: 0x0931, 0x21f7: 0x1570, 0x21f8: 0x17f8, 0x21f9: 0x14d4, 0x21fa: 0x0007, 0x21fb: 0x093d,
- 0x21fc: 0x0984, 0x21fd: 0x093f, 0x21fe: 0x0941, 0x21ff: 0x098c,
- // Block 0x88, offset 0x2200
- 0x2200: 0x094c, 0x2201: 0x0494, 0x2202: 0x097c, 0x2203: 0x0499, 0x2204: 0x094e, 0x2205: 0x04c5,
- 0x2206: 0x0950, 0x2207: 0x14a0, 0x2208: 0x001e, 0x2209: 0x0960, 0x220a: 0x17fa, 0x220b: 0x049b,
- 0x220c: 0x02c8, 0x220d: 0x0962, 0x220e: 0x0964, 0x220f: 0x096d, 0x2210: 0x04a6, 0x2211: 0x04c7,
- 0x2212: 0x04a8, 0x2213: 0x09df, 0x2214: 0x0906, 0x2215: 0x090b, 0x2216: 0x14ad, 0x2217: 0x090d,
- 0x2218: 0x090f, 0x2219: 0x14d9, 0x221a: 0x0914, 0x221b: 0x0916, 0x221c: 0x0918, 0x221d: 0x091a,
- 0x221e: 0x091c, 0x221f: 0x091e, 0x2220: 0x0920, 0x2221: 0x0922, 0x2222: 0x0924, 0x2223: 0x0929,
- 0x2224: 0x14c8, 0x2225: 0x092b, 0x2226: 0x17f6, 0x2227: 0x092d, 0x2228: 0x092f, 0x2229: 0x155f,
- 0x222a: 0x0931, 0x222b: 0x1570, 0x222c: 0x17f8, 0x222d: 0x14d4, 0x222e: 0x0007, 0x222f: 0x093d,
- 0x2230: 0x0984, 0x2231: 0x093f, 0x2232: 0x0941, 0x2233: 0x098c, 0x2234: 0x094c, 0x2235: 0x0494,
- 0x2236: 0x097c, 0x2237: 0x0499, 0x2238: 0x094e, 0x2239: 0x04c5, 0x223a: 0x0950, 0x223b: 0x14a0,
- 0x223c: 0x001e, 0x223d: 0x0960, 0x223e: 0x17fa, 0x223f: 0x049b,
- // Block 0x89, offset 0x2240
- 0x2240: 0x02c8, 0x2241: 0x0962, 0x2242: 0x0964, 0x2243: 0x096d, 0x2244: 0x04a6, 0x2245: 0x04c7,
- 0x2246: 0x04a8, 0x2247: 0x09df, 0x2248: 0x0906, 0x2249: 0x090b, 0x224a: 0x14ad, 0x224b: 0x090d,
- 0x224c: 0x090f, 0x224d: 0x14d9, 0x224e: 0x0914, 0x224f: 0x0916, 0x2250: 0x0918, 0x2251: 0x091a,
- 0x2252: 0x091c, 0x2253: 0x091e, 0x2254: 0x0920, 0x2255: 0x0922, 0x2256: 0x0924, 0x2257: 0x0929,
- 0x2258: 0x14c8, 0x2259: 0x092b, 0x225a: 0x17f6, 0x225b: 0x092d, 0x225c: 0x092f, 0x225d: 0x155f,
- 0x225e: 0x0931, 0x225f: 0x1570, 0x2260: 0x17f8, 0x2261: 0x14d4, 0x2262: 0x0007, 0x2263: 0x093d,
- 0x2264: 0x0984, 0x2265: 0x093f, 0x2266: 0x0941, 0x2267: 0x098c, 0x2268: 0x094c, 0x2269: 0x0494,
- 0x226a: 0x097c, 0x226b: 0x0499, 0x226c: 0x094e, 0x226d: 0x04c5, 0x226e: 0x0950, 0x226f: 0x14a0,
- 0x2270: 0x001e, 0x2271: 0x0960, 0x2272: 0x17fa, 0x2273: 0x049b, 0x2274: 0x02c8, 0x2275: 0x0962,
- 0x2276: 0x0964, 0x2277: 0x096d, 0x2278: 0x04a6, 0x2279: 0x04c7, 0x227a: 0x04a8, 0x227b: 0x09df,
- 0x227c: 0x0906, 0x227d: 0x090b, 0x227e: 0x14ad, 0x227f: 0x090d,
- // Block 0x8a, offset 0x2280
- 0x2280: 0x090f, 0x2281: 0x14d9, 0x2282: 0x0914, 0x2283: 0x0916, 0x2284: 0x0918, 0x2285: 0x091a,
- 0x2286: 0x091c, 0x2287: 0x091e, 0x2288: 0x0920, 0x2289: 0x0922, 0x228a: 0x0924, 0x228b: 0x0929,
- 0x228c: 0x14c8, 0x228d: 0x092b, 0x228e: 0x17f6, 0x228f: 0x092d, 0x2290: 0x092f, 0x2291: 0x155f,
- 0x2292: 0x0931, 0x2293: 0x1570, 0x2294: 0x17f8, 0x2295: 0x14d4, 0x2296: 0x0007, 0x2297: 0x093d,
- 0x2298: 0x0984, 0x2299: 0x093f, 0x229a: 0x0941, 0x229b: 0x098c, 0x229c: 0x094c, 0x229d: 0x0494,
- 0x229e: 0x097c, 0x229f: 0x0499, 0x22a0: 0x094e, 0x22a1: 0x04c5, 0x22a2: 0x0950, 0x22a3: 0x14a0,
- 0x22a4: 0x001e, 0x22a5: 0x0960, 0x22a6: 0x17fa, 0x22a7: 0x049b, 0x22a8: 0x02c8, 0x22a9: 0x0962,
- 0x22aa: 0x0964, 0x22ab: 0x096d, 0x22ac: 0x04a6, 0x22ad: 0x04c7, 0x22ae: 0x04a8, 0x22af: 0x09df,
- 0x22b0: 0x0906, 0x22b1: 0x090b, 0x22b2: 0x14ad, 0x22b3: 0x090d, 0x22b4: 0x090f, 0x22b5: 0x14d9,
- 0x22b6: 0x0914, 0x22b7: 0x0916, 0x22b8: 0x0918, 0x22b9: 0x091a, 0x22ba: 0x091c, 0x22bb: 0x091e,
- 0x22bc: 0x0920, 0x22bd: 0x0922, 0x22be: 0x0924, 0x22bf: 0x0929,
- // Block 0x8b, offset 0x22c0
- 0x22c0: 0x14c8, 0x22c1: 0x092b, 0x22c2: 0x17f6, 0x22c3: 0x092d, 0x22c4: 0x092f, 0x22c5: 0x155f,
- 0x22c6: 0x0931, 0x22c7: 0x1570, 0x22c8: 0x17f8, 0x22c9: 0x14d4, 0x22ca: 0x0007, 0x22cb: 0x093d,
- 0x22cc: 0x0984, 0x22cd: 0x093f, 0x22ce: 0x0941, 0x22cf: 0x098c, 0x22d0: 0x094c, 0x22d1: 0x0494,
- 0x22d2: 0x097c, 0x22d3: 0x0499, 0x22d4: 0x094e, 0x22d5: 0x04c5, 0x22d6: 0x0950, 0x22d7: 0x14a0,
- 0x22d8: 0x001e, 0x22d9: 0x0960, 0x22da: 0x17fa, 0x22db: 0x049b, 0x22dc: 0x02c8, 0x22dd: 0x0962,
- 0x22de: 0x0964, 0x22df: 0x096d, 0x22e0: 0x04a6, 0x22e1: 0x04c7, 0x22e2: 0x04a8, 0x22e3: 0x09df,
- 0x22e4: 0x3b27, 0x22e5: 0x3b2a, 0x22e8: 0x3b2d, 0x22e9: 0x3b30,
- 0x22ea: 0x14eb, 0x22eb: 0x3b33, 0x22ec: 0x3b36, 0x22ed: 0x3b39, 0x22ee: 0x3b3c, 0x22ef: 0x057b,
- 0x22f0: 0x3b3f, 0x22f1: 0x3b42, 0x22f2: 0x3b45, 0x22f3: 0x3b48, 0x22f4: 0x3b4b, 0x22f5: 0x3b4e,
- 0x22f6: 0x3b51, 0x22f7: 0x14ee, 0x22f8: 0x3b54, 0x22f9: 0x057b, 0x22fa: 0x0581, 0x22fb: 0x3b57,
- 0x22fc: 0x055f, 0x22fd: 0x3b5a, 0x22fe: 0x3b5d, 0x22ff: 0x3b60,
- // Block 0x8c, offset 0x2300
- 0x2300: 0x14d6, 0x2301: 0x3b63, 0x2302: 0x3b67, 0x2303: 0x0559, 0x2304: 0x0973, 0x2305: 0x0976,
- 0x2306: 0x057e, 0x2307: 0x3b6a, 0x2308: 0x3b6d, 0x2309: 0x055c, 0x230a: 0x12fd, 0x230b: 0x0572,
- 0x230c: 0x3b70, 0x230d: 0x0015, 0x230e: 0x3b73, 0x230f: 0x3b76, 0x2310: 0x3b79, 0x2311: 0x056f,
- 0x2312: 0x0575, 0x2313: 0x0578, 0x2314: 0x3b7c, 0x2315: 0x3b7f, 0x2316: 0x3b82, 0x2317: 0x056c,
- 0x2318: 0x0979, 0x2319: 0x3b85, 0x231a: 0x3b88, 0x231b: 0x3b8b, 0x231c: 0x057e, 0x231d: 0x055c,
- 0x231e: 0x0572, 0x231f: 0x056c, 0x2320: 0x0575, 0x2321: 0x056f, 0x2322: 0x3b2d, 0x2323: 0x3b30,
- 0x2324: 0x14eb, 0x2325: 0x3b33, 0x2326: 0x3b36, 0x2327: 0x3b39, 0x2328: 0x3b3c, 0x2329: 0x057b,
- 0x232a: 0x3b3f, 0x232b: 0x3b42, 0x232c: 0x3b45, 0x232d: 0x3b48, 0x232e: 0x3b4b, 0x232f: 0x3b4e,
- 0x2330: 0x3b51, 0x2331: 0x14ee, 0x2332: 0x3b54, 0x2333: 0x057b, 0x2334: 0x0581, 0x2335: 0x3b57,
- 0x2336: 0x055f, 0x2337: 0x3b5a, 0x2338: 0x3b5d, 0x2339: 0x3b60, 0x233a: 0x14d6, 0x233b: 0x3b63,
- 0x233c: 0x3b67, 0x233d: 0x0559, 0x233e: 0x0973, 0x233f: 0x0976,
- // Block 0x8d, offset 0x2340
- 0x2340: 0x057e, 0x2341: 0x3b6a, 0x2342: 0x3b6d, 0x2343: 0x055c, 0x2344: 0x12fd, 0x2345: 0x0572,
- 0x2346: 0x3b70, 0x2347: 0x0015, 0x2348: 0x3b73, 0x2349: 0x3b76, 0x234a: 0x3b79, 0x234b: 0x056f,
- 0x234c: 0x0575, 0x234d: 0x0578, 0x234e: 0x3b7c, 0x234f: 0x3b7f, 0x2350: 0x3b82, 0x2351: 0x056c,
- 0x2352: 0x0979, 0x2353: 0x3b85, 0x2354: 0x3b88, 0x2355: 0x3b8b, 0x2356: 0x057e, 0x2357: 0x055c,
- 0x2358: 0x0572, 0x2359: 0x056c, 0x235a: 0x0575, 0x235b: 0x056f, 0x235c: 0x3b2d, 0x235d: 0x3b30,
- 0x235e: 0x14eb, 0x235f: 0x3b33, 0x2360: 0x3b36, 0x2361: 0x3b39, 0x2362: 0x3b3c, 0x2363: 0x057b,
- 0x2364: 0x3b3f, 0x2365: 0x3b42, 0x2366: 0x3b45, 0x2367: 0x3b48, 0x2368: 0x3b4b, 0x2369: 0x3b4e,
- 0x236a: 0x3b51, 0x236b: 0x14ee, 0x236c: 0x3b54, 0x236d: 0x057b, 0x236e: 0x0581, 0x236f: 0x3b57,
- 0x2370: 0x055f, 0x2371: 0x3b5a, 0x2372: 0x3b5d, 0x2373: 0x3b60, 0x2374: 0x14d6, 0x2375: 0x3b63,
- 0x2376: 0x3b67, 0x2377: 0x0559, 0x2378: 0x0973, 0x2379: 0x0976, 0x237a: 0x057e, 0x237b: 0x3b6a,
- 0x237c: 0x3b6d, 0x237d: 0x055c, 0x237e: 0x12fd, 0x237f: 0x0572,
- // Block 0x8e, offset 0x2380
- 0x2380: 0x3b70, 0x2381: 0x0015, 0x2382: 0x3b73, 0x2383: 0x3b76, 0x2384: 0x3b79, 0x2385: 0x056f,
- 0x2386: 0x0575, 0x2387: 0x0578, 0x2388: 0x3b7c, 0x2389: 0x3b7f, 0x238a: 0x3b82, 0x238b: 0x056c,
- 0x238c: 0x0979, 0x238d: 0x3b85, 0x238e: 0x3b88, 0x238f: 0x3b8b, 0x2390: 0x057e, 0x2391: 0x055c,
- 0x2392: 0x0572, 0x2393: 0x056c, 0x2394: 0x0575, 0x2395: 0x056f, 0x2396: 0x3b2d, 0x2397: 0x3b30,
- 0x2398: 0x14eb, 0x2399: 0x3b33, 0x239a: 0x3b36, 0x239b: 0x3b39, 0x239c: 0x3b3c, 0x239d: 0x057b,
- 0x239e: 0x3b3f, 0x239f: 0x3b42, 0x23a0: 0x3b45, 0x23a1: 0x3b48, 0x23a2: 0x3b4b, 0x23a3: 0x3b4e,
- 0x23a4: 0x3b51, 0x23a5: 0x14ee, 0x23a6: 0x3b54, 0x23a7: 0x057b, 0x23a8: 0x0581, 0x23a9: 0x3b57,
- 0x23aa: 0x055f, 0x23ab: 0x3b5a, 0x23ac: 0x3b5d, 0x23ad: 0x3b60, 0x23ae: 0x14d6, 0x23af: 0x3b63,
- 0x23b0: 0x3b67, 0x23b1: 0x0559, 0x23b2: 0x0973, 0x23b3: 0x0976, 0x23b4: 0x057e, 0x23b5: 0x3b6a,
- 0x23b6: 0x3b6d, 0x23b7: 0x055c, 0x23b8: 0x12fd, 0x23b9: 0x0572, 0x23ba: 0x3b70, 0x23bb: 0x0015,
- 0x23bc: 0x3b73, 0x23bd: 0x3b76, 0x23be: 0x3b79, 0x23bf: 0x056f,
- // Block 0x8f, offset 0x23c0
- 0x23c0: 0x0575, 0x23c1: 0x0578, 0x23c2: 0x3b7c, 0x23c3: 0x3b7f, 0x23c4: 0x3b82, 0x23c5: 0x056c,
- 0x23c6: 0x0979, 0x23c7: 0x3b85, 0x23c8: 0x3b88, 0x23c9: 0x3b8b, 0x23ca: 0x057e, 0x23cb: 0x055c,
- 0x23cc: 0x0572, 0x23cd: 0x056c, 0x23ce: 0x0575, 0x23cf: 0x056f, 0x23d0: 0x3b2d, 0x23d1: 0x3b30,
- 0x23d2: 0x14eb, 0x23d3: 0x3b33, 0x23d4: 0x3b36, 0x23d5: 0x3b39, 0x23d6: 0x3b3c, 0x23d7: 0x057b,
- 0x23d8: 0x3b3f, 0x23d9: 0x3b42, 0x23da: 0x3b45, 0x23db: 0x3b48, 0x23dc: 0x3b4b, 0x23dd: 0x3b4e,
- 0x23de: 0x3b51, 0x23df: 0x14ee, 0x23e0: 0x3b54, 0x23e1: 0x057b, 0x23e2: 0x0581, 0x23e3: 0x3b57,
- 0x23e4: 0x055f, 0x23e5: 0x3b5a, 0x23e6: 0x3b5d, 0x23e7: 0x3b60, 0x23e8: 0x14d6, 0x23e9: 0x3b63,
- 0x23ea: 0x3b67, 0x23eb: 0x0559, 0x23ec: 0x0973, 0x23ed: 0x0976, 0x23ee: 0x057e, 0x23ef: 0x3b6a,
- 0x23f0: 0x3b6d, 0x23f1: 0x055c, 0x23f2: 0x12fd, 0x23f3: 0x0572, 0x23f4: 0x3b70, 0x23f5: 0x0015,
- 0x23f6: 0x3b73, 0x23f7: 0x3b76, 0x23f8: 0x3b79, 0x23f9: 0x056f, 0x23fa: 0x0575, 0x23fb: 0x0578,
- 0x23fc: 0x3b7c, 0x23fd: 0x3b7f, 0x23fe: 0x3b82, 0x23ff: 0x056c,
- // Block 0x90, offset 0x2400
- 0x2400: 0x0979, 0x2401: 0x3b85, 0x2402: 0x3b88, 0x2403: 0x3b8b, 0x2404: 0x057e, 0x2405: 0x055c,
- 0x2406: 0x0572, 0x2407: 0x056c, 0x2408: 0x0575, 0x2409: 0x056f, 0x240a: 0x3b8f, 0x240b: 0x3b92,
- 0x240e: 0x1486, 0x240f: 0x001c, 0x2410: 0x000d, 0x2411: 0x000f,
- 0x2412: 0x1488, 0x2413: 0x148a, 0x2414: 0x148c, 0x2415: 0x148e, 0x2416: 0x1490, 0x2417: 0x1492,
- 0x2418: 0x1486, 0x2419: 0x001c, 0x241a: 0x000d, 0x241b: 0x000f, 0x241c: 0x1488, 0x241d: 0x148a,
- 0x241e: 0x148c, 0x241f: 0x148e, 0x2420: 0x1490, 0x2421: 0x1492, 0x2422: 0x1486, 0x2423: 0x001c,
- 0x2424: 0x000d, 0x2425: 0x000f, 0x2426: 0x1488, 0x2427: 0x148a, 0x2428: 0x148c, 0x2429: 0x148e,
- 0x242a: 0x1490, 0x242b: 0x1492, 0x242c: 0x1486, 0x242d: 0x001c, 0x242e: 0x000d, 0x242f: 0x000f,
- 0x2430: 0x1488, 0x2431: 0x148a, 0x2432: 0x148c, 0x2433: 0x148e, 0x2434: 0x1490, 0x2435: 0x1492,
- 0x2436: 0x1486, 0x2437: 0x001c, 0x2438: 0x000d, 0x2439: 0x000f, 0x243a: 0x1488, 0x243b: 0x148a,
- 0x243c: 0x148c, 0x243d: 0x148e, 0x243e: 0x1490, 0x243f: 0x1492,
- // Block 0x91, offset 0x2440
- 0x2440: 0x3b95, 0x2441: 0x3b98, 0x2442: 0x3b9b, 0x2443: 0x3b9e, 0x2444: 0x3ba1, 0x2445: 0x3ba4,
- 0x2446: 0x3ba7, 0x2447: 0x3baa, 0x2448: 0x3bad, 0x2449: 0x3bb0, 0x244a: 0x3bb3,
- 0x2450: 0x3bb6, 0x2451: 0x3bba,
- 0x2452: 0x3bbe, 0x2453: 0x3bc2, 0x2454: 0x3bc6, 0x2455: 0x3bca, 0x2456: 0x3bce, 0x2457: 0x3bd2,
- 0x2458: 0x3bd6, 0x2459: 0x3bda, 0x245a: 0x3bde, 0x245b: 0x3be2, 0x245c: 0x3be6, 0x245d: 0x3bea,
- 0x245e: 0x3bee, 0x245f: 0x3bf2, 0x2460: 0x3bf6, 0x2461: 0x3bfa, 0x2462: 0x3bfe, 0x2463: 0x3c02,
- 0x2464: 0x3c06, 0x2465: 0x3c0a, 0x2466: 0x3c0e, 0x2467: 0x3c12, 0x2468: 0x3c16, 0x2469: 0x3c1a,
- 0x246a: 0x3c1e, 0x246b: 0x14ad, 0x246c: 0x092b, 0x246d: 0x3c26, 0x246e: 0x3c29,
- 0x2470: 0x0906, 0x2471: 0x090b, 0x2472: 0x14ad, 0x2473: 0x090d, 0x2474: 0x090f, 0x2475: 0x14d9,
- 0x2476: 0x0914, 0x2477: 0x0916, 0x2478: 0x0918, 0x2479: 0x091a, 0x247a: 0x091c, 0x247b: 0x091e,
- 0x247c: 0x0920, 0x247d: 0x0922, 0x247e: 0x0924, 0x247f: 0x0929,
- // Block 0x92, offset 0x2480
- 0x2480: 0x14c8, 0x2481: 0x092b, 0x2482: 0x17f6, 0x2483: 0x092d, 0x2484: 0x092f, 0x2485: 0x155f,
- 0x2486: 0x0931, 0x2487: 0x1570, 0x2488: 0x17f8, 0x2489: 0x14d4, 0x248a: 0x3c2c, 0x248b: 0x293d,
- 0x248c: 0x3c2f, 0x248d: 0x3c32, 0x248e: 0x3c35, 0x248f: 0x3c39,
- // Block 0x93, offset 0x24c0
- 0x24d0: 0x3c3c,
- // Block 0x94, offset 0x2500
- 0x2500: 0x3c3f, 0x2501: 0x3c46, 0x2502: 0x2291,
- 0x2510: 0x1922, 0x2511: 0x3c4d,
- 0x2512: 0x3c51, 0x2513: 0x1cb3, 0x2514: 0x183e, 0x2515: 0x3c55, 0x2516: 0x3c59, 0x2517: 0x1ed0,
- 0x2518: 0x3c5d, 0x2519: 0x3c61, 0x251a: 0x3c65, 0x251b: 0x2d49, 0x251c: 0x3c69, 0x251d: 0x3c6d,
- 0x251e: 0x3c71, 0x251f: 0x3c75, 0x2520: 0x3c79, 0x2521: 0x3c7d, 0x2522: 0x19b2, 0x2523: 0x3c81,
- 0x2524: 0x3c85, 0x2525: 0x3c89, 0x2526: 0x3c8d, 0x2527: 0x3c91, 0x2528: 0x3c95, 0x2529: 0x1826,
- 0x252a: 0x1eb0, 0x252b: 0x3c99, 0x252c: 0x21c7, 0x252d: 0x1ebc, 0x252e: 0x21cb, 0x252f: 0x3c9d,
- 0x2530: 0x1a92, 0x2531: 0x3ca1, 0x2532: 0x3ca5, 0x2533: 0x3ca9, 0x2534: 0x3cad, 0x2535: 0x3cb1,
- 0x2536: 0x2183, 0x2537: 0x194a, 0x2538: 0x3cb5, 0x2539: 0x3cb9, 0x253a: 0x3cbd,
- // Block 0x95, offset 0x2540
- 0x2540: 0x3cc1, 0x2541: 0x3ccb, 0x2542: 0x3cd5, 0x2543: 0x3cdf, 0x2544: 0x3ce9, 0x2545: 0x3cf3,
- 0x2546: 0x3cfd, 0x2547: 0x3d07, 0x2548: 0x3d11,
- 0x2550: 0x3d1b, 0x2551: 0x3d1f,
- // Block 0x96, offset 0x2580
- 0x2580: 0x3d23, 0x2581: 0x3d27, 0x2582: 0x3d2b, 0x2583: 0x3d2f, 0x2584: 0x3d34, 0x2585: 0x2eb5,
- 0x2586: 0x3d38, 0x2587: 0x3d3c, 0x2588: 0x3d40, 0x2589: 0x3d44, 0x258a: 0x2eb9, 0x258b: 0x3d48,
- 0x258c: 0x3d4c, 0x258d: 0x3d50, 0x258e: 0x2ebd, 0x258f: 0x3d55, 0x2590: 0x3d59, 0x2591: 0x3d5d,
- 0x2592: 0x3d61, 0x2593: 0x3d66, 0x2594: 0x3d6a, 0x2595: 0x3c71, 0x2596: 0x3d6e, 0x2597: 0x3d73,
- 0x2598: 0x3d77, 0x2599: 0x3d7b, 0x259a: 0x3d7f, 0x259b: 0x2f9a, 0x259c: 0x3d83, 0x259d: 0x1866,
- 0x259e: 0x3d88, 0x259f: 0x3d8c, 0x25a0: 0x3d90, 0x25a1: 0x3d94, 0x25a2: 0x3cb9, 0x25a3: 0x3d98,
- 0x25a4: 0x3d9c, 0x25a5: 0x2fae, 0x25a6: 0x2ec1, 0x25a7: 0x2ec5, 0x25a8: 0x2fb2, 0x25a9: 0x3da0,
- 0x25aa: 0x3da4, 0x25ab: 0x2bf1, 0x25ac: 0x3da8, 0x25ad: 0x2ec9, 0x25ae: 0x3dac, 0x25af: 0x3db0,
- 0x25b0: 0x3db4, 0x25b1: 0x3db8, 0x25b2: 0x3db8, 0x25b3: 0x3db8, 0x25b4: 0x3dbc, 0x25b5: 0x3dc1,
- 0x25b6: 0x3dc5, 0x25b7: 0x3dc9, 0x25b8: 0x3dcd, 0x25b9: 0x3dd2, 0x25ba: 0x3dd6, 0x25bb: 0x3dda,
- 0x25bc: 0x3dde, 0x25bd: 0x3de2, 0x25be: 0x3de6, 0x25bf: 0x3dea,
- // Block 0x97, offset 0x25c0
- 0x25c0: 0x3dee, 0x25c1: 0x3df2, 0x25c2: 0x3df6, 0x25c3: 0x3dfa, 0x25c4: 0x3dfe, 0x25c5: 0x3e02,
- 0x25c6: 0x3e02, 0x25c7: 0x2fba, 0x25c8: 0x3e06, 0x25c9: 0x3e0a, 0x25ca: 0x3e0e, 0x25cb: 0x3e12,
- 0x25cc: 0x2ed1, 0x25cd: 0x3e16, 0x25ce: 0x3e1a, 0x25cf: 0x3e1e, 0x25d0: 0x2e39, 0x25d1: 0x3e22,
- 0x25d2: 0x3e26, 0x25d3: 0x3e2a, 0x25d4: 0x3e2e, 0x25d5: 0x3e32, 0x25d6: 0x3e36, 0x25d7: 0x3e3a,
- 0x25d8: 0x3e3e, 0x25d9: 0x3e42, 0x25da: 0x3e47, 0x25db: 0x3e4b, 0x25dc: 0x3e4f, 0x25dd: 0x3c55,
- 0x25de: 0x3e53, 0x25df: 0x3e57, 0x25e0: 0x3e5b, 0x25e1: 0x3e60, 0x25e2: 0x3e65, 0x25e3: 0x3e69,
- 0x25e4: 0x3e6d, 0x25e5: 0x3e71, 0x25e6: 0x3e75, 0x25e7: 0x3e79, 0x25e8: 0x3e7d, 0x25e9: 0x3e81,
- 0x25ea: 0x3e85, 0x25eb: 0x3e85, 0x25ec: 0x3e89, 0x25ed: 0x3e8e, 0x25ee: 0x3e92, 0x25ef: 0x2be1,
- 0x25f0: 0x3e96, 0x25f1: 0x3e9a, 0x25f2: 0x3e9f, 0x25f3: 0x3ea3, 0x25f4: 0x3ea7, 0x25f5: 0x18ce,
- 0x25f6: 0x3eab, 0x25f7: 0x3eaf, 0x25f8: 0x18d6, 0x25f9: 0x3eb3, 0x25fa: 0x3eb7, 0x25fb: 0x3ebb,
- 0x25fc: 0x3ec0, 0x25fd: 0x3ec4, 0x25fe: 0x3ec9, 0x25ff: 0x3ecd,
- // Block 0x98, offset 0x2600
- 0x2600: 0x3ed1, 0x2601: 0x3ed5, 0x2602: 0x3ed9, 0x2603: 0x3edd, 0x2604: 0x3ee1, 0x2605: 0x3ee5,
- 0x2606: 0x3ee9, 0x2607: 0x3eed, 0x2608: 0x3ef1, 0x2609: 0x3ef5, 0x260a: 0x3efa, 0x260b: 0x3efe,
- 0x260c: 0x3f02, 0x260d: 0x3f06, 0x260e: 0x2b11, 0x260f: 0x3f0a, 0x2610: 0x18fe, 0x2611: 0x3f0f,
- 0x2612: 0x3f0f, 0x2613: 0x3f14, 0x2614: 0x3f18, 0x2615: 0x3f18, 0x2616: 0x3f1c, 0x2617: 0x3f20,
- 0x2618: 0x3f25, 0x2619: 0x3f2a, 0x261a: 0x3f2e, 0x261b: 0x3f32, 0x261c: 0x3f36, 0x261d: 0x3f3a,
- 0x261e: 0x3f3e, 0x261f: 0x3f42, 0x2620: 0x3f46, 0x2621: 0x3f4a, 0x2622: 0x3f4e, 0x2623: 0x2ee5,
- 0x2624: 0x3f52, 0x2625: 0x3f57, 0x2626: 0x3f5b, 0x2627: 0x3f5f, 0x2628: 0x2fea, 0x2629: 0x3f5f,
- 0x262a: 0x3f63, 0x262b: 0x2eed, 0x262c: 0x3f67, 0x262d: 0x3f6b, 0x262e: 0x3f6f, 0x262f: 0x3f73,
- 0x2630: 0x2ef1, 0x2631: 0x2aa5, 0x2632: 0x3f77, 0x2633: 0x3f7b, 0x2634: 0x3f7f, 0x2635: 0x3f83,
- 0x2636: 0x3f87, 0x2637: 0x3f8b, 0x2638: 0x3f8f, 0x2639: 0x3f94, 0x263a: 0x3f98, 0x263b: 0x3f9c,
- 0x263c: 0x3fa0, 0x263d: 0x3fa4, 0x263e: 0x3fa8, 0x263f: 0x3fad,
- // Block 0x99, offset 0x2640
- 0x2640: 0x3fb1, 0x2641: 0x3fb5, 0x2642: 0x3fb9, 0x2643: 0x3fbd, 0x2644: 0x3fc1, 0x2645: 0x3fc5,
- 0x2646: 0x3fc9, 0x2647: 0x3fcd, 0x2648: 0x2ef5, 0x2649: 0x3fd1, 0x264a: 0x3fd5, 0x264b: 0x3fda,
- 0x264c: 0x3fde, 0x264d: 0x3fe2, 0x264e: 0x3fe6, 0x264f: 0x2efd, 0x2650: 0x3fea, 0x2651: 0x3fee,
- 0x2652: 0x3ff2, 0x2653: 0x3ff6, 0x2654: 0x3ffa, 0x2655: 0x3ffe, 0x2656: 0x4002, 0x2657: 0x4006,
- 0x2658: 0x2b15, 0x2659: 0x300a, 0x265a: 0x400a, 0x265b: 0x400e, 0x265c: 0x4012, 0x265d: 0x4016,
- 0x265e: 0x401b, 0x265f: 0x401f, 0x2660: 0x4023, 0x2661: 0x4027, 0x2662: 0x2f01, 0x2663: 0x402b,
- 0x2664: 0x4030, 0x2665: 0x4034, 0x2666: 0x4038, 0x2667: 0x30b5, 0x2668: 0x403c, 0x2669: 0x4040,
- 0x266a: 0x4044, 0x266b: 0x4048, 0x266c: 0x404c, 0x266d: 0x4051, 0x266e: 0x4055, 0x266f: 0x4059,
- 0x2670: 0x405d, 0x2671: 0x4062, 0x2672: 0x4066, 0x2673: 0x406a, 0x2674: 0x406e, 0x2675: 0x2c25,
- 0x2676: 0x4072, 0x2677: 0x4076, 0x2678: 0x407b, 0x2679: 0x4080, 0x267a: 0x4085, 0x267b: 0x4089,
- 0x267c: 0x408e, 0x267d: 0x4092, 0x267e: 0x4096, 0x267f: 0x409a,
- // Block 0x9a, offset 0x2680
- 0x2680: 0x409e, 0x2681: 0x2f05, 0x2682: 0x2d71, 0x2683: 0x40a2, 0x2684: 0x40a6, 0x2685: 0x40aa,
- 0x2686: 0x40ae, 0x2687: 0x40b3, 0x2688: 0x40b7, 0x2689: 0x40bb, 0x268a: 0x40bf, 0x268b: 0x3016,
- 0x268c: 0x40c3, 0x268d: 0x40c7, 0x268e: 0x40cc, 0x268f: 0x40d0, 0x2690: 0x40d4, 0x2691: 0x40d9,
- 0x2692: 0x40de, 0x2693: 0x40e2, 0x2694: 0x301a, 0x2695: 0x40e6, 0x2696: 0x40ea, 0x2697: 0x40ee,
- 0x2698: 0x40f2, 0x2699: 0x40f6, 0x269a: 0x40fa, 0x269b: 0x40fe, 0x269c: 0x4103, 0x269d: 0x4107,
- 0x269e: 0x410c, 0x269f: 0x4110, 0x26a0: 0x4115, 0x26a1: 0x3022, 0x26a2: 0x4119, 0x26a3: 0x411d,
- 0x26a4: 0x4122, 0x26a5: 0x4126, 0x26a6: 0x412a, 0x26a7: 0x412f, 0x26a8: 0x4134, 0x26a9: 0x4138,
- 0x26aa: 0x413c, 0x26ab: 0x4140, 0x26ac: 0x4144, 0x26ad: 0x4144, 0x26ae: 0x4148, 0x26af: 0x414c,
- 0x26b0: 0x302a, 0x26b1: 0x4150, 0x26b2: 0x4154, 0x26b3: 0x4158, 0x26b4: 0x415c, 0x26b5: 0x4160,
- 0x26b6: 0x4165, 0x26b7: 0x4169, 0x26b8: 0x2bed, 0x26b9: 0x416e, 0x26ba: 0x4173, 0x26bb: 0x4177,
- 0x26bc: 0x417c, 0x26bd: 0x4181, 0x26be: 0x4186, 0x26bf: 0x418a,
- // Block 0x9b, offset 0x26c0
- 0x26c0: 0x3042, 0x26c1: 0x418e, 0x26c2: 0x4193, 0x26c3: 0x4198, 0x26c4: 0x419d, 0x26c5: 0x41a2,
- 0x26c6: 0x41a6, 0x26c7: 0x41a6, 0x26c8: 0x3046, 0x26c9: 0x30bd, 0x26ca: 0x41aa, 0x26cb: 0x41ae,
- 0x26cc: 0x41b2, 0x26cd: 0x41b6, 0x26ce: 0x41bb, 0x26cf: 0x2b59, 0x26d0: 0x304e, 0x26d1: 0x41bf,
- 0x26d2: 0x41c3, 0x26d3: 0x2f2d, 0x26d4: 0x41c8, 0x26d5: 0x41cd, 0x26d6: 0x2e89, 0x26d7: 0x41d2,
- 0x26d8: 0x41d6, 0x26d9: 0x2f39, 0x26da: 0x41da, 0x26db: 0x41de, 0x26dc: 0x41e2, 0x26dd: 0x41e7,
- 0x26de: 0x41e7, 0x26df: 0x41ec, 0x26e0: 0x41f0, 0x26e1: 0x41f4, 0x26e2: 0x41f9, 0x26e3: 0x41fd,
- 0x26e4: 0x4201, 0x26e5: 0x4205, 0x26e6: 0x420a, 0x26e7: 0x420e, 0x26e8: 0x4212, 0x26e9: 0x4216,
- 0x26ea: 0x421a, 0x26eb: 0x421e, 0x26ec: 0x4223, 0x26ed: 0x4227, 0x26ee: 0x422b, 0x26ef: 0x422f,
- 0x26f0: 0x4233, 0x26f1: 0x4237, 0x26f2: 0x423b, 0x26f3: 0x4240, 0x26f4: 0x4245, 0x26f5: 0x4249,
- 0x26f6: 0x424e, 0x26f7: 0x4252, 0x26f8: 0x4257, 0x26f9: 0x425b, 0x26fa: 0x2f51, 0x26fb: 0x425f,
- 0x26fc: 0x4264, 0x26fd: 0x4269, 0x26fe: 0x426d, 0x26ff: 0x4272,
- // Block 0x9c, offset 0x2700
- 0x2700: 0x4276, 0x2701: 0x427b, 0x2702: 0x427f, 0x2703: 0x4283, 0x2704: 0x4287, 0x2705: 0x428b,
- 0x2706: 0x428f, 0x2707: 0x4293, 0x2708: 0x4298, 0x2709: 0x429d, 0x270a: 0x42a2, 0x270b: 0x3f14,
- 0x270c: 0x42a7, 0x270d: 0x42ab, 0x270e: 0x42af, 0x270f: 0x42b3, 0x2710: 0x42b7, 0x2711: 0x42bb,
- 0x2712: 0x42bf, 0x2713: 0x42c3, 0x2714: 0x42c7, 0x2715: 0x42cb, 0x2716: 0x42cf, 0x2717: 0x42d3,
- 0x2718: 0x2c31, 0x2719: 0x42d8, 0x271a: 0x42dc, 0x271b: 0x42e0, 0x271c: 0x42e4, 0x271d: 0x42e8,
- 0x271e: 0x42ec, 0x271f: 0x2f5d, 0x2720: 0x42f0, 0x2721: 0x42f4, 0x2722: 0x42f8, 0x2723: 0x42fc,
- 0x2724: 0x4300, 0x2725: 0x4305, 0x2726: 0x430a, 0x2727: 0x430f, 0x2728: 0x4313, 0x2729: 0x4317,
- 0x272a: 0x431b, 0x272b: 0x431f, 0x272c: 0x4324, 0x272d: 0x4328, 0x272e: 0x432d, 0x272f: 0x4331,
- 0x2730: 0x4335, 0x2731: 0x433a, 0x2732: 0x433f, 0x2733: 0x4343, 0x2734: 0x2b45, 0x2735: 0x4347,
- 0x2736: 0x434b, 0x2737: 0x434f, 0x2738: 0x4353, 0x2739: 0x4357, 0x273a: 0x435b, 0x273b: 0x306a,
- 0x273c: 0x435f, 0x273d: 0x4363, 0x273e: 0x4367, 0x273f: 0x436b,
- // Block 0x9d, offset 0x2740
- 0x2740: 0x436f, 0x2741: 0x4373, 0x2742: 0x4377, 0x2743: 0x437b, 0x2744: 0x1a66, 0x2745: 0x437f,
- 0x2746: 0x4384, 0x2747: 0x4388, 0x2748: 0x438c, 0x2749: 0x4390, 0x274a: 0x4394, 0x274b: 0x4398,
- 0x274c: 0x439d, 0x274d: 0x43a2, 0x274e: 0x43a6, 0x274f: 0x43aa, 0x2750: 0x307e, 0x2751: 0x3082,
- 0x2752: 0x1a82, 0x2753: 0x43ae, 0x2754: 0x43b3, 0x2755: 0x43b7, 0x2756: 0x43bb, 0x2757: 0x43bf,
- 0x2758: 0x43c3, 0x2759: 0x43c8, 0x275a: 0x43cd, 0x275b: 0x43d1, 0x275c: 0x43d5, 0x275d: 0x43d9,
- 0x275e: 0x43de, 0x275f: 0x3086, 0x2760: 0x43e2, 0x2761: 0x43e7, 0x2762: 0x43ec, 0x2763: 0x43f0,
- 0x2764: 0x43f4, 0x2765: 0x43f8, 0x2766: 0x43fd, 0x2767: 0x4401, 0x2768: 0x4405, 0x2769: 0x4409,
- 0x276a: 0x440d, 0x276b: 0x4411, 0x276c: 0x4415, 0x276d: 0x4419, 0x276e: 0x441e, 0x276f: 0x4422,
- 0x2770: 0x4426, 0x2771: 0x442a, 0x2772: 0x442f, 0x2773: 0x4433, 0x2774: 0x4437, 0x2775: 0x443b,
- 0x2776: 0x443f, 0x2777: 0x4444, 0x2778: 0x4449, 0x2779: 0x444d, 0x277a: 0x4451, 0x277b: 0x4455,
- 0x277c: 0x445a, 0x277d: 0x445e, 0x277e: 0x309e, 0x277f: 0x309e,
- // Block 0x9e, offset 0x2780
- 0x2780: 0x4463, 0x2781: 0x4467, 0x2782: 0x446c, 0x2783: 0x4470, 0x2784: 0x4474, 0x2785: 0x4478,
- 0x2786: 0x447c, 0x2787: 0x4480, 0x2788: 0x4484, 0x2789: 0x4488, 0x278a: 0x30a2, 0x278b: 0x448d,
- 0x278c: 0x4491, 0x278d: 0x4495, 0x278e: 0x4499, 0x278f: 0x449d, 0x2790: 0x44a1, 0x2791: 0x44a6,
- 0x2792: 0x44aa, 0x2793: 0x44af, 0x2794: 0x44b4, 0x2795: 0x1b42, 0x2796: 0x44b9, 0x2797: 0x1b52,
- 0x2798: 0x44bd, 0x2799: 0x44c1, 0x279a: 0x44c5, 0x279b: 0x44c9, 0x279c: 0x1b66, 0x279d: 0x44cd,
+ 0x1040: 0x436f, 0x1041: 0x4373, 0x1042: 0x4377, 0x1043: 0x437b, 0x1044: 0x1a66, 0x1045: 0x437f,
+ 0x1046: 0x4384, 0x1047: 0x4388, 0x1048: 0x438c, 0x1049: 0x4390, 0x104a: 0x4394, 0x104b: 0x4398,
+ 0x104c: 0x439d, 0x104d: 0x43a2, 0x104e: 0x43a6, 0x104f: 0x43aa, 0x1050: 0x307e, 0x1051: 0x3082,
+ 0x1052: 0x1a82, 0x1053: 0x43ae, 0x1054: 0x43b3, 0x1055: 0x43b7, 0x1056: 0x43bb, 0x1057: 0x43bf,
+ 0x1058: 0x43c3, 0x1059: 0x43c8, 0x105a: 0x43cd, 0x105b: 0x43d1, 0x105c: 0x43d5, 0x105d: 0x43d9,
+ 0x105e: 0x43de, 0x105f: 0x3086, 0x1060: 0x43e2, 0x1061: 0x43e7, 0x1062: 0x43ec, 0x1063: 0x43f0,
+ 0x1064: 0x43f4, 0x1065: 0x43f8, 0x1066: 0x43fd, 0x1067: 0x4401, 0x1068: 0x4405, 0x1069: 0x4409,
+ 0x106a: 0x440d, 0x106b: 0x4411, 0x106c: 0x4415, 0x106d: 0x4419, 0x106e: 0x441e, 0x106f: 0x4422,
+ 0x1070: 0x4426, 0x1071: 0x442a, 0x1072: 0x442f, 0x1073: 0x4433, 0x1074: 0x4437, 0x1075: 0x443b,
+ 0x1076: 0x443f, 0x1077: 0x4444, 0x1078: 0x4449, 0x1079: 0x444d, 0x107a: 0x4451, 0x107b: 0x4455,
+ 0x107c: 0x445a, 0x107d: 0x445e, 0x107e: 0x309e, 0x107f: 0x309e,
+}
+
+// nfkcDecompSparseOffset: 93 entries, 186 bytes
+var nfkcDecompSparseOffset = []uint16{0x0, 0xc, 0x16, 0x1e, 0x24, 0x27, 0x31, 0x37, 0x3e, 0x44, 0x4c, 0x59, 0x60, 0x66, 0x6e, 0x70, 0x72, 0x74, 0x78, 0x7c, 0x7e, 0x82, 0x85, 0x88, 0x8c, 0x8e, 0x90, 0x92, 0x96, 0x98, 0x9c, 0x9e, 0xa0, 0xa2, 0xa4, 0xae, 0xb6, 0xb8, 0xba, 0xc3, 0xc6, 0xcd, 0xd8, 0xe6, 0xf4, 0xfe, 0x102, 0x104, 0x10e, 0x11a, 0x11f, 0x122, 0x124, 0x126, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x133, 0x135, 0x137, 0x139, 0x13b, 0x140, 0x14f, 0x15d, 0x15f, 0x161, 0x169, 0x179, 0x17b, 0x186, 0x18d, 0x198, 0x1a4, 0x1b5, 0x1c6, 0x1cd, 0x1de, 0x1ec, 0x1fa, 0x209, 0x21a, 0x21f, 0x22c, 0x230, 0x234, 0x238, 0x23a, 0x249, 0x24b, 0x24f}
+
+// nfkcDecompSparseValues: 605 entries, 2420 bytes
+var nfkcDecompSparseValues = [605]valueRange{
+ // Block 0x0, offset 0x1
+ {value: 0x0002, lo: 0x0b},
+ {value: 0x0001, lo: 0xa0, hi: 0xa0},
+ {value: 0x0003, lo: 0xa8, hi: 0xa8},
+ {value: 0x0007, lo: 0xaa, hi: 0xaa},
+ {value: 0x0009, lo: 0xaf, hi: 0xaf},
+ {value: 0x000d, lo: 0xb2, hi: 0xb4},
+ {value: 0x0015, lo: 0xb5, hi: 0xb5},
+ {value: 0x0018, lo: 0xb8, hi: 0xb8},
+ {value: 0x001c, lo: 0xb9, hi: 0xba},
+ {value: 0x0020, lo: 0xbc, hi: 0xbc},
+ {value: 0x0026, lo: 0xbd, hi: 0xbd},
+ {value: 0x002c, lo: 0xbe, hi: 0xbe},
+ // Block 0x1, offset 0x2
+ {value: 0x0004, lo: 0x09},
+ {value: 0x0032, lo: 0x80, hi: 0x85},
+ {value: 0x004a, lo: 0x87, hi: 0x8f},
+ {value: 0x006e, lo: 0x91, hi: 0x96},
+ {value: 0x0086, lo: 0x99, hi: 0x9d},
+ {value: 0x009a, lo: 0xa0, hi: 0xa5},
+ {value: 0x00b2, lo: 0xa7, hi: 0xaf},
+ {value: 0x00d6, lo: 0xb1, hi: 0xb6},
+ {value: 0x00ee, lo: 0xb9, hi: 0xbd},
+ {value: 0x0102, lo: 0xbf, hi: 0xbf},
+ // Block 0x2, offset 0x3
+ {value: 0x0004, lo: 0x07},
+ {value: 0x0106, lo: 0x80, hi: 0x8f},
+ {value: 0x0146, lo: 0x92, hi: 0xa5},
+ {value: 0x0196, lo: 0xa8, hi: 0xb0},
+ {value: 0x01ba, lo: 0xb2, hi: 0xb2},
+ {value: 0x01bd, lo: 0xb3, hi: 0xb3},
+ {value: 0x01c0, lo: 0xb4, hi: 0xb7},
+ {value: 0x01d0, lo: 0xb9, hi: 0xbf},
+ // Block 0x3, offset 0x4
+ {value: 0x0004, lo: 0x05},
+ {value: 0x01ec, lo: 0x80, hi: 0x80},
+ {value: 0x01f0, lo: 0x83, hi: 0x89},
+ {value: 0x020c, lo: 0x8c, hi: 0x91},
+ {value: 0x0224, lo: 0x94, hi: 0xa5},
+ {value: 0x026c, lo: 0xa8, hi: 0xbf},
+ // Block 0x4, offset 0x5
+ {value: 0x0004, lo: 0x02},
+ {value: 0x02ca, lo: 0xa0, hi: 0xa1},
+ {value: 0x02d2, lo: 0xaf, hi: 0xb0},
+ // Block 0x5, offset 0x6
+ {value: 0x0004, lo: 0x09},
+ {value: 0x03d8, lo: 0x80, hi: 0x9b},
+ {value: 0x0448, lo: 0x9e, hi: 0x9f},
+ {value: 0x0450, lo: 0xa6, hi: 0xaa},
+ {value: 0x0466, lo: 0xab, hi: 0xab},
+ {value: 0x046c, lo: 0xac, hi: 0xac},
+ {value: 0x0472, lo: 0xad, hi: 0xad},
+ {value: 0x0478, lo: 0xae, hi: 0xb0},
+ {value: 0x0486, lo: 0xb1, hi: 0xb1},
+ {value: 0x048c, lo: 0xb2, hi: 0xb3},
+ // Block 0x6, offset 0x7
+ {value: 0x0002, lo: 0x05},
+ {value: 0x0494, lo: 0xb0, hi: 0xb1},
+ {value: 0x0499, lo: 0xb2, hi: 0xb4},
+ {value: 0x04a0, lo: 0xb5, hi: 0xb5},
+ {value: 0x04a3, lo: 0xb6, hi: 0xb6},
+ {value: 0x04a6, lo: 0xb7, hi: 0xb8},
+ // Block 0x7, offset 0x8
+ {value: 0x0004, lo: 0x06},
+ {value: 0x04aa, lo: 0x98, hi: 0x9d},
+ {value: 0x04c2, lo: 0xa0, hi: 0xa0},
+ {value: 0x04c5, lo: 0xa1, hi: 0xa1},
+ {value: 0x02c8, lo: 0xa2, hi: 0xa2},
+ {value: 0x04c7, lo: 0xa3, hi: 0xa3},
+ {value: 0x04c9, lo: 0xa4, hi: 0xa4},
+ // Block 0x8, offset 0x9
+ {value: 0x0003, lo: 0x05},
+ {value: 0x04cc, lo: 0x80, hi: 0x81},
+ {value: 0x04d2, lo: 0x83, hi: 0x84},
+ {value: 0x04da, lo: 0xb4, hi: 0xb4},
+ {value: 0x04dd, lo: 0xba, hi: 0xba},
+ {value: 0x04e1, lo: 0xbe, hi: 0xbe},
+ // Block 0x9, offset 0xa
+ {value: 0x0005, lo: 0x07},
+ {value: 0x0011, lo: 0x84, hi: 0x84},
+ {value: 0x04e8, lo: 0x85, hi: 0x85},
+ {value: 0x04ee, lo: 0x86, hi: 0x87},
+ {value: 0x04f6, lo: 0x88, hi: 0x8a},
+ {value: 0x0505, lo: 0x8c, hi: 0x8c},
+ {value: 0x050a, lo: 0x8e, hi: 0x90},
+ {value: 0x051b, lo: 0xaa, hi: 0xb0},
+ // Block 0xa, offset 0xb
+ {value: 0x0003, lo: 0x0c},
+ {value: 0x0540, lo: 0x8a, hi: 0x8a},
+ {value: 0x0545, lo: 0x8b, hi: 0x8b},
+ {value: 0x054a, lo: 0x8c, hi: 0x8c},
+ {value: 0x054f, lo: 0x8d, hi: 0x8d},
+ {value: 0x0554, lo: 0x8e, hi: 0x8e},
+ {value: 0x0559, lo: 0x90, hi: 0x92},
+ {value: 0x050a, lo: 0x93, hi: 0x93},
+ {value: 0x0520, lo: 0x94, hi: 0x94},
+ {value: 0x056c, lo: 0x95, hi: 0x96},
+ {value: 0x0572, lo: 0xb0, hi: 0xb2},
+ {value: 0x057b, lo: 0xb4, hi: 0xb5},
+ {value: 0x0581, lo: 0xb9, hi: 0xb9},
+ // Block 0xb, offset 0xc
+ {value: 0x0005, lo: 0x06},
+ {value: 0x0584, lo: 0x80, hi: 0x81},
+ {value: 0x058e, lo: 0x83, hi: 0x83},
+ {value: 0x0593, lo: 0x87, hi: 0x87},
+ {value: 0x0598, lo: 0x8c, hi: 0x8e},
+ {value: 0x05a7, lo: 0x99, hi: 0x99},
+ {value: 0x05ac, lo: 0xb9, hi: 0xb9},
+ // Block 0xc, offset 0xd
+ {value: 0x0005, lo: 0x05},
+ {value: 0x05b1, lo: 0x90, hi: 0x91},
+ {value: 0x05bb, lo: 0x93, hi: 0x93},
+ {value: 0x05c0, lo: 0x97, hi: 0x97},
+ {value: 0x05c5, lo: 0x9c, hi: 0x9e},
+ {value: 0x05d4, lo: 0xb6, hi: 0xb7},
+ // Block 0xd, offset 0xe
+ {value: 0x0005, lo: 0x07},
+ {value: 0x05de, lo: 0x81, hi: 0x82},
+ {value: 0x05e8, lo: 0x90, hi: 0x93},
+ {value: 0x05fc, lo: 0x96, hi: 0x97},
+ {value: 0x0606, lo: 0x9a, hi: 0x9f},
+ {value: 0x0624, lo: 0xa2, hi: 0xa7},
+ {value: 0x0642, lo: 0xaa, hi: 0xb5},
+ {value: 0x067e, lo: 0xb8, hi: 0xb9},
+ // Block 0xe, offset 0xf
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0688, lo: 0x87, hi: 0x87},
+ // Block 0xf, offset 0x10
+ {value: 0x0005, lo: 0x01},
+ {value: 0x068d, lo: 0xa2, hi: 0xa6},
+ // Block 0x10, offset 0x11
+ {value: 0x0005, lo: 0x01},
+ {value: 0x06a6, lo: 0xb5, hi: 0xb8},
+ // Block 0x11, offset 0x12
+ {value: 0x0005, lo: 0x03},
+ {value: 0x06ba, lo: 0x80, hi: 0x80},
+ {value: 0x06bf, lo: 0x82, hi: 0x82},
+ {value: 0x06c4, lo: 0x93, hi: 0x93},
+ // Block 0x12, offset 0x13
+ {value: 0x0007, lo: 0x03},
+ {value: 0x06c9, lo: 0xa9, hi: 0xa9},
+ {value: 0x06d0, lo: 0xb1, hi: 0xb1},
+ {value: 0x06d7, lo: 0xb4, hi: 0xb4},
+ // Block 0x13, offset 0x14
+ {value: 0x0007, lo: 0x01},
+ {value: 0x06de, lo: 0x98, hi: 0x9f},
+ // Block 0x14, offset 0x15
+ {value: 0x0007, lo: 0x03},
+ {value: 0x0716, lo: 0x8b, hi: 0x8c},
+ {value: 0x0724, lo: 0x9c, hi: 0x9d},
+ {value: 0x0732, lo: 0x9f, hi: 0x9f},
+ // Block 0x15, offset 0x16
+ {value: 0x0007, lo: 0x02},
+ {value: 0x0739, lo: 0xb3, hi: 0xb3},
+ {value: 0x0740, lo: 0xb6, hi: 0xb6},
+ // Block 0x16, offset 0x17
+ {value: 0x0007, lo: 0x02},
+ {value: 0x0747, lo: 0x99, hi: 0x9b},
+ {value: 0x075c, lo: 0x9e, hi: 0x9e},
+ // Block 0x17, offset 0x18
+ {value: 0x0007, lo: 0x03},
+ {value: 0x0763, lo: 0x88, hi: 0x88},
+ {value: 0x076a, lo: 0x8b, hi: 0x8c},
+ {value: 0x0778, lo: 0x9c, hi: 0x9d},
+ // Block 0x18, offset 0x19
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0786, lo: 0x94, hi: 0x94},
+ // Block 0x19, offset 0x1a
+ {value: 0x0007, lo: 0x01},
+ {value: 0x078d, lo: 0x8a, hi: 0x8c},
+ // Block 0x1a, offset 0x1b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x07a2, lo: 0x88, hi: 0x88},
+ // Block 0x1b, offset 0x1c
+ {value: 0x0007, lo: 0x03},
+ {value: 0x07a9, lo: 0x80, hi: 0x80},
+ {value: 0x07b0, lo: 0x87, hi: 0x88},
+ {value: 0x07be, lo: 0x8a, hi: 0x8b},
+ // Block 0x1c, offset 0x1d
+ {value: 0x0007, lo: 0x01},
+ {value: 0x07cf, lo: 0x8a, hi: 0x8c},
+ // Block 0x1d, offset 0x1e
+ {value: 0x0007, lo: 0x03},
+ {value: 0x07e4, lo: 0x9a, hi: 0x9a},
+ {value: 0x07eb, lo: 0x9c, hi: 0x9d},
+ {value: 0x07fc, lo: 0x9e, hi: 0x9e},
+ // Block 0x1e, offset 0x1f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0803, lo: 0xb3, hi: 0xb3},
+ // Block 0x1f, offset 0x20
+ {value: 0x0000, lo: 0x01},
+ {value: 0x080a, lo: 0xb3, hi: 0xb3},
+ // Block 0x20, offset 0x21
+ {value: 0x0007, lo: 0x01},
+ {value: 0x0811, lo: 0x9c, hi: 0x9d},
+ // Block 0x21, offset 0x22
+ {value: 0x0000, lo: 0x01},
+ {value: 0x081f, lo: 0x8c, hi: 0x8c},
+ // Block 0x22, offset 0x23
+ {value: 0x0007, lo: 0x09},
+ {value: 0x0823, lo: 0x83, hi: 0x83},
+ {value: 0x082a, lo: 0x8d, hi: 0x8d},
+ {value: 0x0831, lo: 0x92, hi: 0x92},
+ {value: 0x0838, lo: 0x97, hi: 0x97},
+ {value: 0x083f, lo: 0x9c, hi: 0x9c},
+ {value: 0x0846, lo: 0xa9, hi: 0xa9},
+ {value: 0x084d, lo: 0xb3, hi: 0xb3},
+ {value: 0x0854, lo: 0xb5, hi: 0xb7},
+ {value: 0x086c, lo: 0xb8, hi: 0xb9},
+ // Block 0x23, offset 0x24
+ {value: 0x0007, lo: 0x07},
+ {value: 0x087d, lo: 0x81, hi: 0x81},
+ {value: 0x0884, lo: 0x93, hi: 0x93},
+ {value: 0x088b, lo: 0x9d, hi: 0x9d},
+ {value: 0x0892, lo: 0xa2, hi: 0xa2},
+ {value: 0x0899, lo: 0xa7, hi: 0xa7},
+ {value: 0x08a0, lo: 0xac, hi: 0xac},
+ {value: 0x08a7, lo: 0xb9, hi: 0xb9},
+ // Block 0x24, offset 0x25
+ {value: 0x0000, lo: 0x01},
+ {value: 0x08ae, lo: 0xa6, hi: 0xa6},
+ // Block 0x25, offset 0x26
+ {value: 0x0000, lo: 0x01},
+ {value: 0x08b5, lo: 0xbc, hi: 0xbc},
+ // Block 0x26, offset 0x27
+ {value: 0x0007, lo: 0x08},
+ {value: 0x08b9, lo: 0x86, hi: 0x86},
+ {value: 0x08c0, lo: 0x88, hi: 0x88},
+ {value: 0x08c7, lo: 0x8a, hi: 0x8a},
+ {value: 0x08ce, lo: 0x8c, hi: 0x8c},
+ {value: 0x08d5, lo: 0x8e, hi: 0x8e},
+ {value: 0x08dc, lo: 0x92, hi: 0x92},
+ {value: 0x08e3, lo: 0xbb, hi: 0xbb},
+ {value: 0x08ea, lo: 0xbd, hi: 0xbd},
+ // Block 0x27, offset 0x28
+ {value: 0x0007, lo: 0x02},
+ {value: 0x08f1, lo: 0x80, hi: 0x81},
+ {value: 0x08ff, lo: 0x83, hi: 0x83},
+ // Block 0x28, offset 0x29
+ {value: 0x0002, lo: 0x06},
+ {value: 0x0906, lo: 0xac, hi: 0xad},
+ {value: 0x090b, lo: 0xae, hi: 0xae},
+ {value: 0x090d, lo: 0xb0, hi: 0xb2},
+ {value: 0x0914, lo: 0xb3, hi: 0xba},
+ {value: 0x0924, lo: 0xbc, hi: 0xbd},
+ {value: 0x0929, lo: 0xbe, hi: 0xbf},
+ // Block 0x29, offset 0x2a
+ {value: 0x0003, lo: 0x0a},
+ {value: 0x0981, lo: 0x9b, hi: 0x9c},
+ {value: 0x0986, lo: 0x9d, hi: 0x9e},
+ {value: 0x0949, lo: 0x9f, hi: 0x9f},
+ {value: 0x098c, lo: 0xa0, hi: 0xa0},
+ {value: 0x098e, lo: 0xa1, hi: 0xa7},
+ {value: 0x09a4, lo: 0xa8, hi: 0xaa},
+ {value: 0x09ae, lo: 0xab, hi: 0xb8},
+ {value: 0x09d9, lo: 0xb9, hi: 0xbb},
+ {value: 0x09e1, lo: 0xbc, hi: 0xbe},
+ {value: 0x055c, lo: 0xbf, hi: 0xbf},
+ // Block 0x2a, offset 0x2b
+ {value: 0x0004, lo: 0x0d},
+ {value: 0x09ea, lo: 0x80, hi: 0x88},
+ {value: 0x0a10, lo: 0x89, hi: 0x89},
+ {value: 0x0a16, lo: 0x8a, hi: 0x94},
+ {value: 0x0a44, lo: 0x95, hi: 0x95},
+ {value: 0x0a4a, lo: 0x96, hi: 0x96},
+ {value: 0x0a50, lo: 0x97, hi: 0x97},
+ {value: 0x0a56, lo: 0x98, hi: 0x9c},
+ {value: 0x0a6c, lo: 0x9d, hi: 0x9d},
+ {value: 0x0a72, lo: 0x9e, hi: 0xae},
+ {value: 0x0ab8, lo: 0xaf, hi: 0xaf},
+ {value: 0x0abe, lo: 0xb0, hi: 0xb8},
+ {value: 0x0ae4, lo: 0xb9, hi: 0xb9},
+ {value: 0x0aea, lo: 0xba, hi: 0xbf},
+ // Block 0x2b, offset 0x2c
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x0001, lo: 0x80, hi: 0x8a},
+ {value: 0x1436, lo: 0x91, hi: 0x91},
+ {value: 0x143a, lo: 0x97, hi: 0x97},
+ {value: 0x143e, lo: 0xa4, hi: 0xa4},
+ {value: 0x1440, lo: 0xa5, hi: 0xa5},
+ {value: 0x1443, lo: 0xa6, hi: 0xa6},
+ {value: 0x0001, lo: 0xaf, hi: 0xaf},
+ {value: 0x1447, lo: 0xb3, hi: 0xb3},
+ {value: 0x144e, lo: 0xb4, hi: 0xb4},
+ {value: 0x1458, lo: 0xb6, hi: 0xb6},
+ {value: 0x145f, lo: 0xb7, hi: 0xb7},
+ {value: 0x1469, lo: 0xbc, hi: 0xbc},
+ {value: 0x146c, lo: 0xbe, hi: 0xbe},
+ // Block 0x2c, offset 0x2d
+ {value: 0x0002, lo: 0x09},
+ {value: 0x1470, lo: 0x87, hi: 0x87},
+ {value: 0x1473, lo: 0x88, hi: 0x88},
+ {value: 0x1476, lo: 0x89, hi: 0x89},
+ {value: 0x1479, lo: 0x97, hi: 0x97},
+ {value: 0x0001, lo: 0x9f, hi: 0x9f},
+ {value: 0x1486, lo: 0xb0, hi: 0xb0},
+ {value: 0x097c, lo: 0xb1, hi: 0xb1},
+ {value: 0x1488, lo: 0xb4, hi: 0xbb},
+ {value: 0x149a, lo: 0xbc, hi: 0xbf},
+ // Block 0x2d, offset 0x2e
+ {value: 0x0006, lo: 0x03},
+ {value: 0x1599, lo: 0x89, hi: 0x89},
+ {value: 0x159f, lo: 0x9a, hi: 0x9b},
+ {value: 0x15ab, lo: 0xae, hi: 0xae},
+ // Block 0x2e, offset 0x2f
+ {value: 0x0006, lo: 0x01},
+ {value: 0x15b1, lo: 0x8d, hi: 0x8f},
+ // Block 0x2f, offset 0x30
+ {value: 0x0006, lo: 0x09},
+ {value: 0x15c3, lo: 0x84, hi: 0x84},
+ {value: 0x15c9, lo: 0x89, hi: 0x89},
+ {value: 0x15cf, lo: 0x8c, hi: 0x8c},
+ {value: 0x15d5, lo: 0xa4, hi: 0xa4},
+ {value: 0x15db, lo: 0xa6, hi: 0xa6},
+ {value: 0x15e1, lo: 0xac, hi: 0xac},
+ {value: 0x15e8, lo: 0xad, hi: 0xad},
+ {value: 0x15f2, lo: 0xaf, hi: 0xaf},
+ {value: 0x15f9, lo: 0xb0, hi: 0xb0},
+ // Block 0x30, offset 0x31
+ {value: 0x0006, lo: 0x0b},
+ {value: 0x1603, lo: 0x81, hi: 0x81},
+ {value: 0x1609, lo: 0x84, hi: 0x84},
+ {value: 0x160f, lo: 0x87, hi: 0x87},
+ {value: 0x1615, lo: 0x89, hi: 0x89},
+ {value: 0x161b, lo: 0xa0, hi: 0xa0},
+ {value: 0x161f, lo: 0xa2, hi: 0xa2},
+ {value: 0x1625, lo: 0xad, hi: 0xae},
+ {value: 0x162f, lo: 0xaf, hi: 0xaf},
+ {value: 0x1633, lo: 0xb0, hi: 0xb1},
+ {value: 0x163f, lo: 0xb4, hi: 0xb5},
+ {value: 0x164b, lo: 0xb8, hi: 0xb9},
+ // Block 0x31, offset 0x32
+ {value: 0x0006, lo: 0x04},
+ {value: 0x1657, lo: 0x80, hi: 0x81},
+ {value: 0x1663, lo: 0x84, hi: 0x85},
+ {value: 0x166f, lo: 0x88, hi: 0x89},
+ {value: 0x167b, lo: 0xac, hi: 0xaf},
+ // Block 0x32, offset 0x33
+ {value: 0x0006, lo: 0x02},
+ {value: 0x1693, lo: 0xa0, hi: 0xa3},
+ {value: 0x16ab, lo: 0xaa, hi: 0xad},
+ // Block 0x33, offset 0x34
+ {value: 0x0004, lo: 0x01},
+ {value: 0x16c3, lo: 0xa9, hi: 0xaa},
+ // Block 0x34, offset 0x35
+ {value: 0x0000, lo: 0x01},
+ {value: 0x17fc, lo: 0x8c, hi: 0x8c},
+ // Block 0x35, offset 0x36
+ {value: 0x0004, lo: 0x02},
+ {value: 0x1809, lo: 0xb4, hi: 0xb5},
+ {value: 0x1810, lo: 0xb6, hi: 0xb6},
+ // Block 0x36, offset 0x37
+ {value: 0x0000, lo: 0x01},
+ {value: 0x1814, lo: 0x9c, hi: 0x9c},
+ // Block 0x37, offset 0x38
+ {value: 0x10c6, lo: 0x01},
+ {value: 0x0499, lo: 0xbc, hi: 0xbd},
+ // Block 0x38, offset 0x39
+ {value: 0x0000, lo: 0x01},
+ {value: 0x181a, lo: 0xaf, hi: 0xaf},
+ // Block 0x39, offset 0x3a
+ {value: 0x0000, lo: 0x01},
+ {value: 0x181e, lo: 0x9f, hi: 0x9f},
+ // Block 0x3a, offset 0x3b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x1822, lo: 0xb3, hi: 0xb3},
+ // Block 0x3b, offset 0x3c
+ {value: 0x0004, lo: 0x01},
+ {value: 0x1826, lo: 0x80, hi: 0xbf},
+ // Block 0x3c, offset 0x3d
+ {value: 0x0004, lo: 0x01},
+ {value: 0x1926, lo: 0x80, hi: 0xbf},
+ // Block 0x3d, offset 0x3e
+ {value: 0x0004, lo: 0x01},
+ {value: 0x1a26, lo: 0x80, hi: 0xbf},
+ // Block 0x3e, offset 0x3f
+ {value: 0x0004, lo: 0x01},
+ {value: 0x1b26, lo: 0x80, hi: 0x95},
+ // Block 0x3f, offset 0x40
+ {value: 0x0300, lo: 0x04},
+ {value: 0x0001, lo: 0x80, hi: 0x80},
+ {value: 0x1b7e, lo: 0xb6, hi: 0xb6},
+ {value: 0x1882, lo: 0xb8, hi: 0xb9},
+ {value: 0x1b86, lo: 0xba, hi: 0xba},
+ // Block 0x40, offset 0x41
+ {value: 0x0007, lo: 0x0e},
+ {value: 0x1c39, lo: 0x94, hi: 0x94},
+ {value: 0x1c40, lo: 0x9b, hi: 0x9b},
+ {value: 0x1c45, lo: 0x9c, hi: 0x9c},
+ {value: 0x1c4a, lo: 0x9e, hi: 0x9f},
+ {value: 0x1c58, lo: 0xac, hi: 0xac},
+ {value: 0x1c5f, lo: 0xae, hi: 0xae},
+ {value: 0x1c66, lo: 0xb0, hi: 0xb0},
+ {value: 0x1c6d, lo: 0xb2, hi: 0xb2},
+ {value: 0x1c74, lo: 0xb4, hi: 0xb4},
+ {value: 0x1c7b, lo: 0xb6, hi: 0xb6},
+ {value: 0x1c82, lo: 0xb8, hi: 0xb8},
+ {value: 0x1c89, lo: 0xba, hi: 0xba},
+ {value: 0x1c90, lo: 0xbc, hi: 0xbc},
+ {value: 0x1c97, lo: 0xbe, hi: 0xbe},
+ // Block 0x41, offset 0x42
+ {value: 0x0007, lo: 0x0d},
+ {value: 0x1c9e, lo: 0x80, hi: 0x80},
+ {value: 0x1ca5, lo: 0x82, hi: 0x82},
+ {value: 0x1cac, lo: 0x85, hi: 0x85},
+ {value: 0x1cb3, lo: 0x87, hi: 0x87},
+ {value: 0x1cba, lo: 0x89, hi: 0x89},
+ {value: 0x1cc1, lo: 0x90, hi: 0x91},
+ {value: 0x1ccf, lo: 0x93, hi: 0x94},
+ {value: 0x1cdd, lo: 0x96, hi: 0x97},
+ {value: 0x1ceb, lo: 0x99, hi: 0x9a},
+ {value: 0x1cf9, lo: 0x9c, hi: 0x9d},
+ {value: 0x1d07, lo: 0xb4, hi: 0xb4},
+ {value: 0x1d0e, lo: 0xb7, hi: 0xba},
+ {value: 0x1d2a, lo: 0xbe, hi: 0xbf},
+ // Block 0x42, offset 0x43
+ {value: 0x0004, lo: 0x01},
+ {value: 0x1d38, lo: 0xb1, hi: 0xbf},
+ // Block 0x43, offset 0x44
+ {value: 0x0004, lo: 0x01},
+ {value: 0x1d74, lo: 0x80, hi: 0xbf},
+ // Block 0x44, offset 0x45
+ {value: 0x0004, lo: 0x07},
+ {value: 0x1e74, lo: 0x80, hi: 0x8e},
+ {value: 0x1826, lo: 0x92, hi: 0x92},
+ {value: 0x183e, lo: 0x93, hi: 0x93},
+ {value: 0x1eb0, lo: 0x94, hi: 0x99},
+ {value: 0x1836, lo: 0x9a, hi: 0x9a},
+ {value: 0x1ec8, lo: 0x9b, hi: 0x9e},
+ {value: 0x1846, lo: 0x9f, hi: 0x9f},
+ // Block 0x45, offset 0x46
+ {value: 0x0004, lo: 0x0f},
+ {value: 0x221c, lo: 0x80, hi: 0x80},
+ {value: 0x2221, lo: 0x81, hi: 0x81},
+ {value: 0x2226, lo: 0x82, hi: 0x82},
+ {value: 0x222b, lo: 0x83, hi: 0x83},
+ {value: 0x2230, lo: 0x84, hi: 0x84},
+ {value: 0x2235, lo: 0x85, hi: 0x85},
+ {value: 0x223a, lo: 0x86, hi: 0x86},
+ {value: 0x223f, lo: 0x87, hi: 0x87},
+ {value: 0x2244, lo: 0x88, hi: 0x88},
+ {value: 0x2249, lo: 0x89, hi: 0x89},
+ {value: 0x224f, lo: 0x8a, hi: 0x8a},
+ {value: 0x2255, lo: 0x8b, hi: 0x8b},
+ {value: 0x225b, lo: 0x8c, hi: 0x8c},
+ {value: 0x225e, lo: 0x8d, hi: 0x8e},
+ {value: 0x2265, lo: 0x8f, hi: 0xbe},
+ // Block 0x46, offset 0x47
+ {value: 0x0000, lo: 0x01},
+ {value: 0x2a7d, lo: 0xb0, hi: 0xb0},
+ // Block 0x47, offset 0x48
+ {value: 0x0004, lo: 0x0a},
+ {value: 0x2a81, lo: 0x80, hi: 0x81},
+ {value: 0x1a9e, lo: 0x82, hi: 0x82},
+ {value: 0x2a89, lo: 0x83, hi: 0x86},
+ {value: 0x1b76, lo: 0x87, hi: 0x87},
+ {value: 0x1b76, lo: 0x88, hi: 0x88},
+ {value: 0x2a99, lo: 0x89, hi: 0x89},
+ {value: 0x1abe, lo: 0x8a, hi: 0x8a},
+ {value: 0x2a9d, lo: 0x8b, hi: 0xb3},
+ {value: 0x1a16, lo: 0xb4, hi: 0xb4},
+ {value: 0x2b41, lo: 0xb5, hi: 0xbf},
+ // Block 0x48, offset 0x49
+ {value: 0x0004, lo: 0x06},
+ {value: 0x1b3a, lo: 0x80, hi: 0x80},
+ {value: 0x2b6d, lo: 0x81, hi: 0x9b},
+ {value: 0x2ac1, lo: 0x9c, hi: 0x9c},
+ {value: 0x2bd9, lo: 0x9d, hi: 0xb0},
+ {value: 0x1aa6, lo: 0xb1, hi: 0xb1},
+ {value: 0x2c29, lo: 0xb2, hi: 0xbf},
+ // Block 0x49, offset 0x4a
+ {value: 0x0004, lo: 0x0a},
+ {value: 0x2c61, lo: 0x80, hi: 0x80},
+ {value: 0x18ba, lo: 0x81, hi: 0x81},
+ {value: 0x2c65, lo: 0x82, hi: 0x89},
+ {value: 0x186e, lo: 0x8a, hi: 0x8a},
+ {value: 0x2c85, lo: 0x8b, hi: 0xa0},
+ {value: 0x2c21, lo: 0xa1, hi: 0xa1},
+ {value: 0x2cdd, lo: 0xa2, hi: 0xa9},
+ {value: 0x2be1, lo: 0xaa, hi: 0xaa},
+ {value: 0x2cfd, lo: 0xab, hi: 0xbe},
+ {value: 0x2ac1, lo: 0xbf, hi: 0xbf},
+ // Block 0x4a, offset 0x4b
+ {value: 0x0004, lo: 0x0b},
+ {value: 0x2d4d, lo: 0x80, hi: 0x83},
+ {value: 0x1b72, lo: 0x84, hi: 0x84},
+ {value: 0x2d5d, lo: 0x85, hi: 0x90},
+ {value: 0x2173, lo: 0x91, hi: 0x91},
+ {value: 0x2d8d, lo: 0x92, hi: 0x9a},
+ {value: 0x2be9, lo: 0x9b, hi: 0x9b},
+ {value: 0x2db1, lo: 0x9c, hi: 0xa8},
+ {value: 0x1aba, lo: 0xa9, hi: 0xa9},
+ {value: 0x2de5, lo: 0xaa, hi: 0xb6},
+ {value: 0x19f6, lo: 0xb7, hi: 0xb7},
+ {value: 0x2e19, lo: 0xb8, hi: 0xbf},
+ // Block 0x4b, offset 0x4c
+ {value: 0x0004, lo: 0x10},
+ {value: 0x2e39, lo: 0x80, hi: 0x87},
+ {value: 0x1a62, lo: 0x88, hi: 0x88},
+ {value: 0x2e59, lo: 0x89, hi: 0x89},
+ {value: 0x1a6e, lo: 0x8a, hi: 0x8a},
+ {value: 0x2e5d, lo: 0x8b, hi: 0x8d},
+ {value: 0x2e69, lo: 0x90, hi: 0x90},
+ {value: 0x2e6d, lo: 0x92, hi: 0x92},
+ {value: 0x2e71, lo: 0x95, hi: 0x9d},
+ {value: 0x1a12, lo: 0x9e, hi: 0x9e},
+ {value: 0x2e95, lo: 0xa0, hi: 0xa0},
+ {value: 0x2e99, lo: 0xa2, hi: 0xa2},
+ {value: 0x2e9d, lo: 0xa5, hi: 0xa6},
+ {value: 0x2ea5, lo: 0xaa, hi: 0xad},
+ {value: 0x2eb5, lo: 0xb0, hi: 0xbb},
+ {value: 0x18d6, lo: 0xbc, hi: 0xbc},
+ {value: 0x2ee5, lo: 0xbd, hi: 0xbf},
+ // Block 0x4c, offset 0x4d
+ {value: 0x0004, lo: 0x10},
+ {value: 0x2ef1, lo: 0x80, hi: 0x8b},
+ {value: 0x2187, lo: 0x8c, hi: 0x8c},
+ {value: 0x2f21, lo: 0x8d, hi: 0x90},
+ {value: 0x2197, lo: 0x91, hi: 0x91},
+ {value: 0x2f31, lo: 0x92, hi: 0x96},
+ {value: 0x2cb1, lo: 0x97, hi: 0x97},
+ {value: 0x2f45, lo: 0x98, hi: 0x9d},
+ {value: 0x2f59, lo: 0x9e, hi: 0xa6},
+ {value: 0x2e9d, lo: 0xa7, hi: 0xa7},
+ {value: 0x2f7d, lo: 0xa8, hi: 0xac},
+ {value: 0x2f92, lo: 0xad, hi: 0xad},
+ {value: 0x2f96, lo: 0xb0, hi: 0xb7},
+ {value: 0x2ecd, lo: 0xb8, hi: 0xb8},
+ {value: 0x2fb6, lo: 0xb9, hi: 0xbb},
+ {value: 0x2e69, lo: 0xbc, hi: 0xbc},
+ {value: 0x2fc2, lo: 0xbd, hi: 0xbf},
+ // Block 0x4d, offset 0x4e
+ {value: 0x0005, lo: 0x06},
+ {value: 0x3277, lo: 0x80, hi: 0x80},
+ {value: 0x327e, lo: 0x81, hi: 0x81},
+ {value: 0x3285, lo: 0x82, hi: 0x82},
+ {value: 0x326d, lo: 0x83, hi: 0x83},
+ {value: 0x328c, lo: 0x84, hi: 0x84},
+ {value: 0x3293, lo: 0x85, hi: 0xbf},
+ // Block 0x4e, offset 0x4f
+ {value: 0x0005, lo: 0x10},
+ {value: 0x356a, lo: 0x80, hi: 0x8b},
+ {value: 0x3514, lo: 0x8c, hi: 0x8c},
+ {value: 0x35a6, lo: 0x8d, hi: 0x90},
+ {value: 0x3533, lo: 0x91, hi: 0xa7},
+ {value: 0x3514, lo: 0xa8, hi: 0xa8},
+ {value: 0x35a6, lo: 0xa9, hi: 0xac},
+ {value: 0x3597, lo: 0xad, hi: 0xaf},
+ {value: 0x3514, lo: 0xb0, hi: 0xb0},
+ {value: 0x350f, lo: 0xb1, hi: 0xb1},
+ {value: 0x3519, lo: 0xb2, hi: 0xb2},
+ {value: 0x333d, lo: 0xb3, hi: 0xb3},
+ {value: 0x3306, lo: 0xb4, hi: 0xb6},
+ {value: 0x3597, lo: 0xb7, hi: 0xb9},
+ {value: 0x333d, lo: 0xba, hi: 0xbb},
+ {value: 0x35ba, lo: 0xbc, hi: 0xbc},
+ {value: 0x35ba, lo: 0xbd, hi: 0xbd},
+ // Block 0x4f, offset 0x50
+ {value: 0x0007, lo: 0x0d},
+ {value: 0x35bf, lo: 0x90, hi: 0x91},
+ {value: 0x35c6, lo: 0x92, hi: 0x98},
+ {value: 0x35f0, lo: 0x99, hi: 0x9f},
+ {value: 0x361a, lo: 0xa0, hi: 0xa2},
+ {value: 0x3628, lo: 0xa3, hi: 0xa4},
+ {value: 0x362f, lo: 0xa5, hi: 0xa7},
+ {value: 0x363d, lo: 0xa8, hi: 0xaa},
+ {value: 0x364b, lo: 0xab, hi: 0xac},
+ {value: 0x3652, lo: 0xad, hi: 0xaf},
+ {value: 0x3660, lo: 0xb0, hi: 0xb1},
+ {value: 0x3667, lo: 0xb2, hi: 0xb6},
+ {value: 0x3683, lo: 0xb7, hi: 0xbc},
+ {value: 0x36a6, lo: 0xbd, hi: 0xbf},
+ // Block 0x50, offset 0x51
+ {value: 0x0007, lo: 0x0d},
+ {value: 0x36bb, lo: 0x80, hi: 0x83},
+ {value: 0x36d0, lo: 0x84, hi: 0x85},
+ {value: 0x36d7, lo: 0x86, hi: 0x87},
+ {value: 0x36de, lo: 0x88, hi: 0x8f},
+ {value: 0x3716, lo: 0x92, hi: 0x97},
+ {value: 0x3739, lo: 0x98, hi: 0x9c},
+ {value: 0x3755, lo: 0x9d, hi: 0xb3},
+ {value: 0x36ad, lo: 0xb4, hi: 0xb4},
+ {value: 0x36bb, lo: 0xb5, hi: 0xb5},
+ {value: 0x37f6, lo: 0xb6, hi: 0xbb},
+ {value: 0x3812, lo: 0xbc, hi: 0xbc},
+ {value: 0x3804, lo: 0xbd, hi: 0xbd},
+ {value: 0x3820, lo: 0xbe, hi: 0xbf},
+ // Block 0x51, offset 0x52
+ {value: 0x0009, lo: 0x0e},
+ {value: 0x382e, lo: 0x80, hi: 0x80},
+ {value: 0x3835, lo: 0x81, hi: 0x81},
+ {value: 0x383c, lo: 0x82, hi: 0x82},
+ {value: 0x3819, lo: 0x83, hi: 0x83},
+ {value: 0x367c, lo: 0x84, hi: 0x84},
+ {value: 0x3636, lo: 0x85, hi: 0x85},
+ {value: 0x3843, lo: 0x86, hi: 0x86},
+ {value: 0x384a, lo: 0x87, hi: 0x87},
+ {value: 0x3851, lo: 0xb0, hi: 0xb0},
+ {value: 0x3858, lo: 0xb1, hi: 0xb1},
+ {value: 0x385f, lo: 0xb2, hi: 0xb9},
+ {value: 0x38a5, lo: 0xba, hi: 0xba},
+ {value: 0x38c7, lo: 0xbb, hi: 0xbb},
+ {value: 0x38d7, lo: 0xbc, hi: 0xbc},
+ // Block 0x52, offset 0x53
+ {value: 0x0004, lo: 0x10},
+ {value: 0x38e0, lo: 0x90, hi: 0x90},
+ {value: 0x38e2, lo: 0x91, hi: 0x93},
+ {value: 0x04e1, lo: 0x94, hi: 0x94},
+ {value: 0x38ec, lo: 0x95, hi: 0x95},
+ {value: 0x38ee, lo: 0x96, hi: 0x96},
+ {value: 0x38f0, lo: 0x97, hi: 0x98},
+ {value: 0x1443, lo: 0x99, hi: 0x99},
+ {value: 0x1440, lo: 0xb0, hi: 0xb0},
+ {value: 0x38f8, lo: 0xb1, hi: 0xb3},
+ {value: 0x3900, lo: 0xb4, hi: 0xb4},
+ {value: 0x149c, lo: 0xb5, hi: 0xb5},
+ {value: 0x149e, lo: 0xb6, hi: 0xb6},
+ {value: 0x3902, lo: 0xb7, hi: 0xb7},
+ {value: 0x3904, lo: 0xb8, hi: 0xb8},
+ {value: 0x3906, lo: 0xb9, hi: 0xbe},
+ {value: 0x16c3, lo: 0xbf, hi: 0xbf},
+ // Block 0x53, offset 0x54
+ {value: 0x0004, lo: 0x04},
+ {value: 0x22a5, lo: 0x80, hi: 0x9c},
+ {value: 0x3a38, lo: 0x9d, hi: 0x9f},
+ {value: 0x1e04, lo: 0xa0, hi: 0xa0},
+ {value: 0x1d38, lo: 0xa1, hi: 0xbe},
+ // Block 0x54, offset 0x55
+ {value: 0x0004, lo: 0x0c},
+ {value: 0x1db0, lo: 0x82, hi: 0x87},
+ {value: 0x1dc8, lo: 0x8a, hi: 0x8f},
+ {value: 0x1de0, lo: 0x92, hi: 0x97},
+ {value: 0x1df8, lo: 0x9a, hi: 0x9c},
+ {value: 0x3a44, lo: 0xa0, hi: 0xa0},
+ {value: 0x3a47, lo: 0xa1, hi: 0xa1},
+ {value: 0x3a4a, lo: 0xa2, hi: 0xa2},
+ {value: 0x0009, lo: 0xa3, hi: 0xa3},
+ {value: 0x3a4d, lo: 0xa4, hi: 0xa4},
+ {value: 0x3a50, lo: 0xa5, hi: 0xa5},
+ {value: 0x3a53, lo: 0xa6, hi: 0xa6},
+ {value: 0x3a57, lo: 0xa8, hi: 0xae},
+ // Block 0x55, offset 0x56
+ {value: 0x0009, lo: 0x03},
+ {value: 0x3a73, lo: 0x9a, hi: 0x9a},
+ {value: 0x3a7c, lo: 0x9c, hi: 0x9c},
+ {value: 0x3a85, lo: 0xab, hi: 0xab},
+ // Block 0x56, offset 0x57
+ {value: 0x000d, lo: 0x03},
+ {value: 0x3a8e, lo: 0x9e, hi: 0x9e},
+ {value: 0x3a97, lo: 0x9f, hi: 0x9f},
+ {value: 0x3aa0, lo: 0xa0, hi: 0xa4},
+ // Block 0x57, offset 0x58
+ {value: 0x0009, lo: 0x03},
+ {value: 0x3ae1, lo: 0xbb, hi: 0xbd},
+ {value: 0x3b00, lo: 0xbe, hi: 0xbe},
+ {value: 0x3b0d, lo: 0xbf, hi: 0xbf},
+ // Block 0x58, offset 0x59
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3b1a, lo: 0x80, hi: 0x80},
+ // Block 0x59, offset 0x5a
+ {value: 0x0003, lo: 0x0e},
+ {value: 0x14c8, lo: 0x80, hi: 0x80},
+ {value: 0x092b, lo: 0x81, hi: 0x81},
+ {value: 0x17f6, lo: 0x82, hi: 0x82},
+ {value: 0x092d, lo: 0x83, hi: 0x83},
+ {value: 0x092f, lo: 0x84, hi: 0x84},
+ {value: 0x155f, lo: 0x85, hi: 0x85},
+ {value: 0x0931, lo: 0x86, hi: 0x86},
+ {value: 0x1570, lo: 0x87, hi: 0x87},
+ {value: 0x17f8, lo: 0x88, hi: 0x88},
+ {value: 0x14d4, lo: 0x89, hi: 0x89},
+ {value: 0x3c2c, lo: 0x8a, hi: 0x8a},
+ {value: 0x293d, lo: 0x8b, hi: 0x8b},
+ {value: 0x3c2f, lo: 0x8c, hi: 0x8e},
+ {value: 0x3c39, lo: 0x8f, hi: 0x8f},
+ // Block 0x5a, offset 0x5b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3c3c, lo: 0x90, hi: 0x90},
+ // Block 0x5b, offset 0x5c
+ {value: 0x000a, lo: 0x03},
+ {value: 0x3cc1, lo: 0x80, hi: 0x88},
+ {value: 0x3d1b, lo: 0x90, hi: 0x90},
+ {value: 0x3d1f, lo: 0x91, hi: 0x91},
+ // Block 0x5c, offset 0x5d
+ {value: 0x0004, lo: 0x0d},
+ {value: 0x4463, lo: 0x80, hi: 0x81},
+ {value: 0x446c, lo: 0x82, hi: 0x89},
+ {value: 0x30a2, lo: 0x8a, hi: 0x8a},
+ {value: 0x448d, lo: 0x8b, hi: 0x90},
+ {value: 0x44a6, lo: 0x91, hi: 0x92},
+ {value: 0x44af, lo: 0x93, hi: 0x93},
+ {value: 0x44b4, lo: 0x94, hi: 0x94},
+ {value: 0x1b42, lo: 0x95, hi: 0x95},
+ {value: 0x44b9, lo: 0x96, hi: 0x96},
+ {value: 0x1b52, lo: 0x97, hi: 0x97},
+ {value: 0x44bd, lo: 0x98, hi: 0x9b},
+ {value: 0x1b66, lo: 0x9c, hi: 0x9c},
+ {value: 0x44cd, lo: 0x9d, hi: 0x9d},
}
// nfkcDecompLookup: 960 bytes
@@ -4367,51 +4608,51 @@ var nfkcDecompLookup = [960]uint8{
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x0c2: 0x03, 0x0c3: 0x04, 0x0c4: 0x05, 0x0c5: 0x06, 0x0c6: 0x07, 0x0c7: 0x08,
- 0x0c8: 0x09, 0x0ca: 0x0a, 0x0cb: 0x0b, 0x0cd: 0x0c, 0x0ce: 0x0d, 0x0cf: 0x0e,
- 0x0d0: 0x0f, 0x0d1: 0x10, 0x0d3: 0x11, 0x0d6: 0x12,
- 0x0d8: 0x13, 0x0d9: 0x14, 0x0db: 0x15,
+ 0x0c2: 0x42, 0x0c3: 0x43, 0x0c4: 0x44, 0x0c5: 0x45, 0x0c6: 0x46, 0x0c7: 0x03,
+ 0x0c8: 0x47, 0x0ca: 0x48, 0x0cb: 0x49, 0x0cd: 0x4a, 0x0ce: 0x4b, 0x0cf: 0x4c,
+ 0x0d0: 0x4d, 0x0d1: 0x4e, 0x0d3: 0x4f, 0x0d6: 0x50,
+ 0x0d8: 0x51, 0x0d9: 0x52, 0x0db: 0x53,
0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07,
0x0ea: 0x08, 0x0ef: 0x09,
0x0f0: 0x0e,
// Block 0x4, offset 0x100
- 0x124: 0x16, 0x125: 0x17, 0x127: 0x18,
- 0x128: 0x19, 0x129: 0x1a, 0x12d: 0x1b, 0x12e: 0x1c, 0x12f: 0x1d,
- 0x131: 0x1e, 0x133: 0x1f, 0x135: 0x20, 0x137: 0x21,
- 0x138: 0x22, 0x13a: 0x23, 0x13b: 0x24, 0x13c: 0x25, 0x13d: 0x26, 0x13e: 0x27,
+ 0x124: 0x54, 0x125: 0x55, 0x127: 0x56,
+ 0x128: 0x57, 0x129: 0x58, 0x12d: 0x59, 0x12e: 0x5a, 0x12f: 0x5b,
+ 0x131: 0x5c, 0x133: 0x5d, 0x135: 0x5e, 0x137: 0x5f,
+ 0x138: 0x60, 0x13a: 0x61, 0x13b: 0x62, 0x13c: 0x63, 0x13d: 0x64, 0x13e: 0x65,
// Block 0x5, offset 0x140
- 0x140: 0x28, 0x143: 0x29,
- 0x16c: 0x2a, 0x16d: 0x2b,
- 0x174: 0x2c, 0x175: 0x2d, 0x176: 0x2e,
- 0x178: 0x2f, 0x179: 0x30, 0x17a: 0x31, 0x17b: 0x32, 0x17c: 0x33, 0x17d: 0x34, 0x17e: 0x35, 0x17f: 0x36,
+ 0x140: 0x66, 0x143: 0x67,
+ 0x16c: 0x68, 0x16d: 0x69,
+ 0x174: 0x6a, 0x175: 0x04, 0x176: 0x6b,
+ 0x178: 0x6c, 0x179: 0x05, 0x17a: 0x06, 0x17b: 0x07, 0x17c: 0x08, 0x17d: 0x09, 0x17e: 0x0a, 0x17f: 0x0b,
// Block 0x6, offset 0x180
- 0x180: 0x37, 0x181: 0x38, 0x182: 0x39, 0x184: 0x3a, 0x185: 0x3b, 0x186: 0x3c, 0x187: 0x3d,
- 0x188: 0x3e, 0x189: 0x3f, 0x18a: 0x40, 0x18b: 0x41, 0x18c: 0x42,
- 0x191: 0x43, 0x192: 0x44, 0x193: 0x45,
- 0x1a8: 0x46, 0x1a9: 0x47, 0x1ab: 0x48,
- 0x1b1: 0x49, 0x1b5: 0x4a,
- 0x1ba: 0x4b, 0x1bb: 0x4c, 0x1bc: 0x4d, 0x1bd: 0x4e, 0x1be: 0x4f, 0x1bf: 0x50,
+ 0x180: 0x6d, 0x181: 0x6e, 0x182: 0x0c, 0x184: 0x0d, 0x185: 0x0e, 0x186: 0x6f, 0x187: 0x70,
+ 0x188: 0x71, 0x189: 0x72, 0x18a: 0x73, 0x18b: 0x74, 0x18c: 0x75,
+ 0x191: 0x0f, 0x192: 0x10, 0x193: 0x11,
+ 0x1a8: 0x76, 0x1a9: 0x77, 0x1ab: 0x78,
+ 0x1b1: 0x79, 0x1b5: 0x7a,
+ 0x1ba: 0x7b, 0x1bb: 0x7c, 0x1bc: 0x7d, 0x1bd: 0x7e, 0x1be: 0x7f, 0x1bf: 0x80,
// Block 0x7, offset 0x1c0
- 0x1c0: 0x51, 0x1c1: 0x52, 0x1c2: 0x53, 0x1c3: 0x54, 0x1c4: 0x55, 0x1c5: 0x56, 0x1c6: 0x57,
- 0x1c8: 0x58, 0x1c9: 0x59, 0x1ca: 0x5a, 0x1cb: 0x5b, 0x1cc: 0x5c, 0x1cd: 0x5d, 0x1ce: 0x5e, 0x1cf: 0x5f,
+ 0x1c0: 0x81, 0x1c1: 0x12, 0x1c2: 0x82, 0x1c3: 0x83, 0x1c4: 0x84, 0x1c5: 0x85, 0x1c6: 0x86,
+ 0x1c8: 0x13, 0x1c9: 0x14, 0x1ca: 0x15, 0x1cb: 0x87, 0x1cc: 0x16, 0x1cd: 0x17, 0x1ce: 0x18, 0x1cf: 0x19,
// Block 0x8, offset 0x200
- 0x21d: 0x60,
+ 0x21d: 0x88,
// Block 0x9, offset 0x240
- 0x264: 0x61, 0x265: 0x62, 0x266: 0x63, 0x267: 0x64,
- 0x268: 0x65, 0x269: 0x66, 0x26a: 0x67, 0x26b: 0x68, 0x26c: 0x69, 0x26d: 0x6a, 0x26e: 0x6b, 0x26f: 0x6c,
- 0x270: 0x6d, 0x271: 0x6e, 0x272: 0x6f, 0x273: 0x70, 0x274: 0x71, 0x275: 0x72, 0x276: 0x73, 0x277: 0x74,
- 0x278: 0x75, 0x279: 0x76, 0x27a: 0x77, 0x27b: 0x78, 0x27c: 0x79, 0x27d: 0x7a, 0x27e: 0x7b, 0x27f: 0x7c,
+ 0x264: 0x89, 0x265: 0x8a, 0x266: 0x8b, 0x267: 0x8c,
+ 0x268: 0x8d, 0x269: 0x8e, 0x26a: 0x1a, 0x26b: 0x1b, 0x26c: 0x1c, 0x26d: 0x1d, 0x26e: 0x1e, 0x26f: 0x1f,
+ 0x270: 0x8f, 0x271: 0x20, 0x272: 0x21, 0x273: 0x22, 0x274: 0x90, 0x275: 0x91, 0x276: 0x92, 0x277: 0x93,
+ 0x278: 0x94, 0x279: 0x23, 0x27a: 0x24, 0x27b: 0x25, 0x27c: 0x26, 0x27d: 0x27, 0x27e: 0x95, 0x27f: 0x96,
// Block 0xa, offset 0x280
- 0x282: 0x7d,
+ 0x282: 0x97,
// Block 0xb, offset 0x2c0
- 0x2c5: 0x7e, 0x2c6: 0x7f, 0x2c7: 0x80,
- 0x2d0: 0x81, 0x2d1: 0x82, 0x2d2: 0x83, 0x2d3: 0x84, 0x2d4: 0x85, 0x2d5: 0x86, 0x2d6: 0x87, 0x2d7: 0x88,
- 0x2d8: 0x89, 0x2d9: 0x8a, 0x2da: 0x8b, 0x2db: 0x8c, 0x2dc: 0x8d, 0x2dd: 0x8e, 0x2de: 0x8f, 0x2df: 0x90,
+ 0x2c5: 0x98, 0x2c6: 0x99, 0x2c7: 0x9a,
+ 0x2d0: 0x28, 0x2d1: 0x29, 0x2d2: 0x2a, 0x2d3: 0x2b, 0x2d4: 0x2c, 0x2d5: 0x2d, 0x2d6: 0x2e, 0x2d7: 0x2f,
+ 0x2d8: 0x30, 0x2d9: 0x31, 0x2da: 0x32, 0x2db: 0x33, 0x2dc: 0x34, 0x2dd: 0x35, 0x2de: 0x36, 0x2df: 0x37,
// Block 0xc, offset 0x300
- 0x304: 0x91, 0x305: 0x92, 0x306: 0x93,
- 0x308: 0x94, 0x309: 0x95,
+ 0x304: 0x38, 0x305: 0x9b, 0x306: 0x9c,
+ 0x308: 0x39, 0x309: 0x9d,
// Block 0xd, offset 0x340
- 0x360: 0x96, 0x361: 0x97, 0x362: 0x98, 0x363: 0x99, 0x364: 0x9a, 0x365: 0x9b, 0x366: 0x9c, 0x367: 0x9d,
+ 0x360: 0x3a, 0x361: 0x3b, 0x362: 0x3c, 0x363: 0x3d, 0x364: 0x3e, 0x365: 0x3f, 0x366: 0x40, 0x367: 0x41,
0x368: 0x9e,
// Block 0xe, offset 0x380
0x391: 0x0a,
@@ -4419,7 +4660,7 @@ var nfkcDecompLookup = [960]uint8{
0x3af: 0x0d,
}
-var nfkcDecompTrie = trie{nfkcDecompLookup[:], nfkcDecompValues[:]}
+var nfkcDecompTrie = trie{nfkcDecompLookup[:], nfkcDecompValues[:], nfkcDecompSparseValues[:], nfkcDecompSparseOffset[:], 66}
// recompMap: 7448 bytes (entries only)
var recompMap = map[uint32]uint32{
@@ -5356,9 +5597,9 @@ var recompMap = map[uint32]uint32{
0x10A510BA: 0x110AB,
}
-// charInfoValues: 10944 entries, 21888 bytes
+// charInfoValues: 1024 entries, 2048 bytes
// Block 2 is the null block.
-var charInfoValues = [10944]uint16{
+var charInfoValues = [1024]uint16{
// Block 0x0, offset 0x0
0x003c: 0x8800, 0x003d: 0x8800, 0x003e: 0x8800,
// Block 0x1, offset 0x40
@@ -5374,1121 +5615,1071 @@ var charInfoValues = [10944]uint16{
0x0076: 0x8800, 0x0077: 0x8800, 0x0078: 0x8800, 0x0079: 0x8800, 0x007a: 0x8800,
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x00e0: 0x3000,
- 0x00e8: 0x3800,
- 0x00ea: 0x3000, 0x00ef: 0x3000,
- 0x00f2: 0x3000, 0x00f3: 0x3000, 0x00f4: 0x3000, 0x00f5: 0x3000,
- 0x00f8: 0x3000, 0x00f9: 0x3000, 0x00fa: 0x3000,
- 0x00fc: 0x3000, 0x00fd: 0x3000, 0x00fe: 0x3000,
+ 0x00c0: 0x1100, 0x00c1: 0x1100, 0x00c2: 0x9900, 0x00c3: 0x1100, 0x00c4: 0x9900, 0x00c5: 0x9900,
+ 0x00c6: 0x8800, 0x00c7: 0x9900, 0x00c8: 0x1100, 0x00c9: 0x1100, 0x00ca: 0x9900, 0x00cb: 0x1100,
+ 0x00cc: 0x1100, 0x00cd: 0x1100, 0x00ce: 0x1100, 0x00cf: 0x9900, 0x00d1: 0x1100,
+ 0x00d2: 0x1100, 0x00d3: 0x1100, 0x00d4: 0x9900, 0x00d5: 0x9900, 0x00d6: 0x9900,
+ 0x00d8: 0x8800, 0x00d9: 0x1100, 0x00da: 0x1100, 0x00db: 0x1100, 0x00dc: 0x9900, 0x00dd: 0x1100,
+ 0x00e0: 0x1100, 0x00e1: 0x1100, 0x00e2: 0x9900, 0x00e3: 0x1100,
+ 0x00e4: 0x9900, 0x00e5: 0x9900, 0x00e6: 0x8800, 0x00e7: 0x9900, 0x00e8: 0x1100, 0x00e9: 0x1100,
+ 0x00ea: 0x9900, 0x00eb: 0x1100, 0x00ec: 0x1100, 0x00ed: 0x1100, 0x00ee: 0x1100, 0x00ef: 0x9900,
+ 0x00f1: 0x1100, 0x00f2: 0x1100, 0x00f3: 0x1100, 0x00f4: 0x9900, 0x00f5: 0x9900,
+ 0x00f6: 0x9900, 0x00f8: 0x8800, 0x00f9: 0x1100, 0x00fa: 0x1100, 0x00fb: 0x1100,
+ 0x00fc: 0x9900, 0x00fd: 0x1100, 0x00ff: 0x1100,
// Block 0x4, offset 0x100
- 0x0100: 0x1100, 0x0101: 0x1100, 0x0102: 0x9900, 0x0103: 0x1100, 0x0104: 0x9900, 0x0105: 0x9900,
- 0x0106: 0x8800, 0x0107: 0x9900, 0x0108: 0x1100, 0x0109: 0x1100, 0x010a: 0x9900, 0x010b: 0x1100,
- 0x010c: 0x1100, 0x010d: 0x1100, 0x010e: 0x1100, 0x010f: 0x9900, 0x0111: 0x1100,
- 0x0112: 0x1100, 0x0113: 0x1100, 0x0114: 0x9900, 0x0115: 0x9900, 0x0116: 0x9900,
- 0x0118: 0x8800, 0x0119: 0x1100, 0x011a: 0x1100, 0x011b: 0x1100, 0x011c: 0x9900, 0x011d: 0x1100,
- 0x0120: 0x1100, 0x0121: 0x1100, 0x0122: 0x9900, 0x0123: 0x1100,
- 0x0124: 0x9900, 0x0125: 0x9900, 0x0126: 0x8800, 0x0127: 0x9900, 0x0128: 0x1100, 0x0129: 0x1100,
- 0x012a: 0x9900, 0x012b: 0x1100, 0x012c: 0x1100, 0x012d: 0x1100, 0x012e: 0x1100, 0x012f: 0x9900,
- 0x0131: 0x1100, 0x0132: 0x1100, 0x0133: 0x1100, 0x0134: 0x9900, 0x0135: 0x9900,
- 0x0136: 0x9900, 0x0138: 0x8800, 0x0139: 0x1100, 0x013a: 0x1100, 0x013b: 0x1100,
- 0x013c: 0x9900, 0x013d: 0x1100, 0x013f: 0x1100,
+ 0x0100: 0x66e6, 0x0101: 0x66e6, 0x0102: 0x66e6, 0x0103: 0x66e6, 0x0104: 0x66e6, 0x0105: 0x00e6,
+ 0x0106: 0x66e6, 0x0107: 0x66e6, 0x0108: 0x66e6, 0x0109: 0x66e6, 0x010a: 0x66e6, 0x010b: 0x66e6,
+ 0x010c: 0x66e6, 0x010d: 0x00e6, 0x010e: 0x00e6, 0x010f: 0x66e6, 0x0110: 0x00e6, 0x0111: 0x66e6,
+ 0x0112: 0x00e6, 0x0113: 0x66e6, 0x0114: 0x66e6, 0x0115: 0x00e8, 0x0116: 0x00dc, 0x0117: 0x00dc,
+ 0x0118: 0x00dc, 0x0119: 0x00dc, 0x011a: 0x00e8, 0x011b: 0x66d8, 0x011c: 0x00dc, 0x011d: 0x00dc,
+ 0x011e: 0x00dc, 0x011f: 0x00dc, 0x0120: 0x00dc, 0x0121: 0x00ca, 0x0122: 0x00ca, 0x0123: 0x66dc,
+ 0x0124: 0x66dc, 0x0125: 0x66dc, 0x0126: 0x66dc, 0x0127: 0x66ca, 0x0128: 0x66ca, 0x0129: 0x00dc,
+ 0x012a: 0x00dc, 0x012b: 0x00dc, 0x012c: 0x00dc, 0x012d: 0x66dc, 0x012e: 0x66dc, 0x012f: 0x00dc,
+ 0x0130: 0x66dc, 0x0131: 0x66dc, 0x0132: 0x00dc, 0x0133: 0x00dc, 0x0134: 0x0001, 0x0135: 0x0001,
+ 0x0136: 0x0001, 0x0137: 0x0001, 0x0138: 0x6601, 0x0139: 0x00dc, 0x013a: 0x00dc, 0x013b: 0x00dc,
+ 0x013c: 0x00dc, 0x013d: 0x00e6, 0x013e: 0x00e6, 0x013f: 0x00e6,
// Block 0x5, offset 0x140
- 0x0140: 0x1100, 0x0141: 0x1100, 0x0142: 0x9900, 0x0143: 0x9900, 0x0144: 0x1100, 0x0145: 0x1100,
- 0x0146: 0x1100, 0x0147: 0x1100, 0x0148: 0x1100, 0x0149: 0x1100, 0x014a: 0x1100, 0x014b: 0x1100,
- 0x014c: 0x1100, 0x014d: 0x1100, 0x014e: 0x1100, 0x014f: 0x1100,
- 0x0152: 0x9900, 0x0153: 0x9900, 0x0154: 0x1100, 0x0155: 0x1100, 0x0156: 0x1100, 0x0157: 0x1100,
- 0x0158: 0x1100, 0x0159: 0x1100, 0x015a: 0x1100, 0x015b: 0x1100, 0x015c: 0x1100, 0x015d: 0x1100,
- 0x015e: 0x1100, 0x015f: 0x1100, 0x0160: 0x1100, 0x0161: 0x1100, 0x0162: 0x1100, 0x0163: 0x1100,
- 0x0164: 0x1100, 0x0165: 0x1100, 0x0168: 0x1100, 0x0169: 0x1100,
- 0x016a: 0x1100, 0x016b: 0x1100, 0x016c: 0x1100, 0x016d: 0x1100, 0x016e: 0x1100, 0x016f: 0x1100,
- 0x0170: 0x1100, 0x0172: 0x3000, 0x0173: 0x3000, 0x0174: 0x1100, 0x0175: 0x1100,
- 0x0176: 0x1100, 0x0177: 0x1100, 0x0179: 0x1100, 0x017a: 0x1100, 0x017b: 0x1100,
- 0x017c: 0x1100, 0x017d: 0x1100, 0x017e: 0x1100, 0x017f: 0x3000,
+ 0x0140: 0x33e6, 0x0141: 0x33e6, 0x0142: 0x66e6, 0x0143: 0x33e6, 0x0144: 0x33e6, 0x0145: 0x66f0,
+ 0x0146: 0x00e6, 0x0147: 0x00dc, 0x0148: 0x00dc, 0x0149: 0x00dc, 0x014a: 0x00e6, 0x014b: 0x00e6,
+ 0x014c: 0x00e6, 0x014d: 0x00dc, 0x014e: 0x00dc, 0x0150: 0x00e6, 0x0151: 0x00e6,
+ 0x0152: 0x00e6, 0x0153: 0x00dc, 0x0154: 0x00dc, 0x0155: 0x00dc, 0x0156: 0x00dc, 0x0157: 0x00e6,
+ 0x0158: 0x00e8, 0x0159: 0x00dc, 0x015a: 0x00dc, 0x015b: 0x00e6, 0x015c: 0x00e9, 0x015d: 0x00ea,
+ 0x015e: 0x00ea, 0x015f: 0x00e9, 0x0160: 0x00ea, 0x0161: 0x00ea, 0x0162: 0x00e9, 0x0163: 0x00e6,
+ 0x0164: 0x00e6, 0x0165: 0x00e6, 0x0166: 0x00e6, 0x0167: 0x00e6, 0x0168: 0x00e6, 0x0169: 0x00e6,
+ 0x016a: 0x00e6, 0x016b: 0x00e6, 0x016c: 0x00e6, 0x016d: 0x00e6, 0x016e: 0x00e6, 0x016f: 0x00e6,
+ 0x0174: 0x3300,
+ 0x017a: 0x3000,
+ 0x017e: 0x3300,
// Block 0x6, offset 0x180
- 0x0180: 0x3000, 0x0183: 0x1100, 0x0184: 0x1100, 0x0185: 0x1100,
- 0x0186: 0x1100, 0x0187: 0x1100, 0x0188: 0x1100, 0x0189: 0x3000,
- 0x018c: 0x9900, 0x018d: 0x9900, 0x018e: 0x1100, 0x018f: 0x1100, 0x0190: 0x1100, 0x0191: 0x1100,
- 0x0194: 0x1100, 0x0195: 0x1100, 0x0196: 0x1100, 0x0197: 0x1100,
- 0x0198: 0x1100, 0x0199: 0x1100, 0x019a: 0x9900, 0x019b: 0x9900, 0x019c: 0x1100, 0x019d: 0x1100,
- 0x019e: 0x1100, 0x019f: 0x1100, 0x01a0: 0x9900, 0x01a1: 0x9900, 0x01a2: 0x1100, 0x01a3: 0x1100,
- 0x01a4: 0x1100, 0x01a5: 0x1100, 0x01a8: 0x9900, 0x01a9: 0x9900,
- 0x01aa: 0x9900, 0x01ab: 0x9900, 0x01ac: 0x1100, 0x01ad: 0x1100, 0x01ae: 0x1100, 0x01af: 0x1100,
- 0x01b0: 0x1100, 0x01b1: 0x1100, 0x01b2: 0x1100, 0x01b3: 0x1100, 0x01b4: 0x1100, 0x01b5: 0x1100,
- 0x01b6: 0x1100, 0x01b7: 0x1100, 0x01b8: 0x1100, 0x01b9: 0x1100, 0x01ba: 0x1100, 0x01bb: 0x1100,
- 0x01bc: 0x1100, 0x01bd: 0x1100, 0x01be: 0x1100, 0x01bf: 0x3800,
+ 0x0184: 0x3000, 0x0185: 0x3100,
+ 0x0186: 0x1100, 0x0187: 0x3300, 0x0188: 0x1100, 0x0189: 0x1100, 0x018a: 0x1100,
+ 0x018c: 0x1100, 0x018e: 0x1100, 0x018f: 0x1100, 0x0190: 0x1100, 0x0191: 0x8800,
+ 0x0195: 0x8800, 0x0197: 0x8800,
+ 0x0199: 0x8800,
+ 0x019f: 0x8800, 0x01a1: 0x8800,
+ 0x01a5: 0x8800, 0x01a9: 0x8800,
+ 0x01aa: 0x1100, 0x01ab: 0x1100, 0x01ac: 0x9900, 0x01ad: 0x1100, 0x01ae: 0x9900, 0x01af: 0x1100,
+ 0x01b0: 0x1100, 0x01b1: 0x8800, 0x01b5: 0x8800,
+ 0x01b7: 0x8800, 0x01b9: 0x8800,
+ 0x01bf: 0x8800,
// Block 0x7, offset 0x1c0
- 0x01e0: 0x9900, 0x01e1: 0x9900,
- 0x01ef: 0x9900,
- 0x01f0: 0x9900,
- 0x01f7: 0x8800,
+ 0x01c0: 0x1100, 0x01c1: 0x1100, 0x01c3: 0x1100,
+ 0x01c6: 0x8800, 0x01c7: 0x1100,
+ 0x01cc: 0x1100, 0x01cd: 0x1100, 0x01ce: 0x1100, 0x01d0: 0x8800,
+ 0x01d3: 0x8800, 0x01d5: 0x8800, 0x01d6: 0x8800, 0x01d7: 0x8800,
+ 0x01d8: 0x8800, 0x01d9: 0x1100, 0x01da: 0x8800,
+ 0x01de: 0x8800, 0x01e3: 0x8800,
+ 0x01e7: 0x8800,
+ 0x01eb: 0x8800, 0x01ed: 0x8800,
+ 0x01f0: 0x8800, 0x01f3: 0x8800, 0x01f5: 0x8800,
+ 0x01f6: 0x8800, 0x01f7: 0x8800, 0x01f8: 0x8800, 0x01f9: 0x1100, 0x01fa: 0x8800,
+ 0x01fe: 0x8800,
// Block 0x8, offset 0x200
- 0x0204: 0x3000, 0x0205: 0x3000,
- 0x0206: 0x3000, 0x0207: 0x3000, 0x0208: 0x3000, 0x0209: 0x3000, 0x020a: 0x3000, 0x020b: 0x3000,
- 0x020c: 0x3000, 0x020d: 0x1100, 0x020e: 0x1100, 0x020f: 0x1100, 0x0210: 0x1100, 0x0211: 0x1100,
- 0x0212: 0x1100, 0x0213: 0x1100, 0x0214: 0x1100, 0x0215: 0x1100, 0x0216: 0x1100, 0x0217: 0x1100,
- 0x0218: 0x1100, 0x0219: 0x1100, 0x021a: 0x1100, 0x021b: 0x1100, 0x021c: 0x1100,
- 0x021e: 0x1100, 0x021f: 0x1100, 0x0220: 0x1100, 0x0221: 0x1100, 0x0222: 0x1100, 0x0223: 0x1100,
- 0x0226: 0x1100, 0x0227: 0x1100, 0x0228: 0x1100, 0x0229: 0x1100,
- 0x022a: 0x9900, 0x022b: 0x9900, 0x022c: 0x1100, 0x022d: 0x1100, 0x022e: 0x1100, 0x022f: 0x1100,
- 0x0230: 0x1100, 0x0231: 0x3000, 0x0232: 0x3000, 0x0233: 0x3000, 0x0234: 0x1100, 0x0235: 0x1100,
- 0x0238: 0x1100, 0x0239: 0x1100, 0x023a: 0x1100, 0x023b: 0x1100,
- 0x023c: 0x1100, 0x023d: 0x1100, 0x023e: 0x1100, 0x023f: 0x1100,
+ 0x0207: 0x3000,
+ 0x0211: 0x00dc,
+ 0x0212: 0x00e6, 0x0213: 0x00e6, 0x0214: 0x00e6, 0x0215: 0x00e6, 0x0216: 0x00dc, 0x0217: 0x00e6,
+ 0x0218: 0x00e6, 0x0219: 0x00e6, 0x021a: 0x00de, 0x021b: 0x00dc, 0x021c: 0x00e6, 0x021d: 0x00e6,
+ 0x021e: 0x00e6, 0x021f: 0x00e6, 0x0220: 0x00e6, 0x0221: 0x00e6, 0x0222: 0x00dc, 0x0223: 0x00dc,
+ 0x0224: 0x00dc, 0x0225: 0x00dc, 0x0226: 0x00dc, 0x0227: 0x00dc, 0x0228: 0x00e6, 0x0229: 0x00e6,
+ 0x022a: 0x00dc, 0x022b: 0x00e6, 0x022c: 0x00e6, 0x022d: 0x00de, 0x022e: 0x00e4, 0x022f: 0x00e6,
+ 0x0230: 0x000a, 0x0231: 0x000b, 0x0232: 0x000c, 0x0233: 0x000d, 0x0234: 0x000e, 0x0235: 0x000f,
+ 0x0236: 0x0010, 0x0237: 0x0011, 0x0238: 0x0012, 0x0239: 0x0013, 0x023a: 0x0013, 0x023b: 0x0014,
+ 0x023c: 0x0015, 0x023d: 0x0016, 0x023f: 0x0017,
// Block 0x9, offset 0x240
- 0x0240: 0x1100, 0x0241: 0x1100, 0x0242: 0x1100, 0x0243: 0x1100, 0x0244: 0x1100, 0x0245: 0x1100,
- 0x0246: 0x1100, 0x0247: 0x1100, 0x0248: 0x1100, 0x0249: 0x1100, 0x024a: 0x1100, 0x024b: 0x1100,
- 0x024c: 0x1100, 0x024d: 0x1100, 0x024e: 0x1100, 0x024f: 0x1100, 0x0250: 0x1100, 0x0251: 0x1100,
- 0x0252: 0x1100, 0x0253: 0x1100, 0x0254: 0x1100, 0x0255: 0x1100, 0x0256: 0x1100, 0x0257: 0x1100,
- 0x0258: 0x1100, 0x0259: 0x1100, 0x025a: 0x1100, 0x025b: 0x1100,
- 0x025e: 0x1100, 0x025f: 0x1100,
- 0x0266: 0x9900, 0x0267: 0x9900, 0x0268: 0x9900, 0x0269: 0x9900,
- 0x026a: 0x1100, 0x026b: 0x1100, 0x026c: 0x1100, 0x026d: 0x1100, 0x026e: 0x9900, 0x026f: 0x9900,
- 0x0270: 0x1100, 0x0271: 0x1100, 0x0272: 0x1100, 0x0273: 0x1100,
+ 0x0248: 0x8800, 0x024a: 0x8800, 0x024b: 0x001b,
+ 0x024c: 0x001c, 0x024d: 0x001d, 0x024e: 0x001e, 0x024f: 0x001f, 0x0250: 0x0020, 0x0251: 0x0021,
+ 0x0252: 0x0022, 0x0253: 0x66e6, 0x0254: 0x66e6, 0x0255: 0x66dc, 0x0256: 0x00dc, 0x0257: 0x00e6,
+ 0x0258: 0x00e6, 0x0259: 0x00e6, 0x025a: 0x00e6, 0x025b: 0x00e6, 0x025c: 0x00dc, 0x025d: 0x00e6,
+ 0x025e: 0x00e6, 0x025f: 0x00dc,
+ 0x0270: 0x0023, 0x0275: 0x3000,
+ 0x0276: 0x3000, 0x0277: 0x3000, 0x0278: 0x3000,
// Block 0xa, offset 0x280
- 0x0292: 0x8800,
- 0x02b0: 0x3000, 0x02b1: 0x3000, 0x02b2: 0x3000, 0x02b3: 0x3000, 0x02b4: 0x3000, 0x02b5: 0x3000,
- 0x02b6: 0x3000, 0x02b7: 0x3000, 0x02b8: 0x3000,
+ 0x0280: 0x9900, 0x0281: 0x9900, 0x0282: 0x1100, 0x0283: 0x1100, 0x0284: 0x1100, 0x0285: 0x1100,
+ 0x0288: 0x9900, 0x0289: 0x9900, 0x028a: 0x1100, 0x028b: 0x1100,
+ 0x028c: 0x1100, 0x028d: 0x1100, 0x0290: 0x9900, 0x0291: 0x9900,
+ 0x0292: 0x1100, 0x0293: 0x1100, 0x0294: 0x1100, 0x0295: 0x1100, 0x0296: 0x1100, 0x0297: 0x1100,
+ 0x0299: 0x9900, 0x029b: 0x1100, 0x029d: 0x1100,
+ 0x029f: 0x1100, 0x02a0: 0x9900, 0x02a1: 0x9900, 0x02a2: 0x9900, 0x02a3: 0x9900,
+ 0x02a4: 0x9900, 0x02a5: 0x9900, 0x02a6: 0x9900, 0x02a7: 0x9900, 0x02a8: 0x9900, 0x02a9: 0x9900,
+ 0x02aa: 0x9900, 0x02ab: 0x9900, 0x02ac: 0x9900, 0x02ad: 0x9900, 0x02ae: 0x9900, 0x02af: 0x9900,
+ 0x02b0: 0x9900, 0x02b1: 0x3300, 0x02b2: 0x1100, 0x02b3: 0x3300, 0x02b4: 0x9900, 0x02b5: 0x3300,
+ 0x02b6: 0x1100, 0x02b7: 0x3300, 0x02b8: 0x1100, 0x02b9: 0x3300, 0x02ba: 0x1100, 0x02bb: 0x3300,
+ 0x02bc: 0x9900, 0x02bd: 0x3300,
// Block 0xb, offset 0x2c0
- 0x02d8: 0x3000, 0x02d9: 0x3000, 0x02da: 0x3000, 0x02db: 0x3000, 0x02dc: 0x3000, 0x02dd: 0x3000,
- 0x02e0: 0x3000, 0x02e1: 0x3000, 0x02e2: 0x3000, 0x02e3: 0x3000,
- 0x02e4: 0x3000,
+ 0x02c0: 0x3000, 0x02c1: 0x3100, 0x02c2: 0x1100, 0x02c3: 0x1100, 0x02c4: 0x1100,
+ 0x02c6: 0x9900, 0x02c7: 0x1100, 0x02c8: 0x1100, 0x02c9: 0x3300, 0x02ca: 0x1100, 0x02cb: 0x3300,
+ 0x02cc: 0x1100, 0x02cd: 0x3100, 0x02ce: 0x3100, 0x02cf: 0x3100, 0x02d0: 0x1100, 0x02d1: 0x1100,
+ 0x02d2: 0x1100, 0x02d3: 0x3300, 0x02d6: 0x1100, 0x02d7: 0x1100,
+ 0x02d8: 0x1100, 0x02d9: 0x1100, 0x02da: 0x1100, 0x02db: 0x3300, 0x02dd: 0x3100,
+ 0x02de: 0x3100, 0x02df: 0x3100, 0x02e0: 0x1100, 0x02e1: 0x1100, 0x02e2: 0x1100, 0x02e3: 0x3300,
+ 0x02e4: 0x1100, 0x02e5: 0x1100, 0x02e6: 0x1100, 0x02e7: 0x1100, 0x02e8: 0x1100, 0x02e9: 0x1100,
+ 0x02ea: 0x1100, 0x02eb: 0x3300, 0x02ec: 0x1100, 0x02ed: 0x3100, 0x02ee: 0x3300, 0x02ef: 0x3300,
+ 0x02f2: 0x1100, 0x02f3: 0x1100, 0x02f4: 0x1100,
+ 0x02f6: 0x9900, 0x02f7: 0x1100, 0x02f8: 0x1100, 0x02f9: 0x3300, 0x02fa: 0x1100, 0x02fb: 0x3300,
+ 0x02fc: 0x1100, 0x02fd: 0x3300, 0x02fe: 0x3800,
// Block 0xc, offset 0x300
- 0x0300: 0x66e6, 0x0301: 0x66e6, 0x0302: 0x66e6, 0x0303: 0x66e6, 0x0304: 0x66e6, 0x0305: 0x00e6,
- 0x0306: 0x66e6, 0x0307: 0x66e6, 0x0308: 0x66e6, 0x0309: 0x66e6, 0x030a: 0x66e6, 0x030b: 0x66e6,
- 0x030c: 0x66e6, 0x030d: 0x00e6, 0x030e: 0x00e6, 0x030f: 0x66e6, 0x0310: 0x00e6, 0x0311: 0x66e6,
- 0x0312: 0x00e6, 0x0313: 0x66e6, 0x0314: 0x66e6, 0x0315: 0x00e8, 0x0316: 0x00dc, 0x0317: 0x00dc,
- 0x0318: 0x00dc, 0x0319: 0x00dc, 0x031a: 0x00e8, 0x031b: 0x66d8, 0x031c: 0x00dc, 0x031d: 0x00dc,
- 0x031e: 0x00dc, 0x031f: 0x00dc, 0x0320: 0x00dc, 0x0321: 0x00ca, 0x0322: 0x00ca, 0x0323: 0x66dc,
- 0x0324: 0x66dc, 0x0325: 0x66dc, 0x0326: 0x66dc, 0x0327: 0x66ca, 0x0328: 0x66ca, 0x0329: 0x00dc,
- 0x032a: 0x00dc, 0x032b: 0x00dc, 0x032c: 0x00dc, 0x032d: 0x66dc, 0x032e: 0x66dc, 0x032f: 0x00dc,
- 0x0330: 0x66dc, 0x0331: 0x66dc, 0x0332: 0x00dc, 0x0333: 0x00dc, 0x0334: 0x0001, 0x0335: 0x0001,
- 0x0336: 0x0001, 0x0337: 0x0001, 0x0338: 0x6601, 0x0339: 0x00dc, 0x033a: 0x00dc, 0x033b: 0x00dc,
- 0x033c: 0x00dc, 0x033d: 0x00e6, 0x033e: 0x00e6, 0x033f: 0x00e6,
+ 0x0301: 0x1100, 0x0303: 0x8800, 0x0304: 0x1100, 0x0305: 0x8800,
+ 0x0307: 0x1100, 0x0308: 0x8800, 0x0309: 0x1100,
+ 0x030d: 0x8800,
+ 0x0320: 0x1100, 0x0321: 0x8800, 0x0322: 0x1100,
+ 0x0324: 0x8800, 0x0325: 0x8800,
+ 0x032d: 0x1100, 0x032e: 0x1100, 0x032f: 0x1100,
+ 0x0330: 0x1100, 0x0331: 0x1100, 0x0332: 0x8800, 0x0333: 0x8800, 0x0334: 0x1100, 0x0335: 0x1100,
+ 0x0336: 0x8800, 0x0337: 0x8800, 0x0338: 0x1100, 0x0339: 0x1100, 0x033a: 0x8800, 0x033b: 0x8800,
+ 0x033c: 0x8800, 0x033d: 0x8800,
// Block 0xd, offset 0x340
- 0x0340: 0x33e6, 0x0341: 0x33e6, 0x0342: 0x66e6, 0x0343: 0x33e6, 0x0344: 0x33e6, 0x0345: 0x66f0,
- 0x0346: 0x00e6, 0x0347: 0x00dc, 0x0348: 0x00dc, 0x0349: 0x00dc, 0x034a: 0x00e6, 0x034b: 0x00e6,
- 0x034c: 0x00e6, 0x034d: 0x00dc, 0x034e: 0x00dc, 0x0350: 0x00e6, 0x0351: 0x00e6,
- 0x0352: 0x00e6, 0x0353: 0x00dc, 0x0354: 0x00dc, 0x0355: 0x00dc, 0x0356: 0x00dc, 0x0357: 0x00e6,
- 0x0358: 0x00e8, 0x0359: 0x00dc, 0x035a: 0x00dc, 0x035b: 0x00e6, 0x035c: 0x00e9, 0x035d: 0x00ea,
- 0x035e: 0x00ea, 0x035f: 0x00e9, 0x0360: 0x00ea, 0x0361: 0x00ea, 0x0362: 0x00e9, 0x0363: 0x00e6,
- 0x0364: 0x00e6, 0x0365: 0x00e6, 0x0366: 0x00e6, 0x0367: 0x00e6, 0x0368: 0x00e6, 0x0369: 0x00e6,
- 0x036a: 0x00e6, 0x036b: 0x00e6, 0x036c: 0x00e6, 0x036d: 0x00e6, 0x036e: 0x00e6, 0x036f: 0x00e6,
- 0x0374: 0x3300,
- 0x037a: 0x3000,
- 0x037e: 0x3300,
+ 0x0346: 0x8800, 0x034b: 0x8800,
+ 0x034c: 0x1100, 0x034d: 0x8800, 0x034e: 0x1100, 0x034f: 0x8800, 0x0350: 0x1100, 0x0351: 0x8800,
+ 0x0352: 0x1100, 0x0353: 0x8800, 0x0354: 0x1100, 0x0355: 0x8800, 0x0356: 0x1100, 0x0357: 0x8800,
+ 0x0358: 0x1100, 0x0359: 0x8800, 0x035a: 0x1100, 0x035b: 0x8800, 0x035c: 0x1100, 0x035d: 0x8800,
+ 0x035e: 0x1100, 0x035f: 0x8800, 0x0360: 0x1100, 0x0361: 0x8800, 0x0362: 0x1100,
+ 0x0364: 0x8800, 0x0365: 0x1100, 0x0366: 0x8800, 0x0367: 0x1100, 0x0368: 0x8800, 0x0369: 0x1100,
+ 0x036f: 0x8800,
+ 0x0370: 0x1100, 0x0371: 0x1100, 0x0372: 0x8800, 0x0373: 0x1100, 0x0374: 0x1100, 0x0375: 0x8800,
+ 0x0376: 0x1100, 0x0377: 0x1100, 0x0378: 0x8800, 0x0379: 0x1100, 0x037a: 0x1100, 0x037b: 0x8800,
+ 0x037c: 0x1100, 0x037d: 0x1100,
// Block 0xe, offset 0x380
- 0x0384: 0x3000, 0x0385: 0x3100,
- 0x0386: 0x1100, 0x0387: 0x3300, 0x0388: 0x1100, 0x0389: 0x1100, 0x038a: 0x1100,
- 0x038c: 0x1100, 0x038e: 0x1100, 0x038f: 0x1100, 0x0390: 0x1100, 0x0391: 0x8800,
- 0x0395: 0x8800, 0x0397: 0x8800,
- 0x0399: 0x8800,
- 0x039f: 0x8800, 0x03a1: 0x8800,
- 0x03a5: 0x8800, 0x03a9: 0x8800,
- 0x03aa: 0x1100, 0x03ab: 0x1100, 0x03ac: 0x9900, 0x03ad: 0x1100, 0x03ae: 0x9900, 0x03af: 0x1100,
- 0x03b0: 0x1100, 0x03b1: 0x8800, 0x03b5: 0x8800,
- 0x03b7: 0x8800, 0x03b9: 0x8800,
- 0x03bf: 0x8800,
+ 0x0394: 0x1100,
+ 0x0399: 0x6608, 0x039a: 0x6608, 0x039b: 0x3000, 0x039c: 0x3000, 0x039d: 0x8800,
+ 0x039e: 0x1100, 0x039f: 0x3000,
+ 0x03a6: 0x8800,
+ 0x03ab: 0x8800, 0x03ac: 0x1100, 0x03ad: 0x8800, 0x03ae: 0x1100, 0x03af: 0x8800,
+ 0x03b0: 0x1100, 0x03b1: 0x8800, 0x03b2: 0x1100, 0x03b3: 0x8800, 0x03b4: 0x1100, 0x03b5: 0x8800,
+ 0x03b6: 0x1100, 0x03b7: 0x8800, 0x03b8: 0x1100, 0x03b9: 0x8800, 0x03ba: 0x1100, 0x03bb: 0x8800,
+ 0x03bc: 0x1100, 0x03bd: 0x8800, 0x03be: 0x1100, 0x03bf: 0x8800,
// Block 0xf, offset 0x3c0
- 0x03c1: 0x8800, 0x03c5: 0x8800,
- 0x03c9: 0x8800, 0x03ca: 0x9900, 0x03cb: 0x9900,
- 0x03cc: 0x1100, 0x03cd: 0x1100, 0x03ce: 0x9900, 0x03d0: 0x3000, 0x03d1: 0x3000,
- 0x03d2: 0x3800, 0x03d3: 0x3100, 0x03d4: 0x3100, 0x03d5: 0x3000, 0x03d6: 0x3000,
- 0x03f0: 0x3000, 0x03f1: 0x3000, 0x03f2: 0x3000, 0x03f4: 0x3000, 0x03f5: 0x3000,
- 0x03f9: 0x3000,
- // Block 0x10, offset 0x400
- 0x0400: 0x1100, 0x0401: 0x1100, 0x0403: 0x1100,
- 0x0406: 0x8800, 0x0407: 0x1100,
- 0x040c: 0x1100, 0x040d: 0x1100, 0x040e: 0x1100, 0x0410: 0x8800,
- 0x0413: 0x8800, 0x0415: 0x8800, 0x0416: 0x8800, 0x0417: 0x8800,
- 0x0418: 0x8800, 0x0419: 0x1100, 0x041a: 0x8800,
- 0x041e: 0x8800, 0x0423: 0x8800,
- 0x0427: 0x8800,
- 0x042b: 0x8800, 0x042d: 0x8800,
- 0x0430: 0x8800, 0x0433: 0x8800, 0x0435: 0x8800,
- 0x0436: 0x8800, 0x0437: 0x8800, 0x0438: 0x8800, 0x0439: 0x1100, 0x043a: 0x8800,
- 0x043e: 0x8800,
- // Block 0x11, offset 0x440
- 0x0443: 0x8800,
- 0x0447: 0x8800, 0x044b: 0x8800,
- 0x044d: 0x8800, 0x0450: 0x1100, 0x0451: 0x1100,
- 0x0453: 0x1100, 0x0456: 0x8800, 0x0457: 0x1100,
- 0x045c: 0x1100, 0x045d: 0x1100,
- 0x045e: 0x1100,
- 0x0474: 0x8800, 0x0475: 0x8800,
- 0x0476: 0x1100, 0x0477: 0x1100,
- // Block 0x12, offset 0x480
- 0x0483: 0x00e6, 0x0484: 0x00e6, 0x0485: 0x00e6,
- 0x0486: 0x00e6, 0x0487: 0x00e6,
- // Block 0x13, offset 0x4c0
- 0x04c1: 0x1100, 0x04c2: 0x1100,
- 0x04d0: 0x1100, 0x04d1: 0x1100,
- 0x04d2: 0x1100, 0x04d3: 0x1100, 0x04d6: 0x1100, 0x04d7: 0x1100,
- 0x04d8: 0x8800, 0x04d9: 0x8800, 0x04da: 0x1100, 0x04db: 0x1100, 0x04dc: 0x1100, 0x04dd: 0x1100,
- 0x04de: 0x1100, 0x04df: 0x1100, 0x04e2: 0x1100, 0x04e3: 0x1100,
- 0x04e4: 0x1100, 0x04e5: 0x1100, 0x04e6: 0x1100, 0x04e7: 0x1100, 0x04e8: 0x8800, 0x04e9: 0x8800,
- 0x04ea: 0x1100, 0x04eb: 0x1100, 0x04ec: 0x1100, 0x04ed: 0x1100, 0x04ee: 0x1100, 0x04ef: 0x1100,
- 0x04f0: 0x1100, 0x04f1: 0x1100, 0x04f2: 0x1100, 0x04f3: 0x1100, 0x04f4: 0x1100, 0x04f5: 0x1100,
- 0x04f8: 0x1100, 0x04f9: 0x1100,
- // Block 0x14, offset 0x500
- 0x0507: 0x3000,
- 0x0511: 0x00dc,
- 0x0512: 0x00e6, 0x0513: 0x00e6, 0x0514: 0x00e6, 0x0515: 0x00e6, 0x0516: 0x00dc, 0x0517: 0x00e6,
- 0x0518: 0x00e6, 0x0519: 0x00e6, 0x051a: 0x00de, 0x051b: 0x00dc, 0x051c: 0x00e6, 0x051d: 0x00e6,
- 0x051e: 0x00e6, 0x051f: 0x00e6, 0x0520: 0x00e6, 0x0521: 0x00e6, 0x0522: 0x00dc, 0x0523: 0x00dc,
- 0x0524: 0x00dc, 0x0525: 0x00dc, 0x0526: 0x00dc, 0x0527: 0x00dc, 0x0528: 0x00e6, 0x0529: 0x00e6,
- 0x052a: 0x00dc, 0x052b: 0x00e6, 0x052c: 0x00e6, 0x052d: 0x00de, 0x052e: 0x00e4, 0x052f: 0x00e6,
- 0x0530: 0x000a, 0x0531: 0x000b, 0x0532: 0x000c, 0x0533: 0x000d, 0x0534: 0x000e, 0x0535: 0x000f,
- 0x0536: 0x0010, 0x0537: 0x0011, 0x0538: 0x0012, 0x0539: 0x0013, 0x053a: 0x0013, 0x053b: 0x0014,
- 0x053c: 0x0015, 0x053d: 0x0016, 0x053f: 0x0017,
- // Block 0x15, offset 0x540
- 0x0541: 0x0018, 0x0542: 0x0019, 0x0544: 0x00e6, 0x0545: 0x00dc,
- 0x0547: 0x0012,
- // Block 0x16, offset 0x580
- 0x0590: 0x00e6, 0x0591: 0x00e6,
- 0x0592: 0x00e6, 0x0593: 0x00e6, 0x0594: 0x00e6, 0x0595: 0x00e6, 0x0596: 0x00e6, 0x0597: 0x00e6,
- 0x0598: 0x001e, 0x0599: 0x001f, 0x059a: 0x0020,
- 0x05a2: 0x1100, 0x05a3: 0x1100,
- 0x05a4: 0x1100, 0x05a5: 0x1100, 0x05a6: 0x1100, 0x05a7: 0x8800,
- // Block 0x17, offset 0x5c0
- 0x05c8: 0x8800, 0x05ca: 0x8800, 0x05cb: 0x001b,
- 0x05cc: 0x001c, 0x05cd: 0x001d, 0x05ce: 0x001e, 0x05cf: 0x001f, 0x05d0: 0x0020, 0x05d1: 0x0021,
- 0x05d2: 0x0022, 0x05d3: 0x66e6, 0x05d4: 0x66e6, 0x05d5: 0x66dc, 0x05d6: 0x00dc, 0x05d7: 0x00e6,
- 0x05d8: 0x00e6, 0x05d9: 0x00e6, 0x05da: 0x00e6, 0x05db: 0x00e6, 0x05dc: 0x00dc, 0x05dd: 0x00e6,
- 0x05de: 0x00e6, 0x05df: 0x00dc,
- 0x05f0: 0x0023, 0x05f5: 0x3000,
- 0x05f6: 0x3000, 0x05f7: 0x3000, 0x05f8: 0x3000,
- // Block 0x18, offset 0x600
- 0x0600: 0x1100, 0x0601: 0x8800, 0x0602: 0x1100,
- 0x0612: 0x8800, 0x0613: 0x1100, 0x0615: 0x8800, 0x0616: 0x00e6, 0x0617: 0x00e6,
- 0x0618: 0x00e6, 0x0619: 0x00e6, 0x061a: 0x00e6, 0x061b: 0x00e6, 0x061c: 0x00e6,
- 0x061f: 0x00e6, 0x0620: 0x00e6, 0x0621: 0x00e6, 0x0622: 0x00e6, 0x0623: 0x00dc,
- 0x0624: 0x00e6, 0x0627: 0x00e6, 0x0628: 0x00e6,
- 0x062a: 0x00dc, 0x062b: 0x00e6, 0x062c: 0x00e6, 0x062d: 0x00dc,
- // Block 0x19, offset 0x640
- 0x0651: 0x0024,
- 0x0670: 0x00e6, 0x0671: 0x00dc, 0x0672: 0x00e6, 0x0673: 0x00e6, 0x0674: 0x00dc, 0x0675: 0x00e6,
- 0x0676: 0x00e6, 0x0677: 0x00dc, 0x0678: 0x00dc, 0x0679: 0x00dc, 0x067a: 0x00e6, 0x067b: 0x00dc,
- 0x067c: 0x00dc, 0x067d: 0x00e6, 0x067e: 0x00dc, 0x067f: 0x00e6,
- // Block 0x1a, offset 0x680
- 0x0680: 0x00e6, 0x0681: 0x00e6, 0x0682: 0x00dc, 0x0683: 0x00e6, 0x0684: 0x00dc, 0x0685: 0x00e6,
- 0x0686: 0x00dc, 0x0687: 0x00e6, 0x0688: 0x00dc, 0x0689: 0x00e6, 0x068a: 0x00e6,
- // Block 0x1b, offset 0x6c0
- 0x06eb: 0x00e6, 0x06ec: 0x00e6, 0x06ed: 0x00e6, 0x06ee: 0x00e6, 0x06ef: 0x00e6,
- 0x06f0: 0x00e6, 0x06f1: 0x00e6, 0x06f2: 0x00dc, 0x06f3: 0x00e6,
- // Block 0x1c, offset 0x700
- 0x0716: 0x00e6, 0x0717: 0x00e6,
- 0x0718: 0x00e6, 0x0719: 0x00e6, 0x071b: 0x00e6, 0x071c: 0x00e6, 0x071d: 0x00e6,
- 0x071e: 0x00e6, 0x071f: 0x00e6, 0x0720: 0x00e6, 0x0721: 0x00e6, 0x0722: 0x00e6, 0x0723: 0x00e6,
- 0x0725: 0x00e6, 0x0726: 0x00e6, 0x0727: 0x00e6, 0x0729: 0x00e6,
- 0x072a: 0x00e6, 0x072b: 0x00e6, 0x072c: 0x00e6, 0x072d: 0x00e6,
- // Block 0x1d, offset 0x740
- 0x0759: 0x00dc, 0x075a: 0x00dc, 0x075b: 0x00dc,
- // Block 0x1e, offset 0x780
- 0x07a8: 0x8800, 0x07a9: 0x1100,
- 0x07b0: 0x8800, 0x07b1: 0x1100, 0x07b3: 0x8800, 0x07b4: 0x1100,
- 0x07bc: 0x6607,
- // Block 0x1f, offset 0x7c0
- 0x07cd: 0x0009, 0x07d1: 0x00e6,
- 0x07d2: 0x00dc, 0x07d3: 0x00e6, 0x07d4: 0x00e6,
- 0x07d8: 0x3300, 0x07d9: 0x3300, 0x07da: 0x3300, 0x07db: 0x3300, 0x07dc: 0x3300, 0x07dd: 0x3300,
- 0x07de: 0x3300, 0x07df: 0x3300,
- // Block 0x20, offset 0x800
- 0x083c: 0x0007, 0x083e: 0x6600,
- // Block 0x21, offset 0x840
- 0x0847: 0x8800, 0x084b: 0x1100,
- 0x084c: 0x1100, 0x084d: 0x0009,
- 0x0857: 0x6600,
- 0x085c: 0x3300, 0x085d: 0x3300,
- 0x085f: 0x3300,
- // Block 0x22, offset 0x880
- 0x08b3: 0x3300,
- 0x08b6: 0x3300,
- 0x08bc: 0x0007,
- // Block 0x23, offset 0x8c0
- 0x08cd: 0x0009,
- 0x08d9: 0x3300, 0x08da: 0x3300, 0x08db: 0x3300,
- 0x08de: 0x3300,
- // Block 0x24, offset 0x900
- 0x093c: 0x0007,
- // Block 0x25, offset 0x940
- 0x094d: 0x0009,
- // Block 0x26, offset 0x980
- 0x0987: 0x8800, 0x0988: 0x1100, 0x098b: 0x1100,
- 0x098c: 0x1100, 0x098d: 0x0009,
- 0x0996: 0x6600, 0x0997: 0x6600,
- 0x099c: 0x3300, 0x099d: 0x3300,
- // Block 0x27, offset 0x9c0
- 0x09d2: 0x8800, 0x09d4: 0x1100,
- 0x09fe: 0x6600,
- // Block 0x28, offset 0xa00
- 0x0a06: 0x8800, 0x0a07: 0x8800, 0x0a0a: 0x1100, 0x0a0b: 0x1100,
- 0x0a0c: 0x1100, 0x0a0d: 0x0009,
- 0x0a17: 0x6600,
- // Block 0x29, offset 0xa40
- 0x0a46: 0x8800, 0x0a48: 0x1100,
- 0x0a4d: 0x0009,
- 0x0a55: 0x0054, 0x0a56: 0x665b,
- // Block 0x2a, offset 0xa80
- 0x0abc: 0x0007, 0x0abf: 0x8800,
- // Block 0x2b, offset 0xac0
- 0x0ac0: 0x1100, 0x0ac2: 0x6600,
- 0x0ac6: 0x8800, 0x0ac7: 0x1100, 0x0ac8: 0x1100, 0x0aca: 0x9900, 0x0acb: 0x1100,
- 0x0acd: 0x0009,
- 0x0ad5: 0x6600, 0x0ad6: 0x6600,
- // Block 0x2c, offset 0xb00
- 0x0b3e: 0x6600,
- // Block 0x2d, offset 0xb40
- 0x0b4a: 0x6609,
- 0x0b4f: 0x6600,
- 0x0b59: 0x8800, 0x0b5a: 0x1100, 0x0b5c: 0x9900, 0x0b5d: 0x1100,
- 0x0b5e: 0x1100, 0x0b5f: 0x6600,
- // Block 0x2e, offset 0xb80
- 0x0bb3: 0x3000,
- 0x0bb8: 0x0067, 0x0bb9: 0x0067, 0x0bba: 0x0009,
- // Block 0x2f, offset 0xbc0
- 0x0bc8: 0x006b, 0x0bc9: 0x006b, 0x0bca: 0x006b, 0x0bcb: 0x006b,
- // Block 0x30, offset 0xc00
- 0x0c33: 0x3000,
- 0x0c38: 0x0076, 0x0c39: 0x0076,
- // Block 0x31, offset 0xc40
- 0x0c48: 0x007a, 0x0c49: 0x007a, 0x0c4a: 0x007a, 0x0c4b: 0x007a,
- 0x0c5c: 0x3000, 0x0c5d: 0x3000,
- // Block 0x32, offset 0xc80
- 0x0c8c: 0x3000,
- 0x0c98: 0x00dc, 0x0c99: 0x00dc,
- 0x0cb5: 0x00dc,
- 0x0cb7: 0x00dc, 0x0cb9: 0x00d8,
- // Block 0x33, offset 0xcc0
- 0x0cc3: 0x3300,
- 0x0ccd: 0x3300,
- 0x0cd2: 0x3300, 0x0cd7: 0x3300,
- 0x0cdc: 0x3300,
- 0x0ce9: 0x3300,
- 0x0cf1: 0x0081, 0x0cf2: 0x0082, 0x0cf3: 0x3300, 0x0cf4: 0x0084, 0x0cf5: 0x3300,
- 0x0cf6: 0x3300, 0x0cf7: 0x3000, 0x0cf8: 0x3300, 0x0cf9: 0x3000, 0x0cfa: 0x0082, 0x0cfb: 0x0082,
- 0x0cfc: 0x0082, 0x0cfd: 0x0082,
- // Block 0x34, offset 0xd00
- 0x0d00: 0x0082, 0x0d01: 0x3300, 0x0d02: 0x00e6, 0x0d03: 0x00e6, 0x0d04: 0x0009,
- 0x0d06: 0x00e6, 0x0d07: 0x00e6,
- 0x0d13: 0x3300,
- 0x0d1d: 0x3300,
- 0x0d22: 0x3300,
- 0x0d27: 0x3300,
- 0x0d2c: 0x3300,
- 0x0d39: 0x3300,
- // Block 0x35, offset 0xd40
- 0x0d46: 0x00dc,
- // Block 0x36, offset 0xd80
- 0x0da5: 0x8800, 0x0da6: 0x1100,
- 0x0dae: 0x6600,
- 0x0db7: 0x0007, 0x0db9: 0x0009, 0x0dba: 0x0009,
- // Block 0x37, offset 0xdc0
- 0x0dcd: 0x00dc,
- // Block 0x38, offset 0xe00
- 0x0e3c: 0x3000,
- // Block 0x39, offset 0xe40
- 0x0e61: 0x6600, 0x0e62: 0x6600, 0x0e63: 0x6600,
- 0x0e64: 0x6600, 0x0e65: 0x6600, 0x0e66: 0x6600, 0x0e67: 0x6600, 0x0e68: 0x6600, 0x0e69: 0x6600,
- 0x0e6a: 0x6600, 0x0e6b: 0x6600, 0x0e6c: 0x6600, 0x0e6d: 0x6600, 0x0e6e: 0x6600, 0x0e6f: 0x6600,
- 0x0e70: 0x6600, 0x0e71: 0x6600, 0x0e72: 0x6600, 0x0e73: 0x6600, 0x0e74: 0x6600, 0x0e75: 0x6600,
- // Block 0x3a, offset 0xe80
- 0x0ea8: 0x6600, 0x0ea9: 0x6600,
- 0x0eaa: 0x6600, 0x0eab: 0x6600, 0x0eac: 0x6600, 0x0ead: 0x6600, 0x0eae: 0x6600, 0x0eaf: 0x6600,
- 0x0eb0: 0x6600, 0x0eb1: 0x6600, 0x0eb2: 0x6600, 0x0eb3: 0x6600, 0x0eb4: 0x6600, 0x0eb5: 0x6600,
- 0x0eb6: 0x6600, 0x0eb7: 0x6600, 0x0eb8: 0x6600, 0x0eb9: 0x6600, 0x0eba: 0x6600, 0x0ebb: 0x6600,
- 0x0ebc: 0x6600, 0x0ebd: 0x6600, 0x0ebe: 0x6600, 0x0ebf: 0x6600,
- // Block 0x3b, offset 0xec0
- 0x0ec0: 0x6600, 0x0ec1: 0x6600, 0x0ec2: 0x6600,
- // Block 0x3c, offset 0xf00
- 0x0f1d: 0x00e6,
- 0x0f1e: 0x00e6, 0x0f1f: 0x00e6,
- // Block 0x3d, offset 0xf40
- 0x0f54: 0x0009,
- 0x0f74: 0x0009,
- // Block 0x3e, offset 0xf80
- 0x0f92: 0x0009,
- 0x0f9d: 0x00e6,
- // Block 0x3f, offset 0xfc0
- 0x0fe9: 0x00e4,
- // Block 0x40, offset 0x1000
- 0x1039: 0x00de, 0x103a: 0x00e6, 0x103b: 0x00dc,
- // Block 0x41, offset 0x1040
- 0x1057: 0x00e6,
- 0x1058: 0x00dc,
- // Block 0x42, offset 0x1080
- 0x10a0: 0x0009,
- 0x10b5: 0x00e6,
- 0x10b6: 0x00e6, 0x10b7: 0x00e6, 0x10b8: 0x00e6, 0x10b9: 0x00e6, 0x10ba: 0x00e6, 0x10bb: 0x00e6,
- 0x10bc: 0x00e6, 0x10bf: 0x00dc,
- // Block 0x43, offset 0x10c0
- 0x10c5: 0x8800,
- 0x10c6: 0x1100, 0x10c7: 0x8800, 0x10c8: 0x1100, 0x10c9: 0x8800, 0x10ca: 0x1100, 0x10cb: 0x8800,
- 0x10cc: 0x1100, 0x10cd: 0x8800, 0x10ce: 0x1100, 0x10d1: 0x8800,
- 0x10d2: 0x1100,
- 0x10f4: 0x0007, 0x10f5: 0x6600,
- 0x10fa: 0x8800, 0x10fb: 0x1100,
- 0x10fc: 0x8800, 0x10fd: 0x1100, 0x10fe: 0x8800, 0x10ff: 0x8800,
- // Block 0x44, offset 0x1100
- 0x1100: 0x1100, 0x1101: 0x1100, 0x1102: 0x8800, 0x1103: 0x1100, 0x1104: 0x0009,
- 0x112b: 0x00e6, 0x112c: 0x00dc, 0x112d: 0x00e6, 0x112e: 0x00e6, 0x112f: 0x00e6,
- 0x1130: 0x00e6, 0x1131: 0x00e6, 0x1132: 0x00e6, 0x1133: 0x00e6,
- // Block 0x45, offset 0x1140
- 0x116a: 0x0009,
- // Block 0x46, offset 0x1180
- 0x11a6: 0x0007,
- 0x11b2: 0x0009, 0x11b3: 0x0009,
- // Block 0x47, offset 0x11c0
- 0x11f7: 0x0007,
- // Block 0x48, offset 0x1200
- 0x1210: 0x00e6, 0x1211: 0x00e6,
- 0x1212: 0x00e6, 0x1214: 0x0001, 0x1215: 0x00dc, 0x1216: 0x00dc, 0x1217: 0x00dc,
- 0x1218: 0x00dc, 0x1219: 0x00dc, 0x121a: 0x00e6, 0x121b: 0x00e6, 0x121c: 0x00dc, 0x121d: 0x00dc,
- 0x121e: 0x00dc, 0x121f: 0x00dc, 0x1220: 0x00e6, 0x1222: 0x0001, 0x1223: 0x0001,
- 0x1224: 0x0001, 0x1225: 0x0001, 0x1226: 0x0001, 0x1227: 0x0001, 0x1228: 0x0001,
- 0x122d: 0x00dc,
- // Block 0x49, offset 0x1240
- 0x126c: 0x3000, 0x126d: 0x3000, 0x126e: 0x3000,
- 0x1270: 0x3000, 0x1271: 0x3000, 0x1272: 0x3000, 0x1273: 0x3000, 0x1274: 0x3000, 0x1275: 0x3000,
- 0x1276: 0x3000, 0x1277: 0x3000, 0x1278: 0x3000, 0x1279: 0x3000, 0x127a: 0x3000,
- 0x127c: 0x3000, 0x127d: 0x3000, 0x127e: 0x3000, 0x127f: 0x3000,
- // Block 0x4a, offset 0x1280
- 0x1280: 0x3000, 0x1281: 0x3000, 0x1282: 0x3000, 0x1283: 0x3000, 0x1284: 0x3000, 0x1285: 0x3000,
- 0x1286: 0x3000, 0x1287: 0x3000, 0x1288: 0x3000, 0x1289: 0x3000, 0x128a: 0x3000, 0x128b: 0x3000,
- 0x128c: 0x3000, 0x128d: 0x3000, 0x128f: 0x3000, 0x1290: 0x3000, 0x1291: 0x3000,
- 0x1292: 0x3000, 0x1293: 0x3000, 0x1294: 0x3000, 0x1295: 0x3000, 0x1296: 0x3000, 0x1297: 0x3000,
- 0x1298: 0x3000, 0x1299: 0x3000, 0x129a: 0x3000, 0x129b: 0x3000, 0x129c: 0x3000, 0x129d: 0x3000,
- 0x129e: 0x3000, 0x129f: 0x3000, 0x12a0: 0x3000, 0x12a1: 0x3000, 0x12a2: 0x3000, 0x12a3: 0x3000,
- 0x12a4: 0x3000, 0x12a5: 0x3000, 0x12a6: 0x3000, 0x12a7: 0x3000, 0x12a8: 0x3000, 0x12a9: 0x3000,
- 0x12aa: 0x3000,
- 0x12b8: 0x3000,
- // Block 0x4b, offset 0x12c0
- 0x12db: 0x3000, 0x12dc: 0x3000, 0x12dd: 0x3000,
- 0x12de: 0x3000, 0x12df: 0x3000, 0x12e0: 0x3000, 0x12e1: 0x3000, 0x12e2: 0x3000, 0x12e3: 0x3000,
- 0x12e4: 0x3000, 0x12e5: 0x3000, 0x12e6: 0x3000, 0x12e7: 0x3000, 0x12e8: 0x3000, 0x12e9: 0x3000,
- 0x12ea: 0x3000, 0x12eb: 0x3000, 0x12ec: 0x3000, 0x12ed: 0x3000, 0x12ee: 0x3000, 0x12ef: 0x3000,
- 0x12f0: 0x3000, 0x12f1: 0x3000, 0x12f2: 0x3000, 0x12f3: 0x3000, 0x12f4: 0x3000, 0x12f5: 0x3000,
- 0x12f6: 0x3000, 0x12f7: 0x3000, 0x12f8: 0x3000, 0x12f9: 0x3000, 0x12fa: 0x3000, 0x12fb: 0x3000,
- 0x12fc: 0x3000, 0x12fd: 0x3000, 0x12fe: 0x3000, 0x12ff: 0x3000,
- // Block 0x4c, offset 0x1300
- 0x1300: 0x00e6, 0x1301: 0x00e6, 0x1302: 0x00dc, 0x1303: 0x00e6, 0x1304: 0x00e6, 0x1305: 0x00e6,
- 0x1306: 0x00e6, 0x1307: 0x00e6, 0x1308: 0x00e6, 0x1309: 0x00e6, 0x130a: 0x00dc, 0x130b: 0x00e6,
- 0x130c: 0x00e6, 0x130d: 0x00ea, 0x130e: 0x00d6, 0x130f: 0x00dc, 0x1310: 0x00ca, 0x1311: 0x00e6,
- 0x1312: 0x00e6, 0x1313: 0x00e6, 0x1314: 0x00e6, 0x1315: 0x00e6, 0x1316: 0x00e6, 0x1317: 0x00e6,
- 0x1318: 0x00e6, 0x1319: 0x00e6, 0x131a: 0x00e6, 0x131b: 0x00e6, 0x131c: 0x00e6, 0x131d: 0x00e6,
- 0x131e: 0x00e6, 0x131f: 0x00e6, 0x1320: 0x00e6, 0x1321: 0x00e6, 0x1322: 0x00e6, 0x1323: 0x00e6,
- 0x1324: 0x00e6, 0x1325: 0x00e6, 0x1326: 0x00e6,
- 0x133c: 0x00e9, 0x133d: 0x00dc, 0x133e: 0x00e6, 0x133f: 0x00dc,
- // Block 0x4d, offset 0x1340
- 0x1340: 0x1100, 0x1341: 0x1100, 0x1342: 0x1100, 0x1343: 0x1100, 0x1344: 0x1100, 0x1345: 0x1100,
- 0x1346: 0x1100, 0x1347: 0x1100, 0x1348: 0x1100, 0x1349: 0x1100, 0x134a: 0x1100, 0x134b: 0x1100,
- 0x134c: 0x1100, 0x134d: 0x1100, 0x134e: 0x1100, 0x134f: 0x1100, 0x1350: 0x1100, 0x1351: 0x1100,
- 0x1352: 0x1100, 0x1353: 0x1100, 0x1354: 0x1100, 0x1355: 0x1100, 0x1356: 0x1100, 0x1357: 0x1100,
- 0x1358: 0x1100, 0x1359: 0x1100, 0x135a: 0x1100, 0x135b: 0x1100, 0x135c: 0x1100, 0x135d: 0x1100,
- 0x135e: 0x1100, 0x135f: 0x1100, 0x1360: 0x1100, 0x1361: 0x1100, 0x1362: 0x1100, 0x1363: 0x1100,
- 0x1364: 0x1100, 0x1365: 0x1100, 0x1366: 0x1100, 0x1367: 0x1100, 0x1368: 0x1100, 0x1369: 0x1100,
- 0x136a: 0x1100, 0x136b: 0x1100, 0x136c: 0x1100, 0x136d: 0x1100, 0x136e: 0x1100, 0x136f: 0x1100,
- 0x1370: 0x1100, 0x1371: 0x1100, 0x1372: 0x1100, 0x1373: 0x1100, 0x1374: 0x1100, 0x1375: 0x1100,
- 0x1376: 0x9900, 0x1377: 0x9900, 0x1378: 0x1100, 0x1379: 0x1100, 0x137a: 0x1100, 0x137b: 0x1100,
- 0x137c: 0x1100, 0x137d: 0x1100, 0x137e: 0x1100, 0x137f: 0x1100,
- // Block 0x4e, offset 0x1380
- 0x1380: 0x1100, 0x1381: 0x1100, 0x1382: 0x1100, 0x1383: 0x1100, 0x1384: 0x1100, 0x1385: 0x1100,
- 0x1386: 0x1100, 0x1387: 0x1100, 0x1388: 0x1100, 0x1389: 0x1100, 0x138a: 0x1100, 0x138b: 0x1100,
- 0x138c: 0x1100, 0x138d: 0x1100, 0x138e: 0x1100, 0x138f: 0x1100, 0x1390: 0x1100, 0x1391: 0x1100,
- 0x1392: 0x1100, 0x1393: 0x1100, 0x1394: 0x1100, 0x1395: 0x1100, 0x1396: 0x1100, 0x1397: 0x1100,
- 0x1398: 0x1100, 0x1399: 0x1100, 0x139a: 0x9900, 0x139b: 0x9900, 0x139c: 0x1100, 0x139d: 0x1100,
- 0x139e: 0x1100, 0x139f: 0x1100, 0x13a0: 0x1100, 0x13a1: 0x1100, 0x13a2: 0x9900, 0x13a3: 0x9900,
- 0x13a4: 0x1100, 0x13a5: 0x1100, 0x13a6: 0x1100, 0x13a7: 0x1100, 0x13a8: 0x1100, 0x13a9: 0x1100,
- 0x13aa: 0x1100, 0x13ab: 0x1100, 0x13ac: 0x1100, 0x13ad: 0x1100, 0x13ae: 0x1100, 0x13af: 0x1100,
- 0x13b0: 0x1100, 0x13b1: 0x1100, 0x13b2: 0x1100, 0x13b3: 0x1100, 0x13b4: 0x1100, 0x13b5: 0x1100,
- 0x13b6: 0x1100, 0x13b7: 0x1100, 0x13b8: 0x1100, 0x13b9: 0x1100, 0x13ba: 0x1100, 0x13bb: 0x1100,
- 0x13bc: 0x1100, 0x13bd: 0x1100, 0x13be: 0x1100, 0x13bf: 0x1100,
- // Block 0x4f, offset 0x13c0
- 0x13c0: 0x1100, 0x13c1: 0x1100, 0x13c2: 0x1100, 0x13c3: 0x1100, 0x13c4: 0x1100, 0x13c5: 0x1100,
- 0x13c6: 0x1100, 0x13c7: 0x1100, 0x13c8: 0x1100, 0x13c9: 0x1100, 0x13ca: 0x1100, 0x13cb: 0x1100,
- 0x13cc: 0x1100, 0x13cd: 0x1100, 0x13ce: 0x1100, 0x13cf: 0x1100, 0x13d0: 0x1100, 0x13d1: 0x1100,
- 0x13d2: 0x1100, 0x13d3: 0x1100, 0x13d4: 0x1100, 0x13d5: 0x1100, 0x13d6: 0x1100, 0x13d7: 0x1100,
- 0x13d8: 0x1100, 0x13d9: 0x1100, 0x13da: 0x3000, 0x13db: 0x3100,
- 0x13e0: 0x9900, 0x13e1: 0x9900, 0x13e2: 0x1100, 0x13e3: 0x1100,
- 0x13e4: 0x1100, 0x13e5: 0x1100, 0x13e6: 0x1100, 0x13e7: 0x1100, 0x13e8: 0x1100, 0x13e9: 0x1100,
- 0x13ea: 0x1100, 0x13eb: 0x1100, 0x13ec: 0x1100, 0x13ed: 0x1100, 0x13ee: 0x1100, 0x13ef: 0x1100,
- 0x13f0: 0x1100, 0x13f1: 0x1100, 0x13f2: 0x1100, 0x13f3: 0x1100, 0x13f4: 0x1100, 0x13f5: 0x1100,
- 0x13f6: 0x1100, 0x13f7: 0x1100, 0x13f8: 0x9900, 0x13f9: 0x9900, 0x13fa: 0x1100, 0x13fb: 0x1100,
- 0x13fc: 0x1100, 0x13fd: 0x1100, 0x13fe: 0x1100, 0x13ff: 0x1100,
- // Block 0x50, offset 0x1400
- 0x1400: 0x1100, 0x1401: 0x1100, 0x1402: 0x1100, 0x1403: 0x1100, 0x1404: 0x1100, 0x1405: 0x1100,
- 0x1406: 0x1100, 0x1407: 0x1100, 0x1408: 0x1100, 0x1409: 0x1100, 0x140a: 0x1100, 0x140b: 0x1100,
- 0x140c: 0x9900, 0x140d: 0x9900, 0x140e: 0x1100, 0x140f: 0x1100, 0x1410: 0x1100, 0x1411: 0x1100,
- 0x1412: 0x1100, 0x1413: 0x1100, 0x1414: 0x1100, 0x1415: 0x1100, 0x1416: 0x1100, 0x1417: 0x1100,
- 0x1418: 0x1100, 0x1419: 0x1100, 0x141a: 0x1100, 0x141b: 0x1100, 0x141c: 0x1100, 0x141d: 0x1100,
- 0x141e: 0x1100, 0x141f: 0x1100, 0x1420: 0x1100, 0x1421: 0x1100, 0x1422: 0x1100, 0x1423: 0x1100,
- 0x1424: 0x1100, 0x1425: 0x1100, 0x1426: 0x1100, 0x1427: 0x1100, 0x1428: 0x1100, 0x1429: 0x1100,
- 0x142a: 0x1100, 0x142b: 0x1100, 0x142c: 0x1100, 0x142d: 0x1100, 0x142e: 0x1100, 0x142f: 0x1100,
- 0x1430: 0x1100, 0x1431: 0x1100, 0x1432: 0x1100, 0x1433: 0x1100, 0x1434: 0x1100, 0x1435: 0x1100,
- 0x1436: 0x1100, 0x1437: 0x1100, 0x1438: 0x1100, 0x1439: 0x1100,
- // Block 0x51, offset 0x1440
- 0x1440: 0x9900, 0x1441: 0x9900, 0x1442: 0x9900, 0x1443: 0x9900, 0x1444: 0x9900, 0x1445: 0x9900,
- 0x1446: 0x9900, 0x1447: 0x9900, 0x1448: 0x9900, 0x1449: 0x9900, 0x144a: 0x9900, 0x144b: 0x9900,
- 0x144c: 0x9900, 0x144d: 0x9900, 0x144e: 0x9900, 0x144f: 0x9900, 0x1450: 0x9900, 0x1451: 0x9900,
- 0x1452: 0x1100, 0x1453: 0x1100, 0x1454: 0x1100, 0x1455: 0x1100,
- 0x1458: 0x9900, 0x1459: 0x9900, 0x145a: 0x1100, 0x145b: 0x1100, 0x145c: 0x1100, 0x145d: 0x1100,
- 0x1460: 0x9900, 0x1461: 0x9900, 0x1462: 0x9900, 0x1463: 0x9900,
- 0x1464: 0x9900, 0x1465: 0x9900, 0x1466: 0x9900, 0x1467: 0x9900, 0x1468: 0x9900, 0x1469: 0x9900,
- 0x146a: 0x9900, 0x146b: 0x9900, 0x146c: 0x9900, 0x146d: 0x9900, 0x146e: 0x9900, 0x146f: 0x9900,
- 0x1470: 0x9900, 0x1471: 0x9900, 0x1472: 0x1100, 0x1473: 0x1100, 0x1474: 0x1100, 0x1475: 0x1100,
- 0x1476: 0x1100, 0x1477: 0x1100, 0x1478: 0x9900, 0x1479: 0x9900, 0x147a: 0x1100, 0x147b: 0x1100,
- 0x147c: 0x1100, 0x147d: 0x1100, 0x147e: 0x1100, 0x147f: 0x1100,
- // Block 0x52, offset 0x1480
- 0x1480: 0x9900, 0x1481: 0x9900, 0x1482: 0x1100, 0x1483: 0x1100, 0x1484: 0x1100, 0x1485: 0x1100,
- 0x1488: 0x9900, 0x1489: 0x9900, 0x148a: 0x1100, 0x148b: 0x1100,
- 0x148c: 0x1100, 0x148d: 0x1100, 0x1490: 0x9900, 0x1491: 0x9900,
- 0x1492: 0x1100, 0x1493: 0x1100, 0x1494: 0x1100, 0x1495: 0x1100, 0x1496: 0x1100, 0x1497: 0x1100,
- 0x1499: 0x9900, 0x149b: 0x1100, 0x149d: 0x1100,
- 0x149f: 0x1100, 0x14a0: 0x9900, 0x14a1: 0x9900, 0x14a2: 0x9900, 0x14a3: 0x9900,
- 0x14a4: 0x9900, 0x14a5: 0x9900, 0x14a6: 0x9900, 0x14a7: 0x9900, 0x14a8: 0x9900, 0x14a9: 0x9900,
- 0x14aa: 0x9900, 0x14ab: 0x9900, 0x14ac: 0x9900, 0x14ad: 0x9900, 0x14ae: 0x9900, 0x14af: 0x9900,
- 0x14b0: 0x9900, 0x14b1: 0x3300, 0x14b2: 0x1100, 0x14b3: 0x3300, 0x14b4: 0x9900, 0x14b5: 0x3300,
- 0x14b6: 0x1100, 0x14b7: 0x3300, 0x14b8: 0x1100, 0x14b9: 0x3300, 0x14ba: 0x1100, 0x14bb: 0x3300,
- 0x14bc: 0x9900, 0x14bd: 0x3300,
- // Block 0x53, offset 0x14c0
- 0x14c0: 0x1100, 0x14c1: 0x1100, 0x14c2: 0x1100, 0x14c3: 0x1100, 0x14c4: 0x1100, 0x14c5: 0x1100,
- 0x14c6: 0x1100, 0x14c7: 0x1100, 0x14c8: 0x1100, 0x14c9: 0x1100, 0x14ca: 0x1100, 0x14cb: 0x1100,
- 0x14cc: 0x1100, 0x14cd: 0x1100, 0x14ce: 0x1100, 0x14cf: 0x1100, 0x14d0: 0x1100, 0x14d1: 0x1100,
- 0x14d2: 0x1100, 0x14d3: 0x1100, 0x14d4: 0x1100, 0x14d5: 0x1100, 0x14d6: 0x1100, 0x14d7: 0x1100,
- 0x14d8: 0x1100, 0x14d9: 0x1100, 0x14da: 0x1100, 0x14db: 0x1100, 0x14dc: 0x1100, 0x14dd: 0x1100,
- 0x14de: 0x1100, 0x14df: 0x1100, 0x14e0: 0x1100, 0x14e1: 0x1100, 0x14e2: 0x1100, 0x14e3: 0x1100,
- 0x14e4: 0x1100, 0x14e5: 0x1100, 0x14e6: 0x1100, 0x14e7: 0x1100, 0x14e8: 0x1100, 0x14e9: 0x1100,
- 0x14ea: 0x1100, 0x14eb: 0x1100, 0x14ec: 0x1100, 0x14ed: 0x1100, 0x14ee: 0x1100, 0x14ef: 0x1100,
- 0x14f0: 0x1100, 0x14f1: 0x1100, 0x14f2: 0x1100, 0x14f3: 0x1100, 0x14f4: 0x1100,
- 0x14f6: 0x9900, 0x14f7: 0x1100, 0x14f8: 0x1100, 0x14f9: 0x1100, 0x14fa: 0x1100, 0x14fb: 0x3300,
- 0x14fc: 0x1100, 0x14fd: 0x3000, 0x14fe: 0x3300, 0x14ff: 0x3800,
- // Block 0x54, offset 0x1500
- 0x1500: 0x3000, 0x1501: 0x3100, 0x1502: 0x1100, 0x1503: 0x1100, 0x1504: 0x1100,
- 0x1506: 0x9900, 0x1507: 0x1100, 0x1508: 0x1100, 0x1509: 0x3300, 0x150a: 0x1100, 0x150b: 0x3300,
- 0x150c: 0x1100, 0x150d: 0x3100, 0x150e: 0x3100, 0x150f: 0x3100, 0x1510: 0x1100, 0x1511: 0x1100,
- 0x1512: 0x1100, 0x1513: 0x3300, 0x1516: 0x1100, 0x1517: 0x1100,
- 0x1518: 0x1100, 0x1519: 0x1100, 0x151a: 0x1100, 0x151b: 0x3300, 0x151d: 0x3100,
- 0x151e: 0x3100, 0x151f: 0x3100, 0x1520: 0x1100, 0x1521: 0x1100, 0x1522: 0x1100, 0x1523: 0x3300,
- 0x1524: 0x1100, 0x1525: 0x1100, 0x1526: 0x1100, 0x1527: 0x1100, 0x1528: 0x1100, 0x1529: 0x1100,
- 0x152a: 0x1100, 0x152b: 0x3300, 0x152c: 0x1100, 0x152d: 0x3100, 0x152e: 0x3300, 0x152f: 0x3300,
- 0x1532: 0x1100, 0x1533: 0x1100, 0x1534: 0x1100,
- 0x1536: 0x9900, 0x1537: 0x1100, 0x1538: 0x1100, 0x1539: 0x3300, 0x153a: 0x1100, 0x153b: 0x3300,
- 0x153c: 0x1100, 0x153d: 0x3300, 0x153e: 0x3800,
- // Block 0x55, offset 0x1540
- 0x1540: 0x3300, 0x1541: 0x3300, 0x1542: 0x3000, 0x1543: 0x3000, 0x1544: 0x3000, 0x1545: 0x3000,
- 0x1546: 0x3000, 0x1547: 0x3000, 0x1548: 0x3000, 0x1549: 0x3000, 0x154a: 0x3000,
- 0x1551: 0x3000,
- 0x1557: 0x3000,
- 0x1564: 0x3000, 0x1565: 0x3000, 0x1566: 0x3000,
- 0x156f: 0x3000,
- 0x1573: 0x3000, 0x1574: 0x3000,
- 0x1576: 0x3000, 0x1577: 0x3000,
- 0x157c: 0x3000, 0x157e: 0x3000,
- // Block 0x56, offset 0x1580
- 0x1587: 0x3000, 0x1588: 0x3000, 0x1589: 0x3000,
- 0x1597: 0x3000,
- 0x159f: 0x3000,
- 0x15b0: 0x3000, 0x15b1: 0x3000, 0x15b4: 0x3000, 0x15b5: 0x3000,
- 0x15b6: 0x3000, 0x15b7: 0x3000, 0x15b8: 0x3000, 0x15b9: 0x3000, 0x15ba: 0x3000, 0x15bb: 0x3000,
- 0x15bc: 0x3000, 0x15bd: 0x3000, 0x15be: 0x3000, 0x15bf: 0x3000,
- // Block 0x57, offset 0x15c0
- 0x15c0: 0x3000, 0x15c1: 0x3000, 0x15c2: 0x3000, 0x15c3: 0x3000, 0x15c4: 0x3000, 0x15c5: 0x3000,
- 0x15c6: 0x3000, 0x15c7: 0x3000, 0x15c8: 0x3000, 0x15c9: 0x3000, 0x15ca: 0x3000, 0x15cb: 0x3000,
- 0x15cc: 0x3000, 0x15cd: 0x3000, 0x15ce: 0x3000, 0x15d0: 0x3000, 0x15d1: 0x3000,
- 0x15d2: 0x3000, 0x15d3: 0x3000, 0x15d4: 0x3000, 0x15d5: 0x3000, 0x15d6: 0x3000, 0x15d7: 0x3000,
- 0x15d8: 0x3000, 0x15d9: 0x3000, 0x15da: 0x3000, 0x15db: 0x3000, 0x15dc: 0x3000,
- 0x15e8: 0x3000,
- // Block 0x58, offset 0x1600
- 0x1610: 0x00e6, 0x1611: 0x00e6,
- 0x1612: 0x0001, 0x1613: 0x0001, 0x1614: 0x00e6, 0x1615: 0x00e6, 0x1616: 0x00e6, 0x1617: 0x00e6,
- 0x1618: 0x0001, 0x1619: 0x0001, 0x161a: 0x0001, 0x161b: 0x00e6, 0x161c: 0x00e6,
- 0x1621: 0x00e6,
- 0x1625: 0x0001, 0x1626: 0x0001, 0x1627: 0x00e6, 0x1628: 0x00dc, 0x1629: 0x00e6,
- 0x162a: 0x0001, 0x162b: 0x0001, 0x162c: 0x00dc, 0x162d: 0x00dc, 0x162e: 0x00dc, 0x162f: 0x00dc,
- 0x1630: 0x00e6,
- // Block 0x59, offset 0x1640
- 0x1640: 0x3000, 0x1641: 0x3000, 0x1642: 0x3000, 0x1643: 0x3000, 0x1645: 0x3000,
- 0x1646: 0x3000, 0x1647: 0x3000, 0x1649: 0x3000, 0x164a: 0x3000, 0x164b: 0x3000,
- 0x164c: 0x3000, 0x164d: 0x3000, 0x164e: 0x3000, 0x164f: 0x3000, 0x1650: 0x3000, 0x1651: 0x3000,
- 0x1652: 0x3000, 0x1653: 0x3000, 0x1655: 0x3000, 0x1656: 0x3000,
- 0x1659: 0x3000, 0x165a: 0x3000, 0x165b: 0x3000, 0x165c: 0x3000, 0x165d: 0x3000,
- 0x1660: 0x3000, 0x1661: 0x3000, 0x1662: 0x3000,
- 0x1664: 0x3000, 0x1666: 0x3300, 0x1668: 0x3000,
- 0x166a: 0x3300, 0x166b: 0x3300, 0x166c: 0x3000, 0x166d: 0x3000, 0x166f: 0x3000,
- 0x1670: 0x3000, 0x1671: 0x3000, 0x1673: 0x3000, 0x1674: 0x3000, 0x1675: 0x3000,
- 0x1676: 0x3000, 0x1677: 0x3000, 0x1678: 0x3000, 0x1679: 0x3000, 0x167b: 0x3000,
- 0x167c: 0x3000, 0x167d: 0x3000, 0x167e: 0x3000, 0x167f: 0x3000,
- // Block 0x5a, offset 0x1680
- 0x1680: 0x3000, 0x1685: 0x3000,
- 0x1686: 0x3000, 0x1687: 0x3000, 0x1688: 0x3000, 0x1689: 0x3000,
- 0x1690: 0x3000, 0x1691: 0x3000,
- 0x1692: 0x3000, 0x1693: 0x3000, 0x1694: 0x3000, 0x1695: 0x3000, 0x1696: 0x3000, 0x1697: 0x3000,
- 0x1698: 0x3000, 0x1699: 0x3000, 0x169a: 0x3000, 0x169b: 0x3000, 0x169c: 0x3000, 0x169d: 0x3000,
- 0x169e: 0x3000, 0x169f: 0x3000, 0x16a0: 0x3000, 0x16a1: 0x3000, 0x16a2: 0x3000, 0x16a3: 0x3000,
- 0x16a4: 0x3000, 0x16a5: 0x3000, 0x16a6: 0x3000, 0x16a7: 0x3000, 0x16a8: 0x3000, 0x16a9: 0x3000,
- 0x16aa: 0x3000, 0x16ab: 0x3000, 0x16ac: 0x3000, 0x16ad: 0x3000, 0x16ae: 0x3000, 0x16af: 0x3000,
- 0x16b0: 0x3000, 0x16b1: 0x3000, 0x16b2: 0x3000, 0x16b3: 0x3000, 0x16b4: 0x3000, 0x16b5: 0x3000,
- 0x16b6: 0x3000, 0x16b7: 0x3000, 0x16b8: 0x3000, 0x16b9: 0x3000, 0x16ba: 0x3000, 0x16bb: 0x3000,
- 0x16bc: 0x3000, 0x16bd: 0x3000, 0x16be: 0x3000, 0x16bf: 0x3000,
- // Block 0x5b, offset 0x16c0
- 0x16c9: 0x3000,
- 0x16d0: 0x8800,
- 0x16d2: 0x8800, 0x16d4: 0x8800,
- 0x16da: 0x1100, 0x16db: 0x1100,
- 0x16ee: 0x1100,
- // Block 0x5c, offset 0x1700
- 0x170d: 0x1100, 0x170e: 0x1100, 0x170f: 0x1100, 0x1710: 0x8800,
- 0x1712: 0x8800, 0x1714: 0x8800,
- // Block 0x5d, offset 0x1740
- 0x1743: 0x8800, 0x1744: 0x1100,
- 0x1748: 0x8800, 0x1749: 0x1100, 0x174b: 0x8800,
- 0x174c: 0x1100,
- 0x1763: 0x8800,
- 0x1764: 0x1100, 0x1765: 0x8800, 0x1766: 0x1100,
- 0x176c: 0x3000, 0x176d: 0x3000, 0x176f: 0x3000,
- 0x1770: 0x3000,
- 0x177c: 0x8800,
- // Block 0x5e, offset 0x1780
- 0x1781: 0x1100, 0x1783: 0x8800, 0x1784: 0x1100, 0x1785: 0x8800,
- 0x1787: 0x1100, 0x1788: 0x8800, 0x1789: 0x1100,
- 0x178d: 0x8800,
- 0x17a0: 0x1100, 0x17a1: 0x8800, 0x17a2: 0x1100,
- 0x17a4: 0x8800, 0x17a5: 0x8800,
- 0x17ad: 0x1100, 0x17ae: 0x1100, 0x17af: 0x1100,
- 0x17b0: 0x1100, 0x17b1: 0x1100, 0x17b2: 0x8800, 0x17b3: 0x8800, 0x17b4: 0x1100, 0x17b5: 0x1100,
- 0x17b6: 0x8800, 0x17b7: 0x8800, 0x17b8: 0x1100, 0x17b9: 0x1100, 0x17ba: 0x8800, 0x17bb: 0x8800,
- 0x17bc: 0x8800, 0x17bd: 0x8800,
- // Block 0x5f, offset 0x17c0
- 0x17c0: 0x1100, 0x17c1: 0x1100, 0x17c2: 0x8800, 0x17c3: 0x8800, 0x17c4: 0x1100, 0x17c5: 0x1100,
- 0x17c6: 0x8800, 0x17c7: 0x8800, 0x17c8: 0x1100, 0x17c9: 0x1100,
- 0x17d1: 0x8800,
- 0x17d2: 0x8800,
- 0x17e2: 0x8800,
- 0x17e8: 0x8800, 0x17e9: 0x8800,
- 0x17eb: 0x8800, 0x17ec: 0x1100, 0x17ed: 0x1100, 0x17ee: 0x1100, 0x17ef: 0x1100,
- 0x17f2: 0x8800, 0x17f3: 0x8800, 0x17f4: 0x8800, 0x17f5: 0x8800,
- // Block 0x60, offset 0x1800
- 0x1820: 0x1100, 0x1821: 0x1100, 0x1822: 0x1100, 0x1823: 0x1100,
- 0x182a: 0x1100, 0x182b: 0x1100, 0x182c: 0x1100, 0x182d: 0x1100,
- // Block 0x61, offset 0x1840
- 0x1869: 0x3300,
- 0x186a: 0x3300,
- // Block 0x62, offset 0x1880
- 0x18a0: 0x3000, 0x18a1: 0x3000, 0x18a2: 0x3000, 0x18a3: 0x3000,
- 0x18a4: 0x3000, 0x18a5: 0x3000, 0x18a6: 0x3000, 0x18a7: 0x3000, 0x18a8: 0x3000, 0x18a9: 0x3000,
- 0x18aa: 0x3000, 0x18ab: 0x3000, 0x18ac: 0x3000, 0x18ad: 0x3000, 0x18ae: 0x3000, 0x18af: 0x3000,
- 0x18b0: 0x3000, 0x18b1: 0x3000, 0x18b2: 0x3000, 0x18b3: 0x3000, 0x18b4: 0x3000, 0x18b5: 0x3000,
- 0x18b6: 0x3000, 0x18b7: 0x3000, 0x18b8: 0x3000, 0x18b9: 0x3000, 0x18ba: 0x3000, 0x18bb: 0x3000,
- 0x18bc: 0x3000, 0x18bd: 0x3000, 0x18be: 0x3000, 0x18bf: 0x3000,
- // Block 0x63, offset 0x18c0
- 0x18c0: 0x3000, 0x18c1: 0x3000, 0x18c2: 0x3000, 0x18c3: 0x3000, 0x18c4: 0x3000, 0x18c5: 0x3000,
- 0x18c6: 0x3000, 0x18c7: 0x3000, 0x18c8: 0x3000, 0x18c9: 0x3000, 0x18ca: 0x3000, 0x18cb: 0x3000,
- 0x18cc: 0x3000, 0x18cd: 0x3000, 0x18ce: 0x3000, 0x18cf: 0x3000, 0x18d0: 0x3000, 0x18d1: 0x3000,
- 0x18d2: 0x3000, 0x18d3: 0x3000, 0x18d4: 0x3000, 0x18d5: 0x3000, 0x18d6: 0x3000, 0x18d7: 0x3000,
- 0x18d8: 0x3000, 0x18d9: 0x3000, 0x18da: 0x3000, 0x18db: 0x3000, 0x18dc: 0x3000, 0x18dd: 0x3000,
- 0x18de: 0x3000, 0x18df: 0x3000, 0x18e0: 0x3000, 0x18e1: 0x3000, 0x18e2: 0x3000, 0x18e3: 0x3000,
- 0x18e4: 0x3000, 0x18e5: 0x3000, 0x18e6: 0x3000, 0x18e7: 0x3000, 0x18e8: 0x3000, 0x18e9: 0x3000,
- 0x18ea: 0x3000, 0x18eb: 0x3000, 0x18ec: 0x3000, 0x18ed: 0x3000, 0x18ee: 0x3000, 0x18ef: 0x3000,
- 0x18f0: 0x3000, 0x18f1: 0x3000, 0x18f2: 0x3000, 0x18f3: 0x3000, 0x18f4: 0x3000, 0x18f5: 0x3000,
- 0x18f6: 0x3000, 0x18f7: 0x3000, 0x18f8: 0x3000, 0x18f9: 0x3000, 0x18fa: 0x3000, 0x18fb: 0x3000,
- 0x18fc: 0x3000, 0x18fd: 0x3000, 0x18fe: 0x3000, 0x18ff: 0x3000,
- // Block 0x64, offset 0x1900
- 0x1900: 0x3000, 0x1901: 0x3000, 0x1902: 0x3000, 0x1903: 0x3000, 0x1904: 0x3000, 0x1905: 0x3000,
- 0x1906: 0x3000, 0x1907: 0x3000, 0x1908: 0x3000, 0x1909: 0x3000, 0x190a: 0x3000, 0x190b: 0x3000,
- 0x190c: 0x3000, 0x190d: 0x3000, 0x190e: 0x3000, 0x190f: 0x3000, 0x1910: 0x3000, 0x1911: 0x3000,
- 0x1912: 0x3000, 0x1913: 0x3000, 0x1914: 0x3000, 0x1915: 0x3000, 0x1916: 0x3000, 0x1917: 0x3000,
- 0x1918: 0x3000, 0x1919: 0x3000, 0x191a: 0x3000, 0x191b: 0x3000, 0x191c: 0x3000, 0x191d: 0x3000,
- 0x191e: 0x3000, 0x191f: 0x3000, 0x1920: 0x3000, 0x1921: 0x3000, 0x1922: 0x3000, 0x1923: 0x3000,
- 0x1924: 0x3000, 0x1925: 0x3000, 0x1926: 0x3000, 0x1927: 0x3000, 0x1928: 0x3000, 0x1929: 0x3000,
- 0x192a: 0x3000,
- // Block 0x65, offset 0x1940
- 0x194c: 0x3000,
- // Block 0x66, offset 0x1980
- 0x19b4: 0x3000, 0x19b5: 0x3000,
- 0x19b6: 0x3000,
- // Block 0x67, offset 0x19c0
- 0x19dc: 0x3300,
- // Block 0x68, offset 0x1a00
- 0x1a3c: 0x3000, 0x1a3d: 0x3000,
- // Block 0x69, offset 0x1a40
- 0x1a6f: 0x00e6,
- 0x1a70: 0x00e6, 0x1a71: 0x00e6,
- // Block 0x6a, offset 0x1a80
- 0x1aaf: 0x3000,
- 0x1abf: 0x0009,
- // Block 0x6b, offset 0x1ac0
- 0x1ae0: 0x00e6, 0x1ae1: 0x00e6, 0x1ae2: 0x00e6, 0x1ae3: 0x00e6,
- 0x1ae4: 0x00e6, 0x1ae5: 0x00e6, 0x1ae6: 0x00e6, 0x1ae7: 0x00e6, 0x1ae8: 0x00e6, 0x1ae9: 0x00e6,
- 0x1aea: 0x00e6, 0x1aeb: 0x00e6, 0x1aec: 0x00e6, 0x1aed: 0x00e6, 0x1aee: 0x00e6, 0x1aef: 0x00e6,
- 0x1af0: 0x00e6, 0x1af1: 0x00e6, 0x1af2: 0x00e6, 0x1af3: 0x00e6, 0x1af4: 0x00e6, 0x1af5: 0x00e6,
- 0x1af6: 0x00e6, 0x1af7: 0x00e6, 0x1af8: 0x00e6, 0x1af9: 0x00e6, 0x1afa: 0x00e6, 0x1afb: 0x00e6,
- 0x1afc: 0x00e6, 0x1afd: 0x00e6, 0x1afe: 0x00e6, 0x1aff: 0x00e6,
- // Block 0x6c, offset 0x1b00
- 0x1b1f: 0x3000,
- // Block 0x6d, offset 0x1b40
- 0x1b73: 0x3000,
- // Block 0x6e, offset 0x1b80
- 0x1b80: 0x3000, 0x1b81: 0x3000, 0x1b82: 0x3000, 0x1b83: 0x3000, 0x1b84: 0x3000, 0x1b85: 0x3000,
- 0x1b86: 0x3000, 0x1b87: 0x3000, 0x1b88: 0x3000, 0x1b89: 0x3000, 0x1b8a: 0x3000, 0x1b8b: 0x3000,
- 0x1b8c: 0x3000, 0x1b8d: 0x3000, 0x1b8e: 0x3000, 0x1b8f: 0x3000, 0x1b90: 0x3000, 0x1b91: 0x3000,
- 0x1b92: 0x3000, 0x1b93: 0x3000, 0x1b94: 0x3000, 0x1b95: 0x3000,
- // Block 0x6f, offset 0x1bc0
- 0x1bc0: 0x3000,
- 0x1bea: 0x00da, 0x1beb: 0x00e4, 0x1bec: 0x00e8, 0x1bed: 0x00de, 0x1bee: 0x00e0, 0x1bef: 0x00e0,
- 0x1bf6: 0x3000, 0x1bf8: 0x3000, 0x1bf9: 0x3000, 0x1bfa: 0x3000,
- // Block 0x70, offset 0x1c00
- 0x1c06: 0x8800, 0x1c0b: 0x8800,
- 0x1c0c: 0x1100, 0x1c0d: 0x8800, 0x1c0e: 0x1100, 0x1c0f: 0x8800, 0x1c10: 0x1100, 0x1c11: 0x8800,
- 0x1c12: 0x1100, 0x1c13: 0x8800, 0x1c14: 0x1100, 0x1c15: 0x8800, 0x1c16: 0x1100, 0x1c17: 0x8800,
- 0x1c18: 0x1100, 0x1c19: 0x8800, 0x1c1a: 0x1100, 0x1c1b: 0x8800, 0x1c1c: 0x1100, 0x1c1d: 0x8800,
- 0x1c1e: 0x1100, 0x1c1f: 0x8800, 0x1c20: 0x1100, 0x1c21: 0x8800, 0x1c22: 0x1100,
- 0x1c24: 0x8800, 0x1c25: 0x1100, 0x1c26: 0x8800, 0x1c27: 0x1100, 0x1c28: 0x8800, 0x1c29: 0x1100,
- 0x1c2f: 0x8800,
- 0x1c30: 0x1100, 0x1c31: 0x1100, 0x1c32: 0x8800, 0x1c33: 0x1100, 0x1c34: 0x1100, 0x1c35: 0x8800,
- 0x1c36: 0x1100, 0x1c37: 0x1100, 0x1c38: 0x8800, 0x1c39: 0x1100, 0x1c3a: 0x1100, 0x1c3b: 0x8800,
- 0x1c3c: 0x1100, 0x1c3d: 0x1100,
- // Block 0x71, offset 0x1c40
- 0x1c54: 0x1100,
- 0x1c59: 0x6608, 0x1c5a: 0x6608, 0x1c5b: 0x3000, 0x1c5c: 0x3000, 0x1c5d: 0x8800,
- 0x1c5e: 0x1100, 0x1c5f: 0x3000,
- 0x1c66: 0x8800,
- 0x1c6b: 0x8800, 0x1c6c: 0x1100, 0x1c6d: 0x8800, 0x1c6e: 0x1100, 0x1c6f: 0x8800,
- 0x1c70: 0x1100, 0x1c71: 0x8800, 0x1c72: 0x1100, 0x1c73: 0x8800, 0x1c74: 0x1100, 0x1c75: 0x8800,
- 0x1c76: 0x1100, 0x1c77: 0x8800, 0x1c78: 0x1100, 0x1c79: 0x8800, 0x1c7a: 0x1100, 0x1c7b: 0x8800,
- 0x1c7c: 0x1100, 0x1c7d: 0x8800, 0x1c7e: 0x1100, 0x1c7f: 0x8800,
- // Block 0x72, offset 0x1c80
- 0x1c80: 0x1100, 0x1c81: 0x8800, 0x1c82: 0x1100, 0x1c84: 0x8800, 0x1c85: 0x1100,
- 0x1c86: 0x8800, 0x1c87: 0x1100, 0x1c88: 0x8800, 0x1c89: 0x1100,
- 0x1c8f: 0x8800, 0x1c90: 0x1100, 0x1c91: 0x1100,
- 0x1c92: 0x8800, 0x1c93: 0x1100, 0x1c94: 0x1100, 0x1c95: 0x8800, 0x1c96: 0x1100, 0x1c97: 0x1100,
- 0x1c98: 0x8800, 0x1c99: 0x1100, 0x1c9a: 0x1100, 0x1c9b: 0x8800, 0x1c9c: 0x1100, 0x1c9d: 0x1100,
- 0x1caf: 0x8800,
- 0x1cb0: 0x8800, 0x1cb1: 0x8800, 0x1cb2: 0x8800, 0x1cb4: 0x1100,
- 0x1cb7: 0x1100, 0x1cb8: 0x1100, 0x1cb9: 0x1100, 0x1cba: 0x1100,
- 0x1cbd: 0x8800, 0x1cbe: 0x1100, 0x1cbf: 0x3000,
- // Block 0x73, offset 0x1cc0
- 0x1cf1: 0x3000, 0x1cf2: 0x3000, 0x1cf3: 0x3000, 0x1cf4: 0x3000, 0x1cf5: 0x3000,
- 0x1cf6: 0x3000, 0x1cf7: 0x3000, 0x1cf8: 0x3000, 0x1cf9: 0x3000, 0x1cfa: 0x3000, 0x1cfb: 0x3000,
- 0x1cfc: 0x3000, 0x1cfd: 0x3000, 0x1cfe: 0x3000, 0x1cff: 0x3000,
- // Block 0x74, offset 0x1d00
- 0x1d00: 0x3000, 0x1d01: 0x3000, 0x1d02: 0x3000, 0x1d03: 0x3000, 0x1d04: 0x3000, 0x1d05: 0x3000,
- 0x1d06: 0x3000, 0x1d07: 0x3000, 0x1d08: 0x3000, 0x1d09: 0x3000, 0x1d0a: 0x3000, 0x1d0b: 0x3000,
- 0x1d0c: 0x3000, 0x1d0d: 0x3000, 0x1d0e: 0x3000,
- 0x1d12: 0x3000, 0x1d13: 0x3000, 0x1d14: 0x3000, 0x1d15: 0x3000, 0x1d16: 0x3000, 0x1d17: 0x3000,
- 0x1d18: 0x3000, 0x1d19: 0x3000, 0x1d1a: 0x3000, 0x1d1b: 0x3000, 0x1d1c: 0x3000, 0x1d1d: 0x3000,
- 0x1d1e: 0x3000, 0x1d1f: 0x3000,
- // Block 0x75, offset 0x1d40
- 0x1d40: 0x3000, 0x1d41: 0x3000, 0x1d42: 0x3000, 0x1d43: 0x3000, 0x1d44: 0x3000, 0x1d45: 0x3000,
- 0x1d46: 0x3000, 0x1d47: 0x3000, 0x1d48: 0x3000, 0x1d49: 0x3000, 0x1d4a: 0x3000, 0x1d4b: 0x3000,
- 0x1d4c: 0x3000, 0x1d4d: 0x3000, 0x1d4e: 0x3000, 0x1d4f: 0x3000, 0x1d50: 0x3000, 0x1d51: 0x3000,
- 0x1d52: 0x3000, 0x1d53: 0x3000, 0x1d54: 0x3000, 0x1d55: 0x3000, 0x1d56: 0x3000, 0x1d57: 0x3000,
- 0x1d58: 0x3000, 0x1d59: 0x3000, 0x1d5a: 0x3000, 0x1d5b: 0x3000, 0x1d5c: 0x3000, 0x1d5d: 0x3000,
- 0x1d5e: 0x3000, 0x1d60: 0x3000, 0x1d61: 0x3000, 0x1d62: 0x3000, 0x1d63: 0x3000,
- 0x1d64: 0x3000, 0x1d65: 0x3000, 0x1d66: 0x3000, 0x1d67: 0x3000, 0x1d68: 0x3000, 0x1d69: 0x3000,
- 0x1d6a: 0x3000, 0x1d6b: 0x3000, 0x1d6c: 0x3000, 0x1d6d: 0x3000, 0x1d6e: 0x3000, 0x1d6f: 0x3000,
- 0x1d70: 0x3000, 0x1d71: 0x3000, 0x1d72: 0x3000, 0x1d73: 0x3000, 0x1d74: 0x3000, 0x1d75: 0x3000,
- 0x1d76: 0x3000, 0x1d77: 0x3000, 0x1d78: 0x3000, 0x1d79: 0x3000, 0x1d7a: 0x3000, 0x1d7b: 0x3000,
- 0x1d7c: 0x3000, 0x1d7d: 0x3000, 0x1d7e: 0x3000, 0x1d7f: 0x3000,
- // Block 0x76, offset 0x1d80
- 0x1d80: 0x3000, 0x1d81: 0x3000, 0x1d82: 0x3000, 0x1d83: 0x3000, 0x1d84: 0x3000, 0x1d85: 0x3000,
- 0x1d86: 0x3000, 0x1d87: 0x3000,
- 0x1d90: 0x3000, 0x1d91: 0x3000,
- 0x1d92: 0x3000, 0x1d93: 0x3000, 0x1d94: 0x3000, 0x1d95: 0x3000, 0x1d96: 0x3000, 0x1d97: 0x3000,
- 0x1d98: 0x3000, 0x1d99: 0x3000, 0x1d9a: 0x3000, 0x1d9b: 0x3000, 0x1d9c: 0x3000, 0x1d9d: 0x3000,
- 0x1d9e: 0x3000, 0x1d9f: 0x3000, 0x1da0: 0x3000, 0x1da1: 0x3000, 0x1da2: 0x3000, 0x1da3: 0x3000,
- 0x1da4: 0x3000, 0x1da5: 0x3000, 0x1da6: 0x3000, 0x1da7: 0x3000, 0x1da8: 0x3000, 0x1da9: 0x3000,
- 0x1daa: 0x3000, 0x1dab: 0x3000, 0x1dac: 0x3000, 0x1dad: 0x3000, 0x1dae: 0x3000, 0x1daf: 0x3000,
- 0x1db0: 0x3000, 0x1db1: 0x3000, 0x1db2: 0x3000, 0x1db3: 0x3000, 0x1db4: 0x3000, 0x1db5: 0x3000,
- 0x1db6: 0x3000, 0x1db7: 0x3000, 0x1db8: 0x3000, 0x1db9: 0x3000, 0x1dba: 0x3000, 0x1dbb: 0x3000,
- 0x1dbc: 0x3000, 0x1dbd: 0x3000, 0x1dbe: 0x3000,
- // Block 0x77, offset 0x1dc0
- 0x1dc0: 0x3000, 0x1dc1: 0x3000, 0x1dc2: 0x3000, 0x1dc3: 0x3000, 0x1dc4: 0x3000, 0x1dc5: 0x3000,
- 0x1dc6: 0x3000, 0x1dc7: 0x3000, 0x1dc8: 0x3000, 0x1dc9: 0x3000, 0x1dca: 0x3000, 0x1dcb: 0x3000,
- 0x1dcc: 0x3000, 0x1dcd: 0x3000, 0x1dce: 0x3000, 0x1dcf: 0x3000, 0x1dd0: 0x3000, 0x1dd1: 0x3000,
- 0x1dd2: 0x3000, 0x1dd3: 0x3000, 0x1dd4: 0x3000, 0x1dd5: 0x3000, 0x1dd6: 0x3000, 0x1dd7: 0x3000,
- 0x1dd8: 0x3000, 0x1dd9: 0x3000, 0x1dda: 0x3000, 0x1ddb: 0x3000, 0x1ddc: 0x3000, 0x1ddd: 0x3000,
- 0x1dde: 0x3000, 0x1ddf: 0x3000, 0x1de0: 0x3000, 0x1de1: 0x3000, 0x1de2: 0x3000, 0x1de3: 0x3000,
- 0x1de4: 0x3000, 0x1de5: 0x3000, 0x1de6: 0x3000, 0x1de7: 0x3000, 0x1de8: 0x3000, 0x1de9: 0x3000,
- 0x1dea: 0x3000, 0x1deb: 0x3000, 0x1dec: 0x3000, 0x1ded: 0x3000, 0x1dee: 0x3000, 0x1def: 0x3000,
- 0x1df0: 0x3000, 0x1df1: 0x3000, 0x1df2: 0x3000, 0x1df3: 0x3000, 0x1df4: 0x3000, 0x1df5: 0x3000,
- 0x1df6: 0x3000, 0x1df7: 0x3000, 0x1df8: 0x3000, 0x1df9: 0x3000, 0x1dfa: 0x3000, 0x1dfb: 0x3000,
- 0x1dfc: 0x3000, 0x1dfd: 0x3000, 0x1dfe: 0x3000,
- // Block 0x78, offset 0x1e00
- 0x1e2f: 0x00e6,
- 0x1e3c: 0x00e6, 0x1e3d: 0x00e6,
- // Block 0x79, offset 0x1e40
- 0x1e70: 0x00e6, 0x1e71: 0x00e6,
- // Block 0x7a, offset 0x1e80
- 0x1eb0: 0x3000,
- // Block 0x7b, offset 0x1ec0
- 0x1ec6: 0x0009,
- // Block 0x7c, offset 0x1f00
- 0x1f04: 0x0009,
- 0x1f20: 0x00e6, 0x1f21: 0x00e6, 0x1f22: 0x00e6, 0x1f23: 0x00e6,
- 0x1f24: 0x00e6, 0x1f25: 0x00e6, 0x1f26: 0x00e6, 0x1f27: 0x00e6, 0x1f28: 0x00e6, 0x1f29: 0x00e6,
- 0x1f2a: 0x00e6, 0x1f2b: 0x00e6, 0x1f2c: 0x00e6, 0x1f2d: 0x00e6, 0x1f2e: 0x00e6, 0x1f2f: 0x00e6,
- 0x1f30: 0x00e6, 0x1f31: 0x00e6,
- // Block 0x7d, offset 0x1f40
- 0x1f6b: 0x00dc, 0x1f6c: 0x00dc, 0x1f6d: 0x00dc,
- // Block 0x7e, offset 0x1f80
- 0x1f93: 0x0009,
- // Block 0x7f, offset 0x1fc0
- 0x1ff3: 0x0007,
- // Block 0x80, offset 0x2000
- 0x2000: 0x0009,
- // Block 0x81, offset 0x2040
- 0x2070: 0x00e6, 0x2072: 0x00e6, 0x2073: 0x00e6, 0x2074: 0x00dc,
- 0x2077: 0x00e6, 0x2078: 0x00e6,
- 0x207e: 0x00e6, 0x207f: 0x00e6,
- // Block 0x82, offset 0x2080
- 0x2081: 0x00e6,
- // Block 0x83, offset 0x20c0
- 0x20ed: 0x0009,
- // Block 0x84, offset 0x2100
- 0x2100: 0x1100, 0x2101: 0x1100, 0x2102: 0x1100, 0x2103: 0x1100, 0x2104: 0x1100, 0x2105: 0x1100,
- 0x2106: 0x1100, 0x2107: 0x1100, 0x2108: 0x1100, 0x2109: 0x1100, 0x210a: 0x1100, 0x210b: 0x1100,
- 0x210c: 0x1100, 0x210d: 0x1100, 0x210e: 0x1100, 0x210f: 0x1100, 0x2110: 0x1100, 0x2111: 0x1100,
- 0x2112: 0x1100, 0x2113: 0x1100, 0x2114: 0x1100, 0x2115: 0x1100, 0x2116: 0x1100, 0x2117: 0x1100,
- 0x2118: 0x1100, 0x2119: 0x1100, 0x211a: 0x1100, 0x211b: 0x1100, 0x211c: 0x1100, 0x211d: 0x1100,
- 0x211e: 0x1100, 0x211f: 0x1100, 0x2120: 0x1100, 0x2121: 0x1100, 0x2122: 0x1100, 0x2123: 0x1100,
- 0x2124: 0x1100, 0x2125: 0x1100, 0x2126: 0x1100, 0x2127: 0x1100, 0x2128: 0x1100, 0x2129: 0x1100,
- 0x212a: 0x1100, 0x212b: 0x1100, 0x212c: 0x1100, 0x212d: 0x1100, 0x212e: 0x1100, 0x212f: 0x1100,
- 0x2130: 0x1100, 0x2131: 0x1100, 0x2132: 0x1100, 0x2133: 0x1100, 0x2134: 0x1100, 0x2135: 0x1100,
- 0x2136: 0x1100, 0x2137: 0x1100, 0x2138: 0x1100, 0x2139: 0x1100, 0x213a: 0x1100, 0x213b: 0x1100,
- 0x213c: 0x1100, 0x213d: 0x1100, 0x213e: 0x1100, 0x213f: 0x1100,
- // Block 0x85, offset 0x2140
- 0x2140: 0x1100, 0x2141: 0x1100, 0x2142: 0x1100, 0x2143: 0x1100, 0x2144: 0x1100, 0x2145: 0x1100,
- 0x2146: 0x1100, 0x2147: 0x1100, 0x2148: 0x1100, 0x2149: 0x1100, 0x214a: 0x1100, 0x214b: 0x1100,
- 0x214c: 0x1100, 0x214d: 0x1100, 0x214e: 0x1100, 0x214f: 0x1100, 0x2150: 0x1100, 0x2151: 0x1100,
- 0x2152: 0x1100, 0x2153: 0x1100, 0x2154: 0x1100, 0x2155: 0x1100, 0x2156: 0x1100, 0x2157: 0x1100,
- 0x2158: 0x1100, 0x2159: 0x1100, 0x215a: 0x1100, 0x215b: 0x1100, 0x215c: 0x1100, 0x215d: 0x1100,
- 0x215e: 0x1100, 0x215f: 0x1100, 0x2160: 0x1100, 0x2161: 0x1100, 0x2162: 0x1100, 0x2163: 0x1100,
- // Block 0x86, offset 0x2180
- 0x2180: 0x3300, 0x2181: 0x3300, 0x2182: 0x3300, 0x2183: 0x3300, 0x2184: 0x3300, 0x2185: 0x3300,
- 0x2186: 0x3300, 0x2187: 0x3300, 0x2188: 0x3300, 0x2189: 0x3300, 0x218a: 0x3300, 0x218b: 0x3300,
- 0x218c: 0x3300, 0x218d: 0x3300, 0x218e: 0x3300, 0x218f: 0x3300, 0x2190: 0x3300, 0x2191: 0x3300,
- 0x2192: 0x3300, 0x2193: 0x3300, 0x2194: 0x3300, 0x2195: 0x3300, 0x2196: 0x3300, 0x2197: 0x3300,
- 0x2198: 0x3300, 0x2199: 0x3300, 0x219a: 0x3300, 0x219b: 0x3300, 0x219c: 0x3300, 0x219d: 0x3300,
- 0x219e: 0x3300, 0x219f: 0x3300, 0x21a0: 0x3300, 0x21a1: 0x3300, 0x21a2: 0x3300, 0x21a3: 0x3300,
- 0x21a4: 0x3300, 0x21a5: 0x3300, 0x21a6: 0x3300, 0x21a7: 0x3300, 0x21a8: 0x3300, 0x21a9: 0x3300,
- 0x21aa: 0x3300, 0x21ab: 0x3300, 0x21ac: 0x3300, 0x21ad: 0x3300, 0x21ae: 0x3300, 0x21af: 0x3300,
- 0x21b0: 0x3300, 0x21b1: 0x3300, 0x21b2: 0x3300, 0x21b3: 0x3300, 0x21b4: 0x3300, 0x21b5: 0x3300,
- 0x21b6: 0x3300, 0x21b7: 0x3300, 0x21b8: 0x3300, 0x21b9: 0x3300, 0x21ba: 0x3300, 0x21bb: 0x3300,
- 0x21bc: 0x3300, 0x21bd: 0x3300, 0x21be: 0x3300, 0x21bf: 0x3300,
- // Block 0x87, offset 0x21c0
- 0x21c0: 0x3300, 0x21c1: 0x3300, 0x21c2: 0x3300, 0x21c3: 0x3300, 0x21c4: 0x3300, 0x21c5: 0x3300,
- 0x21c6: 0x3300, 0x21c7: 0x3300, 0x21c8: 0x3300, 0x21c9: 0x3300, 0x21ca: 0x3300, 0x21cb: 0x3300,
- 0x21cc: 0x3300, 0x21cd: 0x3300, 0x21d0: 0x3300,
- 0x21d2: 0x3300, 0x21d5: 0x3300, 0x21d6: 0x3300, 0x21d7: 0x3300,
- 0x21d8: 0x3300, 0x21d9: 0x3300, 0x21da: 0x3300, 0x21db: 0x3300, 0x21dc: 0x3300, 0x21dd: 0x3300,
- 0x21de: 0x3300, 0x21e0: 0x3300, 0x21e2: 0x3300,
- 0x21e5: 0x3300, 0x21e6: 0x3300,
- 0x21ea: 0x3300, 0x21eb: 0x3300, 0x21ec: 0x3300, 0x21ed: 0x3300,
- 0x21f0: 0x3300, 0x21f1: 0x3300, 0x21f2: 0x3300, 0x21f3: 0x3300, 0x21f4: 0x3300, 0x21f5: 0x3300,
- 0x21f6: 0x3300, 0x21f7: 0x3300, 0x21f8: 0x3300, 0x21f9: 0x3300, 0x21fa: 0x3300, 0x21fb: 0x3300,
- 0x21fc: 0x3300, 0x21fd: 0x3300, 0x21fe: 0x3300, 0x21ff: 0x3300,
- // Block 0x88, offset 0x2200
- 0x2200: 0x3300, 0x2201: 0x3300, 0x2202: 0x3300, 0x2203: 0x3300, 0x2204: 0x3300, 0x2205: 0x3300,
- 0x2206: 0x3300, 0x2207: 0x3300, 0x2208: 0x3300, 0x2209: 0x3300, 0x220a: 0x3300, 0x220b: 0x3300,
- 0x220c: 0x3300, 0x220d: 0x3300, 0x220e: 0x3300, 0x220f: 0x3300, 0x2210: 0x3300, 0x2211: 0x3300,
- 0x2212: 0x3300, 0x2213: 0x3300, 0x2214: 0x3300, 0x2215: 0x3300, 0x2216: 0x3300, 0x2217: 0x3300,
- 0x2218: 0x3300, 0x2219: 0x3300, 0x221a: 0x3300, 0x221b: 0x3300, 0x221c: 0x3300, 0x221d: 0x3300,
- 0x221e: 0x3300, 0x221f: 0x3300, 0x2220: 0x3300, 0x2221: 0x3300, 0x2222: 0x3300, 0x2223: 0x3300,
- 0x2224: 0x3300, 0x2225: 0x3300, 0x2226: 0x3300, 0x2227: 0x3300, 0x2228: 0x3300, 0x2229: 0x3300,
- 0x222a: 0x3300, 0x222b: 0x3300, 0x222c: 0x3300, 0x222d: 0x3300,
- 0x2230: 0x3300, 0x2231: 0x3300, 0x2232: 0x3300, 0x2233: 0x3300, 0x2234: 0x3300, 0x2235: 0x3300,
- 0x2236: 0x3300, 0x2237: 0x3300, 0x2238: 0x3300, 0x2239: 0x3300, 0x223a: 0x3300, 0x223b: 0x3300,
- 0x223c: 0x3300, 0x223d: 0x3300, 0x223e: 0x3300, 0x223f: 0x3300,
- // Block 0x89, offset 0x2240
- 0x2240: 0x3300, 0x2241: 0x3300, 0x2242: 0x3300, 0x2243: 0x3300, 0x2244: 0x3300, 0x2245: 0x3300,
- 0x2246: 0x3300, 0x2247: 0x3300, 0x2248: 0x3300, 0x2249: 0x3300, 0x224a: 0x3300, 0x224b: 0x3300,
- 0x224c: 0x3300, 0x224d: 0x3300, 0x224e: 0x3300, 0x224f: 0x3300, 0x2250: 0x3300, 0x2251: 0x3300,
- 0x2252: 0x3300, 0x2253: 0x3300, 0x2254: 0x3300, 0x2255: 0x3300, 0x2256: 0x3300, 0x2257: 0x3300,
- 0x2258: 0x3300, 0x2259: 0x3300,
- // Block 0x8a, offset 0x2280
- 0x2280: 0x3000, 0x2281: 0x3000, 0x2282: 0x3000, 0x2283: 0x3000, 0x2284: 0x3000, 0x2285: 0x3000,
- 0x2286: 0x3000,
- 0x2293: 0x3000, 0x2294: 0x3000, 0x2295: 0x3000, 0x2296: 0x3000, 0x2297: 0x3000,
- 0x229d: 0x3300,
- 0x229e: 0x001a, 0x229f: 0x3300, 0x22a0: 0x3000, 0x22a1: 0x3000, 0x22a2: 0x3000, 0x22a3: 0x3000,
- 0x22a4: 0x3000, 0x22a5: 0x3000, 0x22a6: 0x3000, 0x22a7: 0x3000, 0x22a8: 0x3000, 0x22a9: 0x3000,
- 0x22aa: 0x3300, 0x22ab: 0x3300, 0x22ac: 0x3300, 0x22ad: 0x3300, 0x22ae: 0x3300, 0x22af: 0x3300,
- 0x22b0: 0x3300, 0x22b1: 0x3300, 0x22b2: 0x3300, 0x22b3: 0x3300, 0x22b4: 0x3300, 0x22b5: 0x3300,
- 0x22b6: 0x3300, 0x22b8: 0x3300, 0x22b9: 0x3300, 0x22ba: 0x3300, 0x22bb: 0x3300,
- 0x22bc: 0x3300, 0x22be: 0x3300,
- // Block 0x8b, offset 0x22c0
- 0x22c0: 0x3300, 0x22c1: 0x3300, 0x22c3: 0x3300, 0x22c4: 0x3300,
- 0x22c6: 0x3300, 0x22c7: 0x3300, 0x22c8: 0x3300, 0x22c9: 0x3300, 0x22ca: 0x3300, 0x22cb: 0x3300,
- 0x22cc: 0x3300, 0x22cd: 0x3300, 0x22ce: 0x3300, 0x22cf: 0x3000, 0x22d0: 0x3000, 0x22d1: 0x3000,
- 0x22d2: 0x3000, 0x22d3: 0x3000, 0x22d4: 0x3000, 0x22d5: 0x3000, 0x22d6: 0x3000, 0x22d7: 0x3000,
- 0x22d8: 0x3000, 0x22d9: 0x3000, 0x22da: 0x3000, 0x22db: 0x3000, 0x22dc: 0x3000, 0x22dd: 0x3000,
- 0x22de: 0x3000, 0x22df: 0x3000, 0x22e0: 0x3000, 0x22e1: 0x3000, 0x22e2: 0x3000, 0x22e3: 0x3000,
- 0x22e4: 0x3000, 0x22e5: 0x3000, 0x22e6: 0x3000, 0x22e7: 0x3000, 0x22e8: 0x3000, 0x22e9: 0x3000,
- 0x22ea: 0x3000, 0x22eb: 0x3000, 0x22ec: 0x3000, 0x22ed: 0x3000, 0x22ee: 0x3000, 0x22ef: 0x3000,
- 0x22f0: 0x3000, 0x22f1: 0x3000, 0x22f2: 0x3000, 0x22f3: 0x3000, 0x22f4: 0x3000, 0x22f5: 0x3000,
- 0x22f6: 0x3000, 0x22f7: 0x3000, 0x22f8: 0x3000, 0x22f9: 0x3000, 0x22fa: 0x3000, 0x22fb: 0x3000,
- 0x22fc: 0x3000, 0x22fd: 0x3000, 0x22fe: 0x3000, 0x22ff: 0x3000,
- // Block 0x8c, offset 0x2300
- 0x2300: 0x3000, 0x2301: 0x3000, 0x2302: 0x3000, 0x2303: 0x3000, 0x2304: 0x3000, 0x2305: 0x3000,
- 0x2306: 0x3000, 0x2307: 0x3000, 0x2308: 0x3000, 0x2309: 0x3000, 0x230a: 0x3000, 0x230b: 0x3000,
- 0x230c: 0x3000, 0x230d: 0x3000, 0x230e: 0x3000, 0x230f: 0x3000, 0x2310: 0x3000, 0x2311: 0x3000,
- 0x2312: 0x3000, 0x2313: 0x3000, 0x2314: 0x3000, 0x2315: 0x3000, 0x2316: 0x3000, 0x2317: 0x3000,
- 0x2318: 0x3000, 0x2319: 0x3000, 0x231a: 0x3000, 0x231b: 0x3000, 0x231c: 0x3000, 0x231d: 0x3000,
- 0x231e: 0x3000, 0x231f: 0x3000, 0x2320: 0x3000, 0x2321: 0x3000, 0x2322: 0x3000, 0x2323: 0x3000,
- 0x2324: 0x3000, 0x2325: 0x3000, 0x2326: 0x3000, 0x2327: 0x3000, 0x2328: 0x3000, 0x2329: 0x3000,
- 0x232a: 0x3000, 0x232b: 0x3000, 0x232c: 0x3000, 0x232d: 0x3000, 0x232e: 0x3000, 0x232f: 0x3000,
- 0x2330: 0x3000, 0x2331: 0x3000,
- // Block 0x8d, offset 0x2340
- 0x2353: 0x3000, 0x2354: 0x3000, 0x2355: 0x3000, 0x2356: 0x3000, 0x2357: 0x3000,
- 0x2358: 0x3000, 0x2359: 0x3000, 0x235a: 0x3000, 0x235b: 0x3000, 0x235c: 0x3000, 0x235d: 0x3000,
- 0x235e: 0x3000, 0x235f: 0x3000, 0x2360: 0x3000, 0x2361: 0x3000, 0x2362: 0x3000, 0x2363: 0x3000,
- 0x2364: 0x3000, 0x2365: 0x3000, 0x2366: 0x3000, 0x2367: 0x3000, 0x2368: 0x3000, 0x2369: 0x3000,
- 0x236a: 0x3000, 0x236b: 0x3000, 0x236c: 0x3000, 0x236d: 0x3000, 0x236e: 0x3000, 0x236f: 0x3000,
- 0x2370: 0x3000, 0x2371: 0x3000, 0x2372: 0x3000, 0x2373: 0x3000, 0x2374: 0x3000, 0x2375: 0x3000,
- 0x2376: 0x3000, 0x2377: 0x3000, 0x2378: 0x3000, 0x2379: 0x3000, 0x237a: 0x3000, 0x237b: 0x3000,
- 0x237c: 0x3000, 0x237d: 0x3000, 0x237e: 0x3000, 0x237f: 0x3000,
- // Block 0x8e, offset 0x2380
- 0x2380: 0x3000, 0x2381: 0x3000, 0x2382: 0x3000, 0x2383: 0x3000, 0x2384: 0x3000, 0x2385: 0x3000,
- 0x2386: 0x3000, 0x2387: 0x3000, 0x2388: 0x3000, 0x2389: 0x3000, 0x238a: 0x3000, 0x238b: 0x3000,
- 0x238c: 0x3000, 0x238d: 0x3000, 0x238e: 0x3000, 0x238f: 0x3000, 0x2390: 0x3000, 0x2391: 0x3000,
- 0x2392: 0x3000, 0x2393: 0x3000, 0x2394: 0x3000, 0x2395: 0x3000, 0x2396: 0x3000, 0x2397: 0x3000,
- 0x2398: 0x3000, 0x2399: 0x3000, 0x239a: 0x3000, 0x239b: 0x3000, 0x239c: 0x3000, 0x239d: 0x3000,
- 0x239e: 0x3000, 0x239f: 0x3000, 0x23a0: 0x3000, 0x23a1: 0x3000, 0x23a2: 0x3000, 0x23a3: 0x3000,
- 0x23a4: 0x3000, 0x23a5: 0x3000, 0x23a6: 0x3000, 0x23a7: 0x3000, 0x23a8: 0x3000, 0x23a9: 0x3000,
- 0x23aa: 0x3000, 0x23ab: 0x3000, 0x23ac: 0x3000, 0x23ad: 0x3000, 0x23ae: 0x3000, 0x23af: 0x3000,
- 0x23b0: 0x3000, 0x23b1: 0x3000, 0x23b2: 0x3000, 0x23b3: 0x3000, 0x23b4: 0x3000, 0x23b5: 0x3000,
- 0x23b6: 0x3000, 0x23b7: 0x3000, 0x23b8: 0x3000, 0x23b9: 0x3000, 0x23ba: 0x3000, 0x23bb: 0x3000,
- 0x23bc: 0x3000, 0x23bd: 0x3000,
- // Block 0x8f, offset 0x23c0
- 0x23d0: 0x3000, 0x23d1: 0x3000,
- 0x23d2: 0x3000, 0x23d3: 0x3000, 0x23d4: 0x3000, 0x23d5: 0x3000, 0x23d6: 0x3000, 0x23d7: 0x3000,
- 0x23d8: 0x3000, 0x23d9: 0x3000, 0x23da: 0x3000, 0x23db: 0x3000, 0x23dc: 0x3000, 0x23dd: 0x3000,
- 0x23de: 0x3000, 0x23df: 0x3000, 0x23e0: 0x3000, 0x23e1: 0x3000, 0x23e2: 0x3000, 0x23e3: 0x3000,
- 0x23e4: 0x3000, 0x23e5: 0x3000, 0x23e6: 0x3000, 0x23e7: 0x3000, 0x23e8: 0x3000, 0x23e9: 0x3000,
- 0x23ea: 0x3000, 0x23eb: 0x3000, 0x23ec: 0x3000, 0x23ed: 0x3000, 0x23ee: 0x3000, 0x23ef: 0x3000,
- 0x23f0: 0x3000, 0x23f1: 0x3000, 0x23f2: 0x3000, 0x23f3: 0x3000, 0x23f4: 0x3000, 0x23f5: 0x3000,
- 0x23f6: 0x3000, 0x23f7: 0x3000, 0x23f8: 0x3000, 0x23f9: 0x3000, 0x23fa: 0x3000, 0x23fb: 0x3000,
- 0x23fc: 0x3000, 0x23fd: 0x3000, 0x23fe: 0x3000, 0x23ff: 0x3000,
- // Block 0x90, offset 0x2400
- 0x2400: 0x3000, 0x2401: 0x3000, 0x2402: 0x3000, 0x2403: 0x3000, 0x2404: 0x3000, 0x2405: 0x3000,
- 0x2406: 0x3000, 0x2407: 0x3000, 0x2408: 0x3000, 0x2409: 0x3000, 0x240a: 0x3000, 0x240b: 0x3000,
- 0x240c: 0x3000, 0x240d: 0x3000, 0x240e: 0x3000, 0x240f: 0x3000,
- 0x2412: 0x3000, 0x2413: 0x3000, 0x2414: 0x3000, 0x2415: 0x3000, 0x2416: 0x3000, 0x2417: 0x3000,
- 0x2418: 0x3000, 0x2419: 0x3000, 0x241a: 0x3000, 0x241b: 0x3000, 0x241c: 0x3000, 0x241d: 0x3000,
- 0x241e: 0x3000, 0x241f: 0x3000, 0x2420: 0x3000, 0x2421: 0x3000, 0x2422: 0x3000, 0x2423: 0x3000,
- 0x2424: 0x3000, 0x2425: 0x3000, 0x2426: 0x3000, 0x2427: 0x3000, 0x2428: 0x3000, 0x2429: 0x3000,
- 0x242a: 0x3000, 0x242b: 0x3000, 0x242c: 0x3000, 0x242d: 0x3000, 0x242e: 0x3000, 0x242f: 0x3000,
- 0x2430: 0x3000, 0x2431: 0x3000, 0x2432: 0x3000, 0x2433: 0x3000, 0x2434: 0x3000, 0x2435: 0x3000,
- 0x2436: 0x3000, 0x2437: 0x3000, 0x2438: 0x3000, 0x2439: 0x3000, 0x243a: 0x3000, 0x243b: 0x3000,
- 0x243c: 0x3000, 0x243d: 0x3000, 0x243e: 0x3000, 0x243f: 0x3000,
- // Block 0x91, offset 0x2440
- 0x2440: 0x3000, 0x2441: 0x3000, 0x2442: 0x3000, 0x2443: 0x3000, 0x2444: 0x3000, 0x2445: 0x3000,
- 0x2446: 0x3000, 0x2447: 0x3000,
- 0x2470: 0x3000, 0x2471: 0x3000, 0x2472: 0x3000, 0x2473: 0x3000, 0x2474: 0x3000, 0x2475: 0x3000,
- 0x2476: 0x3000, 0x2477: 0x3000, 0x2478: 0x3000, 0x2479: 0x3000, 0x247a: 0x3000, 0x247b: 0x3000,
- 0x247c: 0x3000,
- // Block 0x92, offset 0x2480
- 0x2490: 0x3000, 0x2491: 0x3000,
- 0x2492: 0x3000, 0x2493: 0x3000, 0x2494: 0x3000, 0x2495: 0x3000, 0x2496: 0x3000, 0x2497: 0x3000,
- 0x2498: 0x3000, 0x2499: 0x3000,
- 0x24a0: 0x00e6, 0x24a1: 0x00e6, 0x24a2: 0x00e6, 0x24a3: 0x00e6,
- 0x24a4: 0x00e6, 0x24a5: 0x00e6, 0x24a6: 0x00e6,
- 0x24b0: 0x3000, 0x24b1: 0x3000, 0x24b2: 0x3000, 0x24b3: 0x3000, 0x24b4: 0x3000, 0x24b5: 0x3000,
- 0x24b6: 0x3000, 0x24b7: 0x3000, 0x24b8: 0x3000, 0x24b9: 0x3000, 0x24ba: 0x3000, 0x24bb: 0x3000,
- 0x24bc: 0x3000, 0x24bd: 0x3000, 0x24be: 0x3000, 0x24bf: 0x3000,
- // Block 0x93, offset 0x24c0
- 0x24c0: 0x3000, 0x24c1: 0x3000, 0x24c2: 0x3000, 0x24c3: 0x3000, 0x24c4: 0x3000,
- 0x24c7: 0x3000, 0x24c8: 0x3000, 0x24c9: 0x3000, 0x24ca: 0x3000, 0x24cb: 0x3000,
- 0x24cc: 0x3000, 0x24cd: 0x3000, 0x24ce: 0x3000, 0x24cf: 0x3000, 0x24d0: 0x3000, 0x24d1: 0x3000,
- 0x24d2: 0x3000, 0x24d4: 0x3000, 0x24d5: 0x3000, 0x24d6: 0x3000, 0x24d7: 0x3000,
- 0x24d8: 0x3000, 0x24d9: 0x3000, 0x24da: 0x3000, 0x24db: 0x3000, 0x24dc: 0x3000, 0x24dd: 0x3000,
- 0x24de: 0x3000, 0x24df: 0x3000, 0x24e0: 0x3000, 0x24e1: 0x3000, 0x24e2: 0x3000, 0x24e3: 0x3000,
- 0x24e4: 0x3000, 0x24e5: 0x3000, 0x24e6: 0x3000, 0x24e8: 0x3000, 0x24e9: 0x3000,
- 0x24ea: 0x3000, 0x24eb: 0x3000,
- 0x24f0: 0x3000, 0x24f1: 0x3000, 0x24f2: 0x3000, 0x24f4: 0x3000,
- 0x24f6: 0x3000, 0x24f7: 0x3000, 0x24f8: 0x3000, 0x24f9: 0x3000, 0x24fa: 0x3000, 0x24fb: 0x3000,
- 0x24fc: 0x3000, 0x24fd: 0x3000, 0x24fe: 0x3000, 0x24ff: 0x3000,
- // Block 0x94, offset 0x2500
- 0x2500: 0x3000, 0x2501: 0x3000, 0x2502: 0x3000, 0x2503: 0x3000, 0x2504: 0x3000, 0x2505: 0x3000,
- 0x2506: 0x3000, 0x2507: 0x3000, 0x2508: 0x3000, 0x2509: 0x3000, 0x250a: 0x3000, 0x250b: 0x3000,
- 0x250c: 0x3000, 0x250d: 0x3000, 0x250e: 0x3000, 0x250f: 0x3000, 0x2510: 0x3000, 0x2511: 0x3000,
- 0x2512: 0x3000, 0x2513: 0x3000, 0x2514: 0x3000, 0x2515: 0x3000, 0x2516: 0x3000, 0x2517: 0x3000,
- 0x2518: 0x3000, 0x2519: 0x3000, 0x251a: 0x3000, 0x251b: 0x3000, 0x251c: 0x3000, 0x251d: 0x3000,
- 0x251e: 0x3000, 0x251f: 0x3000, 0x2520: 0x3000, 0x2521: 0x3000, 0x2522: 0x3000, 0x2523: 0x3000,
- 0x2524: 0x3000, 0x2525: 0x3000, 0x2526: 0x3000, 0x2527: 0x3000, 0x2528: 0x3000, 0x2529: 0x3000,
- 0x252a: 0x3000, 0x252b: 0x3000, 0x252c: 0x3000, 0x252d: 0x3000, 0x252e: 0x3000, 0x252f: 0x3000,
- 0x2530: 0x3000, 0x2531: 0x3000, 0x2532: 0x3000, 0x2533: 0x3000, 0x2534: 0x3000, 0x2535: 0x3000,
- 0x2536: 0x3000, 0x2537: 0x3000, 0x2538: 0x3000, 0x2539: 0x3000, 0x253a: 0x3000, 0x253b: 0x3000,
- 0x253c: 0x3000,
- // Block 0x95, offset 0x2540
- 0x2541: 0x3000, 0x2542: 0x3000, 0x2543: 0x3000, 0x2544: 0x3000, 0x2545: 0x3000,
- 0x2546: 0x3000, 0x2547: 0x3000, 0x2548: 0x3000, 0x2549: 0x3000, 0x254a: 0x3000, 0x254b: 0x3000,
- 0x254c: 0x3000, 0x254d: 0x3000, 0x254e: 0x3000, 0x254f: 0x3000, 0x2550: 0x3000, 0x2551: 0x3000,
- 0x2552: 0x3000, 0x2553: 0x3000, 0x2554: 0x3000, 0x2555: 0x3000, 0x2556: 0x3000, 0x2557: 0x3000,
- 0x2558: 0x3000, 0x2559: 0x3000, 0x255a: 0x3000, 0x255b: 0x3000, 0x255c: 0x3000, 0x255d: 0x3000,
- 0x255e: 0x3000, 0x255f: 0x3000, 0x2560: 0x3000, 0x2561: 0x3000, 0x2562: 0x3000, 0x2563: 0x3000,
- 0x2564: 0x3000, 0x2565: 0x3000, 0x2566: 0x3000, 0x2567: 0x3000, 0x2568: 0x3000, 0x2569: 0x3000,
- 0x256a: 0x3000, 0x256b: 0x3000, 0x256c: 0x3000, 0x256d: 0x3000, 0x256e: 0x3000, 0x256f: 0x3000,
- 0x2570: 0x3000, 0x2571: 0x3000, 0x2572: 0x3000, 0x2573: 0x3000, 0x2574: 0x3000, 0x2575: 0x3000,
- 0x2576: 0x3000, 0x2577: 0x3000, 0x2578: 0x3000, 0x2579: 0x3000, 0x257a: 0x3000, 0x257b: 0x3000,
- 0x257c: 0x3000, 0x257d: 0x3000, 0x257e: 0x3000, 0x257f: 0x3000,
- // Block 0x96, offset 0x2580
- 0x2582: 0x3000, 0x2583: 0x3000, 0x2584: 0x3000, 0x2585: 0x3000,
- 0x2586: 0x3000, 0x2587: 0x3000, 0x258a: 0x3000, 0x258b: 0x3000,
- 0x258c: 0x3000, 0x258d: 0x3000, 0x258e: 0x3000, 0x258f: 0x3000,
- 0x2592: 0x3000, 0x2593: 0x3000, 0x2594: 0x3000, 0x2595: 0x3000, 0x2596: 0x3000, 0x2597: 0x3000,
- 0x259a: 0x3000, 0x259b: 0x3000, 0x259c: 0x3000,
- 0x25a0: 0x3000, 0x25a1: 0x3000, 0x25a2: 0x3000, 0x25a3: 0x3000,
- 0x25a4: 0x3000, 0x25a5: 0x3000, 0x25a6: 0x3000, 0x25a8: 0x3000, 0x25a9: 0x3000,
- 0x25aa: 0x3000, 0x25ab: 0x3000, 0x25ac: 0x3000, 0x25ad: 0x3000, 0x25ae: 0x3000,
- // Block 0x97, offset 0x25c0
- 0x25fd: 0x00dc,
- // Block 0x98, offset 0x2600
- 0x260d: 0x00dc, 0x260f: 0x00e6,
- 0x2638: 0x00e6, 0x2639: 0x0001, 0x263a: 0x00dc,
- 0x263f: 0x0009,
- // Block 0x99, offset 0x2640
- 0x2659: 0x8800, 0x265a: 0x1100, 0x265b: 0x8800, 0x265c: 0x1100,
- 0x2665: 0x8800,
- 0x266b: 0x1100,
- 0x2679: 0x0009, 0x267a: 0x6607,
- // Block 0x9a, offset 0x2680
- 0x269e: 0x3300, 0x269f: 0x3300, 0x26a0: 0x3300, 0x26a1: 0x3300, 0x26a2: 0x3300, 0x26a3: 0x3300,
- 0x26a4: 0x3300, 0x26a5: 0x00d8, 0x26a6: 0x00d8, 0x26a7: 0x0001, 0x26a8: 0x0001, 0x26a9: 0x0001,
- 0x26ad: 0x00e2, 0x26ae: 0x00d8, 0x26af: 0x00d8,
- 0x26b0: 0x00d8, 0x26b1: 0x00d8, 0x26b2: 0x00d8,
- 0x26bb: 0x00dc,
- 0x26bc: 0x00dc, 0x26bd: 0x00dc, 0x26be: 0x00dc, 0x26bf: 0x00dc,
- // Block 0x9b, offset 0x26c0
- 0x26c0: 0x00dc, 0x26c1: 0x00dc, 0x26c2: 0x00dc, 0x26c5: 0x00e6,
- 0x26c6: 0x00e6, 0x26c7: 0x00e6, 0x26c8: 0x00e6, 0x26c9: 0x00e6, 0x26ca: 0x00dc, 0x26cb: 0x00dc,
- 0x26ea: 0x00e6, 0x26eb: 0x00e6, 0x26ec: 0x00e6, 0x26ed: 0x00e6,
- 0x26fb: 0x3300,
- 0x26fc: 0x3300, 0x26fd: 0x3300, 0x26fe: 0x3300, 0x26ff: 0x3300,
- // Block 0x9c, offset 0x2700
- 0x2700: 0x3300,
- // Block 0x9d, offset 0x2740
- 0x2742: 0x00e6, 0x2743: 0x00e6, 0x2744: 0x00e6,
- // Block 0x9e, offset 0x2780
- 0x2780: 0x3000, 0x2781: 0x3000, 0x2782: 0x3000, 0x2783: 0x3000, 0x2784: 0x3000, 0x2785: 0x3000,
- 0x2786: 0x3000, 0x2787: 0x3000, 0x2788: 0x3000, 0x2789: 0x3000, 0x278a: 0x3000, 0x278b: 0x3000,
- 0x278c: 0x3000, 0x278d: 0x3000, 0x278e: 0x3000, 0x278f: 0x3000, 0x2790: 0x3000, 0x2791: 0x3000,
- 0x2792: 0x3000, 0x2793: 0x3000, 0x2794: 0x3000, 0x2796: 0x3000, 0x2797: 0x3000,
- 0x2798: 0x3000, 0x2799: 0x3000, 0x279a: 0x3000, 0x279b: 0x3000, 0x279c: 0x3000, 0x279d: 0x3000,
- 0x279e: 0x3000, 0x279f: 0x3000, 0x27a0: 0x3000, 0x27a1: 0x3000, 0x27a2: 0x3000, 0x27a3: 0x3000,
- 0x27a4: 0x3000, 0x27a5: 0x3000, 0x27a6: 0x3000, 0x27a7: 0x3000, 0x27a8: 0x3000, 0x27a9: 0x3000,
- 0x27aa: 0x3000, 0x27ab: 0x3000, 0x27ac: 0x3000, 0x27ad: 0x3000, 0x27ae: 0x3000, 0x27af: 0x3000,
- 0x27b0: 0x3000, 0x27b1: 0x3000, 0x27b2: 0x3000, 0x27b3: 0x3000, 0x27b4: 0x3000, 0x27b5: 0x3000,
- 0x27b6: 0x3000, 0x27b7: 0x3000, 0x27b8: 0x3000, 0x27b9: 0x3000, 0x27ba: 0x3000, 0x27bb: 0x3000,
- 0x27bc: 0x3000, 0x27bd: 0x3000, 0x27be: 0x3000, 0x27bf: 0x3000,
- // Block 0x9f, offset 0x27c0
- 0x27c0: 0x3000, 0x27c1: 0x3000, 0x27c2: 0x3000, 0x27c3: 0x3000, 0x27c4: 0x3000, 0x27c5: 0x3000,
- 0x27c6: 0x3000, 0x27c7: 0x3000, 0x27c8: 0x3000, 0x27c9: 0x3000, 0x27ca: 0x3000, 0x27cb: 0x3000,
- 0x27cc: 0x3000, 0x27cd: 0x3000, 0x27ce: 0x3000, 0x27cf: 0x3000, 0x27d0: 0x3000, 0x27d1: 0x3000,
- 0x27d2: 0x3000, 0x27d3: 0x3000, 0x27d4: 0x3000, 0x27d5: 0x3000, 0x27d6: 0x3000, 0x27d7: 0x3000,
- 0x27d8: 0x3000, 0x27d9: 0x3000, 0x27da: 0x3000, 0x27db: 0x3000, 0x27dc: 0x3000,
- 0x27de: 0x3000, 0x27df: 0x3000, 0x27e2: 0x3000,
- 0x27e5: 0x3000, 0x27e6: 0x3000, 0x27e9: 0x3000,
- 0x27ea: 0x3000, 0x27eb: 0x3000, 0x27ec: 0x3000, 0x27ee: 0x3000, 0x27ef: 0x3000,
- 0x27f0: 0x3000, 0x27f1: 0x3000, 0x27f2: 0x3000, 0x27f3: 0x3000, 0x27f4: 0x3000, 0x27f5: 0x3000,
- 0x27f6: 0x3000, 0x27f7: 0x3000, 0x27f8: 0x3000, 0x27f9: 0x3000, 0x27fb: 0x3000,
- 0x27fd: 0x3000, 0x27fe: 0x3000, 0x27ff: 0x3000,
- // Block 0xa0, offset 0x2800
- 0x2800: 0x3000, 0x2801: 0x3000, 0x2802: 0x3000, 0x2803: 0x3000, 0x2805: 0x3000,
- 0x2806: 0x3000, 0x2807: 0x3000, 0x2808: 0x3000, 0x2809: 0x3000, 0x280a: 0x3000, 0x280b: 0x3000,
- 0x280c: 0x3000, 0x280d: 0x3000, 0x280e: 0x3000, 0x280f: 0x3000, 0x2810: 0x3000, 0x2811: 0x3000,
- 0x2812: 0x3000, 0x2813: 0x3000, 0x2814: 0x3000, 0x2815: 0x3000, 0x2816: 0x3000, 0x2817: 0x3000,
- 0x2818: 0x3000, 0x2819: 0x3000, 0x281a: 0x3000, 0x281b: 0x3000, 0x281c: 0x3000, 0x281d: 0x3000,
- 0x281e: 0x3000, 0x281f: 0x3000, 0x2820: 0x3000, 0x2821: 0x3000, 0x2822: 0x3000, 0x2823: 0x3000,
- 0x2824: 0x3000, 0x2825: 0x3000, 0x2826: 0x3000, 0x2827: 0x3000, 0x2828: 0x3000, 0x2829: 0x3000,
- 0x282a: 0x3000, 0x282b: 0x3000, 0x282c: 0x3000, 0x282d: 0x3000, 0x282e: 0x3000, 0x282f: 0x3000,
- 0x2830: 0x3000, 0x2831: 0x3000, 0x2832: 0x3000, 0x2833: 0x3000, 0x2834: 0x3000, 0x2835: 0x3000,
- 0x2836: 0x3000, 0x2837: 0x3000, 0x2838: 0x3000, 0x2839: 0x3000, 0x283a: 0x3000, 0x283b: 0x3000,
- 0x283c: 0x3000, 0x283d: 0x3000, 0x283e: 0x3000, 0x283f: 0x3000,
- // Block 0xa1, offset 0x2840
- 0x2840: 0x3000, 0x2841: 0x3000, 0x2842: 0x3000, 0x2843: 0x3000, 0x2844: 0x3000, 0x2845: 0x3000,
- 0x2847: 0x3000, 0x2848: 0x3000, 0x2849: 0x3000, 0x284a: 0x3000,
- 0x284d: 0x3000, 0x284e: 0x3000, 0x284f: 0x3000, 0x2850: 0x3000, 0x2851: 0x3000,
- 0x2852: 0x3000, 0x2853: 0x3000, 0x2854: 0x3000, 0x2856: 0x3000, 0x2857: 0x3000,
- 0x2858: 0x3000, 0x2859: 0x3000, 0x285a: 0x3000, 0x285b: 0x3000, 0x285c: 0x3000,
- 0x285e: 0x3000, 0x285f: 0x3000, 0x2860: 0x3000, 0x2861: 0x3000, 0x2862: 0x3000, 0x2863: 0x3000,
- 0x2864: 0x3000, 0x2865: 0x3000, 0x2866: 0x3000, 0x2867: 0x3000, 0x2868: 0x3000, 0x2869: 0x3000,
- 0x286a: 0x3000, 0x286b: 0x3000, 0x286c: 0x3000, 0x286d: 0x3000, 0x286e: 0x3000, 0x286f: 0x3000,
- 0x2870: 0x3000, 0x2871: 0x3000, 0x2872: 0x3000, 0x2873: 0x3000, 0x2874: 0x3000, 0x2875: 0x3000,
- 0x2876: 0x3000, 0x2877: 0x3000, 0x2878: 0x3000, 0x2879: 0x3000, 0x287b: 0x3000,
- 0x287c: 0x3000, 0x287d: 0x3000, 0x287e: 0x3000,
- // Block 0xa2, offset 0x2880
- 0x2880: 0x3000, 0x2881: 0x3000, 0x2882: 0x3000, 0x2883: 0x3000, 0x2884: 0x3000,
- 0x2886: 0x3000, 0x288a: 0x3000, 0x288b: 0x3000,
- 0x288c: 0x3000, 0x288d: 0x3000, 0x288e: 0x3000, 0x288f: 0x3000, 0x2890: 0x3000,
- 0x2892: 0x3000, 0x2893: 0x3000, 0x2894: 0x3000, 0x2895: 0x3000, 0x2896: 0x3000, 0x2897: 0x3000,
- 0x2898: 0x3000, 0x2899: 0x3000, 0x289a: 0x3000, 0x289b: 0x3000, 0x289c: 0x3000, 0x289d: 0x3000,
- 0x289e: 0x3000, 0x289f: 0x3000, 0x28a0: 0x3000, 0x28a1: 0x3000, 0x28a2: 0x3000, 0x28a3: 0x3000,
- 0x28a4: 0x3000, 0x28a5: 0x3000, 0x28a6: 0x3000, 0x28a7: 0x3000, 0x28a8: 0x3000, 0x28a9: 0x3000,
- 0x28aa: 0x3000, 0x28ab: 0x3000, 0x28ac: 0x3000, 0x28ad: 0x3000, 0x28ae: 0x3000, 0x28af: 0x3000,
- 0x28b0: 0x3000, 0x28b1: 0x3000, 0x28b2: 0x3000, 0x28b3: 0x3000, 0x28b4: 0x3000, 0x28b5: 0x3000,
- 0x28b6: 0x3000, 0x28b7: 0x3000, 0x28b8: 0x3000, 0x28b9: 0x3000, 0x28ba: 0x3000, 0x28bb: 0x3000,
- 0x28bc: 0x3000, 0x28bd: 0x3000, 0x28be: 0x3000, 0x28bf: 0x3000,
- // Block 0xa3, offset 0x28c0
- 0x28c0: 0x3000, 0x28c1: 0x3000, 0x28c2: 0x3000, 0x28c3: 0x3000, 0x28c4: 0x3000, 0x28c5: 0x3000,
- 0x28c6: 0x3000, 0x28c7: 0x3000, 0x28c8: 0x3000, 0x28c9: 0x3000, 0x28ca: 0x3000, 0x28cb: 0x3000,
- 0x28cc: 0x3000, 0x28cd: 0x3000, 0x28ce: 0x3000, 0x28cf: 0x3000, 0x28d0: 0x3000, 0x28d1: 0x3000,
- 0x28d2: 0x3000, 0x28d3: 0x3000, 0x28d4: 0x3000, 0x28d5: 0x3000, 0x28d6: 0x3000, 0x28d7: 0x3000,
- 0x28d8: 0x3000, 0x28d9: 0x3000, 0x28da: 0x3000, 0x28db: 0x3000, 0x28dc: 0x3000, 0x28dd: 0x3000,
- 0x28de: 0x3000, 0x28df: 0x3000, 0x28e0: 0x3000, 0x28e1: 0x3000, 0x28e2: 0x3000, 0x28e3: 0x3000,
- 0x28e4: 0x3000, 0x28e5: 0x3000, 0x28e8: 0x3000, 0x28e9: 0x3000,
- 0x28ea: 0x3000, 0x28eb: 0x3000, 0x28ec: 0x3000, 0x28ed: 0x3000, 0x28ee: 0x3000, 0x28ef: 0x3000,
- 0x28f0: 0x3000, 0x28f1: 0x3000, 0x28f2: 0x3000, 0x28f3: 0x3000, 0x28f4: 0x3000, 0x28f5: 0x3000,
- 0x28f6: 0x3000, 0x28f7: 0x3000, 0x28f8: 0x3000, 0x28f9: 0x3000, 0x28fa: 0x3000, 0x28fb: 0x3000,
- 0x28fc: 0x3000, 0x28fd: 0x3000, 0x28fe: 0x3000, 0x28ff: 0x3000,
- // Block 0xa4, offset 0x2900
- 0x2900: 0x3000, 0x2901: 0x3000, 0x2902: 0x3000, 0x2903: 0x3000, 0x2904: 0x3000, 0x2905: 0x3000,
- 0x2906: 0x3000, 0x2907: 0x3000, 0x2908: 0x3000, 0x2909: 0x3000, 0x290a: 0x3000, 0x290b: 0x3000,
- 0x290e: 0x3000, 0x290f: 0x3000, 0x2910: 0x3000, 0x2911: 0x3000,
- 0x2912: 0x3000, 0x2913: 0x3000, 0x2914: 0x3000, 0x2915: 0x3000, 0x2916: 0x3000, 0x2917: 0x3000,
- 0x2918: 0x3000, 0x2919: 0x3000, 0x291a: 0x3000, 0x291b: 0x3000, 0x291c: 0x3000, 0x291d: 0x3000,
- 0x291e: 0x3000, 0x291f: 0x3000, 0x2920: 0x3000, 0x2921: 0x3000, 0x2922: 0x3000, 0x2923: 0x3000,
- 0x2924: 0x3000, 0x2925: 0x3000, 0x2926: 0x3000, 0x2927: 0x3000, 0x2928: 0x3000, 0x2929: 0x3000,
- 0x292a: 0x3000, 0x292b: 0x3000, 0x292c: 0x3000, 0x292d: 0x3000, 0x292e: 0x3000, 0x292f: 0x3000,
- 0x2930: 0x3000, 0x2931: 0x3000, 0x2932: 0x3000, 0x2933: 0x3000, 0x2934: 0x3000, 0x2935: 0x3000,
- 0x2936: 0x3000, 0x2937: 0x3000, 0x2938: 0x3000, 0x2939: 0x3000, 0x293a: 0x3000, 0x293b: 0x3000,
- 0x293c: 0x3000, 0x293d: 0x3000, 0x293e: 0x3000, 0x293f: 0x3000,
- // Block 0xa5, offset 0x2940
- 0x2940: 0x3000, 0x2941: 0x3000, 0x2942: 0x3000, 0x2943: 0x3000, 0x2944: 0x3000, 0x2945: 0x3000,
- 0x2946: 0x3000, 0x2947: 0x3000, 0x2948: 0x3000, 0x2949: 0x3000, 0x294a: 0x3000,
- 0x2950: 0x3000, 0x2951: 0x3000,
- 0x2952: 0x3000, 0x2953: 0x3000, 0x2954: 0x3000, 0x2955: 0x3000, 0x2956: 0x3000, 0x2957: 0x3000,
- 0x2958: 0x3000, 0x2959: 0x3000, 0x295a: 0x3000, 0x295b: 0x3000, 0x295c: 0x3000, 0x295d: 0x3000,
- 0x295e: 0x3000, 0x295f: 0x3000, 0x2960: 0x3000, 0x2961: 0x3000, 0x2962: 0x3000, 0x2963: 0x3000,
- 0x2964: 0x3000, 0x2965: 0x3000, 0x2966: 0x3000, 0x2967: 0x3000, 0x2968: 0x3000, 0x2969: 0x3000,
- 0x296a: 0x3000, 0x296b: 0x3000, 0x296c: 0x3000, 0x296d: 0x3000, 0x296e: 0x3000,
- 0x2970: 0x3000, 0x2971: 0x3000, 0x2972: 0x3000, 0x2973: 0x3000, 0x2974: 0x3000, 0x2975: 0x3000,
- 0x2976: 0x3000, 0x2977: 0x3000, 0x2978: 0x3000, 0x2979: 0x3000, 0x297a: 0x3000, 0x297b: 0x3000,
- 0x297c: 0x3000, 0x297d: 0x3000, 0x297e: 0x3000, 0x297f: 0x3000,
- // Block 0xa6, offset 0x2980
- 0x2980: 0x3000, 0x2981: 0x3000, 0x2982: 0x3000, 0x2983: 0x3000, 0x2984: 0x3000, 0x2985: 0x3000,
- 0x2986: 0x3000, 0x2987: 0x3000, 0x2988: 0x3000, 0x2989: 0x3000, 0x298a: 0x3000, 0x298b: 0x3000,
- 0x298c: 0x3000, 0x298d: 0x3000, 0x298e: 0x3000, 0x298f: 0x3000,
- // Block 0xa7, offset 0x29c0
- 0x29d0: 0x3000,
- // Block 0xa8, offset 0x2a00
- 0x2a00: 0x3000, 0x2a01: 0x3000, 0x2a02: 0x3000,
- 0x2a10: 0x3000, 0x2a11: 0x3000,
- 0x2a12: 0x3000, 0x2a13: 0x3000, 0x2a14: 0x3000, 0x2a15: 0x3000, 0x2a16: 0x3000, 0x2a17: 0x3000,
- 0x2a18: 0x3000, 0x2a19: 0x3000, 0x2a1a: 0x3000, 0x2a1b: 0x3000, 0x2a1c: 0x3000, 0x2a1d: 0x3000,
- 0x2a1e: 0x3000, 0x2a1f: 0x3000, 0x2a20: 0x3000, 0x2a21: 0x3000, 0x2a22: 0x3000, 0x2a23: 0x3000,
- 0x2a24: 0x3000, 0x2a25: 0x3000, 0x2a26: 0x3000, 0x2a27: 0x3000, 0x2a28: 0x3000, 0x2a29: 0x3000,
- 0x2a2a: 0x3000, 0x2a2b: 0x3000, 0x2a2c: 0x3000, 0x2a2d: 0x3000, 0x2a2e: 0x3000, 0x2a2f: 0x3000,
- 0x2a30: 0x3000, 0x2a31: 0x3000, 0x2a32: 0x3000, 0x2a33: 0x3000, 0x2a34: 0x3000, 0x2a35: 0x3000,
- 0x2a36: 0x3000, 0x2a37: 0x3000, 0x2a38: 0x3000, 0x2a39: 0x3000, 0x2a3a: 0x3000,
- // Block 0xa9, offset 0x2a40
- 0x2a40: 0x3000, 0x2a41: 0x3000, 0x2a42: 0x3000, 0x2a43: 0x3000, 0x2a44: 0x3000, 0x2a45: 0x3000,
- 0x2a46: 0x3000, 0x2a47: 0x3000, 0x2a48: 0x3000,
- 0x2a50: 0x3000, 0x2a51: 0x3000,
- // Block 0xaa, offset 0x2a80
- 0x2a80: 0x3300, 0x2a81: 0x3300, 0x2a82: 0x3300, 0x2a83: 0x3300, 0x2a84: 0x3300, 0x2a85: 0x3300,
- 0x2a86: 0x3300, 0x2a87: 0x3300, 0x2a88: 0x3300, 0x2a89: 0x3300, 0x2a8a: 0x3300, 0x2a8b: 0x3300,
- 0x2a8c: 0x3300, 0x2a8d: 0x3300, 0x2a8e: 0x3300, 0x2a8f: 0x3300, 0x2a90: 0x3300, 0x2a91: 0x3300,
- 0x2a92: 0x3300, 0x2a93: 0x3300, 0x2a94: 0x3300, 0x2a95: 0x3300, 0x2a96: 0x3300, 0x2a97: 0x3300,
- 0x2a98: 0x3300, 0x2a99: 0x3300, 0x2a9a: 0x3300, 0x2a9b: 0x3300, 0x2a9c: 0x3300, 0x2a9d: 0x3300,
+ 0x03c0: 0x1100, 0x03c1: 0x8800, 0x03c2: 0x1100, 0x03c4: 0x8800, 0x03c5: 0x1100,
+ 0x03c6: 0x8800, 0x03c7: 0x1100, 0x03c8: 0x8800, 0x03c9: 0x1100,
+ 0x03cf: 0x8800, 0x03d0: 0x1100, 0x03d1: 0x1100,
+ 0x03d2: 0x8800, 0x03d3: 0x1100, 0x03d4: 0x1100, 0x03d5: 0x8800, 0x03d6: 0x1100, 0x03d7: 0x1100,
+ 0x03d8: 0x8800, 0x03d9: 0x1100, 0x03da: 0x1100, 0x03db: 0x8800, 0x03dc: 0x1100, 0x03dd: 0x1100,
+ 0x03ef: 0x8800,
+ 0x03f0: 0x8800, 0x03f1: 0x8800, 0x03f2: 0x8800, 0x03f4: 0x1100,
+ 0x03f7: 0x1100, 0x03f8: 0x1100, 0x03f9: 0x1100, 0x03fa: 0x1100,
+ 0x03fd: 0x8800, 0x03fe: 0x1100, 0x03ff: 0x3000,
+}
+
+// charInfoSparseOffset: 156 entries, 312 bytes
+var charInfoSparseOffset = []uint16{0x0, 0x8, 0x13, 0x21, 0x25, 0x2f, 0x36, 0x39, 0x3c, 0x4a, 0x56, 0x58, 0x62, 0x67, 0x6e, 0x7d, 0x8a, 0x92, 0x96, 0x9b, 0x9d, 0xa5, 0xab, 0xae, 0xb5, 0xb9, 0xbd, 0xbf, 0xc1, 0xc8, 0xcc, 0xd1, 0xd7, 0xda, 0xe3, 0xe5, 0xed, 0xf1, 0xf3, 0xf6, 0xf9, 0xff, 0x10f, 0x11b, 0x11d, 0x123, 0x125, 0x127, 0x129, 0x12b, 0x12d, 0x12f, 0x131, 0x134, 0x137, 0x139, 0x13c, 0x13f, 0x143, 0x152, 0x15a, 0x15c, 0x15f, 0x161, 0x16a, 0x16e, 0x172, 0x174, 0x183, 0x187, 0x18d, 0x195, 0x199, 0x1a2, 0x1ab, 0x1b6, 0x1bc, 0x1c0, 0x1ce, 0x1dd, 0x1e1, 0x1e8, 0x1ed, 0x1fc, 0x208, 0x20b, 0x20d, 0x20f, 0x211, 0x213, 0x215, 0x217, 0x219, 0x21b, 0x21d, 0x220, 0x222, 0x224, 0x226, 0x228, 0x231, 0x233, 0x236, 0x239, 0x23c, 0x23e, 0x241, 0x243, 0x245, 0x247, 0x24a, 0x24c, 0x24e, 0x250, 0x252, 0x258, 0x25a, 0x25c, 0x25e, 0x260, 0x262, 0x26c, 0x26f, 0x271, 0x27b, 0x280, 0x282, 0x284, 0x286, 0x288, 0x28b, 0x28e, 0x292, 0x29a, 0x29c, 0x29e, 0x2a5, 0x2a7, 0x2ae, 0x2b6, 0x2bd, 0x2c3, 0x2c5, 0x2c7, 0x2ca, 0x2d3, 0x2d6, 0x2dd, 0x2e2, 0x2e5, 0x2e8, 0x2ec, 0x2ee, 0x2f0, 0x2f3, 0x2f6}
+
+// charInfoSparseValues: 760 entries, 3040 bytes
+var charInfoSparseValues = [760]valueRange{
+ // Block 0x0, offset 0x1
+ {value: 0x0000, lo: 0x07},
+ {value: 0x3000, lo: 0xa0, hi: 0xa0},
+ {value: 0x3800, lo: 0xa8, hi: 0xa8},
+ {value: 0x3000, lo: 0xaa, hi: 0xaa},
+ {value: 0x3000, lo: 0xaf, hi: 0xaf},
+ {value: 0x3000, lo: 0xb2, hi: 0xb5},
+ {value: 0x3000, lo: 0xb8, hi: 0xba},
+ {value: 0x3000, lo: 0xbc, hi: 0xbe},
+ // Block 0x1, offset 0x2
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x1100, lo: 0x80, hi: 0x81},
+ {value: 0x9900, lo: 0x82, hi: 0x83},
+ {value: 0x1100, lo: 0x84, hi: 0x8f},
+ {value: 0x9900, lo: 0x92, hi: 0x93},
+ {value: 0x1100, lo: 0x94, hi: 0xa5},
+ {value: 0x1100, lo: 0xa8, hi: 0xb0},
+ {value: 0x3000, lo: 0xb2, hi: 0xb3},
+ {value: 0x1100, lo: 0xb4, hi: 0xb7},
+ {value: 0x1100, lo: 0xb9, hi: 0xbe},
+ {value: 0x3000, lo: 0xbf, hi: 0xbf},
+ // Block 0x2, offset 0x3
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x3000, lo: 0x80, hi: 0x80},
+ {value: 0x1100, lo: 0x83, hi: 0x88},
+ {value: 0x3000, lo: 0x89, hi: 0x89},
+ {value: 0x9900, lo: 0x8c, hi: 0x8d},
+ {value: 0x1100, lo: 0x8e, hi: 0x91},
+ {value: 0x1100, lo: 0x94, hi: 0x99},
+ {value: 0x9900, lo: 0x9a, hi: 0x9b},
+ {value: 0x1100, lo: 0x9c, hi: 0x9f},
+ {value: 0x9900, lo: 0xa0, hi: 0xa1},
+ {value: 0x1100, lo: 0xa2, hi: 0xa5},
+ {value: 0x9900, lo: 0xa8, hi: 0xab},
+ {value: 0x1100, lo: 0xac, hi: 0xbe},
+ {value: 0x3800, lo: 0xbf, hi: 0xbf},
+ // Block 0x3, offset 0x4
+ {value: 0x0000, lo: 0x03},
+ {value: 0x9900, lo: 0xa0, hi: 0xa1},
+ {value: 0x9900, lo: 0xaf, hi: 0xb0},
+ {value: 0x8800, lo: 0xb7, hi: 0xb7},
+ // Block 0x4, offset 0x5
+ {value: 0x0000, lo: 0x09},
+ {value: 0x3000, lo: 0x84, hi: 0x8c},
+ {value: 0x1100, lo: 0x8d, hi: 0x9c},
+ {value: 0x1100, lo: 0x9e, hi: 0xa3},
+ {value: 0x1100, lo: 0xa6, hi: 0xa9},
+ {value: 0x9900, lo: 0xaa, hi: 0xab},
+ {value: 0x1100, lo: 0xac, hi: 0xb0},
+ {value: 0x3000, lo: 0xb1, hi: 0xb3},
+ {value: 0x1100, lo: 0xb4, hi: 0xb5},
+ {value: 0x1100, lo: 0xb8, hi: 0xbf},
+ // Block 0x5, offset 0x6
+ {value: 0x0000, lo: 0x06},
+ {value: 0x1100, lo: 0x80, hi: 0x9b},
+ {value: 0x1100, lo: 0x9e, hi: 0x9f},
+ {value: 0x9900, lo: 0xa6, hi: 0xa9},
+ {value: 0x1100, lo: 0xaa, hi: 0xad},
+ {value: 0x9900, lo: 0xae, hi: 0xaf},
+ {value: 0x1100, lo: 0xb0, hi: 0xb3},
+ // Block 0x6, offset 0x7
+ {value: 0x0000, lo: 0x02},
+ {value: 0x8800, lo: 0x92, hi: 0x92},
+ {value: 0x3000, lo: 0xb0, hi: 0xb8},
+ // Block 0x7, offset 0x8
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x98, hi: 0x9d},
+ {value: 0x3000, lo: 0xa0, hi: 0xa4},
+ // Block 0x8, offset 0x9
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x8800, lo: 0x81, hi: 0x81},
+ {value: 0x8800, lo: 0x85, hi: 0x85},
+ {value: 0x8800, lo: 0x89, hi: 0x89},
+ {value: 0x9900, lo: 0x8a, hi: 0x8b},
+ {value: 0x1100, lo: 0x8c, hi: 0x8d},
+ {value: 0x9900, lo: 0x8e, hi: 0x8e},
+ {value: 0x3000, lo: 0x90, hi: 0x91},
+ {value: 0x3800, lo: 0x92, hi: 0x92},
+ {value: 0x3100, lo: 0x93, hi: 0x94},
+ {value: 0x3000, lo: 0x95, hi: 0x96},
+ {value: 0x3000, lo: 0xb0, hi: 0xb2},
+ {value: 0x3000, lo: 0xb4, hi: 0xb5},
+ {value: 0x3000, lo: 0xb9, hi: 0xb9},
+ // Block 0x9, offset 0xa
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x8800, lo: 0x83, hi: 0x83},
+ {value: 0x8800, lo: 0x87, hi: 0x87},
+ {value: 0x8800, lo: 0x8b, hi: 0x8b},
+ {value: 0x8800, lo: 0x8d, hi: 0x8d},
+ {value: 0x1100, lo: 0x90, hi: 0x91},
+ {value: 0x1100, lo: 0x93, hi: 0x93},
+ {value: 0x8800, lo: 0x96, hi: 0x96},
+ {value: 0x1100, lo: 0x97, hi: 0x97},
+ {value: 0x1100, lo: 0x9c, hi: 0x9e},
+ {value: 0x8800, lo: 0xb4, hi: 0xb5},
+ {value: 0x1100, lo: 0xb6, hi: 0xb7},
+ // Block 0xa, offset 0xb
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00e6, lo: 0x83, hi: 0x87},
+ // Block 0xb, offset 0xc
+ {value: 0x0000, lo: 0x09},
+ {value: 0x1100, lo: 0x81, hi: 0x82},
+ {value: 0x1100, lo: 0x90, hi: 0x93},
+ {value: 0x1100, lo: 0x96, hi: 0x97},
+ {value: 0x8800, lo: 0x98, hi: 0x99},
+ {value: 0x1100, lo: 0x9a, hi: 0x9f},
+ {value: 0x1100, lo: 0xa2, hi: 0xa7},
+ {value: 0x8800, lo: 0xa8, hi: 0xa9},
+ {value: 0x1100, lo: 0xaa, hi: 0xb5},
+ {value: 0x1100, lo: 0xb8, hi: 0xb9},
+ // Block 0xc, offset 0xd
+ {value: 0x0001, lo: 0x04},
+ {value: 0x0018, lo: 0x81, hi: 0x82},
+ {value: 0x00e6, lo: 0x84, hi: 0x84},
+ {value: 0x00dc, lo: 0x85, hi: 0x85},
+ {value: 0x0012, lo: 0x87, hi: 0x87},
+ // Block 0xd, offset 0xe
+ {value: 0x0000, lo: 0x06},
+ {value: 0x00e6, lo: 0x90, hi: 0x97},
+ {value: 0x001e, lo: 0x98, hi: 0x98},
+ {value: 0x001f, lo: 0x99, hi: 0x99},
+ {value: 0x0020, lo: 0x9a, hi: 0x9a},
+ {value: 0x1100, lo: 0xa2, hi: 0xa6},
+ {value: 0x8800, lo: 0xa7, hi: 0xa7},
+ // Block 0xe, offset 0xf
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x1100, lo: 0x80, hi: 0x80},
+ {value: 0x8800, lo: 0x81, hi: 0x81},
+ {value: 0x1100, lo: 0x82, hi: 0x82},
+ {value: 0x8800, lo: 0x92, hi: 0x92},
+ {value: 0x1100, lo: 0x93, hi: 0x93},
+ {value: 0x8800, lo: 0x95, hi: 0x95},
+ {value: 0x00e6, lo: 0x96, hi: 0x9c},
+ {value: 0x00e6, lo: 0x9f, hi: 0xa2},
+ {value: 0x00dc, lo: 0xa3, hi: 0xa3},
+ {value: 0x00e6, lo: 0xa4, hi: 0xa4},
+ {value: 0x00e6, lo: 0xa7, hi: 0xa8},
+ {value: 0x00dc, lo: 0xaa, hi: 0xaa},
+ {value: 0x00e6, lo: 0xab, hi: 0xac},
+ {value: 0x00dc, lo: 0xad, hi: 0xad},
+ // Block 0xf, offset 0x10
+ {value: 0x0000, lo: 0x0c},
+ {value: 0x0024, lo: 0x91, hi: 0x91},
+ {value: 0x00e6, lo: 0xb0, hi: 0xb0},
+ {value: 0x00dc, lo: 0xb1, hi: 0xb1},
+ {value: 0x00e6, lo: 0xb2, hi: 0xb3},
+ {value: 0x00dc, lo: 0xb4, hi: 0xb4},
+ {value: 0x00e6, lo: 0xb5, hi: 0xb6},
+ {value: 0x00dc, lo: 0xb7, hi: 0xb9},
+ {value: 0x00e6, lo: 0xba, hi: 0xba},
+ {value: 0x00dc, lo: 0xbb, hi: 0xbc},
+ {value: 0x00e6, lo: 0xbd, hi: 0xbd},
+ {value: 0x00dc, lo: 0xbe, hi: 0xbe},
+ {value: 0x00e6, lo: 0xbf, hi: 0xbf},
+ // Block 0x10, offset 0x11
+ {value: 0x000a, lo: 0x07},
+ {value: 0x00e6, lo: 0x80, hi: 0x80},
+ {value: 0x00e6, lo: 0x81, hi: 0x81},
+ {value: 0x00dc, lo: 0x82, hi: 0x83},
+ {value: 0x00dc, lo: 0x84, hi: 0x85},
+ {value: 0x00dc, lo: 0x86, hi: 0x87},
+ {value: 0x00dc, lo: 0x88, hi: 0x89},
+ {value: 0x00e6, lo: 0x8a, hi: 0x8a},
+ // Block 0x11, offset 0x12
+ {value: 0x0000, lo: 0x03},
+ {value: 0x00e6, lo: 0xab, hi: 0xb1},
+ {value: 0x00dc, lo: 0xb2, hi: 0xb2},
+ {value: 0x00e6, lo: 0xb3, hi: 0xb3},
+ // Block 0x12, offset 0x13
+ {value: 0x0000, lo: 0x04},
+ {value: 0x00e6, lo: 0x96, hi: 0x99},
+ {value: 0x00e6, lo: 0x9b, hi: 0xa3},
+ {value: 0x00e6, lo: 0xa5, hi: 0xa7},
+ {value: 0x00e6, lo: 0xa9, hi: 0xad},
+ // Block 0x13, offset 0x14
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00dc, lo: 0x99, hi: 0x9b},
+ // Block 0x14, offset 0x15
+ {value: 0x7700, lo: 0x07},
+ {value: 0x8800, lo: 0xa8, hi: 0xa8},
+ {value: 0x1100, lo: 0xa9, hi: 0xa9},
+ {value: 0x8800, lo: 0xb0, hi: 0xb0},
+ {value: 0x1100, lo: 0xb1, hi: 0xb1},
+ {value: 0x8800, lo: 0xb3, hi: 0xb3},
+ {value: 0x1100, lo: 0xb4, hi: 0xb4},
+ {value: 0x6607, lo: 0xbc, hi: 0xbc},
+ // Block 0x15, offset 0x16
+ {value: 0x0000, lo: 0x05},
+ {value: 0x0009, lo: 0x8d, hi: 0x8d},
+ {value: 0x00e6, lo: 0x91, hi: 0x91},
+ {value: 0x00dc, lo: 0x92, hi: 0x92},
+ {value: 0x00e6, lo: 0x93, hi: 0x94},
+ {value: 0x3300, lo: 0x98, hi: 0x9f},
+ // Block 0x16, offset 0x17
+ {value: 0x65f9, lo: 0x02},
+ {value: 0x0007, lo: 0xbc, hi: 0xbc},
+ {value: 0x6600, lo: 0xbe, hi: 0xbe},
+ // Block 0x17, offset 0x18
+ {value: 0x0000, lo: 0x06},
+ {value: 0x8800, lo: 0x87, hi: 0x87},
+ {value: 0x1100, lo: 0x8b, hi: 0x8c},
+ {value: 0x0009, lo: 0x8d, hi: 0x8d},
+ {value: 0x6600, lo: 0x97, hi: 0x97},
+ {value: 0x3300, lo: 0x9c, hi: 0x9d},
+ {value: 0x3300, lo: 0x9f, hi: 0x9f},
+ // Block 0x18, offset 0x19
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3300, lo: 0xb3, hi: 0xb3},
+ {value: 0x3300, lo: 0xb6, hi: 0xb6},
+ {value: 0x0007, lo: 0xbc, hi: 0xbc},
+ // Block 0x19, offset 0x1a
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0009, lo: 0x8d, hi: 0x8d},
+ {value: 0x3300, lo: 0x99, hi: 0x9b},
+ {value: 0x3300, lo: 0x9e, hi: 0x9e},
+ // Block 0x1a, offset 0x1b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0007, lo: 0xbc, hi: 0xbc},
+ // Block 0x1b, offset 0x1c
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0009, lo: 0x8d, hi: 0x8d},
+ // Block 0x1c, offset 0x1d
+ {value: 0x0000, lo: 0x06},
+ {value: 0x8800, lo: 0x87, hi: 0x87},
+ {value: 0x1100, lo: 0x88, hi: 0x88},
+ {value: 0x1100, lo: 0x8b, hi: 0x8c},
+ {value: 0x0009, lo: 0x8d, hi: 0x8d},
+ {value: 0x6600, lo: 0x96, hi: 0x97},
+ {value: 0x3300, lo: 0x9c, hi: 0x9d},
+ // Block 0x1d, offset 0x1e
+ {value: 0x5500, lo: 0x03},
+ {value: 0x8800, lo: 0x92, hi: 0x92},
+ {value: 0x1100, lo: 0x94, hi: 0x94},
+ {value: 0x6600, lo: 0xbe, hi: 0xbe},
+ // Block 0x1e, offset 0x1f
+ {value: 0x0000, lo: 0x04},
+ {value: 0x8800, lo: 0x86, hi: 0x87},
+ {value: 0x1100, lo: 0x8a, hi: 0x8c},
+ {value: 0x0009, lo: 0x8d, hi: 0x8d},
+ {value: 0x6600, lo: 0x97, hi: 0x97},
+ // Block 0x1f, offset 0x20
+ {value: 0x004b, lo: 0x05},
+ {value: 0x8800, lo: 0x86, hi: 0x86},
+ {value: 0x1100, lo: 0x88, hi: 0x88},
+ {value: 0x0009, lo: 0x8d, hi: 0x8d},
+ {value: 0x0054, lo: 0x95, hi: 0x95},
+ {value: 0x665b, lo: 0x96, hi: 0x96},
+ // Block 0x20, offset 0x21
+ {value: 0x87f9, lo: 0x02},
+ {value: 0x0007, lo: 0xbc, hi: 0xbc},
+ {value: 0x8800, lo: 0xbf, hi: 0xbf},
+ // Block 0x21, offset 0x22
+ {value: 0x0000, lo: 0x08},
+ {value: 0x1100, lo: 0x80, hi: 0x80},
+ {value: 0x6600, lo: 0x82, hi: 0x82},
+ {value: 0x8800, lo: 0x86, hi: 0x86},
+ {value: 0x1100, lo: 0x87, hi: 0x88},
+ {value: 0x9900, lo: 0x8a, hi: 0x8a},
+ {value: 0x1100, lo: 0x8b, hi: 0x8b},
+ {value: 0x0009, lo: 0x8d, hi: 0x8d},
+ {value: 0x6600, lo: 0x95, hi: 0x96},
+ // Block 0x22, offset 0x23
+ {value: 0x0000, lo: 0x01},
+ {value: 0x6600, lo: 0xbe, hi: 0xbe},
+ // Block 0x23, offset 0x24
+ {value: 0x0000, lo: 0x07},
+ {value: 0x6609, lo: 0x8a, hi: 0x8a},
+ {value: 0x6600, lo: 0x8f, hi: 0x8f},
+ {value: 0x8800, lo: 0x99, hi: 0x99},
+ {value: 0x1100, lo: 0x9a, hi: 0x9a},
+ {value: 0x9900, lo: 0x9c, hi: 0x9c},
+ {value: 0x1100, lo: 0x9d, hi: 0x9e},
+ {value: 0x6600, lo: 0x9f, hi: 0x9f},
+ // Block 0x24, offset 0x25
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3000, lo: 0xb3, hi: 0xb3},
+ {value: 0x0067, lo: 0xb8, hi: 0xb9},
+ {value: 0x0009, lo: 0xba, hi: 0xba},
+ // Block 0x25, offset 0x26
+ {value: 0x0000, lo: 0x01},
+ {value: 0x006b, lo: 0x88, hi: 0x8b},
+ // Block 0x26, offset 0x27
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0xb3, hi: 0xb3},
+ {value: 0x0076, lo: 0xb8, hi: 0xb9},
+ // Block 0x27, offset 0x28
+ {value: 0x0000, lo: 0x02},
+ {value: 0x007a, lo: 0x88, hi: 0x8b},
+ {value: 0x3000, lo: 0x9c, hi: 0x9d},
+ // Block 0x28, offset 0x29
+ {value: 0x0000, lo: 0x05},
+ {value: 0x3000, lo: 0x8c, hi: 0x8c},
+ {value: 0x00dc, lo: 0x98, hi: 0x99},
+ {value: 0x00dc, lo: 0xb5, hi: 0xb5},
+ {value: 0x00dc, lo: 0xb7, hi: 0xb7},
+ {value: 0x00d8, lo: 0xb9, hi: 0xb9},
+ // Block 0x29, offset 0x2a
+ {value: 0x0000, lo: 0x0f},
+ {value: 0x3300, lo: 0x83, hi: 0x83},
+ {value: 0x3300, lo: 0x8d, hi: 0x8d},
+ {value: 0x3300, lo: 0x92, hi: 0x92},
+ {value: 0x3300, lo: 0x97, hi: 0x97},
+ {value: 0x3300, lo: 0x9c, hi: 0x9c},
+ {value: 0x3300, lo: 0xa9, hi: 0xa9},
+ {value: 0x0081, lo: 0xb1, hi: 0xb1},
+ {value: 0x0082, lo: 0xb2, hi: 0xb2},
+ {value: 0x3300, lo: 0xb3, hi: 0xb3},
+ {value: 0x0084, lo: 0xb4, hi: 0xb4},
+ {value: 0x3300, lo: 0xb5, hi: 0xb6},
+ {value: 0x3000, lo: 0xb7, hi: 0xb7},
+ {value: 0x3300, lo: 0xb8, hi: 0xb8},
+ {value: 0x3000, lo: 0xb9, hi: 0xb9},
+ {value: 0x0082, lo: 0xba, hi: 0xbd},
+ // Block 0x2a, offset 0x2b
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x0082, lo: 0x80, hi: 0x80},
+ {value: 0x3300, lo: 0x81, hi: 0x81},
+ {value: 0x00e6, lo: 0x82, hi: 0x83},
+ {value: 0x0009, lo: 0x84, hi: 0x84},
+ {value: 0x00e6, lo: 0x86, hi: 0x87},
+ {value: 0x3300, lo: 0x93, hi: 0x93},
+ {value: 0x3300, lo: 0x9d, hi: 0x9d},
+ {value: 0x3300, lo: 0xa2, hi: 0xa2},
+ {value: 0x3300, lo: 0xa7, hi: 0xa7},
+ {value: 0x3300, lo: 0xac, hi: 0xac},
+ {value: 0x3300, lo: 0xb9, hi: 0xb9},
+ // Block 0x2b, offset 0x2c
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00dc, lo: 0x86, hi: 0x86},
+ // Block 0x2c, offset 0x2d
+ {value: 0x0000, lo: 0x05},
+ {value: 0x8800, lo: 0xa5, hi: 0xa5},
+ {value: 0x1100, lo: 0xa6, hi: 0xa6},
+ {value: 0x6600, lo: 0xae, hi: 0xae},
+ {value: 0x0007, lo: 0xb7, hi: 0xb7},
+ {value: 0x0009, lo: 0xb9, hi: 0xba},
+ // Block 0x2d, offset 0x2e
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00dc, lo: 0x8d, hi: 0x8d},
+ // Block 0x2e, offset 0x2f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0xbc, hi: 0xbc},
+ // Block 0x2f, offset 0x30
+ {value: 0x0000, lo: 0x01},
+ {value: 0x8800, lo: 0x80, hi: 0x92},
+ // Block 0x30, offset 0x31
+ {value: 0x0000, lo: 0x01},
+ {value: 0xee00, lo: 0xa1, hi: 0xb5},
+ // Block 0x31, offset 0x32
+ {value: 0x0000, lo: 0x01},
+ {value: 0x6600, lo: 0xa8, hi: 0xbf},
+ // Block 0x32, offset 0x33
+ {value: 0x0000, lo: 0x01},
+ {value: 0x6600, lo: 0x80, hi: 0x82},
+ // Block 0x33, offset 0x34
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00e6, lo: 0x9d, hi: 0x9f},
+ // Block 0x34, offset 0x35
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0009, lo: 0x94, hi: 0x94},
+ {value: 0x0009, lo: 0xb4, hi: 0xb4},
+ // Block 0x35, offset 0x36
+ {value: 0x00dd, lo: 0x02},
+ {value: 0x0009, lo: 0x92, hi: 0x92},
+ {value: 0x00e6, lo: 0x9d, hi: 0x9d},
+ // Block 0x36, offset 0x37
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00e4, lo: 0xa9, hi: 0xa9},
+ // Block 0x37, offset 0x38
+ {value: 0x0008, lo: 0x02},
+ {value: 0x00de, lo: 0xb9, hi: 0xba},
+ {value: 0x00dc, lo: 0xbb, hi: 0xbb},
+ // Block 0x38, offset 0x39
+ {value: 0x0000, lo: 0x02},
+ {value: 0x00e6, lo: 0x97, hi: 0x97},
+ {value: 0x00dc, lo: 0x98, hi: 0x98},
+ // Block 0x39, offset 0x3a
+ {value: 0x0000, lo: 0x03},
+ {value: 0x0009, lo: 0xa0, hi: 0xa0},
+ {value: 0x00e6, lo: 0xb5, hi: 0xbc},
+ {value: 0x00dc, lo: 0xbf, hi: 0xbf},
+ // Block 0x3a, offset 0x3b
+ {value: 0x7700, lo: 0x0e},
+ {value: 0x8800, lo: 0x85, hi: 0x85},
+ {value: 0x1100, lo: 0x86, hi: 0x87},
+ {value: 0x1100, lo: 0x88, hi: 0x89},
+ {value: 0x1100, lo: 0x8a, hi: 0x8b},
+ {value: 0x1100, lo: 0x8c, hi: 0x8d},
+ {value: 0x1100, lo: 0x8e, hi: 0x8e},
+ {value: 0x8800, lo: 0x91, hi: 0x91},
+ {value: 0x1100, lo: 0x92, hi: 0x92},
+ {value: 0x0007, lo: 0xb4, hi: 0xb4},
+ {value: 0x6600, lo: 0xb5, hi: 0xb5},
+ {value: 0x8800, lo: 0xba, hi: 0xba},
+ {value: 0x1100, lo: 0xbb, hi: 0xbc},
+ {value: 0x1100, lo: 0xbd, hi: 0xbe},
+ {value: 0x8800, lo: 0xbf, hi: 0xbf},
+ // Block 0x3b, offset 0x3c
+ {value: 0x0000, lo: 0x07},
+ {value: 0x1100, lo: 0x80, hi: 0x81},
+ {value: 0x8800, lo: 0x82, hi: 0x82},
+ {value: 0x1100, lo: 0x83, hi: 0x83},
+ {value: 0x0009, lo: 0x84, hi: 0x84},
+ {value: 0x00e6, lo: 0xab, hi: 0xab},
+ {value: 0x00dc, lo: 0xac, hi: 0xac},
+ {value: 0x00e6, lo: 0xad, hi: 0xb3},
+ // Block 0x3c, offset 0x3d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0009, lo: 0xaa, hi: 0xaa},
+ // Block 0x3d, offset 0x3e
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0007, lo: 0xa6, hi: 0xa6},
+ {value: 0x0009, lo: 0xb2, hi: 0xb3},
+ // Block 0x3e, offset 0x3f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0007, lo: 0xb7, hi: 0xb7},
+ // Block 0x3f, offset 0x40
+ {value: 0x0000, lo: 0x08},
+ {value: 0x00e6, lo: 0x90, hi: 0x92},
+ {value: 0x0001, lo: 0x94, hi: 0x94},
+ {value: 0x00dc, lo: 0x95, hi: 0x99},
+ {value: 0x00e6, lo: 0x9a, hi: 0x9b},
+ {value: 0x00dc, lo: 0x9c, hi: 0x9f},
+ {value: 0x00e6, lo: 0xa0, hi: 0xa0},
+ {value: 0x0001, lo: 0xa2, hi: 0xa8},
+ {value: 0x00dc, lo: 0xad, hi: 0xad},
+ // Block 0x40, offset 0x41
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3000, lo: 0xac, hi: 0xae},
+ {value: 0x3000, lo: 0xb0, hi: 0xba},
+ {value: 0x3000, lo: 0xbc, hi: 0xbf},
+ // Block 0x41, offset 0x42
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3000, lo: 0x80, hi: 0x8d},
+ {value: 0x3000, lo: 0x8f, hi: 0xaa},
+ {value: 0x3000, lo: 0xb8, hi: 0xb8},
+ // Block 0x42, offset 0x43
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x9b, hi: 0xbf},
+ // Block 0x43, offset 0x44
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x00e6, lo: 0x80, hi: 0x81},
+ {value: 0x00dc, lo: 0x82, hi: 0x82},
+ {value: 0x00e6, lo: 0x83, hi: 0x89},
+ {value: 0x00dc, lo: 0x8a, hi: 0x8a},
+ {value: 0x00e6, lo: 0x8b, hi: 0x8c},
+ {value: 0x00ea, lo: 0x8d, hi: 0x8d},
+ {value: 0x00d6, lo: 0x8e, hi: 0x8e},
+ {value: 0x00dc, lo: 0x8f, hi: 0x8f},
+ {value: 0x00ca, lo: 0x90, hi: 0x90},
+ {value: 0x00e6, lo: 0x91, hi: 0xa6},
+ {value: 0x00e9, lo: 0xbc, hi: 0xbc},
+ {value: 0x00dc, lo: 0xbd, hi: 0xbd},
+ {value: 0x00e6, lo: 0xbe, hi: 0xbe},
+ {value: 0x00dc, lo: 0xbf, hi: 0xbf},
+ // Block 0x44, offset 0x45
+ {value: 0x0000, lo: 0x03},
+ {value: 0x1100, lo: 0x80, hi: 0xb5},
+ {value: 0x9900, lo: 0xb6, hi: 0xb7},
+ {value: 0x1100, lo: 0xb8, hi: 0xbf},
+ // Block 0x45, offset 0x46
+ {value: 0x0000, lo: 0x05},
+ {value: 0x1100, lo: 0x80, hi: 0x99},
+ {value: 0x9900, lo: 0x9a, hi: 0x9b},
+ {value: 0x1100, lo: 0x9c, hi: 0xa1},
+ {value: 0x9900, lo: 0xa2, hi: 0xa3},
+ {value: 0x1100, lo: 0xa4, hi: 0xbf},
+ // Block 0x46, offset 0x47
+ {value: 0x0000, lo: 0x07},
+ {value: 0x1100, lo: 0x80, hi: 0x99},
+ {value: 0x3000, lo: 0x9a, hi: 0x9a},
+ {value: 0x3100, lo: 0x9b, hi: 0x9b},
+ {value: 0x9900, lo: 0xa0, hi: 0xa1},
+ {value: 0x1100, lo: 0xa2, hi: 0xb7},
+ {value: 0x9900, lo: 0xb8, hi: 0xb9},
+ {value: 0x1100, lo: 0xba, hi: 0xbf},
+ // Block 0x47, offset 0x48
+ {value: 0x0000, lo: 0x03},
+ {value: 0x1100, lo: 0x80, hi: 0x8b},
+ {value: 0x9900, lo: 0x8c, hi: 0x8d},
+ {value: 0x1100, lo: 0x8e, hi: 0xb9},
+ // Block 0x48, offset 0x49
+ {value: 0x0000, lo: 0x08},
+ {value: 0x9900, lo: 0x80, hi: 0x91},
+ {value: 0x1100, lo: 0x92, hi: 0x95},
+ {value: 0x9900, lo: 0x98, hi: 0x99},
+ {value: 0x1100, lo: 0x9a, hi: 0x9d},
+ {value: 0x9900, lo: 0xa0, hi: 0xb1},
+ {value: 0x1100, lo: 0xb2, hi: 0xb7},
+ {value: 0x9900, lo: 0xb8, hi: 0xb9},
+ {value: 0x1100, lo: 0xba, hi: 0xbf},
+ // Block 0x49, offset 0x4a
+ {value: 0x0000, lo: 0x08},
+ {value: 0x1100, lo: 0x80, hi: 0xb4},
+ {value: 0x9900, lo: 0xb6, hi: 0xb6},
+ {value: 0x1100, lo: 0xb7, hi: 0xba},
+ {value: 0x3300, lo: 0xbb, hi: 0xbb},
+ {value: 0x1100, lo: 0xbc, hi: 0xbc},
+ {value: 0x3000, lo: 0xbd, hi: 0xbd},
+ {value: 0x3300, lo: 0xbe, hi: 0xbe},
+ {value: 0x3800, lo: 0xbf, hi: 0xbf},
+ // Block 0x4a, offset 0x4b
+ {value: 0x0000, lo: 0x0a},
+ {value: 0x3300, lo: 0x80, hi: 0x81},
+ {value: 0x3000, lo: 0x82, hi: 0x8a},
+ {value: 0x3000, lo: 0x91, hi: 0x91},
+ {value: 0x3000, lo: 0x97, hi: 0x97},
+ {value: 0x3000, lo: 0xa4, hi: 0xa6},
+ {value: 0x3000, lo: 0xaf, hi: 0xaf},
+ {value: 0x3000, lo: 0xb3, hi: 0xb4},
+ {value: 0x3000, lo: 0xb6, hi: 0xb7},
+ {value: 0x3000, lo: 0xbc, hi: 0xbc},
+ {value: 0x3000, lo: 0xbe, hi: 0xbe},
+ // Block 0x4b, offset 0x4c
+ {value: 0x0000, lo: 0x05},
+ {value: 0x3000, lo: 0x87, hi: 0x89},
+ {value: 0x3000, lo: 0x97, hi: 0x97},
+ {value: 0x3000, lo: 0x9f, hi: 0x9f},
+ {value: 0x3000, lo: 0xb0, hi: 0xb1},
+ {value: 0x3000, lo: 0xb4, hi: 0xbf},
+ // Block 0x4c, offset 0x4d
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3000, lo: 0x80, hi: 0x8e},
+ {value: 0x3000, lo: 0x90, hi: 0x9c},
+ {value: 0x3000, lo: 0xa8, hi: 0xa8},
+ // Block 0x4d, offset 0x4e
+ {value: 0x0000, lo: 0x0d},
+ {value: 0x00e6, lo: 0x90, hi: 0x91},
+ {value: 0x0001, lo: 0x92, hi: 0x93},
+ {value: 0x00e6, lo: 0x94, hi: 0x97},
+ {value: 0x0001, lo: 0x98, hi: 0x9a},
+ {value: 0x00e6, lo: 0x9b, hi: 0x9c},
+ {value: 0x00e6, lo: 0xa1, hi: 0xa1},
+ {value: 0x0001, lo: 0xa5, hi: 0xa6},
+ {value: 0x00e6, lo: 0xa7, hi: 0xa7},
+ {value: 0x00dc, lo: 0xa8, hi: 0xa8},
+ {value: 0x00e6, lo: 0xa9, hi: 0xa9},
+ {value: 0x0001, lo: 0xaa, hi: 0xab},
+ {value: 0x00dc, lo: 0xac, hi: 0xaf},
+ {value: 0x00e6, lo: 0xb0, hi: 0xb0},
+ // Block 0x4e, offset 0x4f
+ {value: 0x0000, lo: 0x0e},
+ {value: 0x3000, lo: 0x80, hi: 0x83},
+ {value: 0x3000, lo: 0x85, hi: 0x87},
+ {value: 0x3000, lo: 0x89, hi: 0x93},
+ {value: 0x3000, lo: 0x95, hi: 0x96},
+ {value: 0x3000, lo: 0x99, hi: 0x9d},
+ {value: 0x3000, lo: 0xa0, hi: 0xa2},
+ {value: 0x3000, lo: 0xa4, hi: 0xa4},
+ {value: 0x3300, lo: 0xa6, hi: 0xa6},
+ {value: 0x3000, lo: 0xa8, hi: 0xa8},
+ {value: 0x3300, lo: 0xaa, hi: 0xab},
+ {value: 0x3000, lo: 0xac, hi: 0xad},
+ {value: 0x3000, lo: 0xaf, hi: 0xb1},
+ {value: 0x3000, lo: 0xb3, hi: 0xb9},
+ {value: 0x3000, lo: 0xbb, hi: 0xbf},
+ // Block 0x4f, offset 0x50
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3000, lo: 0x80, hi: 0x80},
+ {value: 0x3000, lo: 0x85, hi: 0x89},
+ {value: 0x3000, lo: 0x90, hi: 0xbf},
+ // Block 0x50, offset 0x51
+ {value: 0x0000, lo: 0x06},
+ {value: 0x3000, lo: 0x89, hi: 0x89},
+ {value: 0x8800, lo: 0x90, hi: 0x90},
+ {value: 0x8800, lo: 0x92, hi: 0x92},
+ {value: 0x8800, lo: 0x94, hi: 0x94},
+ {value: 0x1100, lo: 0x9a, hi: 0x9b},
+ {value: 0x1100, lo: 0xae, hi: 0xae},
+ // Block 0x51, offset 0x52
+ {value: 0x0000, lo: 0x04},
+ {value: 0x1100, lo: 0x8d, hi: 0x8f},
+ {value: 0x8800, lo: 0x90, hi: 0x90},
+ {value: 0x8800, lo: 0x92, hi: 0x92},
+ {value: 0x8800, lo: 0x94, hi: 0x94},
+ // Block 0x52, offset 0x53
+ {value: 0x7700, lo: 0x0e},
+ {value: 0x8800, lo: 0x83, hi: 0x83},
+ {value: 0x1100, lo: 0x84, hi: 0x84},
+ {value: 0x8800, lo: 0x88, hi: 0x88},
+ {value: 0x1100, lo: 0x89, hi: 0x89},
+ {value: 0x8800, lo: 0x8b, hi: 0x8b},
+ {value: 0x1100, lo: 0x8c, hi: 0x8c},
+ {value: 0x8800, lo: 0xa3, hi: 0xa3},
+ {value: 0x1100, lo: 0xa4, hi: 0xa5},
+ {value: 0x1100, lo: 0xa6, hi: 0xa6},
+ {value: 0x3000, lo: 0xac, hi: 0xac},
+ {value: 0x3000, lo: 0xad, hi: 0xad},
+ {value: 0x3000, lo: 0xaf, hi: 0xaf},
+ {value: 0x3000, lo: 0xb0, hi: 0xb0},
+ {value: 0x8800, lo: 0xbc, hi: 0xbc},
+ // Block 0x53, offset 0x54
+ {value: 0x0000, lo: 0x0b},
+ {value: 0x1100, lo: 0x80, hi: 0x81},
+ {value: 0x8800, lo: 0x82, hi: 0x83},
+ {value: 0x1100, lo: 0x84, hi: 0x85},
+ {value: 0x8800, lo: 0x86, hi: 0x87},
+ {value: 0x1100, lo: 0x88, hi: 0x89},
+ {value: 0x8800, lo: 0x91, hi: 0x92},
+ {value: 0x8800, lo: 0xa2, hi: 0xa2},
+ {value: 0x8800, lo: 0xa8, hi: 0xa9},
+ {value: 0x8800, lo: 0xab, hi: 0xab},
+ {value: 0x1100, lo: 0xac, hi: 0xaf},
+ {value: 0x8800, lo: 0xb2, hi: 0xb5},
+ // Block 0x54, offset 0x55
+ {value: 0x0000, lo: 0x02},
+ {value: 0x1100, lo: 0xa0, hi: 0xa3},
+ {value: 0x1100, lo: 0xaa, hi: 0xad},
+ // Block 0x55, offset 0x56
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3300, lo: 0xa9, hi: 0xaa},
+ // Block 0x56, offset 0x57
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0xa0, hi: 0xbf},
+ // Block 0x57, offset 0x58
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x80, hi: 0xbf},
+ // Block 0x58, offset 0x59
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x80, hi: 0xaa},
+ // Block 0x59, offset 0x5a
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x8c, hi: 0x8c},
+ // Block 0x5a, offset 0x5b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0xb4, hi: 0xb6},
+ // Block 0x5b, offset 0x5c
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3300, lo: 0x9c, hi: 0x9c},
+ // Block 0x5c, offset 0x5d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0xbc, hi: 0xbd},
+ // Block 0x5d, offset 0x5e
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00e6, lo: 0xaf, hi: 0xb1},
+ // Block 0x5e, offset 0x5f
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0xaf, hi: 0xaf},
+ {value: 0x0009, lo: 0xbf, hi: 0xbf},
+ // Block 0x5f, offset 0x60
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00e6, lo: 0xa0, hi: 0xbf},
+ // Block 0x60, offset 0x61
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x9f, hi: 0x9f},
+ // Block 0x61, offset 0x62
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0xb3, hi: 0xb3},
+ // Block 0x62, offset 0x63
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x80, hi: 0x95},
+ // Block 0x63, offset 0x64
+ {value: 0x0000, lo: 0x08},
+ {value: 0x3000, lo: 0x80, hi: 0x80},
+ {value: 0x00da, lo: 0xaa, hi: 0xaa},
+ {value: 0x00e4, lo: 0xab, hi: 0xab},
+ {value: 0x00e8, lo: 0xac, hi: 0xac},
+ {value: 0x00de, lo: 0xad, hi: 0xad},
+ {value: 0x00e0, lo: 0xae, hi: 0xaf},
+ {value: 0x3000, lo: 0xb6, hi: 0xb6},
+ {value: 0x3000, lo: 0xb8, hi: 0xba},
+ // Block 0x64, offset 0x65
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0xb1, hi: 0xbf},
+ // Block 0x65, offset 0x66
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x8e},
+ {value: 0x3000, lo: 0x92, hi: 0x9f},
+ // Block 0x66, offset 0x67
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x9e},
+ {value: 0x3000, lo: 0xa0, hi: 0xbf},
+ // Block 0x67, offset 0x68
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x87},
+ {value: 0x3000, lo: 0x90, hi: 0xbe},
+ // Block 0x68, offset 0x69
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x80, hi: 0xbe},
+ // Block 0x69, offset 0x6a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x00e6, lo: 0xaf, hi: 0xaf},
+ {value: 0x00e6, lo: 0xbc, hi: 0xbd},
+ // Block 0x6a, offset 0x6b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00e6, lo: 0xb0, hi: 0xb1},
+ // Block 0x6b, offset 0x6c
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0xb0, hi: 0xb0},
+ // Block 0x6c, offset 0x6d
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0009, lo: 0x86, hi: 0x86},
+ // Block 0x6d, offset 0x6e
+ {value: 0x0000, lo: 0x02},
+ {value: 0x0009, lo: 0x84, hi: 0x84},
+ {value: 0x00e6, lo: 0xa0, hi: 0xb1},
+ // Block 0x6e, offset 0x6f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00dc, lo: 0xab, hi: 0xad},
+ // Block 0x6f, offset 0x70
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0009, lo: 0x93, hi: 0x93},
+ // Block 0x70, offset 0x71
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0007, lo: 0xb3, hi: 0xb3},
+ // Block 0x71, offset 0x72
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0009, lo: 0x80, hi: 0x80},
+ // Block 0x72, offset 0x73
+ {value: 0x0000, lo: 0x05},
+ {value: 0x00e6, lo: 0xb0, hi: 0xb0},
+ {value: 0x00e6, lo: 0xb2, hi: 0xb3},
+ {value: 0x00dc, lo: 0xb4, hi: 0xb4},
+ {value: 0x00e6, lo: 0xb7, hi: 0xb8},
+ {value: 0x00e6, lo: 0xbe, hi: 0xbf},
+ // Block 0x73, offset 0x74
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00e6, lo: 0x81, hi: 0x81},
+ // Block 0x74, offset 0x75
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0009, lo: 0xad, hi: 0xad},
+ // Block 0x75, offset 0x76
+ {value: 0x0000, lo: 0x01},
+ {value: 0x1100, lo: 0x80, hi: 0xbf},
+ // Block 0x76, offset 0x77
+ {value: 0x0000, lo: 0x01},
+ {value: 0x1100, lo: 0x80, hi: 0xa3},
+ // Block 0x77, offset 0x78
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3300, lo: 0x80, hi: 0xbf},
+ // Block 0x78, offset 0x79
+ {value: 0x0000, lo: 0x09},
+ {value: 0x3300, lo: 0x80, hi: 0x8d},
+ {value: 0x3300, lo: 0x90, hi: 0x90},
+ {value: 0x3300, lo: 0x92, hi: 0x92},
+ {value: 0x3300, lo: 0x95, hi: 0x9e},
+ {value: 0x3300, lo: 0xa0, hi: 0xa0},
+ {value: 0x3300, lo: 0xa2, hi: 0xa2},
+ {value: 0x3300, lo: 0xa5, hi: 0xa6},
+ {value: 0x3300, lo: 0xaa, hi: 0xad},
+ {value: 0x3300, lo: 0xb0, hi: 0xbf},
+ // Block 0x79, offset 0x7a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3300, lo: 0x80, hi: 0xad},
+ {value: 0x3300, lo: 0xb0, hi: 0xbf},
+ // Block 0x7a, offset 0x7b
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3300, lo: 0x80, hi: 0x99},
+ // Block 0x7b, offset 0x7c
+ {value: 0x0000, lo: 0x09},
+ {value: 0x3000, lo: 0x80, hi: 0x86},
+ {value: 0x3000, lo: 0x93, hi: 0x97},
+ {value: 0x3300, lo: 0x9d, hi: 0x9d},
+ {value: 0x001a, lo: 0x9e, hi: 0x9e},
+ {value: 0x3300, lo: 0x9f, hi: 0x9f},
+ {value: 0x3000, lo: 0xa0, hi: 0xa9},
+ {value: 0x3300, lo: 0xaa, hi: 0xb6},
+ {value: 0x3300, lo: 0xb8, hi: 0xbc},
+ {value: 0x3300, lo: 0xbe, hi: 0xbe},
+ // Block 0x7c, offset 0x7d
+ {value: 0x0000, lo: 0x04},
+ {value: 0x3300, lo: 0x80, hi: 0x81},
+ {value: 0x3300, lo: 0x83, hi: 0x84},
+ {value: 0x3300, lo: 0x86, hi: 0x8e},
+ {value: 0x3000, lo: 0x8f, hi: 0xbf},
+ // Block 0x7d, offset 0x7e
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x80, hi: 0xb1},
+ // Block 0x7e, offset 0x7f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x93, hi: 0xbf},
+ // Block 0x7f, offset 0x80
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x80, hi: 0xbd},
+ // Block 0x80, offset 0x81
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x90, hi: 0xbf},
+ // Block 0x81, offset 0x82
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x8f},
+ {value: 0x3000, lo: 0x92, hi: 0xbf},
+ // Block 0x82, offset 0x83
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x87},
+ {value: 0x3000, lo: 0xb0, hi: 0xbc},
+ // Block 0x83, offset 0x84
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3000, lo: 0x90, hi: 0x99},
+ {value: 0x00e6, lo: 0xa0, hi: 0xa6},
+ {value: 0x3000, lo: 0xb0, hi: 0xbf},
+ // Block 0x84, offset 0x85
+ {value: 0x0000, lo: 0x07},
+ {value: 0x3000, lo: 0x80, hi: 0x84},
+ {value: 0x3000, lo: 0x87, hi: 0x92},
+ {value: 0x3000, lo: 0x94, hi: 0xa6},
+ {value: 0x3000, lo: 0xa8, hi: 0xab},
+ {value: 0x3000, lo: 0xb0, hi: 0xb2},
+ {value: 0x3000, lo: 0xb4, hi: 0xb4},
+ {value: 0x3000, lo: 0xb6, hi: 0xbf},
+ // Block 0x85, offset 0x86
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x80, hi: 0xbc},
+ // Block 0x86, offset 0x87
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x81, hi: 0xbf},
+ // Block 0x87, offset 0x88
+ {value: 0x0000, lo: 0x06},
+ {value: 0x3000, lo: 0x82, hi: 0x87},
+ {value: 0x3000, lo: 0x8a, hi: 0x8f},
+ {value: 0x3000, lo: 0x92, hi: 0x97},
+ {value: 0x3000, lo: 0x9a, hi: 0x9c},
+ {value: 0x3000, lo: 0xa0, hi: 0xa6},
+ {value: 0x3000, lo: 0xa8, hi: 0xae},
+ // Block 0x88, offset 0x89
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00dc, lo: 0xbd, hi: 0xbd},
+ // Block 0x89, offset 0x8a
+ {value: 0x0000, lo: 0x06},
+ {value: 0x00dc, lo: 0x8d, hi: 0x8d},
+ {value: 0x00e6, lo: 0x8f, hi: 0x8f},
+ {value: 0x00e6, lo: 0xb8, hi: 0xb8},
+ {value: 0x0001, lo: 0xb9, hi: 0xb9},
+ {value: 0x00dc, lo: 0xba, hi: 0xba},
+ {value: 0x0009, lo: 0xbf, hi: 0xbf},
+ // Block 0x8a, offset 0x8b
+ {value: 0x7700, lo: 0x07},
+ {value: 0x8800, lo: 0x99, hi: 0x99},
+ {value: 0x1100, lo: 0x9a, hi: 0x9b},
+ {value: 0x1100, lo: 0x9c, hi: 0x9c},
+ {value: 0x8800, lo: 0xa5, hi: 0xa5},
+ {value: 0x1100, lo: 0xab, hi: 0xab},
+ {value: 0x0009, lo: 0xb9, hi: 0xb9},
+ {value: 0x6607, lo: 0xba, hi: 0xba},
+ // Block 0x8b, offset 0x8c
+ {value: 0x0000, lo: 0x06},
+ {value: 0x3300, lo: 0x9e, hi: 0xa4},
+ {value: 0x00d8, lo: 0xa5, hi: 0xa6},
+ {value: 0x0001, lo: 0xa7, hi: 0xa9},
+ {value: 0x00e2, lo: 0xad, hi: 0xad},
+ {value: 0x00d8, lo: 0xae, hi: 0xb2},
+ {value: 0x00dc, lo: 0xbb, hi: 0xbf},
+ // Block 0x8c, offset 0x8d
+ {value: 0x0000, lo: 0x05},
+ {value: 0x00dc, lo: 0x80, hi: 0x82},
+ {value: 0x00e6, lo: 0x85, hi: 0x89},
+ {value: 0x00dc, lo: 0x8a, hi: 0x8b},
+ {value: 0x00e6, lo: 0xaa, hi: 0xad},
+ {value: 0x3300, lo: 0xbb, hi: 0xbf},
+ // Block 0x8d, offset 0x8e
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3300, lo: 0x80, hi: 0x80},
+ // Block 0x8e, offset 0x8f
+ {value: 0x0000, lo: 0x01},
+ {value: 0x00e6, lo: 0x82, hi: 0x84},
+ // Block 0x8f, offset 0x90
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x94},
+ {value: 0x3000, lo: 0x96, hi: 0xbf},
+ // Block 0x90, offset 0x91
+ {value: 0x0000, lo: 0x08},
+ {value: 0x3000, lo: 0x80, hi: 0x9c},
+ {value: 0x3000, lo: 0x9e, hi: 0x9f},
+ {value: 0x3000, lo: 0xa2, hi: 0xa2},
+ {value: 0x3000, lo: 0xa5, hi: 0xa6},
+ {value: 0x3000, lo: 0xa9, hi: 0xac},
+ {value: 0x3000, lo: 0xae, hi: 0xb9},
+ {value: 0x3000, lo: 0xbb, hi: 0xbb},
+ {value: 0x3000, lo: 0xbd, hi: 0xbf},
+ // Block 0x91, offset 0x92
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x83},
+ {value: 0x3000, lo: 0x85, hi: 0xbf},
+ // Block 0x92, offset 0x93
+ {value: 0x0000, lo: 0x06},
+ {value: 0x3000, lo: 0x80, hi: 0x85},
+ {value: 0x3000, lo: 0x87, hi: 0x8a},
+ {value: 0x3000, lo: 0x8d, hi: 0x94},
+ {value: 0x3000, lo: 0x96, hi: 0x9c},
+ {value: 0x3000, lo: 0x9e, hi: 0xb9},
+ {value: 0x3000, lo: 0xbb, hi: 0xbe},
+ // Block 0x93, offset 0x94
+ {value: 0x0000, lo: 0x04},
+ {value: 0x3000, lo: 0x80, hi: 0x84},
+ {value: 0x3000, lo: 0x86, hi: 0x86},
+ {value: 0x3000, lo: 0x8a, hi: 0x90},
+ {value: 0x3000, lo: 0x92, hi: 0xbf},
+ // Block 0x94, offset 0x95
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0xa5},
+ {value: 0x3000, lo: 0xa8, hi: 0xbf},
+ // Block 0x95, offset 0x96
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x8b},
+ {value: 0x3000, lo: 0x8e, hi: 0xbf},
+ // Block 0x96, offset 0x97
+ {value: 0x0000, lo: 0x03},
+ {value: 0x3000, lo: 0x80, hi: 0x8a},
+ {value: 0x3000, lo: 0x90, hi: 0xae},
+ {value: 0x3000, lo: 0xb0, hi: 0xbf},
+ // Block 0x97, offset 0x98
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x80, hi: 0x8f},
+ // Block 0x98, offset 0x99
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3000, lo: 0x90, hi: 0x90},
+ // Block 0x99, offset 0x9a
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x82},
+ {value: 0x3000, lo: 0x90, hi: 0xba},
+ // Block 0x9a, offset 0x9b
+ {value: 0x0000, lo: 0x02},
+ {value: 0x3000, lo: 0x80, hi: 0x88},
+ {value: 0x3000, lo: 0x90, hi: 0x91},
+ // Block 0x9b, offset 0x9c
+ {value: 0x0000, lo: 0x01},
+ {value: 0x3300, lo: 0x80, hi: 0x9d},
}
// charInfoLookup: 1152 bytes
@@ -6498,83 +6689,83 @@ var charInfoLookup = [1152]uint8{
// Block 0x1, offset 0x40
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
- 0x0c2: 0x03, 0x0c3: 0x04, 0x0c4: 0x05, 0x0c5: 0x06, 0x0c6: 0x07, 0x0c7: 0x08,
- 0x0c8: 0x09, 0x0ca: 0x0a, 0x0cb: 0x0b, 0x0cc: 0x0c, 0x0cd: 0x0d, 0x0ce: 0x0e, 0x0cf: 0x0f,
- 0x0d0: 0x10, 0x0d1: 0x11, 0x0d2: 0x12, 0x0d3: 0x13, 0x0d6: 0x14, 0x0d7: 0x15,
- 0x0d8: 0x16, 0x0d9: 0x17, 0x0db: 0x18, 0x0dc: 0x19, 0x0dd: 0x1a, 0x0df: 0x1b,
+ 0x0c2: 0x10, 0x0c3: 0x03, 0x0c4: 0x11, 0x0c5: 0x12, 0x0c6: 0x13, 0x0c7: 0x14,
+ 0x0c8: 0x15, 0x0ca: 0x16, 0x0cb: 0x17, 0x0cc: 0x04, 0x0cd: 0x05, 0x0ce: 0x06, 0x0cf: 0x18,
+ 0x0d0: 0x07, 0x0d1: 0x19, 0x0d2: 0x1a, 0x0d3: 0x1b, 0x0d6: 0x08, 0x0d7: 0x1c,
+ 0x0d8: 0x1d, 0x0d9: 0x09, 0x0db: 0x1e, 0x0dc: 0x1f, 0x0dd: 0x20, 0x0df: 0x21,
0x0e0: 0x04, 0x0e1: 0x05, 0x0e2: 0x06, 0x0e3: 0x07,
0x0ea: 0x08, 0x0eb: 0x09, 0x0ec: 0x09, 0x0ed: 0x0a, 0x0ef: 0x0b,
0x0f0: 0x11,
// Block 0x4, offset 0x100
- 0x120: 0x1c, 0x121: 0x1d, 0x124: 0x1e, 0x125: 0x1f, 0x126: 0x20, 0x127: 0x21,
- 0x128: 0x22, 0x129: 0x23, 0x12a: 0x24, 0x12b: 0x25, 0x12c: 0x20, 0x12d: 0x26, 0x12e: 0x27, 0x12f: 0x28,
- 0x131: 0x29, 0x132: 0x2a, 0x133: 0x2b, 0x134: 0x2c, 0x135: 0x28, 0x137: 0x2d,
- 0x138: 0x2e, 0x139: 0x2f, 0x13a: 0x30, 0x13b: 0x31, 0x13c: 0x32, 0x13d: 0x33, 0x13e: 0x34, 0x13f: 0x35,
+ 0x120: 0x22, 0x121: 0x23, 0x124: 0x24, 0x125: 0x25, 0x126: 0x26, 0x127: 0x27,
+ 0x128: 0x28, 0x129: 0x29, 0x12a: 0x2a, 0x12b: 0x2b, 0x12c: 0x26, 0x12d: 0x2c, 0x12e: 0x2d, 0x12f: 0x2e,
+ 0x131: 0x2f, 0x132: 0x30, 0x133: 0x31, 0x134: 0x32, 0x135: 0x2e, 0x137: 0x33,
+ 0x138: 0x34, 0x139: 0x35, 0x13a: 0x36, 0x13b: 0x37, 0x13c: 0x38, 0x13d: 0x39, 0x13e: 0x3a, 0x13f: 0x3b,
// Block 0x5, offset 0x140
- 0x140: 0x36, 0x142: 0x37, 0x143: 0x38, 0x145: 0x39, 0x146: 0x3a, 0x147: 0x3b,
- 0x14d: 0x3c,
- 0x15c: 0x3d, 0x15f: 0x3e,
- 0x162: 0x3f, 0x164: 0x40,
- 0x168: 0x41, 0x169: 0x42, 0x16c: 0x43, 0x16d: 0x44, 0x16e: 0x45, 0x16f: 0x46,
- 0x170: 0x47, 0x173: 0x48, 0x174: 0x49, 0x175: 0x4a, 0x176: 0x4b, 0x177: 0x4c,
- 0x178: 0x4d, 0x179: 0x4e, 0x17a: 0x4f, 0x17b: 0x50, 0x17c: 0x51, 0x17d: 0x52, 0x17e: 0x53, 0x17f: 0x54,
+ 0x140: 0x3c, 0x142: 0x3d, 0x143: 0x3e, 0x144: 0x3f, 0x145: 0x40, 0x146: 0x41, 0x147: 0x42,
+ 0x14d: 0x43,
+ 0x15c: 0x44, 0x15f: 0x45,
+ 0x162: 0x46, 0x164: 0x47,
+ 0x168: 0x48, 0x169: 0x49, 0x16c: 0x4a, 0x16d: 0x4b, 0x16e: 0x4c, 0x16f: 0x4d,
+ 0x170: 0x4e, 0x173: 0x4f, 0x174: 0x50, 0x175: 0x51, 0x176: 0x52, 0x177: 0x53,
+ 0x178: 0x54, 0x179: 0x55, 0x17a: 0x56, 0x17b: 0x57, 0x17c: 0x58, 0x17d: 0x0a, 0x17e: 0x59, 0x17f: 0x0b,
// Block 0x6, offset 0x180
- 0x180: 0x55, 0x181: 0x56, 0x182: 0x57, 0x183: 0x58, 0x184: 0x59, 0x185: 0x5a, 0x186: 0x5b, 0x187: 0x5c,
- 0x188: 0x5d, 0x189: 0x5e, 0x18a: 0x5f, 0x18b: 0x60, 0x18c: 0x61,
- 0x191: 0x62, 0x192: 0x63, 0x193: 0x64,
- 0x1a8: 0x65, 0x1a9: 0x66, 0x1ab: 0x67,
- 0x1b1: 0x68, 0x1b3: 0x69, 0x1b5: 0x6a, 0x1b7: 0x6b,
- 0x1ba: 0x6c, 0x1bb: 0x6d, 0x1bc: 0x63, 0x1bd: 0x63, 0x1be: 0x63, 0x1bf: 0x6e,
+ 0x180: 0x5a, 0x181: 0x5b, 0x182: 0x5c, 0x183: 0x5d, 0x184: 0x5e, 0x185: 0x5f, 0x186: 0x60, 0x187: 0x61,
+ 0x188: 0x62, 0x189: 0x0c, 0x18a: 0x63, 0x18b: 0x64, 0x18c: 0x65,
+ 0x191: 0x66, 0x192: 0x67, 0x193: 0x68,
+ 0x1a8: 0x69, 0x1a9: 0x6a, 0x1ab: 0x6b,
+ 0x1b1: 0x6c, 0x1b3: 0x6d, 0x1b5: 0x6e, 0x1b7: 0x6f,
+ 0x1ba: 0x70, 0x1bb: 0x71, 0x1bc: 0x67, 0x1bd: 0x67, 0x1be: 0x67, 0x1bf: 0x72,
// Block 0x7, offset 0x1c0
- 0x1c0: 0x6f, 0x1c1: 0x70, 0x1c2: 0x71, 0x1c3: 0x72, 0x1c4: 0x73, 0x1c5: 0x63, 0x1c6: 0x74,
- 0x1c8: 0x75, 0x1c9: 0x76, 0x1ca: 0x63, 0x1cb: 0x77, 0x1cc: 0x63, 0x1cd: 0x63, 0x1ce: 0x63, 0x1cf: 0x63,
+ 0x1c0: 0x73, 0x1c1: 0x0d, 0x1c2: 0x0e, 0x1c3: 0x0f, 0x1c4: 0x74, 0x1c5: 0x67, 0x1c6: 0x75,
+ 0x1c8: 0x76, 0x1c9: 0x77, 0x1ca: 0x67, 0x1cb: 0x78, 0x1cc: 0x67, 0x1cd: 0x67, 0x1ce: 0x67, 0x1cf: 0x67,
// Block 0x8, offset 0x200
- 0x219: 0x78, 0x21b: 0x79, 0x21d: 0x7a,
- 0x220: 0x7b, 0x223: 0x7c, 0x224: 0x7d, 0x225: 0x7e, 0x226: 0x7f, 0x227: 0x80,
- 0x22a: 0x81, 0x22b: 0x82, 0x22f: 0x83,
- 0x230: 0x84, 0x231: 0x84, 0x232: 0x84, 0x233: 0x84, 0x234: 0x84, 0x235: 0x84, 0x236: 0x84, 0x237: 0x84,
- 0x238: 0x84, 0x239: 0x84, 0x23a: 0x84, 0x23b: 0x84, 0x23c: 0x84, 0x23d: 0x84, 0x23e: 0x84, 0x23f: 0x84,
+ 0x219: 0x79, 0x21b: 0x7a, 0x21d: 0x7b,
+ 0x220: 0x7c, 0x223: 0x7d, 0x224: 0x7e, 0x225: 0x7f, 0x226: 0x80, 0x227: 0x81,
+ 0x22a: 0x82, 0x22b: 0x83, 0x22f: 0x84,
+ 0x230: 0x85, 0x231: 0x85, 0x232: 0x85, 0x233: 0x85, 0x234: 0x85, 0x235: 0x85, 0x236: 0x85, 0x237: 0x85,
+ 0x238: 0x85, 0x239: 0x85, 0x23a: 0x85, 0x23b: 0x85, 0x23c: 0x85, 0x23d: 0x85, 0x23e: 0x85, 0x23f: 0x85,
// Block 0x9, offset 0x240
- 0x240: 0x84, 0x241: 0x84, 0x242: 0x84, 0x243: 0x84, 0x244: 0x84, 0x245: 0x84, 0x246: 0x84, 0x247: 0x84,
- 0x248: 0x84, 0x249: 0x84, 0x24a: 0x84, 0x24b: 0x84, 0x24c: 0x84, 0x24d: 0x84, 0x24e: 0x84, 0x24f: 0x84,
- 0x250: 0x84, 0x251: 0x84, 0x252: 0x84, 0x253: 0x84, 0x254: 0x84, 0x255: 0x84, 0x256: 0x84, 0x257: 0x84,
- 0x258: 0x84, 0x259: 0x84, 0x25a: 0x84, 0x25b: 0x84, 0x25c: 0x84, 0x25d: 0x84, 0x25e: 0x84, 0x25f: 0x84,
- 0x260: 0x84, 0x261: 0x84, 0x262: 0x84, 0x263: 0x84, 0x264: 0x84, 0x265: 0x84, 0x266: 0x84, 0x267: 0x84,
- 0x268: 0x84, 0x269: 0x84, 0x26a: 0x84, 0x26b: 0x84, 0x26c: 0x84, 0x26d: 0x84, 0x26e: 0x84, 0x26f: 0x84,
- 0x270: 0x84, 0x271: 0x84, 0x272: 0x84, 0x273: 0x84, 0x274: 0x84, 0x275: 0x84, 0x276: 0x84, 0x277: 0x84,
- 0x278: 0x84, 0x279: 0x84, 0x27a: 0x84, 0x27b: 0x84, 0x27c: 0x84, 0x27d: 0x84, 0x27e: 0x84, 0x27f: 0x84,
+ 0x240: 0x85, 0x241: 0x85, 0x242: 0x85, 0x243: 0x85, 0x244: 0x85, 0x245: 0x85, 0x246: 0x85, 0x247: 0x85,
+ 0x248: 0x85, 0x249: 0x85, 0x24a: 0x85, 0x24b: 0x85, 0x24c: 0x85, 0x24d: 0x85, 0x24e: 0x85, 0x24f: 0x85,
+ 0x250: 0x85, 0x251: 0x85, 0x252: 0x85, 0x253: 0x85, 0x254: 0x85, 0x255: 0x85, 0x256: 0x85, 0x257: 0x85,
+ 0x258: 0x85, 0x259: 0x85, 0x25a: 0x85, 0x25b: 0x85, 0x25c: 0x85, 0x25d: 0x85, 0x25e: 0x85, 0x25f: 0x85,
+ 0x260: 0x85, 0x261: 0x85, 0x262: 0x85, 0x263: 0x85, 0x264: 0x85, 0x265: 0x85, 0x266: 0x85, 0x267: 0x85,
+ 0x268: 0x85, 0x269: 0x85, 0x26a: 0x85, 0x26b: 0x85, 0x26c: 0x85, 0x26d: 0x85, 0x26e: 0x85, 0x26f: 0x85,
+ 0x270: 0x85, 0x271: 0x85, 0x272: 0x85, 0x273: 0x85, 0x274: 0x85, 0x275: 0x85, 0x276: 0x85, 0x277: 0x85,
+ 0x278: 0x85, 0x279: 0x85, 0x27a: 0x85, 0x27b: 0x85, 0x27c: 0x85, 0x27d: 0x85, 0x27e: 0x85, 0x27f: 0x85,
// Block 0xa, offset 0x280
- 0x280: 0x84, 0x281: 0x84, 0x282: 0x84, 0x283: 0x84, 0x284: 0x84, 0x285: 0x84, 0x286: 0x84, 0x287: 0x84,
- 0x288: 0x84, 0x289: 0x84, 0x28a: 0x84, 0x28b: 0x84, 0x28c: 0x84, 0x28d: 0x84, 0x28e: 0x84, 0x28f: 0x84,
- 0x290: 0x84, 0x291: 0x84, 0x292: 0x84, 0x293: 0x84, 0x294: 0x84, 0x295: 0x84, 0x296: 0x84, 0x297: 0x84,
- 0x298: 0x84, 0x299: 0x84, 0x29a: 0x84, 0x29b: 0x84, 0x29c: 0x84, 0x29d: 0x84, 0x29e: 0x85,
+ 0x280: 0x85, 0x281: 0x85, 0x282: 0x85, 0x283: 0x85, 0x284: 0x85, 0x285: 0x85, 0x286: 0x85, 0x287: 0x85,
+ 0x288: 0x85, 0x289: 0x85, 0x28a: 0x85, 0x28b: 0x85, 0x28c: 0x85, 0x28d: 0x85, 0x28e: 0x85, 0x28f: 0x85,
+ 0x290: 0x85, 0x291: 0x85, 0x292: 0x85, 0x293: 0x85, 0x294: 0x85, 0x295: 0x85, 0x296: 0x85, 0x297: 0x85,
+ 0x298: 0x85, 0x299: 0x85, 0x29a: 0x85, 0x29b: 0x85, 0x29c: 0x85, 0x29d: 0x85, 0x29e: 0x86,
// Block 0xb, offset 0x2c0
- 0x2e4: 0x86, 0x2e5: 0x86, 0x2e6: 0x86, 0x2e7: 0x86,
- 0x2e8: 0x87, 0x2e9: 0x88, 0x2ea: 0x86, 0x2eb: 0x89, 0x2ec: 0x8a, 0x2ed: 0x8b, 0x2ee: 0x8c, 0x2ef: 0x8d,
- 0x2f0: 0x63, 0x2f1: 0x63, 0x2f2: 0x63, 0x2f3: 0x63, 0x2f4: 0x8e, 0x2f5: 0x8f, 0x2f6: 0x90, 0x2f7: 0x91,
- 0x2f8: 0x92, 0x2f9: 0x93, 0x2fa: 0x63, 0x2fb: 0x94, 0x2fc: 0x95, 0x2fd: 0x63, 0x2fe: 0x77, 0x2ff: 0x96,
+ 0x2e4: 0x87, 0x2e5: 0x87, 0x2e6: 0x87, 0x2e7: 0x87,
+ 0x2e8: 0x88, 0x2e9: 0x89, 0x2ea: 0x87, 0x2eb: 0x8a, 0x2ec: 0x8b, 0x2ed: 0x8c, 0x2ee: 0x8d, 0x2ef: 0x8e,
+ 0x2f0: 0x67, 0x2f1: 0x67, 0x2f2: 0x67, 0x2f3: 0x67, 0x2f4: 0x8f, 0x2f5: 0x90, 0x2f6: 0x91, 0x2f7: 0x92,
+ 0x2f8: 0x93, 0x2f9: 0x94, 0x2fa: 0x67, 0x2fb: 0x95, 0x2fc: 0x96, 0x2fd: 0x67, 0x2fe: 0x78, 0x2ff: 0x97,
// Block 0xc, offset 0x300
- 0x307: 0x97,
- 0x328: 0x98,
+ 0x307: 0x98,
+ 0x328: 0x99,
// Block 0xd, offset 0x340
- 0x341: 0x7b, 0x342: 0x99,
+ 0x341: 0x7c, 0x342: 0x9a,
// Block 0xe, offset 0x380
- 0x385: 0x9a, 0x386: 0x9b, 0x387: 0x9c,
- 0x389: 0x9d,
- 0x390: 0x63, 0x391: 0x9e, 0x392: 0x9f, 0x393: 0xa0, 0x394: 0xa1, 0x395: 0xa2, 0x396: 0x63, 0x397: 0x63,
- 0x398: 0x63, 0x399: 0x63, 0x39a: 0xa3, 0x39b: 0x63, 0x39c: 0x63, 0x39d: 0x63, 0x39e: 0x63, 0x39f: 0xa4,
+ 0x385: 0x9b, 0x386: 0x9c, 0x387: 0x9d,
+ 0x389: 0x9e,
+ 0x390: 0x67, 0x391: 0x9f, 0x392: 0xa0, 0x393: 0xa1, 0x394: 0xa2, 0x395: 0xa3, 0x396: 0x67, 0x397: 0x67,
+ 0x398: 0x67, 0x399: 0x67, 0x39a: 0xa4, 0x39b: 0x67, 0x39c: 0x67, 0x39d: 0x67, 0x39e: 0x67, 0x39f: 0xa5,
// Block 0xf, offset 0x3c0
- 0x3c4: 0xa5, 0x3c5: 0xa6, 0x3c6: 0xa7,
- 0x3c8: 0xa8, 0x3c9: 0xa9,
+ 0x3c4: 0xa6, 0x3c5: 0xa7, 0x3c6: 0xa8,
+ 0x3c8: 0xa9, 0x3c9: 0xaa,
// Block 0x10, offset 0x400
- 0x420: 0x86, 0x421: 0x86, 0x422: 0x86, 0x423: 0x86, 0x424: 0x86, 0x425: 0x86, 0x426: 0x86, 0x427: 0x86,
- 0x428: 0xaa,
+ 0x420: 0x87, 0x421: 0x87, 0x422: 0x87, 0x423: 0x87, 0x424: 0x87, 0x425: 0x87, 0x426: 0x87, 0x427: 0x87,
+ 0x428: 0xab,
// Block 0x11, offset 0x440
0x450: 0x0c, 0x451: 0x0d,
0x45d: 0x0e, 0x45f: 0x0f,
0x46f: 0x10,
}
-var charInfoTrie = trie{charInfoLookup[:], charInfoValues[:]}
+var charInfoTrie = trie{charInfoLookup[:], charInfoValues[:], charInfoSparseValues[:], charInfoSparseOffset[:], 16}
-// Total size of tables: 78KB (80234 bytes)
+// Total size of tables: 48KB (48756 bytes)
diff --git a/libgo/go/exp/norm/trie.go b/libgo/go/exp/norm/trie.go
index 6b654018757..93cb9c33903 100644
--- a/libgo/go/exp/norm/trie.go
+++ b/libgo/go/exp/norm/trie.go
@@ -4,9 +4,44 @@
package norm
+type valueRange struct {
+ value uint16 // header: value:stride
+ lo, hi byte // header: lo:n
+}
+
type trie struct {
- index []uint8
- values []uint16
+ index []uint8
+ values []uint16
+ sparse []valueRange
+ sparseOffset []uint16
+ cutoff uint8 // indices >= cutoff are sparse
+}
+
+// lookupValue determines the type of block n and looks up the value for b.
+// For n < t.cutoff, the block is a simple lookup table. Otherwise, the block
+// is a list of ranges with an accompanying value. Given a matching range r,
+// the value for b is by r.value + (b - r.lo) * stride.
+func (t *trie) lookupValue(n uint8, b byte) uint16 {
+ if n < t.cutoff {
+ return t.values[uint16(n)<<6+uint16(b&maskx)]
+ }
+ offset := t.sparseOffset[n-t.cutoff]
+ header := t.sparse[offset]
+ lo := offset + 1
+ hi := lo + uint16(header.lo)
+ for lo < hi {
+ m := lo + (hi-lo)/2
+ r := t.sparse[m]
+ if r.lo <= b && b <= r.hi {
+ return r.value + uint16(b-r.lo)*header.value
+ }
+ if b < r.lo {
+ hi = m
+ } else {
+ lo = m + 1
+ }
+ }
+ return 0
}
const (
@@ -44,8 +79,7 @@ func (t *trie) lookup(s []byte) (v uint16, sz int) {
if c1 < tx || t2 <= c1 {
return 0, 1
}
- o := uint16(i)<<6 + uint16(c1)&maskx
- return t.values[o], 2
+ return t.lookupValue(i, c1), 2
case c0 < t4:
if len(s) < 3 {
return 0, 0
@@ -61,8 +95,7 @@ func (t *trie) lookup(s []byte) (v uint16, sz int) {
if c2 < tx || t2 <= c2 {
return 0, 2
}
- o = uint16(i)<<6 + uint16(c2)&maskx
- return t.values[o], 3
+ return t.lookupValue(i, c2), 3
case c0 < t5:
if len(s) < 4 {
return 0, 0
@@ -84,18 +117,7 @@ func (t *trie) lookup(s []byte) (v uint16, sz int) {
if c3 < tx || t2 <= c3 {
return 0, 3
}
- o = uint16(i)<<6 + uint16(c3)&maskx
- return t.values[o], 4
- case c0 < t6:
- if len(s) < 5 {
- return 0, 0
- }
- return 0, 5
- case c0 < te:
- if len(s) < 6 {
- return 0, 0
- }
- return 0, 6
+ return t.lookupValue(i, c3), 4
}
// Illegal rune
return 0, 1
@@ -120,8 +142,7 @@ func (t *trie) lookupString(s string) (v uint16, sz int) {
if c1 < tx || t2 <= c1 {
return 0, 1
}
- o := uint16(i)<<6 + uint16(c1)&maskx
- return t.values[o], 2
+ return t.lookupValue(i, c1), 2
case c0 < t4:
if len(s) < 3 {
return 0, 0
@@ -137,8 +158,7 @@ func (t *trie) lookupString(s string) (v uint16, sz int) {
if c2 < tx || t2 <= c2 {
return 0, 2
}
- o = uint16(i)<<6 + uint16(c2)&maskx
- return t.values[o], 3
+ return t.lookupValue(i, c2), 3
case c0 < t5:
if len(s) < 4 {
return 0, 0
@@ -160,18 +180,7 @@ func (t *trie) lookupString(s string) (v uint16, sz int) {
if c3 < tx || t2 <= c3 {
return 0, 3
}
- o = uint16(i)<<6 + uint16(c3)&maskx
- return t.values[o], 4
- case c0 < t6:
- if len(s) < 5 {
- return 0, 0
- }
- return 0, 5
- case c0 < te:
- if len(s) < 6 {
- return 0, 0
- }
- return 0, 6
+ return t.lookupValue(i, c3), 4
}
// Illegal rune
return 0, 1
@@ -188,19 +197,16 @@ func (t *trie) lookupUnsafe(s []byte) uint16 {
return 0
}
i := t.index[c0]
- o := uint16(i)<<6 + uint16(s[1])&maskx
if c0 < t3 {
- return t.values[o]
+ return t.lookupValue(i, s[1])
}
- i = t.index[o]
- o = uint16(i)<<6 + uint16(s[2])&maskx
+ i = t.index[uint16(i)<<6+uint16(s[1])&maskx]
if c0 < t4 {
- return t.values[o]
+ return t.lookupValue(i, s[2])
}
- i = t.index[o]
- o = uint16(i)<<6 + uint16(s[3])&maskx
+ i = t.index[uint16(i)<<6+uint16(s[2])&maskx]
if c0 < t5 {
- return t.values[o]
+ return t.lookupValue(i, s[3])
}
return 0
}
@@ -216,19 +222,16 @@ func (t *trie) lookupStringUnsafe(s string) uint16 {
return 0
}
i := t.index[c0]
- o := uint16(i)<<6 + uint16(s[1])&maskx
if c0 < t3 {
- return t.values[o]
+ return t.lookupValue(i, s[1])
}
- i = t.index[o]
- o = uint16(i)<<6 + uint16(s[2])&maskx
+ i = t.index[uint16(i)<<6+uint16(s[1])&maskx]
if c0 < t4 {
- return t.values[o]
+ return t.lookupValue(i, s[2])
}
- i = t.index[o]
- o = uint16(i)<<6 + uint16(s[3])&maskx
+ i = t.index[uint16(i)<<6+uint16(s[2])&maskx]
if c0 < t5 {
- return t.values[o]
+ return t.lookupValue(i, s[3])
}
return 0
}
diff --git a/libgo/go/exp/norm/trie_test.go b/libgo/go/exp/norm/trie_test.go
index ad87d972b02..5649fb7eea7 100644
--- a/libgo/go/exp/norm/trie_test.go
+++ b/libgo/go/exp/norm/trie_test.go
@@ -8,6 +8,41 @@ import (
// Test data is located in triedata_test.go; generated by maketesttables.
var testdata = testdataTrie
+type rangeTest struct {
+ block uint8
+ lookup byte
+ result uint16
+ table []valueRange
+ offsets []uint16
+}
+
+var range1Off = []uint16{0, 2}
+var range1 = []valueRange{
+ {0, 1, 0},
+ {1, 0x80, 0x80},
+ {0, 2, 0},
+ {1, 0x80, 0x80},
+ {9, 0xff, 0xff},
+}
+
+var rangeTests = []rangeTest{
+ {10, 0x80, 1, range1, range1Off},
+ {10, 0x00, 0, range1, range1Off},
+ {11, 0x80, 1, range1, range1Off},
+ {11, 0xff, 9, range1, range1Off},
+ {11, 0x00, 0, range1, range1Off},
+}
+
+func TestLookupSparse(t *testing.T) {
+ for i, test := range rangeTests {
+ n := trie{sparse: test.table, sparseOffset: test.offsets, cutoff: 10}
+ v := n.lookupValue(test.block, test.lookup)
+ if v != test.result {
+ t.Errorf("LookupSparse:%d: found %X; want %X", i, v, test.result)
+ }
+ }
+}
+
// Test cases for illegal runes.
type trietest struct {
size int
@@ -32,8 +67,10 @@ var tests = []trietest{
{0, []byte{t2}},
{0, []byte{t3, tx}},
{0, []byte{t4, tx, tx}},
- {0, []byte{t5, tx, tx, tx}},
- {0, []byte{t6, tx, tx, tx, tx}},
+
+ // we only support UTF-8 up to utf8.UTFMax bytes (4 bytes)
+ {1, []byte{t5, tx, tx, tx, tx}},
+ {1, []byte{t6, tx, tx, tx, tx, tx}},
}
func mkUtf8(rune int) ([]byte, int) {
@@ -47,10 +84,10 @@ func TestLookup(t *testing.T) {
b, szg := mkUtf8(tt)
v, szt := testdata.lookup(b)
if int(v) != i {
- t.Errorf("lookup(%U): found value %#x, expected %#x", i, v, i)
+ t.Errorf("lookup(%U): found value %#x, expected %#x", tt, v, i)
}
if szt != szg {
- t.Errorf("lookup(%U): found size %d, expected %d", i, szt, szg)
+ t.Errorf("lookup(%U): found size %d, expected %d", tt, szt, szg)
}
}
for i, tt := range tests {
diff --git a/libgo/go/exp/norm/triedata_test.go b/libgo/go/exp/norm/triedata_test.go
index f886e6004a4..e8898e5d425 100644
--- a/libgo/go/exp/norm/triedata_test.go
+++ b/libgo/go/exp/norm/triedata_test.go
@@ -4,34 +4,55 @@
package norm
-var testRunes = []int{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111}
+var testRunes = []int{1, 12, 127, 128, 256, 2047, 2048, 2457, 65535, 65536, 65793, 1114111, 512, 513, 514, 528, 533}
-// testdataValues: 768 entries, 1536 bytes
+// testdataValues: 192 entries, 384 bytes
// Block 2 is the null block.
-var testdataValues = [768]uint16{
+var testdataValues = [192]uint16{
// Block 0x0, offset 0x0
0x000c: 0x0001,
// Block 0x1, offset 0x40
0x007f: 0x0002,
// Block 0x2, offset 0x80
- // Block 0x3, offset 0xc0
- 0x00c0: 0x0003,
- // Block 0x4, offset 0x100
- 0x0100: 0x0004,
- // Block 0x5, offset 0x140
- 0x017f: 0x0005,
- // Block 0x6, offset 0x180
- 0x0180: 0x0006,
- // Block 0x7, offset 0x1c0
- 0x01d9: 0x0007,
- // Block 0x8, offset 0x200
- 0x023f: 0x0008,
- // Block 0x9, offset 0x240
- 0x0240: 0x0009,
- // Block 0xa, offset 0x280
- 0x0281: 0x000a,
- // Block 0xb, offset 0x2c0
- 0x02ff: 0x000b,
+}
+
+// testdataSparseOffset: 10 entries, 20 bytes
+var testdataSparseOffset = []uint16{0x0, 0x2, 0x4, 0x8, 0xa, 0xc, 0xe, 0x10, 0x12, 0x14}
+
+// testdataSparseValues: 22 entries, 88 bytes
+var testdataSparseValues = [22]valueRange{
+ // Block 0x0, offset 0x1
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0003, lo: 0x80, hi: 0x80},
+ // Block 0x1, offset 0x2
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0004, lo: 0x80, hi: 0x80},
+ // Block 0x2, offset 0x3
+ {value: 0x0001, lo: 0x03},
+ {value: 0x000c, lo: 0x80, hi: 0x82},
+ {value: 0x000f, lo: 0x90, hi: 0x90},
+ {value: 0x0010, lo: 0x95, hi: 0x95},
+ // Block 0x3, offset 0x4
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0005, lo: 0xbf, hi: 0xbf},
+ // Block 0x4, offset 0x5
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0006, lo: 0x80, hi: 0x80},
+ // Block 0x5, offset 0x6
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0007, lo: 0x99, hi: 0x99},
+ // Block 0x6, offset 0x7
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0008, lo: 0xbf, hi: 0xbf},
+ // Block 0x7, offset 0x8
+ {value: 0x0000, lo: 0x01},
+ {value: 0x0009, lo: 0x80, hi: 0x80},
+ // Block 0x8, offset 0x9
+ {value: 0x0000, lo: 0x01},
+ {value: 0x000a, lo: 0x81, hi: 0x81},
+ // Block 0x9, offset 0xa
+ {value: 0x0000, lo: 0x01},
+ {value: 0x000b, lo: 0xbf, hi: 0xbf},
}
// testdataLookup: 640 bytes
@@ -42,22 +63,23 @@ var testdataLookup = [640]uint8{
// Block 0x2, offset 0x80
// Block 0x3, offset 0xc0
0x0c2: 0x03, 0x0c4: 0x04,
- 0x0df: 0x05,
+ 0x0c8: 0x05,
+ 0x0df: 0x06,
0x0e0: 0x04,
0x0ef: 0x05,
0x0f0: 0x07, 0x0f4: 0x09,
// Block 0x4, offset 0x100
- 0x120: 0x06, 0x126: 0x07,
+ 0x120: 0x07, 0x126: 0x08,
// Block 0x5, offset 0x140
- 0x17f: 0x08,
+ 0x17f: 0x09,
// Block 0x6, offset 0x180
- 0x180: 0x09, 0x184: 0x0a,
+ 0x180: 0x0a, 0x184: 0x0b,
// Block 0x7, offset 0x1c0
0x1d0: 0x06,
// Block 0x8, offset 0x200
- 0x23f: 0x0b,
+ 0x23f: 0x0c,
// Block 0x9, offset 0x240
0x24f: 0x08,
}
-var testdataTrie = trie{testdataLookup[:], testdataValues[:]}
+var testdataTrie = trie{testdataLookup[:], testdataValues[:], testdataSparseValues[:], testdataSparseOffset[:], 3}
diff --git a/libgo/go/exp/norm/triegen.go b/libgo/go/exp/norm/triegen.go
index 2b7eeee175b..515e1c7860b 100644
--- a/libgo/go/exp/norm/triegen.go
+++ b/libgo/go/exp/norm/triegen.go
@@ -17,10 +17,13 @@ import (
"utf8"
)
+const blockSize = 64
+const maxSparseEntries = 16
+
// Intermediate trie structure
type trieNode struct {
table [256]*trieNode
- value uint16
+ value int
b byte
leaf bool
}
@@ -53,6 +56,44 @@ func (n trieNode) isInternal() bool {
return internal
}
+func (n trieNode) mostFrequentStride() int {
+ counts := make(map[int]int)
+ v := 0
+ for _, t := range n.table[0x80 : 0x80+blockSize] {
+ if t != nil {
+ if stride := t.value - v; v != 0 && stride >= 0 {
+ counts[stride]++
+ }
+ v = t.value
+ }
+ }
+ var maxs, maxc int
+ for stride, cnt := range counts {
+ if cnt > maxc {
+ maxs, maxc = stride, cnt
+ }
+ }
+ return maxs
+}
+
+func (n trieNode) countSparseEntries() int {
+ stride := n.mostFrequentStride()
+ var count, v int
+ for _, t := range n.table[0x80 : 0x80+blockSize] {
+ tv := 0
+ if t != nil {
+ tv = t.value
+ }
+ if tv-v != stride {
+ if tv != 0 {
+ count++
+ }
+ }
+ v = tv
+ }
+ return count
+}
+
func (n *trieNode) insert(rune int, value uint16) {
var p [utf8.UTFMax]byte
sz := utf8.EncodeRune(p[:], rune)
@@ -69,35 +110,40 @@ func (n *trieNode) insert(rune int, value uint16) {
}
n = nn
}
- n.value = value
+ n.value = int(value)
n.leaf = true
}
type nodeIndex struct {
lookupBlocks []*trieNode
valueBlocks []*trieNode
+ sparseBlocks []*trieNode
+ sparseOffset []uint16
+ sparseCount int
- lookupBlockIdx map[uint32]uint16
- valueBlockIdx map[uint32]uint16
+ lookupBlockIdx map[uint32]int
+ valueBlockIdx map[uint32]int
}
func newIndex() *nodeIndex {
index := &nodeIndex{}
index.lookupBlocks = make([]*trieNode, 0)
index.valueBlocks = make([]*trieNode, 0)
- index.lookupBlockIdx = make(map[uint32]uint16)
- index.valueBlockIdx = make(map[uint32]uint16)
+ index.sparseBlocks = make([]*trieNode, 0)
+ index.sparseOffset = make([]uint16, 1)
+ index.lookupBlockIdx = make(map[uint32]int)
+ index.valueBlockIdx = make(map[uint32]int)
return index
}
-func computeOffsets(index *nodeIndex, n *trieNode) uint16 {
+func computeOffsets(index *nodeIndex, n *trieNode) int {
if n.leaf {
return n.value
}
hasher := crc32.New(crc32.MakeTable(crc32.IEEE))
// We only index continuation bytes.
- for i := 0; i < 64; i++ {
- var v uint16 = 0
+ for i := 0; i < blockSize; i++ {
+ v := 0
if nn := n.table[0x80+i]; nn != nil {
v = computeOffsets(index, nn)
}
@@ -107,7 +153,7 @@ func computeOffsets(index *nodeIndex, n *trieNode) uint16 {
if n.isInternal() {
v, ok := index.lookupBlockIdx[h]
if !ok {
- v = uint16(len(index.lookupBlocks))
+ v = len(index.lookupBlocks)
index.lookupBlocks = append(index.lookupBlocks, n)
index.lookupBlockIdx[h] = v
}
@@ -115,9 +161,17 @@ func computeOffsets(index *nodeIndex, n *trieNode) uint16 {
} else {
v, ok := index.valueBlockIdx[h]
if !ok {
- v = uint16(len(index.valueBlocks))
- index.valueBlocks = append(index.valueBlocks, n)
- index.valueBlockIdx[h] = v
+ if c := n.countSparseEntries(); c > maxSparseEntries {
+ v = len(index.valueBlocks)
+ index.valueBlocks = append(index.valueBlocks, n)
+ index.valueBlockIdx[h] = v
+ } else {
+ v = -len(index.sparseOffset)
+ index.sparseBlocks = append(index.sparseBlocks, n)
+ index.sparseOffset = append(index.sparseOffset, uint16(index.sparseCount))
+ index.sparseCount += c + 1
+ index.valueBlockIdx[h] = v
+ }
}
n.value = v
}
@@ -125,14 +179,14 @@ func computeOffsets(index *nodeIndex, n *trieNode) uint16 {
}
func printValueBlock(nr int, n *trieNode, offset int) {
- boff := nr * 64
+ boff := nr * blockSize
fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
var printnewline bool
- for i := 0; i < 64; i++ {
+ for i := 0; i < blockSize; i++ {
if i%6 == 0 {
printnewline = true
}
- v := uint16(0)
+ v := 0
if nn := n.table[i+offset]; nn != nil {
v = nn.value
}
@@ -141,24 +195,55 @@ func printValueBlock(nr int, n *trieNode, offset int) {
fmt.Printf("\n")
printnewline = false
}
- fmt.Printf("%#04x:%#04x, ", nr*64+i, v)
+ fmt.Printf("%#04x:%#04x, ", boff+i, v)
}
}
}
-func printLookupBlock(nr int, n *trieNode, offset int) {
- boff := nr * 64
+func printSparseBlock(nr int, n *trieNode) {
+ boff := -n.value
+ fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
+ v := 0
+ //stride := f(n)
+ stride := n.mostFrequentStride()
+ c := n.countSparseEntries()
+ fmt.Printf("\n{value:%#04x,lo:%#02x},", stride, uint8(c))
+ for i, nn := range n.table[0x80 : 0x80+blockSize] {
+ nv := 0
+ if nn != nil {
+ nv = nn.value
+ }
+ if nv-v != stride {
+ if v != 0 {
+ fmt.Printf(",hi:%#02x},", 0x80+i-1)
+ }
+ if nv != 0 {
+ fmt.Printf("\n{value:%#04x,lo:%#02x", nv, nn.b)
+ }
+ }
+ v = nv
+ }
+ if v != 0 {
+ fmt.Printf(",hi:%#02x},", 0x80+blockSize-1)
+ }
+}
+
+func printLookupBlock(nr int, n *trieNode, offset, cutoff int) {
+ boff := nr * blockSize
fmt.Printf("\n// Block %#x, offset %#x", nr, boff)
var printnewline bool
- for i := 0; i < 64; i++ {
+ for i := 0; i < blockSize; i++ {
if i%8 == 0 {
printnewline = true
}
- v := uint16(0)
+ v := 0
if nn := n.table[i+offset]; nn != nil {
v = nn.value
}
if v != 0 {
+ if v < 0 {
+ v = -v - 1 + cutoff
+ }
if printnewline {
fmt.Printf("\n")
printnewline = false
@@ -182,7 +267,7 @@ func (t *trieNode) printTables(name string) int {
}
}
- nv := len(index.valueBlocks) * 64
+ nv := len(index.valueBlocks) * blockSize
fmt.Printf("// %sValues: %d entries, %d bytes\n", name, nv, nv*2)
fmt.Printf("// Block 2 is the null block.\n")
fmt.Printf("var %sValues = [%d]uint16 {", name, nv)
@@ -194,18 +279,32 @@ func (t *trieNode) printTables(name string) int {
}
fmt.Print("\n}\n\n")
- ni := len(index.lookupBlocks) * 64
+ ls := len(index.sparseBlocks)
+ fmt.Printf("// %sSparseOffset: %d entries, %d bytes\n", name, ls, ls*2)
+ fmt.Printf("var %sSparseOffset = %#v\n\n", name, index.sparseOffset[1:])
+
+ ns := index.sparseCount
+ fmt.Printf("// %sSparseValues: %d entries, %d bytes\n", name, ns, ns*4)
+ fmt.Printf("var %sSparseValues = [%d]valueRange {", name, ns)
+ for i, n := range index.sparseBlocks {
+ printSparseBlock(i, n)
+ }
+ fmt.Print("\n}\n\n")
+
+ cutoff := len(index.valueBlocks)
+ ni := len(index.lookupBlocks) * blockSize
fmt.Printf("// %sLookup: %d bytes\n", name, ni)
fmt.Printf("// Block 0 is the null block.\n")
fmt.Printf("var %sLookup = [%d]uint8 {", name, ni)
- printLookupBlock(0, newNode(), 0)
- printLookupBlock(1, newNode(), 0)
- printLookupBlock(2, newNode(), 0)
- printLookupBlock(3, t, 0xC0)
+ printLookupBlock(0, newNode(), 0, cutoff)
+ printLookupBlock(1, newNode(), 0, cutoff)
+ printLookupBlock(2, newNode(), 0, cutoff)
+ printLookupBlock(3, t, 0xC0, cutoff)
for i := 4; i < len(index.lookupBlocks); i++ {
- printLookupBlock(i, index.lookupBlocks[i], 0x80)
+ printLookupBlock(i, index.lookupBlocks[i], 0x80, cutoff)
}
fmt.Print("\n}\n\n")
- fmt.Printf("var %sTrie = trie{ %sLookup[:], %sValues[:] }\n\n", name, name, name)
- return nv*2 + ni
+ fmt.Printf("var %sTrie = trie{ %sLookup[:], %sValues[:], %sSparseValues[:], %sSparseOffset[:], %d}\n\n",
+ name, name, name, name, name, cutoff)
+ return nv*2 + ns*4 + ni + ls*2
}
diff --git a/libgo/go/exp/regexp/all_test.go b/libgo/go/exp/regexp/all_test.go
deleted file mode 100644
index 77f32ca1a57..00000000000
--- a/libgo/go/exp/regexp/all_test.go
+++ /dev/null
@@ -1,429 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package regexp
-
-import (
- "os"
- "strings"
- "testing"
-)
-
-var good_re = []string{
- ``,
- `.`,
- `^.$`,
- `a`,
- `a*`,
- `a+`,
- `a?`,
- `a|b`,
- `a*|b*`,
- `(a*|b)(c*|d)`,
- `[a-z]`,
- `[a-abc-c\-\]\[]`,
- `[a-z]+`,
- `[abc]`,
- `[^1234]`,
- `[^\n]`,
- `\!\\`,
-}
-
-/*
-type stringError struct {
- re string
- err os.Error
-}
-
-var bad_re = []stringError{
- {`*`, ErrBareClosure},
- {`+`, ErrBareClosure},
- {`?`, ErrBareClosure},
- {`(abc`, ErrUnmatchedLpar},
- {`abc)`, ErrUnmatchedRpar},
- {`x[a-z`, ErrUnmatchedLbkt},
- {`abc]`, ErrUnmatchedRbkt},
- {`[z-a]`, ErrBadRange},
- {`abc\`, ErrExtraneousBackslash},
- {`a**`, ErrBadClosure},
- {`a*+`, ErrBadClosure},
- {`a??`, ErrBadClosure},
- {`\x`, ErrBadBackslash},
-}
-*/
-
-func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
- re, err := Compile(expr)
- if err != error {
- t.Error("compiling `", expr, "`; unexpected error: ", err.String())
- }
- return re
-}
-
-func TestGoodCompile(t *testing.T) {
- for i := 0; i < len(good_re); i++ {
- compileTest(t, good_re[i], nil)
- }
-}
-
-/*
-func TestBadCompile(t *testing.T) {
- for i := 0; i < len(bad_re); i++ {
- compileTest(t, bad_re[i].re, bad_re[i].err)
- }
-}
-*/
-
-func matchTest(t *testing.T, test *FindTest) {
- re := compileTest(t, test.pat, nil)
- if re == nil {
- return
- }
- m := re.MatchString(test.text)
- if m != (len(test.matches) > 0) {
- t.Errorf("MatchString failure on %s: %t should be %t", test, m, len(test.matches) > 0)
- }
- // now try bytes
- m = re.Match([]byte(test.text))
- if m != (len(test.matches) > 0) {
- t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
- }
-}
-
-func TestMatch(t *testing.T) {
- for _, test := range findTests {
- matchTest(t, &test)
- }
-}
-
-func matchFunctionTest(t *testing.T, test *FindTest) {
- m, err := MatchString(test.pat, test.text)
- if err == nil {
- return
- }
- if m != (len(test.matches) > 0) {
- t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
- }
-}
-
-func TestMatchFunction(t *testing.T) {
- for _, test := range findTests {
- matchFunctionTest(t, &test)
- }
-}
-
-type ReplaceTest struct {
- pattern, replacement, input, output string
-}
-
-var replaceTests = []ReplaceTest{
- // Test empty input and/or replacement, with pattern that matches the empty string.
- {"", "", "", ""},
- {"", "x", "", "x"},
- {"", "", "abc", "abc"},
- {"", "x", "abc", "xaxbxcx"},
-
- // Test empty input and/or replacement, with pattern that does not match the empty string.
- {"b", "", "", ""},
- {"b", "x", "", ""},
- {"b", "", "abc", "ac"},
- {"b", "x", "abc", "axc"},
- {"y", "", "", ""},
- {"y", "x", "", ""},
- {"y", "", "abc", "abc"},
- {"y", "x", "abc", "abc"},
-
- // Multibyte characters -- verify that we don't try to match in the middle
- // of a character.
- {"[a-c]*", "x", "\u65e5", "x\u65e5x"},
- {"[^\u65e5]", "x", "abc\u65e5def", "xxx\u65e5xxx"},
-
- // Start and end of a string.
- {"^[a-c]*", "x", "abcdabc", "xdabc"},
- {"[a-c]*$", "x", "abcdabc", "abcdx"},
- {"^[a-c]*$", "x", "abcdabc", "abcdabc"},
- {"^[a-c]*", "x", "abc", "x"},
- {"[a-c]*$", "x", "abc", "x"},
- {"^[a-c]*$", "x", "abc", "x"},
- {"^[a-c]*", "x", "dabce", "xdabce"},
- {"[a-c]*$", "x", "dabce", "dabcex"},
- {"^[a-c]*$", "x", "dabce", "dabce"},
- {"^[a-c]*", "x", "", "x"},
- {"[a-c]*$", "x", "", "x"},
- {"^[a-c]*$", "x", "", "x"},
-
- {"^[a-c]+", "x", "abcdabc", "xdabc"},
- {"[a-c]+$", "x", "abcdabc", "abcdx"},
- {"^[a-c]+$", "x", "abcdabc", "abcdabc"},
- {"^[a-c]+", "x", "abc", "x"},
- {"[a-c]+$", "x", "abc", "x"},
- {"^[a-c]+$", "x", "abc", "x"},
- {"^[a-c]+", "x", "dabce", "dabce"},
- {"[a-c]+$", "x", "dabce", "dabce"},
- {"^[a-c]+$", "x", "dabce", "dabce"},
- {"^[a-c]+", "x", "", ""},
- {"[a-c]+$", "x", "", ""},
- {"^[a-c]+$", "x", "", ""},
-
- // Other cases.
- {"abc", "def", "abcdefg", "defdefg"},
- {"bc", "BC", "abcbcdcdedef", "aBCBCdcdedef"},
- {"abc", "", "abcdabc", "d"},
- {"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"},
- {"abc", "d", "", ""},
- {"abc", "d", "abc", "d"},
- {".+", "x", "abc", "x"},
- {"[a-c]*", "x", "def", "xdxexfx"},
- {"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"},
- {"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"},
-}
-
-type ReplaceFuncTest struct {
- pattern string
- replacement func(string) string
- input, output string
-}
-
-var replaceFuncTests = []ReplaceFuncTest{
- {"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"},
- {"[a-c]+", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxabcydef"},
- {"[a-c]*", func(s string) string { return "x" + s + "y" }, "defabcdef", "xydxyexyfxabcydxyexyfxy"},
-}
-
-func TestReplaceAll(t *testing.T) {
- for _, tc := range replaceTests {
- re, err := Compile(tc.pattern)
- if err != nil {
- t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
- continue
- }
- actual := re.ReplaceAllString(tc.input, tc.replacement)
- if actual != tc.output {
- t.Errorf("%q.Replace(%q,%q) = %q; want %q",
- tc.pattern, tc.input, tc.replacement, actual, tc.output)
- }
- // now try bytes
- actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replacement)))
- if actual != tc.output {
- t.Errorf("%q.Replace(%q,%q) = %q; want %q",
- tc.pattern, tc.input, tc.replacement, actual, tc.output)
- }
- }
-}
-
-func TestReplaceAllFunc(t *testing.T) {
- for _, tc := range replaceFuncTests {
- re, err := Compile(tc.pattern)
- if err != nil {
- t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
- continue
- }
- actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
- if actual != tc.output {
- t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
- tc.pattern, tc.input, tc.replacement, actual, tc.output)
- }
- // now try bytes
- actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) }))
- if actual != tc.output {
- t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
- tc.pattern, tc.input, tc.replacement, actual, tc.output)
- }
- }
-}
-
-type MetaTest struct {
- pattern, output, literal string
- isLiteral bool
-}
-
-var metaTests = []MetaTest{
- {``, ``, ``, true},
- {`foo`, `foo`, `foo`, true},
- {`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
- {`foo.\$`, `foo\.\\\$`, `foo`, false}, // has escaped operators and real operators
- {`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false},
-}
-
-func TestQuoteMeta(t *testing.T) {
- for _, tc := range metaTests {
- // Verify that QuoteMeta returns the expected string.
- quoted := QuoteMeta(tc.pattern)
- if quoted != tc.output {
- t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
- tc.pattern, quoted, tc.output)
- continue
- }
-
- // Verify that the quoted string is in fact treated as expected
- // by Compile -- i.e. that it matches the original, unquoted string.
- if tc.pattern != "" {
- re, err := Compile(quoted)
- if err != nil {
- t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
- continue
- }
- src := "abc" + tc.pattern + "def"
- repl := "xyz"
- replaced := re.ReplaceAllString(src, repl)
- expected := "abcxyzdef"
- if replaced != expected {
- t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
- tc.pattern, src, repl, replaced, expected)
- }
- }
- }
-}
-
-func TestLiteralPrefix(t *testing.T) {
- for _, tc := range metaTests {
- // Literal method needs to scan the pattern.
- re := MustCompile(tc.pattern)
- str, complete := re.LiteralPrefix()
- if complete != tc.isLiteral {
- t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
- }
- if str != tc.literal {
- t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
- }
- }
-}
-
-type numSubexpCase struct {
- input string
- expected int
-}
-
-var numSubexpCases = []numSubexpCase{
- {``, 0},
- {`.*`, 0},
- {`abba`, 0},
- {`ab(b)a`, 1},
- {`ab(.*)a`, 1},
- {`(.*)ab(.*)a`, 2},
- {`(.*)(ab)(.*)a`, 3},
- {`(.*)((a)b)(.*)a`, 4},
- {`(.*)(\(ab)(.*)a`, 3},
- {`(.*)(\(a\)b)(.*)a`, 3},
-}
-
-func TestNumSubexp(t *testing.T) {
- for _, c := range numSubexpCases {
- re := MustCompile(c.input)
- n := re.NumSubexp()
- if n != c.expected {
- t.Errorf("NumSubexp for %q returned %d, expected %d", c.input, n, c.expected)
- }
- }
-}
-
-func BenchmarkLiteral(b *testing.B) {
- x := strings.Repeat("x", 50) + "y"
- b.StopTimer()
- re := MustCompile("y")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- if !re.MatchString(x) {
- println("no match!")
- break
- }
- }
-}
-
-func BenchmarkNotLiteral(b *testing.B) {
- x := strings.Repeat("x", 50) + "y"
- b.StopTimer()
- re := MustCompile(".y")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- if !re.MatchString(x) {
- println("no match!")
- break
- }
- }
-}
-
-func BenchmarkMatchClass(b *testing.B) {
- b.StopTimer()
- x := strings.Repeat("xxxx", 20) + "w"
- re := MustCompile("[abcdw]")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- if !re.MatchString(x) {
- println("no match!")
- break
- }
- }
-}
-
-func BenchmarkMatchClass_InRange(b *testing.B) {
- b.StopTimer()
- // 'b' is between 'a' and 'c', so the charclass
- // range checking is no help here.
- x := strings.Repeat("bbbb", 20) + "c"
- re := MustCompile("[ac]")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- if !re.MatchString(x) {
- println("no match!")
- break
- }
- }
-}
-
-func BenchmarkReplaceAll(b *testing.B) {
- x := "abcdefghijklmnopqrstuvwxyz"
- b.StopTimer()
- re := MustCompile("[cjrw]")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- re.ReplaceAllString(x, "")
- }
-}
-
-func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) {
- b.StopTimer()
- x := []byte("abcdefghijklmnopqrstuvwxyz")
- re := MustCompile("^zbc(d|e)")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- re.Match(x)
- }
-}
-
-func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) {
- b.StopTimer()
- x := []byte("abcdefghijklmnopqrstuvwxyz")
- for i := 0; i < 15; i++ {
- x = append(x, x...)
- }
- re := MustCompile("^zbc(d|e)")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- re.Match(x)
- }
-}
-
-func BenchmarkAnchoredShortMatch(b *testing.B) {
- b.StopTimer()
- x := []byte("abcdefghijklmnopqrstuvwxyz")
- re := MustCompile("^.bc(d|e)")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- re.Match(x)
- }
-}
-
-func BenchmarkAnchoredLongMatch(b *testing.B) {
- b.StopTimer()
- x := []byte("abcdefghijklmnopqrstuvwxyz")
- for i := 0; i < 15; i++ {
- x = append(x, x...)
- }
- re := MustCompile("^.bc(d|e)")
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- re.Match(x)
- }
-}
diff --git a/libgo/go/exp/regexp/exec.go b/libgo/go/exp/regexp/exec.go
deleted file mode 100644
index 0670bb9b1b4..00000000000
--- a/libgo/go/exp/regexp/exec.go
+++ /dev/null
@@ -1,295 +0,0 @@
-package regexp
-
-import "exp/regexp/syntax"
-
-// A queue is a 'sparse array' holding pending threads of execution.
-// See http://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html
-type queue struct {
- sparse []uint32
- dense []entry
-}
-
-// A entry is an entry on a queue.
-// It holds both the instruction pc and the actual thread.
-// Some queue entries are just place holders so that the machine
-// knows it has considered that pc. Such entries have t == nil.
-type entry struct {
- pc uint32
- t *thread
-}
-
-// A thread is the state of a single path through the machine:
-// an instruction and a corresponding capture array.
-// See http://swtch.com/~rsc/regexp/regexp2.html
-type thread struct {
- inst *syntax.Inst
- cap []int
-}
-
-// A machine holds all the state during an NFA simulation for p.
-type machine struct {
- re *Regexp // corresponding Regexp
- p *syntax.Prog // compiled program
- q0, q1 queue // two queues for runq, nextq
- pool []*thread // pool of available threads
- matched bool // whether a match was found
- matchcap []int // capture information for the match
-}
-
-// progMachine returns a new machine running the prog p.
-func progMachine(p *syntax.Prog) *machine {
- m := &machine{p: p}
- n := len(m.p.Inst)
- m.q0 = queue{make([]uint32, n), make([]entry, 0, n)}
- m.q1 = queue{make([]uint32, n), make([]entry, 0, n)}
- ncap := p.NumCap
- if ncap < 2 {
- ncap = 2
- }
- m.matchcap = make([]int, ncap)
- return m
-}
-
-// alloc allocates a new thread with the given instruction.
-// It uses the free pool if possible.
-func (m *machine) alloc(i *syntax.Inst) *thread {
- var t *thread
- if n := len(m.pool); n > 0 {
- t = m.pool[n-1]
- m.pool = m.pool[:n-1]
- } else {
- t = new(thread)
- t.cap = make([]int, cap(m.matchcap))
- }
- t.cap = t.cap[:len(m.matchcap)]
- t.inst = i
- return t
-}
-
-// free returns t to the free pool.
-func (m *machine) free(t *thread) {
- m.pool = append(m.pool, t)
-}
-
-// match runs the machine over the input starting at pos.
-// It reports whether a match was found.
-// If so, m.matchcap holds the submatch information.
-func (m *machine) match(i input, pos int) bool {
- startCond := m.re.cond
- if startCond == ^syntax.EmptyOp(0) { // impossible
- return false
- }
- m.matched = false
- for i := range m.matchcap {
- m.matchcap[i] = -1
- }
- runq, nextq := &m.q0, &m.q1
- rune, rune1 := endOfText, endOfText
- width, width1 := 0, 0
- rune, width = i.step(pos)
- if rune != endOfText {
- rune1, width1 = i.step(pos + width)
- }
- // TODO: Let caller specify the initial flag setting.
- // For now assume pos == 0 is beginning of text and
- // pos != 0 is not even beginning of line.
- // TODO: Word boundary.
- var flag syntax.EmptyOp
- if pos == 0 {
- flag = syntax.EmptyBeginText | syntax.EmptyBeginLine
- }
-
- // Update flag using lookahead rune.
- if rune1 == '\n' {
- flag |= syntax.EmptyEndLine
- }
- if rune1 == endOfText {
- flag |= syntax.EmptyEndText
- }
-
- for {
- if len(runq.dense) == 0 {
- if startCond&syntax.EmptyBeginText != 0 && pos != 0 {
- // Anchored match, past beginning of text.
- break
- }
- if m.matched {
- // Have match; finished exploring alternatives.
- break
- }
- if len(m.re.prefix) > 0 && rune1 != m.re.prefixRune && i.canCheckPrefix() {
- // Match requires literal prefix; fast search for it.
- advance := i.index(m.re, pos)
- if advance < 0 {
- break
- }
- pos += advance
- rune, width = i.step(pos)
- rune1, width1 = i.step(pos + width)
- }
- }
- if !m.matched {
- if len(m.matchcap) > 0 {
- m.matchcap[0] = pos
- }
- m.add(runq, uint32(m.p.Start), pos, m.matchcap, flag)
- }
- // TODO: word boundary
- flag = 0
- if rune == '\n' {
- flag |= syntax.EmptyBeginLine
- }
- if rune1 == '\n' {
- flag |= syntax.EmptyEndLine
- }
- if rune1 == endOfText {
- flag |= syntax.EmptyEndText
- }
- m.step(runq, nextq, pos, pos+width, rune, flag)
- if width == 0 {
- break
- }
- pos += width
- rune, width = rune1, width1
- if rune != endOfText {
- rune1, width1 = i.step(pos + width)
- }
- runq, nextq = nextq, runq
- }
- m.clear(nextq)
- return m.matched
-}
-
-// clear frees all threads on the thread queue.
-func (m *machine) clear(q *queue) {
- for _, d := range q.dense {
- if d.t != nil {
- m.free(d.t)
- }
- }
- q.dense = q.dense[:0]
-}
-
-// step executes one step of the machine, running each of the threads
-// on runq and appending new threads to nextq.
-// The step processes the rune c (which may be endOfText),
-// which starts at position pos and ends at nextPos.
-// nextCond gives the setting for the empty-width flags after c.
-func (m *machine) step(runq, nextq *queue, pos, nextPos, c int, nextCond syntax.EmptyOp) {
- for j := 0; j < len(runq.dense); j++ {
- d := &runq.dense[j]
- t := d.t
- if t == nil {
- continue
- }
- /*
- * If we support leftmost-longest matching:
- if longest && matched && match[0] < t.cap[0] {
- m.free(t)
- continue
- }
- */
-
- i := t.inst
- switch i.Op {
- default:
- panic("bad inst")
-
- case syntax.InstMatch:
- if len(t.cap) > 0 {
- t.cap[1] = pos
- copy(m.matchcap, t.cap)
- }
- m.matched = true
- for _, d := range runq.dense[j+1:] {
- if d.t != nil {
- m.free(d.t)
- }
- }
- runq.dense = runq.dense[:0]
-
- case syntax.InstRune:
- if i.MatchRune(c) {
- m.add(nextq, i.Out, nextPos, t.cap, nextCond)
- }
- }
- m.free(t)
- }
- runq.dense = runq.dense[:0]
-}
-
-// add adds an entry to q for pc, unless the q already has such an entry.
-// It also recursively adds an entry for all instructions reachable from pc by following
-// empty-width conditions satisfied by cond. pos gives the current position
-// in the input.
-func (m *machine) add(q *queue, pc uint32, pos int, cap []int, cond syntax.EmptyOp) {
- if pc == 0 {
- return
- }
- if j := q.sparse[pc]; j < uint32(len(q.dense)) && q.dense[j].pc == pc {
- return
- }
-
- j := len(q.dense)
- q.dense = q.dense[:j+1]
- d := &q.dense[j]
- d.t = nil
- d.pc = pc
- q.sparse[pc] = uint32(j)
-
- i := &m.p.Inst[pc]
- switch i.Op {
- default:
- panic("unhandled")
- case syntax.InstFail:
- // nothing
- case syntax.InstAlt, syntax.InstAltMatch:
- m.add(q, i.Out, pos, cap, cond)
- m.add(q, i.Arg, pos, cap, cond)
- case syntax.InstEmptyWidth:
- if syntax.EmptyOp(i.Arg)&^cond == 0 {
- m.add(q, i.Out, pos, cap, cond)
- }
- case syntax.InstNop:
- m.add(q, i.Out, pos, cap, cond)
- case syntax.InstCapture:
- if int(i.Arg) < len(cap) {
- opos := cap[i.Arg]
- cap[i.Arg] = pos
- m.add(q, i.Out, pos, cap, cond)
- cap[i.Arg] = opos
- } else {
- m.add(q, i.Out, pos, cap, cond)
- }
- case syntax.InstMatch, syntax.InstRune:
- t := m.alloc(i)
- if len(t.cap) > 0 {
- copy(t.cap, cap)
- }
- d.t = t
- }
-}
-
-// empty is a non-nil 0-element slice,
-// so doExecute can avoid an allocation
-// when 0 captures are requested from a successful match.
-var empty = make([]int, 0)
-
-// doExecute finds the leftmost match in the input and returns
-// the position of its subexpressions.
-func (re *Regexp) doExecute(i input, pos int, ncap int) []int {
- m := re.get()
- m.matchcap = m.matchcap[:ncap]
- if !m.match(i, pos) {
- re.put(m)
- return nil
- }
- if ncap == 0 {
- re.put(m)
- return empty // empty but not nil
- }
- cap := make([]int, ncap)
- copy(cap, m.matchcap)
- re.put(m)
- return cap
-}
diff --git a/libgo/go/exp/regexp/find_test.go b/libgo/go/exp/regexp/find_test.go
deleted file mode 100644
index dddc3484c93..00000000000
--- a/libgo/go/exp/regexp/find_test.go
+++ /dev/null
@@ -1,472 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package regexp
-
-import (
- "fmt"
- "strings"
- "testing"
-)
-
-// For each pattern/text pair, what is the expected output of each function?
-// We can derive the textual results from the indexed results, the non-submatch
-// results from the submatched results, the single results from the 'all' results,
-// and the byte results from the string results. Therefore the table includes
-// only the FindAllStringSubmatchIndex result.
-type FindTest struct {
- pat string
- text string
- matches [][]int
-}
-
-func (t FindTest) String() string {
- return fmt.Sprintf("pat: %#q text: %#q", t.pat, t.text)
-}
-
-var findTests = []FindTest{
- {``, ``, build(1, 0, 0)},
- {`^abcdefg`, "abcdefg", build(1, 0, 7)},
- {`a+`, "baaab", build(1, 1, 4)},
- {"abcd..", "abcdef", build(1, 0, 6)},
- {`a`, "a", build(1, 0, 1)},
- {`x`, "y", nil},
- {`b`, "abc", build(1, 1, 2)},
- {`.`, "a", build(1, 0, 1)},
- {`.*`, "abcdef", build(1, 0, 6)},
- {`^`, "abcde", build(1, 0, 0)},
- {`$`, "abcde", build(1, 5, 5)},
- {`^abcd$`, "abcd", build(1, 0, 4)},
- {`^bcd'`, "abcdef", nil},
- {`^abcd$`, "abcde", nil},
- {`a+`, "baaab", build(1, 1, 4)},
- {`a*`, "baaab", build(3, 0, 0, 1, 4, 5, 5)},
- {`[a-z]+`, "abcd", build(1, 0, 4)},
- {`[^a-z]+`, "ab1234cd", build(1, 2, 6)},
- {`[a\-\]z]+`, "az]-bcz", build(2, 0, 4, 6, 7)},
- {`[^\n]+`, "abcd\n", build(1, 0, 4)},
- {`[日本語]+`, "日本語日本語", build(1, 0, 18)},
- {`日本語+`, "日本語", build(1, 0, 9)},
- {`日本語+`, "日本語語語語", build(1, 0, 18)},
- {`()`, "", build(1, 0, 0, 0, 0)},
- {`(a)`, "a", build(1, 0, 1, 0, 1)},
- {`(.)(.)`, "æ—¥a", build(1, 0, 4, 0, 3, 3, 4)},
- {`(.*)`, "", build(1, 0, 0, 0, 0)},
- {`(.*)`, "abcd", build(1, 0, 4, 0, 4)},
- {`(..)(..)`, "abcd", build(1, 0, 4, 0, 2, 2, 4)},
- {`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)},
- {`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)},
- {`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
- {`\a\f\n\r\t\v`, "\a\f\n\r\t\v", build(1, 0, 6)},
- {`[\a\f\n\r\t\v]+`, "\a\f\n\r\t\v", build(1, 0, 6)},
-
- {`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)},
- {`(.*).*`, "ab", build(1, 0, 2, 0, 2)},
- {`[.]`, ".", build(1, 0, 1)},
- {`/$`, "/abc/", build(1, 4, 5)},
- {`/$`, "/abc", nil},
-
- // multiple matches
- {`.`, "abc", build(3, 0, 1, 1, 2, 2, 3)},
- {`(.)`, "abc", build(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)},
- {`.(.)`, "abcd", build(2, 0, 2, 1, 2, 2, 4, 3, 4)},
- {`ab*`, "abbaab", build(3, 0, 3, 3, 4, 4, 6)},
- {`a(b*)`, "abbaab", build(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)},
-
- // fixed bugs
- {`ab$`, "cab", build(1, 1, 3)},
- {`axxb$`, "axxcb", nil},
- {`data`, "daXY data", build(1, 5, 9)},
- {`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
- {`zx+`, "zzx", build(1, 1, 3)},
-
- // can backslash-escape any punctuation
- {`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
- `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
- {`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`,
- `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
- {"\\`", "`", build(1, 0, 1)},
- {"[\\`]+", "`", build(1, 0, 1)},
-
- // long set of matches (longer than startSize)
- {
- ".",
- "qwertyuiopasdfghjklzxcvbnm1234567890",
- build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
- 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
- 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
- 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36),
- },
-}
-
-// build is a helper to construct a [][]int by extracting n sequences from x.
-// This represents n matches with len(x)/n submatches each.
-func build(n int, x ...int) [][]int {
- ret := make([][]int, n)
- runLength := len(x) / n
- j := 0
- for i := range ret {
- ret[i] = make([]int, runLength)
- copy(ret[i], x[j:])
- j += runLength
- if j > len(x) {
- panic("invalid build entry")
- }
- }
- return ret
-}
-
-// First the simple cases.
-
-func TestFind(t *testing.T) {
- for _, test := range findTests {
- re := MustCompile(test.pat)
- if re.String() != test.pat {
- t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat)
- }
- result := re.Find([]byte(test.text))
- switch {
- case len(test.matches) == 0 && len(result) == 0:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case test.matches != nil && result != nil:
- expect := test.text[test.matches[0][0]:test.matches[0][1]]
- if expect != string(result) {
- t.Errorf("expected %q got %q: %s", expect, result, test)
- }
- }
- }
-}
-
-func TestFindString(t *testing.T) {
- for _, test := range findTests {
- result := MustCompile(test.pat).FindString(test.text)
- switch {
- case len(test.matches) == 0 && len(result) == 0:
- // ok
- case test.matches == nil && result != "":
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == "":
- // Tricky because an empty result has two meanings: no match or empty match.
- if test.matches[0][0] != test.matches[0][1] {
- t.Errorf("expected match; got none: %s", test)
- }
- case test.matches != nil && result != "":
- expect := test.text[test.matches[0][0]:test.matches[0][1]]
- if expect != result {
- t.Errorf("expected %q got %q: %s", expect, result, test)
- }
- }
- }
-}
-
-func testFindIndex(test *FindTest, result []int, t *testing.T) {
- switch {
- case len(test.matches) == 0 && len(result) == 0:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case test.matches != nil && result != nil:
- expect := test.matches[0]
- if expect[0] != result[0] || expect[1] != result[1] {
- t.Errorf("expected %v got %v: %s", expect, result, test)
- }
- }
-}
-
-func TestFindIndex(t *testing.T) {
- for _, test := range findTests {
- testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test.text)), t)
- }
-}
-
-func TestFindStringIndex(t *testing.T) {
- for _, test := range findTests {
- testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.text), t)
- }
-}
-
-func TestFindReaderIndex(t *testing.T) {
- for _, test := range findTests {
- testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strings.NewReader(test.text)), t)
- }
-}
-
-// Now come the simple All cases.
-
-func TestFindAll(t *testing.T) {
- for _, test := range findTests {
- result := MustCompile(test.pat).FindAll([]byte(test.text), -1)
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Fatalf("expected match; got none: %s", test)
- case test.matches != nil && result != nil:
- if len(test.matches) != len(result) {
- t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
- continue
- }
- for k, e := range test.matches {
- expect := test.text[e[0]:e[1]]
- if expect != string(result[k]) {
- t.Errorf("match %d: expected %q got %q: %s", k, expect, result[k], test)
- }
- }
- }
- }
-}
-
-func TestFindAllString(t *testing.T) {
- for _, test := range findTests {
- result := MustCompile(test.pat).FindAllString(test.text, -1)
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case test.matches != nil && result != nil:
- if len(test.matches) != len(result) {
- t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
- continue
- }
- for k, e := range test.matches {
- expect := test.text[e[0]:e[1]]
- if expect != result[k] {
- t.Errorf("expected %q got %q: %s", expect, result, test)
- }
- }
- }
- }
-}
-
-func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) {
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case test.matches != nil && result != nil:
- if len(test.matches) != len(result) {
- t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
- return
- }
- for k, e := range test.matches {
- if e[0] != result[k][0] || e[1] != result[k][1] {
- t.Errorf("match %d: expected %v got %v: %s", k, e, result[k], test)
- }
- }
- }
-}
-
-func TestFindAllIndex(t *testing.T) {
- for _, test := range findTests {
- testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byte(test.text), -1), t)
- }
-}
-
-func TestFindAllStringIndex(t *testing.T) {
- for _, test := range findTests {
- testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex(test.text, -1), t)
- }
-}
-
-// Now come the Submatch cases.
-
-func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte, t *testing.T) {
- if len(submatches) != len(result)*2 {
- t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
- return
- }
- for k := 0; k < len(submatches); k += 2 {
- if submatches[k] == -1 {
- if result[k/2] != nil {
- t.Errorf("match %d: expected nil got %q: %s", n, result, test)
- }
- continue
- }
- expect := test.text[submatches[k]:submatches[k+1]]
- if expect != string(result[k/2]) {
- t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
- return
- }
- }
-}
-
-func TestFindSubmatch(t *testing.T) {
- for _, test := range findTests {
- result := MustCompile(test.pat).FindSubmatch([]byte(test.text))
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case test.matches != nil && result != nil:
- testSubmatchBytes(&test, 0, test.matches[0], result, t)
- }
- }
-}
-
-func testSubmatchString(test *FindTest, n int, submatches []int, result []string, t *testing.T) {
- if len(submatches) != len(result)*2 {
- t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
- return
- }
- for k := 0; k < len(submatches); k += 2 {
- if submatches[k] == -1 {
- if result[k/2] != "" {
- t.Errorf("match %d: expected nil got %q: %s", n, result, test)
- }
- continue
- }
- expect := test.text[submatches[k]:submatches[k+1]]
- if expect != result[k/2] {
- t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
- return
- }
- }
-}
-
-func TestFindStringSubmatch(t *testing.T) {
- for _, test := range findTests {
- result := MustCompile(test.pat).FindStringSubmatch(test.text)
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case test.matches != nil && result != nil:
- testSubmatchString(&test, 0, test.matches[0], result, t)
- }
- }
-}
-
-func testSubmatchIndices(test *FindTest, n int, expect, result []int, t *testing.T) {
- if len(expect) != len(result) {
- t.Errorf("match %d: expected %d matches; got %d: %s", n, len(expect)/2, len(result)/2, test)
- return
- }
- for k, e := range expect {
- if e != result[k] {
- t.Errorf("match %d: submatch error: expected %v got %v: %s", n, expect, result, test)
- }
- }
-}
-
-func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) {
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case test.matches != nil && result != nil:
- testSubmatchIndices(test, 0, test.matches[0], result, t)
- }
-}
-
-func TestFindSubmatchIndex(t *testing.T) {
- for _, test := range findTests {
- testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchIndex([]byte(test.text)), t)
- }
-}
-
-func TestFindStringSubmatchIndex(t *testing.T) {
- for _, test := range findTests {
- testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSubmatchIndex(test.text), t)
- }
-}
-
-func TestFindReaderSubmatchIndex(t *testing.T) {
- for _, test := range findTests {
- testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSubmatchIndex(strings.NewReader(test.text)), t)
- }
-}
-
-// Now come the monster AllSubmatch cases.
-
-func TestFindAllSubmatch(t *testing.T) {
- for _, test := range findTests {
- result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text), -1)
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case len(test.matches) != len(result):
- t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
- case test.matches != nil && result != nil:
- for k, match := range test.matches {
- testSubmatchBytes(&test, k, match, result[k], t)
- }
- }
- }
-}
-
-func TestFindAllStringSubmatch(t *testing.T) {
- for _, test := range findTests {
- result := MustCompile(test.pat).FindAllStringSubmatch(test.text, -1)
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case len(test.matches) != len(result):
- t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
- case test.matches != nil && result != nil:
- for k, match := range test.matches {
- testSubmatchString(&test, k, match, result[k], t)
- }
- }
- }
-}
-
-func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) {
- switch {
- case test.matches == nil && result == nil:
- // ok
- case test.matches == nil && result != nil:
- t.Errorf("expected no match; got one: %s", test)
- case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
- case len(test.matches) != len(result):
- t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
- case test.matches != nil && result != nil:
- for k, match := range test.matches {
- testSubmatchIndices(test, k, match, result[k], t)
- }
- }
-}
-
-func TestFindAllSubmatchIndex(t *testing.T) {
- for _, test := range findTests {
- testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSubmatchIndex([]byte(test.text), -1), t)
- }
-}
-
-func TestFindAllStringSubmatchIndex(t *testing.T) {
- for _, test := range findTests {
- testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStringSubmatchIndex(test.text, -1), t)
- }
-}
diff --git a/libgo/go/exp/regexp/regexp.go b/libgo/go/exp/regexp/regexp.go
deleted file mode 100644
index 1b75900f816..00000000000
--- a/libgo/go/exp/regexp/regexp.go
+++ /dev/null
@@ -1,795 +0,0 @@
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package regexp implements a simple regular expression library.
-//
-// The syntax of the regular expressions accepted is the same
-// general syntax used by Perl, Python, and other languages.
-// More precisely, it is the syntax accepted by RE2 and described at
-// http://code.google.com/p/re2/wiki/Syntax, except for \C.
-//
-// All characters are UTF-8-encoded code points.
-//
-// There are 16 methods of Regexp that match a regular expression and identify
-// the matched text. Their names are matched by this regular expression:
-//
-// Find(All)?(String)?(Submatch)?(Index)?
-//
-// If 'All' is present, the routine matches successive non-overlapping
-// matches of the entire expression. Empty matches abutting a preceding
-// match are ignored. The return value is a slice containing the successive
-// return values of the corresponding non-'All' routine. These routines take
-// an extra integer argument, n; if n >= 0, the function returns at most n
-// matches/submatches.
-//
-// If 'String' is present, the argument is a string; otherwise it is a slice
-// of bytes; return values are adjusted as appropriate.
-//
-// If 'Submatch' is present, the return value is a slice identifying the
-// successive submatches of the expression. Submatches are matches of
-// parenthesized subexpressions within the regular expression, numbered from
-// left to right in order of opening parenthesis. Submatch 0 is the match of
-// the entire expression, submatch 1 the match of the first parenthesized
-// subexpression, and so on.
-//
-// If 'Index' is present, matches and submatches are identified by byte index
-// pairs within the input string: result[2*n:2*n+1] identifies the indexes of
-// the nth submatch. The pair for n==0 identifies the match of the entire
-// expression. If 'Index' is not present, the match is identified by the
-// text of the match/submatch. If an index is negative, it means that
-// subexpression did not match any string in the input.
-//
-// There is also a subset of the methods that can be applied to text read
-// from a RuneReader:
-//
-// MatchReader, FindReaderIndex, FindReaderSubmatchIndex
-//
-// This set may grow. Note that regular expression matches may need to
-// examine text beyond the text returned by a match, so the methods that
-// match text from a RuneReader may read arbitrarily far into the input
-// before returning.
-//
-// (There are a few other methods that do not match this pattern.)
-//
-package regexp
-
-import (
- "bytes"
- "exp/regexp/syntax"
- "io"
- "os"
- "strings"
- "sync"
- "utf8"
-)
-
-var debug = false
-
-// Error is the local type for a parsing error.
-type Error string
-
-func (e Error) String() string {
- return string(e)
-}
-
-// Regexp is the representation of a compiled regular expression.
-// The public interface is entirely through methods.
-// A Regexp is safe for concurrent use by multiple goroutines.
-type Regexp struct {
- // read-only after Compile
- expr string // as passed to Compile
- prog *syntax.Prog // compiled program
- prefix string // required prefix in unanchored matches
- prefixBytes []byte // prefix, as a []byte
- prefixComplete bool // prefix is the entire regexp
- prefixRune int // first rune in prefix
- cond syntax.EmptyOp // empty-width conditions required at start of match
-
- // cache of machines for running regexp
- mu sync.Mutex
- machine []*machine
-}
-
-// String returns the source text used to compile the regular expression.
-func (re *Regexp) String() string {
- return re.expr
-}
-
-// Compile parses a regular expression and returns, if successful, a Regexp
-// object that can be used to match against text.
-func Compile(expr string) (*Regexp, os.Error) {
- re, err := syntax.Parse(expr, syntax.Perl)
- if err != nil {
- return nil, err
- }
- prog, err := syntax.Compile(re)
- if err != nil {
- return nil, err
- }
- regexp := &Regexp{
- expr: expr,
- prog: prog,
- }
- regexp.prefix, regexp.prefixComplete = prog.Prefix()
- if regexp.prefix != "" {
- // TODO(rsc): Remove this allocation by adding
- // IndexString to package bytes.
- regexp.prefixBytes = []byte(regexp.prefix)
- regexp.prefixRune, _ = utf8.DecodeRuneInString(regexp.prefix)
- }
- regexp.cond = prog.StartCond()
- return regexp, nil
-}
-
-// get returns a machine to use for matching re.
-// It uses the re's machine cache if possible, to avoid
-// unnecessary allocation.
-func (re *Regexp) get() *machine {
- re.mu.Lock()
- if n := len(re.machine); n > 0 {
- z := re.machine[n-1]
- re.machine = re.machine[:n-1]
- re.mu.Unlock()
- return z
- }
- re.mu.Unlock()
- z := progMachine(re.prog)
- z.re = re
- return z
-}
-
-// put returns a machine to the re's machine cache.
-// There is no attempt to limit the size of the cache, so it will
-// grow to the maximum number of simultaneous matches
-// run using re. (The cache empties when re gets garbage collected.)
-func (re *Regexp) put(z *machine) {
- re.mu.Lock()
- re.machine = append(re.machine, z)
- re.mu.Unlock()
-}
-
-// MustCompile is like Compile but panics if the expression cannot be parsed.
-// It simplifies safe initialization of global variables holding compiled regular
-// expressions.
-func MustCompile(str string) *Regexp {
- regexp, error := Compile(str)
- if error != nil {
- panic(`regexp: compiling "` + str + `": ` + error.String())
- }
- return regexp
-}
-
-// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
-func (re *Regexp) NumSubexp() int {
- // NumCap/2 because captures count ( and ) separately.
- // -1 because NumCap counts $0 but NumSubexp does not.
- return re.prog.NumCap/2 - 1
-}
-
-const endOfText = -1
-
-// input abstracts different representations of the input text. It provides
-// one-character lookahead.
-type input interface {
- step(pos int) (rune int, width int) // advance one rune
- canCheckPrefix() bool // can we look ahead without losing info?
- hasPrefix(re *Regexp) bool
- index(re *Regexp, pos int) int
-}
-
-// inputString scans a string.
-type inputString struct {
- str string
-}
-
-func newInputString(str string) *inputString {
- return &inputString{str: str}
-}
-
-func (i *inputString) step(pos int) (int, int) {
- if pos < len(i.str) {
- return utf8.DecodeRuneInString(i.str[pos:len(i.str)])
- }
- return endOfText, 0
-}
-
-func (i *inputString) canCheckPrefix() bool {
- return true
-}
-
-func (i *inputString) hasPrefix(re *Regexp) bool {
- return strings.HasPrefix(i.str, re.prefix)
-}
-
-func (i *inputString) index(re *Regexp, pos int) int {
- return strings.Index(i.str[pos:], re.prefix)
-}
-
-// inputBytes scans a byte slice.
-type inputBytes struct {
- str []byte
-}
-
-func newInputBytes(str []byte) *inputBytes {
- return &inputBytes{str: str}
-}
-
-func (i *inputBytes) step(pos int) (int, int) {
- if pos < len(i.str) {
- return utf8.DecodeRune(i.str[pos:len(i.str)])
- }
- return endOfText, 0
-}
-
-func (i *inputBytes) canCheckPrefix() bool {
- return true
-}
-
-func (i *inputBytes) hasPrefix(re *Regexp) bool {
- return bytes.HasPrefix(i.str, re.prefixBytes)
-}
-
-func (i *inputBytes) index(re *Regexp, pos int) int {
- return bytes.Index(i.str[pos:], re.prefixBytes)
-}
-
-// inputReader scans a RuneReader.
-type inputReader struct {
- r io.RuneReader
- atEOT bool
- pos int
-}
-
-func newInputReader(r io.RuneReader) *inputReader {
- return &inputReader{r: r}
-}
-
-func (i *inputReader) step(pos int) (int, int) {
- if !i.atEOT && pos != i.pos {
- return endOfText, 0
-
- }
- r, w, err := i.r.ReadRune()
- if err != nil {
- i.atEOT = true
- return endOfText, 0
- }
- i.pos += w
- return r, w
-}
-
-func (i *inputReader) canCheckPrefix() bool {
- return false
-}
-
-func (i *inputReader) hasPrefix(re *Regexp) bool {
- return false
-}
-
-func (i *inputReader) index(re *Regexp, pos int) int {
- return -1
-}
-
-// LiteralPrefix returns a literal string that must begin any match
-// of the regular expression re. It returns the boolean true if the
-// literal string comprises the entire regular expression.
-func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
- return re.prefix, re.prefixComplete
-}
-
-// MatchReader returns whether the Regexp matches the text read by the
-// RuneReader. The return value is a boolean: true for match, false for no
-// match.
-func (re *Regexp) MatchReader(r io.RuneReader) bool {
- return re.doExecute(newInputReader(r), 0, 0) != nil
-}
-
-// MatchString returns whether the Regexp matches the string s.
-// The return value is a boolean: true for match, false for no match.
-func (re *Regexp) MatchString(s string) bool {
- return re.doExecute(newInputString(s), 0, 0) != nil
-}
-
-// Match returns whether the Regexp matches the byte slice b.
-// The return value is a boolean: true for match, false for no match.
-func (re *Regexp) Match(b []byte) bool {
- return re.doExecute(newInputBytes(b), 0, 0) != nil
-}
-
-// MatchReader checks whether a textual regular expression matches the text
-// read by the RuneReader. More complicated queries need to use Compile and
-// the full Regexp interface.
-func MatchReader(pattern string, r io.RuneReader) (matched bool, error os.Error) {
- re, err := Compile(pattern)
- if err != nil {
- return false, err
- }
- return re.MatchReader(r), nil
-}
-
-// MatchString checks whether a textual regular expression
-// matches a string. More complicated queries need
-// to use Compile and the full Regexp interface.
-func MatchString(pattern string, s string) (matched bool, error os.Error) {
- re, err := Compile(pattern)
- if err != nil {
- return false, err
- }
- return re.MatchString(s), nil
-}
-
-// Match checks whether a textual regular expression
-// matches a byte slice. More complicated queries need
-// to use Compile and the full Regexp interface.
-func Match(pattern string, b []byte) (matched bool, error os.Error) {
- re, err := Compile(pattern)
- if err != nil {
- return false, err
- }
- return re.Match(b), nil
-}
-
-// ReplaceAllString returns a copy of src in which all matches for the Regexp
-// have been replaced by repl. No support is provided for expressions
-// (e.g. \1 or $1) in the replacement string.
-func (re *Regexp) ReplaceAllString(src, repl string) string {
- return re.ReplaceAllStringFunc(src, func(string) string { return repl })
-}
-
-// ReplaceAllStringFunc returns a copy of src in which all matches for the
-// Regexp have been replaced by the return value of of function repl (whose
-// first argument is the matched string). No support is provided for
-// expressions (e.g. \1 or $1) in the replacement string.
-func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
- lastMatchEnd := 0 // end position of the most recent match
- searchPos := 0 // position where we next look for a match
- buf := new(bytes.Buffer)
- for searchPos <= len(src) {
- a := re.doExecute(newInputString(src), searchPos, 2)
- if len(a) == 0 {
- break // no more matches
- }
-
- // Copy the unmatched characters before this match.
- io.WriteString(buf, src[lastMatchEnd:a[0]])
-
- // Now insert a copy of the replacement string, but not for a
- // match of the empty string immediately after another match.
- // (Otherwise, we get double replacement for patterns that
- // match both empty and nonempty strings.)
- if a[1] > lastMatchEnd || a[0] == 0 {
- io.WriteString(buf, repl(src[a[0]:a[1]]))
- }
- lastMatchEnd = a[1]
-
- // Advance past this match; always advance at least one character.
- _, width := utf8.DecodeRuneInString(src[searchPos:])
- if searchPos+width > a[1] {
- searchPos += width
- } else if searchPos+1 > a[1] {
- // This clause is only needed at the end of the input
- // string. In that case, DecodeRuneInString returns width=0.
- searchPos++
- } else {
- searchPos = a[1]
- }
- }
-
- // Copy the unmatched characters after the last match.
- io.WriteString(buf, src[lastMatchEnd:])
-
- return buf.String()
-}
-
-// ReplaceAll returns a copy of src in which all matches for the Regexp
-// have been replaced by repl. No support is provided for expressions
-// (e.g. \1 or $1) in the replacement text.
-func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
- return re.ReplaceAllFunc(src, func([]byte) []byte { return repl })
-}
-
-// ReplaceAllFunc returns a copy of src in which all matches for the
-// Regexp have been replaced by the return value of of function repl (whose
-// first argument is the matched []byte). No support is provided for
-// expressions (e.g. \1 or $1) in the replacement string.
-func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
- lastMatchEnd := 0 // end position of the most recent match
- searchPos := 0 // position where we next look for a match
- buf := new(bytes.Buffer)
- for searchPos <= len(src) {
- a := re.doExecute(newInputBytes(src), searchPos, 2)
- if len(a) == 0 {
- break // no more matches
- }
-
- // Copy the unmatched characters before this match.
- buf.Write(src[lastMatchEnd:a[0]])
-
- // Now insert a copy of the replacement string, but not for a
- // match of the empty string immediately after another match.
- // (Otherwise, we get double replacement for patterns that
- // match both empty and nonempty strings.)
- if a[1] > lastMatchEnd || a[0] == 0 {
- buf.Write(repl(src[a[0]:a[1]]))
- }
- lastMatchEnd = a[1]
-
- // Advance past this match; always advance at least one character.
- _, width := utf8.DecodeRune(src[searchPos:])
- if searchPos+width > a[1] {
- searchPos += width
- } else if searchPos+1 > a[1] {
- // This clause is only needed at the end of the input
- // string. In that case, DecodeRuneInString returns width=0.
- searchPos++
- } else {
- searchPos = a[1]
- }
- }
-
- // Copy the unmatched characters after the last match.
- buf.Write(src[lastMatchEnd:])
-
- return buf.Bytes()
-}
-
-var specialBytes = []byte(`\.+*?()|[]{}^$`)
-
-func special(b byte) bool {
- return bytes.IndexByte(specialBytes, b) >= 0
-}
-
-// QuoteMeta returns a string that quotes all regular expression metacharacters
-// inside the argument text; the returned string is a regular expression matching
-// the literal text. For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
-func QuoteMeta(s string) string {
- b := make([]byte, 2*len(s))
-
- // A byte loop is correct because all metacharacters are ASCII.
- j := 0
- for i := 0; i < len(s); i++ {
- if special(s[i]) {
- b[j] = '\\'
- j++
- }
- b[j] = s[i]
- j++
- }
- return string(b[0:j])
-}
-
-// Find matches in slice b if b is non-nil, otherwise find matches in string s.
-func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
- var end int
- if b == nil {
- end = len(s)
- } else {
- end = len(b)
- }
-
- for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
- var in input
- if b == nil {
- in = newInputString(s)
- } else {
- in = newInputBytes(b)
- }
- matches := re.doExecute(in, pos, re.prog.NumCap)
- if len(matches) == 0 {
- break
- }
-
- accept := true
- if matches[1] == pos {
- // We've found an empty match.
- if matches[0] == prevMatchEnd {
- // We don't allow an empty match right
- // after a previous match, so ignore it.
- accept = false
- }
- var width int
- // TODO: use step()
- if b == nil {
- _, width = utf8.DecodeRuneInString(s[pos:end])
- } else {
- _, width = utf8.DecodeRune(b[pos:end])
- }
- if width > 0 {
- pos += width
- } else {
- pos = end + 1
- }
- } else {
- pos = matches[1]
- }
- prevMatchEnd = matches[1]
-
- if accept {
- deliver(matches)
- i++
- }
- }
-}
-
-// Find returns a slice holding the text of the leftmost match in b of the regular expression.
-// A return value of nil indicates no match.
-func (re *Regexp) Find(b []byte) []byte {
- a := re.doExecute(newInputBytes(b), 0, 2)
- if a == nil {
- return nil
- }
- return b[a[0]:a[1]]
-}
-
-// FindIndex returns a two-element slice of integers defining the location of
-// the leftmost match in b of the regular expression. The match itself is at
-// b[loc[0]:loc[1]].
-// A return value of nil indicates no match.
-func (re *Regexp) FindIndex(b []byte) (loc []int) {
- a := re.doExecute(newInputBytes(b), 0, 2)
- if a == nil {
- return nil
- }
- return a[0:2]
-}
-
-// FindString returns a string holding the text of the leftmost match in s of the regular
-// expression. If there is no match, the return value is an empty string,
-// but it will also be empty if the regular expression successfully matches
-// an empty string. Use FindStringIndex or FindStringSubmatch if it is
-// necessary to distinguish these cases.
-func (re *Regexp) FindString(s string) string {
- a := re.doExecute(newInputString(s), 0, 2)
- if a == nil {
- return ""
- }
- return s[a[0]:a[1]]
-}
-
-// FindStringIndex returns a two-element slice of integers defining the
-// location of the leftmost match in s of the regular expression. The match
-// itself is at s[loc[0]:loc[1]].
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringIndex(s string) []int {
- a := re.doExecute(newInputString(s), 0, 2)
- if a == nil {
- return nil
- }
- return a[0:2]
-}
-
-// FindReaderIndex returns a two-element slice of integers defining the
-// location of the leftmost match of the regular expression in text read from
-// the RuneReader. The match itself is at s[loc[0]:loc[1]]. A return
-// value of nil indicates no match.
-func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
- a := re.doExecute(newInputReader(r), 0, 2)
- if a == nil {
- return nil
- }
- return a[0:2]
-}
-
-// FindSubmatch returns a slice of slices holding the text of the leftmost
-// match of the regular expression in b and the matches, if any, of its
-// subexpressions, as defined by the 'Submatch' descriptions in the package
-// comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindSubmatch(b []byte) [][]byte {
- a := re.doExecute(newInputBytes(b), 0, re.prog.NumCap)
- if a == nil {
- return nil
- }
- ret := make([][]byte, len(a)/2)
- for i := range ret {
- if a[2*i] >= 0 {
- ret[i] = b[a[2*i]:a[2*i+1]]
- }
- }
- return ret
-}
-
-// FindSubmatchIndex returns a slice holding the index pairs identifying the
-// leftmost match of the regular expression in b and the matches, if any, of
-// its subexpressions, as defined by the 'Submatch' and 'Index' descriptions
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindSubmatchIndex(b []byte) []int {
- return re.doExecute(newInputBytes(b), 0, re.prog.NumCap)
-}
-
-// FindStringSubmatch returns a slice of strings holding the text of the
-// leftmost match of the regular expression in s and the matches, if any, of
-// its subexpressions, as defined by the 'Submatch' description in the
-// package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringSubmatch(s string) []string {
- a := re.doExecute(newInputString(s), 0, re.prog.NumCap)
- if a == nil {
- return nil
- }
- ret := make([]string, len(a)/2)
- for i := range ret {
- if a[2*i] >= 0 {
- ret[i] = s[a[2*i]:a[2*i+1]]
- }
- }
- return ret
-}
-
-// FindStringSubmatchIndex returns a slice holding the index pairs
-// identifying the leftmost match of the regular expression in s and the
-// matches, if any, of its subexpressions, as defined by the 'Submatch' and
-// 'Index' descriptions in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindStringSubmatchIndex(s string) []int {
- return re.doExecute(newInputString(s), 0, re.prog.NumCap)
-}
-
-// FindReaderSubmatchIndex returns a slice holding the index pairs
-// identifying the leftmost match of the regular expression of text read by
-// the RuneReader, and the matches, if any, of its subexpressions, as defined
-// by the 'Submatch' and 'Index' descriptions in the package comment. A
-// return value of nil indicates no match.
-func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
- return re.doExecute(newInputReader(r), 0, re.prog.NumCap)
-}
-
-const startSize = 10 // The size at which to start a slice in the 'All' routines.
-
-// FindAll is the 'All' version of Find; it returns a slice of all successive
-// matches of the expression, as defined by the 'All' description in the
-// package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAll(b []byte, n int) [][]byte {
- if n < 0 {
- n = len(b) + 1
- }
- result := make([][]byte, 0, startSize)
- re.allMatches("", b, n, func(match []int) {
- result = append(result, b[match[0]:match[1]])
- })
- if len(result) == 0 {
- return nil
- }
- return result
-}
-
-// FindAllIndex is the 'All' version of FindIndex; it returns a slice of all
-// successive matches of the expression, as defined by the 'All' description
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllIndex(b []byte, n int) [][]int {
- if n < 0 {
- n = len(b) + 1
- }
- result := make([][]int, 0, startSize)
- re.allMatches("", b, n, func(match []int) {
- result = append(result, match[0:2])
- })
- if len(result) == 0 {
- return nil
- }
- return result
-}
-
-// FindAllString is the 'All' version of FindString; it returns a slice of all
-// successive matches of the expression, as defined by the 'All' description
-// in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllString(s string, n int) []string {
- if n < 0 {
- n = len(s) + 1
- }
- result := make([]string, 0, startSize)
- re.allMatches(s, nil, n, func(match []int) {
- result = append(result, s[match[0]:match[1]])
- })
- if len(result) == 0 {
- return nil
- }
- return result
-}
-
-// FindAllStringIndex is the 'All' version of FindStringIndex; it returns a
-// slice of all successive matches of the expression, as defined by the 'All'
-// description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringIndex(s string, n int) [][]int {
- if n < 0 {
- n = len(s) + 1
- }
- result := make([][]int, 0, startSize)
- re.allMatches(s, nil, n, func(match []int) {
- result = append(result, match[0:2])
- })
- if len(result) == 0 {
- return nil
- }
- return result
-}
-
-// FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice
-// of all successive matches of the expression, as defined by the 'All'
-// description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
- if n < 0 {
- n = len(b) + 1
- }
- result := make([][][]byte, 0, startSize)
- re.allMatches("", b, n, func(match []int) {
- slice := make([][]byte, len(match)/2)
- for j := range slice {
- if match[2*j] >= 0 {
- slice[j] = b[match[2*j]:match[2*j+1]]
- }
- }
- result = append(result, slice)
- })
- if len(result) == 0 {
- return nil
- }
- return result
-}
-
-// FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns
-// a slice of all successive matches of the expression, as defined by the
-// 'All' description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int {
- if n < 0 {
- n = len(b) + 1
- }
- result := make([][]int, 0, startSize)
- re.allMatches("", b, n, func(match []int) {
- result = append(result, match)
- })
- if len(result) == 0 {
- return nil
- }
- return result
-}
-
-// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it
-// returns a slice of all successive matches of the expression, as defined by
-// the 'All' description in the package comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
- if n < 0 {
- n = len(s) + 1
- }
- result := make([][]string, 0, startSize)
- re.allMatches(s, nil, n, func(match []int) {
- slice := make([]string, len(match)/2)
- for j := range slice {
- if match[2*j] >= 0 {
- slice[j] = s[match[2*j]:match[2*j+1]]
- }
- }
- result = append(result, slice)
- })
- if len(result) == 0 {
- return nil
- }
- return result
-}
-
-// FindAllStringSubmatchIndex is the 'All' version of
-// FindStringSubmatchIndex; it returns a slice of all successive matches of
-// the expression, as defined by the 'All' description in the package
-// comment.
-// A return value of nil indicates no match.
-func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
- if n < 0 {
- n = len(s) + 1
- }
- result := make([][]int, 0, startSize)
- re.allMatches(s, nil, n, func(match []int) {
- result = append(result, match)
- })
- if len(result) == 0 {
- return nil
- }
- return result
-}
diff --git a/libgo/go/exp/regexp/syntax/compile.go b/libgo/go/exp/regexp/syntax/compile.go
deleted file mode 100644
index 5ea2425c3aa..00000000000
--- a/libgo/go/exp/regexp/syntax/compile.go
+++ /dev/null
@@ -1,269 +0,0 @@
-package syntax
-
-import (
- "os"
- "unicode"
-)
-
-// A patchList is a list of instruction pointers that need to be filled in (patched).
-// Because the pointers haven't been filled in yet, we can reuse their storage
-// to hold the list. It's kind of sleazy, but works well in practice.
-// See http://swtch.com/~rsc/regexp/regexp1.html for inspiration.
-//
-// These aren't really pointers: they're integers, so we can reinterpret them
-// this way without using package unsafe. A value l denotes
-// p.inst[l>>1].Out (l&1==0) or .Arg (l&1==1).
-// l == 0 denotes the empty list, okay because we start every program
-// with a fail instruction, so we'll never want to point at its output link.
-type patchList uint32
-
-func (l patchList) next(p *Prog) patchList {
- i := &p.Inst[l>>1]
- if l&1 == 0 {
- return patchList(i.Out)
- }
- return patchList(i.Arg)
-}
-
-func (l patchList) patch(p *Prog, val uint32) {
- for l != 0 {
- i := &p.Inst[l>>1]
- if l&1 == 0 {
- l = patchList(i.Out)
- i.Out = val
- } else {
- l = patchList(i.Arg)
- i.Arg = val
- }
- }
-}
-
-func (l1 patchList) append(p *Prog, l2 patchList) patchList {
- if l1 == 0 {
- return l2
- }
- if l2 == 0 {
- return l1
- }
-
- last := l1
- for {
- next := last.next(p)
- if next == 0 {
- break
- }
- last = next
- }
-
- i := &p.Inst[last>>1]
- if last&1 == 0 {
- i.Out = uint32(l2)
- } else {
- i.Arg = uint32(l2)
- }
- return l1
-}
-
-// A frag represents a compiled program fragment.
-type frag struct {
- i uint32 // index of first instruction
- out patchList // where to record end instruction
-}
-
-type compiler struct {
- p *Prog
-}
-
-// Compile compiles the regexp into a program to be executed.
-func Compile(re *Regexp) (*Prog, os.Error) {
- var c compiler
- c.init()
- f := c.compile(re)
- f.out.patch(c.p, c.inst(InstMatch).i)
- c.p.Start = int(f.i)
- return c.p, nil
-}
-
-func (c *compiler) init() {
- c.p = new(Prog)
- c.p.NumCap = 2 // implicit ( and ) for whole match $0
- c.inst(InstFail)
-}
-
-var anyRuneNotNL = []int{0, '\n' - 1, '\n' - 1, unicode.MaxRune}
-var anyRune = []int{0, unicode.MaxRune}
-
-func (c *compiler) compile(re *Regexp) frag {
- switch re.Op {
- case OpNoMatch:
- return c.fail()
- case OpEmptyMatch:
- return c.nop()
- case OpLiteral:
- if len(re.Rune) == 0 {
- return c.nop()
- }
- var f frag
- for j := range re.Rune {
- f1 := c.rune(re.Rune[j : j+1])
- if j == 0 {
- f = f1
- } else {
- f = c.cat(f, f1)
- }
- }
- return f
- case OpCharClass:
- return c.rune(re.Rune)
- case OpAnyCharNotNL:
- return c.rune(anyRuneNotNL)
- case OpAnyChar:
- return c.rune(anyRune)
- case OpBeginLine:
- return c.empty(EmptyBeginLine)
- case OpEndLine:
- return c.empty(EmptyEndLine)
- case OpBeginText:
- return c.empty(EmptyBeginText)
- case OpEndText:
- return c.empty(EmptyEndText)
- case OpWordBoundary:
- return c.empty(EmptyWordBoundary)
- case OpNoWordBoundary:
- return c.empty(EmptyNoWordBoundary)
- case OpCapture:
- bra := c.cap(uint32(re.Cap << 1))
- sub := c.compile(re.Sub[0])
- ket := c.cap(uint32(re.Cap<<1 | 1))
- return c.cat(c.cat(bra, sub), ket)
- case OpStar:
- return c.star(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
- case OpPlus:
- return c.plus(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
- case OpQuest:
- return c.quest(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
- case OpConcat:
- if len(re.Sub) == 0 {
- return c.nop()
- }
- var f frag
- for i, sub := range re.Sub {
- if i == 0 {
- f = c.compile(sub)
- } else {
- f = c.cat(f, c.compile(sub))
- }
- }
- return f
- case OpAlternate:
- var f frag
- for _, sub := range re.Sub {
- f = c.alt(f, c.compile(sub))
- }
- return f
- }
- panic("regexp: unhandled case in compile")
-}
-
-func (c *compiler) inst(op InstOp) frag {
- // TODO: impose length limit
- f := frag{i: uint32(len(c.p.Inst))}
- c.p.Inst = append(c.p.Inst, Inst{Op: op})
- return f
-}
-
-func (c *compiler) nop() frag {
- f := c.inst(InstNop)
- f.out = patchList(f.i << 1)
- return f
-}
-
-func (c *compiler) fail() frag {
- return frag{}
-}
-
-func (c *compiler) cap(arg uint32) frag {
- f := c.inst(InstCapture)
- f.out = patchList(f.i << 1)
- c.p.Inst[f.i].Arg = arg
-
- if c.p.NumCap < int(arg)+1 {
- c.p.NumCap = int(arg) + 1
- }
- return f
-}
-
-func (c *compiler) cat(f1, f2 frag) frag {
- // concat of failure is failure
- if f1.i == 0 || f2.i == 0 {
- return frag{}
- }
-
- // TODO: elide nop
-
- f1.out.patch(c.p, f2.i)
- return frag{f1.i, f2.out}
-}
-
-func (c *compiler) alt(f1, f2 frag) frag {
- // alt of failure is other
- if f1.i == 0 {
- return f2
- }
- if f2.i == 0 {
- return f1
- }
-
- f := c.inst(InstAlt)
- i := &c.p.Inst[f.i]
- i.Out = f1.i
- i.Arg = f2.i
- f.out = f1.out.append(c.p, f2.out)
- return f
-}
-
-func (c *compiler) quest(f1 frag, nongreedy bool) frag {
- f := c.inst(InstAlt)
- i := &c.p.Inst[f.i]
- if nongreedy {
- i.Arg = f1.i
- f.out = patchList(f.i << 1)
- } else {
- i.Out = f1.i
- f.out = patchList(f.i<<1 | 1)
- }
- f.out = f.out.append(c.p, f1.out)
- return f
-}
-
-func (c *compiler) star(f1 frag, nongreedy bool) frag {
- f := c.inst(InstAlt)
- i := &c.p.Inst[f.i]
- if nongreedy {
- i.Arg = f1.i
- f.out = patchList(f.i << 1)
- } else {
- i.Out = f1.i
- f.out = patchList(f.i<<1 | 1)
- }
- f1.out.patch(c.p, f.i)
- return f
-}
-
-func (c *compiler) plus(f1 frag, nongreedy bool) frag {
- return frag{f1.i, c.star(f1, nongreedy).out}
-}
-
-func (c *compiler) empty(op EmptyOp) frag {
- f := c.inst(InstEmptyWidth)
- c.p.Inst[f.i].Arg = uint32(op)
- f.out = patchList(f.i << 1)
- return f
-}
-
-func (c *compiler) rune(rune []int) frag {
- f := c.inst(InstRune)
- c.p.Inst[f.i].Rune = rune
- f.out = patchList(f.i << 1)
- return f
-}
diff --git a/libgo/go/exp/regexp/syntax/parse.go b/libgo/go/exp/regexp/syntax/parse.go
deleted file mode 100644
index 4eed182687b..00000000000
--- a/libgo/go/exp/regexp/syntax/parse.go
+++ /dev/null
@@ -1,1797 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syntax
-
-import (
- "os"
- "sort"
- "strings"
- "unicode"
- "utf8"
-)
-
-// An Error describes a failure to parse a regular expression
-// and gives the offending expression.
-type Error struct {
- Code ErrorCode
- Expr string
-}
-
-func (e *Error) String() string {
- return "error parsing regexp: " + e.Code.String() + ": `" + e.Expr + "`"
-}
-
-// An ErrorCode describes a failure to parse a regular expression.
-type ErrorCode string
-
-const (
- // Unexpected error
- ErrInternalError ErrorCode = "regexp/syntax: internal error"
-
- // Parse errors
- ErrInvalidCharClass ErrorCode = "invalid character class"
- ErrInvalidCharRange ErrorCode = "invalid character class range"
- ErrInvalidEscape ErrorCode = "invalid escape sequence"
- ErrInvalidNamedCapture ErrorCode = "invalid named capture"
- ErrInvalidPerlOp ErrorCode = "invalid or unsupported Perl syntax"
- ErrInvalidRepeatOp ErrorCode = "invalid nested repetition operator"
- ErrInvalidRepeatSize ErrorCode = "invalid repeat count"
- ErrInvalidUTF8 ErrorCode = "invalid UTF-8"
- ErrMissingBracket ErrorCode = "missing closing ]"
- ErrMissingParen ErrorCode = "missing closing )"
- ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator"
- ErrTrailingBackslash ErrorCode = "trailing backslash at end of expression"
-)
-
-func (e ErrorCode) String() string {
- return string(e)
-}
-
-// Flags control the behavior of the parser and record information about regexp context.
-type Flags uint16
-
-const (
- FoldCase Flags = 1 << iota // case-insensitive match
- Literal // treat pattern as literal string
- ClassNL // allow character classes like [^a-z] and [[:space:]] to match newline
- DotNL // allow . to match newline
- OneLine // treat ^ and $ as only matching at beginning and end of text
- NonGreedy // make repetition operators default to non-greedy
- PerlX // allow Perl extensions
- UnicodeGroups // allow \p{Han}, \P{Han} for Unicode group and negation
- WasDollar // regexp OpEndText was $, not \z
- Simple // regexp contains no counted repetition
-
- MatchNL = ClassNL | DotNL
-
- Perl = ClassNL | OneLine | PerlX | UnicodeGroups // as close to Perl as possible
- POSIX Flags = 0 // POSIX syntax
-)
-
-// Pseudo-ops for parsing stack.
-const (
- opLeftParen = opPseudo + iota
- opVerticalBar
-)
-
-type parser struct {
- flags Flags // parse mode flags
- stack []*Regexp // stack of parsed expressions
- free *Regexp
- numCap int // number of capturing groups seen
- wholeRegexp string
- tmpClass []int // temporary char class work space
-}
-
-func (p *parser) newRegexp(op Op) *Regexp {
- re := p.free
- if re != nil {
- p.free = re.Sub0[0]
- *re = Regexp{}
- } else {
- re = new(Regexp)
- }
- re.Op = op
- return re
-}
-
-func (p *parser) reuse(re *Regexp) {
- re.Sub0[0] = p.free
- p.free = re
-}
-
-// Parse stack manipulation.
-
-// push pushes the regexp re onto the parse stack and returns the regexp.
-func (p *parser) push(re *Regexp) *Regexp {
- if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
- // Single rune.
- if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
- return nil
- }
- re.Op = OpLiteral
- re.Rune = re.Rune[:1]
- re.Flags = p.flags &^ FoldCase
- } else if re.Op == OpCharClass && len(re.Rune) == 4 &&
- re.Rune[0] == re.Rune[1] && re.Rune[2] == re.Rune[3] &&
- unicode.SimpleFold(re.Rune[0]) == re.Rune[2] &&
- unicode.SimpleFold(re.Rune[2]) == re.Rune[0] ||
- re.Op == OpCharClass && len(re.Rune) == 2 &&
- re.Rune[0]+1 == re.Rune[1] &&
- unicode.SimpleFold(re.Rune[0]) == re.Rune[1] &&
- unicode.SimpleFold(re.Rune[1]) == re.Rune[0] {
- // Case-insensitive rune like [Aa] or [Δδ].
- if p.maybeConcat(re.Rune[0], p.flags|FoldCase) {
- return nil
- }
-
- // Rewrite as (case-insensitive) literal.
- re.Op = OpLiteral
- re.Rune = re.Rune[:1]
- re.Flags = p.flags | FoldCase
- } else {
- // Incremental concatenation.
- p.maybeConcat(-1, 0)
- }
-
- p.stack = append(p.stack, re)
- return re
-}
-
-// maybeConcat implements incremental concatenation
-// of literal runes into string nodes. The parser calls this
-// before each push, so only the top fragment of the stack
-// might need processing. Since this is called before a push,
-// the topmost literal is no longer subject to operators like *
-// (Otherwise ab* would turn into (ab)*.)
-// If r >= 0 and there's a node left over, maybeConcat uses it
-// to push r with the given flags.
-// maybeConcat reports whether r was pushed.
-func (p *parser) maybeConcat(r int, flags Flags) bool {
- n := len(p.stack)
- if n < 2 {
- return false
- }
-
- re1 := p.stack[n-1]
- re2 := p.stack[n-2]
- if re1.Op != OpLiteral || re2.Op != OpLiteral || re1.Flags&FoldCase != re2.Flags&FoldCase {
- return false
- }
-
- // Push re1 into re2.
- re2.Rune = append(re2.Rune, re1.Rune...)
-
- // Reuse re1 if possible.
- if r >= 0 {
- re1.Rune = re1.Rune0[:1]
- re1.Rune[0] = r
- re1.Flags = flags
- return true
- }
-
- p.stack = p.stack[:n-1]
- p.reuse(re1)
- return false // did not push r
-}
-
-// newLiteral returns a new OpLiteral Regexp with the given flags
-func (p *parser) newLiteral(r int, flags Flags) *Regexp {
- re := p.newRegexp(OpLiteral)
- re.Flags = flags
- re.Rune0[0] = r
- re.Rune = re.Rune0[:1]
- return re
-}
-
-// literal pushes a literal regexp for the rune r on the stack
-// and returns that regexp.
-func (p *parser) literal(r int) {
- p.push(p.newLiteral(r, p.flags))
-}
-
-// op pushes a regexp with the given op onto the stack
-// and returns that regexp.
-func (p *parser) op(op Op) *Regexp {
- re := p.newRegexp(op)
- re.Flags = p.flags
- return p.push(re)
-}
-
-// repeat replaces the top stack element with itself repeated
-// according to op.
-func (p *parser) repeat(op Op, min, max int, opstr, t, lastRepeat string) (string, os.Error) {
- flags := p.flags
- if p.flags&PerlX != 0 {
- if len(t) > 0 && t[0] == '?' {
- t = t[1:]
- flags ^= NonGreedy
- }
- if lastRepeat != "" {
- // In Perl it is not allowed to stack repetition operators:
- // a** is a syntax error, not a doubled star, and a++ means
- // something else entirely, which we don't support!
- return "", &Error{ErrInvalidRepeatOp, lastRepeat[:len(lastRepeat)-len(t)]}
- }
- }
- n := len(p.stack)
- if n == 0 {
- return "", &Error{ErrMissingRepeatArgument, opstr}
- }
- sub := p.stack[n-1]
- re := p.newRegexp(op)
- re.Min = min
- re.Max = max
- re.Flags = flags
- re.Sub = re.Sub0[:1]
- re.Sub[0] = sub
- p.stack[n-1] = re
- return t, nil
-}
-
-// concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation.
-func (p *parser) concat() *Regexp {
- p.maybeConcat(-1, 0)
-
- // Scan down to find pseudo-operator | or (.
- i := len(p.stack)
- for i > 0 && p.stack[i-1].Op < opPseudo {
- i--
- }
- subs := p.stack[i:]
- p.stack = p.stack[:i]
-
- // Empty concatenation is special case.
- if len(subs) == 0 {
- return p.push(p.newRegexp(OpEmptyMatch))
- }
-
- return p.push(p.collapse(subs, OpConcat))
-}
-
-// alternate replaces the top of the stack (above the topmost '(') with its alternation.
-func (p *parser) alternate() *Regexp {
- // Scan down to find pseudo-operator (.
- // There are no | above (.
- i := len(p.stack)
- for i > 0 && p.stack[i-1].Op < opPseudo {
- i--
- }
- subs := p.stack[i:]
- p.stack = p.stack[:i]
-
- // Make sure top class is clean.
- // All the others already are (see swapVerticalBar).
- if len(subs) > 0 {
- cleanAlt(subs[len(subs)-1])
- }
-
- // Empty alternate is special case
- // (shouldn't happen but easy to handle).
- if len(subs) == 0 {
- return p.push(p.newRegexp(OpNoMatch))
- }
-
- return p.push(p.collapse(subs, OpAlternate))
-}
-
-// cleanAlt cleans re for eventual inclusion in an alternation.
-func cleanAlt(re *Regexp) {
- switch re.Op {
- case OpCharClass:
- re.Rune = cleanClass(&re.Rune)
- if len(re.Rune) == 2 && re.Rune[0] == 0 && re.Rune[1] == unicode.MaxRune {
- re.Rune = nil
- re.Op = OpAnyChar
- return
- }
- if len(re.Rune) == 4 && re.Rune[0] == 0 && re.Rune[1] == '\n'-1 && re.Rune[2] == '\n'+1 && re.Rune[3] == unicode.MaxRune {
- re.Rune = nil
- re.Op = OpAnyCharNotNL
- return
- }
- if cap(re.Rune)-len(re.Rune) > 100 {
- // re.Rune will not grow any more.
- // Make a copy or inline to reclaim storage.
- re.Rune = append(re.Rune0[:0], re.Rune...)
- }
- }
-}
-
-// collapse returns the result of applying op to sub.
-// If sub contains op nodes, they all get hoisted up
-// so that there is never a concat of a concat or an
-// alternate of an alternate.
-func (p *parser) collapse(subs []*Regexp, op Op) *Regexp {
- if len(subs) == 1 {
- return subs[0]
- }
- re := p.newRegexp(op)
- re.Sub = re.Sub0[:0]
- for _, sub := range subs {
- if sub.Op == op {
- re.Sub = append(re.Sub, sub.Sub...)
- p.reuse(sub)
- } else {
- re.Sub = append(re.Sub, sub)
- }
- }
- if op == OpAlternate {
- re.Sub = p.factor(re.Sub, re.Flags)
- if len(re.Sub) == 1 {
- old := re
- re = re.Sub[0]
- p.reuse(old)
- }
- }
- return re
-}
-
-// factor factors common prefixes from the alternation list sub.
-// It returns a replacement list that reuses the same storage and
-// frees (passes to p.reuse) any removed *Regexps.
-//
-// For example,
-// ABC|ABD|AEF|BCX|BCY
-// simplifies by literal prefix extraction to
-// A(B(C|D)|EF)|BC(X|Y)
-// which simplifies by character class introduction to
-// A(B[CD]|EF)|BC[XY]
-//
-func (p *parser) factor(sub []*Regexp, flags Flags) []*Regexp {
- if len(sub) < 2 {
- return sub
- }
-
- // Round 1: Factor out common literal prefixes.
- var str []int
- var strflags Flags
- start := 0
- out := sub[:0]
- for i := 0; i <= len(sub); i++ {
- // Invariant: the Regexps that were in sub[0:start] have been
- // used or marked for reuse, and the slice space has been reused
- // for out (len(out) <= start).
- //
- // Invariant: sub[start:i] consists of regexps that all begin
- // with str as modified by strflags.
- var istr []int
- var iflags Flags
- if i < len(sub) {
- istr, iflags = p.leadingString(sub[i])
- if iflags == strflags {
- same := 0
- for same < len(str) && same < len(istr) && str[same] == istr[same] {
- same++
- }
- if same > 0 {
- // Matches at least one rune in current range.
- // Keep going around.
- str = str[:same]
- continue
- }
- }
- }
-
- // Found end of a run with common leading literal string:
- // sub[start:i] all begin with str[0:len(str)], but sub[i]
- // does not even begin with str[0].
- //
- // Factor out common string and append factored expression to out.
- if i == start {
- // Nothing to do - run of length 0.
- } else if i == start+1 {
- // Just one: don't bother factoring.
- out = append(out, sub[start])
- } else {
- // Construct factored form: prefix(suffix1|suffix2|...)
- prefix := p.newRegexp(OpLiteral)
- prefix.Flags = strflags
- prefix.Rune = append(prefix.Rune[:0], str...)
-
- for j := start; j < i; j++ {
- sub[j] = p.removeLeadingString(sub[j], len(str))
- }
- suffix := p.collapse(sub[start:i], OpAlternate) // recurse
-
- re := p.newRegexp(OpConcat)
- re.Sub = append(re.Sub[:0], prefix, suffix)
- out = append(out, re)
- }
-
- // Prepare for next iteration.
- start = i
- str = istr
- strflags = iflags
- }
- sub = out
-
- // Round 2: Factor out common complex prefixes,
- // just the first piece of each concatenation,
- // whatever it is. This is good enough a lot of the time.
- start = 0
- out = sub[:0]
- var first *Regexp
- for i := 0; i <= len(sub); i++ {
- // Invariant: the Regexps that were in sub[0:start] have been
- // used or marked for reuse, and the slice space has been reused
- // for out (len(out) <= start).
- //
- // Invariant: sub[start:i] consists of regexps that all begin
- // with str as modified by strflags.
- var ifirst *Regexp
- if i < len(sub) {
- ifirst = p.leadingRegexp(sub[i])
- if first != nil && first.Equal(ifirst) {
- continue
- }
- }
-
- // Found end of a run with common leading regexp:
- // sub[start:i] all begin with first but sub[i] does not.
- //
- // Factor out common regexp and append factored expression to out.
- if i == start {
- // Nothing to do - run of length 0.
- } else if i == start+1 {
- // Just one: don't bother factoring.
- out = append(out, sub[start])
- } else {
- // Construct factored form: prefix(suffix1|suffix2|...)
- prefix := first
-
- for j := start; j < i; j++ {
- reuse := j != start // prefix came from sub[start]
- sub[j] = p.removeLeadingRegexp(sub[j], reuse)
- }
- suffix := p.collapse(sub[start:i], OpAlternate) // recurse
-
- re := p.newRegexp(OpConcat)
- re.Sub = append(re.Sub[:0], prefix, suffix)
- out = append(out, re)
- }
-
- // Prepare for next iteration.
- start = i
- first = ifirst
- }
- sub = out
-
- // Round 3: Collapse runs of single literals into character classes.
- start = 0
- out = sub[:0]
- for i := 0; i <= len(sub); i++ {
- // Invariant: the Regexps that were in sub[0:start] have been
- // used or marked for reuse, and the slice space has been reused
- // for out (len(out) <= start).
- //
- // Invariant: sub[start:i] consists of regexps that are either
- // literal runes or character classes.
- if i < len(sub) && isCharClass(sub[i]) {
- continue
- }
-
- // sub[i] is not a char or char class;
- // emit char class for sub[start:i]...
- if i == start {
- // Nothing to do - run of length 0.
- } else if i == start+1 {
- out = append(out, sub[start])
- } else {
- // Make new char class.
- // Start with most complex regexp in sub[start].
- max := start
- for j := start + 1; j < i; j++ {
- if sub[max].Op < sub[j].Op || sub[max].Op == sub[j].Op && len(sub[max].Rune) < len(sub[j].Rune) {
- max = j
- }
- }
- sub[start], sub[max] = sub[max], sub[start]
-
- for j := start + 1; j < i; j++ {
- mergeCharClass(sub[start], sub[j])
- p.reuse(sub[j])
- }
- cleanAlt(sub[start])
- out = append(out, sub[start])
- }
-
- // ... and then emit sub[i].
- if i < len(sub) {
- out = append(out, sub[i])
- }
- start = i + 1
- }
- sub = out
-
- // Round 4: Collapse runs of empty matches into a single empty match.
- start = 0
- out = sub[:0]
- for i := range sub {
- if i+1 < len(sub) && sub[i].Op == OpEmptyMatch && sub[i+1].Op == OpEmptyMatch {
- continue
- }
- out = append(out, sub[i])
- }
- sub = out
-
- return sub
-}
-
-// leadingString returns the leading literal string that re begins with.
-// The string refers to storage in re or its children.
-func (p *parser) leadingString(re *Regexp) ([]int, Flags) {
- if re.Op == OpConcat && len(re.Sub) > 0 {
- re = re.Sub[0]
- }
- if re.Op != OpLiteral {
- return nil, 0
- }
- return re.Rune, re.Flags & FoldCase
-}
-
-// removeLeadingString removes the first n leading runes
-// from the beginning of re. It returns the replacement for re.
-func (p *parser) removeLeadingString(re *Regexp, n int) *Regexp {
- if re.Op == OpConcat && len(re.Sub) > 0 {
- // Removing a leading string in a concatenation
- // might simplify the concatenation.
- sub := re.Sub[0]
- sub = p.removeLeadingString(sub, n)
- re.Sub[0] = sub
- if sub.Op == OpEmptyMatch {
- p.reuse(sub)
- switch len(re.Sub) {
- case 0, 1:
- // Impossible but handle.
- re.Op = OpEmptyMatch
- re.Sub = nil
- case 2:
- old := re
- re = re.Sub[1]
- p.reuse(old)
- default:
- copy(re.Sub, re.Sub[1:])
- re.Sub = re.Sub[:len(re.Sub)-1]
- }
- }
- return re
- }
-
- if re.Op == OpLiteral {
- re.Rune = re.Rune[:copy(re.Rune, re.Rune[n:])]
- if len(re.Rune) == 0 {
- re.Op = OpEmptyMatch
- }
- }
- return re
-}
-
-// leadingRegexp returns the leading regexp that re begins with.
-// The regexp refers to storage in re or its children.
-func (p *parser) leadingRegexp(re *Regexp) *Regexp {
- if re.Op == OpEmptyMatch {
- return nil
- }
- if re.Op == OpConcat && len(re.Sub) > 0 {
- sub := re.Sub[0]
- if sub.Op == OpEmptyMatch {
- return nil
- }
- return sub
- }
- return re
-}
-
-// removeLeadingRegexp removes the leading regexp in re.
-// It returns the replacement for re.
-// If reuse is true, it passes the removed regexp (if no longer needed) to p.reuse.
-func (p *parser) removeLeadingRegexp(re *Regexp, reuse bool) *Regexp {
- if re.Op == OpConcat && len(re.Sub) > 0 {
- if reuse {
- p.reuse(re.Sub[0])
- }
- re.Sub = re.Sub[:copy(re.Sub, re.Sub[1:])]
- switch len(re.Sub) {
- case 0:
- re.Op = OpEmptyMatch
- re.Sub = nil
- case 1:
- old := re
- re = re.Sub[0]
- p.reuse(old)
- }
- return re
- }
- re.Op = OpEmptyMatch
- return re
-}
-
-func literalRegexp(s string, flags Flags) *Regexp {
- re := &Regexp{Op: OpLiteral}
- re.Flags = flags
- re.Rune = re.Rune0[:0] // use local storage for small strings
- for _, c := range s {
- if len(re.Rune) >= cap(re.Rune) {
- // string is too long to fit in Rune0. let Go handle it
- re.Rune = []int(s)
- break
- }
- re.Rune = append(re.Rune, c)
- }
- return re
-}
-
-// Parsing.
-
-func Parse(s string, flags Flags) (*Regexp, os.Error) {
- if flags&Literal != 0 {
- // Trivial parser for literal string.
- if err := checkUTF8(s); err != nil {
- return nil, err
- }
- return literalRegexp(s, flags), nil
- }
-
- // Otherwise, must do real work.
- var (
- p parser
- err os.Error
- c int
- op Op
- lastRepeat string
- min, max int
- )
- p.flags = flags
- p.wholeRegexp = s
- t := s
- for t != "" {
- repeat := ""
- BigSwitch:
- switch t[0] {
- default:
- if c, t, err = nextRune(t); err != nil {
- return nil, err
- }
- p.literal(c)
-
- case '(':
- if p.flags&PerlX != 0 && len(t) >= 2 && t[1] == '?' {
- // Flag changes and non-capturing groups.
- if t, err = p.parsePerlFlags(t); err != nil {
- return nil, err
- }
- break
- }
- p.numCap++
- p.op(opLeftParen).Cap = p.numCap
- t = t[1:]
- case '|':
- if err = p.parseVerticalBar(); err != nil {
- return nil, err
- }
- t = t[1:]
- case ')':
- if err = p.parseRightParen(); err != nil {
- return nil, err
- }
- t = t[1:]
- case '^':
- if p.flags&OneLine != 0 {
- p.op(OpBeginText)
- } else {
- p.op(OpBeginLine)
- }
- t = t[1:]
- case '$':
- if p.flags&OneLine != 0 {
- p.op(OpEndText).Flags |= WasDollar
- } else {
- p.op(OpEndLine)
- }
- t = t[1:]
- case '.':
- if p.flags&DotNL != 0 {
- p.op(OpAnyChar)
- } else {
- p.op(OpAnyCharNotNL)
- }
- t = t[1:]
- case '[':
- if t, err = p.parseClass(t); err != nil {
- return nil, err
- }
- case '*', '+', '?':
- switch t[0] {
- case '*':
- op = OpStar
- case '+':
- op = OpPlus
- case '?':
- op = OpQuest
- }
- if t, err = p.repeat(op, min, max, t[:1], t[1:], lastRepeat); err != nil {
- return nil, err
- }
- case '{':
- op = OpRepeat
- min, max, tt, ok := p.parseRepeat(t)
- if !ok {
- // If the repeat cannot be parsed, { is a literal.
- p.literal('{')
- t = t[1:]
- break
- }
- if t, err = p.repeat(op, min, max, t[:len(t)-len(tt)], tt, lastRepeat); err != nil {
- return nil, err
- }
- case '\\':
- if p.flags&PerlX != 0 && len(t) >= 2 {
- switch t[1] {
- case 'A':
- p.op(OpBeginText)
- t = t[2:]
- break BigSwitch
- case 'b':
- p.op(OpWordBoundary)
- t = t[2:]
- break BigSwitch
- case 'B':
- p.op(OpNoWordBoundary)
- t = t[2:]
- break BigSwitch
- case 'C':
- // any byte; not supported
- return nil, &Error{ErrInvalidEscape, t[:2]}
- case 'Q':
- // \Q ... \E: the ... is always literals
- var lit string
- if i := strings.Index(t, `\E`); i < 0 {
- lit = t[2:]
- t = ""
- } else {
- lit = t[2:i]
- t = t[i+2:]
- }
- p.push(literalRegexp(lit, p.flags))
- break BigSwitch
- case 'z':
- p.op(OpEndText)
- t = t[2:]
- break BigSwitch
- }
- }
-
- re := p.newRegexp(OpCharClass)
- re.Flags = p.flags
-
- // Look for Unicode character group like \p{Han}
- if len(t) >= 2 && (t[1] == 'p' || t[1] == 'P') {
- r, rest, err := p.parseUnicodeClass(t, re.Rune0[:0])
- if err != nil {
- return nil, err
- }
- if r != nil {
- re.Rune = r
- t = rest
- p.push(re)
- break BigSwitch
- }
- }
-
- // Perl character class escape.
- if r, rest := p.parsePerlClassEscape(t, re.Rune0[:0]); r != nil {
- re.Rune = r
- t = rest
- p.push(re)
- break BigSwitch
- }
- p.reuse(re)
-
- // Ordinary single-character escape.
- if c, t, err = p.parseEscape(t); err != nil {
- return nil, err
- }
- p.literal(c)
- }
- lastRepeat = repeat
- }
-
- p.concat()
- if p.swapVerticalBar() {
- // pop vertical bar
- p.stack = p.stack[:len(p.stack)-1]
- }
- p.alternate()
-
- n := len(p.stack)
- if n != 1 {
- return nil, &Error{ErrMissingParen, s}
- }
- return p.stack[0], nil
-}
-
-// parseRepeat parses {min} (max=min) or {min,} (max=-1) or {min,max}.
-// If s is not of that form, it returns ok == false.
-func (p *parser) parseRepeat(s string) (min, max int, rest string, ok bool) {
- if s == "" || s[0] != '{' {
- return
- }
- s = s[1:]
- if min, s, ok = p.parseInt(s); !ok {
- return
- }
- if s == "" {
- return
- }
- if s[0] != ',' {
- max = min
- } else {
- s = s[1:]
- if s == "" {
- return
- }
- if s[0] == '}' {
- max = -1
- } else if max, s, ok = p.parseInt(s); !ok {
- return
- }
- }
- if s == "" || s[0] != '}' {
- return
- }
- rest = s[1:]
- ok = true
- return
-}
-
-// parsePerlFlags parses a Perl flag setting or non-capturing group or both,
-// like (?i) or (?: or (?i:. It removes the prefix from s and updates the parse state.
-// The caller must have ensured that s begins with "(?".
-func (p *parser) parsePerlFlags(s string) (rest string, err os.Error) {
- t := s
-
- // Check for named captures, first introduced in Python's regexp library.
- // As usual, there are three slightly different syntaxes:
- //
- // (?P<name>expr) the original, introduced by Python
- // (?<name>expr) the .NET alteration, adopted by Perl 5.10
- // (?'name'expr) another .NET alteration, adopted by Perl 5.10
- //
- // Perl 5.10 gave in and implemented the Python version too,
- // but they claim that the last two are the preferred forms.
- // PCRE and languages based on it (specifically, PHP and Ruby)
- // support all three as well. EcmaScript 4 uses only the Python form.
- //
- // In both the open source world (via Code Search) and the
- // Google source tree, (?P<expr>name) is the dominant form,
- // so that's the one we implement. One is enough.
- if len(t) > 4 && t[2] == 'P' && t[3] == '<' {
- // Pull out name.
- end := strings.IndexRune(t, '>')
- if end < 0 {
- if err = checkUTF8(t); err != nil {
- return "", err
- }
- return "", &Error{ErrInvalidNamedCapture, s}
- }
-
- capture := t[:end+1] // "(?P<name>"
- name := t[4:end] // "name"
- if err = checkUTF8(name); err != nil {
- return "", err
- }
- if !isValidCaptureName(name) {
- return "", &Error{ErrInvalidNamedCapture, capture}
- }
-
- // Like ordinary capture, but named.
- p.numCap++
- re := p.op(opLeftParen)
- re.Cap = p.numCap
- re.Name = name
- return t[end+1:], nil
- }
-
- // Non-capturing group. Might also twiddle Perl flags.
- var c int
- t = t[2:] // skip (?
- flags := p.flags
- sign := +1
- sawFlag := false
-Loop:
- for t != "" {
- if c, t, err = nextRune(t); err != nil {
- return "", err
- }
- switch c {
- default:
- break Loop
-
- // Flags.
- case 'i':
- flags |= FoldCase
- sawFlag = true
- case 'm':
- flags &^= OneLine
- sawFlag = true
- case 's':
- flags |= DotNL
- sawFlag = true
- case 'U':
- flags |= NonGreedy
- sawFlag = true
-
- // Switch to negation.
- case '-':
- if sign < 0 {
- break Loop
- }
- sign = -1
- // Invert flags so that | above turn into &^ and vice versa.
- // We'll invert flags again before using it below.
- flags = ^flags
- sawFlag = false
-
- // End of flags, starting group or not.
- case ':', ')':
- if sign < 0 {
- if !sawFlag {
- break Loop
- }
- flags = ^flags
- }
- if c == ':' {
- // Open new group
- p.op(opLeftParen)
- }
- p.flags = flags
- return t, nil
- }
- }
-
- return "", &Error{ErrInvalidPerlOp, s[:len(s)-len(t)]}
-}
-
-// isValidCaptureName reports whether name
-// is a valid capture name: [A-Za-z0-9_]+.
-// PCRE limits names to 32 bytes.
-// Python rejects names starting with digits.
-// We don't enforce either of those.
-func isValidCaptureName(name string) bool {
- if name == "" {
- return false
- }
- for _, c := range name {
- if c != '_' && !isalnum(c) {
- return false
- }
- }
- return true
-}
-
-// parseInt parses a decimal integer.
-func (p *parser) parseInt(s string) (n int, rest string, ok bool) {
- if s == "" || s[0] < '0' || '9' < s[0] {
- return
- }
- // Disallow leading zeros.
- if len(s) >= 2 && s[0] == '0' && '0' <= s[1] && s[1] <= '9' {
- return
- }
- for s != "" && '0' <= s[0] && s[0] <= '9' {
- // Avoid overflow.
- if n >= 1e8 {
- return
- }
- n = n*10 + int(s[0]) - '0'
- s = s[1:]
- }
- rest = s
- ok = true
- return
-}
-
-// can this be represented as a character class?
-// single-rune literal string, char class, ., and .|\n.
-func isCharClass(re *Regexp) bool {
- return re.Op == OpLiteral && len(re.Rune) == 1 ||
- re.Op == OpCharClass ||
- re.Op == OpAnyCharNotNL ||
- re.Op == OpAnyChar
-}
-
-// does re match r?
-func matchRune(re *Regexp, r int) bool {
- switch re.Op {
- case OpLiteral:
- return len(re.Rune) == 1 && re.Rune[0] == r
- case OpCharClass:
- for i := 0; i < len(re.Rune); i += 2 {
- if re.Rune[i] <= r && r <= re.Rune[i+1] {
- return true
- }
- }
- return false
- case OpAnyCharNotNL:
- return r != '\n'
- case OpAnyChar:
- return true
- }
- return false
-}
-
-// parseVerticalBar handles a | in the input.
-func (p *parser) parseVerticalBar() os.Error {
- p.concat()
-
- // The concatenation we just parsed is on top of the stack.
- // If it sits above an opVerticalBar, swap it below
- // (things below an opVerticalBar become an alternation).
- // Otherwise, push a new vertical bar.
- if !p.swapVerticalBar() {
- p.op(opVerticalBar)
- }
-
- return nil
-}
-
-// mergeCharClass makes dst = dst|src.
-// The caller must ensure that dst.Op >= src.Op,
-// to reduce the amount of copying.
-func mergeCharClass(dst, src *Regexp) {
- switch dst.Op {
- case OpAnyChar:
- // src doesn't add anything.
- case OpAnyCharNotNL:
- // src might add \n
- if matchRune(src, '\n') {
- dst.Op = OpAnyChar
- }
- case OpCharClass:
- // src is simpler, so either literal or char class
- if src.Op == OpLiteral {
- dst.Rune = appendRange(dst.Rune, src.Rune[0], src.Rune[0])
- } else {
- dst.Rune = appendClass(dst.Rune, src.Rune)
- }
- case OpLiteral:
- // both literal
- if src.Rune[0] == dst.Rune[0] {
- break
- }
- dst.Op = OpCharClass
- dst.Rune = append(dst.Rune, dst.Rune[0])
- dst.Rune = appendRange(dst.Rune, src.Rune[0], src.Rune[0])
- }
-}
-
-// If the top of the stack is an element followed by an opVerticalBar
-// swapVerticalBar swaps the two and returns true.
-// Otherwise it returns false.
-func (p *parser) swapVerticalBar() bool {
- // If above and below vertical bar are literal or char class,
- // can merge into a single char class.
- n := len(p.stack)
- if n >= 3 && p.stack[n-2].Op == opVerticalBar && isCharClass(p.stack[n-1]) && isCharClass(p.stack[n-3]) {
- re1 := p.stack[n-1]
- re3 := p.stack[n-3]
- // Make re3 the more complex of the two.
- if re1.Op > re3.Op {
- re1, re3 = re3, re1
- p.stack[n-3] = re3
- }
- mergeCharClass(re3, re1)
- p.reuse(re1)
- p.stack = p.stack[:n-1]
- return true
- }
-
- if n >= 2 {
- re1 := p.stack[n-1]
- re2 := p.stack[n-2]
- if re2.Op == opVerticalBar {
- if n >= 3 {
- // Now out of reach.
- // Clean opportunistically.
- cleanAlt(p.stack[n-3])
- }
- p.stack[n-2] = re1
- p.stack[n-1] = re2
- return true
- }
- }
- return false
-}
-
-// parseRightParen handles a ) in the input.
-func (p *parser) parseRightParen() os.Error {
- p.concat()
- if p.swapVerticalBar() {
- // pop vertical bar
- p.stack = p.stack[:len(p.stack)-1]
- }
- p.alternate()
-
- n := len(p.stack)
- if n < 2 {
- return &Error{ErrInternalError, ""}
- }
- re1 := p.stack[n-1]
- re2 := p.stack[n-2]
- p.stack = p.stack[:n-2]
- if re2.Op != opLeftParen {
- return &Error{ErrMissingParen, p.wholeRegexp}
- }
- if re2.Cap == 0 {
- // Just for grouping.
- p.push(re1)
- } else {
- re2.Op = OpCapture
- re2.Sub = re2.Sub0[:1]
- re2.Sub[0] = re1
- p.push(re2)
- }
- return nil
-}
-
-// parseEscape parses an escape sequence at the beginning of s
-// and returns the rune.
-func (p *parser) parseEscape(s string) (r int, rest string, err os.Error) {
- t := s[1:]
- if t == "" {
- return 0, "", &Error{ErrTrailingBackslash, ""}
- }
- c, t, err := nextRune(t)
- if err != nil {
- return 0, "", err
- }
-
-Switch:
- switch c {
- default:
- if c < utf8.RuneSelf && !isalnum(c) {
- // Escaped non-word characters are always themselves.
- // PCRE is not quite so rigorous: it accepts things like
- // \q, but we don't. We once rejected \_, but too many
- // programs and people insist on using it, so allow \_.
- return c, t, nil
- }
-
- // Octal escapes.
- case '1', '2', '3', '4', '5', '6', '7':
- // Single non-zero digit is a backreference; not supported
- if t == "" || t[0] < '0' || t[0] > '7' {
- break
- }
- fallthrough
- case '0':
- // Consume up to three octal digits; already have one.
- r = c - '0'
- for i := 1; i < 3; i++ {
- if t == "" || t[0] < '0' || t[0] > '7' {
- break
- }
- r = r*8 + int(t[0]) - '0'
- t = t[1:]
- }
- return r, t, nil
-
- // Hexadecimal escapes.
- case 'x':
- if t == "" {
- break
- }
- if c, t, err = nextRune(t); err != nil {
- return 0, "", err
- }
- if c == '{' {
- // Any number of digits in braces.
- // Perl accepts any text at all; it ignores all text
- // after the first non-hex digit. We require only hex digits,
- // and at least one.
- nhex := 0
- r = 0
- for {
- if t == "" {
- break Switch
- }
- if c, t, err = nextRune(t); err != nil {
- return 0, "", err
- }
- if c == '}' {
- break
- }
- v := unhex(c)
- if v < 0 {
- break Switch
- }
- r = r*16 + v
- if r > unicode.MaxRune {
- break Switch
- }
- nhex++
- }
- if nhex == 0 {
- break Switch
- }
- return r, t, nil
- }
-
- // Easy case: two hex digits.
- x := unhex(c)
- if c, t, err = nextRune(t); err != nil {
- return 0, "", err
- }
- y := unhex(c)
- if x < 0 || y < 0 {
- break
- }
- return x*16 + y, t, nil
-
- // C escapes. There is no case 'b', to avoid misparsing
- // the Perl word-boundary \b as the C backspace \b
- // when in POSIX mode. In Perl, /\b/ means word-boundary
- // but /[\b]/ means backspace. We don't support that.
- // If you want a backspace, embed a literal backspace
- // character or use \x08.
- case 'a':
- return '\a', t, err
- case 'f':
- return '\f', t, err
- case 'n':
- return '\n', t, err
- case 'r':
- return '\r', t, err
- case 't':
- return '\t', t, err
- case 'v':
- return '\v', t, err
- }
- return 0, "", &Error{ErrInvalidEscape, s[:len(s)-len(t)]}
-}
-
-// parseClassChar parses a character class character at the beginning of s
-// and returns it.
-func (p *parser) parseClassChar(s, wholeClass string) (r int, rest string, err os.Error) {
- if s == "" {
- return 0, "", &Error{Code: ErrMissingBracket, Expr: wholeClass}
- }
-
- // Allow regular escape sequences even though
- // many need not be escaped in this context.
- if s[0] == '\\' {
- return p.parseEscape(s)
- }
-
- return nextRune(s)
-}
-
-type charGroup struct {
- sign int
- class []int
-}
-
-// parsePerlClassEscape parses a leading Perl character class escape like \d
-// from the beginning of s. If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parsePerlClassEscape(s string, r []int) (out []int, rest string) {
- if p.flags&PerlX == 0 || len(s) < 2 || s[0] != '\\' {
- return
- }
- g := perlGroup[s[0:2]]
- if g.sign == 0 {
- return
- }
- return p.appendGroup(r, g), s[2:]
-}
-
-// parseNamedClass parses a leading POSIX named character class like [:alnum:]
-// from the beginning of s. If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parseNamedClass(s string, r []int) (out []int, rest string, err os.Error) {
- if len(s) < 2 || s[0] != '[' || s[1] != ':' {
- return
- }
-
- i := strings.Index(s[2:], ":]")
- if i < 0 {
- return
- }
- i += 2
- name, s := s[0:i+2], s[i+2:]
- g := posixGroup[name]
- if g.sign == 0 {
- return nil, "", &Error{ErrInvalidCharRange, name}
- }
- return p.appendGroup(r, g), s, nil
-}
-
-func (p *parser) appendGroup(r []int, g charGroup) []int {
- if p.flags&FoldCase == 0 {
- if g.sign < 0 {
- r = appendNegatedClass(r, g.class)
- } else {
- r = appendClass(r, g.class)
- }
- } else {
- tmp := p.tmpClass[:0]
- tmp = appendFoldedClass(tmp, g.class)
- p.tmpClass = tmp
- tmp = cleanClass(&p.tmpClass)
- if g.sign < 0 {
- r = appendNegatedClass(r, tmp)
- } else {
- r = appendClass(r, tmp)
- }
- }
- return r
-}
-
-// unicodeTable returns the unicode.RangeTable identified by name
-// and the table of additional fold-equivalent code points.
-func unicodeTable(name string) (*unicode.RangeTable, *unicode.RangeTable) {
- if t := unicode.Categories[name]; t != nil {
- return t, unicode.FoldCategory[name]
- }
- if t := unicode.Scripts[name]; t != nil {
- return t, unicode.FoldScript[name]
- }
- return nil, nil
-}
-
-// parseUnicodeClass parses a leading Unicode character class like \p{Han}
-// from the beginning of s. If one is present, it appends the characters to r
-// and returns the new slice r and the remainder of the string.
-func (p *parser) parseUnicodeClass(s string, r []int) (out []int, rest string, err os.Error) {
- if p.flags&UnicodeGroups == 0 || len(s) < 2 || s[0] != '\\' || s[1] != 'p' && s[1] != 'P' {
- return
- }
-
- // Committed to parse or return error.
- sign := +1
- if s[1] == 'P' {
- sign = -1
- }
- t := s[2:]
- c, t, err := nextRune(t)
- if err != nil {
- return
- }
- var seq, name string
- if c != '{' {
- // Single-letter name.
- seq = s[:len(s)-len(t)]
- name = seq[2:]
- } else {
- // Name is in braces.
- end := strings.IndexRune(s, '}')
- if end < 0 {
- if err = checkUTF8(s); err != nil {
- return
- }
- return nil, "", &Error{ErrInvalidCharRange, s}
- }
- seq, t = s[:end+1], s[end+1:]
- name = s[3:end]
- if err = checkUTF8(name); err != nil {
- return
- }
- }
-
- // Group can have leading negation too. \p{^Han} == \P{Han}, \P{^Han} == \p{Han}.
- if name != "" && name[0] == '^' {
- sign = -sign
- name = name[1:]
- }
-
- tab, fold := unicodeTable(name)
- if tab == nil {
- return nil, "", &Error{ErrInvalidCharRange, seq}
- }
-
- if p.flags&FoldCase == 0 || fold == nil {
- if sign > 0 {
- r = appendTable(r, tab)
- } else {
- r = appendNegatedTable(r, tab)
- }
- } else {
- // Merge and clean tab and fold in a temporary buffer.
- // This is necessary for the negative case and just tidy
- // for the positive case.
- tmp := p.tmpClass[:0]
- tmp = appendTable(tmp, tab)
- tmp = appendTable(tmp, fold)
- p.tmpClass = tmp
- tmp = cleanClass(&p.tmpClass)
- if sign > 0 {
- r = appendClass(r, tmp)
- } else {
- r = appendNegatedClass(r, tmp)
- }
- }
- return r, t, nil
-}
-
-// parseClass parses a character class at the beginning of s
-// and pushes it onto the parse stack.
-func (p *parser) parseClass(s string) (rest string, err os.Error) {
- t := s[1:] // chop [
- re := p.newRegexp(OpCharClass)
- re.Flags = p.flags
- re.Rune = re.Rune0[:0]
-
- sign := +1
- if t != "" && t[0] == '^' {
- sign = -1
- t = t[1:]
-
- // If character class does not match \n, add it here,
- // so that negation later will do the right thing.
- if p.flags&ClassNL == 0 {
- re.Rune = append(re.Rune, '\n', '\n')
- }
- }
-
- class := re.Rune
- first := true // ] and - are okay as first char in class
- for t == "" || t[0] != ']' || first {
- // POSIX: - is only okay unescaped as first or last in class.
- // Perl: - is okay anywhere.
- if t != "" && t[0] == '-' && p.flags&PerlX == 0 && !first && (len(t) == 1 || t[1] != ']') {
- _, size := utf8.DecodeRuneInString(t[1:])
- return "", &Error{Code: ErrInvalidCharRange, Expr: t[:1+size]}
- }
- first = false
-
- // Look for POSIX [:alnum:] etc.
- if len(t) > 2 && t[0] == '[' && t[1] == ':' {
- nclass, nt, err := p.parseNamedClass(t, class)
- if err != nil {
- return "", err
- }
- if nclass != nil {
- class, t = nclass, nt
- continue
- }
- }
-
- // Look for Unicode character group like \p{Han}.
- nclass, nt, err := p.parseUnicodeClass(t, class)
- if err != nil {
- return "", err
- }
- if nclass != nil {
- class, t = nclass, nt
- continue
- }
-
- // Look for Perl character class symbols (extension).
- if nclass, nt := p.parsePerlClassEscape(t, class); nclass != nil {
- class, t = nclass, nt
- continue
- }
-
- // Single character or simple range.
- rng := t
- var lo, hi int
- if lo, t, err = p.parseClassChar(t, s); err != nil {
- return "", err
- }
- hi = lo
- // [a-] means (a|-) so check for final ].
- if len(t) >= 2 && t[0] == '-' && t[1] != ']' {
- t = t[1:]
- if hi, t, err = p.parseClassChar(t, s); err != nil {
- return "", err
- }
- if hi < lo {
- rng = rng[:len(rng)-len(t)]
- return "", &Error{Code: ErrInvalidCharRange, Expr: rng}
- }
- }
- if p.flags&FoldCase == 0 {
- class = appendRange(class, lo, hi)
- } else {
- class = appendFoldedRange(class, lo, hi)
- }
- }
- t = t[1:] // chop ]
-
- // Use &re.Rune instead of &class to avoid allocation.
- re.Rune = class
- class = cleanClass(&re.Rune)
- if sign < 0 {
- class = negateClass(class)
- }
- re.Rune = class
- p.push(re)
- return t, nil
-}
-
-// cleanClass sorts the ranges (pairs of elements of r),
-// merges them, and eliminates duplicates.
-func cleanClass(rp *[]int) []int {
-
- // Sort by lo increasing, hi decreasing to break ties.
- sort.Sort(ranges{rp})
-
- r := *rp
- if len(r) < 2 {
- return r
- }
-
- // Merge abutting, overlapping.
- w := 2 // write index
- for i := 2; i < len(r); i += 2 {
- lo, hi := r[i], r[i+1]
- if lo <= r[w-1]+1 {
- // merge with previous range
- if hi > r[w-1] {
- r[w-1] = hi
- }
- continue
- }
- // new disjoint range
- r[w] = lo
- r[w+1] = hi
- w += 2
- }
-
- return r[:w]
-}
-
-// appendRange returns the result of appending the range lo-hi to the class r.
-func appendRange(r []int, lo, hi int) []int {
- // Expand last range or next to last range if it overlaps or abuts.
- // Checking two ranges helps when appending case-folded
- // alphabets, so that one range can be expanding A-Z and the
- // other expanding a-z.
- n := len(r)
- for i := 2; i <= 4; i += 2 { // twice, using i=2, i=4
- if n >= i {
- rlo, rhi := r[n-i], r[n-i+1]
- if lo <= rhi+1 && rlo <= hi+1 {
- if lo < rlo {
- r[n-i] = lo
- }
- if hi > rhi {
- r[n-i+1] = hi
- }
- return r
- }
- }
- }
-
- return append(r, lo, hi)
-}
-
-const (
- // minimum and maximum runes involved in folding.
- // checked during test.
- minFold = 0x0041
- maxFold = 0x1044f
-)
-
-// appendFoldedRange returns the result of appending the range lo-hi
-// and its case folding-equivalent runes to the class r.
-func appendFoldedRange(r []int, lo, hi int) []int {
- // Optimizations.
- if lo <= minFold && hi >= maxFold {
- // Range is full: folding can't add more.
- return appendRange(r, lo, hi)
- }
- if hi < minFold || lo > maxFold {
- // Range is outside folding possibilities.
- return appendRange(r, lo, hi)
- }
- if lo < minFold {
- // [lo, minFold-1] needs no folding.
- r = appendRange(r, lo, minFold-1)
- lo = minFold
- }
- if hi > maxFold {
- // [maxFold+1, hi] needs no folding.
- r = appendRange(r, maxFold+1, hi)
- hi = maxFold
- }
-
- // Brute force. Depend on appendRange to coalesce ranges on the fly.
- for c := lo; c <= hi; c++ {
- r = appendRange(r, c, c)
- f := unicode.SimpleFold(c)
- for f != c {
- r = appendRange(r, f, f)
- f = unicode.SimpleFold(f)
- }
- }
- return r
-}
-
-// appendClass returns the result of appending the class x to the class r.
-// It assume x is clean.
-func appendClass(r []int, x []int) []int {
- for i := 0; i < len(x); i += 2 {
- r = appendRange(r, x[i], x[i+1])
- }
- return r
-}
-
-// appendFolded returns the result of appending the case folding of the class x to the class r.
-func appendFoldedClass(r []int, x []int) []int {
- for i := 0; i < len(x); i += 2 {
- r = appendFoldedRange(r, x[i], x[i+1])
- }
- return r
-}
-
-// appendNegatedClass returns the result of appending the negation of the class x to the class r.
-// It assumes x is clean.
-func appendNegatedClass(r []int, x []int) []int {
- nextLo := 0
- for i := 0; i < len(x); i += 2 {
- lo, hi := x[i], x[i+1]
- if nextLo <= lo-1 {
- r = appendRange(r, nextLo, lo-1)
- }
- nextLo = hi + 1
- }
- if nextLo <= unicode.MaxRune {
- r = appendRange(r, nextLo, unicode.MaxRune)
- }
- return r
-}
-
-// appendTable returns the result of appending x to the class r.
-func appendTable(r []int, x *unicode.RangeTable) []int {
- for _, xr := range x.R16 {
- lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
- if stride == 1 {
- r = appendRange(r, lo, hi)
- continue
- }
- for c := lo; c <= hi; c += stride {
- r = appendRange(r, c, c)
- }
- }
- for _, xr := range x.R32 {
- lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
- if stride == 1 {
- r = appendRange(r, lo, hi)
- continue
- }
- for c := lo; c <= hi; c += stride {
- r = appendRange(r, c, c)
- }
- }
- return r
-}
-
-// appendNegatedTable returns the result of appending the negation of x to the class r.
-func appendNegatedTable(r []int, x *unicode.RangeTable) []int {
- nextLo := 0 // lo end of next class to add
- for _, xr := range x.R16 {
- lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
- if stride == 1 {
- if nextLo <= lo-1 {
- r = appendRange(r, nextLo, lo-1)
- }
- nextLo = hi + 1
- continue
- }
- for c := lo; c <= hi; c += stride {
- if nextLo <= c-1 {
- r = appendRange(r, nextLo, c-1)
- }
- nextLo = c + 1
- }
- }
- for _, xr := range x.R32 {
- lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
- if stride == 1 {
- if nextLo <= lo-1 {
- r = appendRange(r, nextLo, lo-1)
- }
- nextLo = hi + 1
- continue
- }
- for c := lo; c <= hi; c += stride {
- if nextLo <= c-1 {
- r = appendRange(r, nextLo, c-1)
- }
- nextLo = c + 1
- }
- }
- if nextLo <= unicode.MaxRune {
- r = appendRange(r, nextLo, unicode.MaxRune)
- }
- return r
-}
-
-// negateClass overwrites r and returns r's negation.
-// It assumes the class r is already clean.
-func negateClass(r []int) []int {
- nextLo := 0 // lo end of next class to add
- w := 0 // write index
- for i := 0; i < len(r); i += 2 {
- lo, hi := r[i], r[i+1]
- if nextLo <= lo-1 {
- r[w] = nextLo
- r[w+1] = lo - 1
- w += 2
- }
- nextLo = hi + 1
- }
- r = r[:w]
- if nextLo <= unicode.MaxRune {
- // It's possible for the negation to have one more
- // range - this one - than the original class, so use append.
- r = append(r, nextLo, unicode.MaxRune)
- }
- return r
-}
-
-// ranges implements sort.Interface on a []rune.
-// The choice of receiver type definition is strange
-// but avoids an allocation since we already have
-// a *[]int.
-type ranges struct {
- p *[]int
-}
-
-func (ra ranges) Less(i, j int) bool {
- p := *ra.p
- i *= 2
- j *= 2
- return p[i] < p[j] || p[i] == p[j] && p[i+1] > p[j+1]
-}
-
-func (ra ranges) Len() int {
- return len(*ra.p) / 2
-}
-
-func (ra ranges) Swap(i, j int) {
- p := *ra.p
- i *= 2
- j *= 2
- p[i], p[i+1], p[j], p[j+1] = p[j], p[j+1], p[i], p[i+1]
-}
-
-func checkUTF8(s string) os.Error {
- for s != "" {
- rune, size := utf8.DecodeRuneInString(s)
- if rune == utf8.RuneError && size == 1 {
- return &Error{Code: ErrInvalidUTF8, Expr: s}
- }
- s = s[size:]
- }
- return nil
-}
-
-func nextRune(s string) (c int, t string, err os.Error) {
- c, size := utf8.DecodeRuneInString(s)
- if c == utf8.RuneError && size == 1 {
- return 0, "", &Error{Code: ErrInvalidUTF8, Expr: s}
- }
- return c, s[size:], nil
-}
-
-func isalnum(c int) bool {
- return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
-}
-
-func unhex(c int) int {
- if '0' <= c && c <= '9' {
- return c - '0'
- }
- if 'a' <= c && c <= 'f' {
- return c - 'a' + 10
- }
- if 'A' <= c && c <= 'F' {
- return c - 'A' + 10
- }
- return -1
-}
diff --git a/libgo/go/exp/regexp/syntax/parse_test.go b/libgo/go/exp/regexp/syntax/parse_test.go
deleted file mode 100644
index 779b9afdeae..00000000000
--- a/libgo/go/exp/regexp/syntax/parse_test.go
+++ /dev/null
@@ -1,350 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syntax
-
-import (
- "bytes"
- "fmt"
- "testing"
- "unicode"
-)
-
-var parseTests = []struct {
- Regexp string
- Dump string
-}{
- // Base cases
- {`a`, `lit{a}`},
- {`a.`, `cat{lit{a}dot{}}`},
- {`a.b`, `cat{lit{a}dot{}lit{b}}`},
- {`ab`, `str{ab}`},
- {`a.b.c`, `cat{lit{a}dot{}lit{b}dot{}lit{c}}`},
- {`abc`, `str{abc}`},
- {`a|^`, `alt{lit{a}bol{}}`},
- {`a|b`, `cc{0x61-0x62}`},
- {`(a)`, `cap{lit{a}}`},
- {`(a)|b`, `alt{cap{lit{a}}lit{b}}`},
- {`a*`, `star{lit{a}}`},
- {`a+`, `plus{lit{a}}`},
- {`a?`, `que{lit{a}}`},
- {`a{2}`, `rep{2,2 lit{a}}`},
- {`a{2,3}`, `rep{2,3 lit{a}}`},
- {`a{2,}`, `rep{2,-1 lit{a}}`},
- {`a*?`, `nstar{lit{a}}`},
- {`a+?`, `nplus{lit{a}}`},
- {`a??`, `nque{lit{a}}`},
- {`a{2}?`, `nrep{2,2 lit{a}}`},
- {`a{2,3}?`, `nrep{2,3 lit{a}}`},
- {`a{2,}?`, `nrep{2,-1 lit{a}}`},
- {``, `emp{}`},
- {`|`, `emp{}`}, // alt{emp{}emp{}} but got factored
- {`|x|`, `alt{emp{}lit{x}emp{}}`},
- {`.`, `dot{}`},
- {`^`, `bol{}`},
- {`$`, `eol{}`},
- {`\|`, `lit{|}`},
- {`\(`, `lit{(}`},
- {`\)`, `lit{)}`},
- {`\*`, `lit{*}`},
- {`\+`, `lit{+}`},
- {`\?`, `lit{?}`},
- {`{`, `lit{{}`},
- {`}`, `lit{}}`},
- {`\.`, `lit{.}`},
- {`\^`, `lit{^}`},
- {`\$`, `lit{$}`},
- {`\\`, `lit{\}`},
- {`[ace]`, `cc{0x61 0x63 0x65}`},
- {`[abc]`, `cc{0x61-0x63}`},
- {`[a-z]`, `cc{0x61-0x7a}`},
- {`[a]`, `lit{a}`},
- {`\-`, `lit{-}`},
- {`-`, `lit{-}`},
- {`\_`, `lit{_}`},
- {`abc`, `str{abc}`},
- {`abc|def`, `alt{str{abc}str{def}}`},
- {`abc|def|ghi`, `alt{str{abc}str{def}str{ghi}}`},
-
- // Posix and Perl extensions
- {`[[:lower:]]`, `cc{0x61-0x7a}`},
- {`[a-z]`, `cc{0x61-0x7a}`},
- {`[^[:lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
- {`[[:^lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
- {`(?i)[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
- {`(?i)[a-z]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
- {`(?i)[^[:lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
- {`(?i)[[:^lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
- {`\d`, `cc{0x30-0x39}`},
- {`\D`, `cc{0x0-0x2f 0x3a-0x10ffff}`},
- {`\s`, `cc{0x9-0xa 0xc-0xd 0x20}`},
- {`\S`, `cc{0x0-0x8 0xb 0xe-0x1f 0x21-0x10ffff}`},
- {`\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a}`},
- {`\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x10ffff}`},
- {`(?i)\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a 0x17f 0x212a}`},
- {`(?i)\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
- {`[^\\]`, `cc{0x0-0x5b 0x5d-0x10ffff}`},
- // { `\C`, `byte{}` }, // probably never
-
- // Unicode, negatives, and a double negative.
- {`\p{Braille}`, `cc{0x2800-0x28ff}`},
- {`\P{Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
- {`\p{^Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
- {`\P{^Braille}`, `cc{0x2800-0x28ff}`},
- {`\pZ`, `cc{0x20 0xa0 0x1680 0x180e 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
- {`[\p{Braille}]`, `cc{0x2800-0x28ff}`},
- {`[\P{Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
- {`[\p{^Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
- {`[\P{^Braille}]`, `cc{0x2800-0x28ff}`},
- {`[\pZ]`, `cc{0x20 0xa0 0x1680 0x180e 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
- {`\p{Lu}`, mkCharClass(unicode.IsUpper)},
- {`[\p{Lu}]`, mkCharClass(unicode.IsUpper)},
- {`(?i)[\p{Lu}]`, mkCharClass(isUpperFold)},
-
- // Hex, octal.
- {`[\012-\234]\141`, `cat{cc{0xa-0x9c}lit{a}}`},
- {`[\x{41}-\x7a]\x61`, `cat{cc{0x41-0x7a}lit{a}}`},
-
- // More interesting regular expressions.
- {`a{,2}`, `str{a{,2}}`},
- {`\.\^\$\\`, `str{.^$\}`},
- {`[a-zABC]`, `cc{0x41-0x43 0x61-0x7a}`},
- {`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
- {`[α-ε☺]`, `cc{0x3b1-0x3b5 0x263a}`}, // utf-8
- {`a*{`, `cat{star{lit{a}}lit{{}}`},
-
- // Test precedences
- {`(?:ab)*`, `star{str{ab}}`},
- {`(ab)*`, `star{cap{str{ab}}}`},
- {`ab|cd`, `alt{str{ab}str{cd}}`},
- {`a(b|c)d`, `cat{lit{a}cap{cc{0x62-0x63}}lit{d}}`},
-
- // Test flattening.
- {`(?:a)`, `lit{a}`},
- {`(?:ab)(?:cd)`, `str{abcd}`},
- {`(?:a+b+)(?:c+d+)`, `cat{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
- {`(?:a+|b+)|(?:c+|d+)`, `alt{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
- {`(?:a|b)|(?:c|d)`, `cc{0x61-0x64}`},
- {`a|.`, `dot{}`},
- {`.|a`, `dot{}`},
- {`(?:[abc]|A|Z|hello|world)`, `alt{cc{0x41 0x5a 0x61-0x63}str{hello}str{world}}`},
- {`(?:[abc]|A|Z)`, `cc{0x41 0x5a 0x61-0x63}`},
-
- // Test Perl quoted literals
- {`\Q+|*?{[\E`, `str{+|*?{[}`},
- {`\Q+\E+`, `plus{lit{+}}`},
- {`\Q\\E`, `lit{\}`},
- {`\Q\\\E`, `str{\\}`},
-
- // Test Perl \A and \z
- {`(?m)^`, `bol{}`},
- {`(?m)$`, `eol{}`},
- {`(?-m)^`, `bot{}`},
- {`(?-m)$`, `eot{}`},
- {`(?m)\A`, `bot{}`},
- {`(?m)\z`, `eot{\z}`},
- {`(?-m)\A`, `bot{}`},
- {`(?-m)\z`, `eot{\z}`},
-
- // Test named captures
- {`(?P<name>a)`, `cap{name:lit{a}}`},
-
- // Case-folded literals
- {`[Aa]`, `litfold{A}`},
- {`[\x{100}\x{101}]`, `litfold{Ä€}`},
- {`[Δδ]`, `litfold{Δ}`},
-
- // Strings
- {`abcde`, `str{abcde}`},
- {`[Aa][Bb]cd`, `cat{strfold{AB}str{cd}}`},
-
- // Factoring.
- {`abc|abd|aef|bcx|bcy`, `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}cat{str{bc}cc{0x78-0x79}}}`},
- {`ax+y|ax+z|ay+w`, `cat{lit{a}alt{cat{plus{lit{x}}cc{0x79-0x7a}}cat{plus{lit{y}}lit{w}}}}`},
-}
-
-const testFlags = MatchNL | PerlX | UnicodeGroups
-
-// Test Parse -> Dump.
-func TestParseDump(t *testing.T) {
- for _, tt := range parseTests {
- re, err := Parse(tt.Regexp, testFlags)
- if err != nil {
- t.Errorf("Parse(%#q): %v", tt.Regexp, err)
- continue
- }
- d := dump(re)
- if d != tt.Dump {
- t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
- }
- }
-}
-
-// dump prints a string representation of the regexp showing
-// the structure explicitly.
-func dump(re *Regexp) string {
- var b bytes.Buffer
- dumpRegexp(&b, re)
- return b.String()
-}
-
-var opNames = []string{
- OpNoMatch: "no",
- OpEmptyMatch: "emp",
- OpLiteral: "lit",
- OpCharClass: "cc",
- OpAnyCharNotNL: "dnl",
- OpAnyChar: "dot",
- OpBeginLine: "bol",
- OpEndLine: "eol",
- OpBeginText: "bot",
- OpEndText: "eot",
- OpWordBoundary: "wb",
- OpNoWordBoundary: "nwb",
- OpCapture: "cap",
- OpStar: "star",
- OpPlus: "plus",
- OpQuest: "que",
- OpRepeat: "rep",
- OpConcat: "cat",
- OpAlternate: "alt",
-}
-
-// dumpRegexp writes an encoding of the syntax tree for the regexp re to b.
-// It is used during testing to distinguish between parses that might print
-// the same using re's String method.
-func dumpRegexp(b *bytes.Buffer, re *Regexp) {
- if int(re.Op) >= len(opNames) || opNames[re.Op] == "" {
- fmt.Fprintf(b, "op%d", re.Op)
- } else {
- switch re.Op {
- default:
- b.WriteString(opNames[re.Op])
- case OpStar, OpPlus, OpQuest, OpRepeat:
- if re.Flags&NonGreedy != 0 {
- b.WriteByte('n')
- }
- b.WriteString(opNames[re.Op])
- case OpLiteral:
- if len(re.Rune) > 1 {
- b.WriteString("str")
- } else {
- b.WriteString("lit")
- }
- if re.Flags&FoldCase != 0 {
- for _, r := range re.Rune {
- if unicode.SimpleFold(r) != r {
- b.WriteString("fold")
- break
- }
- }
- }
- }
- }
- b.WriteByte('{')
- switch re.Op {
- case OpEndText:
- if re.Flags&WasDollar == 0 {
- b.WriteString(`\z`)
- }
- case OpLiteral:
- for _, r := range re.Rune {
- b.WriteRune(r)
- }
- case OpConcat, OpAlternate:
- for _, sub := range re.Sub {
- dumpRegexp(b, sub)
- }
- case OpStar, OpPlus, OpQuest:
- dumpRegexp(b, re.Sub[0])
- case OpRepeat:
- fmt.Fprintf(b, "%d,%d ", re.Min, re.Max)
- dumpRegexp(b, re.Sub[0])
- case OpCapture:
- if re.Name != "" {
- b.WriteString(re.Name)
- b.WriteByte(':')
- }
- dumpRegexp(b, re.Sub[0])
- case OpCharClass:
- sep := ""
- for i := 0; i < len(re.Rune); i += 2 {
- b.WriteString(sep)
- sep = " "
- lo, hi := re.Rune[i], re.Rune[i+1]
- if lo == hi {
- fmt.Fprintf(b, "%#x", lo)
- } else {
- fmt.Fprintf(b, "%#x-%#x", lo, hi)
- }
- }
- }
- b.WriteByte('}')
-}
-
-func mkCharClass(f func(int) bool) string {
- re := &Regexp{Op: OpCharClass}
- lo := -1
- for i := 0; i <= unicode.MaxRune; i++ {
- if f(i) {
- if lo < 0 {
- lo = i
- }
- } else {
- if lo >= 0 {
- re.Rune = append(re.Rune, lo, i-1)
- lo = -1
- }
- }
- }
- if lo >= 0 {
- re.Rune = append(re.Rune, lo, unicode.MaxRune)
- }
- return dump(re)
-}
-
-func isUpperFold(rune int) bool {
- if unicode.IsUpper(rune) {
- return true
- }
- c := unicode.SimpleFold(rune)
- for c != rune {
- if unicode.IsUpper(c) {
- return true
- }
- c = unicode.SimpleFold(c)
- }
- return false
-}
-
-func TestFoldConstants(t *testing.T) {
- last := -1
- for i := 0; i <= unicode.MaxRune; i++ {
- if unicode.SimpleFold(i) == i {
- continue
- }
- if last == -1 && minFold != i {
- t.Errorf("minFold=%#U should be %#U", minFold, i)
- }
- last = i
- }
- if maxFold != last {
- t.Errorf("maxFold=%#U should be %#U", maxFold, last)
- }
-}
-
-func TestAppendRangeCollapse(t *testing.T) {
- // AppendRange should collapse each of the new ranges
- // into the earlier ones (it looks back two ranges), so that
- // the slice never grows very large.
- // Note that we are not calling cleanClass.
- var r []int
- for i := 'A'; i <= 'Z'; i++ {
- r = appendRange(r, i, i)
- r = appendRange(r, i+'a'-'A', i+'a'-'A')
- }
- if string(r) != "AZaz" {
- t.Errorf("appendRange interlaced A-Z a-z = %s, want AZaz", string(r))
- }
-}
diff --git a/libgo/go/exp/regexp/syntax/prog.go b/libgo/go/exp/regexp/syntax/prog.go
deleted file mode 100644
index bf85b720d02..00000000000
--- a/libgo/go/exp/regexp/syntax/prog.go
+++ /dev/null
@@ -1,237 +0,0 @@
-package syntax
-
-import (
- "bytes"
- "strconv"
-)
-
-// Compiled program.
-// May not belong in this package, but convenient for now.
-
-// A Prog is a compiled regular expression program.
-type Prog struct {
- Inst []Inst
- Start int // index of start instruction
- NumCap int // number of InstCapture insts in re
-}
-
-// An InstOp is an instruction opcode.
-type InstOp uint8
-
-const (
- InstAlt InstOp = iota
- InstAltMatch
- InstCapture
- InstEmptyWidth
- InstMatch
- InstFail
- InstNop
- InstRune
-)
-
-// An EmptyOp specifies a kind or mixture of zero-width assertions.
-type EmptyOp uint8
-
-const (
- EmptyBeginLine EmptyOp = 1 << iota
- EmptyEndLine
- EmptyBeginText
- EmptyEndText
- EmptyWordBoundary
- EmptyNoWordBoundary
-)
-
-// An Inst is a single instruction in a regular expression program.
-type Inst struct {
- Op InstOp
- Out uint32 // all but InstMatch, InstFail
- Arg uint32 // InstAlt, InstAltMatch, InstCapture, InstEmptyWidth
- Rune []int
-}
-
-func (p *Prog) String() string {
- var b bytes.Buffer
- dumpProg(&b, p)
- return b.String()
-}
-
-// skipNop follows any no-op or capturing instructions
-// and returns the resulting pc.
-func (p *Prog) skipNop(pc uint32) *Inst {
- i := &p.Inst[pc]
- for i.Op == InstNop || i.Op == InstCapture {
- pc = i.Out
- i = &p.Inst[pc]
- }
- return i
-}
-
-// Prefix returns a literal string that all matches for the
-// regexp must start with. Complete is true if the prefix
-// is the entire match.
-func (p *Prog) Prefix() (prefix string, complete bool) {
- i := p.skipNop(uint32(p.Start))
-
- // Avoid allocation of buffer if prefix is empty.
- if i.Op != InstRune || len(i.Rune) != 1 {
- return "", i.Op == InstMatch
- }
-
- // Have prefix; gather characters.
- var buf bytes.Buffer
- for i.Op == InstRune && len(i.Rune) == 1 {
- buf.WriteRune(i.Rune[0])
- i = p.skipNop(i.Out)
- }
- return buf.String(), i.Op == InstMatch
-}
-
-// StartCond returns the leading empty-width conditions that must
-// be true in any match. It returns ^EmptyOp(0) if no matches are possible.
-func (p *Prog) StartCond() EmptyOp {
- var flag EmptyOp
- pc := uint32(p.Start)
- i := &p.Inst[pc]
-Loop:
- for {
- switch i.Op {
- case InstEmptyWidth:
- flag |= EmptyOp(i.Arg)
- case InstFail:
- return ^EmptyOp(0)
- case InstCapture, InstNop:
- // skip
- default:
- break Loop
- }
- pc = i.Out
- i = &p.Inst[pc]
- }
- return flag
-}
-
-// MatchRune returns true if the instruction matches (and consumes) r.
-// It should only be called when i.Op == InstRune.
-func (i *Inst) MatchRune(r int) bool {
- rune := i.Rune
-
- // Special case: single-rune slice is from literal string, not char class.
- // TODO: Case folding.
- if len(rune) == 1 {
- return r == rune[0]
- }
-
- // Peek at the first few pairs.
- // Should handle ASCII well.
- for j := 0; j < len(rune) && j <= 8; j += 2 {
- if r < rune[j] {
- return false
- }
- if r <= rune[j+1] {
- return true
- }
- }
-
- // Otherwise binary search.
- lo := 0
- hi := len(rune) / 2
- for lo < hi {
- m := lo + (hi-lo)/2
- if c := rune[2*m]; c <= r {
- if r <= rune[2*m+1] {
- return true
- }
- lo = m + 1
- } else {
- hi = m
- }
- }
- return false
-}
-
-// As per re2's Prog::IsWordChar. Determines whether rune is an ASCII word char.
-// Since we act on runes, it would be easy to support Unicode here.
-func wordRune(rune int) bool {
- return rune == '_' ||
- ('A' <= rune && rune <= 'Z') ||
- ('a' <= rune && rune <= 'z') ||
- ('0' <= rune && rune <= '9')
-}
-
-// MatchEmptyWidth returns true if the instruction matches
-// an empty string between the runes before and after.
-// It should only be called when i.Op == InstEmptyWidth.
-func (i *Inst) MatchEmptyWidth(before int, after int) bool {
- switch EmptyOp(i.Arg) {
- case EmptyBeginLine:
- return before == '\n' || before == -1
- case EmptyEndLine:
- return after == '\n' || after == -1
- case EmptyBeginText:
- return before == -1
- case EmptyEndText:
- return after == -1
- case EmptyWordBoundary:
- return wordRune(before) != wordRune(after)
- case EmptyNoWordBoundary:
- return wordRune(before) == wordRune(after)
- }
- panic("unknown empty width arg")
-}
-
-func (i *Inst) String() string {
- var b bytes.Buffer
- dumpInst(&b, i)
- return b.String()
-}
-
-func bw(b *bytes.Buffer, args ...string) {
- for _, s := range args {
- b.WriteString(s)
- }
-}
-
-func dumpProg(b *bytes.Buffer, p *Prog) {
- for j := range p.Inst {
- i := &p.Inst[j]
- pc := strconv.Itoa(j)
- if len(pc) < 3 {
- b.WriteString(" "[len(pc):])
- }
- if j == p.Start {
- pc += "*"
- }
- bw(b, pc, "\t")
- dumpInst(b, i)
- bw(b, "\n")
- }
-}
-
-func u32(i uint32) string {
- return strconv.Uitoa64(uint64(i))
-}
-
-func dumpInst(b *bytes.Buffer, i *Inst) {
- switch i.Op {
- case InstAlt:
- bw(b, "alt -> ", u32(i.Out), ", ", u32(i.Arg))
- case InstAltMatch:
- bw(b, "altmatch -> ", u32(i.Out), ", ", u32(i.Arg))
- case InstCapture:
- bw(b, "cap ", u32(i.Arg), " -> ", u32(i.Out))
- case InstEmptyWidth:
- bw(b, "empty ", u32(i.Arg), " -> ", u32(i.Out))
- case InstMatch:
- bw(b, "match")
- case InstFail:
- bw(b, "fail")
- case InstNop:
- bw(b, "nop -> ", u32(i.Out))
- case InstRune:
- if i.Rune == nil {
- // shouldn't happen
- bw(b, "rune <nil>")
- }
- bw(b, "rune ", strconv.QuoteToASCII(string(i.Rune)), " -> ", u32(i.Out))
- }
-}
diff --git a/libgo/go/exp/regexp/syntax/prog_test.go b/libgo/go/exp/regexp/syntax/prog_test.go
deleted file mode 100644
index 7be4281c27f..00000000000
--- a/libgo/go/exp/regexp/syntax/prog_test.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package syntax
-
-import (
- "testing"
-)
-
-var compileTests = []struct {
- Regexp string
- Prog string
-}{
- {"a", ` 0 fail
- 1* rune "a" -> 2
- 2 match
-`},
- {"[A-M][n-z]", ` 0 fail
- 1* rune "AM" -> 2
- 2 rune "nz" -> 3
- 3 match
-`},
- {"", ` 0 fail
- 1* nop -> 2
- 2 match
-`},
- {"a?", ` 0 fail
- 1 rune "a" -> 3
- 2* alt -> 1, 3
- 3 match
-`},
- {"a??", ` 0 fail
- 1 rune "a" -> 3
- 2* alt -> 3, 1
- 3 match
-`},
- {"a+", ` 0 fail
- 1* rune "a" -> 2
- 2 alt -> 1, 3
- 3 match
-`},
- {"a+?", ` 0 fail
- 1* rune "a" -> 2
- 2 alt -> 3, 1
- 3 match
-`},
- {"a*", ` 0 fail
- 1 rune "a" -> 2
- 2* alt -> 1, 3
- 3 match
-`},
- {"a*?", ` 0 fail
- 1 rune "a" -> 2
- 2* alt -> 3, 1
- 3 match
-`},
- {"a+b+", ` 0 fail
- 1* rune "a" -> 2
- 2 alt -> 1, 3
- 3 rune "b" -> 4
- 4 alt -> 3, 5
- 5 match
-`},
- {"(a+)(b+)", ` 0 fail
- 1* cap 2 -> 2
- 2 rune "a" -> 3
- 3 alt -> 2, 4
- 4 cap 3 -> 5
- 5 cap 4 -> 6
- 6 rune "b" -> 7
- 7 alt -> 6, 8
- 8 cap 5 -> 9
- 9 match
-`},
- {"a+|b+", ` 0 fail
- 1 rune "a" -> 2
- 2 alt -> 1, 6
- 3 rune "b" -> 4
- 4 alt -> 3, 6
- 5* alt -> 1, 3
- 6 match
-`},
-}
-
-func TestCompile(t *testing.T) {
- for _, tt := range compileTests {
- re, _ := Parse(tt.Regexp, Perl)
- p, _ := Compile(re)
- s := p.String()
- if s != tt.Prog {
- t.Errorf("compiled %#q:\n--- have\n%s---\n--- want\n%s---", tt.Regexp, s, tt.Prog)
- }
- }
-}
diff --git a/libgo/go/exp/regexp/syntax/regexp.go b/libgo/go/exp/regexp/syntax/regexp.go
deleted file mode 100644
index 00a4addefc4..00000000000
--- a/libgo/go/exp/regexp/syntax/regexp.go
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package syntax parses regular expressions into syntax trees.
-// WORK IN PROGRESS.
-package syntax
-
-// Note to implementers:
-// In this package, re is always a *Regexp and r is always a rune.
-
-import (
- "bytes"
- "strconv"
- "strings"
- "unicode"
-)
-
-// A Regexp is a node in a regular expression syntax tree.
-type Regexp struct {
- Op Op // operator
- Flags Flags
- Sub []*Regexp // subexpressions, if any
- Sub0 [1]*Regexp // storage for short Sub
- Rune []int // matched runes, for OpLiteral, OpCharClass
- Rune0 [2]int // storage for short Rune
- Min, Max int // min, max for OpRepeat
- Cap int // capturing index, for OpCapture
- Name string // capturing name, for OpCapture
-}
-
-// An Op is a single regular expression operator.
-type Op uint8
-
-// Operators are listed in precedence order, tightest binding to weakest.
-// Character class operators are listed simplest to most complex
-// (OpLiteral, OpCharClass, OpAnyCharNotNL, OpAnyChar).
-
-const (
- OpNoMatch Op = 1 + iota // matches no strings
- OpEmptyMatch // matches empty string
- OpLiteral // matches Runes sequence
- OpCharClass // matches Runes interpreted as range pair list
- OpAnyCharNotNL // matches any character
- OpAnyChar // matches any character
- OpBeginLine // matches empty string at beginning of line
- OpEndLine // matches empty string at end of line
- OpBeginText // matches empty string at beginning of text
- OpEndText // matches empty string at end of text
- OpWordBoundary // matches word boundary `\b`
- OpNoWordBoundary // matches word non-boundary `\B`
- OpCapture // capturing subexpression with index Cap, optional name Name
- OpStar // matches Sub[0] zero or more times
- OpPlus // matches Sub[0] one or more times
- OpQuest // matches Sub[0] zero or one times
- OpRepeat // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit)
- OpConcat // matches concatenation of Subs
- OpAlternate // matches alternation of Subs
-)
-
-const opPseudo Op = 128 // where pseudo-ops start
-
-// Equal returns true if x and y have identical structure.
-func (x *Regexp) Equal(y *Regexp) bool {
- if x == nil || y == nil {
- return x == y
- }
- if x.Op != y.Op {
- return false
- }
- switch x.Op {
- case OpEndText:
- // The parse flags remember whether this is \z or \Z.
- if x.Flags&WasDollar != y.Flags&WasDollar {
- return false
- }
-
- case OpLiteral, OpCharClass:
- if len(x.Rune) != len(y.Rune) {
- return false
- }
- for i, r := range x.Rune {
- if r != y.Rune[i] {
- return false
- }
- }
-
- case OpAlternate, OpConcat:
- if len(x.Sub) != len(y.Sub) {
- return false
- }
- for i, sub := range x.Sub {
- if !sub.Equal(y.Sub[i]) {
- return false
- }
- }
-
- case OpStar, OpPlus, OpQuest:
- if x.Flags&NonGreedy != y.Flags&NonGreedy || !x.Sub[0].Equal(y.Sub[0]) {
- return false
- }
-
- case OpRepeat:
- if x.Flags&NonGreedy != y.Flags&NonGreedy || x.Min != y.Min || x.Max != y.Max || !x.Sub[0].Equal(y.Sub[0]) {
- return false
- }
-
- case OpCapture:
- if x.Cap != y.Cap || x.Name != y.Name || !x.Sub[0].Equal(y.Sub[0]) {
- return false
- }
- }
- return true
-}
-
-// writeRegexp writes the Perl syntax for the regular expression re to b.
-func writeRegexp(b *bytes.Buffer, re *Regexp) {
- switch re.Op {
- default:
- b.WriteString("<invalid op" + strconv.Itoa(int(re.Op)) + ">")
- case OpNoMatch:
- b.WriteString(`[^\x00-\x{10FFFF}]`)
- case OpEmptyMatch:
- b.WriteString(`(?:)`)
- case OpLiteral:
- if re.Flags&FoldCase != 0 {
- b.WriteString(`(?i:`)
- }
- for _, r := range re.Rune {
- escape(b, r, false)
- }
- if re.Flags&FoldCase != 0 {
- b.WriteString(`)`)
- }
- case OpCharClass:
- if len(re.Rune)%2 != 0 {
- b.WriteString(`[invalid char class]`)
- break
- }
- b.WriteRune('[')
- if len(re.Rune) == 0 {
- b.WriteString(`^\x00-\x{10FFFF}`)
- } else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune {
- // Contains 0 and MaxRune. Probably a negated class.
- // Print the gaps.
- b.WriteRune('^')
- for i := 1; i < len(re.Rune)-1; i += 2 {
- lo, hi := re.Rune[i]+1, re.Rune[i+1]-1
- escape(b, lo, lo == '-')
- if lo != hi {
- b.WriteRune('-')
- escape(b, hi, hi == '-')
- }
- }
- } else {
- for i := 0; i < len(re.Rune); i += 2 {
- lo, hi := re.Rune[i], re.Rune[i+1]
- escape(b, lo, lo == '-')
- if lo != hi {
- b.WriteRune('-')
- escape(b, hi, hi == '-')
- }
- }
- }
- b.WriteRune(']')
- case OpAnyCharNotNL:
- b.WriteString(`[^\n]`)
- case OpAnyChar:
- b.WriteRune('.')
- case OpBeginLine:
- b.WriteRune('^')
- case OpEndLine:
- b.WriteRune('$')
- case OpBeginText:
- b.WriteString(`\A`)
- case OpEndText:
- b.WriteString(`\z`)
- case OpWordBoundary:
- b.WriteString(`\b`)
- case OpNoWordBoundary:
- b.WriteString(`\B`)
- case OpCapture:
- if re.Name != "" {
- b.WriteString(`(?P<`)
- b.WriteString(re.Name)
- b.WriteRune('>')
- } else {
- b.WriteRune('(')
- }
- if re.Sub[0].Op != OpEmptyMatch {
- writeRegexp(b, re.Sub[0])
- }
- b.WriteRune(')')
- case OpStar, OpPlus, OpQuest, OpRepeat:
- if sub := re.Sub[0]; sub.Op > OpCapture {
- b.WriteString(`(?:`)
- writeRegexp(b, sub)
- b.WriteString(`)`)
- } else {
- writeRegexp(b, sub)
- }
- switch re.Op {
- case OpStar:
- b.WriteRune('*')
- case OpPlus:
- b.WriteRune('+')
- case OpQuest:
- b.WriteRune('?')
- case OpRepeat:
- b.WriteRune('{')
- b.WriteString(strconv.Itoa(re.Min))
- if re.Max != re.Min {
- b.WriteRune(',')
- if re.Max >= 0 {
- b.WriteString(strconv.Itoa(re.Max))
- }
- }
- b.WriteRune('}')
- }
- case OpConcat:
- for _, sub := range re.Sub {
- if sub.Op == OpAlternate {
- b.WriteString(`(?:`)
- writeRegexp(b, sub)
- b.WriteString(`)`)
- } else {
- writeRegexp(b, sub)
- }
- }
- case OpAlternate:
- for i, sub := range re.Sub {
- if i > 0 {
- b.WriteRune('|')
- }
- writeRegexp(b, sub)
- }
- }
-}
-
-func (re *Regexp) String() string {
- var b bytes.Buffer
- writeRegexp(&b, re)
- return b.String()
-}
-
-const meta = `\.+*?()|[]{}^$`
-
-func escape(b *bytes.Buffer, r int, force bool) {
- if unicode.IsPrint(r) {
- if strings.IndexRune(meta, r) >= 0 || force {
- b.WriteRune('\\')
- }
- b.WriteRune(r)
- return
- }
-
- switch r {
- case '\a':
- b.WriteString(`\a`)
- case '\f':
- b.WriteString(`\f`)
- case '\n':
- b.WriteString(`\n`)
- case '\r':
- b.WriteString(`\r`)
- case '\t':
- b.WriteString(`\t`)
- case '\v':
- b.WriteString(`\v`)
- default:
- if r < 0x100 {
- b.WriteString(`\x`)
- s := strconv.Itob(r, 16)
- if len(s) == 1 {
- b.WriteRune('0')
- }
- b.WriteString(s)
- break
- }
- b.WriteString(`\x{`)
- b.WriteString(strconv.Itob(r, 16))
- b.WriteString(`}`)
- }
-}
diff --git a/libgo/go/exp/regexp/syntax/simplify_test.go b/libgo/go/exp/regexp/syntax/simplify_test.go
deleted file mode 100644
index c8cec21831a..00000000000
--- a/libgo/go/exp/regexp/syntax/simplify_test.go
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syntax
-
-import "testing"
-
-var simplifyTests = []struct {
- Regexp string
- Simple string
-}{
- // Already-simple constructs
- {`a`, `a`},
- {`ab`, `ab`},
- {`a|b`, `[a-b]`},
- {`ab|cd`, `ab|cd`},
- {`(ab)*`, `(ab)*`},
- {`(ab)+`, `(ab)+`},
- {`(ab)?`, `(ab)?`},
- {`.`, `.`},
- {`^`, `^`},
- {`$`, `$`},
- {`[ac]`, `[ac]`},
- {`[^ac]`, `[^ac]`},
-
- // Posix character classes
- {`[[:alnum:]]`, `[0-9A-Za-z]`},
- {`[[:alpha:]]`, `[A-Za-z]`},
- {`[[:blank:]]`, `[\t ]`},
- {`[[:cntrl:]]`, `[\x00-\x1f\x7f]`},
- {`[[:digit:]]`, `[0-9]`},
- {`[[:graph:]]`, `[!-~]`},
- {`[[:lower:]]`, `[a-z]`},
- {`[[:print:]]`, `[ -~]`},
- {`[[:punct:]]`, "[!-/:-@\\[-`\\{-~]"},
- {`[[:space:]]`, `[\t-\r ]`},
- {`[[:upper:]]`, `[A-Z]`},
- {`[[:xdigit:]]`, `[0-9A-Fa-f]`},
-
- // Perl character classes
- {`\d`, `[0-9]`},
- {`\s`, `[\t-\n\f-\r ]`},
- {`\w`, `[0-9A-Z_a-z]`},
- {`\D`, `[^0-9]`},
- {`\S`, `[^\t-\n\f-\r ]`},
- {`\W`, `[^0-9A-Z_a-z]`},
- {`[\d]`, `[0-9]`},
- {`[\s]`, `[\t-\n\f-\r ]`},
- {`[\w]`, `[0-9A-Z_a-z]`},
- {`[\D]`, `[^0-9]`},
- {`[\S]`, `[^\t-\n\f-\r ]`},
- {`[\W]`, `[^0-9A-Z_a-z]`},
-
- // Posix repetitions
- {`a{1}`, `a`},
- {`a{2}`, `aa`},
- {`a{5}`, `aaaaa`},
- {`a{0,1}`, `a?`},
- // The next three are illegible because Simplify inserts (?:)
- // parens instead of () parens to avoid creating extra
- // captured subexpressions. The comments show a version with fewer parens.
- {`(a){0,2}`, `(?:(a)(a)?)?`}, // (aa?)?
- {`(a){0,4}`, `(?:(a)(?:(a)(?:(a)(a)?)?)?)?`}, // (a(a(aa?)?)?)?
- {`(a){2,6}`, `(a)(a)(?:(a)(?:(a)(?:(a)(a)?)?)?)?`}, // aa(a(a(aa?)?)?)?
- {`a{0,2}`, `(?:aa?)?`}, // (aa?)?
- {`a{0,4}`, `(?:a(?:a(?:aa?)?)?)?`}, // (a(a(aa?)?)?)?
- {`a{2,6}`, `aa(?:a(?:a(?:aa?)?)?)?`}, // aa(a(a(aa?)?)?)?
- {`a{0,}`, `a*`},
- {`a{1,}`, `a+`},
- {`a{2,}`, `aa+`},
- {`a{5,}`, `aaaaa+`},
-
- // Test that operators simplify their arguments.
- {`(?:a{1,}){1,}`, `a+`},
- {`(a{1,}b{1,})`, `(a+b+)`},
- {`a{1,}|b{1,}`, `a+|b+`},
- {`(?:a{1,})*`, `(?:a+)*`},
- {`(?:a{1,})+`, `a+`},
- {`(?:a{1,})?`, `(?:a+)?`},
- {``, `(?:)`},
- {`a{0}`, `(?:)`},
-
- // Character class simplification
- {`[ab]`, `[a-b]`},
- {`[a-za-za-z]`, `[a-z]`},
- {`[A-Za-zA-Za-z]`, `[A-Za-z]`},
- {`[ABCDEFGH]`, `[A-H]`},
- {`[AB-CD-EF-GH]`, `[A-H]`},
- {`[W-ZP-XE-R]`, `[E-Z]`},
- {`[a-ee-gg-m]`, `[a-m]`},
- {`[a-ea-ha-m]`, `[a-m]`},
- {`[a-ma-ha-e]`, `[a-m]`},
- {`[a-zA-Z0-9 -~]`, `[ -~]`},
-
- // Empty character classes
- {`[^[:cntrl:][:^cntrl:]]`, `[^\x00-\x{10FFFF}]`},
-
- // Full character classes
- {`[[:cntrl:][:^cntrl:]]`, `.`},
-
- // Unicode case folding.
- {`(?i)A`, `(?i:A)`},
- {`(?i)a`, `(?i:a)`},
- {`(?i)[A]`, `(?i:A)`},
- {`(?i)[a]`, `(?i:A)`},
- {`(?i)K`, `(?i:K)`},
- {`(?i)k`, `(?i:k)`},
- {`(?i)\x{212a}`, "(?i:\u212A)"},
- {`(?i)[K]`, "[Kk\u212A]"},
- {`(?i)[k]`, "[Kk\u212A]"},
- {`(?i)[\x{212a}]`, "[Kk\u212A]"},
- {`(?i)[a-z]`, "[A-Za-z\u017F\u212A]"},
- {`(?i)[\x00-\x{FFFD}]`, "[\\x00-\uFFFD]"},
- {`(?i)[\x00-\x{10FFFF}]`, `.`},
-
- // Empty string as a regular expression.
- // The empty string must be preserved inside parens in order
- // to make submatches work right, so these tests are less
- // interesting than they might otherwise be. String inserts
- // explicit (?:) in place of non-parenthesized empty strings,
- // to make them easier to spot for other parsers.
- {`(a|b|)`, `([a-b]|(?:))`},
- {`(|)`, `()`},
- {`a()`, `a()`},
- {`(()|())`, `(()|())`},
- {`(a|)`, `(a|(?:))`},
- {`ab()cd()`, `ab()cd()`},
- {`()`, `()`},
- {`()*`, `()*`},
- {`()+`, `()+`},
- {`()?`, `()?`},
- {`(){0}`, `(?:)`},
- {`(){1}`, `()`},
- {`(){1,}`, `()+`},
- {`(){0,2}`, `(?:()()?)?`},
-}
-
-func TestSimplify(t *testing.T) {
- for _, tt := range simplifyTests {
- re, err := Parse(tt.Regexp, MatchNL|Perl&^OneLine)
- if err != nil {
- t.Errorf("Parse(%#q) = error %v", tt.Regexp, err)
- continue
- }
- s := re.Simplify().String()
- if s != tt.Simple {
- t.Errorf("Simplify(%#q) = %#q, want %#q", tt.Regexp, s, tt.Simple)
- }
- }
-}
diff --git a/libgo/go/exp/spdy/read.go b/libgo/go/exp/spdy/read.go
new file mode 100644
index 00000000000..2b1fd3d0d42
--- /dev/null
+++ b/libgo/go/exp/spdy/read.go
@@ -0,0 +1,313 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package spdy
+
+import (
+ "compress/zlib"
+ "encoding/binary"
+ "http"
+ "io"
+ "os"
+ "strings"
+)
+
+func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) os.Error {
+ return f.readSynStreamFrame(h, frame)
+}
+
+func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) os.Error {
+ return f.readSynReplyFrame(h, frame)
+}
+
+func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) os.Error {
+ frame.CFHeader = h
+ if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
+ return err
+ }
+ if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) os.Error {
+ frame.CFHeader = h
+ var numSettings uint32
+ if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
+ return err
+ }
+ frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
+ for i := uint32(0); i < numSettings; i++ {
+ if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
+ return err
+ }
+ frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
+ frame.FlagIdValues[i].Id &= 0xffffff
+ if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (frame *NoopFrame) read(h ControlFrameHeader, f *Framer) os.Error {
+ frame.CFHeader = h
+ return nil
+}
+
+func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) os.Error {
+ frame.CFHeader = h
+ if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) os.Error {
+ frame.CFHeader = h
+ if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) os.Error {
+ return f.readHeadersFrame(h, frame)
+}
+
+func newControlFrame(frameType ControlFrameType) (controlFrame, os.Error) {
+ ctor, ok := cframeCtor[frameType]
+ if !ok {
+ return nil, &Error{Err: InvalidControlFrame}
+ }
+ return ctor(), nil
+}
+
+var cframeCtor = map[ControlFrameType]func() controlFrame{
+ TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
+ TypeSynReply: func() controlFrame { return new(SynReplyFrame) },
+ TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
+ TypeSettings: func() controlFrame { return new(SettingsFrame) },
+ TypeNoop: func() controlFrame { return new(NoopFrame) },
+ TypePing: func() controlFrame { return new(PingFrame) },
+ TypeGoAway: func() controlFrame { return new(GoAwayFrame) },
+ TypeHeaders: func() controlFrame { return new(HeadersFrame) },
+ // TODO(willchan): Add TypeWindowUpdate
+}
+
+func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) os.Error {
+ if f.headerDecompressor != nil {
+ f.headerReader.N = payloadSize
+ return nil
+ }
+ f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
+ decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(HeaderDictionary))
+ if err != nil {
+ return err
+ }
+ f.headerDecompressor = decompressor
+ return nil
+}
+
+// ReadFrame reads SPDY encoded data and returns a decompressed Frame.
+func (f *Framer) ReadFrame() (Frame, os.Error) {
+ var firstWord uint32
+ if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
+ return nil, err
+ }
+ if (firstWord & 0x80000000) != 0 {
+ frameType := ControlFrameType(firstWord & 0xffff)
+ version := uint16(0x7fff & (firstWord >> 16))
+ return f.parseControlFrame(version, frameType)
+ }
+ return f.parseDataFrame(firstWord & 0x7fffffff)
+}
+
+func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, os.Error) {
+ var length uint32
+ if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
+ return nil, err
+ }
+ flags := ControlFlags((length & 0xff000000) >> 24)
+ length &= 0xffffff
+ header := ControlFrameHeader{version, frameType, flags, length}
+ cframe, err := newControlFrame(frameType)
+ if err != nil {
+ return nil, err
+ }
+ if err = cframe.read(header, f); err != nil {
+ return nil, err
+ }
+ return cframe, nil
+}
+
+func parseHeaderValueBlock(r io.Reader, streamId uint32) (http.Header, os.Error) {
+ var numHeaders uint16
+ if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
+ return nil, err
+ }
+ var e os.Error
+ h := make(http.Header, int(numHeaders))
+ for i := 0; i < int(numHeaders); i++ {
+ var length uint16
+ if err := binary.Read(r, binary.BigEndian, &length); err != nil {
+ return nil, err
+ }
+ nameBytes := make([]byte, length)
+ if _, err := io.ReadFull(r, nameBytes); err != nil {
+ return nil, err
+ }
+ name := string(nameBytes)
+ if name != strings.ToLower(name) {
+ e = &Error{UnlowercasedHeaderName, streamId}
+ name = strings.ToLower(name)
+ }
+ if h[name] != nil {
+ e = &Error{DuplicateHeaders, streamId}
+ }
+ if err := binary.Read(r, binary.BigEndian, &length); err != nil {
+ return nil, err
+ }
+ value := make([]byte, length)
+ if _, err := io.ReadFull(r, value); err != nil {
+ return nil, err
+ }
+ valueList := strings.Split(string(value), "\x00")
+ for _, v := range valueList {
+ h.Add(name, v)
+ }
+ }
+ if e != nil {
+ return h, e
+ }
+ return h, nil
+}
+
+func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) os.Error {
+ frame.CFHeader = h
+ var err os.Error
+ if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
+ return err
+ }
+ if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
+ return err
+ }
+ if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
+ return err
+ }
+ frame.Priority >>= 14
+
+ reader := f.r
+ if !f.headerCompressionDisabled {
+ f.uncorkHeaderDecompressor(int64(h.length - 10))
+ reader = f.headerDecompressor
+ }
+
+ frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
+ if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
+ err = &Error{WrongCompressedPayloadSize, 0}
+ }
+ if err != nil {
+ return err
+ }
+ // Remove this condition when we bump Version to 3.
+ if Version >= 3 {
+ for h := range frame.Headers {
+ if invalidReqHeaders[h] {
+ return &Error{InvalidHeaderPresent, frame.StreamId}
+ }
+ }
+ }
+ return nil
+}
+
+func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) os.Error {
+ frame.CFHeader = h
+ var err os.Error
+ if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
+ return err
+ }
+ var unused uint16
+ if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
+ return err
+ }
+ reader := f.r
+ if !f.headerCompressionDisabled {
+ f.uncorkHeaderDecompressor(int64(h.length - 6))
+ reader = f.headerDecompressor
+ }
+ frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
+ if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
+ err = &Error{WrongCompressedPayloadSize, 0}
+ }
+ if err != nil {
+ return err
+ }
+ // Remove this condition when we bump Version to 3.
+ if Version >= 3 {
+ for h := range frame.Headers {
+ if invalidRespHeaders[h] {
+ return &Error{InvalidHeaderPresent, frame.StreamId}
+ }
+ }
+ }
+ return nil
+}
+
+func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) os.Error {
+ frame.CFHeader = h
+ var err os.Error
+ if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
+ return err
+ }
+ var unused uint16
+ if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
+ return err
+ }
+ reader := f.r
+ if !f.headerCompressionDisabled {
+ f.uncorkHeaderDecompressor(int64(h.length - 6))
+ reader = f.headerDecompressor
+ }
+ frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
+ if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
+ err = &Error{WrongCompressedPayloadSize, 0}
+ }
+ if err != nil {
+ return err
+ }
+
+ // Remove this condition when we bump Version to 3.
+ if Version >= 3 {
+ var invalidHeaders map[string]bool
+ if frame.StreamId%2 == 0 {
+ invalidHeaders = invalidReqHeaders
+ } else {
+ invalidHeaders = invalidRespHeaders
+ }
+ for h := range frame.Headers {
+ if invalidHeaders[h] {
+ return &Error{InvalidHeaderPresent, frame.StreamId}
+ }
+ }
+ }
+ return nil
+}
+
+func (f *Framer) parseDataFrame(streamId uint32) (*DataFrame, os.Error) {
+ var length uint32
+ if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
+ return nil, err
+ }
+ var frame DataFrame
+ frame.StreamId = streamId
+ frame.Flags = DataFlags(length >> 24)
+ length &= 0xffffff
+ frame.Data = make([]byte, length)
+ if _, err := io.ReadFull(f.r, frame.Data); err != nil {
+ return nil, err
+ }
+ return &frame, nil
+}
diff --git a/libgo/go/http/spdy/spdy_test.go b/libgo/go/exp/spdy/spdy_test.go
index cb91e028613..cb91e028613 100644
--- a/libgo/go/http/spdy/spdy_test.go
+++ b/libgo/go/exp/spdy/spdy_test.go
diff --git a/libgo/go/http/spdy/types.go b/libgo/go/exp/spdy/types.go
index 41cafb1741f..41cafb1741f 100644
--- a/libgo/go/http/spdy/types.go
+++ b/libgo/go/exp/spdy/types.go
diff --git a/libgo/go/http/spdy/write.go b/libgo/go/exp/spdy/write.go
index 7d40bbe9fe2..7d40bbe9fe2 100644
--- a/libgo/go/http/spdy/write.go
+++ b/libgo/go/exp/spdy/write.go
diff --git a/libgo/go/exp/sql/convert.go b/libgo/go/exp/sql/convert.go
new file mode 100644
index 00000000000..a35e0be9cbe
--- /dev/null
+++ b/libgo/go/exp/sql/convert.go
@@ -0,0 +1,106 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Type conversions for Scan.
+
+package sql
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "strconv"
+)
+
+// convertAssign copies to dest the value in src, converting it if possible.
+// An error is returned if the copy would result in loss of information.
+// dest should be a pointer type.
+func convertAssign(dest, src interface{}) os.Error {
+ // Common cases, without reflect. Fall through.
+ switch s := src.(type) {
+ case string:
+ switch d := dest.(type) {
+ case *string:
+ *d = s
+ return nil
+ }
+ case []byte:
+ switch d := dest.(type) {
+ case *string:
+ *d = string(s)
+ return nil
+ case *[]byte:
+ *d = s
+ return nil
+ }
+ }
+
+ sv := reflect.ValueOf(src)
+
+ switch d := dest.(type) {
+ case *string:
+ switch sv.Kind() {
+ case reflect.Bool,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Float32, reflect.Float64:
+ *d = fmt.Sprintf("%v", src)
+ return nil
+ }
+ }
+
+ if scanner, ok := dest.(ScannerInto); ok {
+ return scanner.ScanInto(src)
+ }
+
+ dpv := reflect.ValueOf(dest)
+ if dpv.Kind() != reflect.Ptr {
+ return os.NewError("destination not a pointer")
+ }
+
+ dv := reflect.Indirect(dpv)
+ if dv.Kind() == sv.Kind() {
+ dv.Set(sv)
+ return nil
+ }
+
+ switch dv.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ if s, ok := asString(src); ok {
+ i64, err := strconv.Atoi64(s)
+ if err != nil {
+ return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+ }
+ if dv.OverflowInt(i64) {
+ return fmt.Errorf("string %q overflows %s", s, dv.Kind())
+ }
+ dv.SetInt(i64)
+ return nil
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ if s, ok := asString(src); ok {
+ u64, err := strconv.Atoui64(s)
+ if err != nil {
+ return fmt.Errorf("converting string %q to a %s: %v", s, dv.Kind(), err)
+ }
+ if dv.OverflowUint(u64) {
+ return fmt.Errorf("string %q overflows %s", s, dv.Kind())
+ }
+ dv.SetUint(u64)
+ return nil
+ }
+ }
+
+ return fmt.Errorf("unsupported driver -> Scan pair: %T -> %T", src, dest)
+}
+
+func asString(src interface{}) (s string, ok bool) {
+ switch v := src.(type) {
+ case string:
+ return v, true
+ case []byte:
+ return string(v), true
+ }
+ return "", false
+}
diff --git a/libgo/go/exp/sql/convert_test.go b/libgo/go/exp/sql/convert_test.go
new file mode 100644
index 00000000000..88ba8e7a77a
--- /dev/null
+++ b/libgo/go/exp/sql/convert_test.go
@@ -0,0 +1,108 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sql
+
+import (
+ "fmt"
+ "reflect"
+ "testing"
+)
+
+type conversionTest struct {
+ s, d interface{} // source and destination
+
+ // following are used if they're non-zero
+ wantint int64
+ wantuint uint64
+ wantstr string
+ wanterr string
+}
+
+// Target variables for scanning into.
+var (
+ scanstr string
+ scanint int
+ scanint8 int8
+ scanint16 int16
+ scanint32 int32
+ scanuint8 uint8
+ scanuint16 uint16
+)
+
+var conversionTests = []conversionTest{
+ // Exact conversions (destination pointer type matches source type)
+ {s: "foo", d: &scanstr, wantstr: "foo"},
+ {s: 123, d: &scanint, wantint: 123},
+
+ // To strings
+ {s: []byte("byteslice"), d: &scanstr, wantstr: "byteslice"},
+ {s: 123, d: &scanstr, wantstr: "123"},
+ {s: int8(123), d: &scanstr, wantstr: "123"},
+ {s: int64(123), d: &scanstr, wantstr: "123"},
+ {s: uint8(123), d: &scanstr, wantstr: "123"},
+ {s: uint16(123), d: &scanstr, wantstr: "123"},
+ {s: uint32(123), d: &scanstr, wantstr: "123"},
+ {s: uint64(123), d: &scanstr, wantstr: "123"},
+ {s: 1.5, d: &scanstr, wantstr: "1.5"},
+
+ // Strings to integers
+ {s: "255", d: &scanuint8, wantuint: 255},
+ {s: "256", d: &scanuint8, wanterr: `string "256" overflows uint8`},
+ {s: "256", d: &scanuint16, wantuint: 256},
+ {s: "-1", d: &scanint, wantint: -1},
+ {s: "foo", d: &scanint, wanterr: `converting string "foo" to a int: parsing "foo": Invalid argument`},
+}
+
+func intValue(intptr interface{}) int64 {
+ return reflect.Indirect(reflect.ValueOf(intptr)).Int()
+}
+
+func uintValue(intptr interface{}) uint64 {
+ return reflect.Indirect(reflect.ValueOf(intptr)).Uint()
+}
+
+func TestConversions(t *testing.T) {
+ for n, ct := range conversionTests {
+ err := convertAssign(ct.d, ct.s)
+ errstr := ""
+ if err != nil {
+ errstr = err.String()
+ }
+ errf := func(format string, args ...interface{}) {
+ base := fmt.Sprintf("convertAssign #%d: for %v (%T) -> %T, ", n, ct.s, ct.s, ct.d)
+ t.Errorf(base+format, args...)
+ }
+ if errstr != ct.wanterr {
+ errf("got error %q, want error %q", errstr, ct.wanterr)
+ }
+ if ct.wantstr != "" && ct.wantstr != scanstr {
+ errf("want string %q, got %q", ct.wantstr, scanstr)
+ }
+ if ct.wantint != 0 && ct.wantint != intValue(ct.d) {
+ errf("want int %d, got %d", ct.wantint, intValue(ct.d))
+ }
+ if ct.wantuint != 0 && ct.wantuint != uintValue(ct.d) {
+ errf("want uint %d, got %d", ct.wantuint, uintValue(ct.d))
+ }
+ }
+}
+
+func TestNullableString(t *testing.T) {
+ var ns NullableString
+ convertAssign(&ns, []byte("foo"))
+ if !ns.Valid {
+ t.Errorf("expecting not null")
+ }
+ if ns.String != "foo" {
+ t.Errorf("expecting foo; got %q", ns.String)
+ }
+ convertAssign(&ns, nil)
+ if ns.Valid {
+ t.Errorf("expecting null on nil")
+ }
+ if ns.String != "" {
+ t.Errorf("expecting blank on nil; got %q", ns.String)
+ }
+}
diff --git a/libgo/go/exp/sql/driver/driver.go b/libgo/go/exp/sql/driver/driver.go
new file mode 100644
index 00000000000..7508b19fa19
--- /dev/null
+++ b/libgo/go/exp/sql/driver/driver.go
@@ -0,0 +1,169 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package driver defines interfaces to be implemented by database
+// drivers as used by package sql.
+//
+// Code simply using databases should use package sql.
+//
+// Drivers only need to be aware of a subset of Go's types. The db package
+// will convert all types into one of the following:
+//
+// int64
+// float64
+// bool
+// nil
+// []byte
+// string [*] everywhere except from Rows.Next.
+//
+package driver
+
+import (
+ "os"
+)
+
+// Driver is the interface that must be implemented by a database
+// driver.
+type Driver interface {
+ // Open returns a new or cached connection to the database.
+ // The name is a string in a driver-specific format.
+ //
+ // The returned connection is only used by one goroutine at a
+ // time.
+ Open(name string) (Conn, os.Error)
+}
+
+// Execer is an optional interface that may be implemented by a Driver
+// or a Conn.
+//
+// If a Driver does not implement Execer, the sql package's DB.Exec
+// method first obtains a free connection from its free pool or from
+// the driver's Open method. Execer should only be implemented by
+// drivers that can provide a more efficient implementation.
+//
+// If a Conn does not implement Execer, the db package's DB.Exec will
+// first prepare a query, execute the statement, and then close the
+// statement.
+//
+// All arguments are of a subset type as defined in the package docs.
+type Execer interface {
+ Exec(query string, args []interface{}) (Result, os.Error)
+}
+
+// Conn is a connection to a database. It is not used concurrently
+// by multiple goroutines.
+//
+// Conn is assumed to be stateful.
+type Conn interface {
+ // Prepare returns a prepared statement, bound to this connection.
+ Prepare(query string) (Stmt, os.Error)
+
+ // Close invalidates and potentially stops any current
+ // prepared statements and transactions, marking this
+ // connection as no longer in use. The driver may cache or
+ // close its underlying connection to its database.
+ Close() os.Error
+
+ // Begin starts and returns a new transaction.
+ Begin() (Tx, os.Error)
+}
+
+// Result is the result of a query execution.
+type Result interface {
+ // LastInsertId returns the database's auto-generated ID
+ // after, for example, an INSERT into a table with primary
+ // key.
+ LastInsertId() (int64, os.Error)
+
+ // RowsAffected returns the number of rows affected by the
+ // query.
+ RowsAffected() (int64, os.Error)
+}
+
+// Stmt is a prepared statement. It is bound to a Conn and not
+// used by multiple goroutines concurrently.
+type Stmt interface {
+ // Close closes the statement.
+ Close() os.Error
+
+ // NumInput returns the number of placeholder parameters.
+ NumInput() int
+
+ // Exec executes a query that doesn't return rows, such
+ // as an INSERT or UPDATE. The args are all of a subset
+ // type as defined above.
+ Exec(args []interface{}) (Result, os.Error)
+
+ // Exec executes a query that may return rows, such as a
+ // SELECT. The args of all of a subset type as defined above.
+ Query(args []interface{}) (Rows, os.Error)
+}
+
+// ColumnConverter may be optionally implemented by Stmt if the
+// the statement is aware of its own columns' types and can
+// convert from any type to a driver subset type.
+type ColumnConverter interface {
+ // ColumnConverter returns a ValueConverter for the provided
+ // column index. If the type of a specific column isn't known
+ // or shouldn't be handled specially, DefaultValueConverter
+ // can be returned.
+ ColumnConverter(idx int) ValueConverter
+}
+
+// Rows is an iterator over an executed query's results.
+type Rows interface {
+ // Columns returns the names of the columns. The number of
+ // columns of the result is inferred from the length of the
+ // slice. If a particular column name isn't known, an empty
+ // string should be returned for that entry.
+ Columns() []string
+
+ // Close closes the rows iterator.
+ Close() os.Error
+
+ // Next is called to populate the next row of data into
+ // the provided slice. The provided slice will be the same
+ // size as the Columns() are wide.
+ //
+ // The dest slice may be populated with only with values
+ // of subset types defined above, but excluding string.
+ // All string values must be converted to []byte.
+ Next(dest []interface{}) os.Error
+}
+
+// Tx is a transaction.
+type Tx interface {
+ Commit() os.Error
+ Rollback() os.Error
+}
+
+// RowsAffected implements Result for an INSERT or UPDATE operation
+// which mutates a number of rows.
+type RowsAffected int64
+
+var _ Result = RowsAffected(0)
+
+func (RowsAffected) LastInsertId() (int64, os.Error) {
+ return 0, os.NewError("no LastInsertId available")
+}
+
+func (v RowsAffected) RowsAffected() (int64, os.Error) {
+ return int64(v), nil
+}
+
+// DDLSuccess is a pre-defined Result for drivers to return when a DDL
+// command succeeds.
+var DDLSuccess ddlSuccess
+
+type ddlSuccess struct{}
+
+var _ Result = ddlSuccess{}
+
+func (ddlSuccess) LastInsertId() (int64, os.Error) {
+ return 0, os.NewError("no LastInsertId available after DDL statement")
+}
+
+func (ddlSuccess) RowsAffected() (int64, os.Error) {
+ return 0, os.NewError("no RowsAffected available after DDL statement")
+}
diff --git a/libgo/go/exp/sql/driver/types.go b/libgo/go/exp/sql/driver/types.go
new file mode 100644
index 00000000000..5521d5389c3
--- /dev/null
+++ b/libgo/go/exp/sql/driver/types.go
@@ -0,0 +1,161 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package driver
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "strconv"
+)
+
+// ValueConverter is the interface providing the ConvertValue method.
+type ValueConverter interface {
+ // ConvertValue converts a value to a restricted subset type.
+ ConvertValue(v interface{}) (interface{}, os.Error)
+}
+
+// Bool is a ValueConverter that converts input values to bools.
+//
+// The conversion rules are:
+// - .... TODO(bradfitz): TBD
+var Bool boolType
+
+type boolType struct{}
+
+var _ ValueConverter = boolType{}
+
+func (boolType) ConvertValue(v interface{}) (interface{}, os.Error) {
+ return nil, fmt.Errorf("TODO(bradfitz): bool conversions")
+}
+
+// Int32 is a ValueConverter that converts input values to int64,
+// respecting the limits of an int32 value.
+var Int32 int32Type
+
+type int32Type struct{}
+
+var _ ValueConverter = int32Type{}
+
+func (int32Type) ConvertValue(v interface{}) (interface{}, os.Error) {
+ rv := reflect.ValueOf(v)
+ switch rv.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ i64 := rv.Int()
+ if i64 > (1<<31)-1 || i64 < -(1<<31) {
+ return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
+ }
+ return i64, nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ u64 := rv.Uint()
+ if u64 > (1<<31)-1 {
+ return nil, fmt.Errorf("sql/driver: value %d overflows int32", v)
+ }
+ return int64(u64), nil
+ case reflect.String:
+ i, err := strconv.Atoi(rv.String())
+ if err != nil {
+ return nil, fmt.Errorf("sql/driver: value %q can't be converted to int32", v)
+ }
+ return int64(i), nil
+ }
+ return nil, fmt.Errorf("sql/driver: unsupported value %v (type %T) converting to int32", v, v)
+}
+
+// String is a ValueConverter that converts its input to a string.
+// If the value is already a string or []byte, it's unchanged.
+// If the value is of another type, conversion to string is done
+// with fmt.Sprintf("%v", v).
+var String stringType
+
+type stringType struct{}
+
+func (stringType) ConvertValue(v interface{}) (interface{}, os.Error) {
+ switch v.(type) {
+ case string, []byte:
+ return v, nil
+ }
+ return fmt.Sprintf("%v", v), nil
+}
+
+// IsParameterSubsetType reports whether v is of a valid type for a
+// parameter. These types are:
+//
+// int64
+// float64
+// bool
+// nil
+// []byte
+// string
+//
+// This is the ame list as IsScanSubsetType, with the addition of
+// string.
+func IsParameterSubsetType(v interface{}) bool {
+ if IsScanSubsetType(v) {
+ return true
+ }
+ if _, ok := v.(string); ok {
+ return true
+ }
+ return false
+}
+
+// IsScanSubsetType reports whether v is of a valid type for a
+// value populated by Rows.Next. These types are:
+//
+// int64
+// float64
+// bool
+// nil
+// []byte
+//
+// This is the same list as IsParameterSubsetType, without string.
+func IsScanSubsetType(v interface{}) bool {
+ if v == nil {
+ return true
+ }
+ switch v.(type) {
+ case int64, float64, []byte, bool:
+ return true
+ }
+ return false
+}
+
+// DefaultParameterConverter is the default implementation of
+// ValueConverter that's used when a Stmt doesn't implement
+// ColumnConverter.
+//
+// DefaultParameterConverter returns the given value directly if
+// IsSubsetType(value). Otherwise integer type are converted to
+// int64, floats to float64, and strings to []byte. Other types are
+// an error.
+var DefaultParameterConverter defaultConverter
+
+type defaultConverter struct{}
+
+var _ ValueConverter = defaultConverter{}
+
+func (defaultConverter) ConvertValue(v interface{}) (interface{}, os.Error) {
+ if IsParameterSubsetType(v) {
+ return v, nil
+ }
+
+ rv := reflect.ValueOf(v)
+ switch rv.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return rv.Int(), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
+ return int64(rv.Uint()), nil
+ case reflect.Uint64:
+ u64 := rv.Uint()
+ if u64 >= 1<<63 {
+ return nil, fmt.Errorf("uint64 values with high bit set are not supported")
+ }
+ return int64(u64), nil
+ case reflect.Float32, reflect.Float64:
+ return rv.Float(), nil
+ }
+ return nil, fmt.Errorf("unsupported type %s", rv.Kind())
+}
diff --git a/libgo/go/exp/sql/fakedb_test.go b/libgo/go/exp/sql/fakedb_test.go
new file mode 100644
index 00000000000..c906185e584
--- /dev/null
+++ b/libgo/go/exp/sql/fakedb_test.go
@@ -0,0 +1,497 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sql
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "strconv"
+ "strings"
+ "sync"
+
+ "exp/sql/driver"
+)
+
+var _ = log.Printf
+
+// fakeDriver is a fake database that implements Go's driver.Driver
+// interface, just for testing.
+//
+// It speaks a query language that's semantically similar to but
+// syntantically different and simpler than SQL. The syntax is as
+// follows:
+//
+// WIPE
+// CREATE|<tablename>|<col>=<type>,<col>=<type>,...
+// where types are: "string", [u]int{8,16,32,64}, "bool"
+// INSERT|<tablename>|col=val,col2=val2,col3=?
+// SELECT|<tablename>|projectcol1,projectcol2|filtercol=?,filtercol2=?
+//
+// When opening a a fakeDriver's database, it starts empty with no
+// tables. All tables and data are stored in memory only.
+type fakeDriver struct {
+ mu sync.Mutex
+ openCount int
+ dbs map[string]*fakeDB
+}
+
+type fakeDB struct {
+ name string
+
+ mu sync.Mutex
+ free []*fakeConn
+ tables map[string]*table
+}
+
+type table struct {
+ mu sync.Mutex
+ colname []string
+ coltype []string
+ rows []*row
+}
+
+func (t *table) columnIndex(name string) int {
+ for n, nname := range t.colname {
+ if name == nname {
+ return n
+ }
+ }
+ return -1
+}
+
+type row struct {
+ cols []interface{} // must be same size as its table colname + coltype
+}
+
+func (r *row) clone() *row {
+ nrow := &row{cols: make([]interface{}, len(r.cols))}
+ copy(nrow.cols, r.cols)
+ return nrow
+}
+
+type fakeConn struct {
+ db *fakeDB // where to return ourselves to
+
+ currTx *fakeTx
+}
+
+type fakeTx struct {
+ c *fakeConn
+}
+
+type fakeStmt struct {
+ c *fakeConn
+ q string // just for debugging
+
+ cmd string
+ table string
+
+ colName []string // used by CREATE, INSERT, SELECT (selected columns)
+ colType []string // used by CREATE
+ colValue []interface{} // used by INSERT (mix of strings and "?" for bound params)
+ placeholders int // used by INSERT/SELECT: number of ? params
+
+ whereCol []string // used by SELECT (all placeholders)
+
+ placeholderConverter []driver.ValueConverter // used by INSERT
+}
+
+var fdriver driver.Driver = &fakeDriver{}
+
+func init() {
+ Register("test", fdriver)
+}
+
+// Supports dsn forms:
+// <dbname>
+// <dbname>;wipe
+func (d *fakeDriver) Open(dsn string) (driver.Conn, os.Error) {
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ d.openCount++
+ if d.dbs == nil {
+ d.dbs = make(map[string]*fakeDB)
+ }
+ parts := strings.Split(dsn, ";")
+ if len(parts) < 1 {
+ return nil, os.NewError("fakedb: no database name")
+ }
+ name := parts[0]
+ db, ok := d.dbs[name]
+ if !ok {
+ db = &fakeDB{name: name}
+ d.dbs[name] = db
+ }
+ return &fakeConn{db: db}, nil
+}
+
+func (db *fakeDB) wipe() {
+ db.mu.Lock()
+ defer db.mu.Unlock()
+ db.tables = nil
+}
+
+func (db *fakeDB) createTable(name string, columnNames, columnTypes []string) os.Error {
+ db.mu.Lock()
+ defer db.mu.Unlock()
+ if db.tables == nil {
+ db.tables = make(map[string]*table)
+ }
+ if _, exist := db.tables[name]; exist {
+ return fmt.Errorf("table %q already exists", name)
+ }
+ if len(columnNames) != len(columnTypes) {
+ return fmt.Errorf("create table of %q len(names) != len(types): %d vs %d",
+ name, len(columnNames), len(columnTypes))
+ }
+ db.tables[name] = &table{colname: columnNames, coltype: columnTypes}
+ return nil
+}
+
+// must be called with db.mu lock held
+func (db *fakeDB) table(table string) (*table, bool) {
+ if db.tables == nil {
+ return nil, false
+ }
+ t, ok := db.tables[table]
+ return t, ok
+}
+
+func (db *fakeDB) columnType(table, column string) (typ string, ok bool) {
+ db.mu.Lock()
+ defer db.mu.Unlock()
+ t, ok := db.table(table)
+ if !ok {
+ return
+ }
+ for n, cname := range t.colname {
+ if cname == column {
+ return t.coltype[n], true
+ }
+ }
+ return "", false
+}
+
+func (c *fakeConn) Begin() (driver.Tx, os.Error) {
+ if c.currTx != nil {
+ return nil, os.NewError("already in a transaction")
+ }
+ c.currTx = &fakeTx{c: c}
+ return c.currTx, nil
+}
+
+func (c *fakeConn) Close() os.Error {
+ if c.currTx != nil {
+ return os.NewError("can't close; in a Transaction")
+ }
+ if c.db == nil {
+ return os.NewError("can't close; already closed")
+ }
+ c.db = nil
+ return nil
+}
+
+func errf(msg string, args ...interface{}) os.Error {
+ return os.NewError("fakedb: " + fmt.Sprintf(msg, args...))
+}
+
+// parts are table|selectCol1,selectCol2|whereCol=?,whereCol2=?
+// (note that where where columns must always contain ? marks,
+// just a limitation for fakedb)
+func (c *fakeConn) prepareSelect(stmt *fakeStmt, parts []string) (driver.Stmt, os.Error) {
+ if len(parts) != 3 {
+ return nil, errf("invalid SELECT syntax with %d parts; want 3", len(parts))
+ }
+ stmt.table = parts[0]
+ stmt.colName = strings.Split(parts[1], ",")
+ for n, colspec := range strings.Split(parts[2], ",") {
+ nameVal := strings.Split(colspec, "=")
+ if len(nameVal) != 2 {
+ return nil, errf("SELECT on table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+ }
+ column, value := nameVal[0], nameVal[1]
+ _, ok := c.db.columnType(stmt.table, column)
+ if !ok {
+ return nil, errf("SELECT on table %q references non-existent column %q", stmt.table, column)
+ }
+ if value != "?" {
+ return nil, errf("SELECT on table %q has pre-bound value for where column %q; need a question mark",
+ stmt.table, column)
+ }
+ stmt.whereCol = append(stmt.whereCol, column)
+ stmt.placeholders++
+ }
+ return stmt, nil
+}
+
+// parts are table|col=type,col2=type2
+func (c *fakeConn) prepareCreate(stmt *fakeStmt, parts []string) (driver.Stmt, os.Error) {
+ if len(parts) != 2 {
+ return nil, errf("invalid CREATE syntax with %d parts; want 2", len(parts))
+ }
+ stmt.table = parts[0]
+ for n, colspec := range strings.Split(parts[1], ",") {
+ nameType := strings.Split(colspec, "=")
+ if len(nameType) != 2 {
+ return nil, errf("CREATE table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+ }
+ stmt.colName = append(stmt.colName, nameType[0])
+ stmt.colType = append(stmt.colType, nameType[1])
+ }
+ return stmt, nil
+}
+
+// parts are table|col=?,col2=val
+func (c *fakeConn) prepareInsert(stmt *fakeStmt, parts []string) (driver.Stmt, os.Error) {
+ if len(parts) != 2 {
+ return nil, errf("invalid INSERT syntax with %d parts; want 2", len(parts))
+ }
+ stmt.table = parts[0]
+ for n, colspec := range strings.Split(parts[1], ",") {
+ nameVal := strings.Split(colspec, "=")
+ if len(nameVal) != 2 {
+ return nil, errf("INSERT table %q has invalid column spec of %q (index %d)", stmt.table, colspec, n)
+ }
+ column, value := nameVal[0], nameVal[1]
+ ctype, ok := c.db.columnType(stmt.table, column)
+ if !ok {
+ return nil, errf("INSERT table %q references non-existent column %q", stmt.table, column)
+ }
+ stmt.colName = append(stmt.colName, column)
+
+ if value != "?" {
+ var subsetVal interface{}
+ // Convert to driver subset type
+ switch ctype {
+ case "string":
+ subsetVal = []byte(value)
+ case "int32":
+ i, err := strconv.Atoi(value)
+ if err != nil {
+ return nil, errf("invalid conversion to int32 from %q", value)
+ }
+ subsetVal = int64(i) // int64 is a subset type, but not int32
+ default:
+ return nil, errf("unsupported conversion for pre-bound parameter %q to type %q", value, ctype)
+ }
+ stmt.colValue = append(stmt.colValue, subsetVal)
+ } else {
+ stmt.placeholders++
+ stmt.placeholderConverter = append(stmt.placeholderConverter, converterForType(ctype))
+ stmt.colValue = append(stmt.colValue, "?")
+ }
+ }
+ return stmt, nil
+}
+
+func (c *fakeConn) Prepare(query string) (driver.Stmt, os.Error) {
+ if c.db == nil {
+ panic("nil c.db; conn = " + fmt.Sprintf("%#v", c))
+ }
+ parts := strings.Split(query, "|")
+ if len(parts) < 1 {
+ return nil, errf("empty query")
+ }
+ cmd := parts[0]
+ parts = parts[1:]
+ stmt := &fakeStmt{q: query, c: c, cmd: cmd}
+ switch cmd {
+ case "WIPE":
+ // Nothing
+ case "SELECT":
+ return c.prepareSelect(stmt, parts)
+ case "CREATE":
+ return c.prepareCreate(stmt, parts)
+ case "INSERT":
+ return c.prepareInsert(stmt, parts)
+ default:
+ return nil, errf("unsupported command type %q", cmd)
+ }
+ return stmt, nil
+}
+
+func (s *fakeStmt) ColumnConverter(idx int) driver.ValueConverter {
+ return s.placeholderConverter[idx]
+}
+
+func (s *fakeStmt) Close() os.Error {
+ return nil
+}
+
+func (s *fakeStmt) Exec(args []interface{}) (driver.Result, os.Error) {
+ db := s.c.db
+ switch s.cmd {
+ case "WIPE":
+ db.wipe()
+ return driver.DDLSuccess, nil
+ case "CREATE":
+ if err := db.createTable(s.table, s.colName, s.colType); err != nil {
+ return nil, err
+ }
+ return driver.DDLSuccess, nil
+ case "INSERT":
+ return s.execInsert(args)
+ }
+ fmt.Printf("EXEC statement, cmd=%q: %#v\n", s.cmd, s)
+ return nil, fmt.Errorf("unimplemented statement Exec command type of %q", s.cmd)
+}
+
+func (s *fakeStmt) execInsert(args []interface{}) (driver.Result, os.Error) {
+ db := s.c.db
+ if len(args) != s.placeholders {
+ panic("error in pkg db; should only get here if size is correct")
+ }
+ db.mu.Lock()
+ t, ok := db.table(s.table)
+ db.mu.Unlock()
+ if !ok {
+ return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
+ }
+
+ t.mu.Lock()
+ defer t.mu.Unlock()
+
+ cols := make([]interface{}, len(t.colname))
+ argPos := 0
+ for n, colname := range s.colName {
+ colidx := t.columnIndex(colname)
+ if colidx == -1 {
+ return nil, fmt.Errorf("fakedb: column %q doesn't exist or dropped since prepared statement was created", colname)
+ }
+ var val interface{}
+ if strvalue, ok := s.colValue[n].(string); ok && strvalue == "?" {
+ val = args[argPos]
+ argPos++
+ } else {
+ val = s.colValue[n]
+ }
+ cols[colidx] = val
+ }
+
+ t.rows = append(t.rows, &row{cols: cols})
+ return driver.RowsAffected(1), nil
+}
+
+func (s *fakeStmt) Query(args []interface{}) (driver.Rows, os.Error) {
+ db := s.c.db
+ if len(args) != s.placeholders {
+ panic("error in pkg db; should only get here if size is correct")
+ }
+
+ db.mu.Lock()
+ t, ok := db.table(s.table)
+ db.mu.Unlock()
+ if !ok {
+ return nil, fmt.Errorf("fakedb: table %q doesn't exist", s.table)
+ }
+ t.mu.Lock()
+ defer t.mu.Unlock()
+
+ colIdx := make(map[string]int) // select column name -> column index in table
+ for _, name := range s.colName {
+ idx := t.columnIndex(name)
+ if idx == -1 {
+ return nil, fmt.Errorf("fakedb: unknown column name %q", name)
+ }
+ colIdx[name] = idx
+ }
+
+ mrows := []*row{}
+rows:
+ for _, trow := range t.rows {
+ // Process the where clause, skipping non-match rows. This is lazy
+ // and just uses fmt.Sprintf("%v") to test equality. Good enough
+ // for test code.
+ for widx, wcol := range s.whereCol {
+ idx := t.columnIndex(wcol)
+ if idx == -1 {
+ return nil, fmt.Errorf("db: invalid where clause column %q", wcol)
+ }
+ tcol := trow.cols[idx]
+ if bs, ok := tcol.([]byte); ok {
+ // lazy hack to avoid sprintf %v on a []byte
+ tcol = string(bs)
+ }
+ if fmt.Sprintf("%v", tcol) != fmt.Sprintf("%v", args[widx]) {
+ continue rows
+ }
+ }
+ mrow := &row{cols: make([]interface{}, len(s.colName))}
+ for seli, name := range s.colName {
+ mrow.cols[seli] = trow.cols[colIdx[name]]
+ }
+ mrows = append(mrows, mrow)
+ }
+
+ cursor := &rowsCursor{
+ pos: -1,
+ rows: mrows,
+ cols: s.colName,
+ }
+ return cursor, nil
+}
+
+func (s *fakeStmt) NumInput() int {
+ return s.placeholders
+}
+
+func (tx *fakeTx) Commit() os.Error {
+ tx.c.currTx = nil
+ return nil
+}
+
+func (tx *fakeTx) Rollback() os.Error {
+ tx.c.currTx = nil
+ return nil
+}
+
+type rowsCursor struct {
+ cols []string
+ pos int
+ rows []*row
+ closed bool
+}
+
+func (rc *rowsCursor) Close() os.Error {
+ rc.closed = true
+ return nil
+}
+
+func (rc *rowsCursor) Columns() []string {
+ return rc.cols
+}
+
+func (rc *rowsCursor) Next(dest []interface{}) os.Error {
+ if rc.closed {
+ return os.NewError("fakedb: cursor is closed")
+ }
+ rc.pos++
+ if rc.pos >= len(rc.rows) {
+ return os.EOF // per interface spec
+ }
+ for i, v := range rc.rows[rc.pos].cols {
+ // TODO(bradfitz): convert to subset types? naah, I
+ // think the subset types should only be input to
+ // driver, but the db package should be able to handle
+ // a wider range of types coming out of drivers. all
+ // for ease of drivers, and to prevent drivers from
+ // messing up conversions or doing them differently.
+ dest[i] = v
+ }
+ return nil
+}
+
+func converterForType(typ string) driver.ValueConverter {
+ switch typ {
+ case "bool":
+ return driver.Bool
+ case "int32":
+ return driver.Int32
+ case "string":
+ return driver.String
+ }
+ panic("invalid fakedb column type of " + typ)
+}
diff --git a/libgo/go/exp/sql/sql.go b/libgo/go/exp/sql/sql.go
new file mode 100644
index 00000000000..7f0e0b28425
--- /dev/null
+++ b/libgo/go/exp/sql/sql.go
@@ -0,0 +1,578 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package sql provides a generic interface around SQL (or SQL-like)
+// databases.
+package sql
+
+import (
+ "fmt"
+ "os"
+ "runtime"
+ "sync"
+
+ "exp/sql/driver"
+)
+
+var drivers = make(map[string]driver.Driver)
+
+// Register makes a database driver available by the provided name.
+// If Register is called twice with the same name or if driver is nil,
+// it panics.
+func Register(name string, driver driver.Driver) {
+ if driver == nil {
+ panic("db: Register driver is nil")
+ }
+ if _, dup := drivers[name]; dup {
+ panic("db: Register called twice for driver " + name)
+ }
+ drivers[name] = driver
+}
+
+// NullableString represents a string that may be null.
+// NullableString implements the ScannerInto interface so
+// it can be used as a scan destination:
+//
+// var s NullableString
+// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s)
+// ...
+// if s.Valid {
+// // use s.String
+// } else {
+// // NULL value
+// }
+//
+// TODO(bradfitz): add other types.
+type NullableString struct {
+ String string
+ Valid bool // Valid is true if String is not NULL
+}
+
+// ScanInto implements the ScannerInto interface.
+func (ms *NullableString) ScanInto(value interface{}) os.Error {
+ if value == nil {
+ ms.String, ms.Valid = "", false
+ return nil
+ }
+ ms.Valid = true
+ return convertAssign(&ms.String, value)
+}
+
+// ScannerInto is an interface used by Scan.
+type ScannerInto interface {
+ // ScanInto assigns a value from a database driver.
+ //
+ // The value will be of one of the following restricted
+ // set of types:
+ //
+ // int64
+ // float64
+ // bool
+ // []byte
+ // nil - for NULL values
+ //
+ // An error should be returned if the value can not be stored
+ // without loss of information.
+ ScanInto(value interface{}) os.Error
+}
+
+// ErrNoRows is returned by Scan when QueryRow doesn't return a
+// row. In such a case, QueryRow returns a placeholder *Row value that
+// defers this error until a Scan.
+var ErrNoRows = os.NewError("db: no rows in result set")
+
+// DB is a database handle. It's safe for concurrent use by multiple
+// goroutines.
+type DB struct {
+ driver driver.Driver
+ dsn string
+
+ mu sync.Mutex
+ freeConn []driver.Conn
+}
+
+// Open opens a database specified by its database driver name and a
+// driver-specific data source name, usually consisting of at least a
+// database name and connection information.
+//
+// Most users will open a database via a driver-specific connection
+// helper function that returns a *DB.
+func Open(driverName, dataSourceName string) (*DB, os.Error) {
+ driver, ok := drivers[driverName]
+ if !ok {
+ return nil, fmt.Errorf("db: unknown driver %q (forgotten import?)", driverName)
+ }
+ return &DB{driver: driver, dsn: dataSourceName}, nil
+}
+
+func (db *DB) maxIdleConns() int {
+ const defaultMaxIdleConns = 2
+ // TODO(bradfitz): ask driver, if supported, for its default preference
+ // TODO(bradfitz): let users override?
+ return defaultMaxIdleConns
+}
+
+// conn returns a newly-opened or cached driver.Conn
+func (db *DB) conn() (driver.Conn, os.Error) {
+ db.mu.Lock()
+ if n := len(db.freeConn); n > 0 {
+ conn := db.freeConn[n-1]
+ db.freeConn = db.freeConn[:n-1]
+ db.mu.Unlock()
+ return conn, nil
+ }
+ db.mu.Unlock()
+ return db.driver.Open(db.dsn)
+}
+
+func (db *DB) connIfFree(wanted driver.Conn) (conn driver.Conn, ok bool) {
+ db.mu.Lock()
+ defer db.mu.Unlock()
+ for n, conn := range db.freeConn {
+ if conn == wanted {
+ db.freeConn[n] = db.freeConn[len(db.freeConn)-1]
+ db.freeConn = db.freeConn[:len(db.freeConn)-1]
+ return wanted, true
+ }
+ }
+ return nil, false
+}
+
+func (db *DB) putConn(c driver.Conn) {
+ if n := len(db.freeConn); n < db.maxIdleConns() {
+ db.freeConn = append(db.freeConn, c)
+ return
+ }
+ db.closeConn(c)
+}
+
+func (db *DB) closeConn(c driver.Conn) {
+ // TODO: check to see if we need this Conn for any prepared statements
+ // that are active.
+ c.Close()
+}
+
+// Prepare creates a prepared statement for later execution.
+func (db *DB) Prepare(query string) (*Stmt, os.Error) {
+ // TODO: check if db.driver supports an optional
+ // driver.Preparer interface and call that instead, if so,
+ // otherwise we make a prepared statement that's bound
+ // to a connection, and to execute this prepared statement
+ // we either need to use this connection (if it's free), else
+ // get a new connection + re-prepare + execute on that one.
+ ci, err := db.conn()
+ if err != nil {
+ return nil, err
+ }
+ defer db.putConn(ci)
+ si, err := ci.Prepare(query)
+ if err != nil {
+ return nil, err
+ }
+ stmt := &Stmt{
+ db: db,
+ query: query,
+ css: []connStmt{{ci, si}},
+ }
+ return stmt, nil
+}
+
+// Exec executes a query without returning any rows.
+func (db *DB) Exec(query string, args ...interface{}) (Result, os.Error) {
+ // Optional fast path, if the driver implements driver.Execer.
+ if execer, ok := db.driver.(driver.Execer); ok {
+ resi, err := execer.Exec(query, args)
+ if err != nil {
+ return nil, err
+ }
+ return result{resi}, nil
+ }
+
+ // If the driver does not implement driver.Execer, we need
+ // a connection.
+ conn, err := db.conn()
+ if err != nil {
+ return nil, err
+ }
+ defer db.putConn(conn)
+
+ if execer, ok := conn.(driver.Execer); ok {
+ resi, err := execer.Exec(query, args)
+ if err != nil {
+ return nil, err
+ }
+ return result{resi}, nil
+ }
+
+ sti, err := conn.Prepare(query)
+ if err != nil {
+ return nil, err
+ }
+ defer sti.Close()
+ resi, err := sti.Exec(args)
+ if err != nil {
+ return nil, err
+ }
+ return result{resi}, nil
+}
+
+// Query executes a query that returns rows, typically a SELECT.
+func (db *DB) Query(query string, args ...interface{}) (*Rows, os.Error) {
+ stmt, err := db.Prepare(query)
+ if err != nil {
+ return nil, err
+ }
+ defer stmt.Close()
+ return stmt.Query(args...)
+}
+
+// QueryRow executes a query that is expected to return at most one row.
+// QueryRow always return a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+func (db *DB) QueryRow(query string, args ...interface{}) *Row {
+ rows, err := db.Query(query, args...)
+ if err != nil {
+ return &Row{err: err}
+ }
+ return &Row{rows: rows}
+}
+
+// Begin starts a transaction. The isolation level is dependent on
+// the driver.
+func (db *DB) Begin() (*Tx, os.Error) {
+ // TODO(bradfitz): add another method for beginning a transaction
+ // at a specific isolation level.
+ panic(todo())
+}
+
+// DriverDatabase returns the database's underlying driver.
+func (db *DB) Driver() driver.Driver {
+ return db.driver
+}
+
+// Tx is an in-progress database transaction.
+type Tx struct {
+
+}
+
+// Commit commits the transaction.
+func (tx *Tx) Commit() os.Error {
+ panic(todo())
+}
+
+// Rollback aborts the transaction.
+func (tx *Tx) Rollback() os.Error {
+ panic(todo())
+}
+
+// Prepare creates a prepared statement.
+func (tx *Tx) Prepare(query string) (*Stmt, os.Error) {
+ panic(todo())
+}
+
+// Exec executes a query that doesn't return rows.
+// For example: an INSERT and UPDATE.
+func (tx *Tx) Exec(query string, args ...interface{}) {
+ panic(todo())
+}
+
+// Query executes a query that returns rows, typically a SELECT.
+func (tx *Tx) Query(query string, args ...interface{}) (*Rows, os.Error) {
+ panic(todo())
+}
+
+// QueryRow executes a query that is expected to return at most one row.
+// QueryRow always return a non-nil value. Errors are deferred until
+// Row's Scan method is called.
+func (tx *Tx) QueryRow(query string, args ...interface{}) *Row {
+ panic(todo())
+}
+
+// connStmt is a prepared statement on a particular connection.
+type connStmt struct {
+ ci driver.Conn
+ si driver.Stmt
+}
+
+// Stmt is a prepared statement. Stmt is safe for concurrent use by multiple goroutines.
+type Stmt struct {
+ // Immutable:
+ db *DB // where we came from
+ query string // that created the Sttm
+
+ mu sync.Mutex
+ closed bool
+ css []connStmt // can use any that have idle connections
+}
+
+func todo() string {
+ _, file, line, _ := runtime.Caller(1)
+ return fmt.Sprintf("%s:%d: TODO: implement", file, line)
+}
+
+// Exec executes a prepared statement with the given arguments and
+// returns a Result summarizing the effect of the statement.
+func (s *Stmt) Exec(args ...interface{}) (Result, os.Error) {
+ ci, si, err := s.connStmt()
+ if err != nil {
+ return nil, err
+ }
+ defer s.db.putConn(ci)
+
+ if want := si.NumInput(); len(args) != want {
+ return nil, fmt.Errorf("db: expected %d arguments, got %d", want, len(args))
+ }
+
+ // Convert args to subset types.
+ if cc, ok := si.(driver.ColumnConverter); ok {
+ for n, arg := range args {
+ args[n], err = cc.ColumnConverter(n).ConvertValue(arg)
+ if err != nil {
+ return nil, fmt.Errorf("db: converting Exec argument #%d's type: %v", n, err)
+ }
+ if !driver.IsParameterSubsetType(args[n]) {
+ return nil, fmt.Errorf("db: driver ColumnConverter error converted %T to unsupported type %T",
+ arg, args[n])
+ }
+ }
+ } else {
+ for n, arg := range args {
+ args[n], err = driver.DefaultParameterConverter.ConvertValue(arg)
+ if err != nil {
+ return nil, fmt.Errorf("db: converting Exec argument #%d's type: %v", n, err)
+ }
+ }
+ }
+
+ resi, err := si.Exec(args)
+ if err != nil {
+ return nil, err
+ }
+ return result{resi}, nil
+}
+
+func (s *Stmt) connStmt(args ...interface{}) (driver.Conn, driver.Stmt, os.Error) {
+ s.mu.Lock()
+ if s.closed {
+ return nil, nil, os.NewError("db: statement is closed")
+ }
+ var cs connStmt
+ match := false
+ for _, v := range s.css {
+ // TODO(bradfitz): lazily clean up entries in this
+ // list with dead conns while enumerating
+ if _, match = s.db.connIfFree(cs.ci); match {
+ cs = v
+ break
+ }
+ }
+ s.mu.Unlock()
+
+ // Make a new conn if all are busy.
+ // TODO(bradfitz): or wait for one? make configurable later?
+ if !match {
+ ci, err := s.db.conn()
+ if err != nil {
+ return nil, nil, err
+ }
+ si, err := ci.Prepare(s.query)
+ if err != nil {
+ return nil, nil, err
+ }
+ s.mu.Lock()
+ cs = connStmt{ci, si}
+ s.css = append(s.css, cs)
+ s.mu.Unlock()
+ }
+
+ return cs.ci, cs.si, nil
+}
+
+// Query executes a prepared query statement with the given arguments
+// and returns the query results as a *Rows.
+func (s *Stmt) Query(args ...interface{}) (*Rows, os.Error) {
+ ci, si, err := s.connStmt(args...)
+ if err != nil {
+ return nil, err
+ }
+ if len(args) != si.NumInput() {
+ return nil, fmt.Errorf("db: statement expects %d inputs; got %d", si.NumInput(), len(args))
+ }
+ rowsi, err := si.Query(args)
+ if err != nil {
+ s.db.putConn(ci)
+ return nil, err
+ }
+ // Note: ownership of ci passes to the *Rows
+ rows := &Rows{
+ db: s.db,
+ ci: ci,
+ rowsi: rowsi,
+ }
+ return rows, nil
+}
+
+// QueryRow executes a prepared query statement with the given arguments.
+// If an error occurs during the execution of the statement, that error will
+// be returned by a call to Scan on the returned *Row, which is always non-nil.
+// If the query selects no rows, the *Row's Scan will return ErrNoRows.
+// Otherwise, the *Row's Scan scans the first selected row and discards
+// the rest.
+//
+// Example usage:
+//
+// var name string
+// err := nameByUseridStmt.QueryRow(id).Scan(&s)
+func (s *Stmt) QueryRow(args ...interface{}) *Row {
+ rows, err := s.Query(args...)
+ if err != nil {
+ return &Row{err: err}
+ }
+ return &Row{rows: rows}
+}
+
+// Close closes the statement.
+func (s *Stmt) Close() os.Error {
+ s.mu.Lock()
+ defer s.mu.Unlock() // TODO(bradfitz): move this unlock after 'closed = true'?
+ if s.closed {
+ return nil
+ }
+ s.closed = true
+ for _, v := range s.css {
+ if ci, match := s.db.connIfFree(v.ci); match {
+ v.si.Close()
+ s.db.putConn(ci)
+ } else {
+ // TODO(bradfitz): care that we can't close
+ // this statement because the statement's
+ // connection is in use?
+ }
+ }
+ return nil
+}
+
+// Rows is the result of a query. Its cursor starts before the first row
+// of the result set. Use Next to advance through the rows:
+//
+// rows, err := db.Query("SELECT ...")
+// ...
+// for rows.Next() {
+// var id int
+// var name string
+// err = rows.Scan(&id, &name)
+// ...
+// }
+// err = rows.Error() // get any Error encountered during iteration
+// ...
+type Rows struct {
+ db *DB
+ ci driver.Conn // owned; must be returned when Rows is closed
+ rowsi driver.Rows
+
+ closed bool
+ lastcols []interface{}
+ lasterr os.Error
+}
+
+// Next prepares the next result row for reading with the Scan method.
+// It returns true on success, false if there is no next result row.
+// Every call to Scan, even the first one, must be preceded by a call
+// to Next.
+func (rs *Rows) Next() bool {
+ if rs.closed {
+ return false
+ }
+ if rs.lasterr != nil {
+ return false
+ }
+ if rs.lastcols == nil {
+ rs.lastcols = make([]interface{}, len(rs.rowsi.Columns()))
+ }
+ rs.lasterr = rs.rowsi.Next(rs.lastcols)
+ return rs.lasterr == nil
+}
+
+// Error returns the error, if any, that was encountered during iteration.
+func (rs *Rows) Error() os.Error {
+ if rs.lasterr == os.EOF {
+ return nil
+ }
+ return rs.lasterr
+}
+
+// Scan copies the columns in the current row into the values pointed
+// at by dest. If dest contains pointers to []byte, the slices should
+// not be modified and should only be considered valid until the next
+// call to Next or Scan.
+func (rs *Rows) Scan(dest ...interface{}) os.Error {
+ if rs.closed {
+ return os.NewError("db: Rows closed")
+ }
+ if rs.lasterr != nil {
+ return rs.lasterr
+ }
+ if rs.lastcols == nil {
+ return os.NewError("db: Scan called without calling Next")
+ }
+ if len(dest) != len(rs.lastcols) {
+ return fmt.Errorf("db: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest))
+ }
+ for i, sv := range rs.lastcols {
+ err := convertAssign(dest[i], sv)
+ if err != nil {
+ return fmt.Errorf("db: Scan error on column index %d: %v", i, err)
+ }
+ }
+ return nil
+}
+
+// Close closes the Rows, preventing further enumeration. If the
+// end is encountered, the Rows are closed automatically. Close
+// is idempotent.
+func (rs *Rows) Close() os.Error {
+ if rs.closed {
+ return nil
+ }
+ rs.closed = true
+ err := rs.rowsi.Close()
+ rs.db.putConn(rs.ci)
+ return err
+}
+
+// Row is the result of calling QueryRow to select a single row.
+type Row struct {
+ // One of these two will be non-nil:
+ err os.Error // deferred error for easy chaining
+ rows *Rows
+}
+
+// Scan copies the columns from the matched row into the values
+// pointed at by dest. If more than one row matches the query,
+// Scan uses the first row and discards the rest. If no row matches
+// the query, Scan returns ErrNoRows.
+//
+// If dest contains pointers to []byte, the slices should not be
+// modified and should only be considered valid until the next call to
+// Next or Scan.
+func (r *Row) Scan(dest ...interface{}) os.Error {
+ if r.err != nil {
+ return r.err
+ }
+ defer r.rows.Close()
+ if !r.rows.Next() {
+ return ErrNoRows
+ }
+ return r.rows.Scan(dest...)
+}
+
+// A Result summarizes an executed SQL command.
+type Result interface {
+ LastInsertId() (int64, os.Error)
+ RowsAffected() (int64, os.Error)
+}
+
+type result struct {
+ driver.Result
+}
diff --git a/libgo/go/exp/sql/sql_test.go b/libgo/go/exp/sql/sql_test.go
new file mode 100644
index 00000000000..eaa0a90356b
--- /dev/null
+++ b/libgo/go/exp/sql/sql_test.go
@@ -0,0 +1,145 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sql
+
+import (
+ "strings"
+ "testing"
+)
+
+func newTestDB(t *testing.T, name string) *DB {
+ db, err := Open("test", "foo")
+ if err != nil {
+ t.Fatalf("Open: %v", err)
+ }
+ if _, err := db.Exec("WIPE"); err != nil {
+ t.Fatalf("exec wipe: %v", err)
+ }
+ if name == "people" {
+ exec(t, db, "CREATE|people|name=string,age=int32,dead=bool")
+ exec(t, db, "INSERT|people|name=Alice,age=?", 1)
+ exec(t, db, "INSERT|people|name=Bob,age=?", 2)
+ exec(t, db, "INSERT|people|name=Chris,age=?", 3)
+
+ }
+ return db
+}
+
+func exec(t *testing.T, db *DB, query string, args ...interface{}) {
+ _, err := db.Exec(query, args...)
+ if err != nil {
+ t.Fatalf("Exec of %q: %v", query, err)
+ }
+}
+
+func TestQuery(t *testing.T) {
+ db := newTestDB(t, "people")
+ var name string
+ var age int
+
+ err := db.QueryRow("SELECT|people|age,name|age=?", 3).Scan(&age)
+ if err == nil || !strings.Contains(err.String(), "expected 2 destination arguments") {
+ t.Errorf("expected error from wrong number of arguments; actually got: %v", err)
+ }
+
+ err = db.QueryRow("SELECT|people|age,name|age=?", 2).Scan(&age, &name)
+ if err != nil {
+ t.Fatalf("age QueryRow+Scan: %v", err)
+ }
+ if name != "Bob" {
+ t.Errorf("expected name Bob, got %q", name)
+ }
+ if age != 2 {
+ t.Errorf("expected age 2, got %d", age)
+ }
+
+ err = db.QueryRow("SELECT|people|age,name|name=?", "Alice").Scan(&age, &name)
+ if err != nil {
+ t.Fatalf("name QueryRow+Scan: %v", err)
+ }
+ if name != "Alice" {
+ t.Errorf("expected name Alice, got %q", name)
+ }
+ if age != 1 {
+ t.Errorf("expected age 1, got %d", age)
+ }
+}
+
+func TestStatementQueryRow(t *testing.T) {
+ db := newTestDB(t, "people")
+ stmt, err := db.Prepare("SELECT|people|age|name=?")
+ if err != nil {
+ t.Fatalf("Prepare: %v", err)
+ }
+ var age int
+ for n, tt := range []struct {
+ name string
+ want int
+ }{
+ {"Alice", 1},
+ {"Bob", 2},
+ {"Chris", 3},
+ } {
+ if err := stmt.QueryRow(tt.name).Scan(&age); err != nil {
+ t.Errorf("%d: on %q, QueryRow/Scan: %v", n, tt.name, err)
+ } else if age != tt.want {
+ t.Errorf("%d: age=%d, want %d", n, age, tt.want)
+ }
+ }
+
+}
+
+// just a test of fakedb itself
+func TestBogusPreboundParameters(t *testing.T) {
+ db := newTestDB(t, "foo")
+ exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+ _, err := db.Prepare("INSERT|t1|name=?,age=bogusconversion")
+ if err == nil {
+ t.Fatalf("expected error")
+ }
+ if err.String() != `fakedb: invalid conversion to int32 from "bogusconversion"` {
+ t.Errorf("unexpected error: %v", err)
+ }
+}
+
+func TestDb(t *testing.T) {
+ db := newTestDB(t, "foo")
+ exec(t, db, "CREATE|t1|name=string,age=int32,dead=bool")
+ stmt, err := db.Prepare("INSERT|t1|name=?,age=?")
+ if err != nil {
+ t.Errorf("Stmt, err = %v, %v", stmt, err)
+ }
+
+ type execTest struct {
+ args []interface{}
+ wantErr string
+ }
+ execTests := []execTest{
+ // Okay:
+ {[]interface{}{"Brad", 31}, ""},
+ {[]interface{}{"Brad", int64(31)}, ""},
+ {[]interface{}{"Bob", "32"}, ""},
+ {[]interface{}{7, 9}, ""},
+
+ // Invalid conversions:
+ {[]interface{}{"Brad", int64(0xFFFFFFFF)}, "db: converting Exec argument #1's type: sql/driver: value 4294967295 overflows int32"},
+ {[]interface{}{"Brad", "strconv fail"}, "db: converting Exec argument #1's type: sql/driver: value \"strconv fail\" can't be converted to int32"},
+
+ // Wrong number of args:
+ {[]interface{}{}, "db: expected 2 arguments, got 0"},
+ {[]interface{}{1, 2, 3}, "db: expected 2 arguments, got 3"},
+ }
+ for n, et := range execTests {
+ _, err := stmt.Exec(et.args...)
+ errStr := ""
+ if err != nil {
+ errStr = err.String()
+ }
+ if errStr != et.wantErr {
+ t.Errorf("stmt.Execute #%d: for %v, got error %q, want error %q",
+ n, et.args, errStr, et.wantErr)
+ }
+ }
+}
diff --git a/libgo/go/exp/ssh/channel.go b/libgo/go/exp/ssh/channel.go
new file mode 100644
index 00000000000..922584f6317
--- /dev/null
+++ b/libgo/go/exp/ssh/channel.go
@@ -0,0 +1,317 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "os"
+ "sync"
+)
+
+// A Channel is an ordered, reliable, duplex stream that is multiplexed over an
+// SSH connection.
+type Channel interface {
+ // Accept accepts the channel creation request.
+ Accept() os.Error
+ // Reject rejects the channel creation request. After calling this, no
+ // other methods on the Channel may be called. If they are then the
+ // peer is likely to signal a protocol error and drop the connection.
+ Reject(reason RejectionReason, message string) os.Error
+
+ // Read may return a ChannelRequest as an os.Error.
+ Read(data []byte) (int, os.Error)
+ Write(data []byte) (int, os.Error)
+ Close() os.Error
+
+ // AckRequest either sends an ack or nack to the channel request.
+ AckRequest(ok bool) os.Error
+
+ // ChannelType returns the type of the channel, as supplied by the
+ // client.
+ ChannelType() string
+ // ExtraData returns the arbitary payload for this channel, as supplied
+ // by the client. This data is specific to the channel type.
+ ExtraData() []byte
+}
+
+// ChannelRequest represents a request sent on a channel, outside of the normal
+// stream of bytes. It may result from calling Read on a Channel.
+type ChannelRequest struct {
+ Request string
+ WantReply bool
+ Payload []byte
+}
+
+func (c ChannelRequest) String() string {
+ return "channel request received"
+}
+
+// RejectionReason is an enumeration used when rejecting channel creation
+// requests. See RFC 4254, section 5.1.
+type RejectionReason int
+
+const (
+ Prohibited RejectionReason = iota + 1
+ ConnectionFailed
+ UnknownChannelType
+ ResourceShortage
+)
+
+type channel struct {
+ // immutable once created
+ chanType string
+ extraData []byte
+
+ theyClosed bool
+ theySentEOF bool
+ weClosed bool
+ dead bool
+
+ serverConn *ServerConnection
+ myId, theirId uint32
+ myWindow, theirWindow uint32
+ maxPacketSize uint32
+ err os.Error
+
+ pendingRequests []ChannelRequest
+ pendingData []byte
+ head, length int
+
+ // This lock is inferior to serverConn.lock
+ lock sync.Mutex
+ cond *sync.Cond
+}
+
+func (c *channel) Accept() os.Error {
+ c.serverConn.lock.Lock()
+ defer c.serverConn.lock.Unlock()
+
+ if c.serverConn.err != nil {
+ return c.serverConn.err
+ }
+
+ confirm := channelOpenConfirmMsg{
+ PeersId: c.theirId,
+ MyId: c.myId,
+ MyWindow: c.myWindow,
+ MaxPacketSize: c.maxPacketSize,
+ }
+ return c.serverConn.writePacket(marshal(msgChannelOpenConfirm, confirm))
+}
+
+func (c *channel) Reject(reason RejectionReason, message string) os.Error {
+ c.serverConn.lock.Lock()
+ defer c.serverConn.lock.Unlock()
+
+ if c.serverConn.err != nil {
+ return c.serverConn.err
+ }
+
+ reject := channelOpenFailureMsg{
+ PeersId: c.theirId,
+ Reason: uint32(reason),
+ Message: message,
+ Language: "en",
+ }
+ return c.serverConn.writePacket(marshal(msgChannelOpenFailure, reject))
+}
+
+func (c *channel) handlePacket(packet interface{}) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ switch packet := packet.(type) {
+ case *channelRequestMsg:
+ req := ChannelRequest{
+ Request: packet.Request,
+ WantReply: packet.WantReply,
+ Payload: packet.RequestSpecificData,
+ }
+
+ c.pendingRequests = append(c.pendingRequests, req)
+ c.cond.Signal()
+ case *channelCloseMsg:
+ c.theyClosed = true
+ c.cond.Signal()
+ case *channelEOFMsg:
+ c.theySentEOF = true
+ c.cond.Signal()
+ default:
+ panic("unknown packet type")
+ }
+}
+
+func (c *channel) handleData(data []byte) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ // The other side should never send us more than our window.
+ if len(data)+c.length > len(c.pendingData) {
+ // TODO(agl): we should tear down the channel with a protocol
+ // error.
+ return
+ }
+
+ c.myWindow -= uint32(len(data))
+ for i := 0; i < 2; i++ {
+ tail := c.head + c.length
+ if tail > len(c.pendingData) {
+ tail -= len(c.pendingData)
+ }
+ n := copy(c.pendingData[tail:], data)
+ data = data[n:]
+ c.length += n
+ }
+
+ c.cond.Signal()
+}
+
+func (c *channel) Read(data []byte) (n int, err os.Error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if c.err != nil {
+ return 0, c.err
+ }
+
+ if c.myWindow <= uint32(len(c.pendingData))/2 {
+ packet := marshal(msgChannelWindowAdjust, windowAdjustMsg{
+ PeersId: c.theirId,
+ AdditionalBytes: uint32(len(c.pendingData)) - c.myWindow,
+ })
+ if err := c.serverConn.writePacket(packet); err != nil {
+ return 0, err
+ }
+ }
+
+ for {
+ if c.theySentEOF || c.theyClosed || c.dead {
+ return 0, os.EOF
+ }
+
+ if len(c.pendingRequests) > 0 {
+ req := c.pendingRequests[0]
+ if len(c.pendingRequests) == 1 {
+ c.pendingRequests = nil
+ } else {
+ oldPendingRequests := c.pendingRequests
+ c.pendingRequests = make([]ChannelRequest, len(oldPendingRequests)-1)
+ copy(c.pendingRequests, oldPendingRequests[1:])
+ }
+
+ return 0, req
+ }
+
+ if c.length > 0 {
+ tail := c.head + c.length
+ if tail > len(c.pendingData) {
+ tail -= len(c.pendingData)
+ }
+ n = copy(data, c.pendingData[c.head:tail])
+ c.head += n
+ c.length -= n
+ if c.head == len(c.pendingData) {
+ c.head = 0
+ }
+ return
+ }
+
+ c.cond.Wait()
+ }
+
+ panic("unreachable")
+}
+
+func (c *channel) Write(data []byte) (n int, err os.Error) {
+ for len(data) > 0 {
+ c.lock.Lock()
+ if c.dead || c.weClosed {
+ return 0, os.EOF
+ }
+
+ if c.theirWindow == 0 {
+ c.cond.Wait()
+ continue
+ }
+ c.lock.Unlock()
+
+ todo := data
+ if uint32(len(todo)) > c.theirWindow {
+ todo = todo[:c.theirWindow]
+ }
+
+ packet := make([]byte, 1+4+4+len(todo))
+ packet[0] = msgChannelData
+ packet[1] = byte(c.theirId) >> 24
+ packet[2] = byte(c.theirId) >> 16
+ packet[3] = byte(c.theirId) >> 8
+ packet[4] = byte(c.theirId)
+ packet[5] = byte(len(todo)) >> 24
+ packet[6] = byte(len(todo)) >> 16
+ packet[7] = byte(len(todo)) >> 8
+ packet[8] = byte(len(todo))
+ copy(packet[9:], todo)
+
+ c.serverConn.lock.Lock()
+ if err = c.serverConn.writePacket(packet); err != nil {
+ c.serverConn.lock.Unlock()
+ return
+ }
+ c.serverConn.lock.Unlock()
+
+ n += len(todo)
+ data = data[len(todo):]
+ }
+
+ return
+}
+
+func (c *channel) Close() os.Error {
+ c.serverConn.lock.Lock()
+ defer c.serverConn.lock.Unlock()
+
+ if c.serverConn.err != nil {
+ return c.serverConn.err
+ }
+
+ if c.weClosed {
+ return os.NewError("ssh: channel already closed")
+ }
+ c.weClosed = true
+
+ closeMsg := channelCloseMsg{
+ PeersId: c.theirId,
+ }
+ return c.serverConn.writePacket(marshal(msgChannelClose, closeMsg))
+}
+
+func (c *channel) AckRequest(ok bool) os.Error {
+ c.serverConn.lock.Lock()
+ defer c.serverConn.lock.Unlock()
+
+ if c.serverConn.err != nil {
+ return c.serverConn.err
+ }
+
+ if ok {
+ ack := channelRequestSuccessMsg{
+ PeersId: c.theirId,
+ }
+ return c.serverConn.writePacket(marshal(msgChannelSuccess, ack))
+ } else {
+ ack := channelRequestFailureMsg{
+ PeersId: c.theirId,
+ }
+ return c.serverConn.writePacket(marshal(msgChannelFailure, ack))
+ }
+ panic("unreachable")
+}
+
+func (c *channel) ChannelType() string {
+ return c.chanType
+}
+
+func (c *channel) ExtraData() []byte {
+ return c.extraData
+}
diff --git a/libgo/go/exp/ssh/common.go b/libgo/go/exp/ssh/common.go
new file mode 100644
index 00000000000..739bd2f9c5f
--- /dev/null
+++ b/libgo/go/exp/ssh/common.go
@@ -0,0 +1,129 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "big"
+ "strconv"
+ "sync"
+)
+
+// These are string constants in the SSH protocol.
+const (
+ kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
+ hostAlgoRSA = "ssh-rsa"
+ cipherAES128CTR = "aes128-ctr"
+ macSHA196 = "hmac-sha1-96"
+ compressionNone = "none"
+ serviceUserAuth = "ssh-userauth"
+ serviceSSH = "ssh-connection"
+)
+
+var supportedKexAlgos = []string{kexAlgoDH14SHA1}
+var supportedHostKeyAlgos = []string{hostAlgoRSA}
+var supportedCiphers = []string{cipherAES128CTR}
+var supportedMACs = []string{macSHA196}
+var supportedCompressions = []string{compressionNone}
+
+// dhGroup is a multiplicative group suitable for implementing Diffie-Hellman key agreement.
+type dhGroup struct {
+ g, p *big.Int
+}
+
+// dhGroup14 is the group called diffie-hellman-group14-sha1 in RFC 4253 and
+// Oakley Group 14 in RFC 3526.
+var dhGroup14 *dhGroup
+
+var dhGroup14Once sync.Once
+
+func initDHGroup14() {
+ p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
+
+ dhGroup14 = &dhGroup{
+ g: new(big.Int).SetInt64(2),
+ p: p,
+ }
+}
+
+// UnexpectedMessageError results when the SSH message that we received didn't
+// match what we wanted.
+type UnexpectedMessageError struct {
+ expected, got uint8
+}
+
+func (u UnexpectedMessageError) String() string {
+ return "ssh: unexpected message type " + strconv.Itoa(int(u.got)) + " (expected " + strconv.Itoa(int(u.expected)) + ")"
+}
+
+// ParseError results from a malformed SSH message.
+type ParseError struct {
+ msgType uint8
+}
+
+func (p ParseError) String() string {
+ return "ssh: parse error in message type " + strconv.Itoa(int(p.msgType))
+}
+
+type handshakeMagics struct {
+ clientVersion, serverVersion []byte
+ clientKexInit, serverKexInit []byte
+}
+
+func findCommonAlgorithm(clientAlgos []string, serverAlgos []string) (commonAlgo string, ok bool) {
+ for _, clientAlgo := range clientAlgos {
+ for _, serverAlgo := range serverAlgos {
+ if clientAlgo == serverAlgo {
+ return clientAlgo, true
+ }
+ }
+ }
+
+ return
+}
+
+func findAgreedAlgorithms(transport *transport, clientKexInit, serverKexInit *kexInitMsg) (kexAlgo, hostKeyAlgo string, ok bool) {
+ kexAlgo, ok = findCommonAlgorithm(clientKexInit.KexAlgos, serverKexInit.KexAlgos)
+ if !ok {
+ return
+ }
+
+ hostKeyAlgo, ok = findCommonAlgorithm(clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos)
+ if !ok {
+ return
+ }
+
+ transport.writer.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer)
+ if !ok {
+ return
+ }
+
+ transport.reader.cipherAlgo, ok = findCommonAlgorithm(clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient)
+ if !ok {
+ return
+ }
+
+ transport.writer.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsClientServer, serverKexInit.MACsClientServer)
+ if !ok {
+ return
+ }
+
+ transport.reader.macAlgo, ok = findCommonAlgorithm(clientKexInit.MACsServerClient, serverKexInit.MACsServerClient)
+ if !ok {
+ return
+ }
+
+ transport.writer.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer)
+ if !ok {
+ return
+ }
+
+ transport.reader.compressionAlgo, ok = findCommonAlgorithm(clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient)
+ if !ok {
+ return
+ }
+
+ ok = true
+ return
+}
diff --git a/libgo/go/exp/ssh/doc.go b/libgo/go/exp/ssh/doc.go
new file mode 100644
index 00000000000..54a7ba9fdae
--- /dev/null
+++ b/libgo/go/exp/ssh/doc.go
@@ -0,0 +1,79 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package ssh implements an SSH server.
+
+SSH is a transport security protocol, an authentication protocol and a
+family of application protocols. The most typical application level
+protocol is a remote shell and this is specifically implemented. However,
+the multiplexed nature of SSH is exposed to users that wish to support
+others.
+
+An SSH server is represented by a Server, which manages a number of
+ServerConnections and handles authentication.
+
+ var s Server
+ s.PubKeyCallback = pubKeyAuth
+ s.PasswordCallback = passwordAuth
+
+ pemBytes, err := ioutil.ReadFile("id_rsa")
+ if err != nil {
+ panic("Failed to load private key")
+ }
+ err = s.SetRSAPrivateKey(pemBytes)
+ if err != nil {
+ panic("Failed to parse private key")
+ }
+
+Once a Server has been set up, connections can be attached.
+
+ var sConn ServerConnection
+ sConn.Server = &s
+ err = sConn.Handshake(conn)
+ if err != nil {
+ panic("failed to handshake")
+ }
+
+An SSH connection multiplexes several channels, which must be accepted themselves:
+
+
+ for {
+ channel, err := sConn.Accept()
+ if err != nil {
+ panic("error from Accept")
+ }
+
+ ...
+ }
+
+Accept reads from the connection, demultiplexes packets to their corresponding
+channels and returns when a new channel request is seen. Some goroutine must
+always be calling Accept; otherwise no messages will be forwarded to the
+channels.
+
+Channels have a type, depending on the application level protocol intended. In
+the case of a shell, the type is "session" and ServerShell may be used to
+present a simple terminal interface.
+
+ if channel.ChannelType() != "session" {
+ c.Reject(UnknownChannelType, "unknown channel type")
+ return
+ }
+ channel.Accept()
+
+ shell := NewServerShell(channel, "> ")
+ go func() {
+ defer channel.Close()
+ for {
+ line, err := shell.ReadLine()
+ if err != nil {
+ break
+ }
+ println(line)
+ }
+ return
+ }()
+*/
+package ssh
diff --git a/libgo/go/exp/ssh/messages.go b/libgo/go/exp/ssh/messages.go
new file mode 100644
index 00000000000..1d0bc577426
--- /dev/null
+++ b/libgo/go/exp/ssh/messages.go
@@ -0,0 +1,636 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "big"
+ "bytes"
+ "io"
+ "os"
+ "reflect"
+)
+
+// These are SSH message type numbers. They are scattered around several
+// documents but many were taken from
+// http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1
+const (
+ msgDisconnect = 1
+ msgIgnore = 2
+ msgUnimplemented = 3
+ msgDebug = 4
+ msgServiceRequest = 5
+ msgServiceAccept = 6
+
+ msgKexInit = 20
+ msgNewKeys = 21
+
+ msgKexDHInit = 30
+ msgKexDHReply = 31
+
+ msgUserAuthRequest = 50
+ msgUserAuthFailure = 51
+ msgUserAuthSuccess = 52
+ msgUserAuthBanner = 53
+ msgUserAuthPubKeyOk = 60
+
+ msgGlobalRequest = 80
+ msgRequestSuccess = 81
+ msgRequestFailure = 82
+
+ msgChannelOpen = 90
+ msgChannelOpenConfirm = 91
+ msgChannelOpenFailure = 92
+ msgChannelWindowAdjust = 93
+ msgChannelData = 94
+ msgChannelExtendedData = 95
+ msgChannelEOF = 96
+ msgChannelClose = 97
+ msgChannelRequest = 98
+ msgChannelSuccess = 99
+ msgChannelFailure = 100
+)
+
+// SSH messages:
+//
+// These structures mirror the wire format of the corresponding SSH messages.
+// They are marshaled using reflection with the marshal and unmarshal functions
+// in this file. The only wrinkle is that a final member of type []byte with a
+// ssh tag of "rest" receives the remainder of a packet when unmarshaling.
+
+// See RFC 4253, section 11.1.
+type disconnectMsg struct {
+ Reason uint32
+ Message string
+ Language string
+}
+
+// See RFC 4253, section 7.1.
+type kexInitMsg struct {
+ Cookie [16]byte
+ KexAlgos []string
+ ServerHostKeyAlgos []string
+ CiphersClientServer []string
+ CiphersServerClient []string
+ MACsClientServer []string
+ MACsServerClient []string
+ CompressionClientServer []string
+ CompressionServerClient []string
+ LanguagesClientServer []string
+ LanguagesServerClient []string
+ FirstKexFollows bool
+ Reserved uint32
+}
+
+// See RFC 4253, section 8.
+type kexDHInitMsg struct {
+ X *big.Int
+}
+
+type kexDHReplyMsg struct {
+ HostKey []byte
+ Y *big.Int
+ Signature []byte
+}
+
+// See RFC 4253, section 10.
+type serviceRequestMsg struct {
+ Service string
+}
+
+// See RFC 4253, section 10.
+type serviceAcceptMsg struct {
+ Service string
+}
+
+// See RFC 4252, section 5.
+type userAuthRequestMsg struct {
+ User string
+ Service string
+ Method string
+ Payload []byte `ssh:"rest"`
+}
+
+// See RFC 4252, section 5.1
+type userAuthFailureMsg struct {
+ Methods []string
+ PartialSuccess bool
+}
+
+// See RFC 4254, section 5.1.
+type channelOpenMsg struct {
+ ChanType string
+ PeersId uint32
+ PeersWindow uint32
+ MaxPacketSize uint32
+ TypeSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+type channelOpenConfirmMsg struct {
+ PeersId uint32
+ MyId uint32
+ MyWindow uint32
+ MaxPacketSize uint32
+ TypeSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.1.
+type channelOpenFailureMsg struct {
+ PeersId uint32
+ Reason uint32
+ Message string
+ Language string
+}
+
+// See RFC 4254, section 5.2.
+type channelData struct {
+ PeersId uint32
+ Payload []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.2.
+type channelExtendedData struct {
+ PeersId uint32
+ Datatype uint32
+ Data string
+}
+
+type channelRequestMsg struct {
+ PeersId uint32
+ Request string
+ WantReply bool
+ RequestSpecificData []byte `ssh:"rest"`
+}
+
+// See RFC 4254, section 5.4.
+type channelRequestSuccessMsg struct {
+ PeersId uint32
+}
+
+// See RFC 4254, section 5.4.
+type channelRequestFailureMsg struct {
+ PeersId uint32
+}
+
+// See RFC 4254, section 5.3
+type channelCloseMsg struct {
+ PeersId uint32
+}
+
+// See RFC 4254, section 5.3
+type channelEOFMsg struct {
+ PeersId uint32
+}
+
+// See RFC 4254, section 4
+type globalRequestMsg struct {
+ Type string
+ WantReply bool
+}
+
+// See RFC 4254, section 5.2
+type windowAdjustMsg struct {
+ PeersId uint32
+ AdditionalBytes uint32
+}
+
+// See RFC 4252, section 7
+type userAuthPubKeyOkMsg struct {
+ Algo string
+ PubKey string
+}
+
+// unmarshal parses the SSH wire data in packet into out using reflection.
+// expectedType is the expected SSH message type. It either returns nil on
+// success, or a ParseError or UnexpectedMessageError on error.
+func unmarshal(out interface{}, packet []byte, expectedType uint8) os.Error {
+ if len(packet) == 0 {
+ return ParseError{expectedType}
+ }
+ if packet[0] != expectedType {
+ return UnexpectedMessageError{expectedType, packet[0]}
+ }
+ packet = packet[1:]
+
+ v := reflect.ValueOf(out).Elem()
+ structType := v.Type()
+ var ok bool
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Field(i)
+ t := field.Type()
+ switch t.Kind() {
+ case reflect.Bool:
+ if len(packet) < 1 {
+ return ParseError{expectedType}
+ }
+ field.SetBool(packet[0] != 0)
+ packet = packet[1:]
+ case reflect.Array:
+ if t.Elem().Kind() != reflect.Uint8 {
+ panic("array of non-uint8")
+ }
+ if len(packet) < t.Len() {
+ return ParseError{expectedType}
+ }
+ for j := 0; j < t.Len(); j++ {
+ field.Index(j).Set(reflect.ValueOf(packet[j]))
+ }
+ packet = packet[t.Len():]
+ case reflect.Uint32:
+ var u32 uint32
+ if u32, packet, ok = parseUint32(packet); !ok {
+ return ParseError{expectedType}
+ }
+ field.SetUint(uint64(u32))
+ case reflect.String:
+ var s []byte
+ if s, packet, ok = parseString(packet); !ok {
+ return ParseError{expectedType}
+ }
+ field.SetString(string(s))
+ case reflect.Slice:
+ switch t.Elem().Kind() {
+ case reflect.Uint8:
+ if structType.Field(i).Tag.Get("ssh") == "rest" {
+ field.Set(reflect.ValueOf(packet))
+ packet = nil
+ } else {
+ var s []byte
+ if s, packet, ok = parseString(packet); !ok {
+ return ParseError{expectedType}
+ }
+ field.Set(reflect.ValueOf(s))
+ }
+ case reflect.String:
+ var nl []string
+ if nl, packet, ok = parseNameList(packet); !ok {
+ return ParseError{expectedType}
+ }
+ field.Set(reflect.ValueOf(nl))
+ default:
+ panic("slice of unknown type")
+ }
+ case reflect.Ptr:
+ if t == bigIntType {
+ var n *big.Int
+ if n, packet, ok = parseInt(packet); !ok {
+ return ParseError{expectedType}
+ }
+ field.Set(reflect.ValueOf(n))
+ } else {
+ panic("pointer to unknown type")
+ }
+ default:
+ panic("unknown type")
+ }
+ }
+
+ if len(packet) != 0 {
+ return ParseError{expectedType}
+ }
+
+ return nil
+}
+
+// marshal serializes the message in msg, using the given message type.
+func marshal(msgType uint8, msg interface{}) []byte {
+ var out []byte
+ out = append(out, msgType)
+
+ v := reflect.ValueOf(msg)
+ structType := v.Type()
+ for i := 0; i < v.NumField(); i++ {
+ field := v.Field(i)
+ t := field.Type()
+ switch t.Kind() {
+ case reflect.Bool:
+ var v uint8
+ if field.Bool() {
+ v = 1
+ }
+ out = append(out, v)
+ case reflect.Array:
+ if t.Elem().Kind() != reflect.Uint8 {
+ panic("array of non-uint8")
+ }
+ for j := 0; j < t.Len(); j++ {
+ out = append(out, byte(field.Index(j).Uint()))
+ }
+ case reflect.Uint32:
+ u32 := uint32(field.Uint())
+ out = append(out, byte(u32>>24))
+ out = append(out, byte(u32>>16))
+ out = append(out, byte(u32>>8))
+ out = append(out, byte(u32))
+ case reflect.String:
+ s := field.String()
+ out = append(out, byte(len(s)>>24))
+ out = append(out, byte(len(s)>>16))
+ out = append(out, byte(len(s)>>8))
+ out = append(out, byte(len(s)))
+ out = append(out, s...)
+ case reflect.Slice:
+ switch t.Elem().Kind() {
+ case reflect.Uint8:
+ length := field.Len()
+ if structType.Field(i).Tag.Get("ssh") != "rest" {
+ out = append(out, byte(length>>24))
+ out = append(out, byte(length>>16))
+ out = append(out, byte(length>>8))
+ out = append(out, byte(length))
+ }
+ for j := 0; j < length; j++ {
+ out = append(out, byte(field.Index(j).Uint()))
+ }
+ case reflect.String:
+ var length int
+ for j := 0; j < field.Len(); j++ {
+ if j != 0 {
+ length++ /* comma */
+ }
+ length += len(field.Index(j).String())
+ }
+
+ out = append(out, byte(length>>24))
+ out = append(out, byte(length>>16))
+ out = append(out, byte(length>>8))
+ out = append(out, byte(length))
+ for j := 0; j < field.Len(); j++ {
+ if j != 0 {
+ out = append(out, ',')
+ }
+ out = append(out, field.Index(j).String()...)
+ }
+ default:
+ panic("slice of unknown type")
+ }
+ case reflect.Ptr:
+ if t == bigIntType {
+ var n *big.Int
+ nValue := reflect.ValueOf(&n)
+ nValue.Elem().Set(field)
+ needed := intLength(n)
+ oldLength := len(out)
+
+ if cap(out)-len(out) < needed {
+ newOut := make([]byte, len(out), 2*(len(out)+needed))
+ copy(newOut, out)
+ out = newOut
+ }
+ out = out[:oldLength+needed]
+ marshalInt(out[oldLength:], n)
+ } else {
+ panic("pointer to unknown type")
+ }
+ }
+ }
+
+ return out
+}
+
+var bigOne = big.NewInt(1)
+
+func parseString(in []byte) (out, rest []byte, ok bool) {
+ if len(in) < 4 {
+ return
+ }
+ length := uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
+ if uint32(len(in)) < 4+length {
+ return
+ }
+ out = in[4 : 4+length]
+ rest = in[4+length:]
+ ok = true
+ return
+}
+
+var comma = []byte{','}
+
+func parseNameList(in []byte) (out []string, rest []byte, ok bool) {
+ contents, rest, ok := parseString(in)
+ if !ok {
+ return
+ }
+ if len(contents) == 0 {
+ return
+ }
+ parts := bytes.Split(contents, comma)
+ out = make([]string, len(parts))
+ for i, part := range parts {
+ out[i] = string(part)
+ }
+ return
+}
+
+func parseInt(in []byte) (out *big.Int, rest []byte, ok bool) {
+ contents, rest, ok := parseString(in)
+ if !ok {
+ return
+ }
+ out = new(big.Int)
+
+ if len(contents) > 0 && contents[0]&0x80 == 0x80 {
+ // This is a negative number
+ notBytes := make([]byte, len(contents))
+ for i := range notBytes {
+ notBytes[i] = ^contents[i]
+ }
+ out.SetBytes(notBytes)
+ out.Add(out, bigOne)
+ out.Neg(out)
+ } else {
+ // Positive number
+ out.SetBytes(contents)
+ }
+ ok = true
+ return
+}
+
+func parseUint32(in []byte) (out uint32, rest []byte, ok bool) {
+ if len(in) < 4 {
+ return
+ }
+ out = uint32(in[0])<<24 | uint32(in[1])<<16 | uint32(in[2])<<8 | uint32(in[3])
+ rest = in[4:]
+ ok = true
+ return
+}
+
+const maxPacketSize = 36000
+
+func nameListLength(namelist []string) int {
+ length := 4 /* uint32 length prefix */
+ for i, name := range namelist {
+ if i != 0 {
+ length++ /* comma */
+ }
+ length += len(name)
+ }
+ return length
+}
+
+func intLength(n *big.Int) int {
+ length := 4 /* length bytes */
+ if n.Sign() < 0 {
+ nMinus1 := new(big.Int).Neg(n)
+ nMinus1.Sub(nMinus1, bigOne)
+ bitLen := nMinus1.BitLen()
+ if bitLen%8 == 0 {
+ // The number will need 0xff padding
+ length++
+ }
+ length += (bitLen + 7) / 8
+ } else if n.Sign() == 0 {
+ // A zero is the zero length string
+ } else {
+ bitLen := n.BitLen()
+ if bitLen%8 == 0 {
+ // The number will need 0x00 padding
+ length++
+ }
+ length += (bitLen + 7) / 8
+ }
+
+ return length
+}
+
+func marshalInt(to []byte, n *big.Int) []byte {
+ lengthBytes := to
+ to = to[4:]
+ length := 0
+
+ if n.Sign() < 0 {
+ // A negative number has to be converted to two's-complement
+ // form. So we'll subtract 1 and invert. If the
+ // most-significant-bit isn't set then we'll need to pad the
+ // beginning with 0xff in order to keep the number negative.
+ nMinus1 := new(big.Int).Neg(n)
+ nMinus1.Sub(nMinus1, bigOne)
+ bytes := nMinus1.Bytes()
+ for i := range bytes {
+ bytes[i] ^= 0xff
+ }
+ if len(bytes) == 0 || bytes[0]&0x80 == 0 {
+ to[0] = 0xff
+ to = to[1:]
+ length++
+ }
+ nBytes := copy(to, bytes)
+ to = to[nBytes:]
+ length += nBytes
+ } else if n.Sign() == 0 {
+ // A zero is the zero length string
+ } else {
+ bytes := n.Bytes()
+ if len(bytes) > 0 && bytes[0]&0x80 != 0 {
+ // We'll have to pad this with a 0x00 in order to
+ // stop it looking like a negative number.
+ to[0] = 0
+ to = to[1:]
+ length++
+ }
+ nBytes := copy(to, bytes)
+ to = to[nBytes:]
+ length += nBytes
+ }
+
+ lengthBytes[0] = byte(length >> 24)
+ lengthBytes[1] = byte(length >> 16)
+ lengthBytes[2] = byte(length >> 8)
+ lengthBytes[3] = byte(length)
+ return to
+}
+
+func writeInt(w io.Writer, n *big.Int) {
+ length := intLength(n)
+ buf := make([]byte, length)
+ marshalInt(buf, n)
+ w.Write(buf)
+}
+
+func writeString(w io.Writer, s []byte) {
+ var lengthBytes [4]byte
+ lengthBytes[0] = byte(len(s) >> 24)
+ lengthBytes[1] = byte(len(s) >> 16)
+ lengthBytes[2] = byte(len(s) >> 8)
+ lengthBytes[3] = byte(len(s))
+ w.Write(lengthBytes[:])
+ w.Write(s)
+}
+
+func stringLength(s []byte) int {
+ return 4 + len(s)
+}
+
+func marshalString(to []byte, s []byte) []byte {
+ to[0] = byte(len(s) >> 24)
+ to[1] = byte(len(s) >> 16)
+ to[2] = byte(len(s) >> 8)
+ to[3] = byte(len(s))
+ to = to[4:]
+ copy(to, s)
+ return to[len(s):]
+}
+
+var bigIntType = reflect.TypeOf((*big.Int)(nil))
+
+// Decode a packet into it's corresponding message.
+func decode(packet []byte) interface{} {
+ var msg interface{}
+ switch packet[0] {
+ case msgDisconnect:
+ msg = new(disconnectMsg)
+ case msgServiceRequest:
+ msg = new(serviceRequestMsg)
+ case msgServiceAccept:
+ msg = new(serviceAcceptMsg)
+ case msgKexInit:
+ msg = new(kexInitMsg)
+ case msgKexDHInit:
+ msg = new(kexDHInitMsg)
+ case msgKexDHReply:
+ msg = new(kexDHReplyMsg)
+ case msgUserAuthRequest:
+ msg = new(userAuthRequestMsg)
+ case msgUserAuthFailure:
+ msg = new(userAuthFailureMsg)
+ case msgUserAuthPubKeyOk:
+ msg = new(userAuthPubKeyOkMsg)
+ case msgGlobalRequest:
+ msg = new(globalRequestMsg)
+ case msgRequestSuccess:
+ msg = new(channelRequestSuccessMsg)
+ case msgRequestFailure:
+ msg = new(channelRequestFailureMsg)
+ case msgChannelOpen:
+ msg = new(channelOpenMsg)
+ case msgChannelOpenConfirm:
+ msg = new(channelOpenConfirmMsg)
+ case msgChannelOpenFailure:
+ msg = new(channelOpenFailureMsg)
+ case msgChannelWindowAdjust:
+ msg = new(windowAdjustMsg)
+ case msgChannelData:
+ msg = new(channelData)
+ case msgChannelExtendedData:
+ msg = new(channelExtendedData)
+ case msgChannelEOF:
+ msg = new(channelEOFMsg)
+ case msgChannelClose:
+ msg = new(channelCloseMsg)
+ case msgChannelRequest:
+ msg = new(channelRequestMsg)
+ case msgChannelSuccess:
+ msg = new(channelRequestSuccessMsg)
+ case msgChannelFailure:
+ msg = new(channelRequestFailureMsg)
+ default:
+ return UnexpectedMessageError{0, packet[0]}
+ }
+ if err := unmarshal(msg, packet, packet[0]); err != nil {
+ return err
+ }
+ return msg
+}
diff --git a/libgo/go/exp/ssh/messages_test.go b/libgo/go/exp/ssh/messages_test.go
new file mode 100644
index 00000000000..629f3d3b145
--- /dev/null
+++ b/libgo/go/exp/ssh/messages_test.go
@@ -0,0 +1,125 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "big"
+ "rand"
+ "reflect"
+ "testing"
+ "testing/quick"
+)
+
+var intLengthTests = []struct {
+ val, length int
+}{
+ {0, 4 + 0},
+ {1, 4 + 1},
+ {127, 4 + 1},
+ {128, 4 + 2},
+ {-1, 4 + 1},
+}
+
+func TestIntLength(t *testing.T) {
+ for _, test := range intLengthTests {
+ v := new(big.Int).SetInt64(int64(test.val))
+ length := intLength(v)
+ if length != test.length {
+ t.Errorf("For %d, got length %d but expected %d", test.val, length, test.length)
+ }
+ }
+}
+
+var messageTypes = []interface{}{
+ &kexInitMsg{},
+ &kexDHInitMsg{},
+ &serviceRequestMsg{},
+ &serviceAcceptMsg{},
+ &userAuthRequestMsg{},
+ &channelOpenMsg{},
+ &channelOpenConfirmMsg{},
+ &channelRequestMsg{},
+ &channelRequestSuccessMsg{},
+}
+
+func TestMarshalUnmarshal(t *testing.T) {
+ rand := rand.New(rand.NewSource(0))
+ for i, iface := range messageTypes {
+ ty := reflect.ValueOf(iface).Type()
+
+ n := 100
+ if testing.Short() {
+ n = 5
+ }
+ for j := 0; j < n; j++ {
+ v, ok := quick.Value(ty, rand)
+ if !ok {
+ t.Errorf("#%d: failed to create value", i)
+ break
+ }
+
+ m1 := v.Elem().Interface()
+ m2 := iface
+
+ marshaled := marshal(msgIgnore, m1)
+ if err := unmarshal(m2, marshaled, msgIgnore); err != nil {
+ t.Errorf("#%d failed to unmarshal %#v: %s", i, m1, err)
+ break
+ }
+
+ if !reflect.DeepEqual(v.Interface(), m2) {
+ t.Errorf("#%d\ngot: %#v\nwant:%#v\n%x", i, m2, m1, marshaled)
+ break
+ }
+ }
+ }
+}
+
+func randomBytes(out []byte, rand *rand.Rand) {
+ for i := 0; i < len(out); i++ {
+ out[i] = byte(rand.Int31())
+ }
+}
+
+func randomNameList(rand *rand.Rand) []string {
+ ret := make([]string, rand.Int31()&15)
+ for i := range ret {
+ s := make([]byte, 1+(rand.Int31()&15))
+ for j := range s {
+ s[j] = 'a' + uint8(rand.Int31()&15)
+ }
+ ret[i] = string(s)
+ }
+ return ret
+}
+
+func randomInt(rand *rand.Rand) *big.Int {
+ return new(big.Int).SetInt64(int64(int32(rand.Uint32())))
+}
+
+func (*kexInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+ ki := &kexInitMsg{}
+ randomBytes(ki.Cookie[:], rand)
+ ki.KexAlgos = randomNameList(rand)
+ ki.ServerHostKeyAlgos = randomNameList(rand)
+ ki.CiphersClientServer = randomNameList(rand)
+ ki.CiphersServerClient = randomNameList(rand)
+ ki.MACsClientServer = randomNameList(rand)
+ ki.MACsServerClient = randomNameList(rand)
+ ki.CompressionClientServer = randomNameList(rand)
+ ki.CompressionServerClient = randomNameList(rand)
+ ki.LanguagesClientServer = randomNameList(rand)
+ ki.LanguagesServerClient = randomNameList(rand)
+ if rand.Int31()&1 == 1 {
+ ki.FirstKexFollows = true
+ }
+ return reflect.ValueOf(ki)
+}
+
+func (*kexDHInitMsg) Generate(rand *rand.Rand, size int) reflect.Value {
+ dhi := &kexDHInitMsg{}
+ dhi.X = randomInt(rand)
+ return reflect.ValueOf(dhi)
+}
diff --git a/libgo/go/exp/ssh/server.go b/libgo/go/exp/ssh/server.go
new file mode 100644
index 00000000000..410cafc44c2
--- /dev/null
+++ b/libgo/go/exp/ssh/server.go
@@ -0,0 +1,645 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "big"
+ "bytes"
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+ _ "crypto/sha1"
+ "crypto/x509"
+ "encoding/pem"
+ "net"
+ "os"
+ "sync"
+)
+
+// Server represents an SSH server. A Server may have several ServerConnections.
+type Server struct {
+ rsa *rsa.PrivateKey
+ rsaSerialized []byte
+
+ // NoClientAuth is true if clients are allowed to connect without
+ // authenticating.
+ NoClientAuth bool
+
+ // PasswordCallback, if non-nil, is called when a user attempts to
+ // authenticate using a password. It may be called concurrently from
+ // several goroutines.
+ PasswordCallback func(user, password string) bool
+
+ // PubKeyCallback, if non-nil, is called when a client attempts public
+ // key authentication. It must return true iff the given public key is
+ // valid for the given user.
+ PubKeyCallback func(user, algo string, pubkey []byte) bool
+}
+
+// SetRSAPrivateKey sets the private key for a Server. A Server must have a
+// private key configured in order to accept connections. The private key must
+// be in the form of a PEM encoded, PKCS#1, RSA private key. The file "id_rsa"
+// typically contains such a key.
+func (s *Server) SetRSAPrivateKey(pemBytes []byte) os.Error {
+ block, _ := pem.Decode(pemBytes)
+ if block == nil {
+ return os.NewError("ssh: no key found")
+ }
+ var err os.Error
+ s.rsa, err = x509.ParsePKCS1PrivateKey(block.Bytes)
+ if err != nil {
+ return err
+ }
+
+ s.rsaSerialized = marshalRSA(s.rsa)
+ return nil
+}
+
+// marshalRSA serializes an RSA private key according to RFC 4256, section 6.6.
+func marshalRSA(priv *rsa.PrivateKey) []byte {
+ e := new(big.Int).SetInt64(int64(priv.E))
+ length := stringLength([]byte(hostAlgoRSA))
+ length += intLength(e)
+ length += intLength(priv.N)
+
+ ret := make([]byte, length)
+ r := marshalString(ret, []byte(hostAlgoRSA))
+ r = marshalInt(r, e)
+ r = marshalInt(r, priv.N)
+
+ return ret
+}
+
+// parseRSA parses an RSA key according to RFC 4256, section 6.6.
+func parseRSA(in []byte) (pubKey *rsa.PublicKey, ok bool) {
+ algo, in, ok := parseString(in)
+ if !ok || string(algo) != hostAlgoRSA {
+ return nil, false
+ }
+ bigE, in, ok := parseInt(in)
+ if !ok || bigE.BitLen() > 24 {
+ return nil, false
+ }
+ e := bigE.Int64()
+ if e < 3 || e&1 == 0 {
+ return nil, false
+ }
+ N, in, ok := parseInt(in)
+ if !ok || len(in) > 0 {
+ return nil, false
+ }
+ return &rsa.PublicKey{
+ N: N,
+ E: int(e),
+ }, true
+}
+
+func parseRSASig(in []byte) (sig []byte, ok bool) {
+ algo, in, ok := parseString(in)
+ if !ok || string(algo) != hostAlgoRSA {
+ return nil, false
+ }
+ sig, in, ok = parseString(in)
+ if len(in) > 0 {
+ ok = false
+ }
+ return
+}
+
+// cachedPubKey contains the results of querying whether a public key is
+// acceptable for a user. The cache only applies to a single ServerConnection.
+type cachedPubKey struct {
+ user, algo string
+ pubKey []byte
+ result bool
+}
+
+const maxCachedPubKeys = 16
+
+// ServerConnection represents an incomming connection to a Server.
+type ServerConnection struct {
+ Server *Server
+
+ *transport
+
+ channels map[uint32]*channel
+ nextChanId uint32
+
+ // lock protects err and also allows Channels to serialise their writes
+ // to out.
+ lock sync.RWMutex
+ err os.Error
+
+ // cachedPubKeys contains the cache results of tests for public keys.
+ // Since SSH clients will query whether a public key is acceptable
+ // before attempting to authenticate with it, we end up with duplicate
+ // queries for public key validity.
+ cachedPubKeys []cachedPubKey
+}
+
+// kexDH performs Diffie-Hellman key agreement on a ServerConnection. The
+// returned values are given the same names as in RFC 4253, section 8.
+func (s *ServerConnection) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handshakeMagics, hostKeyAlgo string) (H, K []byte, err os.Error) {
+ packet, err := s.readPacket()
+ if err != nil {
+ return
+ }
+ var kexDHInit kexDHInitMsg
+ if err = unmarshal(&kexDHInit, packet, msgKexDHInit); err != nil {
+ return
+ }
+
+ if kexDHInit.X.Sign() == 0 || kexDHInit.X.Cmp(group.p) >= 0 {
+ return nil, nil, os.NewError("client DH parameter out of bounds")
+ }
+
+ y, err := rand.Int(rand.Reader, group.p)
+ if err != nil {
+ return
+ }
+
+ Y := new(big.Int).Exp(group.g, y, group.p)
+ kInt := new(big.Int).Exp(kexDHInit.X, y, group.p)
+
+ var serializedHostKey []byte
+ switch hostKeyAlgo {
+ case hostAlgoRSA:
+ serializedHostKey = s.Server.rsaSerialized
+ default:
+ return nil, nil, os.NewError("internal error")
+ }
+
+ h := hashFunc.New()
+ writeString(h, magics.clientVersion)
+ writeString(h, magics.serverVersion)
+ writeString(h, magics.clientKexInit)
+ writeString(h, magics.serverKexInit)
+ writeString(h, serializedHostKey)
+ writeInt(h, kexDHInit.X)
+ writeInt(h, Y)
+ K = make([]byte, intLength(kInt))
+ marshalInt(K, kInt)
+ h.Write(K)
+
+ H = h.Sum()
+
+ h.Reset()
+ h.Write(H)
+ hh := h.Sum()
+
+ var sig []byte
+ switch hostKeyAlgo {
+ case hostAlgoRSA:
+ sig, err = rsa.SignPKCS1v15(rand.Reader, s.Server.rsa, hashFunc, hh)
+ if err != nil {
+ return
+ }
+ default:
+ return nil, nil, os.NewError("internal error")
+ }
+
+ serializedSig := serializeRSASignature(sig)
+
+ kexDHReply := kexDHReplyMsg{
+ HostKey: serializedHostKey,
+ Y: Y,
+ Signature: serializedSig,
+ }
+ packet = marshal(msgKexDHReply, kexDHReply)
+
+ err = s.writePacket(packet)
+ return
+}
+
+func serializeRSASignature(sig []byte) []byte {
+ length := stringLength([]byte(hostAlgoRSA))
+ length += stringLength(sig)
+
+ ret := make([]byte, length)
+ r := marshalString(ret, []byte(hostAlgoRSA))
+ r = marshalString(r, sig)
+
+ return ret
+}
+
+// serverVersion is the fixed identification string that Server will use.
+var serverVersion = []byte("SSH-2.0-Go\r\n")
+
+// buildDataSignedForAuth returns the data that is signed in order to prove
+// posession of a private key. See RFC 4252, section 7.
+func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte {
+ user := []byte(req.User)
+ service := []byte(req.Service)
+ method := []byte(req.Method)
+
+ length := stringLength(sessionId)
+ length += 1
+ length += stringLength(user)
+ length += stringLength(service)
+ length += stringLength(method)
+ length += 1
+ length += stringLength(algo)
+ length += stringLength(pubKey)
+
+ ret := make([]byte, length)
+ r := marshalString(ret, sessionId)
+ r[0] = msgUserAuthRequest
+ r = r[1:]
+ r = marshalString(r, user)
+ r = marshalString(r, service)
+ r = marshalString(r, method)
+ r[0] = 1
+ r = r[1:]
+ r = marshalString(r, algo)
+ r = marshalString(r, pubKey)
+ return ret
+}
+
+// Handshake performs an SSH transport and client authentication on the given ServerConnection.
+func (s *ServerConnection) Handshake(conn net.Conn) os.Error {
+ var magics handshakeMagics
+ s.transport = newTransport(conn, rand.Reader)
+
+ if _, err := conn.Write(serverVersion); err != nil {
+ return err
+ }
+ magics.serverVersion = serverVersion[:len(serverVersion)-2]
+
+ version, ok := readVersion(s.transport)
+ if !ok {
+ return os.NewError("failed to read version string from client")
+ }
+ magics.clientVersion = version
+
+ serverKexInit := kexInitMsg{
+ KexAlgos: supportedKexAlgos,
+ ServerHostKeyAlgos: supportedHostKeyAlgos,
+ CiphersClientServer: supportedCiphers,
+ CiphersServerClient: supportedCiphers,
+ MACsClientServer: supportedMACs,
+ MACsServerClient: supportedMACs,
+ CompressionClientServer: supportedCompressions,
+ CompressionServerClient: supportedCompressions,
+ }
+ kexInitPacket := marshal(msgKexInit, serverKexInit)
+ magics.serverKexInit = kexInitPacket
+
+ if err := s.writePacket(kexInitPacket); err != nil {
+ return err
+ }
+
+ packet, err := s.readPacket()
+ if err != nil {
+ return err
+ }
+
+ magics.clientKexInit = packet
+
+ var clientKexInit kexInitMsg
+ if err = unmarshal(&clientKexInit, packet, msgKexInit); err != nil {
+ return err
+ }
+
+ kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, &clientKexInit, &serverKexInit)
+ if !ok {
+ return os.NewError("ssh: no common algorithms")
+ }
+
+ if clientKexInit.FirstKexFollows && kexAlgo != clientKexInit.KexAlgos[0] {
+ // The client sent a Kex message for the wrong algorithm,
+ // which we have to ignore.
+ _, err := s.readPacket()
+ if err != nil {
+ return err
+ }
+ }
+
+ var H, K []byte
+ var hashFunc crypto.Hash
+ switch kexAlgo {
+ case kexAlgoDH14SHA1:
+ hashFunc = crypto.SHA1
+ dhGroup14Once.Do(initDHGroup14)
+ H, K, err = s.kexDH(dhGroup14, hashFunc, &magics, hostKeyAlgo)
+ default:
+ err = os.NewError("ssh: internal error")
+ }
+
+ if err != nil {
+ return err
+ }
+
+ packet = []byte{msgNewKeys}
+ if err = s.writePacket(packet); err != nil {
+ return err
+ }
+ if err = s.transport.writer.setupKeys(serverKeys, K, H, H, hashFunc); err != nil {
+ return err
+ }
+
+ if packet, err = s.readPacket(); err != nil {
+ return err
+ }
+ if packet[0] != msgNewKeys {
+ return UnexpectedMessageError{msgNewKeys, packet[0]}
+ }
+
+ s.transport.reader.setupKeys(clientKeys, K, H, H, hashFunc)
+
+ packet, err = s.readPacket()
+ if err != nil {
+ return err
+ }
+
+ var serviceRequest serviceRequestMsg
+ if err = unmarshal(&serviceRequest, packet, msgServiceRequest); err != nil {
+ return err
+ }
+ if serviceRequest.Service != serviceUserAuth {
+ return os.NewError("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
+ }
+
+ serviceAccept := serviceAcceptMsg{
+ Service: serviceUserAuth,
+ }
+ packet = marshal(msgServiceAccept, serviceAccept)
+ if err = s.writePacket(packet); err != nil {
+ return err
+ }
+
+ if err = s.authenticate(H); err != nil {
+ return err
+ }
+
+ s.channels = make(map[uint32]*channel)
+ return nil
+}
+
+func isAcceptableAlgo(algo string) bool {
+ return algo == hostAlgoRSA
+}
+
+// testPubKey returns true if the given public key is acceptable for the user.
+func (s *ServerConnection) testPubKey(user, algo string, pubKey []byte) bool {
+ if s.Server.PubKeyCallback == nil || !isAcceptableAlgo(algo) {
+ return false
+ }
+
+ for _, c := range s.cachedPubKeys {
+ if c.user == user && c.algo == algo && bytes.Equal(c.pubKey, pubKey) {
+ return c.result
+ }
+ }
+
+ result := s.Server.PubKeyCallback(user, algo, pubKey)
+ if len(s.cachedPubKeys) < maxCachedPubKeys {
+ c := cachedPubKey{
+ user: user,
+ algo: algo,
+ pubKey: make([]byte, len(pubKey)),
+ result: result,
+ }
+ copy(c.pubKey, pubKey)
+ s.cachedPubKeys = append(s.cachedPubKeys, c)
+ }
+
+ return result
+}
+
+func (s *ServerConnection) authenticate(H []byte) os.Error {
+ var userAuthReq userAuthRequestMsg
+ var err os.Error
+ var packet []byte
+
+userAuthLoop:
+ for {
+ if packet, err = s.readPacket(); err != nil {
+ return err
+ }
+ if err = unmarshal(&userAuthReq, packet, msgUserAuthRequest); err != nil {
+ return err
+ }
+
+ if userAuthReq.Service != serviceSSH {
+ return os.NewError("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
+ }
+
+ switch userAuthReq.Method {
+ case "none":
+ if s.Server.NoClientAuth {
+ break userAuthLoop
+ }
+ case "password":
+ if s.Server.PasswordCallback == nil {
+ break
+ }
+ payload := userAuthReq.Payload
+ if len(payload) < 1 || payload[0] != 0 {
+ return ParseError{msgUserAuthRequest}
+ }
+ payload = payload[1:]
+ password, payload, ok := parseString(payload)
+ if !ok || len(payload) > 0 {
+ return ParseError{msgUserAuthRequest}
+ }
+
+ if s.Server.PasswordCallback(userAuthReq.User, string(password)) {
+ break userAuthLoop
+ }
+ case "publickey":
+ if s.Server.PubKeyCallback == nil {
+ break
+ }
+ payload := userAuthReq.Payload
+ if len(payload) < 1 {
+ return ParseError{msgUserAuthRequest}
+ }
+ isQuery := payload[0] == 0
+ payload = payload[1:]
+ algoBytes, payload, ok := parseString(payload)
+ if !ok {
+ return ParseError{msgUserAuthRequest}
+ }
+ algo := string(algoBytes)
+
+ pubKey, payload, ok := parseString(payload)
+ if !ok {
+ return ParseError{msgUserAuthRequest}
+ }
+ if isQuery {
+ // The client can query if the given public key
+ // would be ok.
+ if len(payload) > 0 {
+ return ParseError{msgUserAuthRequest}
+ }
+ if s.testPubKey(userAuthReq.User, algo, pubKey) {
+ okMsg := userAuthPubKeyOkMsg{
+ Algo: algo,
+ PubKey: string(pubKey),
+ }
+ if err = s.writePacket(marshal(msgUserAuthPubKeyOk, okMsg)); err != nil {
+ return err
+ }
+ continue userAuthLoop
+ }
+ } else {
+ sig, payload, ok := parseString(payload)
+ if !ok || len(payload) > 0 {
+ return ParseError{msgUserAuthRequest}
+ }
+ if !isAcceptableAlgo(algo) {
+ break
+ }
+ rsaSig, ok := parseRSASig(sig)
+ if !ok {
+ return ParseError{msgUserAuthRequest}
+ }
+ signedData := buildDataSignedForAuth(H, userAuthReq, algoBytes, pubKey)
+ switch algo {
+ case hostAlgoRSA:
+ hashFunc := crypto.SHA1
+ h := hashFunc.New()
+ h.Write(signedData)
+ digest := h.Sum()
+ rsaKey, ok := parseRSA(pubKey)
+ if !ok {
+ return ParseError{msgUserAuthRequest}
+ }
+ if rsa.VerifyPKCS1v15(rsaKey, hashFunc, digest, rsaSig) != nil {
+ return ParseError{msgUserAuthRequest}
+ }
+ default:
+ return os.NewError("ssh: isAcceptableAlgo incorrect")
+ }
+ if s.testPubKey(userAuthReq.User, algo, pubKey) {
+ break userAuthLoop
+ }
+ }
+ }
+
+ var failureMsg userAuthFailureMsg
+ if s.Server.PasswordCallback != nil {
+ failureMsg.Methods = append(failureMsg.Methods, "password")
+ }
+ if s.Server.PubKeyCallback != nil {
+ failureMsg.Methods = append(failureMsg.Methods, "publickey")
+ }
+
+ if len(failureMsg.Methods) == 0 {
+ return os.NewError("ssh: no authentication methods configured but NoClientAuth is also false")
+ }
+
+ if err = s.writePacket(marshal(msgUserAuthFailure, failureMsg)); err != nil {
+ return err
+ }
+ }
+
+ packet = []byte{msgUserAuthSuccess}
+ if err = s.writePacket(packet); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+const defaultWindowSize = 32768
+
+// Accept reads and processes messages on a ServerConnection. It must be called
+// in order to demultiplex messages to any resulting Channels.
+func (s *ServerConnection) Accept() (Channel, os.Error) {
+ if s.err != nil {
+ return nil, s.err
+ }
+
+ for {
+ packet, err := s.readPacket()
+ if err != nil {
+
+ s.lock.Lock()
+ s.err = err
+ s.lock.Unlock()
+
+ for _, c := range s.channels {
+ c.dead = true
+ c.handleData(nil)
+ }
+
+ return nil, err
+ }
+
+ switch msg := decode(packet).(type) {
+ case *channelOpenMsg:
+ c := new(channel)
+ c.chanType = msg.ChanType
+ c.theirId = msg.PeersId
+ c.theirWindow = msg.PeersWindow
+ c.maxPacketSize = msg.MaxPacketSize
+ c.extraData = msg.TypeSpecificData
+ c.myWindow = defaultWindowSize
+ c.serverConn = s
+ c.cond = sync.NewCond(&c.lock)
+ c.pendingData = make([]byte, c.myWindow)
+
+ s.lock.Lock()
+ c.myId = s.nextChanId
+ s.nextChanId++
+ s.channels[c.myId] = c
+ s.lock.Unlock()
+ return c, nil
+
+ case *channelRequestMsg:
+ s.lock.Lock()
+ c, ok := s.channels[msg.PeersId]
+ if !ok {
+ continue
+ }
+ c.handlePacket(msg)
+ s.lock.Unlock()
+
+ case *channelData:
+ s.lock.Lock()
+ c, ok := s.channels[msg.PeersId]
+ if !ok {
+ continue
+ }
+ c.handleData(msg.Payload)
+ s.lock.Unlock()
+
+ case *channelEOFMsg:
+ s.lock.Lock()
+ c, ok := s.channels[msg.PeersId]
+ if !ok {
+ continue
+ }
+ c.handlePacket(msg)
+ s.lock.Unlock()
+
+ case *channelCloseMsg:
+ s.lock.Lock()
+ c, ok := s.channels[msg.PeersId]
+ if !ok {
+ continue
+ }
+ c.handlePacket(msg)
+ s.lock.Unlock()
+
+ case *globalRequestMsg:
+ if msg.WantReply {
+ if err := s.writePacket([]byte{msgRequestFailure}); err != nil {
+ return nil, err
+ }
+ }
+
+ case UnexpectedMessageError:
+ return nil, msg
+ case *disconnectMsg:
+ return nil, os.EOF
+ default:
+ // Unknown message. Ignore.
+ }
+ }
+
+ panic("unreachable")
+}
diff --git a/libgo/go/exp/ssh/server_shell.go b/libgo/go/exp/ssh/server_shell.go
new file mode 100644
index 00000000000..0e9967a9091
--- /dev/null
+++ b/libgo/go/exp/ssh/server_shell.go
@@ -0,0 +1,400 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "os"
+)
+
+// ServerShell contains the state for running a VT100 terminal that is capable
+// of reading lines of input.
+type ServerShell struct {
+ c Channel
+ prompt string
+
+ // line is the current line being entered.
+ line []byte
+ // pos is the logical position of the cursor in line
+ pos int
+
+ // cursorX contains the current X value of the cursor where the left
+ // edge is 0. cursorY contains the row number where the first row of
+ // the current line is 0.
+ cursorX, cursorY int
+ // maxLine is the greatest value of cursorY so far.
+ maxLine int
+
+ termWidth, termHeight int
+
+ // outBuf contains the terminal data to be sent.
+ outBuf []byte
+ // remainder contains the remainder of any partial key sequences after
+ // a read. It aliases into inBuf.
+ remainder []byte
+ inBuf [256]byte
+}
+
+// NewServerShell runs a VT100 terminal on the given channel. prompt is a
+// string that is written at the start of each input line. For example: "> ".
+func NewServerShell(c Channel, prompt string) *ServerShell {
+ return &ServerShell{
+ c: c,
+ prompt: prompt,
+ termWidth: 80,
+ termHeight: 24,
+ }
+}
+
+const (
+ keyCtrlD = 4
+ keyEnter = '\r'
+ keyEscape = 27
+ keyBackspace = 127
+ keyUnknown = 256 + iota
+ keyUp
+ keyDown
+ keyLeft
+ keyRight
+ keyAltLeft
+ keyAltRight
+)
+
+// bytesToKey tries to parse a key sequence from b. If successful, it returns
+// the key and the remainder of the input. Otherwise it returns -1.
+func bytesToKey(b []byte) (int, []byte) {
+ if len(b) == 0 {
+ return -1, nil
+ }
+
+ if b[0] != keyEscape {
+ return int(b[0]), b[1:]
+ }
+
+ if len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
+ switch b[2] {
+ case 'A':
+ return keyUp, b[3:]
+ case 'B':
+ return keyDown, b[3:]
+ case 'C':
+ return keyRight, b[3:]
+ case 'D':
+ return keyLeft, b[3:]
+ }
+ }
+
+ if len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
+ switch b[5] {
+ case 'C':
+ return keyAltRight, b[6:]
+ case 'D':
+ return keyAltLeft, b[6:]
+ }
+ }
+
+ // If we get here then we have a key that we don't recognise, or a
+ // partial sequence. It's not clear how one should find the end of a
+ // sequence without knowing them all, but it seems that [a-zA-Z] only
+ // appears at the end of a sequence.
+ for i, c := range b[0:] {
+ if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {
+ return keyUnknown, b[i+1:]
+ }
+ }
+
+ return -1, b
+}
+
+// queue appends data to the end of ss.outBuf
+func (ss *ServerShell) queue(data []byte) {
+ if len(ss.outBuf)+len(data) > cap(ss.outBuf) {
+ newOutBuf := make([]byte, len(ss.outBuf), 2*(len(ss.outBuf)+len(data)))
+ copy(newOutBuf, ss.outBuf)
+ ss.outBuf = newOutBuf
+ }
+
+ oldLen := len(ss.outBuf)
+ ss.outBuf = ss.outBuf[:len(ss.outBuf)+len(data)]
+ copy(ss.outBuf[oldLen:], data)
+}
+
+var eraseUnderCursor = []byte{' ', keyEscape, '[', 'D'}
+
+func isPrintable(key int) bool {
+ return key >= 32 && key < 127
+}
+
+// moveCursorToPos appends data to ss.outBuf which will move the cursor to the
+// given, logical position in the text.
+func (ss *ServerShell) moveCursorToPos(pos int) {
+ x := len(ss.prompt) + pos
+ y := x / ss.termWidth
+ x = x % ss.termWidth
+
+ up := 0
+ if y < ss.cursorY {
+ up = ss.cursorY - y
+ }
+
+ down := 0
+ if y > ss.cursorY {
+ down = y - ss.cursorY
+ }
+
+ left := 0
+ if x < ss.cursorX {
+ left = ss.cursorX - x
+ }
+
+ right := 0
+ if x > ss.cursorX {
+ right = x - ss.cursorX
+ }
+
+ movement := make([]byte, 3*(up+down+left+right))
+ m := movement
+ for i := 0; i < up; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'A'
+ m = m[3:]
+ }
+ for i := 0; i < down; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'B'
+ m = m[3:]
+ }
+ for i := 0; i < left; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'D'
+ m = m[3:]
+ }
+ for i := 0; i < right; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'C'
+ m = m[3:]
+ }
+
+ ss.cursorX = x
+ ss.cursorY = y
+ ss.queue(movement)
+}
+
+const maxLineLength = 4096
+
+// handleKey processes the given key and, optionally, returns a line of text
+// that the user has entered.
+func (ss *ServerShell) handleKey(key int) (line string, ok bool) {
+ switch key {
+ case keyBackspace:
+ if ss.pos == 0 {
+ return
+ }
+ ss.pos--
+
+ copy(ss.line[ss.pos:], ss.line[1+ss.pos:])
+ ss.line = ss.line[:len(ss.line)-1]
+ ss.writeLine(ss.line[ss.pos:])
+ ss.moveCursorToPos(ss.pos)
+ ss.queue(eraseUnderCursor)
+ case keyAltLeft:
+ // move left by a word.
+ if ss.pos == 0 {
+ return
+ }
+ ss.pos--
+ for ss.pos > 0 {
+ if ss.line[ss.pos] != ' ' {
+ break
+ }
+ ss.pos--
+ }
+ for ss.pos > 0 {
+ if ss.line[ss.pos] == ' ' {
+ ss.pos++
+ break
+ }
+ ss.pos--
+ }
+ ss.moveCursorToPos(ss.pos)
+ case keyAltRight:
+ // move right by a word.
+ for ss.pos < len(ss.line) {
+ if ss.line[ss.pos] == ' ' {
+ break
+ }
+ ss.pos++
+ }
+ for ss.pos < len(ss.line) {
+ if ss.line[ss.pos] != ' ' {
+ break
+ }
+ ss.pos++
+ }
+ ss.moveCursorToPos(ss.pos)
+ case keyLeft:
+ if ss.pos == 0 {
+ return
+ }
+ ss.pos--
+ ss.moveCursorToPos(ss.pos)
+ case keyRight:
+ if ss.pos == len(ss.line) {
+ return
+ }
+ ss.pos++
+ ss.moveCursorToPos(ss.pos)
+ case keyEnter:
+ ss.moveCursorToPos(len(ss.line))
+ ss.queue([]byte("\r\n"))
+ line = string(ss.line)
+ ok = true
+ ss.line = ss.line[:0]
+ ss.pos = 0
+ ss.cursorX = 0
+ ss.cursorY = 0
+ ss.maxLine = 0
+ default:
+ if !isPrintable(key) {
+ return
+ }
+ if len(ss.line) == maxLineLength {
+ return
+ }
+ if len(ss.line) == cap(ss.line) {
+ newLine := make([]byte, len(ss.line), 2*(1+len(ss.line)))
+ copy(newLine, ss.line)
+ ss.line = newLine
+ }
+ ss.line = ss.line[:len(ss.line)+1]
+ copy(ss.line[ss.pos+1:], ss.line[ss.pos:])
+ ss.line[ss.pos] = byte(key)
+ ss.writeLine(ss.line[ss.pos:])
+ ss.pos++
+ ss.moveCursorToPos(ss.pos)
+ }
+ return
+}
+
+func (ss *ServerShell) writeLine(line []byte) {
+ for len(line) != 0 {
+ if ss.cursorX == ss.termWidth {
+ ss.queue([]byte("\r\n"))
+ ss.cursorX = 0
+ ss.cursorY++
+ if ss.cursorY > ss.maxLine {
+ ss.maxLine = ss.cursorY
+ }
+ }
+
+ remainingOnLine := ss.termWidth - ss.cursorX
+ todo := len(line)
+ if todo > remainingOnLine {
+ todo = remainingOnLine
+ }
+ ss.queue(line[:todo])
+ ss.cursorX += todo
+ line = line[todo:]
+ }
+}
+
+// parsePtyRequest parses the payload of the pty-req message and extracts the
+// dimensions of the terminal. See RFC 4254, section 6.2.
+func parsePtyRequest(s []byte) (width, height int, ok bool) {
+ _, s, ok = parseString(s)
+ if !ok {
+ return
+ }
+ width32, s, ok := parseUint32(s)
+ if !ok {
+ return
+ }
+ height32, _, ok := parseUint32(s)
+ width = int(width32)
+ height = int(height32)
+ if width < 1 {
+ ok = false
+ }
+ if height < 1 {
+ ok = false
+ }
+ return
+}
+
+func (ss *ServerShell) Write(buf []byte) (n int, err os.Error) {
+ return ss.c.Write(buf)
+}
+
+// ReadLine returns a line of input from the terminal.
+func (ss *ServerShell) ReadLine() (line string, err os.Error) {
+ ss.writeLine([]byte(ss.prompt))
+ ss.c.Write(ss.outBuf)
+ ss.outBuf = ss.outBuf[:0]
+
+ for {
+ // ss.remainder is a slice at the beginning of ss.inBuf
+ // containing a partial key sequence
+ readBuf := ss.inBuf[len(ss.remainder):]
+ var n int
+ n, err = ss.c.Read(readBuf)
+ if err == nil {
+ ss.remainder = ss.inBuf[:n+len(ss.remainder)]
+ rest := ss.remainder
+ lineOk := false
+ for !lineOk {
+ var key int
+ key, rest = bytesToKey(rest)
+ if key < 0 {
+ break
+ }
+ if key == keyCtrlD {
+ return "", os.EOF
+ }
+ line, lineOk = ss.handleKey(key)
+ }
+ if len(rest) > 0 {
+ n := copy(ss.inBuf[:], rest)
+ ss.remainder = ss.inBuf[:n]
+ } else {
+ ss.remainder = nil
+ }
+ ss.c.Write(ss.outBuf)
+ ss.outBuf = ss.outBuf[:0]
+ if lineOk {
+ return
+ }
+ continue
+ }
+
+ if req, ok := err.(ChannelRequest); ok {
+ ok := false
+ switch req.Request {
+ case "pty-req":
+ ss.termWidth, ss.termHeight, ok = parsePtyRequest(req.Payload)
+ if !ok {
+ ss.termWidth = 80
+ ss.termHeight = 24
+ }
+ case "shell":
+ ok = true
+ if len(req.Payload) > 0 {
+ // We don't accept any commands, only the default shell.
+ ok = false
+ }
+ case "env":
+ ok = true
+ }
+ if req.WantReply {
+ ss.c.AckRequest(ok)
+ }
+ } else {
+ return "", err
+ }
+ }
+ panic("unreachable")
+}
diff --git a/libgo/go/exp/ssh/server_shell_test.go b/libgo/go/exp/ssh/server_shell_test.go
new file mode 100644
index 00000000000..622cf7cfada
--- /dev/null
+++ b/libgo/go/exp/ssh/server_shell_test.go
@@ -0,0 +1,134 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "testing"
+ "os"
+)
+
+type MockChannel struct {
+ toSend []byte
+ bytesPerRead int
+ received []byte
+}
+
+func (c *MockChannel) Accept() os.Error {
+ return nil
+}
+
+func (c *MockChannel) Reject(RejectionReason, string) os.Error {
+ return nil
+}
+
+func (c *MockChannel) Read(data []byte) (n int, err os.Error) {
+ n = len(data)
+ if n == 0 {
+ return
+ }
+ if n > len(c.toSend) {
+ n = len(c.toSend)
+ }
+ if n == 0 {
+ return 0, os.EOF
+ }
+ if c.bytesPerRead > 0 && n > c.bytesPerRead {
+ n = c.bytesPerRead
+ }
+ copy(data, c.toSend[:n])
+ c.toSend = c.toSend[n:]
+ return
+}
+
+func (c *MockChannel) Write(data []byte) (n int, err os.Error) {
+ c.received = append(c.received, data...)
+ return len(data), nil
+}
+
+func (c *MockChannel) Close() os.Error {
+ return nil
+}
+
+func (c *MockChannel) AckRequest(ok bool) os.Error {
+ return nil
+}
+
+func (c *MockChannel) ChannelType() string {
+ return ""
+}
+
+func (c *MockChannel) ExtraData() []byte {
+ return nil
+}
+
+func TestClose(t *testing.T) {
+ c := &MockChannel{}
+ ss := NewServerShell(c, "> ")
+ line, err := ss.ReadLine()
+ if line != "" {
+ t.Errorf("Expected empty line but got: %s", line)
+ }
+ if err != os.EOF {
+ t.Errorf("Error should have been EOF but got: %s", err)
+ }
+}
+
+var keyPressTests = []struct {
+ in string
+ line string
+ err os.Error
+}{
+ {
+ "",
+ "",
+ os.EOF,
+ },
+ {
+ "\r",
+ "",
+ nil,
+ },
+ {
+ "foo\r",
+ "foo",
+ nil,
+ },
+ {
+ "a\x1b[Cb\r", // right
+ "ab",
+ nil,
+ },
+ {
+ "a\x1b[Db\r", // left
+ "ba",
+ nil,
+ },
+ {
+ "a\177b\r", // backspace
+ "b",
+ nil,
+ },
+}
+
+func TestKeyPresses(t *testing.T) {
+ for i, test := range keyPressTests {
+ for j := 0; j < len(test.in); j++ {
+ c := &MockChannel{
+ toSend: []byte(test.in),
+ bytesPerRead: j,
+ }
+ ss := NewServerShell(c, "> ")
+ line, err := ss.ReadLine()
+ if line != test.line {
+ t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
+ break
+ }
+ if err != test.err {
+ t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
+ break
+ }
+ }
+ }
+}
diff --git a/libgo/go/exp/ssh/transport.go b/libgo/go/exp/ssh/transport.go
new file mode 100644
index 00000000000..5994004d866
--- /dev/null
+++ b/libgo/go/exp/ssh/transport.go
@@ -0,0 +1,369 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bufio"
+ "crypto"
+ "crypto/aes"
+ "crypto/cipher"
+ "crypto/hmac"
+ "crypto/subtle"
+ "hash"
+ "io"
+ "net"
+ "os"
+ "sync"
+)
+
+const (
+ paddingMultiple = 16 // TODO(dfc) does this need to be configurable?
+)
+
+// filteredConn reduces the set of methods exposed when embeddeding
+// a net.Conn inside ssh.transport.
+// TODO(dfc) suggestions for a better name will be warmly received.
+type filteredConn interface {
+ // Close closes the connection.
+ Close() os.Error
+
+ // LocalAddr returns the local network address.
+ LocalAddr() net.Addr
+
+ // RemoteAddr returns the remote network address.
+ RemoteAddr() net.Addr
+}
+
+// Types implementing packetWriter provide the ability to send packets to
+// an SSH peer.
+type packetWriter interface {
+ // Encrypt and send a packet of data to the remote peer.
+ writePacket(packet []byte) os.Error
+}
+
+// transport represents the SSH connection to the remote peer.
+type transport struct {
+ reader
+ writer
+
+ filteredConn
+}
+
+// reader represents the incoming connection state.
+type reader struct {
+ io.Reader
+ common
+}
+
+// writer represnts the outgoing connection state.
+type writer struct {
+ *sync.Mutex // protects writer.Writer from concurrent writes
+ *bufio.Writer
+ paddingMultiple int
+ rand io.Reader
+ common
+}
+
+// common represents the cipher state needed to process messages in a single
+// direction.
+type common struct {
+ seqNum uint32
+ mac hash.Hash
+ cipher cipher.Stream
+
+ cipherAlgo string
+ macAlgo string
+ compressionAlgo string
+}
+
+// Read and decrypt a single packet from the remote peer.
+func (r *reader) readOnePacket() ([]byte, os.Error) {
+ var lengthBytes = make([]byte, 5)
+ var macSize uint32
+
+ if _, err := io.ReadFull(r, lengthBytes); err != nil {
+ return nil, err
+ }
+
+ if r.cipher != nil {
+ r.cipher.XORKeyStream(lengthBytes, lengthBytes)
+ }
+
+ if r.mac != nil {
+ r.mac.Reset()
+ seqNumBytes := []byte{
+ byte(r.seqNum >> 24),
+ byte(r.seqNum >> 16),
+ byte(r.seqNum >> 8),
+ byte(r.seqNum),
+ }
+ r.mac.Write(seqNumBytes)
+ r.mac.Write(lengthBytes)
+ macSize = uint32(r.mac.Size())
+ }
+
+ length := uint32(lengthBytes[0])<<24 | uint32(lengthBytes[1])<<16 | uint32(lengthBytes[2])<<8 | uint32(lengthBytes[3])
+ paddingLength := uint32(lengthBytes[4])
+
+ if length <= paddingLength+1 {
+ return nil, os.NewError("invalid packet length")
+ }
+ if length > maxPacketSize {
+ return nil, os.NewError("packet too large")
+ }
+
+ packet := make([]byte, length-1+macSize)
+ if _, err := io.ReadFull(r, packet); err != nil {
+ return nil, err
+ }
+ mac := packet[length-1:]
+ if r.cipher != nil {
+ r.cipher.XORKeyStream(packet, packet[:length-1])
+ }
+
+ if r.mac != nil {
+ r.mac.Write(packet[:length-1])
+ if subtle.ConstantTimeCompare(r.mac.Sum(), mac) != 1 {
+ return nil, os.NewError("ssh: MAC failure")
+ }
+ }
+
+ r.seqNum++
+ return packet[:length-paddingLength-1], nil
+}
+
+// Read and decrypt next packet discarding debug and noop messages.
+func (t *transport) readPacket() ([]byte, os.Error) {
+ for {
+ packet, err := t.readOnePacket()
+ if err != nil {
+ return nil, err
+ }
+ if packet[0] != msgIgnore && packet[0] != msgDebug {
+ return packet, nil
+ }
+ }
+ panic("unreachable")
+}
+
+// Encrypt and send a packet of data to the remote peer.
+func (w *writer) writePacket(packet []byte) os.Error {
+ w.Mutex.Lock()
+ defer w.Mutex.Unlock()
+
+ paddingLength := paddingMultiple - (5+len(packet))%paddingMultiple
+ if paddingLength < 4 {
+ paddingLength += paddingMultiple
+ }
+
+ length := len(packet) + 1 + paddingLength
+ lengthBytes := []byte{
+ byte(length >> 24),
+ byte(length >> 16),
+ byte(length >> 8),
+ byte(length),
+ byte(paddingLength),
+ }
+ padding := make([]byte, paddingLength)
+ _, err := io.ReadFull(w.rand, padding)
+ if err != nil {
+ return err
+ }
+
+ if w.mac != nil {
+ w.mac.Reset()
+ seqNumBytes := []byte{
+ byte(w.seqNum >> 24),
+ byte(w.seqNum >> 16),
+ byte(w.seqNum >> 8),
+ byte(w.seqNum),
+ }
+ w.mac.Write(seqNumBytes)
+ w.mac.Write(lengthBytes)
+ w.mac.Write(packet)
+ w.mac.Write(padding)
+ }
+
+ // TODO(dfc) lengthBytes, packet and padding should be
+ // subslices of a single buffer
+ if w.cipher != nil {
+ w.cipher.XORKeyStream(lengthBytes, lengthBytes)
+ w.cipher.XORKeyStream(packet, packet)
+ w.cipher.XORKeyStream(padding, padding)
+ }
+
+ if _, err := w.Write(lengthBytes); err != nil {
+ return err
+ }
+ if _, err := w.Write(packet); err != nil {
+ return err
+ }
+ if _, err := w.Write(padding); err != nil {
+ return err
+ }
+
+ if w.mac != nil {
+ if _, err := w.Write(w.mac.Sum()); err != nil {
+ return err
+ }
+ }
+
+ if err := w.Flush(); err != nil {
+ return err
+ }
+ w.seqNum++
+ return err
+}
+
+// Send a message to the remote peer
+func (t *transport) sendMessage(typ uint8, msg interface{}) os.Error {
+ packet := marshal(typ, msg)
+ return t.writePacket(packet)
+}
+
+func newTransport(conn net.Conn, rand io.Reader) *transport {
+ return &transport{
+ reader: reader{
+ Reader: bufio.NewReader(conn),
+ },
+ writer: writer{
+ Writer: bufio.NewWriter(conn),
+ rand: rand,
+ Mutex: new(sync.Mutex),
+ },
+ filteredConn: conn,
+ }
+}
+
+type direction struct {
+ ivTag []byte
+ keyTag []byte
+ macKeyTag []byte
+}
+
+// TODO(dfc) can this be made a constant ?
+var (
+ serverKeys = direction{[]byte{'B'}, []byte{'D'}, []byte{'F'}}
+ clientKeys = direction{[]byte{'A'}, []byte{'C'}, []byte{'E'}}
+)
+
+// setupKeys sets the cipher and MAC keys from K, H and sessionId, as
+// described in RFC 4253, section 6.4. direction should either be serverKeys
+// (to setup server->client keys) or clientKeys (for client->server keys).
+func (c *common) setupKeys(d direction, K, H, sessionId []byte, hashFunc crypto.Hash) os.Error {
+ h := hashFunc.New()
+
+ blockSize := 16
+ keySize := 16
+ macKeySize := 20
+
+ iv := make([]byte, blockSize)
+ key := make([]byte, keySize)
+ macKey := make([]byte, macKeySize)
+ generateKeyMaterial(iv, d.ivTag, K, H, sessionId, h)
+ generateKeyMaterial(key, d.keyTag, K, H, sessionId, h)
+ generateKeyMaterial(macKey, d.macKeyTag, K, H, sessionId, h)
+
+ c.mac = truncatingMAC{12, hmac.NewSHA1(macKey)}
+ aes, err := aes.NewCipher(key)
+ if err != nil {
+ return err
+ }
+ c.cipher = cipher.NewCTR(aes, iv)
+ return nil
+}
+
+// generateKeyMaterial fills out with key material generated from tag, K, H
+// and sessionId, as specified in RFC 4253, section 7.2.
+func generateKeyMaterial(out, tag []byte, K, H, sessionId []byte, h hash.Hash) {
+ var digestsSoFar []byte
+
+ for len(out) > 0 {
+ h.Reset()
+ h.Write(K)
+ h.Write(H)
+
+ if len(digestsSoFar) == 0 {
+ h.Write(tag)
+ h.Write(sessionId)
+ } else {
+ h.Write(digestsSoFar)
+ }
+
+ digest := h.Sum()
+ n := copy(out, digest)
+ out = out[n:]
+ if len(out) > 0 {
+ digestsSoFar = append(digestsSoFar, digest...)
+ }
+ }
+}
+
+// truncatingMAC wraps around a hash.Hash and truncates the output digest to
+// a given size.
+type truncatingMAC struct {
+ length int
+ hmac hash.Hash
+}
+
+func (t truncatingMAC) Write(data []byte) (int, os.Error) {
+ return t.hmac.Write(data)
+}
+
+func (t truncatingMAC) Sum() []byte {
+ digest := t.hmac.Sum()
+ return digest[:t.length]
+}
+
+func (t truncatingMAC) Reset() {
+ t.hmac.Reset()
+}
+
+func (t truncatingMAC) Size() int {
+ return t.length
+}
+
+// maxVersionStringBytes is the maximum number of bytes that we'll accept as a
+// version string. In the event that the client is talking a different protocol
+// we need to set a limit otherwise we will keep using more and more memory
+// while searching for the end of the version handshake.
+const maxVersionStringBytes = 1024
+
+// Read version string as specified by RFC 4253, section 4.2.
+func readVersion(r io.Reader) (versionString []byte, ok bool) {
+ versionString = make([]byte, 0, 64)
+ seenCR := false
+
+ var buf [1]byte
+forEachByte:
+ for len(versionString) < maxVersionStringBytes {
+ _, err := io.ReadFull(r, buf[:])
+ if err != nil {
+ return
+ }
+ b := buf[0]
+
+ if !seenCR {
+ if b == '\r' {
+ seenCR = true
+ }
+ } else {
+ if b == '\n' {
+ ok = true
+ break forEachByte
+ } else {
+ seenCR = false
+ }
+ }
+ versionString = append(versionString, b)
+ }
+
+ if ok {
+ // We need to remove the CR from versionString
+ versionString = versionString[:len(versionString)-1]
+ }
+
+ return
+}
diff --git a/libgo/go/exp/ssh/transport_test.go b/libgo/go/exp/ssh/transport_test.go
new file mode 100644
index 00000000000..9a610a7803c
--- /dev/null
+++ b/libgo/go/exp/ssh/transport_test.go
@@ -0,0 +1,37 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssh
+
+import (
+ "bufio"
+ "bytes"
+ "testing"
+)
+
+func TestReadVersion(t *testing.T) {
+ buf := []byte(serverVersion)
+ result, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf)))
+ if !ok {
+ t.Error("readVersion didn't read version correctly")
+ }
+ if !bytes.Equal(buf[:len(buf)-2], result) {
+ t.Error("version read did not match expected")
+ }
+}
+
+func TestReadVersionTooLong(t *testing.T) {
+ buf := make([]byte, maxVersionStringBytes+1)
+ if _, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); ok {
+ t.Errorf("readVersion consumed %d bytes without error", len(buf))
+ }
+}
+
+func TestReadVersionWithoutCRLF(t *testing.T) {
+ buf := []byte(serverVersion)
+ buf = buf[:len(buf)-1]
+ if _, ok := readVersion(bufio.NewReader(bytes.NewBuffer(buf))); ok {
+ t.Error("readVersion did not notice \\n was missing")
+ }
+}
diff --git a/libgo/go/exp/template/html/attr.go b/libgo/go/exp/template/html/attr.go
new file mode 100644
index 00000000000..6a36c7b7181
--- /dev/null
+++ b/libgo/go/exp/template/html/attr.go
@@ -0,0 +1,175 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "strings"
+)
+
+// attrTypeMap[n] describes the value of the given attribute.
+// If an attribute affects (or can mask) the encoding or interpretation of
+// other content, or affects the contents, idempotency, or credentials of a
+// network message, then the value in this map is contentTypeUnsafe.
+// This map is derived from HTML5, specifically
+// http://www.w3.org/TR/html5/Overview.html#attributes-1
+// as well as "%URI"-typed attributes from
+// http://www.w3.org/TR/html4/index/attributes.html
+var attrTypeMap = map[string]contentType{
+ "accept": contentTypePlain,
+ "accept-charset": contentTypeUnsafe,
+ "action": contentTypeURL,
+ "alt": contentTypePlain,
+ "archive": contentTypeURL,
+ "async": contentTypeUnsafe,
+ "autocomplete": contentTypePlain,
+ "autofocus": contentTypePlain,
+ "autoplay": contentTypePlain,
+ "background": contentTypeURL,
+ "border": contentTypePlain,
+ "checked": contentTypePlain,
+ "cite": contentTypeURL,
+ "challenge": contentTypeUnsafe,
+ "charset": contentTypeUnsafe,
+ "class": contentTypePlain,
+ "classid": contentTypeURL,
+ "codebase": contentTypeURL,
+ "cols": contentTypePlain,
+ "colspan": contentTypePlain,
+ "content": contentTypeUnsafe,
+ "contenteditable": contentTypePlain,
+ "contextmenu": contentTypePlain,
+ "controls": contentTypePlain,
+ "coords": contentTypePlain,
+ "crossorigin": contentTypeUnsafe,
+ "data": contentTypeURL,
+ "datetime": contentTypePlain,
+ "default": contentTypePlain,
+ "defer": contentTypeUnsafe,
+ "dir": contentTypePlain,
+ "dirname": contentTypePlain,
+ "disabled": contentTypePlain,
+ "draggable": contentTypePlain,
+ "dropzone": contentTypePlain,
+ "enctype": contentTypeUnsafe,
+ "for": contentTypePlain,
+ "form": contentTypeUnsafe,
+ "formaction": contentTypeURL,
+ "formenctype": contentTypeUnsafe,
+ "formmethod": contentTypeUnsafe,
+ "formnovalidate": contentTypeUnsafe,
+ "formtarget": contentTypePlain,
+ "headers": contentTypePlain,
+ "height": contentTypePlain,
+ "hidden": contentTypePlain,
+ "high": contentTypePlain,
+ "href": contentTypeURL,
+ "hreflang": contentTypePlain,
+ "http-equiv": contentTypeUnsafe,
+ "icon": contentTypeURL,
+ "id": contentTypePlain,
+ "ismap": contentTypePlain,
+ "keytype": contentTypeUnsafe,
+ "kind": contentTypePlain,
+ "label": contentTypePlain,
+ "lang": contentTypePlain,
+ "language": contentTypeUnsafe,
+ "list": contentTypePlain,
+ "longdesc": contentTypeURL,
+ "loop": contentTypePlain,
+ "low": contentTypePlain,
+ "manifest": contentTypeURL,
+ "max": contentTypePlain,
+ "maxlength": contentTypePlain,
+ "media": contentTypePlain,
+ "mediagroup": contentTypePlain,
+ "method": contentTypeUnsafe,
+ "min": contentTypePlain,
+ "multiple": contentTypePlain,
+ "name": contentTypePlain,
+ "novalidate": contentTypeUnsafe,
+ // Skip handler names from
+ // http://www.w3.org/TR/html5/Overview.html#event-handlers-on-elements-document-objects-and-window-objects
+ // since we have special handling in attrType.
+ "open": contentTypePlain,
+ "optimum": contentTypePlain,
+ "pattern": contentTypeUnsafe,
+ "placeholder": contentTypePlain,
+ "poster": contentTypeURL,
+ "profile": contentTypeURL,
+ "preload": contentTypePlain,
+ "pubdate": contentTypePlain,
+ "radiogroup": contentTypePlain,
+ "readonly": contentTypePlain,
+ "rel": contentTypeUnsafe,
+ "required": contentTypePlain,
+ "reversed": contentTypePlain,
+ "rows": contentTypePlain,
+ "rowspan": contentTypePlain,
+ "sandbox": contentTypeUnsafe,
+ "spellcheck": contentTypePlain,
+ "scope": contentTypePlain,
+ "scoped": contentTypePlain,
+ "seamless": contentTypePlain,
+ "selected": contentTypePlain,
+ "shape": contentTypePlain,
+ "size": contentTypePlain,
+ "sizes": contentTypePlain,
+ "span": contentTypePlain,
+ "src": contentTypeURL,
+ "srcdoc": contentTypeHTML,
+ "srclang": contentTypePlain,
+ "start": contentTypePlain,
+ "step": contentTypePlain,
+ "style": contentTypeCSS,
+ "tabindex": contentTypePlain,
+ "target": contentTypePlain,
+ "title": contentTypePlain,
+ "type": contentTypeUnsafe,
+ "usemap": contentTypeURL,
+ "value": contentTypeUnsafe,
+ "width": contentTypePlain,
+ "wrap": contentTypePlain,
+ "xmlns": contentTypeURL,
+}
+
+// attrType returns a conservative (upper-bound on authority) guess at the
+// type of the named attribute.
+func attrType(name string) contentType {
+ name = strings.ToLower(name)
+ if strings.HasPrefix(name, "data-") {
+ // Strip data- so that custom attribute heuristics below are
+ // widely applied.
+ // Treat data-action as URL below.
+ name = name[5:]
+ } else if colon := strings.IndexRune(name, ':'); colon != -1 {
+ if name[:colon] == "xmlns" {
+ return contentTypeURL
+ }
+ // Treat svg:href and xlink:href as href below.
+ name = name[colon+1:]
+ }
+ if t, ok := attrTypeMap[name]; ok {
+ return t
+ }
+ // Treat partial event handler names as script.
+ if strings.HasPrefix(name, "on") {
+ return contentTypeJS
+ }
+
+ // Heuristics to prevent "javascript:..." injection in custom
+ // data attributes and custom attributes like g:tweetUrl.
+ // http://www.w3.org/TR/html5/elements.html#embedding-custom-non-visible-data-with-the-data-attributes:
+ // "Custom data attributes are intended to store custom data
+ // private to the page or application, for which there are no
+ // more appropriate attributes or elements."
+ // Developers seem to store URL content in data URLs that start
+ // or end with "URI" or "URL".
+ if strings.Contains(name, "src") ||
+ strings.Contains(name, "uri") ||
+ strings.Contains(name, "url") {
+ return contentTypeURL
+ }
+ return contentTypePlain
+}
diff --git a/libgo/go/exp/template/html/clone.go b/libgo/go/exp/template/html/clone.go
new file mode 100644
index 00000000000..803a64de12f
--- /dev/null
+++ b/libgo/go/exp/template/html/clone.go
@@ -0,0 +1,90 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "template/parse"
+)
+
+// clone clones a template Node.
+func clone(n parse.Node) parse.Node {
+ switch t := n.(type) {
+ case *parse.ActionNode:
+ return cloneAction(t)
+ case *parse.IfNode:
+ b := new(parse.IfNode)
+ copyBranch(&b.BranchNode, &t.BranchNode)
+ return b
+ case *parse.ListNode:
+ return cloneList(t)
+ case *parse.RangeNode:
+ b := new(parse.RangeNode)
+ copyBranch(&b.BranchNode, &t.BranchNode)
+ return b
+ case *parse.TemplateNode:
+ return cloneTemplate(t)
+ case *parse.TextNode:
+ return cloneText(t)
+ case *parse.WithNode:
+ b := new(parse.WithNode)
+ copyBranch(&b.BranchNode, &t.BranchNode)
+ return b
+ }
+ panic("cloning " + n.String() + " is unimplemented")
+}
+
+// cloneAction returns a deep clone of n.
+func cloneAction(n *parse.ActionNode) *parse.ActionNode {
+ // We use keyless fields because they won't compile if a field is added.
+ return &parse.ActionNode{n.NodeType, n.Line, clonePipe(n.Pipe)}
+}
+
+// cloneList returns a deep clone of n.
+func cloneList(n *parse.ListNode) *parse.ListNode {
+ if n == nil {
+ return nil
+ }
+ // We use keyless fields because they won't compile if a field is added.
+ c := parse.ListNode{n.NodeType, make([]parse.Node, len(n.Nodes))}
+ for i, child := range n.Nodes {
+ c.Nodes[i] = clone(child)
+ }
+ return &c
+}
+
+// clonePipe returns a shallow clone of n.
+// The escaper does not modify pipe descendants in place so there's no need to
+// clone deeply.
+func clonePipe(n *parse.PipeNode) *parse.PipeNode {
+ if n == nil {
+ return nil
+ }
+ // We use keyless fields because they won't compile if a field is added.
+ return &parse.PipeNode{n.NodeType, n.Line, n.Decl, n.Cmds}
+}
+
+// cloneTemplate returns a deep clone of n.
+func cloneTemplate(n *parse.TemplateNode) *parse.TemplateNode {
+ // We use keyless fields because they won't compile if a field is added.
+ return &parse.TemplateNode{n.NodeType, n.Line, n.Name, clonePipe(n.Pipe)}
+}
+
+// cloneText clones the given node sharing its []byte.
+func cloneText(n *parse.TextNode) *parse.TextNode {
+ // We use keyless fields because they won't compile if a field is added.
+ return &parse.TextNode{n.NodeType, n.Text}
+}
+
+// copyBranch clones src into dst.
+func copyBranch(dst, src *parse.BranchNode) {
+ // We use keyless fields because they won't compile if a field is added.
+ *dst = parse.BranchNode{
+ src.NodeType,
+ src.Line,
+ clonePipe(src.Pipe),
+ cloneList(src.List),
+ cloneList(src.ElseList),
+ }
+}
diff --git a/libgo/go/exp/template/html/clone_test.go b/libgo/go/exp/template/html/clone_test.go
new file mode 100644
index 00000000000..d91542529b9
--- /dev/null
+++ b/libgo/go/exp/template/html/clone_test.go
@@ -0,0 +1,90 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "template"
+ "template/parse"
+ "testing"
+)
+
+func TestClone(t *testing.T) {
+ tests := []struct {
+ input, want, wantClone string
+ }{
+ {
+ `Hello, {{if true}}{{"<World>"}}{{end}}!`,
+ "Hello, <World>!",
+ "Hello, &lt;World&gt;!",
+ },
+ {
+ `Hello, {{if false}}{{.X}}{{else}}{{"<World>"}}{{end}}!`,
+ "Hello, <World>!",
+ "Hello, &lt;World&gt;!",
+ },
+ {
+ `Hello, {{with "<World>"}}{{.}}{{end}}!`,
+ "Hello, <World>!",
+ "Hello, &lt;World&gt;!",
+ },
+ {
+ `{{range .}}<p>{{.}}</p>{{end}}`,
+ "<p>foo</p><p><bar></p><p>baz</p>",
+ "<p>foo</p><p>&lt;bar&gt;</p><p>baz</p>",
+ },
+ {
+ `Hello, {{"<World>" | html}}!`,
+ "Hello, &lt;World&gt;!",
+ "Hello, &lt;World&gt;!",
+ },
+ {
+ `Hello{{if 1}}, World{{else}}{{template "d"}}{{end}}!`,
+ "Hello, World!",
+ "Hello, World!",
+ },
+ }
+
+ for _, test := range tests {
+ s := template.Must(template.New("s").Parse(test.input))
+ d := template.New("d")
+ d.Tree = &parse.Tree{Name: d.Name(), Root: cloneList(s.Root)}
+
+ if want, got := s.Root.String(), d.Root.String(); want != got {
+ t.Errorf("want %q, got %q", want, got)
+ }
+
+ d, err := Escape(d)
+ if err != nil {
+ t.Errorf("%q: failed to escape: %s", test.input, err)
+ continue
+ }
+
+ if want, got := "s", s.Name(); want != got {
+ t.Errorf("want %q, got %q", want, got)
+ continue
+ }
+ if want, got := "d", d.Name(); want != got {
+ t.Errorf("want %q, got %q", want, got)
+ continue
+ }
+
+ data := []string{"foo", "<bar>", "baz"}
+
+ // Make sure escaping d did not affect s.
+ var b bytes.Buffer
+ s.Execute(&b, data)
+ if got := b.String(); got != test.want {
+ t.Errorf("%q: want %q, got %q", test.input, test.want, got)
+ continue
+ }
+
+ b.Reset()
+ d.Execute(&b, data)
+ if got := b.String(); got != test.wantClone {
+ t.Errorf("%q: want %q, got %q", test.input, test.wantClone, got)
+ }
+ }
+}
diff --git a/libgo/go/exp/template/html/content.go b/libgo/go/exp/template/html/content.go
new file mode 100644
index 00000000000..dcaff8c15c6
--- /dev/null
+++ b/libgo/go/exp/template/html/content.go
@@ -0,0 +1,94 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "fmt"
+)
+
+// Strings of content from a trusted source.
+type (
+ // CSS encapsulates known safe content that matches any of:
+ // (1) The CSS3 stylesheet production, such as `p { color: purple }`.
+ // (2) The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.
+ // (3) CSS3 declaration productions, such as `color: red; margin: 2px`.
+ // (4) The CSS3 value production, such as `rgba(0, 0, 255, 127)`.
+ // See http://www.w3.org/TR/css3-syntax/#style
+ CSS string
+
+ // HTML encapsulates a known safe HTML document fragment.
+ // It should not be used for HTML from a third-party, or HTML with
+ // unclosed tags or comments. The outputs of a sound HTML sanitizer
+ // and a template escaped by this package are fine for use with HTML.
+ HTML string
+
+ // HTMLAttr encapsulates an HTML attribute from a trusted source,
+ // for example: ` dir="ltr"`.
+ HTMLAttr string
+
+ // JS encapsulates a known safe EcmaScript5 Expression, or example,
+ // `(x + y * z())`.
+ // Template authors are responsible for ensuring that typed expressions
+ // do not break the intended precedence and that there is no
+ // statement/expression ambiguity as when passing an expression like
+ // "{ foo: bar() }\n['foo']()", which is both a valid Expression and a
+ // valid Program with a very different meaning.
+ JS string
+
+ // JSStr encapsulates a sequence of characters meant to be embedded
+ // between quotes in a JavaScript expression.
+ // The string must match a series of StringCharacters:
+ // StringCharacter :: SourceCharacter but not `\` or LineTerminator
+ // | EscapeSequence
+ // Note that LineContinuations are not allowed.
+ // JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
+ JSStr string
+
+ // URL encapsulates a known safe URL as defined in RFC 3896.
+ // A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()`
+ // from a trusted source should go in the page, but by default dynamic
+ // `javascript:` URLs are filtered out since they are a frequently
+ // exploited injection vector.
+ URL string
+)
+
+type contentType uint8
+
+const (
+ contentTypePlain contentType = iota
+ contentTypeCSS
+ contentTypeHTML
+ contentTypeHTMLAttr
+ contentTypeJS
+ contentTypeJSStr
+ contentTypeURL
+ // contentTypeUnsafe is used in attr.go for values that affect how
+ // embedded content and network messages are formed, vetted,
+ // or interpreted; or which credentials network messages carry.
+ contentTypeUnsafe
+)
+
+// stringify converts its arguments to a string and the type of the content.
+func stringify(args ...interface{}) (string, contentType) {
+ if len(args) == 1 {
+ switch s := args[0].(type) {
+ case string:
+ return s, contentTypePlain
+ case CSS:
+ return string(s), contentTypeCSS
+ case HTML:
+ return string(s), contentTypeHTML
+ case HTMLAttr:
+ return string(s), contentTypeHTMLAttr
+ case JS:
+ return string(s), contentTypeJS
+ case JSStr:
+ return string(s), contentTypeJSStr
+ case URL:
+ return string(s), contentTypeURL
+ }
+ }
+ return fmt.Sprint(args...), contentTypePlain
+}
diff --git a/libgo/go/exp/template/html/content_test.go b/libgo/go/exp/template/html/content_test.go
new file mode 100644
index 00000000000..033dee1747c
--- /dev/null
+++ b/libgo/go/exp/template/html/content_test.go
@@ -0,0 +1,222 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "strings"
+ "template"
+ "testing"
+)
+
+func TestTypedContent(t *testing.T) {
+ data := []interface{}{
+ `<b> "foo%" O'Reilly &bar;`,
+ CSS(`a[href =~ "//example.com"]#foo`),
+ HTML(`Hello, <b>World</b> &amp;tc!`),
+ HTMLAttr(` dir="ltr"`),
+ JS(`c && alert("Hello, World!");`),
+ JSStr(`Hello, World & O'Reilly\x21`),
+ URL(`greeting=H%69&addressee=(World)`),
+ }
+
+ // For each content sensitive escaper, see how it does on
+ // each of the typed strings above.
+ tests := []struct {
+ // A template containing a single {{.}}.
+ input string
+ want []string
+ }{
+ {
+ `<style>{{.}} { color: blue }</style>`,
+ []string{
+ `ZgotmplZ`,
+ // Allowed but not escaped.
+ `a[href =~ "//example.com"]#foo`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ },
+ },
+ {
+ `<div style="{{.}}">`,
+ []string{
+ `ZgotmplZ`,
+ // Allowed and HTML escaped.
+ `a[href =~ &#34;//example.com&#34;]#foo`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ },
+ },
+ {
+ `{{.}}`,
+ []string{
+ `&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
+ `a[href =~ &#34;//example.com&#34;]#foo`,
+ // Not escaped.
+ `Hello, <b>World</b> &amp;tc!`,
+ ` dir=&#34;ltr&#34;`,
+ `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+ `Hello, World &amp; O&#39;Reilly\x21`,
+ `greeting=H%69&amp;addressee=(World)`,
+ },
+ },
+ {
+ `<a{{.}}>`,
+ []string{
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ // Allowed and HTML escaped.
+ ` dir="ltr"`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ `ZgotmplZ`,
+ },
+ },
+ {
+ `<a title={{.}}>`,
+ []string{
+ `&lt;b&gt;&#32;&#34;foo%&#34;&#32;O&#39;Reilly&#32;&amp;bar;`,
+ `a[href&#32;&#61;~&#32;&#34;//example.com&#34;]#foo`,
+ // Tags stripped, spaces escaped, entity not re-escaped.
+ `Hello,&#32;World&#32;&amp;tc!`,
+ `&#32;dir&#61;&#34;ltr&#34;`,
+ `c&#32;&amp;&amp;&#32;alert(&#34;Hello,&#32;World!&#34;);`,
+ `Hello,&#32;World&#32;&amp;&#32;O&#39;Reilly\x21`,
+ `greeting&#61;H%69&amp;addressee&#61;(World)`,
+ },
+ },
+ {
+ `<a title='{{.}}'>`,
+ []string{
+ `&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
+ `a[href =~ &#34;//example.com&#34;]#foo`,
+ // Tags stripped, entity not re-escaped.
+ `Hello, World &amp;tc!`,
+ ` dir=&#34;ltr&#34;`,
+ `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+ `Hello, World &amp; O&#39;Reilly\x21`,
+ `greeting=H%69&amp;addressee=(World)`,
+ },
+ },
+ {
+ `<textarea>{{.}}</textarea>`,
+ []string{
+ `&lt;b&gt; &#34;foo%&#34; O&#39;Reilly &amp;bar;`,
+ `a[href =~ &#34;//example.com&#34;]#foo`,
+ // Angle brackets escaped to prevent injection of close tags, entity not re-escaped.
+ `Hello, &lt;b&gt;World&lt;/b&gt; &amp;tc!`,
+ ` dir=&#34;ltr&#34;`,
+ `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+ `Hello, World &amp; O&#39;Reilly\x21`,
+ `greeting=H%69&amp;addressee=(World)`,
+ },
+ },
+ {
+ `<script>alert({{.}})</script>`,
+ []string{
+ `"\u003cb\u003e \"foo%\" O'Reilly &bar;"`,
+ `"a[href =~ \"//example.com\"]#foo"`,
+ `"Hello, \u003cb\u003eWorld\u003c/b\u003e &amp;tc!"`,
+ `" dir=\"ltr\""`,
+ // Not escaped.
+ `c && alert("Hello, World!");`,
+ // Escape sequence not over-escaped.
+ `"Hello, World & O'Reilly\x21"`,
+ `"greeting=H%69&addressee=(World)"`,
+ },
+ },
+ {
+ `<button onclick="alert({{.}})">`,
+ []string{
+ `&#34;\u003cb\u003e \&#34;foo%\&#34; O&#39;Reilly &amp;bar;&#34;`,
+ `&#34;a[href =~ \&#34;//example.com\&#34;]#foo&#34;`,
+ `&#34;Hello, \u003cb\u003eWorld\u003c/b\u003e &amp;amp;tc!&#34;`,
+ `&#34; dir=\&#34;ltr\&#34;&#34;`,
+ // Not JS escaped but HTML escaped.
+ `c &amp;&amp; alert(&#34;Hello, World!&#34;);`,
+ // Escape sequence not over-escaped.
+ `&#34;Hello, World &amp; O&#39;Reilly\x21&#34;`,
+ `&#34;greeting=H%69&amp;addressee=(World)&#34;`,
+ },
+ },
+ {
+ `<script>alert("{{.}}")</script>`,
+ []string{
+ `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
+ `a[href =~ \x22\/\/example.com\x22]#foo`,
+ `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
+ ` dir=\x22ltr\x22`,
+ `c \x26\x26 alert(\x22Hello, World!\x22);`,
+ // Escape sequence not over-escaped.
+ `Hello, World \x26 O\x27Reilly\x21`,
+ `greeting=H%69\x26addressee=(World)`,
+ },
+ },
+ {
+ `<button onclick='alert("{{.}}")'>`,
+ []string{
+ `\x3cb\x3e \x22foo%\x22 O\x27Reilly \x26bar;`,
+ `a[href =~ \x22\/\/example.com\x22]#foo`,
+ `Hello, \x3cb\x3eWorld\x3c\/b\x3e \x26amp;tc!`,
+ ` dir=\x22ltr\x22`,
+ `c \x26\x26 alert(\x22Hello, World!\x22);`,
+ // Escape sequence not over-escaped.
+ `Hello, World \x26 O\x27Reilly\x21`,
+ `greeting=H%69\x26addressee=(World)`,
+ },
+ },
+ {
+ `<a href="?q={{.}}">`,
+ []string{
+ `%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
+ `a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
+ `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
+ `%20dir%3d%22ltr%22`,
+ `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
+ `Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
+ // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is done.
+ `greeting=H%69&amp;addressee=%28World%29`,
+ },
+ },
+ {
+ `<style>body { background: url('?img={{.}}') }</style>`,
+ []string{
+ `%3cb%3e%20%22foo%25%22%20O%27Reilly%20%26bar%3b`,
+ `a%5bhref%20%3d~%20%22%2f%2fexample.com%22%5d%23foo`,
+ `Hello%2c%20%3cb%3eWorld%3c%2fb%3e%20%26amp%3btc%21`,
+ `%20dir%3d%22ltr%22`,
+ `c%20%26%26%20alert%28%22Hello%2c%20World%21%22%29%3b`,
+ `Hello%2c%20World%20%26%20O%27Reilly%5cx21`,
+ // Quotes and parens are escaped but %69 is not over-escaped. HTML escaping is not done.
+ `greeting=H%69&addressee=%28World%29`,
+ },
+ },
+ }
+
+ for _, test := range tests {
+ tmpl := template.Must(Escape(template.Must(template.New("x").Parse(test.input))))
+ pre := strings.Index(test.input, "{{.}}")
+ post := len(test.input) - (pre + 5)
+ var b bytes.Buffer
+ for i, x := range data {
+ b.Reset()
+ if err := tmpl.Execute(&b, x); err != nil {
+ t.Errorf("%q with %v: %s", test.input, x, err)
+ continue
+ }
+ if want, got := test.want[i], b.String()[pre:b.Len()-post]; want != got {
+ t.Errorf("%q with %v:\nwant\n\t%q,\ngot\n\t%q\n", test.input, x, want, got)
+ continue
+ }
+ }
+ }
+}
diff --git a/libgo/go/exp/template/html/context.go b/libgo/go/exp/template/html/context.go
index 41100688343..c44df4debc1 100644
--- a/libgo/go/exp/template/html/context.go
+++ b/libgo/go/exp/template/html/context.go
@@ -16,56 +16,176 @@ import (
// http://www.w3.org/TR/html5/the-end.html#parsing-html-fragments
// where the context element is null.
type context struct {
- state state
- delim delim
+ state state
+ delim delim
+ urlPart urlPart
+ jsCtx jsCtx
+ attr attr
+ element element
+ err *Error
}
func (c context) String() string {
- return fmt.Sprintf("context{state: %s, delim: %s", c.state, c.delim)
+ return fmt.Sprintf("{%v %v %v %v %v %v %v}", c.state, c.delim, c.urlPart, c.jsCtx, c.attr, c.element, c.err)
}
-// eq is true if the two contexts are identical field-wise.
+// eq returns whether two contexts are equal.
func (c context) eq(d context) bool {
- return c.state == d.state && c.delim == d.delim
+ return c.state == d.state &&
+ c.delim == d.delim &&
+ c.urlPart == d.urlPart &&
+ c.jsCtx == d.jsCtx &&
+ c.attr == d.attr &&
+ c.element == d.element &&
+ c.err == d.err
+}
+
+// mangle produces an identifier that includes a suffix that distinguishes it
+// from template names mangled with different contexts.
+func (c context) mangle(templateName string) string {
+ // The mangled name for the default context is the input templateName.
+ if c.state == stateText {
+ return templateName
+ }
+ s := templateName + "$htmltemplate_" + c.state.String()
+ if c.delim != 0 {
+ s += "_" + c.delim.String()
+ }
+ if c.urlPart != 0 {
+ s += "_" + c.urlPart.String()
+ }
+ if c.jsCtx != 0 {
+ s += "_" + c.jsCtx.String()
+ }
+ if c.attr != 0 {
+ s += "_" + c.attr.String()
+ }
+ if c.element != 0 {
+ s += "_" + c.element.String()
+ }
+ return s
}
// state describes a high-level HTML parser state.
//
-// It bounds the top of the element stack, and by extension the HTML
-// insertion mode, but also contains state that does not correspond to
-// anything in the HTML5 parsing algorithm because a single token
-// production in the HTML grammar may contain embedded actions in a template.
-// For instance, the quoted HTML attribute produced by
+// It bounds the top of the element stack, and by extension the HTML insertion
+// mode, but also contains state that does not correspond to anything in the
+// HTML5 parsing algorithm because a single token production in the HTML
+// grammar may contain embedded actions in a template. For instance, the quoted
+// HTML attribute produced by
// <div title="Hello {{.World}}">
// is a single token in HTML's grammar but in a template spans several nodes.
type state uint8
const (
- // statePCDATA is parsed character data. An HTML parser is in
+ // stateText is parsed character data. An HTML parser is in
// this state when its parse position is outside an HTML tag,
// directive, comment, and special element body.
- statePCDATA state = iota
+ stateText state = iota
// stateTag occurs before an HTML attribute or the end of a tag.
stateTag
- // stateURI occurs inside an HTML attribute whose content is a URI.
- stateURI
+ // stateAttrName occurs inside an attribute name.
+ // It occurs between the ^'s in ` ^name^ = value`.
+ stateAttrName
+ // stateAfterName occurs after an attr name has ended but before any
+ // equals sign. It occurs between the ^'s in ` name^ ^= value`.
+ stateAfterName
+ // stateBeforeValue occurs after the equals sign but before the value.
+ // It occurs between the ^'s in ` name =^ ^value`.
+ stateBeforeValue
+ // stateHTMLCmt occurs inside an <!-- HTML comment -->.
+ stateHTMLCmt
+ // stateRCDATA occurs inside an RCDATA element (<textarea> or <title>)
+ // as described at http://dev.w3.org/html5/spec/syntax.html#elements-0
+ stateRCDATA
+ // stateAttr occurs inside an HTML attribute whose content is text.
+ stateAttr
+ // stateURL occurs inside an HTML attribute whose content is a URL.
+ stateURL
+ // stateJS occurs inside an event handler or script element.
+ stateJS
+ // stateJSDqStr occurs inside a JavaScript double quoted string.
+ stateJSDqStr
+ // stateJSSqStr occurs inside a JavaScript single quoted string.
+ stateJSSqStr
+ // stateJSRegexp occurs inside a JavaScript regexp literal.
+ stateJSRegexp
+ // stateJSBlockCmt occurs inside a JavaScript /* block comment */.
+ stateJSBlockCmt
+ // stateJSLineCmt occurs inside a JavaScript // line comment.
+ stateJSLineCmt
+ // stateCSS occurs inside a <style> element or style attribute.
+ stateCSS
+ // stateCSSDqStr occurs inside a CSS double quoted string.
+ stateCSSDqStr
+ // stateCSSSqStr occurs inside a CSS single quoted string.
+ stateCSSSqStr
+ // stateCSSDqURL occurs inside a CSS double quoted url("...").
+ stateCSSDqURL
+ // stateCSSSqURL occurs inside a CSS single quoted url('...').
+ stateCSSSqURL
+ // stateCSSURL occurs inside a CSS unquoted url(...).
+ stateCSSURL
+ // stateCSSBlockCmt occurs inside a CSS /* block comment */.
+ stateCSSBlockCmt
+ // stateCSSLineCmt occurs inside a CSS // line comment.
+ stateCSSLineCmt
// stateError is an infectious error state outside any valid
// HTML/CSS/JS construct.
stateError
)
var stateNames = [...]string{
- statePCDATA: "statePCDATA",
- stateTag: "stateTag",
- stateURI: "stateURI",
- stateError: "stateError",
+ stateText: "stateText",
+ stateTag: "stateTag",
+ stateAttrName: "stateAttrName",
+ stateAfterName: "stateAfterName",
+ stateBeforeValue: "stateBeforeValue",
+ stateHTMLCmt: "stateHTMLCmt",
+ stateRCDATA: "stateRCDATA",
+ stateAttr: "stateAttr",
+ stateURL: "stateURL",
+ stateJS: "stateJS",
+ stateJSDqStr: "stateJSDqStr",
+ stateJSSqStr: "stateJSSqStr",
+ stateJSRegexp: "stateJSRegexp",
+ stateJSBlockCmt: "stateJSBlockCmt",
+ stateJSLineCmt: "stateJSLineCmt",
+ stateCSS: "stateCSS",
+ stateCSSDqStr: "stateCSSDqStr",
+ stateCSSSqStr: "stateCSSSqStr",
+ stateCSSDqURL: "stateCSSDqURL",
+ stateCSSSqURL: "stateCSSSqURL",
+ stateCSSURL: "stateCSSURL",
+ stateCSSBlockCmt: "stateCSSBlockCmt",
+ stateCSSLineCmt: "stateCSSLineCmt",
+ stateError: "stateError",
}
func (s state) String() string {
- if uint(s) < uint(len(stateNames)) {
+ if int(s) < len(stateNames) {
return stateNames[s]
}
- return fmt.Sprintf("illegal state %d", uint(s))
+ return fmt.Sprintf("illegal state %d", int(s))
+}
+
+// isComment is true for any state that contains content meant for template
+// authors & maintainers, not for end-users or machines.
+func isComment(s state) bool {
+ switch s {
+ case stateHTMLCmt, stateJSBlockCmt, stateJSLineCmt, stateCSSBlockCmt, stateCSSLineCmt:
+ return true
+ }
+ return false
+}
+
+// isInTag return whether s occurs solely inside an HTML tag.
+func isInTag(s state) bool {
+ switch s {
+ case stateTag, stateAttrName, stateAfterName, stateBeforeValue, stateAttr:
+ return true
+ }
+ return false
}
// delim is the delimiter that will end the current HTML attribute.
@@ -91,8 +211,129 @@ var delimNames = [...]string{
}
func (d delim) String() string {
- if uint(d) < uint(len(delimNames)) {
+ if int(d) < len(delimNames) {
return delimNames[d]
}
- return fmt.Sprintf("illegal delim %d", uint(d))
+ return fmt.Sprintf("illegal delim %d", int(d))
+}
+
+// urlPart identifies a part in an RFC 3986 hierarchical URL to allow different
+// encoding strategies.
+type urlPart uint8
+
+const (
+ // urlPartNone occurs when not in a URL, or possibly at the start:
+ // ^ in "^http://auth/path?k=v#frag".
+ urlPartNone urlPart = iota
+ // urlPartPreQuery occurs in the scheme, authority, or path; between the
+ // ^s in "h^ttp://auth/path^?k=v#frag".
+ urlPartPreQuery
+ // urlPartQueryOrFrag occurs in the query portion between the ^s in
+ // "http://auth/path?^k=v#frag^".
+ urlPartQueryOrFrag
+ // urlPartUnknown occurs due to joining of contexts both before and
+ // after the query separator.
+ urlPartUnknown
+)
+
+var urlPartNames = [...]string{
+ urlPartNone: "urlPartNone",
+ urlPartPreQuery: "urlPartPreQuery",
+ urlPartQueryOrFrag: "urlPartQueryOrFrag",
+ urlPartUnknown: "urlPartUnknown",
+}
+
+func (u urlPart) String() string {
+ if int(u) < len(urlPartNames) {
+ return urlPartNames[u]
+ }
+ return fmt.Sprintf("illegal urlPart %d", int(u))
+}
+
+// jsCtx determines whether a '/' starts a regular expression literal or a
+// division operator.
+type jsCtx uint8
+
+const (
+ // jsCtxRegexp occurs where a '/' would start a regexp literal.
+ jsCtxRegexp jsCtx = iota
+ // jsCtxDivOp occurs where a '/' would start a division operator.
+ jsCtxDivOp
+ // jsCtxUnknown occurs where a '/' is ambiguous due to context joining.
+ jsCtxUnknown
+)
+
+func (c jsCtx) String() string {
+ switch c {
+ case jsCtxRegexp:
+ return "jsCtxRegexp"
+ case jsCtxDivOp:
+ return "jsCtxDivOp"
+ case jsCtxUnknown:
+ return "jsCtxUnknown"
+ }
+ return fmt.Sprintf("illegal jsCtx %d", int(c))
+}
+
+// element identifies the HTML element when inside a start tag or special body.
+// Certain HTML element (for example <script> and <style>) have bodies that are
+// treated differently from stateText so the element type is necessary to
+// transition into the correct context at the end of a tag and to identify the
+// end delimiter for the body.
+type element uint8
+
+const (
+ // elementNone occurs outside a special tag or special element body.
+ elementNone element = iota
+ // elementScript corresponds to the raw text <script> element.
+ elementScript
+ // elementStyle corresponds to the raw text <style> element.
+ elementStyle
+ // elementTextarea corresponds to the RCDATA <textarea> element.
+ elementTextarea
+ // elementTitle corresponds to the RCDATA <title> element.
+ elementTitle
+)
+
+var elementNames = [...]string{
+ elementNone: "elementNone",
+ elementScript: "elementScript",
+ elementStyle: "elementStyle",
+ elementTextarea: "elementTextarea",
+ elementTitle: "elementTitle",
+}
+
+func (e element) String() string {
+ if int(e) < len(elementNames) {
+ return elementNames[e]
+ }
+ return fmt.Sprintf("illegal element %d", int(e))
+}
+
+// attr identifies the most recent HTML attribute when inside a start tag.
+type attr uint8
+
+const (
+ // attrNone corresponds to a normal attribute or no attribute.
+ attrNone attr = iota
+ // attrScript corresponds to an event handler attribute.
+ attrScript
+ // attrStyle corresponds to the style attribute whose value is CSS.
+ attrStyle
+ // attrURL corresponds to an attribute whose value is a URL.
+ attrURL
+)
+
+var attrNames = [...]string{
+ attrNone: "attrNone",
+ attrScript: "attrScript",
+ attrStyle: "attrStyle",
+ attrURL: "attrURL",
+}
+
+func (a attr) String() string {
+ if int(a) < len(attrNames) {
+ return attrNames[a]
+ }
+ return fmt.Sprintf("illegal attr %d", int(a))
}
diff --git a/libgo/go/exp/template/html/css.go b/libgo/go/exp/template/html/css.go
new file mode 100644
index 00000000000..c22ec6df0d0
--- /dev/null
+++ b/libgo/go/exp/template/html/css.go
@@ -0,0 +1,268 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "fmt"
+ "unicode"
+ "utf8"
+)
+
+// endsWithCSSKeyword returns whether b ends with an ident that
+// case-insensitively matches the lower-case kw.
+func endsWithCSSKeyword(b []byte, kw string) bool {
+ i := len(b) - len(kw)
+ if i < 0 {
+ // Too short.
+ return false
+ }
+ if i != 0 {
+ r, _ := utf8.DecodeLastRune(b[:i])
+ if isCSSNmchar(r) {
+ // Too long.
+ return false
+ }
+ }
+ // Many CSS keywords, such as "!important" can have characters encoded,
+ // but the URI production does not allow that according to
+ // http://www.w3.org/TR/css3-syntax/#TOK-URI
+ // This does not attempt to recognize encoded keywords. For example,
+ // given "\75\72\6c" and "url" this return false.
+ return string(bytes.ToLower(b[i:])) == kw
+}
+
+// isCSSNmchar returns whether rune is allowed anywhere in a CSS identifier.
+func isCSSNmchar(rune int) bool {
+ // Based on the CSS3 nmchar production but ignores multi-rune escape
+ // sequences.
+ // http://www.w3.org/TR/css3-syntax/#SUBTOK-nmchar
+ return 'a' <= rune && rune <= 'z' ||
+ 'A' <= rune && rune <= 'Z' ||
+ '0' <= rune && rune <= '9' ||
+ '-' == rune ||
+ '_' == rune ||
+ // Non-ASCII cases below.
+ 0x80 <= rune && rune <= 0xd7ff ||
+ 0xe000 <= rune && rune <= 0xfffd ||
+ 0x10000 <= rune && rune <= 0x10ffff
+}
+
+// decodeCSS decodes CSS3 escapes given a sequence of stringchars.
+// If there is no change, it returns the input, otherwise it returns a slice
+// backed by a new array.
+// http://www.w3.org/TR/css3-syntax/#SUBTOK-stringchar defines stringchar.
+func decodeCSS(s []byte) []byte {
+ i := bytes.IndexByte(s, '\\')
+ if i == -1 {
+ return s
+ }
+ // The UTF-8 sequence for a codepoint is never longer than 1 + the
+ // number hex digits need to represent that codepoint, so len(s) is an
+ // upper bound on the output length.
+ b := make([]byte, 0, len(s))
+ for len(s) != 0 {
+ i := bytes.IndexByte(s, '\\')
+ if i == -1 {
+ i = len(s)
+ }
+ b, s = append(b, s[:i]...), s[i:]
+ if len(s) < 2 {
+ break
+ }
+ // http://www.w3.org/TR/css3-syntax/#SUBTOK-escape
+ // escape ::= unicode | '\' [#x20-#x7E#x80-#xD7FF#xE000-#xFFFD#x10000-#x10FFFF]
+ if isHex(s[1]) {
+ // http://www.w3.org/TR/css3-syntax/#SUBTOK-unicode
+ // unicode ::= '\' [0-9a-fA-F]{1,6} wc?
+ j := 2
+ for j < len(s) && j < 7 && isHex(s[j]) {
+ j++
+ }
+ rune := hexDecode(s[1:j])
+ if rune > unicode.MaxRune {
+ rune, j = rune/16, j-1
+ }
+ n := utf8.EncodeRune(b[len(b):cap(b)], rune)
+ // The optional space at the end allows a hex
+ // sequence to be followed by a literal hex.
+ // string(decodeCSS([]byte(`\A B`))) == "\nB"
+ b, s = b[:len(b)+n], skipCSSSpace(s[j:])
+ } else {
+ // `\\` decodes to `\` and `\"` to `"`.
+ _, n := utf8.DecodeRune(s[1:])
+ b, s = append(b, s[1:1+n]...), s[1+n:]
+ }
+ }
+ return b
+}
+
+// isHex returns whether the given character is a hex digit.
+func isHex(c byte) bool {
+ return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'
+}
+
+// hexDecode decodes a short hex digit sequence: "10" -> 16.
+func hexDecode(s []byte) int {
+ n := 0
+ for _, c := range s {
+ n <<= 4
+ switch {
+ case '0' <= c && c <= '9':
+ n |= int(c - '0')
+ case 'a' <= c && c <= 'f':
+ n |= int(c-'a') + 10
+ case 'A' <= c && c <= 'F':
+ n |= int(c-'A') + 10
+ default:
+ panic(fmt.Sprintf("Bad hex digit in %q", s))
+ }
+ }
+ return n
+}
+
+// skipCSSSpace returns a suffix of c, skipping over a single space.
+func skipCSSSpace(c []byte) []byte {
+ if len(c) == 0 {
+ return c
+ }
+ // wc ::= #x9 | #xA | #xC | #xD | #x20
+ switch c[0] {
+ case '\t', '\n', '\f', ' ':
+ return c[1:]
+ case '\r':
+ // This differs from CSS3's wc production because it contains a
+ // probable spec error whereby wc contains all the single byte
+ // sequences in nl (newline) but not CRLF.
+ if len(c) >= 2 && c[1] == '\n' {
+ return c[2:]
+ }
+ return c[1:]
+ }
+ return c
+}
+
+// isCSSSpace returns whether b is a CSS space char as defined in wc.
+func isCSSSpace(b byte) bool {
+ switch b {
+ case '\t', '\n', '\f', '\r', ' ':
+ return true
+ }
+ return false
+}
+
+// cssEscaper escapes HTML and CSS special characters using \<hex>+ escapes.
+func cssEscaper(args ...interface{}) string {
+ s, _ := stringify(args...)
+ var b bytes.Buffer
+ written := 0
+ for i, r := range s {
+ var repl string
+ switch r {
+ case 0:
+ repl = `\0`
+ case '\t':
+ repl = `\9`
+ case '\n':
+ repl = `\a`
+ case '\f':
+ repl = `\c`
+ case '\r':
+ repl = `\d`
+ // Encode HTML specials as hex so the output can be embedded
+ // in HTML attributes without further encoding.
+ case '"':
+ repl = `\22`
+ case '&':
+ repl = `\26`
+ case '\'':
+ repl = `\27`
+ case '(':
+ repl = `\28`
+ case ')':
+ repl = `\29`
+ case '+':
+ repl = `\2b`
+ case '/':
+ repl = `\2f`
+ case ':':
+ repl = `\3a`
+ case ';':
+ repl = `\3b`
+ case '<':
+ repl = `\3c`
+ case '>':
+ repl = `\3e`
+ case '\\':
+ repl = `\\`
+ case '{':
+ repl = `\7b`
+ case '}':
+ repl = `\7d`
+ default:
+ continue
+ }
+ b.WriteString(s[written:i])
+ b.WriteString(repl)
+ written = i + utf8.RuneLen(r)
+ if repl != `\\` && (written == len(s) || isHex(s[written]) || isCSSSpace(s[written])) {
+ b.WriteByte(' ')
+ }
+ }
+ if written == 0 {
+ return s
+ }
+ b.WriteString(s[written:])
+ return b.String()
+}
+
+var expressionBytes = []byte("expression")
+var mozBindingBytes = []byte("mozbinding")
+
+// cssValueFilter allows innocuous CSS values in the output including CSS
+// quantities (10px or 25%), ID or class literals (#foo, .bar), keyword values
+// (inherit, blue), and colors (#888).
+// It filters out unsafe values, such as those that affect token boundaries,
+// and anything that might execute scripts.
+func cssValueFilter(args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeCSS {
+ return s
+ }
+ b, id := decodeCSS([]byte(s)), make([]byte, 0, 64)
+
+ // CSS3 error handling is specified as honoring string boundaries per
+ // http://www.w3.org/TR/css3-syntax/#error-handling :
+ // Malformed declarations. User agents must handle unexpected
+ // tokens encountered while parsing a declaration by reading until
+ // the end of the declaration, while observing the rules for
+ // matching pairs of (), [], {}, "", and '', and correctly handling
+ // escapes. For example, a malformed declaration may be missing a
+ // property, colon (:) or value.
+ // So we need to make sure that values do not have mismatched bracket
+ // or quote characters to prevent the browser from restarting parsing
+ // inside a string that might embed JavaScript source.
+ for i, c := range b {
+ switch c {
+ case 0, '"', '\'', '(', ')', '/', ';', '@', '[', '\\', ']', '`', '{', '}':
+ return filterFailsafe
+ case '-':
+ // Disallow <!-- or -->.
+ // -- should not appear in valid identifiers.
+ if i != 0 && '-' == b[i-1] {
+ return filterFailsafe
+ }
+ default:
+ if c < 0x80 && isCSSNmchar(int(c)) {
+ id = append(id, c)
+ }
+ }
+ }
+ id = bytes.ToLower(id)
+ if bytes.Index(id, expressionBytes) != -1 || bytes.Index(id, mozBindingBytes) != -1 {
+ return filterFailsafe
+ }
+ return string(b)
+}
diff --git a/libgo/go/exp/template/html/css_test.go b/libgo/go/exp/template/html/css_test.go
new file mode 100644
index 00000000000..5f633e89442
--- /dev/null
+++ b/libgo/go/exp/template/html/css_test.go
@@ -0,0 +1,281 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "strconv"
+ "strings"
+ "testing"
+)
+
+func TestEndsWithCSSKeyword(t *testing.T) {
+ tests := []struct {
+ css, kw string
+ want bool
+ }{
+ {"", "url", false},
+ {"url", "url", true},
+ {"URL", "url", true},
+ {"Url", "url", true},
+ {"url", "important", false},
+ {"important", "important", true},
+ {"image-url", "url", false},
+ {"imageurl", "url", false},
+ {"image url", "url", true},
+ }
+ for _, test := range tests {
+ got := endsWithCSSKeyword([]byte(test.css), test.kw)
+ if got != test.want {
+ t.Errorf("want %t but got %t for css=%v, kw=%v", test.want, got, test.css, test.kw)
+ }
+ }
+}
+
+func TestIsCSSNmchar(t *testing.T) {
+ tests := []struct {
+ rune int
+ want bool
+ }{
+ {0, false},
+ {'0', true},
+ {'9', true},
+ {'A', true},
+ {'Z', true},
+ {'a', true},
+ {'z', true},
+ {'_', true},
+ {'-', true},
+ {':', false},
+ {';', false},
+ {' ', false},
+ {0x7f, false},
+ {0x80, true},
+ {0x1234, true},
+ {0xd800, false},
+ {0xdc00, false},
+ {0xfffe, false},
+ {0x10000, true},
+ {0x110000, false},
+ }
+ for _, test := range tests {
+ got := isCSSNmchar(test.rune)
+ if got != test.want {
+ t.Errorf("%q: want %t but got %t", string(test.rune), test.want, got)
+ }
+ }
+}
+
+func TestDecodeCSS(t *testing.T) {
+ tests := []struct {
+ css, want string
+ }{
+ {``, ``},
+ {`foo`, `foo`},
+ {`foo\`, `foo`},
+ {`foo\\`, `foo\`},
+ {`\`, ``},
+ {`\A`, "\n"},
+ {`\a`, "\n"},
+ {`\0a`, "\n"},
+ {`\00000a`, "\n"},
+ {`\000000a`, "\u0000a"},
+ {`\1234 5`, "\u1234" + "5"},
+ {`\1234\20 5`, "\u1234" + " 5"},
+ {`\1234\A 5`, "\u1234" + "\n5"},
+ {"\\1234\t5", "\u1234" + "5"},
+ {"\\1234\n5", "\u1234" + "5"},
+ {"\\1234\r\n5", "\u1234" + "5"},
+ {`\12345`, "\U00012345"},
+ {`\\`, `\`},
+ {`\\ `, `\ `},
+ {`\"`, `"`},
+ {`\'`, `'`},
+ {`\.`, `.`},
+ {`\. .`, `. .`},
+ {
+ `The \3c i\3equick\3c/i\3e,\d\A\3cspan style=\27 color:brown\27\3e brown\3c/span\3e fox jumps\2028over the \3c canine class=\22lazy\22 \3e dog\3c/canine\3e`,
+ "The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>",
+ },
+ }
+ for _, test := range tests {
+ got1 := string(decodeCSS([]byte(test.css)))
+ if got1 != test.want {
+ t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.css, test.want, got1)
+ }
+ recoded := cssEscaper(got1)
+ if got2 := string(decodeCSS([]byte(recoded))); got2 != test.want {
+ t.Errorf("%q: escape & decode not dual for %q", test.css, recoded)
+ }
+ }
+}
+
+func TestHexDecode(t *testing.T) {
+ for i := 0; i < 0x200000; i += 101 /* coprime with 16 */ {
+ s := strconv.Itob(i, 16)
+ if got := hexDecode([]byte(s)); got != i {
+ t.Errorf("%s: want %d but got %d", s, i, got)
+ }
+ s = strings.ToUpper(s)
+ if got := hexDecode([]byte(s)); got != i {
+ t.Errorf("%s: want %d but got %d", s, i, got)
+ }
+ }
+}
+
+func TestSkipCSSSpace(t *testing.T) {
+ tests := []struct {
+ css, want string
+ }{
+ {"", ""},
+ {"foo", "foo"},
+ {"\n", ""},
+ {"\r\n", ""},
+ {"\r", ""},
+ {"\t", ""},
+ {" ", ""},
+ {"\f", ""},
+ {" foo", "foo"},
+ {" foo", " foo"},
+ {`\20`, `\20`},
+ }
+ for _, test := range tests {
+ got := string(skipCSSSpace([]byte(test.css)))
+ if got != test.want {
+ t.Errorf("%q: want %q but got %q", test.css, test.want, got)
+ }
+ }
+}
+
+func TestCSSEscaper(t *testing.T) {
+ input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ ` !"#$%&'()*+,-./` +
+ `0123456789:;<=>?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ[\]^_` +
+ "`abcdefghijklmno" +
+ "pqrstuvwxyz{|}~\x7f" +
+ "\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+ want := ("\\0\x01\x02\x03\x04\x05\x06\x07" +
+ "\x08\\9 \\a\x0b\\c \\d\x0E\x0F" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17" +
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ ` !\22#$%\26\27\28\29*\2b,-.\2f ` +
+ `0123456789\3a\3b\3c=\3e?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ[\\]^_` +
+ "`abcdefghijklmno" +
+ `pqrstuvwxyz\7b|\7d~` + "\u007f" +
+ "\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+ got := cssEscaper(input)
+ if got != want {
+ t.Errorf("encode: want\n\t%q\nbut got\n\t%q", want, got)
+ }
+
+ got = string(decodeCSS([]byte(got)))
+ if input != got {
+ t.Errorf("decode: want\n\t%q\nbut got\n\t%q", input, got)
+ }
+}
+
+func TestCSSValueFilter(t *testing.T) {
+ tests := []struct {
+ css, want string
+ }{
+ {"", ""},
+ {"foo", "foo"},
+ {"0", "0"},
+ {"0px", "0px"},
+ {"-5px", "-5px"},
+ {"1.25in", "1.25in"},
+ {"+.33em", "+.33em"},
+ {"100%", "100%"},
+ {"12.5%", "12.5%"},
+ {".foo", ".foo"},
+ {"#bar", "#bar"},
+ {"corner-radius", "corner-radius"},
+ {"-moz-corner-radius", "-moz-corner-radius"},
+ {"#000", "#000"},
+ {"#48f", "#48f"},
+ {"#123456", "#123456"},
+ {"U+00-FF, U+980-9FF", "U+00-FF, U+980-9FF"},
+ {"color: red", "color: red"},
+ {"<!--", "ZgotmplZ"},
+ {"-->", "ZgotmplZ"},
+ {"<![CDATA[", "ZgotmplZ"},
+ {"]]>", "ZgotmplZ"},
+ {"</style", "ZgotmplZ"},
+ {`"`, "ZgotmplZ"},
+ {`'`, "ZgotmplZ"},
+ {"`", "ZgotmplZ"},
+ {"\x00", "ZgotmplZ"},
+ {"/* foo */", "ZgotmplZ"},
+ {"//", "ZgotmplZ"},
+ {"[href=~", "ZgotmplZ"},
+ {"expression(alert(1337))", "ZgotmplZ"},
+ {"-expression(alert(1337))", "ZgotmplZ"},
+ {"expression", "ZgotmplZ"},
+ {"Expression", "ZgotmplZ"},
+ {"EXPRESSION", "ZgotmplZ"},
+ {"-moz-binding", "ZgotmplZ"},
+ {"-expr\x00ession(alert(1337))", "ZgotmplZ"},
+ {`-expr\0ession(alert(1337))`, "ZgotmplZ"},
+ {`-express\69on(alert(1337))`, "ZgotmplZ"},
+ {`-express\69 on(alert(1337))`, "ZgotmplZ"},
+ {`-exp\72 ession(alert(1337))`, "ZgotmplZ"},
+ {`-exp\52 ession(alert(1337))`, "ZgotmplZ"},
+ {`-exp\000052 ession(alert(1337))`, "ZgotmplZ"},
+ {`-expre\0000073sion`, "-expre\x073sion"},
+ {`@import url evil.css`, "ZgotmplZ"},
+ }
+ for _, test := range tests {
+ got := cssValueFilter(test.css)
+ if got != test.want {
+ t.Errorf("%q: want %q but got %q", test.css, test.want, got)
+ }
+ }
+}
+
+func BenchmarkCSSEscaper(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ cssEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+ }
+}
+
+func BenchmarkCSSEscaperNoSpecials(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ cssEscaper("The quick, brown fox jumps over the lazy dog.")
+ }
+}
+
+func BenchmarkDecodeCSS(b *testing.B) {
+ s := []byte(`The \3c i\3equick\3c/i\3e,\d\A\3cspan style=\27 color:brown\27\3e brown\3c/span\3e fox jumps\2028over the \3c canine class=\22lazy\22 \3edog\3c/canine\3e`)
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ decodeCSS(s)
+ }
+}
+
+func BenchmarkDecodeCSSNoSpecials(b *testing.B) {
+ s := []byte("The quick, brown fox jumps over the lazy dog.")
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ decodeCSS(s)
+ }
+}
+
+func BenchmarkCSSValueFilter(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ cssValueFilter(` e\78preS\0Sio/**/n(alert(1337))`)
+ }
+}
+
+func BenchmarkCSSValueFilterOk(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ cssValueFilter(`Times New Roman`)
+ }
+}
diff --git a/libgo/go/exp/template/html/doc.go b/libgo/go/exp/template/html/doc.go
new file mode 100644
index 00000000000..a9b78ca5157
--- /dev/null
+++ b/libgo/go/exp/template/html/doc.go
@@ -0,0 +1,190 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package html is a specialization of package template that automates the
+construction of HTML output that is safe against code injection.
+
+
+Introduction
+
+To use this package, invoke the standard template package to parse a template
+set, and then use this package’s EscapeSet function to secure the set.
+The arguments to EscapeSet are the template set and the names of all templates
+that will be passed to Execute.
+
+ set, err := new(template.Set).Parse(...)
+ set, err = EscapeSet(set, "templateName0", ...)
+
+If successful, set will now be injection-safe. Otherwise, the returned set will
+be nil and an error, described below, will explain the problem.
+
+The template names do not need to include helper templates but should include
+all names x used thus:
+
+ set.Execute(out, x, ...)
+
+EscapeSet modifies the named templates in place to treat data values as plain
+text safe for embedding in an HTML document. The escaping is contextual, so
+actions can appear within JavaScript, CSS, and URI contexts without introducing'hazards.
+
+The security model used by this package assumes that template authors are
+trusted, while Execute's data parameter is not. More details are provided below.
+
+Example
+
+ tmpls, err := new(template.Set).Parse(`{{define "t'}}Hello, {{.}}!{{end}}`)
+
+when used by itself
+
+ tmpls.Execute(out, "t", "<script>alert('you have been pwned')</script>")
+
+produces
+
+ Hello, <script>alert('you have been pwned')</script>!
+
+but after securing with EscapeSet like this,
+
+ tmpls, err := EscapeSet(tmpls, "t")
+ tmpls.Execute(out, "t", ...)
+
+produces the safe, escaped HTML output
+
+ Hello, &lt;script&gt;alert('you have been pwned')&lt;/script&gt;!
+
+
+Contexts
+
+EscapeSet understands HTML, CSS, JavaScript, and URIs. It adds sanitizing
+functions to each simple action pipeline, so given the excerpt
+
+ <a href="/search?q={{.}}">{{.}}</a>
+
+EscapeSet will rewrite each {{.}} to add escaping functions where necessary,
+in this case,
+
+ <a href="/search?q={{. | urlquery}}">{{. | html}}</a>
+
+
+Errors
+
+See the documentation of ErrorCode for details.
+
+
+A fuller picture
+
+The rest of this package comment may be skipped on first reading; it includes
+details necessary to understand escaping contexts and error messages. Most users
+will not need to understand these details.
+
+
+Contexts
+
+Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
+how {{.}} appears when used in the context to the left.
+
+Context {{.}} After
+{{.}} O'Reilly: How are &lt;i&gt;you&lt;/i&gt;?
+<a title='{{.}}'> O&#39;Reilly: How are you?
+<a href="/{{.}}"> O&#39;Reilly: How are %3ci%3eyou%3c/i%3e?
+<a href="?q={{.}}"> O&#39;Reilly%3a%20How%20are%3ci%3e...%3f
+<a onx='f("{{.}}")'> O\x27Reilly: How are \x3ci\x3eyou...?
+<a onx='f({{.}})'> "O\x27Reilly: How are \x3ci\x3eyou...?"
+<a onx='pattern = /{{.}}/;'> O\x27Reilly: How are \x3ci\x3eyou...\x3f
+
+If used in an unsafe context, then the value might be filtered out:
+
+Context {{.}} After
+<a href="{{.}}"> #ZgotmplZ
+
+since "O'Reilly:" is not an allowed protocol like "http:".
+
+
+If {{.}} is the innocuous word, `left`, then it can appear more widely,
+
+Context {{.}} After
+{{.}} left
+<a title='{{.}}'> left
+<a href='{{.}}'> left
+<a href='/{{.}}'> left
+<a href='?dir={{.}}'> left
+<a style="border-{{.}}: 4px"> left
+<a style="align: {{.}}"> left
+<a style="background: '{{.}}'> left
+<a style="background: url('{{.}}')> left
+<style>p.{{.}} {color:red}</style> left
+
+Non-string values can be used in JavaScript contexts.
+If {{.}} is
+
+ []struct{A,B string}{ "foo", "bar" }
+
+in the escaped template
+
+ <script>var pair = {{.}};</script>
+
+then the template output is
+
+ <script>var pair = {"A": "foo", "B": "bar"};</script>
+
+See package json to understand how non-string content is marshalled for
+embedding in JavaScript contexts.
+
+
+Typed Strings
+
+By default, EscapeSet assumes all pipelines produce a plain text string. It
+adds escaping pipeline stages necessary to correctly and safely embed that
+plain text string in the appropriate context.
+
+When a data value is not plain text, you can make sure it is not over-escaped
+by marking it with its type.
+
+Types HTML, JS, URL, and others from content.go can carry safe content that is
+exempted from escaping.
+
+The template
+
+ Hello, {{.}}!
+
+can be invoked with
+
+ tmpl.Execute(out, HTML(`<b>World</b>`))
+
+to produce
+
+ Hello, <b>World</b>!
+
+instead of the
+
+ Hello, &lt;b&gt;World&lt;b&gt;!
+
+that would have been produced if {{.}} was a regular string.
+
+
+Security Model
+
+http://js-quasis-libraries-and-repl.googlecode.com/svn/trunk/safetemplate.html#problem_definition defines "safe" as used by this package.
+
+This package assumes that template authors are trusted, that Execute's data
+parameter is not, and seeks to preserve the properties below in the face
+of untrusted data:
+
+Structure Preservation Property
+"... when a template author writes an HTML tag in a safe templating language,
+the browser will interpret the corresponding portion of the output as a tag
+regardless of the values of untrusted data, and similarly for other structures
+such as attribute boundaries and JS and CSS string boundaries."
+
+Code Effect Property
+"... only code specified by the template author should run as a result of
+injecting the template output into a page and all code specified by the
+template author should run as a result of the same."
+
+Least Surprise Property
+"A developer (or code reviewer) familiar with HTML, CSS, and JavaScript;
+who knows that EscapeSet is applied should be able to look at a {{.}}
+and correctly infer what sanitization happens."
+*/
+package html
diff --git a/libgo/go/exp/template/html/error.go b/libgo/go/exp/template/html/error.go
new file mode 100644
index 00000000000..5515bfe68dd
--- /dev/null
+++ b/libgo/go/exp/template/html/error.go
@@ -0,0 +1,213 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "fmt"
+)
+
+// Error describes a problem encountered during template Escaping.
+type Error struct {
+ // ErrorCode describes the kind of error.
+ ErrorCode ErrorCode
+ // Name is the name of the template in which the error was encountered.
+ Name string
+ // Line is the line number of the error in the template source or 0.
+ Line int
+ // Description is a human-readable description of the problem.
+ Description string
+}
+
+// ErrorCode is a code for a kind of error.
+type ErrorCode int
+
+// We define codes for each error that manifests while escaping templates, but
+// escaped templates may also fail at runtime.
+//
+// Output: "ZgotmplZ"
+// Example:
+// <img src="{{.X}}">
+// where {{.X}} evaluates to `javascript:...`
+// Discussion:
+// "ZgotmplZ" is a special value that indicates that unsafe content reached a
+// CSS or URL context at runtime. The output of the example will be
+// <img src="#ZgotmplZ">
+// If the data comes from a trusted source, use content types to exempt it
+// from filtering: URL(`javascript:...`).
+const (
+ // OK indicates the lack of an error.
+ OK ErrorCode = iota
+
+ // ErrAmbigContext: "... appears in an ambiguous URL context"
+ // Example:
+ // <a href="
+ // {{if .C}}
+ // /path/
+ // {{else}}
+ // /search?q=
+ // {{end}}
+ // {{.X}}
+ // ">
+ // Discussion:
+ // {{.X}} is in an ambiguous URL context since, depending on {{.C}},
+ // it may be either a URL suffix or a query parameter.
+ // Moving {{.X}} into the condition removes the ambiguity:
+ // <a href="{{if .C}}/path/{{.X}}{{else}}/search?q={{.X}}">
+ ErrAmbigContext
+
+ // ErrBadHTML: "expected space, attr name, or end of tag, but got ...",
+ // "... in unquoted attr", "... in attribute name"
+ // Example:
+ // <a href = /search?q=foo>
+ // <href=foo>
+ // <form na<e=...>
+ // <option selected<
+ // Discussion:
+ // This is often due to a typo in an HTML element, but some runes
+ // are banned in tag names, attribute names, and unquoted attribute
+ // values because they can tickle parser ambiguities.
+ // Quoting all attributes is the best policy.
+ ErrBadHTML
+
+ // ErrBranchEnd: "{{if}} branches end in different contexts"
+ // Example:
+ // {{if .C}}<a href="{{end}}{{.X}}
+ // Discussion:
+ // EscapeSet statically examines each possible path when it encounters
+ // a {{if}}, {{range}}, or {{with}} to escape any following pipelines.
+ // The example is ambiguous since {{.X}} might be an HTML text node,
+ // or a URL prefix in an HTML attribute. EscapeSet needs to understand
+ // the context of {{.X}} to escape it, but that depends on the
+ // run-time value of {{.C}}.
+ //
+ // The problem is usually something like missing quotes or angle
+ // brackets, or can be avoided by refactoring to put the two contexts
+ // into different branches of an if, range or with. If the problem
+ // is in a {{range}} over a collection that should never be empty,
+ // adding a dummy {{else}} can help.
+ ErrBranchEnd
+
+ // ErrEndContext: "... ends in a non-text context: ..."
+ // Examples:
+ // <div
+ // <div title="no close quote>
+ // <script>f()
+ // Discussion:
+ // EscapeSet assumes the ouput is a DocumentFragment of HTML.
+ // Templates that end without closing tags will trigger this error.
+ // Templates that produce incomplete Fragments should not be named
+ // in the call to EscapeSet.
+ //
+ // If you have a helper template in your set that is not meant to
+ // produce a document fragment, then do not pass its name to
+ // EscapeSet(set, ...names).
+ //
+ // {{define "main"}} <script>{{template "helper"}}</script> {{end}}
+ // {{define "helper"}} document.write(' <div title=" ') {{end}}
+ //
+ // "helper" does not produce a valid document fragment, though it does
+ // produce a valid JavaScript Program.
+ ErrEndContext
+
+ // ErrNoNames: "must specify names of top level templates"
+ //
+ // EscapeSet does not assume that all templates in a set produce HTML.
+ // Some may be helpers that produce snippets of other languages.
+ // Passing in no template names is most likely an error,
+ // so EscapeSet(set) will panic.
+ // If you call EscapeSet with a slice of names, guard it with len:
+ //
+ // if len(names) != 0 {
+ // set, err := EscapeSet(set, ...names)
+ // }
+ ErrNoNames
+
+ // ErrNoSuchTemplate: "no such template ..."
+ // Examples:
+ // {{define "main"}}<div {{template "attrs"}}>{{end}}
+ // {{define "attrs"}}href="{{.URL}}"{{end}}
+ // Discussion:
+ // EscapeSet looks through template calls to compute the context.
+ // Here the {{.URL}} in "attrs" must be treated as a URL when called
+ // from "main", but if "attrs" is not in set when
+ // EscapeSet(&set, "main") is called, this error will arise.
+ ErrNoSuchTemplate
+
+ // ErrOutputContext: "cannot compute output context for template ..."
+ // Examples:
+ // {{define "t"}}{{if .T}}{{template "t" .T}}{{end}}{{.H}}",{{end}}
+ // Discussion:
+ // A recursive template does not end in the same context in which it
+ // starts, and a reliable output context cannot be computed.
+ // Look for typos in the named template.
+ // If the template should not be called in the named start context,
+ // look for calls to that template in unexpected contexts.
+ // Maybe refactor recursive templates to not be recursive.
+ ErrOutputContext
+
+ // ErrPartialCharset: "unfinished JS regexp charset in ..."
+ // Example:
+ // <script>var pattern = /foo[{{.Chars}}]/</script>
+ // Discussion:
+ // EscapeSet does not support interpolation into regular expression
+ // literal character sets.
+ ErrPartialCharset
+
+ // ErrPartialEscape: "unfinished escape sequence in ..."
+ // Example:
+ // <script>alert("\{{.X}}")</script>
+ // Discussion:
+ // EscapeSet does not support actions following a backslash.
+ // This is usually an error and there are better solutions; for
+ // our example
+ // <script>alert("{{.X}}")</script>
+ // should work, and if {{.X}} is a partial escape sequence such as
+ // "xA0", mark the whole sequence as safe content: JSStr(`\xA0`)
+ ErrPartialEscape
+
+ // ErrRangeLoopReentry: "on range loop re-entry: ..."
+ // Example:
+ // {{range .}}<p class={{.}}{{end}}
+ // Discussion:
+ // If an iteration through a range would cause it to end in a
+ // different context than an earlier pass, there is no single context.
+ // In the example, the <p> tag is missing a '>'.
+ // EscapeSet cannot tell whether {{.}} is meant to be an HTML class or
+ // the content of a broken <p> element and complains because the
+ // second iteration would produce something like
+ //
+ // <p class=foo<p class=bar
+ ErrRangeLoopReentry
+
+ // ErrSlashAmbig: '/' could start a division or regexp.
+ // Example:
+ // <script>
+ // {{if .C}}var x = 1{{end}}
+ // /-{{.N}}/i.test(x) ? doThis : doThat();
+ // </script>
+ // Discussion:
+ // The example above could produce `var x = 1/-2/i.test(s)...`
+ // in which the first '/' is a mathematical division operator or it
+ // could produce `/-2/i.test(s)` in which the first '/' starts a
+ // regexp literal.
+ // Look for missing semicolons inside branches, and maybe add
+ // parentheses to make it clear which interpretation you intend.
+ ErrSlashAmbig
+)
+
+func (e *Error) String() string {
+ if e.Line != 0 {
+ return fmt.Sprintf("exp/template/html:%s:%d: %s", e.Name, e.Line, e.Description)
+ } else if e.Name != "" {
+ return fmt.Sprintf("exp/template/html:%s: %s", e.Name, e.Description)
+ }
+ return "exp/template/html: " + e.Description
+}
+
+// errorf creates an error given a format string f and args.
+// The template Name still needs to be supplied.
+func errorf(k ErrorCode, line int, f string, args ...interface{}) *Error {
+ return &Error{k, "", line, fmt.Sprintf(f, args...)}
+}
diff --git a/libgo/go/exp/template/html/escape.go b/libgo/go/exp/template/html/escape.go
index e0e87b98d04..74abccecddf 100644
--- a/libgo/go/exp/template/html/escape.go
+++ b/libgo/go/exp/template/html/escape.go
@@ -2,104 +2,760 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package html is a specialization of exp/template that automates the
-// construction of safe HTML output.
-// At the moment, the escaping is naive. All dynamic content is assumed to be
-// plain text interpolated in an HTML PCDATA context.
package html
import (
+ "bytes"
+ "fmt"
+ "html"
+ "os"
"template"
"template/parse"
)
-// Escape rewrites each action in the template to guarantee the output is
-// HTML-escaped.
-func Escape(t *template.Template) {
- // If the parser shares trees based on common-subexpression
- // joining then we will need to avoid multiply escaping the same action.
- escapeListNode(t.Tree.Root)
+// Escape rewrites each action in the template to guarantee that the output is
+// properly escaped.
+func Escape(t *template.Template) (*template.Template, os.Error) {
+ var s template.Set
+ s.Add(t)
+ if _, err := EscapeSet(&s, t.Name()); err != nil {
+ return nil, err
+ }
+ // TODO: if s contains cloned dependencies due to self-recursion
+ // cross-context, error out.
+ return t, nil
}
-// escapeNode dispatches to escape<NodeType> helpers by type.
-func escapeNode(node parse.Node) {
- switch n := node.(type) {
- case *parse.ListNode:
- escapeListNode(n)
- case *parse.TextNode:
- // Nothing to do.
+// EscapeSet rewrites the template set to guarantee that the output of any of
+// the named templates is properly escaped.
+// Names should include the names of all templates that might be Executed but
+// need not include helper templates.
+// If no error is returned, then the named templates have been modified.
+// Otherwise the named templates have been rendered unusable.
+func EscapeSet(s *template.Set, names ...string) (*template.Set, os.Error) {
+ if len(names) == 0 {
+ // TODO: Maybe add a method to Set to enumerate template names
+ // and use those instead.
+ return nil, &Error{ErrNoNames, "", 0, "must specify names of top level templates"}
+ }
+ e := newEscaper(s)
+ for _, name := range names {
+ c, _ := e.escapeTree(context{}, name, 0)
+ var err os.Error
+ if c.err != nil {
+ err, c.err.Name = c.err, name
+ } else if c.state != stateText {
+ err = &Error{ErrEndContext, name, 0, fmt.Sprintf("ends in a non-text context: %v", c)}
+ }
+ if err != nil {
+ // Prevent execution of unsafe templates.
+ for _, name := range names {
+ if t := s.Template(name); t != nil {
+ t.Tree = nil
+ }
+ }
+ return nil, err
+ }
+ }
+ e.commit()
+ return s, nil
+}
+
+// funcMap maps command names to functions that render their inputs safe.
+var funcMap = template.FuncMap{
+ "exp_template_html_attrescaper": attrEscaper,
+ "exp_template_html_commentescaper": commentEscaper,
+ "exp_template_html_cssescaper": cssEscaper,
+ "exp_template_html_cssvaluefilter": cssValueFilter,
+ "exp_template_html_htmlnamefilter": htmlNameFilter,
+ "exp_template_html_htmlescaper": htmlEscaper,
+ "exp_template_html_jsregexpescaper": jsRegexpEscaper,
+ "exp_template_html_jsstrescaper": jsStrEscaper,
+ "exp_template_html_jsvalescaper": jsValEscaper,
+ "exp_template_html_nospaceescaper": htmlNospaceEscaper,
+ "exp_template_html_rcdataescaper": rcdataEscaper,
+ "exp_template_html_urlescaper": urlEscaper,
+ "exp_template_html_urlfilter": urlFilter,
+ "exp_template_html_urlnormalizer": urlNormalizer,
+}
+
+// equivEscapers matches contextual escapers to equivalent template builtins.
+var equivEscapers = map[string]string{
+ "exp_template_html_attrescaper": "html",
+ "exp_template_html_htmlescaper": "html",
+ "exp_template_html_nospaceescaper": "html",
+ "exp_template_html_rcdataescaper": "html",
+ "exp_template_html_urlescaper": "urlquery",
+ "exp_template_html_urlnormalizer": "urlquery",
+}
+
+// escaper collects type inferences about templates and changes needed to make
+// templates injection safe.
+type escaper struct {
+ // set is the template set being escaped.
+ set *template.Set
+ // output[templateName] is the output context for a templateName that
+ // has been mangled to include its input context.
+ output map[string]context
+ // derived[c.mangle(name)] maps to a template derived from the template
+ // named name templateName for the start context c.
+ derived map[string]*template.Template
+ // called[templateName] is a set of called mangled template names.
+ called map[string]bool
+ // xxxNodeEdits are the accumulated edits to apply during commit.
+ // Such edits are not applied immediately in case a template set
+ // executes a given template in different escaping contexts.
+ actionNodeEdits map[*parse.ActionNode][]string
+ templateNodeEdits map[*parse.TemplateNode]string
+ textNodeEdits map[*parse.TextNode][]byte
+}
+
+// newEscaper creates a blank escaper for the given set.
+func newEscaper(s *template.Set) *escaper {
+ return &escaper{
+ s,
+ map[string]context{},
+ map[string]*template.Template{},
+ map[string]bool{},
+ map[*parse.ActionNode][]string{},
+ map[*parse.TemplateNode]string{},
+ map[*parse.TextNode][]byte{},
+ }
+}
+
+// filterFailsafe is an innocuous word that is emitted in place of unsafe values
+// by sanitizer functions. It is not a keyword in any programming language,
+// contains no special characters, is not empty, and when it appears in output
+// it is distinct enough that a developer can find the source of the problem
+// via a search engine.
+const filterFailsafe = "ZgotmplZ"
+
+// escape escapes a template node.
+func (e *escaper) escape(c context, n parse.Node) context {
+ switch n := n.(type) {
case *parse.ActionNode:
- escapeActionNode(n)
+ return e.escapeAction(c, n)
case *parse.IfNode:
- escapeIfNode(n)
+ return e.escapeBranch(c, &n.BranchNode, "if")
+ case *parse.ListNode:
+ return e.escapeList(c, n)
case *parse.RangeNode:
- escapeRangeNode(n)
+ return e.escapeBranch(c, &n.BranchNode, "range")
case *parse.TemplateNode:
- // Nothing to do.
+ return e.escapeTemplate(c, n)
+ case *parse.TextNode:
+ return e.escapeText(c, n)
case *parse.WithNode:
- escapeWithNode(n)
+ return e.escapeBranch(c, &n.BranchNode, "with")
+ }
+ panic("escaping " + n.String() + " is unimplemented")
+}
+
+// escapeAction escapes an action template node.
+func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
+ if len(n.Pipe.Decl) != 0 {
+ // A local variable assignment, not an interpolation.
+ return c
+ }
+ c = nudge(c)
+ s := make([]string, 0, 3)
+ switch c.state {
+ case stateError:
+ return c
+ case stateURL, stateCSSDqStr, stateCSSSqStr, stateCSSDqURL, stateCSSSqURL, stateCSSURL:
+ switch c.urlPart {
+ case urlPartNone:
+ s = append(s, "exp_template_html_urlfilter")
+ fallthrough
+ case urlPartPreQuery:
+ switch c.state {
+ case stateCSSDqStr, stateCSSSqStr:
+ s = append(s, "exp_template_html_cssescaper")
+ default:
+ s = append(s, "exp_template_html_urlnormalizer")
+ }
+ case urlPartQueryOrFrag:
+ s = append(s, "exp_template_html_urlescaper")
+ case urlPartUnknown:
+ return context{
+ state: stateError,
+ err: errorf(ErrAmbigContext, n.Line, "%s appears in an ambiguous URL context", n),
+ }
+ default:
+ panic(c.urlPart.String())
+ }
+ case stateJS:
+ s = append(s, "exp_template_html_jsvalescaper")
+ // A slash after a value starts a div operator.
+ c.jsCtx = jsCtxDivOp
+ case stateJSDqStr, stateJSSqStr:
+ s = append(s, "exp_template_html_jsstrescaper")
+ case stateJSRegexp:
+ s = append(s, "exp_template_html_jsregexpescaper")
+ case stateCSS:
+ s = append(s, "exp_template_html_cssvaluefilter")
+ case stateText:
+ s = append(s, "exp_template_html_htmlescaper")
+ case stateRCDATA:
+ s = append(s, "exp_template_html_rcdataescaper")
+ case stateAttr:
+ // Handled below in delim check.
+ case stateAttrName, stateTag:
+ c.state = stateAttrName
+ s = append(s, "exp_template_html_htmlnamefilter")
default:
- panic("handling for " + node.String() + " not implemented")
- // TODO: Handle other inner node types.
+ if isComment(c.state) {
+ s = append(s, "exp_template_html_commentescaper")
+ } else {
+ panic("unexpected state " + c.state.String())
+ }
}
+ switch c.delim {
+ case delimNone:
+ // No extra-escaping needed for raw text content.
+ case delimSpaceOrTagEnd:
+ s = append(s, "exp_template_html_nospaceescaper")
+ default:
+ s = append(s, "exp_template_html_attrescaper")
+ }
+ e.editActionNode(n, s)
+ return c
}
-// escapeListNode recursively escapes its input's children.
-func escapeListNode(node *parse.ListNode) {
- if node == nil {
+// ensurePipelineContains ensures that the pipeline has commands with
+// the identifiers in s in order.
+// If the pipeline already has some of the sanitizers, do not interfere.
+// For example, if p is (.X | html) and s is ["escapeJSVal", "html"] then it
+// has one matching, "html", and one to insert, "escapeJSVal", to produce
+// (.X | escapeJSVal | html).
+func ensurePipelineContains(p *parse.PipeNode, s []string) {
+ if len(s) == 0 {
return
}
- children := node.Nodes
- for _, child := range children {
- escapeNode(child)
+ n := len(p.Cmds)
+ // Find the identifiers at the end of the command chain.
+ idents := p.Cmds
+ for i := n - 1; i >= 0; i-- {
+ if cmd := p.Cmds[i]; len(cmd.Args) != 0 {
+ if id, ok := cmd.Args[0].(*parse.IdentifierNode); ok {
+ if id.Ident == "noescape" {
+ return
+ }
+ continue
+ }
+ }
+ idents = p.Cmds[i+1:]
+ }
+ dups := 0
+ for _, id := range idents {
+ if escFnsEq(s[dups], (id.Args[0].(*parse.IdentifierNode)).Ident) {
+ dups++
+ if dups == len(s) {
+ return
+ }
+ }
+ }
+ newCmds := make([]*parse.CommandNode, n-len(idents), n+len(s)-dups)
+ copy(newCmds, p.Cmds)
+ // Merge existing identifier commands with the sanitizers needed.
+ for _, id := range idents {
+ i := indexOfStr((id.Args[0].(*parse.IdentifierNode)).Ident, s, escFnsEq)
+ if i != -1 {
+ for _, name := range s[:i] {
+ newCmds = appendCmd(newCmds, newIdentCmd(name))
+ }
+ s = s[i+1:]
+ }
+ newCmds = appendCmd(newCmds, id)
+ }
+ // Create any remaining sanitizers.
+ for _, name := range s {
+ newCmds = appendCmd(newCmds, newIdentCmd(name))
}
+ p.Cmds = newCmds
}
-// escapeActionNode adds a pipeline call to the end that escapes the result
-// of the expression before it is interpolated into the template output.
-func escapeActionNode(node *parse.ActionNode) {
- pipe := node.Pipe
+// redundantFuncs[a][b] implies that funcMap[b](funcMap[a](x)) == funcMap[a](x)
+// for all x.
+var redundantFuncs = map[string]map[string]bool{
+ "exp_template_html_commentescaper": {
+ "exp_template_html_attrescaper": true,
+ "exp_template_html_nospaceescaper": true,
+ "exp_template_html_htmlescaper": true,
+ },
+ "exp_template_html_cssescaper": {
+ "exp_template_html_attrescaper": true,
+ },
+ "exp_template_html_jsregexpescaper": {
+ "exp_template_html_attrescaper": true,
+ },
+ "exp_template_html_jsstrescaper": {
+ "exp_template_html_attrescaper": true,
+ },
+ "exp_template_html_urlescaper": {
+ "exp_template_html_urlnormalizer": true,
+ },
+}
- cmds := pipe.Cmds
- nCmds := len(cmds)
+// appendCmd appends the given command to the end of the command pipeline
+// unless it is redundant with the last command.
+func appendCmd(cmds []*parse.CommandNode, cmd *parse.CommandNode) []*parse.CommandNode {
+ if n := len(cmds); n != 0 {
+ last, ok := cmds[n-1].Args[0].(*parse.IdentifierNode)
+ next, _ := cmd.Args[0].(*parse.IdentifierNode)
+ if ok && redundantFuncs[last.Ident][next.Ident] {
+ return cmds
+ }
+ }
+ return append(cmds, cmd)
+}
- // If it already has an escaping command, do not interfere.
- if nCmds != 0 {
- if lastCmd := cmds[nCmds-1]; len(lastCmd.Args) != 0 {
- // TODO: Recognize url and js as escaping functions once
- // we have enough context to know whether additional
- // escaping is necessary.
- if arg, ok := lastCmd.Args[0].(*parse.IdentifierNode); ok && arg.Ident == "html" {
- return
- }
+// indexOfStr is the first i such that eq(s, strs[i]) or -1 if s was not found.
+func indexOfStr(s string, strs []string, eq func(a, b string) bool) int {
+ for i, t := range strs {
+ if eq(s, t) {
+ return i
}
}
+ return -1
+}
- htmlEscapeCommand := parse.CommandNode{
+// escFnsEq returns whether the two escaping functions are equivalent.
+func escFnsEq(a, b string) bool {
+ if e := equivEscapers[a]; e != "" {
+ a = e
+ }
+ if e := equivEscapers[b]; e != "" {
+ b = e
+ }
+ return a == b
+}
+
+// newIdentCmd produces a command containing a single identifier node.
+func newIdentCmd(identifier string) *parse.CommandNode {
+ return &parse.CommandNode{
NodeType: parse.NodeCommand,
- Args: []parse.Node{parse.NewIdentifier("html")},
+ Args: []parse.Node{parse.NewIdentifier(identifier)},
}
+}
- node.Pipe.Cmds = append(node.Pipe.Cmds, &htmlEscapeCommand)
+// nudge returns the context that would result from following empty string
+// transitions from the input context.
+// For example, parsing:
+// `<a href=`
+// will end in context{stateBeforeValue, attrURL}, but parsing one extra rune:
+// `<a href=x`
+// will end in context{stateURL, delimSpaceOrTagEnd, ...}.
+// There are two transitions that happen when the 'x' is seen:
+// (1) Transition from a before-value state to a start-of-value state without
+// consuming any character.
+// (2) Consume 'x' and transition past the first value character.
+// In this case, nudging produces the context after (1) happens.
+func nudge(c context) context {
+ switch c.state {
+ case stateTag:
+ // In `<foo {{.}}`, the action should emit an attribute.
+ c.state = stateAttrName
+ case stateBeforeValue:
+ // In `<foo bar={{.}}`, the action is an undelimited value.
+ c.state, c.delim, c.attr = attrStartStates[c.attr], delimSpaceOrTagEnd, attrNone
+ case stateAfterName:
+ // In `<foo bar {{.}}`, the action is an attribute name.
+ c.state, c.attr = stateAttrName, attrNone
+ }
+ return c
}
-// escapeIfNode recursively escapes the if and then clauses but leaves the
-// condition unchanged.
-func escapeIfNode(node *parse.IfNode) {
- escapeListNode(node.List)
- escapeListNode(node.ElseList)
+// join joins the two contexts of a branch template node. The result is an
+// error context if either of the input contexts are error contexts, or if the
+// the input contexts differ.
+func join(a, b context, line int, nodeName string) context {
+ if a.state == stateError {
+ return a
+ }
+ if b.state == stateError {
+ return b
+ }
+ if a.eq(b) {
+ return a
+ }
+
+ c := a
+ c.urlPart = b.urlPart
+ if c.eq(b) {
+ // The contexts differ only by urlPart.
+ c.urlPart = urlPartUnknown
+ return c
+ }
+
+ c = a
+ c.jsCtx = b.jsCtx
+ if c.eq(b) {
+ // The contexts differ only by jsCtx.
+ c.jsCtx = jsCtxUnknown
+ return c
+ }
+
+ // Allow a nudged context to join with an unnudged one.
+ // This means that
+ // <p title={{if .C}}{{.}}{{end}}
+ // ends in an unquoted value state even though the else branch
+ // ends in stateBeforeValue.
+ if c, d := nudge(a), nudge(b); !(c.eq(a) && d.eq(b)) {
+ if e := join(c, d, line, nodeName); e.state != stateError {
+ return e
+ }
+ }
+
+ return context{
+ state: stateError,
+ err: errorf(ErrBranchEnd, line, "{{%s}} branches end in different contexts: %v, %v", nodeName, a, b),
+ }
}
-// escapeRangeNode recursively escapes the loop body and else clause but
-// leaves the series unchanged.
-func escapeRangeNode(node *parse.RangeNode) {
- escapeListNode(node.List)
- escapeListNode(node.ElseList)
+// escapeBranch escapes a branch template node: "if", "range" and "with".
+func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string) context {
+ c0 := e.escapeList(c, n.List)
+ if nodeName == "range" && c0.state != stateError {
+ // The "true" branch of a "range" node can execute multiple times.
+ // We check that executing n.List once results in the same context
+ // as executing n.List twice.
+ c1, _ := e.escapeListConditionally(c0, n.List, nil)
+ c0 = join(c0, c1, n.Line, nodeName)
+ if c0.state == stateError {
+ // Make clear that this is a problem on loop re-entry
+ // since developers tend to overlook that branch when
+ // debugging templates.
+ c0.err.Line = n.Line
+ c0.err.Description = "on range loop re-entry: " + c0.err.Description
+ return c0
+ }
+ }
+ c1 := e.escapeList(c, n.ElseList)
+ return join(c0, c1, n.Line, nodeName)
}
-// escapeWithNode recursively escapes the scope body and else clause but
-// leaves the pipeline unchanged.
-func escapeWithNode(node *parse.WithNode) {
- escapeListNode(node.List)
- escapeListNode(node.ElseList)
+// escapeList escapes a list template node.
+func (e *escaper) escapeList(c context, n *parse.ListNode) context {
+ if n == nil {
+ return c
+ }
+ for _, m := range n.Nodes {
+ c = e.escape(c, m)
+ }
+ return c
+}
+
+// escapeListConditionally escapes a list node but only preserves edits and
+// inferences in e if the inferences and output context satisfy filter.
+// It returns the best guess at an output context, and the result of the filter
+// which is the same as whether e was updated.
+func (e *escaper) escapeListConditionally(c context, n *parse.ListNode, filter func(*escaper, context) bool) (context, bool) {
+ e1 := newEscaper(e.set)
+ // Make type inferences available to f.
+ for k, v := range e.output {
+ e1.output[k] = v
+ }
+ c = e1.escapeList(c, n)
+ ok := filter != nil && filter(e1, c)
+ if ok {
+ // Copy inferences and edits from e1 back into e.
+ for k, v := range e1.output {
+ e.output[k] = v
+ }
+ for k, v := range e1.derived {
+ e.derived[k] = v
+ }
+ for k, v := range e1.called {
+ e.called[k] = v
+ }
+ for k, v := range e1.actionNodeEdits {
+ e.editActionNode(k, v)
+ }
+ for k, v := range e1.templateNodeEdits {
+ e.editTemplateNode(k, v)
+ }
+ for k, v := range e1.textNodeEdits {
+ e.editTextNode(k, v)
+ }
+ }
+ return c, ok
+}
+
+// escapeTemplate escapes a {{template}} call node.
+func (e *escaper) escapeTemplate(c context, n *parse.TemplateNode) context {
+ c, name := e.escapeTree(c, n.Name, n.Line)
+ if name != n.Name {
+ e.editTemplateNode(n, name)
+ }
+ return c
+}
+
+// escapeTree escapes the named template starting in the given context as
+// necessary and returns its output context.
+func (e *escaper) escapeTree(c context, name string, line int) (context, string) {
+ // Mangle the template name with the input context to produce a reliable
+ // identifier.
+ dname := c.mangle(name)
+ e.called[dname] = true
+ if out, ok := e.output[dname]; ok {
+ // Already escaped.
+ return out, dname
+ }
+ t := e.template(name)
+ if t == nil {
+ return context{
+ state: stateError,
+ err: errorf(ErrNoSuchTemplate, line, "no such template %s", name),
+ }, dname
+ }
+ if dname != name {
+ // Use any template derived during an earlier call to EscapeSet
+ // with different top level templates, or clone if necessary.
+ dt := e.template(dname)
+ if dt == nil {
+ dt = template.New(dname)
+ dt.Tree = &parse.Tree{Name: dname, Root: cloneList(t.Root)}
+ e.derived[dname] = dt
+ }
+ t = dt
+ }
+ return e.computeOutCtx(c, t), dname
+}
+
+// computeOutCtx takes a template and its start context and computes the output
+// context while storing any inferences in e.
+func (e *escaper) computeOutCtx(c context, t *template.Template) context {
+ // Propagate context over the body.
+ c1, ok := e.escapeTemplateBody(c, t)
+ if !ok {
+ // Look for a fixed point by assuming c1 as the output context.
+ if c2, ok2 := e.escapeTemplateBody(c1, t); ok2 {
+ c1, ok = c2, true
+ }
+ // Use c1 as the error context if neither assumption worked.
+ }
+ if !ok && c1.state != stateError {
+ return context{
+ state: stateError,
+ // TODO: Find the first node with a line in t.Tree.Root
+ err: errorf(ErrOutputContext, 0, "cannot compute output context for template %s", t.Name()),
+ }
+ }
+ return c1
+}
+
+// escapeTemplateBody escapes the given template assuming the given output
+// context, and returns the best guess at the output context and whether the
+// assumption was correct.
+func (e *escaper) escapeTemplateBody(c context, t *template.Template) (context, bool) {
+ filter := func(e1 *escaper, c1 context) bool {
+ if c1.state == stateError {
+ // Do not update the input escaper, e.
+ return false
+ }
+ if !e1.called[t.Name()] {
+ // If t is not recursively called, then c1 is an
+ // accurate output context.
+ return true
+ }
+ // c1 is accurate if it matches our assumed output context.
+ return c.eq(c1)
+ }
+ // We need to assume an output context so that recursive template calls
+ // take the fast path out of escapeTree instead of infinitely recursing.
+ // Naively assuming that the input context is the same as the output
+ // works >90% of the time.
+ e.output[t.Name()] = c
+ return e.escapeListConditionally(c, t.Tree.Root, filter)
+}
+
+// delimEnds maps each delim to a string of characters that terminate it.
+var delimEnds = [...]string{
+ delimDoubleQuote: `"`,
+ delimSingleQuote: "'",
+ // Determined empirically by running the below in various browsers.
+ // var div = document.createElement("DIV");
+ // for (var i = 0; i < 0x10000; ++i) {
+ // div.innerHTML = "<span title=x" + String.fromCharCode(i) + "-bar>";
+ // if (div.getElementsByTagName("SPAN")[0].title.indexOf("bar") < 0)
+ // document.write("<p>U+" + i.toString(16));
+ // }
+ delimSpaceOrTagEnd: " \t\n\f\r>",
+}
+
+var doctypeBytes = []byte("<!DOCTYPE")
+
+// escapeText escapes a text template node.
+func (e *escaper) escapeText(c context, n *parse.TextNode) context {
+ s, written, i, b := n.Text, 0, 0, new(bytes.Buffer)
+ for i != len(s) {
+ c1, nread := contextAfterText(c, s[i:])
+ i1 := i + nread
+ if c.state == stateText || c.state == stateRCDATA {
+ end := i1
+ if c1.state != c.state {
+ for j := end - 1; j >= i; j-- {
+ if s[j] == '<' {
+ end = j
+ break
+ }
+ }
+ }
+ for j := i; j < end; j++ {
+ if s[j] == '<' && !bytes.HasPrefix(s[j:], doctypeBytes) {
+ b.Write(s[written:j])
+ b.WriteString("&lt;")
+ written = j + 1
+ }
+ }
+ } else if isComment(c.state) && c.delim == delimNone {
+ switch c.state {
+ case stateJSBlockCmt:
+ // http://es5.github.com/#x7.4:
+ // "Comments behave like white space and are
+ // discarded except that, if a MultiLineComment
+ // contains a line terminator character, then
+ // the entire comment is considered to be a
+ // LineTerminator for purposes of parsing by
+ // the syntactic grammar."
+ if bytes.IndexAny(s[written:i1], "\n\r\u2028\u2029") != -1 {
+ b.WriteByte('\n')
+ } else {
+ b.WriteByte(' ')
+ }
+ case stateCSSBlockCmt:
+ b.WriteByte(' ')
+ }
+ written = i1
+ }
+ if c.state != c1.state && isComment(c1.state) && c1.delim == delimNone {
+ // Preserve the portion between written and the comment start.
+ cs := i1 - 2
+ if c1.state == stateHTMLCmt {
+ // "<!--" instead of "/*" or "//"
+ cs -= 2
+ }
+ b.Write(s[written:cs])
+ written = i1
+ }
+ if i == i1 && c.state == c1.state {
+ panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
+ }
+ c, i = c1, i1
+ }
+
+ if written != 0 && c.state != stateError {
+ if !isComment(c.state) || c.delim != delimNone {
+ b.Write(n.Text[written:])
+ }
+ e.editTextNode(n, b.Bytes())
+ }
+ return c
+}
+
+// contextAfterText starts in context c, consumes some tokens from the front of
+// s, then returns the context after those tokens and the unprocessed suffix.
+func contextAfterText(c context, s []byte) (context, int) {
+ if c.delim == delimNone {
+ c1, i := tSpecialTagEnd(c, s)
+ if i == 0 {
+ // A special end tag (`</script>`) has been seen and
+ // all content preceding it has been consumed.
+ return c1, 0
+ }
+ // Consider all content up to any end tag.
+ return transitionFunc[c.state](c, s[:i])
+ }
+
+ i := bytes.IndexAny(s, delimEnds[c.delim])
+ if i == -1 {
+ i = len(s)
+ }
+ if c.delim == delimSpaceOrTagEnd {
+ // http://www.w3.org/TR/html5/tokenization.html#attribute-value-unquoted-state
+ // lists the runes below as error characters.
+ // Error out because HTML parsers may differ on whether
+ // "<a id= onclick=f(" ends inside id's or onchange's value,
+ // "<a class=`foo " ends inside a value,
+ // "<a style=font:'Arial'" needs open-quote fixup.
+ // IE treats '`' as a quotation character.
+ if j := bytes.IndexAny(s[:i], "\"'<=`"); j >= 0 {
+ return context{
+ state: stateError,
+ err: errorf(ErrBadHTML, 0, "%q in unquoted attr: %q", s[j:j+1], s[:i]),
+ }, len(s)
+ }
+ }
+ if i == len(s) {
+ // Remain inside the attribute.
+ // Decode the value so non-HTML rules can easily handle
+ // <button onclick="alert(&quot;Hi!&quot;)">
+ // without having to entity decode token boundaries.
+ for u := []byte(html.UnescapeString(string(s))); len(u) != 0; {
+ c1, i1 := transitionFunc[c.state](c, u)
+ c, u = c1, u[i1:]
+ }
+ return c, len(s)
+ }
+ if c.delim != delimSpaceOrTagEnd {
+ // Consume any quote.
+ i++
+ }
+ // On exiting an attribute, we discard all state information
+ // except the state and element.
+ return context{state: stateTag, element: c.element}, i
+}
+
+// editActionNode records a change to an action pipeline for later commit.
+func (e *escaper) editActionNode(n *parse.ActionNode, cmds []string) {
+ if _, ok := e.actionNodeEdits[n]; ok {
+ panic(fmt.Sprintf("node %s shared between templates", n))
+ }
+ e.actionNodeEdits[n] = cmds
+}
+
+// editTemplateNode records a change to a {{template}} callee for later commit.
+func (e *escaper) editTemplateNode(n *parse.TemplateNode, callee string) {
+ if _, ok := e.templateNodeEdits[n]; ok {
+ panic(fmt.Sprintf("node %s shared between templates", n))
+ }
+ e.templateNodeEdits[n] = callee
+}
+
+// editTextNode records a change to a text node for later commit.
+func (e *escaper) editTextNode(n *parse.TextNode, text []byte) {
+ if _, ok := e.textNodeEdits[n]; ok {
+ panic(fmt.Sprintf("node %s shared between templates", n))
+ }
+ e.textNodeEdits[n] = text
+}
+
+// commit applies changes to actions and template calls needed to contextually
+// autoescape content and adds any derived templates to the set.
+func (e *escaper) commit() {
+ for name, _ := range e.output {
+ e.template(name).Funcs(funcMap)
+ }
+ for _, t := range e.derived {
+ e.set.Add(t)
+ }
+ for n, s := range e.actionNodeEdits {
+ ensurePipelineContains(n.Pipe, s)
+ }
+ for n, name := range e.templateNodeEdits {
+ n.Name = name
+ }
+ for n, s := range e.textNodeEdits {
+ n.Text = s
+ }
+}
+
+// template returns the named template given a mangled template name.
+func (e *escaper) template(name string) *template.Template {
+ t := e.set.Template(name)
+ if t == nil {
+ t = e.derived[name]
+ }
+ return t
}
diff --git a/libgo/go/exp/template/html/escape_test.go b/libgo/go/exp/template/html/escape_test.go
index 345a752a896..a4ea7596cd1 100644
--- a/libgo/go/exp/template/html/escape_test.go
+++ b/libgo/go/exp/template/html/escape_test.go
@@ -6,70 +6,1618 @@ package html
import (
"bytes"
+ "fmt"
+ "json"
+ "os"
+ "strings"
"template"
+ "template/parse"
"testing"
)
-type data struct {
- F, T bool
- C, G, H string
- A, E []string
+type badMarshaler struct{}
+
+func (x *badMarshaler) MarshalJSON() ([]byte, os.Error) {
+ // Keys in valid JSON must be double quoted as must all strings.
+ return []byte("{ foo: 'not quite valid JSON' }"), nil
}
-var testData = data{
- F: false,
- T: true,
- C: "<Cincinatti>",
- G: "<Goodbye>",
- H: "<Hello>",
- A: []string{"<a>", "<b>"},
- E: []string{},
+type goodMarshaler struct{}
+
+func (x *goodMarshaler) MarshalJSON() ([]byte, os.Error) {
+ return []byte(`{ "<foo>": "O'Reilly" }`), nil
}
-type testCase struct {
- name string
- input string
- output string
+func TestEscape(t *testing.T) {
+ var data = struct {
+ F, T bool
+ C, G, H string
+ A, E []string
+ B, M json.Marshaler
+ N int
+ Z *int
+ W HTML
+ }{
+ F: false,
+ T: true,
+ C: "<Cincinatti>",
+ G: "<Goodbye>",
+ H: "<Hello>",
+ A: []string{"<a>", "<b>"},
+ E: []string{},
+ N: 42,
+ B: &badMarshaler{},
+ M: &goodMarshaler{},
+ Z: nil,
+ W: HTML(`&iexcl;<b class="foo">Hello</b>, <textarea>O'World</textarea>!`),
+ }
+
+ tests := []struct {
+ name string
+ input string
+ output string
+ }{
+ {
+ "if",
+ "{{if .T}}Hello{{end}}, {{.C}}!",
+ "Hello, &lt;Cincinatti&gt;!",
+ },
+ {
+ "else",
+ "{{if .F}}{{.H}}{{else}}{{.G}}{{end}}!",
+ "&lt;Goodbye&gt;!",
+ },
+ {
+ "overescaping1",
+ "Hello, {{.C | html}}!",
+ "Hello, &lt;Cincinatti&gt;!",
+ },
+ {
+ "overescaping2",
+ "Hello, {{html .C}}!",
+ "Hello, &lt;Cincinatti&gt;!",
+ },
+ {
+ "overescaping3",
+ "{{with .C}}{{$msg := .}}Hello, {{$msg}}!{{end}}",
+ "Hello, &lt;Cincinatti&gt;!",
+ },
+ {
+ "assignment",
+ "{{if $x := .H}}{{$x}}{{end}}",
+ "&lt;Hello&gt;",
+ },
+ {
+ "withBody",
+ "{{with .H}}{{.}}{{end}}",
+ "&lt;Hello&gt;",
+ },
+ {
+ "withElse",
+ "{{with .E}}{{.}}{{else}}{{.H}}{{end}}",
+ "&lt;Hello&gt;",
+ },
+ {
+ "rangeBody",
+ "{{range .A}}{{.}}{{end}}",
+ "&lt;a&gt;&lt;b&gt;",
+ },
+ {
+ "rangeElse",
+ "{{range .E}}{{.}}{{else}}{{.H}}{{end}}",
+ "&lt;Hello&gt;",
+ },
+ {
+ "nonStringValue",
+ "{{.T}}",
+ "true",
+ },
+ {
+ "constant",
+ `<a href="/search?q={{"'a<b'"}}">`,
+ `<a href="/search?q=%27a%3cb%27">`,
+ },
+ {
+ "multipleAttrs",
+ "<a b=1 c={{.H}}>",
+ "<a b=1 c=&lt;Hello&gt;>",
+ },
+ {
+ "urlStartRel",
+ `<a href='{{"/foo/bar?a=b&c=d"}}'>`,
+ `<a href='/foo/bar?a=b&amp;c=d'>`,
+ },
+ {
+ "urlStartAbsOk",
+ `<a href='{{"http://example.com/foo/bar?a=b&c=d"}}'>`,
+ `<a href='http://example.com/foo/bar?a=b&amp;c=d'>`,
+ },
+ {
+ "protocolRelativeURLStart",
+ `<a href='{{"//example.com:8000/foo/bar?a=b&c=d"}}'>`,
+ `<a href='//example.com:8000/foo/bar?a=b&amp;c=d'>`,
+ },
+ {
+ "pathRelativeURLStart",
+ `<a href="{{"/javascript:80/foo/bar"}}">`,
+ `<a href="/javascript:80/foo/bar">`,
+ },
+ {
+ "dangerousURLStart",
+ `<a href='{{"javascript:alert(%22pwned%22)"}}'>`,
+ `<a href='#ZgotmplZ'>`,
+ },
+ {
+ "dangerousURLStart2",
+ `<a href=' {{"javascript:alert(%22pwned%22)"}}'>`,
+ `<a href=' #ZgotmplZ'>`,
+ },
+ {
+ "nonHierURL",
+ `<a href={{"mailto:Muhammed \"The Greatest\" Ali <m.ali@example.com>"}}>`,
+ `<a href=mailto:Muhammed%20%22The%20Greatest%22%20Ali%20%3cm.ali@example.com%3e>`,
+ },
+ {
+ "urlPath",
+ `<a href='http://{{"javascript:80"}}/foo'>`,
+ `<a href='http://javascript:80/foo'>`,
+ },
+ {
+ "urlQuery",
+ `<a href='/search?q={{.H}}'>`,
+ `<a href='/search?q=%3cHello%3e'>`,
+ },
+ {
+ "urlFragment",
+ `<a href='/faq#{{.H}}'>`,
+ `<a href='/faq#%3cHello%3e'>`,
+ },
+ {
+ "urlBranch",
+ `<a href="{{if .F}}/foo?a=b{{else}}/bar{{end}}">`,
+ `<a href="/bar">`,
+ },
+ {
+ "urlBranchConflictMoot",
+ `<a href="{{if .T}}/foo?a={{else}}/bar#{{end}}{{.C}}">`,
+ `<a href="/foo?a=%3cCincinatti%3e">`,
+ },
+ {
+ "jsStrValue",
+ "<button onclick='alert({{.H}})'>",
+ `<button onclick='alert(&#34;\u003cHello\u003e&#34;)'>`,
+ },
+ {
+ "jsNumericValue",
+ "<button onclick='alert({{.N}})'>",
+ `<button onclick='alert( 42 )'>`,
+ },
+ {
+ "jsBoolValue",
+ "<button onclick='alert({{.T}})'>",
+ `<button onclick='alert( true )'>`,
+ },
+ {
+ "jsNilValue",
+ "<button onclick='alert(typeof{{.Z}})'>",
+ `<button onclick='alert(typeof null )'>`,
+ },
+ {
+ "jsObjValue",
+ "<button onclick='alert({{.A}})'>",
+ `<button onclick='alert([&#34;\u003ca\u003e&#34;,&#34;\u003cb\u003e&#34;])'>`,
+ },
+ {
+ "jsObjValueScript",
+ "<script>alert({{.A}})</script>",
+ `<script>alert(["\u003ca\u003e","\u003cb\u003e"])</script>`,
+ },
+ {
+ "jsObjValueNotOverEscaped",
+ "<button onclick='alert({{.A | html}})'>",
+ `<button onclick='alert([&#34;\u003ca\u003e&#34;,&#34;\u003cb\u003e&#34;])'>`,
+ },
+ {
+ "jsStr",
+ "<button onclick='alert(&quot;{{.H}}&quot;)'>",
+ `<button onclick='alert(&quot;\x3cHello\x3e&quot;)'>`,
+ },
+ {
+ "badMarshaller",
+ `<button onclick='alert(1/{{.B}}in numbers)'>`,
+ `<button onclick='alert(1/ /* json: error calling MarshalJSON for type *html.badMarshaler: invalid character &#39;f&#39; looking for beginning of object key string */null in numbers)'>`,
+ },
+ {
+ "jsMarshaller",
+ `<button onclick='alert({{.M}})'>`,
+ `<button onclick='alert({&#34;&lt;foo&gt;&#34;:&#34;O&#39;Reilly&#34;})'>`,
+ },
+ {
+ "jsStrNotUnderEscaped",
+ "<button onclick='alert({{.C | urlquery}})'>",
+ // URL escaped, then quoted for JS.
+ `<button onclick='alert(&#34;%3CCincinatti%3E&#34;)'>`,
+ },
+ {
+ "jsRe",
+ `<button onclick='alert(/{{"foo+bar"}}/.test(""))'>`,
+ `<button onclick='alert(/foo\x2bbar/.test(""))'>`,
+ },
+ {
+ "jsReBlank",
+ `<script>alert(/{{""}}/.test(""));</script>`,
+ `<script>alert(/(?:)/.test(""));</script>`,
+ },
+ {
+ "jsReAmbigOk",
+ `<script>{{if true}}var x = 1{{end}}</script>`,
+ // The {if} ends in an ambiguous jsCtx but there is
+ // no slash following so we shouldn't care.
+ `<script>var x = 1</script>`,
+ },
+ {
+ "styleBidiKeywordPassed",
+ `<p style="dir: {{"ltr"}}">`,
+ `<p style="dir: ltr">`,
+ },
+ {
+ "styleBidiPropNamePassed",
+ `<p style="border-{{"left"}}: 0; border-{{"right"}}: 1in">`,
+ `<p style="border-left: 0; border-right: 1in">`,
+ },
+ {
+ "styleExpressionBlocked",
+ `<p style="width: {{"expression(alert(1337))"}}">`,
+ `<p style="width: ZgotmplZ">`,
+ },
+ {
+ "styleTagSelectorPassed",
+ `<style>{{"p"}} { color: pink }</style>`,
+ `<style>p { color: pink }</style>`,
+ },
+ {
+ "styleIDPassed",
+ `<style>p{{"#my-ID"}} { font: Arial }</style>`,
+ `<style>p#my-ID { font: Arial }</style>`,
+ },
+ {
+ "styleClassPassed",
+ `<style>p{{".my_class"}} { font: Arial }</style>`,
+ `<style>p.my_class { font: Arial }</style>`,
+ },
+ {
+ "styleQuantityPassed",
+ `<a style="left: {{"2em"}}; top: {{0}}">`,
+ `<a style="left: 2em; top: 0">`,
+ },
+ {
+ "stylePctPassed",
+ `<table style=width:{{"100%"}}>`,
+ `<table style=width:100%>`,
+ },
+ {
+ "styleColorPassed",
+ `<p style="color: {{"#8ff"}}; background: {{"#000"}}">`,
+ `<p style="color: #8ff; background: #000">`,
+ },
+ {
+ "styleObfuscatedExpressionBlocked",
+ `<p style="width: {{" e\78preS\0Sio/**/n(alert(1337))"}}">`,
+ `<p style="width: ZgotmplZ">`,
+ },
+ {
+ "styleMozBindingBlocked",
+ `<p style="{{"-moz-binding(alert(1337))"}}: ...">`,
+ `<p style="ZgotmplZ: ...">`,
+ },
+ {
+ "styleObfuscatedMozBindingBlocked",
+ `<p style="{{" -mo\7a-B\0I/**/nding(alert(1337))"}}: ...">`,
+ `<p style="ZgotmplZ: ...">`,
+ },
+ {
+ "styleFontNameString",
+ `<p style='font-family: "{{"Times New Roman"}}"'>`,
+ `<p style='font-family: "Times New Roman"'>`,
+ },
+ {
+ "styleFontNameString",
+ `<p style='font-family: "{{"Times New Roman"}}", "{{"sans-serif"}}"'>`,
+ `<p style='font-family: "Times New Roman", "sans-serif"'>`,
+ },
+ {
+ "styleFontNameUnquoted",
+ `<p style='font-family: {{"Times New Roman"}}'>`,
+ `<p style='font-family: Times New Roman'>`,
+ },
+ {
+ "styleURLQueryEncoded",
+ `<p style="background: url(/img?name={{"O'Reilly Animal(1)<2>.png"}})">`,
+ `<p style="background: url(/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png)">`,
+ },
+ {
+ "styleQuotedURLQueryEncoded",
+ `<p style="background: url('/img?name={{"O'Reilly Animal(1)<2>.png"}}')">`,
+ `<p style="background: url('/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png')">`,
+ },
+ {
+ "styleStrQueryEncoded",
+ `<p style="background: '/img?name={{"O'Reilly Animal(1)<2>.png"}}'">`,
+ `<p style="background: '/img?name=O%27Reilly%20Animal%281%29%3c2%3e.png'">`,
+ },
+ {
+ "styleURLBadProtocolBlocked",
+ `<a style="background: url('{{"javascript:alert(1337)"}}')">`,
+ `<a style="background: url('#ZgotmplZ')">`,
+ },
+ {
+ "styleStrBadProtocolBlocked",
+ `<a style="background: '{{"vbscript:alert(1337)"}}'">`,
+ `<a style="background: '#ZgotmplZ'">`,
+ },
+ {
+ "styleStrEncodedProtocolEncoded",
+ `<a style="background: '{{"javascript\\3a alert(1337)"}}'">`,
+ // The CSS string 'javascript\\3a alert(1337)' does not contains a colon.
+ `<a style="background: 'javascript\\3a alert\28 1337\29 '">`,
+ },
+ {
+ "styleURLGoodProtocolPassed",
+ `<a style="background: url('{{"http://oreilly.com/O'Reilly Animals(1)<2>;{}.html"}}')">`,
+ `<a style="background: url('http://oreilly.com/O%27Reilly%20Animals%281%29%3c2%3e;%7b%7d.html')">`,
+ },
+ {
+ "styleStrGoodProtocolPassed",
+ `<a style="background: '{{"http://oreilly.com/O'Reilly Animals(1)<2>;{}.html"}}'">`,
+ `<a style="background: 'http\3a\2f\2foreilly.com\2fO\27Reilly Animals\28 1\29\3c 2\3e\3b\7b\7d.html'">`,
+ },
+ {
+ "styleURLEncodedForHTMLInAttr",
+ `<a style="background: url('{{"/search?img=foo&size=icon"}}')">`,
+ `<a style="background: url('/search?img=foo&amp;size=icon')">`,
+ },
+ {
+ "styleURLNotEncodedForHTMLInCdata",
+ `<style>body { background: url('{{"/search?img=foo&size=icon"}}') }</style>`,
+ `<style>body { background: url('/search?img=foo&size=icon') }</style>`,
+ },
+ {
+ "styleURLMixedCase",
+ `<p style="background: URL(#{{.H}})">`,
+ `<p style="background: URL(#%3cHello%3e)">`,
+ },
+ {
+ "stylePropertyPairPassed",
+ `<a style='{{"color: red"}}'>`,
+ `<a style='color: red'>`,
+ },
+ {
+ "styleStrSpecialsEncoded",
+ `<a style="font-family: '{{"/**/'\";:// \\"}}', &quot;{{"/**/'\";:// \\"}}&quot;">`,
+ `<a style="font-family: '\2f**\2f\27\22\3b\3a\2f\2f \\', &quot;\2f**\2f\27\22\3b\3a\2f\2f \\&quot;">`,
+ },
+ {
+ "styleURLSpecialsEncoded",
+ `<a style="border-image: url({{"/**/'\";:// \\"}}), url(&quot;{{"/**/'\";:// \\"}}&quot;), url('{{"/**/'\";:// \\"}}'), 'http://www.example.com/?q={{"/**/'\";:// \\"}}''">`,
+ `<a style="border-image: url(/**/%27%22;://%20%5c), url(&quot;/**/%27%22;://%20%5c&quot;), url('/**/%27%22;://%20%5c'), 'http://www.example.com/?q=%2f%2a%2a%2f%27%22%3b%3a%2f%2f%20%5c''">`,
+ },
+ {
+ "HTML comment",
+ "<b>Hello, <!-- name of world -->{{.C}}</b>",
+ "<b>Hello, &lt;Cincinatti&gt;</b>",
+ },
+ {
+ "HTML comment not first < in text node.",
+ "<<!-- -->!--",
+ "&lt;!--",
+ },
+ {
+ "HTML normalization 1",
+ "a < b",
+ "a &lt; b",
+ },
+ {
+ "HTML normalization 2",
+ "a << b",
+ "a &lt;&lt; b",
+ },
+ {
+ "HTML normalization 3",
+ "a<<!-- --><!-- -->b",
+ "a&lt;b",
+ },
+ {
+ "HTML doctype not normalized",
+ "<!DOCTYPE html>Hello, World!",
+ "<!DOCTYPE html>Hello, World!",
+ },
+ {
+ "No doctype injection",
+ `<!{{"DOCTYPE"}}`,
+ "&lt;!DOCTYPE",
+ },
+ {
+ "Split HTML comment",
+ "<b>Hello, <!-- name of {{if .T}}city -->{{.C}}{{else}}world -->{{.W}}{{end}}</b>",
+ "<b>Hello, &lt;Cincinatti&gt;</b>",
+ },
+ {
+ "JS line comment",
+ "<script>for (;;) { if (c()) break// foo not a label\n" +
+ "foo({{.T}});}</script>",
+ "<script>for (;;) { if (c()) break\n" +
+ "foo( true );}</script>",
+ },
+ {
+ "JS multiline block comment",
+ "<script>for (;;) { if (c()) break/* foo not a label\n" +
+ " */foo({{.T}});}</script>",
+ // Newline separates break from call. If newline
+ // removed, then break will consume label leaving
+ // code invalid.
+ "<script>for (;;) { if (c()) break\n" +
+ "foo( true );}</script>",
+ },
+ {
+ "JS single-line block comment",
+ "<script>for (;;) {\n" +
+ "if (c()) break/* foo a label */foo;" +
+ "x({{.T}});}</script>",
+ // Newline separates break from call. If newline
+ // removed, then break will consume label leaving
+ // code invalid.
+ "<script>for (;;) {\n" +
+ "if (c()) break foo;" +
+ "x( true );}</script>",
+ },
+ {
+ "JS block comment flush with mathematical division",
+ "<script>var a/*b*//c\nd</script>",
+ "<script>var a /c\nd</script>",
+ },
+ {
+ "JS mixed comments",
+ "<script>var a/*b*///c\nd</script>",
+ "<script>var a \nd</script>",
+ },
+ {
+ "CSS comments",
+ "<style>p// paragraph\n" +
+ `{border: 1px/* color */{{"#00f"}}}</style>`,
+ "<style>p\n" +
+ "{border: 1px #00f}</style>",
+ },
+ {
+ "JS attr block comment",
+ `<a onclick="f(&quot;&quot;); /* alert({{.H}}) */">`,
+ // Attribute comment tests should pass if the comments
+ // are successfully elided.
+ `<a onclick="f(&quot;&quot;); /* alert() */">`,
+ },
+ {
+ "JS attr line comment",
+ `<a onclick="// alert({{.G}})">`,
+ `<a onclick="// alert()">`,
+ },
+ {
+ "CSS attr block comment",
+ `<a style="/* color: {{.H}} */">`,
+ `<a style="/* color: */">`,
+ },
+ {
+ "CSS attr line comment",
+ `<a style="// color: {{.G}}">`,
+ `<a style="// color: ">`,
+ },
+ {
+ "HTML substitution commented out",
+ "<p><!-- {{.H}} --></p>",
+ "<p></p>",
+ },
+ {
+ "Comment ends flush with start",
+ "<!--{{.}}--><script>/*{{.}}*///{{.}}\n</script><style>/*{{.}}*///{{.}}\n</style><a onclick='/*{{.}}*///{{.}}' style='/*{{.}}*///{{.}}'>",
+ "<script> \n</script><style> \n</style><a onclick='/**///' style='/**///'>",
+ },
+ {
+ "typed HTML in text",
+ `{{.W}}`,
+ `&iexcl;<b class="foo">Hello</b>, <textarea>O'World</textarea>!`,
+ },
+ {
+ "typed HTML in attribute",
+ `<div title="{{.W}}">`,
+ `<div title="&iexcl;Hello, O&#39;World!">`,
+ },
+ {
+ "typed HTML in script",
+ `<button onclick="alert({{.W}})">`,
+ `<button onclick="alert(&#34;&amp;iexcl;\u003cb class=\&#34;foo\&#34;\u003eHello\u003c/b\u003e, \u003ctextarea\u003eO&#39;World\u003c/textarea\u003e!&#34;)">`,
+ },
+ {
+ "typed HTML in RCDATA",
+ `<textarea>{{.W}}</textarea>`,
+ `<textarea>&iexcl;&lt;b class=&#34;foo&#34;&gt;Hello&lt;/b&gt;, &lt;textarea&gt;O&#39;World&lt;/textarea&gt;!</textarea>`,
+ },
+ {
+ "range in textarea",
+ "<textarea>{{range .A}}{{.}}{{end}}</textarea>",
+ "<textarea>&lt;a&gt;&lt;b&gt;</textarea>",
+ },
+ {
+ "auditable exemption from escaping",
+ "{{range .A}}{{. | noescape}}{{end}}",
+ "<a><b>",
+ },
+ {
+ "No tag injection",
+ `{{"10$"}}<{{"script src,evil.org/pwnd.js"}}...`,
+ `10$&lt;script src,evil.org/pwnd.js...`,
+ },
+ {
+ "No comment injection",
+ `<{{"!--"}}`,
+ `&lt;!--`,
+ },
+ {
+ "No RCDATA end tag injection",
+ `<textarea><{{"/textarea "}}...</textarea>`,
+ `<textarea>&lt;/textarea ...</textarea>`,
+ },
+ {
+ "optional attrs",
+ `<img class="{{"iconClass"}}"` +
+ `{{if .T}} id="{{"<iconId>"}}"{{end}}` +
+ // Double quotes inside if/else.
+ ` src=` +
+ `{{if .T}}"?{{"<iconPath>"}}"` +
+ `{{else}}"images/cleardot.gif"{{end}}` +
+ // Missing space before title, but it is not a
+ // part of the src attribute.
+ `{{if .T}}title="{{"<title>"}}"{{end}}` +
+ // Quotes outside if/else.
+ ` alt="` +
+ `{{if .T}}{{"<alt>"}}` +
+ `{{else}}{{if .F}}{{"<title>"}}{{end}}` +
+ `{{end}}"` +
+ `>`,
+ `<img class="iconClass" id="&lt;iconId&gt;" src="?%3ciconPath%3e"title="&lt;title&gt;" alt="&lt;alt&gt;">`,
+ },
+ {
+ "conditional valueless attr name",
+ `<input{{if .T}} checked{{end}} name=n>`,
+ `<input checked name=n>`,
+ },
+ {
+ "conditional dynamic valueless attr name 1",
+ `<input{{if .T}} {{"checked"}}{{end}} name=n>`,
+ `<input checked name=n>`,
+ },
+ {
+ "conditional dynamic valueless attr name 2",
+ `<input {{if .T}}{{"checked"}} {{end}}name=n>`,
+ `<input checked name=n>`,
+ },
+ {
+ "dynamic attribute name",
+ `<img on{{"load"}}="alert({{"loaded"}})">`,
+ // Treated as JS since quotes are inserted.
+ `<img onload="alert(&#34;loaded&#34;)">`,
+ },
+ {
+ "bad dynamic attribute name 1",
+ // Allow checked, selected, disabled, but not JS or
+ // CSS attributes.
+ `<input {{"onchange"}}="{{"doEvil()"}}">`,
+ `<input ZgotmplZ="doEvil()">`,
+ },
+ {
+ "bad dynamic attribute name 2",
+ `<div {{"sTyle"}}="{{"color: expression(alert(1337))"}}">`,
+ `<div ZgotmplZ="color: expression(alert(1337))">`,
+ },
+ {
+ "bad dynamic attribute name 3",
+ // Allow title or alt, but not a URL.
+ `<img {{"src"}}="{{"javascript:doEvil()"}}">`,
+ `<img ZgotmplZ="javascript:doEvil()">`,
+ },
+ {
+ "bad dynamic attribute name 4",
+ // Structure preservation requires values to associate
+ // with a consistent attribute.
+ `<input checked {{""}}="Whose value am I?">`,
+ `<input checked ZgotmplZ="Whose value am I?">`,
+ },
+ {
+ "dynamic element name",
+ `<h{{3}}><table><t{{"head"}}>...</h{{3}}>`,
+ `<h3><table><thead>...</h3>`,
+ },
+ {
+ "bad dynamic element name",
+ // Dynamic element names are typically used to switch
+ // between (thead, tfoot, tbody), (ul, ol), (th, td),
+ // and other replaceable sets.
+ // We do not currently easily support (ul, ol).
+ // If we do change to support that, this test should
+ // catch failures to filter out special tag names which
+ // would violate the structure preservation property --
+ // if any special tag name could be substituted, then
+ // the content could be raw text/RCDATA for some inputs
+ // and regular HTML content for others.
+ `<{{"script"}}>{{"doEvil()"}}</{{"script"}}>`,
+ `&lt;script>doEvil()&lt;/script>`,
+ },
+ }
+
+ for _, test := range tests {
+ tmpl := template.New(test.name)
+ // TODO: Move noescape into template/func.go
+ tmpl.Funcs(template.FuncMap{
+ "noescape": func(a ...interface{}) string {
+ return fmt.Sprint(a...)
+ },
+ })
+ tmpl = template.Must(Escape(template.Must(tmpl.Parse(test.input))))
+ b := new(bytes.Buffer)
+ if err := tmpl.Execute(b, data); err != nil {
+ t.Errorf("%s: template execution failed: %s", test.name, err)
+ continue
+ }
+ if w, g := test.output, b.String(); w != g {
+ t.Errorf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
+ continue
+ }
+ }
}
-var testCases = []testCase{
- {"if", "{{if .T}}Hello{{end}}, {{.C}}!", "Hello, &lt;Cincinatti&gt;!"},
- {"else", "{{if .F}}{{.H}}{{else}}{{.G}}{{end}}!", "&lt;Goodbye&gt;!"},
- {"overescaping", "Hello, {{.C | html}}!", "Hello, &lt;Cincinatti&gt;!"},
- {"assignment", "{{if $x := .H}}{{$x}}{{end}}", "&lt;Hello&gt;"},
- {"withBody", "{{with .H}}{{.}}{{end}}", "&lt;Hello&gt;"},
- {"withElse", "{{with .E}}{{.}}{{else}}{{.H}}{{end}}", "&lt;Hello&gt;"},
- {"rangeBody", "{{range .A}}{{.}}{{end}}", "&lt;a&gt;&lt;b&gt;"},
- {"rangeElse", "{{range .E}}{{.}}{{else}}{{.H}}{{end}}", "&lt;Hello&gt;"},
- {"nonStringValue", "{{.T}}", "true"},
- {"constant", `<a href="{{"'str'"}}">`, `<a href="&#39;str&#39;">`},
+func TestEscapeSet(t *testing.T) {
+ type dataItem struct {
+ Children []*dataItem
+ X string
+ }
+
+ data := dataItem{
+ Children: []*dataItem{
+ &dataItem{X: "foo"},
+ &dataItem{X: "<bar>"},
+ &dataItem{
+ Children: []*dataItem{
+ &dataItem{X: "baz"},
+ },
+ },
+ },
+ }
+
+ tests := []struct {
+ inputs map[string]string
+ want string
+ }{
+ // The trivial set.
+ {
+ map[string]string{
+ "main": ``,
+ },
+ ``,
+ },
+ // A template called in the start context.
+ {
+ map[string]string{
+ "main": `Hello, {{template "helper"}}!`,
+ // Not a valid top level HTML template.
+ // "<b" is not a full tag.
+ "helper": `{{"<World>"}}`,
+ },
+ `Hello, &lt;World&gt;!`,
+ },
+ // A template called in a context other than the start.
+ {
+ map[string]string{
+ "main": `<a onclick='a = {{template "helper"}};'>`,
+ // Not a valid top level HTML template.
+ // "<b" is not a full tag.
+ "helper": `{{"<a>"}}<b`,
+ },
+ `<a onclick='a = &#34;\u003ca\u003e&#34;<b;'>`,
+ },
+ // A recursive template that ends in its start context.
+ {
+ map[string]string{
+ "main": `{{range .Children}}{{template "main" .}}{{else}}{{.X}} {{end}}`,
+ },
+ `foo &lt;bar&gt; baz `,
+ },
+ // A recursive helper template that ends in its start context.
+ {
+ map[string]string{
+ "main": `{{template "helper" .}}`,
+ "helper": `{{if .Children}}<ul>{{range .Children}}<li>{{template "main" .}}</li>{{end}}</ul>{{else}}{{.X}}{{end}}`,
+ },
+ `<ul><li>foo</li><li>&lt;bar&gt;</li><li><ul><li>baz</li></ul></li></ul>`,
+ },
+ // Co-recursive templates that end in its start context.
+ {
+ map[string]string{
+ "main": `<blockquote>{{range .Children}}{{template "helper" .}}{{end}}</blockquote>`,
+ "helper": `{{if .Children}}{{template "main" .}}{{else}}{{.X}}<br>{{end}}`,
+ },
+ `<blockquote>foo<br>&lt;bar&gt;<br><blockquote>baz<br></blockquote></blockquote>`,
+ },
+ // A template that is called in two different contexts.
+ {
+ map[string]string{
+ "main": `<button onclick="title='{{template "helper"}}'; ...">{{template "helper"}}</button>`,
+ "helper": `{{11}} of {{"<100>"}}`,
+ },
+ `<button onclick="title='11 of \x3c100\x3e'; ...">11 of &lt;100&gt;</button>`,
+ },
+ // A non-recursive template that ends in a different context.
+ // helper starts in jsCtxRegexp and ends in jsCtxDivOp.
+ {
+ map[string]string{
+ "main": `<script>var x={{template "helper"}}/{{"42"}};</script>`,
+ "helper": "{{126}}",
+ },
+ `<script>var x= 126 /"42";</script>`,
+ },
+ // A recursive template that ends in a similar context.
+ {
+ map[string]string{
+ "main": `<script>var x=[{{template "countdown" 4}}];</script>`,
+ "countdown": `{{.}}{{if .}},{{template "countdown" . | pred}}{{end}}`,
+ },
+ `<script>var x=[ 4 , 3 , 2 , 1 , 0 ];</script>`,
+ },
+ // A recursive template that ends in a different context.
+ /*
+ {
+ map[string]string{
+ "main": `<a href="/foo{{template "helper" .}}">`,
+ "helper": `{{if .Children}}{{range .Children}}{{template "helper" .}}{{end}}{{else}}?x={{.X}}{{end}}`,
+ },
+ `<a href="/foo?x=foo?x=%3cbar%3e?x=baz">`,
+ },
+ */
+ }
+
+ // pred is a template function that returns the predecessor of a
+ // natural number for testing recursive templates.
+ fns := template.FuncMap{"pred": func(a ...interface{}) (interface{}, os.Error) {
+ if len(a) == 1 {
+ if i, _ := a[0].(int); i > 0 {
+ return i - 1, nil
+ }
+ }
+ return nil, fmt.Errorf("undefined pred(%v)", a)
+ }}
+
+ for _, test := range tests {
+ var s template.Set
+ for name, src := range test.inputs {
+ t := template.New(name)
+ t.Funcs(fns)
+ s.Add(template.Must(t.Parse(src)))
+ }
+ s.Funcs(fns)
+ if _, err := EscapeSet(&s, "main"); err != nil {
+ t.Errorf("%s for input:\n%v", err, test.inputs)
+ continue
+ }
+ var b bytes.Buffer
+
+ if err := s.Execute(&b, "main", data); err != nil {
+ t.Errorf("%q executing %v", err.String(), s.Template("main"))
+ continue
+ }
+ if got := b.String(); test.want != got {
+ t.Errorf("want\n\t%q\ngot\n\t%q", test.want, got)
+ }
+ }
+
}
-func TestAutoesc(t *testing.T) {
- for _, testCase := range testCases {
- name := testCase.name
- tmpl := template.New(name)
- tmpl, err := tmpl.Parse(testCase.input)
+func TestErrors(t *testing.T) {
+ tests := []struct {
+ input string
+ err string
+ }{
+ // Non-error cases.
+ {
+ "{{if .Cond}}<a>{{else}}<b>{{end}}",
+ "",
+ },
+ {
+ "{{if .Cond}}<a>{{end}}",
+ "",
+ },
+ {
+ "{{if .Cond}}{{else}}<b>{{end}}",
+ "",
+ },
+ {
+ "{{with .Cond}}<div>{{end}}",
+ "",
+ },
+ {
+ "{{range .Items}}<a>{{end}}",
+ "",
+ },
+ {
+ "<a href='/foo?{{range .Items}}&{{.K}}={{.V}}{{end}}'>",
+ "",
+ },
+ // Error cases.
+ {
+ "{{if .Cond}}<a{{end}}",
+ "z:1: {{if}} branches",
+ },
+ {
+ "{{if .Cond}}\n{{else}}\n<a{{end}}",
+ "z:1: {{if}} branches",
+ },
+ {
+ // Missing quote in the else branch.
+ `{{if .Cond}}<a href="foo">{{else}}<a href="bar>{{end}}`,
+ "z:1: {{if}} branches",
+ },
+ {
+ // Different kind of attribute: href implies a URL.
+ "<a {{if .Cond}}href='{{else}}title='{{end}}{{.X}}'>",
+ "z:1: {{if}} branches",
+ },
+ {
+ "\n{{with .X}}<a{{end}}",
+ "z:2: {{with}} branches",
+ },
+ {
+ "\n{{with .X}}<a>{{else}}<a{{end}}",
+ "z:2: {{with}} branches",
+ },
+ {
+ "{{range .Items}}<a{{end}}",
+ `z:1: on range loop re-entry: "<" in attribute name: "<a"`,
+ },
+ {
+ "\n{{range .Items}} x='<a{{end}}",
+ "z:2: on range loop re-entry: {{range}} branches",
+ },
+ {
+ "<a b=1 c={{.H}}",
+ "z: ends in a non-text context: {stateAttr delimSpaceOrTagEnd",
+ },
+ {
+ "<script>foo();",
+ "z: ends in a non-text context: {stateJS",
+ },
+ {
+ `<a href="{{if .F}}/foo?a={{else}}/bar/{{end}}{{.H}}">`,
+ "z:1: (action: [(command: [F=[H]])]) appears in an ambiguous URL context",
+ },
+ {
+ `<a onclick="alert('Hello \`,
+ `unfinished escape sequence in JS string: "Hello \\"`,
+ },
+ {
+ `<a onclick='alert("Hello\, World\`,
+ `unfinished escape sequence in JS string: "Hello\\, World\\"`,
+ },
+ {
+ `<a onclick='alert(/x+\`,
+ `unfinished escape sequence in JS string: "x+\\"`,
+ },
+ {
+ `<a onclick="/foo[\]/`,
+ `unfinished JS regexp charset: "foo[\\]/"`,
+ },
+ {
+ // It is ambiguous whether 1.5 should be 1\.5 or 1.5.
+ // Either `var x = 1/- 1.5 /i.test(x)`
+ // where `i.test(x)` is a method call of reference i,
+ // or `/-1\.5/i.test(x)` which is a method call on a
+ // case insensitive regular expression.
+ `<script>{{if false}}var x = 1{{end}}/-{{"1.5"}}/i.test(x)</script>`,
+ `'/' could start a division or regexp: "/-"`,
+ },
+ {
+ `{{template "foo"}}`,
+ "z:1: no such template foo",
+ },
+ {
+ `{{define "z"}}<div{{template "y"}}>{{end}}` +
+ // Illegal starting in stateTag but not in stateText.
+ `{{define "y"}} foo<b{{end}}`,
+ `"<" in attribute name: " foo<b"`,
+ },
+ {
+ `{{define "z"}}<script>reverseList = [{{template "t"}}]</script>{{end}}` +
+ // Missing " after recursive call.
+ `{{define "t"}}{{if .Tail}}{{template "t" .Tail}}{{end}}{{.Head}}",{{end}}`,
+ `: cannot compute output context for template t$htmltemplate_stateJS_elementScript`,
+ },
+ {
+ `<input type=button value=onclick=>`,
+ `exp/template/html:z: "=" in unquoted attr: "onclick="`,
+ },
+ {
+ `<input type=button value= onclick=>`,
+ `exp/template/html:z: "=" in unquoted attr: "onclick="`,
+ },
+ {
+ `<input type=button value= 1+1=2>`,
+ `exp/template/html:z: "=" in unquoted attr: "1+1=2"`,
+ },
+ {
+ "<a class=`foo>",
+ "exp/template/html:z: \"`\" in unquoted attr: \"`foo\"",
+ },
+ {
+ `<a style=font:'Arial'>`,
+ `exp/template/html:z: "'" in unquoted attr: "font:'Arial'"`,
+ },
+ {
+ `<a=foo>`,
+ `: expected space, attr name, or end of tag, but got "=foo>"`,
+ },
+ }
+
+ for _, test := range tests {
+ var err os.Error
+ if strings.HasPrefix(test.input, "{{define") {
+ var s template.Set
+ _, err = s.Parse(test.input)
+ if err != nil {
+ t.Errorf("Failed to parse %q: %s", test.input, err)
+ continue
+ }
+ _, err = EscapeSet(&s, "z")
+ } else {
+ tmpl := template.Must(template.New("z").Parse(test.input))
+ _, err = Escape(tmpl)
+ }
+ var got string
if err != nil {
- t.Errorf("%s: failed to parse template: %s", name, err)
+ got = err.String()
+ }
+ if test.err == "" {
+ if got != "" {
+ t.Errorf("input=%q: unexpected error %q", test.input, got)
+ }
+ continue
+ }
+ if strings.Index(got, test.err) == -1 {
+ t.Errorf("input=%q: error\n\t%q\ndoes not contain expected string\n\t%q", test.input, got, test.err)
continue
}
+ }
+}
- Escape(tmpl)
+func TestEscapeText(t *testing.T) {
+ tests := []struct {
+ input string
+ output context
+ }{
+ {
+ ``,
+ context{},
+ },
+ {
+ `Hello, World!`,
+ context{},
+ },
+ {
+ // An orphaned "<" is OK.
+ `I <3 Ponies!`,
+ context{},
+ },
+ {
+ `<a`,
+ context{state: stateTag},
+ },
+ {
+ `<a `,
+ context{state: stateTag},
+ },
+ {
+ `<a>`,
+ context{state: stateText},
+ },
+ {
+ `<a href`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a on`,
+ context{state: stateAttrName, attr: attrScript},
+ },
+ {
+ `<a href `,
+ context{state: stateAfterName, attr: attrURL},
+ },
+ {
+ `<a style = `,
+ context{state: stateBeforeValue, attr: attrStyle},
+ },
+ {
+ `<a href=`,
+ context{state: stateBeforeValue, attr: attrURL},
+ },
+ {
+ `<a href=x`,
+ context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a href=x `,
+ context{state: stateTag},
+ },
+ {
+ `<a href=>`,
+ context{state: stateText},
+ },
+ {
+ `<a href=x>`,
+ context{state: stateText},
+ },
+ {
+ `<a href ='`,
+ context{state: stateURL, delim: delimSingleQuote},
+ },
+ {
+ `<a href=''`,
+ context{state: stateTag},
+ },
+ {
+ `<a href= "`,
+ context{state: stateURL, delim: delimDoubleQuote},
+ },
+ {
+ `<a href=""`,
+ context{state: stateTag},
+ },
+ {
+ `<a title="`,
+ context{state: stateAttr, delim: delimDoubleQuote},
+ },
+ {
+ `<a HREF='http:`,
+ context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a Href='/`,
+ context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a href='"`,
+ context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a href="'`,
+ context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a href='&apos;`,
+ context{state: stateURL, delim: delimSingleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a href="&quot;`,
+ context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a href="&#34;`,
+ context{state: stateURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a href=&quot;`,
+ context{state: stateURL, delim: delimSpaceOrTagEnd, urlPart: urlPartPreQuery},
+ },
+ {
+ `<img alt="1">`,
+ context{state: stateText},
+ },
+ {
+ `<img alt="1>"`,
+ context{state: stateTag},
+ },
+ {
+ `<img alt="1>">`,
+ context{state: stateText},
+ },
+ {
+ `<input checked type="checkbox"`,
+ context{state: stateTag},
+ },
+ {
+ `<a onclick="`,
+ context{state: stateJS, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="//foo`,
+ context{state: stateJSLineCmt, delim: delimDoubleQuote},
+ },
+ {
+ "<a onclick='//\n",
+ context{state: stateJS, delim: delimSingleQuote},
+ },
+ {
+ "<a onclick='//\r\n",
+ context{state: stateJS, delim: delimSingleQuote},
+ },
+ {
+ "<a onclick='//\u2028",
+ context{state: stateJS, delim: delimSingleQuote},
+ },
+ {
+ `<a onclick="/*`,
+ context{state: stateJSBlockCmt, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="/*/`,
+ context{state: stateJSBlockCmt, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="/**/`,
+ context{state: stateJS, delim: delimDoubleQuote},
+ },
+ {
+ `<a onkeypress="&quot;`,
+ context{state: stateJSDqStr, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick='&quot;foo&quot;`,
+ context{state: stateJS, delim: delimSingleQuote, jsCtx: jsCtxDivOp},
+ },
+ {
+ `<a onclick=&#39;foo&#39;`,
+ context{state: stateJS, delim: delimSpaceOrTagEnd, jsCtx: jsCtxDivOp},
+ },
+ {
+ `<a onclick=&#39;foo`,
+ context{state: stateJSSqStr, delim: delimSpaceOrTagEnd},
+ },
+ {
+ `<a onclick="&quot;foo'`,
+ context{state: stateJSDqStr, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="'foo&quot;`,
+ context{state: stateJSSqStr, delim: delimDoubleQuote},
+ },
+ {
+ `<A ONCLICK="'`,
+ context{state: stateJSSqStr, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="/`,
+ context{state: stateJSRegexp, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="'foo'`,
+ context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+ },
+ {
+ `<a onclick="'foo\'`,
+ context{state: stateJSSqStr, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="'foo\'`,
+ context{state: stateJSSqStr, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="/foo/`,
+ context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+ },
+ {
+ `<script>/foo/ /=`,
+ context{state: stateJS, element: elementScript},
+ },
+ {
+ `<a onclick="1 /foo`,
+ context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+ },
+ {
+ `<a onclick="1 /*c*/ /foo`,
+ context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+ },
+ {
+ `<a onclick="/foo[/]`,
+ context{state: stateJSRegexp, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="/foo\/`,
+ context{state: stateJSRegexp, delim: delimDoubleQuote},
+ },
+ {
+ `<a onclick="/foo/`,
+ context{state: stateJS, delim: delimDoubleQuote, jsCtx: jsCtxDivOp},
+ },
+ {
+ `<input checked style="`,
+ context{state: stateCSS, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="//`,
+ context{state: stateCSSLineCmt, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="//</script>`,
+ context{state: stateCSSLineCmt, delim: delimDoubleQuote},
+ },
+ {
+ "<a style='//\n",
+ context{state: stateCSS, delim: delimSingleQuote},
+ },
+ {
+ "<a style='//\r",
+ context{state: stateCSS, delim: delimSingleQuote},
+ },
+ {
+ `<a style="/*`,
+ context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="/*/`,
+ context{state: stateCSSBlockCmt, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="/**/`,
+ context{state: stateCSS, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="background: '`,
+ context{state: stateCSSSqStr, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="background: &quot;`,
+ context{state: stateCSSDqStr, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="background: '/foo?img=`,
+ context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
+ },
+ {
+ `<a style="background: '/`,
+ context{state: stateCSSSqStr, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a style="background: url(&#x22;/`,
+ context{state: stateCSSDqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a style="background: url('/`,
+ context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a style="background: url('/)`,
+ context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a style="background: url('/ `,
+ context{state: stateCSSSqURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a style="background: url(/`,
+ context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartPreQuery},
+ },
+ {
+ `<a style="background: url( `,
+ context{state: stateCSSURL, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="background: url( /image?name=`,
+ context{state: stateCSSURL, delim: delimDoubleQuote, urlPart: urlPartQueryOrFrag},
+ },
+ {
+ `<a style="background: url(x)`,
+ context{state: stateCSS, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="background: url('x'`,
+ context{state: stateCSS, delim: delimDoubleQuote},
+ },
+ {
+ `<a style="background: url( x `,
+ context{state: stateCSS, delim: delimDoubleQuote},
+ },
+ {
+ `<!-- foo`,
+ context{state: stateHTMLCmt},
+ },
+ {
+ `<!-->`,
+ context{state: stateHTMLCmt},
+ },
+ {
+ `<!--->`,
+ context{state: stateHTMLCmt},
+ },
+ {
+ `<!-- foo -->`,
+ context{state: stateText},
+ },
+ {
+ `<script`,
+ context{state: stateTag, element: elementScript},
+ },
+ {
+ `<script `,
+ context{state: stateTag, element: elementScript},
+ },
+ {
+ `<script src="foo.js" `,
+ context{state: stateTag, element: elementScript},
+ },
+ {
+ `<script src='foo.js' `,
+ context{state: stateTag, element: elementScript},
+ },
+ {
+ `<script type=text/javascript `,
+ context{state: stateTag, element: elementScript},
+ },
+ {
+ `<script>foo`,
+ context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
+ },
+ {
+ `<script>foo</script>`,
+ context{state: stateText},
+ },
+ {
+ `<script>foo</script><!--`,
+ context{state: stateHTMLCmt},
+ },
+ {
+ `<script>document.write("<p>foo</p>");`,
+ context{state: stateJS, element: elementScript},
+ },
+ {
+ `<script>document.write("<p>foo<\/script>");`,
+ context{state: stateJS, element: elementScript},
+ },
+ {
+ `<script>document.write("<script>alert(1)</script>");`,
+ context{state: stateText},
+ },
+ {
+ `<Script>`,
+ context{state: stateJS, element: elementScript},
+ },
+ {
+ `<SCRIPT>foo`,
+ context{state: stateJS, jsCtx: jsCtxDivOp, element: elementScript},
+ },
+ {
+ `<textarea>value`,
+ context{state: stateRCDATA, element: elementTextarea},
+ },
+ {
+ `<textarea>value</TEXTAREA>`,
+ context{state: stateText},
+ },
+ {
+ `<textarea name=html><b`,
+ context{state: stateRCDATA, element: elementTextarea},
+ },
+ {
+ `<title>value`,
+ context{state: stateRCDATA, element: elementTitle},
+ },
+ {
+ `<style>value`,
+ context{state: stateCSS, element: elementStyle},
+ },
+ {
+ `<a xlink:href`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a xmlns`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a xmlns:foo`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a xmlnsxyz`,
+ context{state: stateAttrName},
+ },
+ {
+ `<a data-url`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a data-iconUri`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a data-urlItem`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a g:`,
+ context{state: stateAttrName},
+ },
+ {
+ `<a g:url`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a g:iconUri`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a g:urlItem`,
+ context{state: stateAttrName, attr: attrURL},
+ },
+ {
+ `<a g:value`,
+ context{state: stateAttrName},
+ },
+ {
+ `<a svg:style='`,
+ context{state: stateCSS, delim: delimSingleQuote},
+ },
+ {
+ `<svg:font-face`,
+ context{state: stateTag},
+ },
+ {
+ `<svg:a svg:onclick="`,
+ context{state: stateJS, delim: delimDoubleQuote},
+ },
+ }
- buffer := new(bytes.Buffer)
+ for _, test := range tests {
+ b, e := []byte(test.input), newEscaper(nil)
+ c := e.escapeText(context{}, &parse.TextNode{parse.NodeText, b})
+ if !test.output.eq(c) {
+ t.Errorf("input %q: want context\n\t%v\ngot\n\t%v", test.input, test.output, c)
+ continue
+ }
+ if test.input != string(b) {
+ t.Errorf("input %q: text node was modified: want %q got %q", test.input, test.input, b)
+ continue
+ }
+ }
+}
- err = tmpl.Execute(buffer, testData)
- if err != nil {
- t.Errorf("%s: template execution failed: %s", name, err)
+func TestEnsurePipelineContains(t *testing.T) {
+ tests := []struct {
+ input, output string
+ ids []string
+ }{
+ {
+ "{{.X}}",
+ "[(command: [F=[X]])]",
+ []string{},
+ },
+ {
+ "{{.X | html}}",
+ "[(command: [F=[X]]) (command: [I=html])]",
+ []string{},
+ },
+ {
+ "{{.X}}",
+ "[(command: [F=[X]]) (command: [I=html])]",
+ []string{"html"},
+ },
+ {
+ "{{.X | html}}",
+ "[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
+ []string{"urlquery"},
+ },
+ {
+ "{{.X | html | urlquery}}",
+ "[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
+ []string{"urlquery"},
+ },
+ {
+ "{{.X | html | urlquery}}",
+ "[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
+ []string{"html", "urlquery"},
+ },
+ {
+ "{{.X | html | urlquery}}",
+ "[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
+ []string{"html"},
+ },
+ {
+ "{{.X | urlquery}}",
+ "[(command: [F=[X]]) (command: [I=html]) (command: [I=urlquery])]",
+ []string{"html", "urlquery"},
+ },
+ {
+ "{{.X | html | print}}",
+ "[(command: [F=[X]]) (command: [I=urlquery]) (command: [I=html]) (command: [I=print])]",
+ []string{"urlquery", "html"},
+ },
+ }
+ for _, test := range tests {
+ tmpl := template.Must(template.New("test").Parse(test.input))
+ action, ok := (tmpl.Tree.Root.Nodes[0].(*parse.ActionNode))
+ if !ok {
+ t.Errorf("First node is not an action: %s", test.input)
continue
}
+ pipe := action.Pipe
+ ensurePipelineContains(pipe, test.ids)
+ got := pipe.String()
+ if got != test.output {
+ t.Errorf("%s, %v: want\n\t%s\ngot\n\t%s", test.input, test.ids, test.output, got)
+ }
+ }
+}
- output := testCase.output
- actual := buffer.String()
- if output != actual {
- t.Errorf("%s: escaped output: %q != %q",
- name, output, actual)
+func expectExecuteFailure(t *testing.T, b *bytes.Buffer) {
+ if x := recover(); x != nil {
+ if b.Len() != 0 {
+ t.Errorf("output on buffer: %q", b.String())
}
+ } else {
+ t.Errorf("unescaped template executed")
+ }
+}
+
+func TestEscapeErrorsNotIgnorable(t *testing.T) {
+ var b bytes.Buffer
+ tmpl := template.Must(template.New("dangerous").Parse("<a"))
+ Escape(tmpl)
+ defer expectExecuteFailure(t, &b)
+ tmpl.Execute(&b, nil)
+}
+
+func TestEscapeSetErrorsNotIgnorable(t *testing.T) {
+ s, err := (&template.Set{}).Parse(`{{define "t"}}<a{{end}}`)
+ if err != nil {
+ t.Errorf("failed to parse set: %q", err)
+ }
+ EscapeSet(s, "t")
+ var b bytes.Buffer
+ defer expectExecuteFailure(t, &b)
+ s.Execute(&b, "t", nil)
+}
+
+func TestRedundantFuncs(t *testing.T) {
+ inputs := []interface{}{
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ ` !"#$%&'()*+,-./` +
+ `0123456789:;<=>?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ[\]^_` +
+ "`abcdefghijklmno" +
+ "pqrstuvwxyz{|}~\x7f" +
+ "\u00A0\u0100\u2028\u2029\ufeff\ufdec\ufffd\uffff\U0001D11E" +
+ "&amp;%22\\",
+ CSS(`a[href =~ "//example.com"]#foo`),
+ HTML(`Hello, <b>World</b> &amp;tc!`),
+ HTMLAttr(` dir="ltr"`),
+ JS(`c && alert("Hello, World!");`),
+ JSStr(`Hello, World & O'Reilly\x21`),
+ URL(`greeting=H%69&addressee=(World)`),
+ }
+
+ for n0, m := range redundantFuncs {
+ f0 := funcMap[n0].(func(...interface{}) string)
+ for n1, _ := range m {
+ f1 := funcMap[n1].(func(...interface{}) string)
+ for _, input := range inputs {
+ want := f0(input)
+ if got := f1(want); want != got {
+ t.Errorf("%s %s with %T %q: want\n\t%q,\ngot\n\t%q", n0, n1, input, input, want, got)
+ }
+ }
+ }
+ }
+}
+
+func BenchmarkEscapedExecute(b *testing.B) {
+ tmpl := template.Must(Escape(template.Must(template.New("t").Parse(`<a onclick="alert('{{.}}')">{{.}}</a>`))))
+ var buf bytes.Buffer
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ tmpl.Execute(&buf, "foo & 'bar' & baz")
+ buf.Reset()
}
}
diff --git a/libgo/go/exp/template/html/html.go b/libgo/go/exp/template/html/html.go
new file mode 100644
index 00000000000..91bb1b17049
--- /dev/null
+++ b/libgo/go/exp/template/html/html.go
@@ -0,0 +1,257 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+ "utf8"
+)
+
+// htmlNospaceEscaper escapes for inclusion in unquoted attribute values.
+func htmlNospaceEscaper(args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeHTML {
+ return htmlReplacer(stripTags(s), htmlNospaceNormReplacementTable, false)
+ }
+ return htmlReplacer(s, htmlNospaceReplacementTable, false)
+}
+
+// attrEscaper escapes for inclusion in quoted attribute values.
+func attrEscaper(args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeHTML {
+ return htmlReplacer(stripTags(s), htmlNormReplacementTable, true)
+ }
+ return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// rcdataEscaper escapes for inclusion in an RCDATA element body.
+func rcdataEscaper(args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeHTML {
+ return htmlReplacer(s, htmlNormReplacementTable, true)
+ }
+ return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// htmlEscaper escapes for inclusion in HTML text.
+func htmlEscaper(args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeHTML {
+ return s
+ }
+ return htmlReplacer(s, htmlReplacementTable, true)
+}
+
+// htmlReplacementTable contains the runes that need to be escaped
+// inside a quoted attribute value or in a text node.
+var htmlReplacementTable = []string{
+ // http://www.w3.org/TR/html5/tokenization.html#attribute-value-unquoted-state: "
+ // U+0000 NULL Parse error. Append a U+FFFD REPLACEMENT
+ // CHARACTER character to the current attribute's value.
+ // "
+ // and similarly
+ // http://www.w3.org/TR/html5/tokenization.html#before-attribute-value-state
+ 0: "\uFFFD",
+ '"': "&#34;",
+ '&': "&amp;",
+ '\'': "&#39;",
+ '+': "&#43;",
+ '<': "&lt;",
+ '>': "&gt;",
+}
+
+// htmlNormReplacementTable is like htmlReplacementTable but without '&' to
+// avoid over-encoding existing entities.
+var htmlNormReplacementTable = []string{
+ 0: "\uFFFD",
+ '"': "&#34;",
+ '\'': "&#39;",
+ '+': "&#43;",
+ '<': "&lt;",
+ '>': "&gt;",
+}
+
+// htmlNospaceReplacementTable contains the runes that need to be escaped
+// inside an unquoted attribute value.
+// The set of runes escaped is the union of the HTML specials and
+// those determined by running the JS below in browsers:
+// <div id=d></div>
+// <script>(function () {
+// var a = [], d = document.getElementById("d"), i, c, s;
+// for (i = 0; i < 0x10000; ++i) {
+// c = String.fromCharCode(i);
+// d.innerHTML = "<span title=" + c + "lt" + c + "></span>"
+// s = d.getElementsByTagName("SPAN")[0];
+// if (!s || s.title !== c + "lt" + c) { a.push(i.toString(16)); }
+// }
+// document.write(a.join(", "));
+// })()</script>
+var htmlNospaceReplacementTable = []string{
+ 0: "&#xfffd;",
+ '\t': "&#9;",
+ '\n': "&#10;",
+ '\v': "&#11;",
+ '\f': "&#12;",
+ '\r': "&#13;",
+ ' ': "&#32;",
+ '"': "&#34;",
+ '&': "&amp;",
+ '\'': "&#39;",
+ '+': "&#43;",
+ '<': "&lt;",
+ '=': "&#61;",
+ '>': "&gt;",
+ // A parse error in the attribute value (unquoted) and
+ // before attribute value states.
+ // Treated as a quoting character by IE.
+ '`': "&#96;",
+}
+
+// htmlNospaceNormReplacementTable is like htmlNospaceReplacementTable but
+// without '&' to avoid over-encoding existing entities.
+var htmlNospaceNormReplacementTable = []string{
+ 0: "&#xfffd;",
+ '\t': "&#9;",
+ '\n': "&#10;",
+ '\v': "&#11;",
+ '\f': "&#12;",
+ '\r': "&#13;",
+ ' ': "&#32;",
+ '"': "&#34;",
+ '\'': "&#39;",
+ '+': "&#43;",
+ '<': "&lt;",
+ '=': "&#61;",
+ '>': "&gt;",
+ // A parse error in the attribute value (unquoted) and
+ // before attribute value states.
+ // Treated as a quoting character by IE.
+ '`': "&#96;",
+}
+
+// htmlReplacer returns s with runes replaced acccording to replacementTable
+// and when badRunes is true, certain bad runes are allowed through unescaped.
+func htmlReplacer(s string, replacementTable []string, badRunes bool) string {
+ written, b := 0, new(bytes.Buffer)
+ for i, r := range s {
+ if r < len(replacementTable) {
+ if repl := replacementTable[r]; len(repl) != 0 {
+ b.WriteString(s[written:i])
+ b.WriteString(repl)
+ // Valid as long as replacementTable doesn't
+ // include anything above 0x7f.
+ written = i + utf8.RuneLen(r)
+ }
+ } else if badRunes {
+ // No-op.
+ // IE does not allow these ranges in unquoted attrs.
+ } else if 0xfdd0 <= r && r <= 0xfdef || 0xfff0 <= r && r <= 0xffff {
+ fmt.Fprintf(b, "%s&#x%x;", s[written:i], r)
+ written = i + utf8.RuneLen(r)
+ }
+ }
+ if written == 0 {
+ return s
+ }
+ b.WriteString(s[written:])
+ return b.String()
+}
+
+// stripTags takes a snippet of HTML and returns only the text content.
+// For example, `<b>&iexcl;Hi!</b> <script>...</script>` -> `&iexcl;Hi! `.
+func stripTags(html string) string {
+ var b bytes.Buffer
+ s, c, i, allText := []byte(html), context{}, 0, true
+ // Using the transition funcs helps us avoid mangling
+ // `<div title="1>2">` or `I <3 Ponies!`.
+ for i != len(s) {
+ if c.delim == delimNone {
+ st := c.state
+ // Use RCDATA instead of parsing into JS or CSS styles.
+ if c.element != elementNone && !isInTag(st) {
+ st = stateRCDATA
+ }
+ d, nread := transitionFunc[st](c, s[i:])
+ i1 := i + nread
+ if c.state == stateText || c.state == stateRCDATA {
+ // Emit text up to the start of the tag or comment.
+ j := i1
+ if d.state != c.state {
+ for j1 := j - 1; j1 >= i; j1-- {
+ if s[j1] == '<' {
+ j = j1
+ break
+ }
+ }
+ }
+ b.Write(s[i:j])
+ } else {
+ allText = false
+ }
+ c, i = d, i1
+ continue
+ }
+ i1 := i + bytes.IndexAny(s[i:], delimEnds[c.delim])
+ if i1 < i {
+ break
+ }
+ if c.delim != delimSpaceOrTagEnd {
+ // Consume any quote.
+ i1++
+ }
+ c, i = context{state: stateTag, element: c.element}, i1
+ }
+ if allText {
+ return html
+ } else if c.state == stateText || c.state == stateRCDATA {
+ b.Write(s[i:])
+ }
+ return b.String()
+}
+
+// htmlNameFilter accepts valid parts of an HTML attribute or tag name or
+// a known-safe HTML attribute.
+func htmlNameFilter(args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeHTMLAttr {
+ return s
+ }
+ if len(s) == 0 {
+ // Avoid violation of structure preservation.
+ // <input checked {{.K}}={{.V}}>.
+ // Without this, if .K is empty then .V is the value of
+ // checked, but otherwise .V is the value of the attribute
+ // named .K.
+ return filterFailsafe
+ }
+ s = strings.ToLower(s)
+ if t := attrType(s); t != contentTypePlain {
+ // TODO: Split attr and element name part filters so we can whitelist
+ // attributes.
+ return filterFailsafe
+ }
+ for _, r := range s {
+ switch {
+ case '0' <= r && r <= '9':
+ case 'a' <= r && r <= 'z':
+ default:
+ return filterFailsafe
+ }
+ }
+ return s
+}
+
+// commentEscaper returns the empty string regardless of input.
+// Comment content does not correspond to any parsed structure or
+// human-readable content, so the simplest and most secure policy is to drop
+// content interpolated into comments.
+// This approach is equally valid whether or not static comment content is
+// removed from the template.
+func commentEscaper(args ...interface{}) string {
+ return ""
+}
diff --git a/libgo/go/exp/template/html/html_test.go b/libgo/go/exp/template/html/html_test.go
new file mode 100644
index 00000000000..e178d0f27e5
--- /dev/null
+++ b/libgo/go/exp/template/html/html_test.go
@@ -0,0 +1,94 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "html"
+ "strings"
+ "testing"
+)
+
+func TestHTMLNospaceEscaper(t *testing.T) {
+ input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ ` !"#$%&'()*+,-./` +
+ `0123456789:;<=>?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ[\]^_` +
+ "`abcdefghijklmno" +
+ "pqrstuvwxyz{|}~\x7f" +
+ "\u00A0\u0100\u2028\u2029\ufeff\ufdec\U0001D11E")
+
+ want := ("&#xfffd;\x01\x02\x03\x04\x05\x06\x07" +
+ "\x08&#9;&#10;&#11;&#12;&#13;\x0E\x0F" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17" +
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ `&#32;!&#34;#$%&amp;&#39;()*&#43;,-./` +
+ `0123456789:;&lt;&#61;&gt;?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ[\]^_` +
+ `&#96;abcdefghijklmno` +
+ `pqrstuvwxyz{|}~` + "\u007f" +
+ "\u00A0\u0100\u2028\u2029\ufeff&#xfdec;\U0001D11E")
+
+ got := htmlNospaceEscaper(input)
+ if got != want {
+ t.Errorf("encode: want\n\t%q\nbut got\n\t%q", want, got)
+ }
+
+ got, want = html.UnescapeString(got), strings.Replace(input, "\x00", "\ufffd", 1)
+ if want != got {
+ t.Errorf("decode: want\n\t%q\nbut got\n\t%q", want, got)
+ }
+}
+
+func TestStripTags(t *testing.T) {
+ tests := []struct {
+ input, want string
+ }{
+ {"", ""},
+ {"Hello, World!", "Hello, World!"},
+ {"foo&amp;bar", "foo&amp;bar"},
+ {`Hello <a href="www.example.com/">World</a>!`, "Hello World!"},
+ {"Foo <textarea>Bar</textarea> Baz", "Foo Bar Baz"},
+ {"Foo <!-- Bar --> Baz", "Foo Baz"},
+ {"<", "<"},
+ {"foo < bar", "foo < bar"},
+ {`Foo<script type="text/javascript">alert(1337)</script>Bar`, "FooBar"},
+ {`Foo<div title="1>2">Bar`, "FooBar"},
+ {`I <3 Ponies!`, `I <3 Ponies!`},
+ {`<script>foo()</script>`, ``},
+ }
+
+ for _, test := range tests {
+ if got := stripTags(test.input); got != test.want {
+ t.Errorf("%q: want %q, got %q", test.input, test.want, got)
+ }
+ }
+}
+
+func BenchmarkHTMLNospaceEscaper(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ htmlNospaceEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+ }
+}
+
+func BenchmarkHTMLNospaceEscaperNoSpecials(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ htmlNospaceEscaper("The_quick,_brown_fox_jumps_over_the_lazy_dog.")
+ }
+}
+
+func BenchmarkStripTags(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ stripTags("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+ }
+}
+
+func BenchmarkStripTagsNoSpecials(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ stripTags("The quick, brown fox jumps over the lazy dog.")
+ }
+}
diff --git a/libgo/go/exp/template/html/js.go b/libgo/go/exp/template/html/js.go
new file mode 100644
index 00000000000..98c2ac5f27f
--- /dev/null
+++ b/libgo/go/exp/template/html/js.go
@@ -0,0 +1,346 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "fmt"
+ "json"
+ "strings"
+ "utf8"
+)
+
+// nextJSCtx returns the context that determines whether a slash after the
+// given run of tokens tokens starts a regular expression instead of a division
+// operator: / or /=.
+//
+// This assumes that the token run does not include any string tokens, comment
+// tokens, regular expression literal tokens, or division operators.
+//
+// This fails on some valid but nonsensical JavaScript programs like
+// "x = ++/foo/i" which is quite different than "x++/foo/i", but is not known to
+// fail on any known useful programs. It is based on the draft
+// JavaScript 2.0 lexical grammar and requires one token of lookbehind:
+// http://www.mozilla.org/js/language/js20-2000-07/rationale/syntax.html
+func nextJSCtx(s []byte, preceding jsCtx) jsCtx {
+ s = bytes.TrimRight(s, "\t\n\f\r \u2028\u2029")
+ if len(s) == 0 {
+ return preceding
+ }
+
+ // All cases below are in the single-byte UTF-8 group.
+ switch c, n := s[len(s)-1], len(s); c {
+ case '+', '-':
+ // ++ and -- are not regexp preceders, but + and - are whether
+ // they are used as infix or prefix operators.
+ start := n - 1
+ // Count the number of adjacent dashes or pluses.
+ for start > 0 && s[start-1] == c {
+ start--
+ }
+ if (n-start)&1 == 1 {
+ // Reached for trailing minus signs since "---" is the
+ // same as "-- -".
+ return jsCtxRegexp
+ }
+ return jsCtxDivOp
+ case '.':
+ // Handle "42."
+ if n != 1 && '0' <= s[n-2] && s[n-2] <= '9' {
+ return jsCtxDivOp
+ }
+ return jsCtxRegexp
+ // Suffixes for all punctuators from section 7.7 of the language spec
+ // that only end binary operators not handled above.
+ case ',', '<', '>', '=', '*', '%', '&', '|', '^', '?':
+ return jsCtxRegexp
+ // Suffixes for all punctuators from section 7.7 of the language spec
+ // that are prefix operators not handled above.
+ case '!', '~':
+ return jsCtxRegexp
+ // Matches all the punctuators from section 7.7 of the language spec
+ // that are open brackets not handled above.
+ case '(', '[':
+ return jsCtxRegexp
+ // Matches all the punctuators from section 7.7 of the language spec
+ // that precede expression starts.
+ case ':', ';', '{':
+ return jsCtxRegexp
+ // CAVEAT: the close punctuators ('}', ']', ')') precede div ops and
+ // are handled in the default except for '}' which can precede a
+ // division op as in
+ // ({ valueOf: function () { return 42 } } / 2
+ // which is valid, but, in practice, developers don't divide object
+ // literals, so our heuristic works well for code like
+ // function () { ... } /foo/.test(x) && sideEffect();
+ // The ')' punctuator can precede a regular expression as in
+ // if (b) /foo/.test(x) && ...
+ // but this is much less likely than
+ // (a + b) / c
+ case '}':
+ return jsCtxRegexp
+ default:
+ // Look for an IdentifierName and see if it is a keyword that
+ // can precede a regular expression.
+ j := n
+ for j > 0 && isJSIdentPart(int(s[j-1])) {
+ j--
+ }
+ if regexpPrecederKeywords[string(s[j:])] {
+ return jsCtxRegexp
+ }
+ }
+ // Otherwise is a punctuator not listed above, or
+ // a string which precedes a div op, or an identifier
+ // which precedes a div op.
+ return jsCtxDivOp
+}
+
+// regexPrecederKeywords is a set of reserved JS keywords that can precede a
+// regular expression in JS source.
+var regexpPrecederKeywords = map[string]bool{
+ "break": true,
+ "case": true,
+ "continue": true,
+ "delete": true,
+ "do": true,
+ "else": true,
+ "finally": true,
+ "in": true,
+ "instanceof": true,
+ "return": true,
+ "throw": true,
+ "try": true,
+ "typeof": true,
+ "void": true,
+}
+
+// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
+// nether side-effects nor free variables outside (NaN, Infinity).
+func jsValEscaper(args ...interface{}) string {
+ var a interface{}
+ if len(args) == 1 {
+ a = args[0]
+ switch t := a.(type) {
+ case JS:
+ return string(t)
+ case JSStr:
+ // TODO: normalize quotes.
+ return `"` + string(t) + `"`
+ case json.Marshaler:
+ // Do not treat as a Stringer.
+ case fmt.Stringer:
+ a = t.String()
+ }
+ } else {
+ a = fmt.Sprint(args...)
+ }
+ // TODO: detect cycles before calling Marshal which loops infinitely on
+ // cyclic data. This may be an unnacceptable DoS risk.
+
+ b, err := json.Marshal(a)
+ if err != nil {
+ // Put a space before comment so that if it is flush against
+ // a division operator it is not turned into a line comment:
+ // x/{{y}}
+ // turning into
+ // x//* error marshalling y:
+ // second line of error message */null
+ return fmt.Sprintf(" /* %s */null ", strings.Replace(err.String(), "*/", "* /", -1))
+ }
+
+ // TODO: maybe post-process output to prevent it from containing
+ // "<!--", "-->", "<![CDATA[", "]]>", or "</script"
+ // in case custom marshallers produce output containing those.
+
+ // TODO: Maybe abbreviate \u00ab to \xab to produce more compact output.
+ if len(b) == 0 {
+ // In, `x=y/{{.}}*z` a json.Marshaler that produces "" should
+ // not cause the output `x=y/*z`.
+ return " null "
+ }
+ first, _ := utf8.DecodeRune(b)
+ last, _ := utf8.DecodeLastRune(b)
+ var buf bytes.Buffer
+ // Prevent IdentifierNames and NumericLiterals from running into
+ // keywords: in, instanceof, typeof, void
+ pad := isJSIdentPart(first) || isJSIdentPart(last)
+ if pad {
+ buf.WriteByte(' ')
+ }
+ written := 0
+ // Make sure that json.Marshal escapes codepoints U+2028 & U+2029
+ // so it falls within the subset of JSON which is valid JS.
+ for i := 0; i < len(b); {
+ rune, n := utf8.DecodeRune(b[i:])
+ repl := ""
+ if rune == 0x2028 {
+ repl = `\u2028`
+ } else if rune == 0x2029 {
+ repl = `\u2029`
+ }
+ if repl != "" {
+ buf.Write(b[written:i])
+ buf.WriteString(repl)
+ written = i + n
+ }
+ i += n
+ }
+ if buf.Len() != 0 {
+ buf.Write(b[written:])
+ if pad {
+ buf.WriteByte(' ')
+ }
+ b = buf.Bytes()
+ }
+ return string(b)
+}
+
+// jsStrEscaper produces a string that can be included between quotes in
+// JavaScript source, in JavaScript embedded in an HTML5 <script> element,
+// or in an HTML5 event handler attribute such as onclick.
+func jsStrEscaper(args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeJSStr {
+ return replace(s, jsStrNormReplacementTable)
+ }
+ return replace(s, jsStrReplacementTable)
+}
+
+// jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression
+// specials so the result is treated literally when included in a regular
+// expression literal. /foo{{.X}}bar/ matches the string "foo" followed by
+// the literal text of {{.X}} followed by the string "bar".
+func jsRegexpEscaper(args ...interface{}) string {
+ s, _ := stringify(args...)
+ s = replace(s, jsRegexpReplacementTable)
+ if s == "" {
+ // /{{.X}}/ should not produce a line comment when .X == "".
+ return "(?:)"
+ }
+ return s
+}
+
+// replace replaces each rune r of s with replacementTable[r], provided that
+// r < len(replacementTable). If replacementTable[r] is the empty string then
+// no replacement is made.
+// It also replaces runes U+2028 and U+2029 with the raw strings `\u2028` and
+// `\u2029`.
+func replace(s string, replacementTable []string) string {
+ var b bytes.Buffer
+ written := 0
+ for i, r := range s {
+ var repl string
+ switch {
+ case r < len(replacementTable) && replacementTable[r] != "":
+ repl = replacementTable[r]
+ case r == '\u2028':
+ repl = `\u2028`
+ case r == '\u2029':
+ repl = `\u2029`
+ default:
+ continue
+ }
+ b.WriteString(s[written:i])
+ b.WriteString(repl)
+ written = i + utf8.RuneLen(r)
+ }
+ if written == 0 {
+ return s
+ }
+ b.WriteString(s[written:])
+ return b.String()
+}
+
+var jsStrReplacementTable = []string{
+ 0: `\0`,
+ '\t': `\t`,
+ '\n': `\n`,
+ '\v': `\x0b`, // "\v" == "v" on IE 6.
+ '\f': `\f`,
+ '\r': `\r`,
+ // Encode HTML specials as hex so the output can be embedded
+ // in HTML attributes without further encoding.
+ '"': `\x22`,
+ '&': `\x26`,
+ '\'': `\x27`,
+ '+': `\x2b`,
+ '/': `\/`,
+ '<': `\x3c`,
+ '>': `\x3e`,
+ '\\': `\\`,
+}
+
+// jsStrNormReplacementTable is like jsStrReplacementTable but does not
+// overencode existing escapes since this table has no entry for `\`.
+var jsStrNormReplacementTable = []string{
+ 0: `\0`,
+ '\t': `\t`,
+ '\n': `\n`,
+ '\v': `\x0b`, // "\v" == "v" on IE 6.
+ '\f': `\f`,
+ '\r': `\r`,
+ // Encode HTML specials as hex so the output can be embedded
+ // in HTML attributes without further encoding.
+ '"': `\x22`,
+ '&': `\x26`,
+ '\'': `\x27`,
+ '+': `\x2b`,
+ '/': `\/`,
+ '<': `\x3c`,
+ '>': `\x3e`,
+}
+
+var jsRegexpReplacementTable = []string{
+ 0: `\0`,
+ '\t': `\t`,
+ '\n': `\n`,
+ '\v': `\x0b`, // "\v" == "v" on IE 6.
+ '\f': `\f`,
+ '\r': `\r`,
+ // Encode HTML specials as hex so the output can be embedded
+ // in HTML attributes without further encoding.
+ '"': `\x22`,
+ '$': `\$`,
+ '&': `\x26`,
+ '\'': `\x27`,
+ '(': `\(`,
+ ')': `\)`,
+ '*': `\*`,
+ '+': `\x2b`,
+ '-': `\-`,
+ '.': `\.`,
+ '/': `\/`,
+ '<': `\x3c`,
+ '>': `\x3e`,
+ '?': `\?`,
+ '[': `\[`,
+ '\\': `\\`,
+ ']': `\]`,
+ '^': `\^`,
+ '{': `\{`,
+ '|': `\|`,
+ '}': `\}`,
+}
+
+// isJSIdentPart returns whether the given rune is a JS identifier part.
+// It does not handle all the non-Latin letters, joiners, and combining marks,
+// but it does handle every codepoint that can occur in a numeric literal or
+// a keyword.
+func isJSIdentPart(rune int) bool {
+ switch {
+ case '$' == rune:
+ return true
+ case '0' <= rune && rune <= '9':
+ return true
+ case 'A' <= rune && rune <= 'Z':
+ return true
+ case '_' == rune:
+ return true
+ case 'a' <= rune && rune <= 'z':
+ return true
+ }
+ return false
+}
diff --git a/libgo/go/exp/template/html/js_test.go b/libgo/go/exp/template/html/js_test.go
new file mode 100644
index 00000000000..e7764054a35
--- /dev/null
+++ b/libgo/go/exp/template/html/js_test.go
@@ -0,0 +1,401 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "math"
+ "strings"
+ "testing"
+)
+
+func TestNextJsCtx(t *testing.T) {
+ tests := []struct {
+ jsCtx jsCtx
+ s string
+ }{
+ // Statement terminators precede regexps.
+ {jsCtxRegexp, ";"},
+ // This is not airtight.
+ // ({ valueOf: function () { return 1 } } / 2)
+ // is valid JavaScript but in practice, devs do not do this.
+ // A block followed by a statement starting with a RegExp is
+ // much more common:
+ // while (x) {...} /foo/.test(x) || panic()
+ {jsCtxRegexp, "}"},
+ // But member, call, grouping, and array expression terminators
+ // precede div ops.
+ {jsCtxDivOp, ")"},
+ {jsCtxDivOp, "]"},
+ // At the start of a primary expression, array, or expression
+ // statement, expect a regexp.
+ {jsCtxRegexp, "("},
+ {jsCtxRegexp, "["},
+ {jsCtxRegexp, "{"},
+ // Assignment operators precede regexps as do all exclusively
+ // prefix and binary operators.
+ {jsCtxRegexp, "="},
+ {jsCtxRegexp, "+="},
+ {jsCtxRegexp, "*="},
+ {jsCtxRegexp, "*"},
+ {jsCtxRegexp, "!"},
+ // Whether the + or - is infix or prefix, it cannot precede a
+ // div op.
+ {jsCtxRegexp, "+"},
+ {jsCtxRegexp, "-"},
+ // An incr/decr op precedes a div operator.
+ // This is not airtight. In (g = ++/h/i) a regexp follows a
+ // pre-increment operator, but in practice devs do not try to
+ // increment or decrement regular expressions.
+ // (g++/h/i) where ++ is a postfix operator on g is much more
+ // common.
+ {jsCtxDivOp, "--"},
+ {jsCtxDivOp, "++"},
+ {jsCtxDivOp, "x--"},
+ // When we have many dashes or pluses, then they are grouped
+ // left to right.
+ {jsCtxRegexp, "x---"}, // A postfix -- then a -.
+ // return followed by a slash returns the regexp literal or the
+ // slash starts a regexp literal in an expression statement that
+ // is dead code.
+ {jsCtxRegexp, "return"},
+ {jsCtxRegexp, "return "},
+ {jsCtxRegexp, "return\t"},
+ {jsCtxRegexp, "return\n"},
+ {jsCtxRegexp, "return\u2028"},
+ // Identifiers can be divided and cannot validly be preceded by
+ // a regular expressions. Semicolon insertion cannot happen
+ // between an identifier and a regular expression on a new line
+ // because the one token lookahead for semicolon insertion has
+ // to conclude that it could be a div binary op and treat it as
+ // such.
+ {jsCtxDivOp, "x"},
+ {jsCtxDivOp, "x "},
+ {jsCtxDivOp, "x\t"},
+ {jsCtxDivOp, "x\n"},
+ {jsCtxDivOp, "x\u2028"},
+ {jsCtxDivOp, "preturn"},
+ // Numbers precede div ops.
+ {jsCtxDivOp, "0"},
+ // Dots that are part of a number are div preceders.
+ {jsCtxDivOp, "0."},
+ }
+
+ for _, test := range tests {
+ if nextJSCtx([]byte(test.s), jsCtxRegexp) != test.jsCtx {
+ t.Errorf("want %s got %q", test.jsCtx, test.s)
+ }
+ if nextJSCtx([]byte(test.s), jsCtxDivOp) != test.jsCtx {
+ t.Errorf("want %s got %q", test.jsCtx, test.s)
+ }
+ }
+
+ if nextJSCtx([]byte(" "), jsCtxRegexp) != jsCtxRegexp {
+ t.Error("Blank tokens")
+ }
+
+ if nextJSCtx([]byte(" "), jsCtxDivOp) != jsCtxDivOp {
+ t.Error("Blank tokens")
+ }
+}
+
+func TestJSValEscaper(t *testing.T) {
+ tests := []struct {
+ x interface{}
+ js string
+ }{
+ {int(42), " 42 "},
+ {uint(42), " 42 "},
+ {int16(42), " 42 "},
+ {uint16(42), " 42 "},
+ {int32(-42), " -42 "},
+ {uint32(42), " 42 "},
+ {int16(-42), " -42 "},
+ {uint16(42), " 42 "},
+ {int64(-42), " -42 "},
+ {uint64(42), " 42 "},
+ {uint64(1) << 53, " 9007199254740992 "},
+ // ulp(1 << 53) > 1 so this loses precision in JS
+ // but it is still a representable integer literal.
+ {uint64(1)<<53 + 1, " 9007199254740993 "},
+ {float32(1.0), " 1 "},
+ {float32(-1.0), " -1 "},
+ {float32(0.5), " 0.5 "},
+ {float32(-0.5), " -0.5 "},
+ {float32(1.0) / float32(256), " 0.00390625 "},
+ {float32(0), " 0 "},
+ {math.Copysign(0, -1), " -0 "},
+ {float64(1.0), " 1 "},
+ {float64(-1.0), " -1 "},
+ {float64(0.5), " 0.5 "},
+ {float64(-0.5), " -0.5 "},
+ {float64(0), " 0 "},
+ {math.Copysign(0, -1), " -0 "},
+ {"", `""`},
+ {"foo", `"foo"`},
+ // Newlines.
+ {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
+ // "\v" == "v" on IE 6 so use "\x0b" instead.
+ {"\t\x0b", `"\u0009\u000b"`},
+ {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
+ {[]interface{}{}, "[]"},
+ {[]interface{}{42, "foo", nil}, `[42,"foo",null]`},
+ {[]string{"<!--", "</script>", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`},
+ {"<!--", `"\u003c!--"`},
+ {"-->", `"--\u003e"`},
+ {"<![CDATA[", `"\u003c![CDATA["`},
+ {"]]>", `"]]\u003e"`},
+ {"</script", `"\u003c/script"`},
+ {"\U0001D11E", "\"\U0001D11E\""}, // or "\uD834\uDD1E"
+ }
+
+ for _, test := range tests {
+ if js := jsValEscaper(test.x); js != test.js {
+ t.Errorf("%+v: want\n\t%q\ngot\n\t%q", test.x, test.js, js)
+ }
+ // Make sure that escaping corner cases are not broken
+ // by nesting.
+ a := []interface{}{test.x}
+ want := "[" + strings.TrimSpace(test.js) + "]"
+ if js := jsValEscaper(a); js != want {
+ t.Errorf("%+v: want\n\t%q\ngot\n\t%q", a, want, js)
+ }
+ }
+}
+
+func TestJSStrEscaper(t *testing.T) {
+ tests := []struct {
+ x interface{}
+ esc string
+ }{
+ {"", ``},
+ {"foo", `foo`},
+ {"\u0000", `\0`},
+ {"\t", `\t`},
+ {"\n", `\n`},
+ {"\r", `\r`},
+ {"\u2028", `\u2028`},
+ {"\u2029", `\u2029`},
+ {"\\", `\\`},
+ {"\\n", `\\n`},
+ {"foo\r\nbar", `foo\r\nbar`},
+ // Preserve attribute boundaries.
+ {`"`, `\x22`},
+ {`'`, `\x27`},
+ // Allow embedding in HTML without further escaping.
+ {`&amp;`, `\x26amp;`},
+ // Prevent breaking out of text node and element boundaries.
+ {"</script>", `\x3c\/script\x3e`},
+ {"<![CDATA[", `\x3c![CDATA[`},
+ {"]]>", `]]\x3e`},
+ // http://dev.w3.org/html5/markup/aria/syntax.html#escaping-text-span
+ // "The text in style, script, title, and textarea elements
+ // must not have an escaping text span start that is not
+ // followed by an escaping text span end."
+ // Furthermore, spoofing an escaping text span end could lead
+ // to different interpretation of a </script> sequence otherwise
+ // masked by the escaping text span, and spoofing a start could
+ // allow regular text content to be interpreted as script
+ // allowing script execution via a combination of a JS string
+ // injection followed by an HTML text injection.
+ {"<!--", `\x3c!--`},
+ {"-->", `--\x3e`},
+ // From http://code.google.com/p/doctype/wiki/ArticleUtf7
+ {"+ADw-script+AD4-alert(1)+ADw-/script+AD4-",
+ `\x2bADw-script\x2bAD4-alert(1)\x2bADw-\/script\x2bAD4-`,
+ },
+ // Invalid UTF-8 sequence
+ {"foo\xA0bar", "foo\xA0bar"},
+ // Invalid unicode scalar value.
+ {"foo\xed\xa0\x80bar", "foo\xed\xa0\x80bar"},
+ }
+
+ for _, test := range tests {
+ esc := jsStrEscaper(test.x)
+ if esc != test.esc {
+ t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
+ }
+ }
+}
+
+func TestJSRegexpEscaper(t *testing.T) {
+ tests := []struct {
+ x interface{}
+ esc string
+ }{
+ {"", `(?:)`},
+ {"foo", `foo`},
+ {"\u0000", `\0`},
+ {"\t", `\t`},
+ {"\n", `\n`},
+ {"\r", `\r`},
+ {"\u2028", `\u2028`},
+ {"\u2029", `\u2029`},
+ {"\\", `\\`},
+ {"\\n", `\\n`},
+ {"foo\r\nbar", `foo\r\nbar`},
+ // Preserve attribute boundaries.
+ {`"`, `\x22`},
+ {`'`, `\x27`},
+ // Allow embedding in HTML without further escaping.
+ {`&amp;`, `\x26amp;`},
+ // Prevent breaking out of text node and element boundaries.
+ {"</script>", `\x3c\/script\x3e`},
+ {"<![CDATA[", `\x3c!\[CDATA\[`},
+ {"]]>", `\]\]\x3e`},
+ // Escaping text spans.
+ {"<!--", `\x3c!\-\-`},
+ {"-->", `\-\-\x3e`},
+ {"*", `\*`},
+ {"+", `\x2b`},
+ {"?", `\?`},
+ {"[](){}", `\[\]\(\)\{\}`},
+ {"$foo|x.y", `\$foo\|x\.y`},
+ {"x^y", `x\^y`},
+ }
+
+ for _, test := range tests {
+ esc := jsRegexpEscaper(test.x)
+ if esc != test.esc {
+ t.Errorf("%q: want %q got %q", test.x, test.esc, esc)
+ }
+ }
+}
+
+func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
+ input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ ` !"#$%&'()*+,-./` +
+ `0123456789:;<=>?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ[\]^_` +
+ "`abcdefghijklmno" +
+ "pqrstuvwxyz{|}~\x7f" +
+ "\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+ tests := []struct {
+ name string
+ escaper func(...interface{}) string
+ escaped string
+ }{
+ {
+ "jsStrEscaper",
+ jsStrEscaper,
+ "\\0\x01\x02\x03\x04\x05\x06\x07" +
+ "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17" +
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ ` !\x22#$%\x26\x27()*\x2b,-.\/` +
+ `0123456789:;\x3c=\x3e?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ[\\]^_` +
+ "`abcdefghijklmno" +
+ "pqrstuvwxyz{|}~\x7f" +
+ "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
+ },
+ {
+ "jsRegexpEscaper",
+ jsRegexpEscaper,
+ "\\0\x01\x02\x03\x04\x05\x06\x07" +
+ "\x08\\t\\n\\x0b\\f\\r\x0E\x0F" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17" +
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ ` !\x22#\$%\x26\x27\(\)\*\x2b,\-\.\/` +
+ `0123456789:;\x3c=\x3e\?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ\[\\\]\^_` +
+ "`abcdefghijklmno" +
+ `pqrstuvwxyz\{\|\}~` + "\u007f" +
+ "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
+ },
+ }
+
+ for _, test := range tests {
+ if s := test.escaper(input); s != test.escaped {
+ t.Errorf("%s once: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+ continue
+ }
+
+ // Escape it rune by rune to make sure that any
+ // fast-path checking does not break escaping.
+ var buf bytes.Buffer
+ for _, c := range input {
+ buf.WriteString(test.escaper(string(c)))
+ }
+
+ if s := buf.String(); s != test.escaped {
+ t.Errorf("%s rune-wise: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+ continue
+ }
+ }
+}
+
+func BenchmarkJSValEscaperWithNum(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ jsValEscaper(3.141592654)
+ }
+}
+
+func BenchmarkJSValEscaperWithStr(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ jsValEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+ }
+}
+
+func BenchmarkJSValEscaperWithStrNoSpecials(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ jsValEscaper("The quick, brown fox jumps over the lazy dog")
+ }
+}
+
+func BenchmarkJSValEscaperWithObj(b *testing.B) {
+ o := struct {
+ S string
+ N int
+ }{
+ "The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>\u2028",
+ 42,
+ }
+ for i := 0; i < b.N; i++ {
+ jsValEscaper(o)
+ }
+}
+
+func BenchmarkJSValEscaperWithObjNoSpecials(b *testing.B) {
+ o := struct {
+ S string
+ N int
+ }{
+ "The quick, brown fox jumps over the lazy dog",
+ 42,
+ }
+ for i := 0; i < b.N; i++ {
+ jsValEscaper(o)
+ }
+}
+
+func BenchmarkJSStrEscaperNoSpecials(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ jsStrEscaper("The quick, brown fox jumps over the lazy dog.")
+ }
+}
+
+func BenchmarkJSStrEscaper(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ jsStrEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+ }
+}
+
+func BenchmarkJSRegexpEscaperNoSpecials(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ jsRegexpEscaper("The quick, brown fox jumps over the lazy dog")
+ }
+}
+
+func BenchmarkJSRegexpEscaper(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ jsRegexpEscaper("The <i>quick</i>,\r\n<span style='color:brown'>brown</span> fox jumps\u2028over the <canine class=\"lazy\">dog</canine>")
+ }
+}
diff --git a/libgo/go/exp/template/html/transition.go b/libgo/go/exp/template/html/transition.go
new file mode 100644
index 00000000000..49a14511745
--- /dev/null
+++ b/libgo/go/exp/template/html/transition.go
@@ -0,0 +1,553 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "strings"
+)
+
+// transitionFunc is the array of context transition functions for text nodes.
+// A transition function takes a context and template text input, and returns
+// the updated context and the number of bytes consumed from the front of the
+// input.
+var transitionFunc = [...]func(context, []byte) (context, int){
+ stateText: tText,
+ stateTag: tTag,
+ stateAttrName: tAttrName,
+ stateAfterName: tAfterName,
+ stateBeforeValue: tBeforeValue,
+ stateHTMLCmt: tHTMLCmt,
+ stateRCDATA: tSpecialTagEnd,
+ stateAttr: tAttr,
+ stateURL: tURL,
+ stateJS: tJS,
+ stateJSDqStr: tJSDelimited,
+ stateJSSqStr: tJSDelimited,
+ stateJSRegexp: tJSDelimited,
+ stateJSBlockCmt: tBlockCmt,
+ stateJSLineCmt: tLineCmt,
+ stateCSS: tCSS,
+ stateCSSDqStr: tCSSStr,
+ stateCSSSqStr: tCSSStr,
+ stateCSSDqURL: tCSSStr,
+ stateCSSSqURL: tCSSStr,
+ stateCSSURL: tCSSStr,
+ stateCSSBlockCmt: tBlockCmt,
+ stateCSSLineCmt: tLineCmt,
+ stateError: tError,
+}
+
+var commentStart = []byte("<!--")
+var commentEnd = []byte("-->")
+
+// tText is the context transition function for the text state.
+func tText(c context, s []byte) (context, int) {
+ k := 0
+ for {
+ i := k + bytes.IndexByte(s[k:], '<')
+ if i < k || i+1 == len(s) {
+ return c, len(s)
+ } else if i+4 <= len(s) && bytes.Equal(commentStart, s[i:i+4]) {
+ return context{state: stateHTMLCmt}, i + 4
+ }
+ i++
+ end := false
+ if s[i] == '/' {
+ if i+1 == len(s) {
+ return c, len(s)
+ }
+ end, i = true, i+1
+ }
+ j, e := eatTagName(s, i)
+ if j != i {
+ if end {
+ e = elementNone
+ }
+ // We've found an HTML tag.
+ return context{state: stateTag, element: e}, j
+ }
+ k = j
+ }
+ panic("unreachable")
+}
+
+var elementContentType = [...]state{
+ elementNone: stateText,
+ elementScript: stateJS,
+ elementStyle: stateCSS,
+ elementTextarea: stateRCDATA,
+ elementTitle: stateRCDATA,
+}
+
+// tTag is the context transition function for the tag state.
+func tTag(c context, s []byte) (context, int) {
+ // Find the attribute name.
+ i := eatWhiteSpace(s, 0)
+ if i == len(s) {
+ return c, len(s)
+ }
+ if s[i] == '>' {
+ return context{
+ state: elementContentType[c.element],
+ element: c.element,
+ }, i + 1
+ }
+ j, err := eatAttrName(s, i)
+ if err != nil {
+ return context{state: stateError, err: err}, len(s)
+ }
+ state, attr := stateTag, attrNone
+ if i == j {
+ return context{
+ state: stateError,
+ err: errorf(ErrBadHTML, 0, "expected space, attr name, or end of tag, but got %q", s[i:]),
+ }, len(s)
+ }
+ switch attrType(string(s[i:j])) {
+ case contentTypeURL:
+ attr = attrURL
+ case contentTypeCSS:
+ attr = attrStyle
+ case contentTypeJS:
+ attr = attrScript
+ }
+ if j == len(s) {
+ state = stateAttrName
+ } else {
+ state = stateAfterName
+ }
+ return context{state: state, element: c.element, attr: attr}, j
+}
+
+// tAttrName is the context transition function for stateAttrName.
+func tAttrName(c context, s []byte) (context, int) {
+ i, err := eatAttrName(s, 0)
+ if err != nil {
+ return context{state: stateError, err: err}, len(s)
+ } else if i != len(s) {
+ c.state = stateAfterName
+ }
+ return c, i
+}
+
+// tAfterName is the context transition function for stateAfterName.
+func tAfterName(c context, s []byte) (context, int) {
+ // Look for the start of the value.
+ i := eatWhiteSpace(s, 0)
+ if i == len(s) {
+ return c, len(s)
+ } else if s[i] != '=' {
+ // Occurs due to tag ending '>', and valueless attribute.
+ c.state = stateTag
+ return c, i
+ }
+ c.state = stateBeforeValue
+ // Consume the "=".
+ return c, i + 1
+}
+
+var attrStartStates = [...]state{
+ attrNone: stateAttr,
+ attrScript: stateJS,
+ attrStyle: stateCSS,
+ attrURL: stateURL,
+}
+
+// tBeforeValue is the context transition function for stateBeforeValue.
+func tBeforeValue(c context, s []byte) (context, int) {
+ i := eatWhiteSpace(s, 0)
+ if i == len(s) {
+ return c, len(s)
+ }
+ // Find the attribute delimiter.
+ delim := delimSpaceOrTagEnd
+ switch s[i] {
+ case '\'':
+ delim, i = delimSingleQuote, i+1
+ case '"':
+ delim, i = delimDoubleQuote, i+1
+ }
+ c.state, c.delim, c.attr = attrStartStates[c.attr], delim, attrNone
+ return c, i
+}
+
+// tHTMLCmt is the context transition function for stateHTMLCmt.
+func tHTMLCmt(c context, s []byte) (context, int) {
+ if i := bytes.Index(s, commentEnd); i != -1 {
+ return context{}, i + 3
+ }
+ return c, len(s)
+}
+
+// specialTagEndMarkers maps element types to the character sequence that
+// case-insensitively signals the end of the special tag body.
+var specialTagEndMarkers = [...]string{
+ elementScript: "</script",
+ elementStyle: "</style",
+ elementTextarea: "</textarea",
+ elementTitle: "</title",
+}
+
+// tSpecialTagEnd is the context transition function for raw text and RCDATA
+// element states.
+func tSpecialTagEnd(c context, s []byte) (context, int) {
+ if c.element != elementNone {
+ if i := strings.Index(strings.ToLower(string(s)), specialTagEndMarkers[c.element]); i != -1 {
+ return context{}, i
+ }
+ }
+ return c, len(s)
+}
+
+// tAttr is the context transition function for the attribute state.
+func tAttr(c context, s []byte) (context, int) {
+ return c, len(s)
+}
+
+// tURL is the context transition function for the URL state.
+func tURL(c context, s []byte) (context, int) {
+ if bytes.IndexAny(s, "#?") >= 0 {
+ c.urlPart = urlPartQueryOrFrag
+ } else if len(s) != eatWhiteSpace(s, 0) && c.urlPart == urlPartNone {
+ // HTML5 uses "Valid URL potentially surrounded by spaces" for
+ // attrs: http://www.w3.org/TR/html5/index.html#attributes-1
+ c.urlPart = urlPartPreQuery
+ }
+ return c, len(s)
+}
+
+// tJS is the context transition function for the JS state.
+func tJS(c context, s []byte) (context, int) {
+ i := bytes.IndexAny(s, `"'/`)
+ if i == -1 {
+ // Entire input is non string, comment, regexp tokens.
+ c.jsCtx = nextJSCtx(s, c.jsCtx)
+ return c, len(s)
+ }
+ c.jsCtx = nextJSCtx(s[:i], c.jsCtx)
+ switch s[i] {
+ case '"':
+ c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp
+ case '\'':
+ c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp
+ case '/':
+ switch {
+ case i+1 < len(s) && s[i+1] == '/':
+ c.state, i = stateJSLineCmt, i+1
+ case i+1 < len(s) && s[i+1] == '*':
+ c.state, i = stateJSBlockCmt, i+1
+ case c.jsCtx == jsCtxRegexp:
+ c.state = stateJSRegexp
+ case c.jsCtx == jsCtxDivOp:
+ c.jsCtx = jsCtxRegexp
+ default:
+ return context{
+ state: stateError,
+ err: errorf(ErrSlashAmbig, 0, "'/' could start a division or regexp: %.32q", s[i:]),
+ }, len(s)
+ }
+ default:
+ panic("unreachable")
+ }
+ return c, i + 1
+}
+
+// tJSDelimited is the context transition function for the JS string and regexp
+// states.
+func tJSDelimited(c context, s []byte) (context, int) {
+ specials := `\"`
+ switch c.state {
+ case stateJSSqStr:
+ specials = `\'`
+ case stateJSRegexp:
+ specials = `\/[]`
+ }
+
+ k, inCharset := 0, false
+ for {
+ i := k + bytes.IndexAny(s[k:], specials)
+ if i < k {
+ break
+ }
+ switch s[i] {
+ case '\\':
+ i++
+ if i == len(s) {
+ return context{
+ state: stateError,
+ err: errorf(ErrPartialEscape, 0, "unfinished escape sequence in JS string: %q", s),
+ }, len(s)
+ }
+ case '[':
+ inCharset = true
+ case ']':
+ inCharset = false
+ default:
+ // end delimiter
+ if !inCharset {
+ c.state, c.jsCtx = stateJS, jsCtxDivOp
+ return c, i + 1
+ }
+ }
+ k = i + 1
+ }
+
+ if inCharset {
+ // This can be fixed by making context richer if interpolation
+ // into charsets is desired.
+ return context{
+ state: stateError,
+ err: errorf(ErrPartialCharset, 0, "unfinished JS regexp charset: %q", s),
+ }, len(s)
+ }
+
+ return c, len(s)
+}
+
+var blockCommentEnd = []byte("*/")
+
+// tBlockCmt is the context transition function for /*comment*/ states.
+func tBlockCmt(c context, s []byte) (context, int) {
+ i := bytes.Index(s, blockCommentEnd)
+ if i == -1 {
+ return c, len(s)
+ }
+ switch c.state {
+ case stateJSBlockCmt:
+ c.state = stateJS
+ case stateCSSBlockCmt:
+ c.state = stateCSS
+ default:
+ panic(c.state.String())
+ }
+ return c, i + 2
+}
+
+// tLineCmt is the context transition function for //comment states.
+func tLineCmt(c context, s []byte) (context, int) {
+ var lineTerminators string
+ var endState state
+ switch c.state {
+ case stateJSLineCmt:
+ lineTerminators, endState = "\n\r\u2028\u2029", stateJS
+ case stateCSSLineCmt:
+ lineTerminators, endState = "\n\f\r", stateCSS
+ // Line comments are not part of any published CSS standard but
+ // are supported by the 4 major browsers.
+ // This defines line comments as
+ // LINECOMMENT ::= "//" [^\n\f\d]*
+ // since http://www.w3.org/TR/css3-syntax/#SUBTOK-nl defines
+ // newlines:
+ // nl ::= #xA | #xD #xA | #xD | #xC
+ default:
+ panic(c.state.String())
+ }
+
+ i := bytes.IndexAny(s, lineTerminators)
+ if i == -1 {
+ return c, len(s)
+ }
+ c.state = endState
+ // Per section 7.4 of EcmaScript 5 : http://es5.github.com/#x7.4
+ // "However, the LineTerminator at the end of the line is not
+ // considered to be part of the single-line comment; it is
+ // recognized separately by the lexical grammar and becomes part
+ // of the stream of input elements for the syntactic grammar."
+ return c, i
+}
+
+// tCSS is the context transition function for the CSS state.
+func tCSS(c context, s []byte) (context, int) {
+ // CSS quoted strings are almost never used except for:
+ // (1) URLs as in background: "/foo.png"
+ // (2) Multiword font-names as in font-family: "Times New Roman"
+ // (3) List separators in content values as in inline-lists:
+ // <style>
+ // ul.inlineList { list-style: none; padding:0 }
+ // ul.inlineList > li { display: inline }
+ // ul.inlineList > li:before { content: ", " }
+ // ul.inlineList > li:first-child:before { content: "" }
+ // </style>
+ // <ul class=inlineList><li>One<li>Two<li>Three</ul>
+ // (4) Attribute value selectors as in a[href="http://example.com/"]
+ //
+ // We conservatively treat all strings as URLs, but make some
+ // allowances to avoid confusion.
+ //
+ // In (1), our conservative assumption is justified.
+ // In (2), valid font names do not contain ':', '?', or '#', so our
+ // conservative assumption is fine since we will never transition past
+ // urlPartPreQuery.
+ // In (3), our protocol heuristic should not be tripped, and there
+ // should not be non-space content after a '?' or '#', so as long as
+ // we only %-encode RFC 3986 reserved characters we are ok.
+ // In (4), we should URL escape for URL attributes, and for others we
+ // have the attribute name available if our conservative assumption
+ // proves problematic for real code.
+
+ k := 0
+ for {
+ i := k + bytes.IndexAny(s[k:], `("'/`)
+ if i < k {
+ return c, len(s)
+ }
+ switch s[i] {
+ case '(':
+ // Look for url to the left.
+ p := bytes.TrimRight(s[:i], "\t\n\f\r ")
+ if endsWithCSSKeyword(p, "url") {
+ j := len(s) - len(bytes.TrimLeft(s[i+1:], "\t\n\f\r "))
+ switch {
+ case j != len(s) && s[j] == '"':
+ c.state, j = stateCSSDqURL, j+1
+ case j != len(s) && s[j] == '\'':
+ c.state, j = stateCSSSqURL, j+1
+ default:
+ c.state = stateCSSURL
+ }
+ return c, j
+ }
+ case '/':
+ if i+1 < len(s) {
+ switch s[i+1] {
+ case '/':
+ c.state = stateCSSLineCmt
+ return c, i + 2
+ case '*':
+ c.state = stateCSSBlockCmt
+ return c, i + 2
+ }
+ }
+ case '"':
+ c.state = stateCSSDqStr
+ return c, i + 1
+ case '\'':
+ c.state = stateCSSSqStr
+ return c, i + 1
+ }
+ k = i + 1
+ }
+ panic("unreachable")
+}
+
+// tCSSStr is the context transition function for the CSS string and URL states.
+func tCSSStr(c context, s []byte) (context, int) {
+ var endAndEsc string
+ switch c.state {
+ case stateCSSDqStr, stateCSSDqURL:
+ endAndEsc = `\"`
+ case stateCSSSqStr, stateCSSSqURL:
+ endAndEsc = `\'`
+ case stateCSSURL:
+ // Unquoted URLs end with a newline or close parenthesis.
+ // The below includes the wc (whitespace character) and nl.
+ endAndEsc = "\\\t\n\f\r )"
+ default:
+ panic(c.state.String())
+ }
+
+ k := 0
+ for {
+ i := k + bytes.IndexAny(s[k:], endAndEsc)
+ if i < k {
+ c, nread := tURL(c, decodeCSS(s[k:]))
+ return c, k + nread
+ }
+ if s[i] == '\\' {
+ i++
+ if i == len(s) {
+ return context{
+ state: stateError,
+ err: errorf(ErrPartialEscape, 0, "unfinished escape sequence in CSS string: %q", s),
+ }, len(s)
+ }
+ } else {
+ c.state = stateCSS
+ return c, i + 1
+ }
+ c, _ = tURL(c, decodeCSS(s[:i+1]))
+ k = i + 1
+ }
+ panic("unreachable")
+}
+
+// tError is the context transition function for the error state.
+func tError(c context, s []byte) (context, int) {
+ return c, len(s)
+}
+
+// eatAttrName returns the largest j such that s[i:j] is an attribute name.
+// It returns an error if s[i:] does not look like it begins with an
+// attribute name, such as encountering a quote mark without a preceding
+// equals sign.
+func eatAttrName(s []byte, i int) (int, *Error) {
+ for j := i; j < len(s); j++ {
+ switch s[j] {
+ case ' ', '\t', '\n', '\f', '\r', '=', '>':
+ return j, nil
+ case '\'', '"', '<':
+ // These result in a parse warning in HTML5 and are
+ // indicative of serious problems if seen in an attr
+ // name in a template.
+ return -1, errorf(ErrBadHTML, 0, "%q in attribute name: %.32q", s[j:j+1], s)
+ default:
+ // No-op.
+ }
+ }
+ return len(s), nil
+}
+
+var elementNameMap = map[string]element{
+ "script": elementScript,
+ "style": elementStyle,
+ "textarea": elementTextarea,
+ "title": elementTitle,
+}
+
+// asciiAlpha returns whether c is an ASCII letter.
+func asciiAlpha(c byte) bool {
+ return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
+}
+
+// asciiAlphaNum returns whether c is an ASCII letter or digit.
+func asciiAlphaNum(c byte) bool {
+ return asciiAlpha(c) || '0' <= c && c <= '9'
+}
+
+// eatTagName returns the largest j such that s[i:j] is a tag name and the tag type.
+func eatTagName(s []byte, i int) (int, element) {
+ if i == len(s) || !asciiAlpha(s[i]) {
+ return i, elementNone
+ }
+ j := i + 1
+ for j < len(s) {
+ x := s[j]
+ if asciiAlphaNum(x) {
+ j++
+ continue
+ }
+ // Allow "x-y" or "x:y" but not "x-", "-y", or "x--y".
+ if (x == ':' || x == '-') && j+1 < len(s) && asciiAlphaNum(s[j+1]) {
+ j += 2
+ continue
+ }
+ break
+ }
+ return j, elementNameMap[strings.ToLower(string(s[i:j]))]
+}
+
+// eatWhiteSpace returns the largest j such that s[i:j] is white space.
+func eatWhiteSpace(s []byte, i int) int {
+ for j := i; j < len(s); j++ {
+ switch s[j] {
+ case ' ', '\t', '\n', '\f', '\r':
+ // No-op.
+ default:
+ return j
+ }
+ }
+ return len(s)
+}
diff --git a/libgo/go/exp/template/html/url.go b/libgo/go/exp/template/html/url.go
new file mode 100644
index 00000000000..5b19df08404
--- /dev/null
+++ b/libgo/go/exp/template/html/url.go
@@ -0,0 +1,105 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+)
+
+// urlFilter returns its input unless it contains an unsafe protocol in which
+// case it defangs the entire URL.
+func urlFilter(args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeURL {
+ return s
+ }
+ if i := strings.IndexRune(s, ':'); i >= 0 && strings.IndexRune(s[:i], '/') < 0 {
+ protocol := strings.ToLower(s[:i])
+ if protocol != "http" && protocol != "https" && protocol != "mailto" {
+ return "#" + filterFailsafe
+ }
+ }
+ return s
+}
+
+// urlEscaper produces an output that can be embedded in a URL query.
+// The output can be embedded in an HTML attribute without further escaping.
+func urlEscaper(args ...interface{}) string {
+ return urlProcessor(false, args...)
+}
+
+// urlEscaper normalizes URL content so it can be embedded in a quote-delimited
+// string or parenthesis delimited url(...).
+// The normalizer does not encode all HTML specials. Specifically, it does not
+// encode '&' so correct embedding in an HTML attribute requires escaping of
+// '&' to '&amp;'.
+func urlNormalizer(args ...interface{}) string {
+ return urlProcessor(true, args...)
+}
+
+// urlProcessor normalizes (when norm is true) or escapes its input to produce
+// a valid hierarchical or opaque URL part.
+func urlProcessor(norm bool, args ...interface{}) string {
+ s, t := stringify(args...)
+ if t == contentTypeURL {
+ norm = true
+ }
+ var b bytes.Buffer
+ written := 0
+ // The byte loop below assumes that all URLs use UTF-8 as the
+ // content-encoding. This is similar to the URI to IRI encoding scheme
+ // defined in section 3.1 of RFC 3987, and behaves the same as the
+ // EcmaScript builtin encodeURIComponent.
+ // It should not cause any misencoding of URLs in pages with
+ // Content-type: text/html;charset=UTF-8.
+ for i, n := 0, len(s); i < n; i++ {
+ c := s[i]
+ switch c {
+ // Single quote and parens are sub-delims in RFC 3986, but we
+ // escape them so the output can be embedded in in single
+ // quoted attributes and unquoted CSS url(...) constructs.
+ // Single quotes are reserved in URLs, but are only used in
+ // the obsolete "mark" rule in an appendix in RFC 3986
+ // so can be safely encoded.
+ case '!', '#', '$', '&', '*', '+', ',', '/', ':', ';', '=', '?', '@', '[', ']':
+ if norm {
+ continue
+ }
+ // Unreserved according to RFC 3986 sec 2.3
+ // "For consistency, percent-encoded octets in the ranges of
+ // ALPHA (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D),
+ // period (%2E), underscore (%5F), or tilde (%7E) should not be
+ // created by URI producers
+ case '-', '.', '_', '~':
+ continue
+ case '%':
+ // When normalizing do not re-encode valid escapes.
+ if norm && i+2 < len(s) && isHex(s[i+1]) && isHex(s[i+2]) {
+ continue
+ }
+ default:
+ // Unreserved according to RFC 3986 sec 2.3
+ if 'a' <= c && c <= 'z' {
+ continue
+ }
+ if 'A' <= c && c <= 'Z' {
+ continue
+ }
+ if '0' <= c && c <= '9' {
+ continue
+ }
+ }
+ b.WriteString(s[written:i])
+ fmt.Fprintf(&b, "%%%02x", c)
+ written = i + 1
+ }
+ if written == 0 {
+ return s
+ }
+ b.WriteString(s[written:])
+ return b.String()
+}
diff --git a/libgo/go/exp/template/html/url_test.go b/libgo/go/exp/template/html/url_test.go
new file mode 100644
index 00000000000..b84623151c7
--- /dev/null
+++ b/libgo/go/exp/template/html/url_test.go
@@ -0,0 +1,112 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "testing"
+)
+
+func TestURLNormalizer(t *testing.T) {
+ tests := []struct {
+ url, want string
+ }{
+ {"", ""},
+ {
+ "http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
+ "http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
+ },
+ {" ", "%20"},
+ {"%7c", "%7c"},
+ {"%7C", "%7C"},
+ {"%2", "%252"},
+ {"%", "%25"},
+ {"%z", "%25z"},
+ {"/foo|bar/%5c\u1234", "/foo%7cbar/%5c%e1%88%b4"},
+ }
+ for _, test := range tests {
+ if got := urlNormalizer(test.url); test.want != got {
+ t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.url, test.want, got)
+ }
+ if test.want != urlNormalizer(test.want) {
+ t.Errorf("not idempotent: %q", test.want)
+ }
+ }
+}
+
+func TestURLFilters(t *testing.T) {
+ input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
+ ` !"#$%&'()*+,-./` +
+ `0123456789:;<=>?` +
+ `@ABCDEFGHIJKLMNO` +
+ `PQRSTUVWXYZ[\]^_` +
+ "`abcdefghijklmno" +
+ "pqrstuvwxyz{|}~\x7f" +
+ "\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
+
+ tests := []struct {
+ name string
+ escaper func(...interface{}) string
+ escaped string
+ }{
+ {
+ "urlEscaper",
+ urlEscaper,
+ "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
+ "%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
+ "%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f" +
+ "0123456789%3a%3b%3c%3d%3e%3f" +
+ "%40ABCDEFGHIJKLMNO" +
+ "PQRSTUVWXYZ%5b%5c%5d%5e_" +
+ "%60abcdefghijklmno" +
+ "pqrstuvwxyz%7b%7c%7d~%7f" +
+ "%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
+ },
+ {
+ "urlNormalizer",
+ urlNormalizer,
+ "%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
+ "%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
+ "%20!%22#$%25&%27%28%29*+,-./" +
+ "0123456789:;%3c=%3e?" +
+ "@ABCDEFGHIJKLMNO" +
+ "PQRSTUVWXYZ[%5c]%5e_" +
+ "%60abcdefghijklmno" +
+ "pqrstuvwxyz%7b%7c%7d~%7f" +
+ "%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
+ },
+ }
+
+ for _, test := range tests {
+ if s := test.escaper(input); s != test.escaped {
+ t.Errorf("%s: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
+ continue
+ }
+ }
+}
+
+func BenchmarkURLEscaper(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ urlEscaper("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
+ }
+}
+
+func BenchmarkURLEscaperNoSpecials(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ urlEscaper("TheQuickBrownFoxJumpsOverTheLazyDog.")
+ }
+}
+
+func BenchmarkURLNormalizer(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ urlNormalizer("The quick brown fox jumps over the lazy dog.\n")
+ }
+}
+
+func BenchmarkURLNormalizerNoSpecials(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ urlNormalizer("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
+ }
+}
diff --git a/libgo/go/exp/terminal/shell.go b/libgo/go/exp/terminal/shell.go
new file mode 100644
index 00000000000..e3f584774e3
--- /dev/null
+++ b/libgo/go/exp/terminal/shell.go
@@ -0,0 +1,359 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package terminal
+
+import (
+ "os"
+ "io"
+)
+
+// Shell contains the state for running a VT100 terminal that is capable of
+// reading lines of input.
+type Shell struct {
+ c io.ReadWriter
+ prompt string
+
+ // line is the current line being entered.
+ line []byte
+ // pos is the logical position of the cursor in line
+ pos int
+
+ // cursorX contains the current X value of the cursor where the left
+ // edge is 0. cursorY contains the row number where the first row of
+ // the current line is 0.
+ cursorX, cursorY int
+ // maxLine is the greatest value of cursorY so far.
+ maxLine int
+
+ termWidth, termHeight int
+
+ // outBuf contains the terminal data to be sent.
+ outBuf []byte
+ // remainder contains the remainder of any partial key sequences after
+ // a read. It aliases into inBuf.
+ remainder []byte
+ inBuf [256]byte
+}
+
+// NewShell runs a VT100 terminal on the given ReadWriter. If the ReadWriter is
+// a local terminal, that terminal must first have been put into raw mode.
+// prompt is a string that is written at the start of each input line (i.e.
+// "> ").
+func NewShell(c io.ReadWriter, prompt string) *Shell {
+ return &Shell{
+ c: c,
+ prompt: prompt,
+ termWidth: 80,
+ termHeight: 24,
+ }
+}
+
+const (
+ keyCtrlD = 4
+ keyEnter = '\r'
+ keyEscape = 27
+ keyBackspace = 127
+ keyUnknown = 256 + iota
+ keyUp
+ keyDown
+ keyLeft
+ keyRight
+ keyAltLeft
+ keyAltRight
+)
+
+// bytesToKey tries to parse a key sequence from b. If successful, it returns
+// the key and the remainder of the input. Otherwise it returns -1.
+func bytesToKey(b []byte) (int, []byte) {
+ if len(b) == 0 {
+ return -1, nil
+ }
+
+ if b[0] != keyEscape {
+ return int(b[0]), b[1:]
+ }
+
+ if len(b) >= 3 && b[0] == keyEscape && b[1] == '[' {
+ switch b[2] {
+ case 'A':
+ return keyUp, b[3:]
+ case 'B':
+ return keyDown, b[3:]
+ case 'C':
+ return keyRight, b[3:]
+ case 'D':
+ return keyLeft, b[3:]
+ }
+ }
+
+ if len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' {
+ switch b[5] {
+ case 'C':
+ return keyAltRight, b[6:]
+ case 'D':
+ return keyAltLeft, b[6:]
+ }
+ }
+
+ // If we get here then we have a key that we don't recognise, or a
+ // partial sequence. It's not clear how one should find the end of a
+ // sequence without knowing them all, but it seems that [a-zA-Z] only
+ // appears at the end of a sequence.
+ for i, c := range b[0:] {
+ if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {
+ return keyUnknown, b[i+1:]
+ }
+ }
+
+ return -1, b
+}
+
+// queue appends data to the end of ss.outBuf
+func (ss *Shell) queue(data []byte) {
+ if len(ss.outBuf)+len(data) > cap(ss.outBuf) {
+ newOutBuf := make([]byte, len(ss.outBuf), 2*(len(ss.outBuf)+len(data)))
+ copy(newOutBuf, ss.outBuf)
+ ss.outBuf = newOutBuf
+ }
+
+ oldLen := len(ss.outBuf)
+ ss.outBuf = ss.outBuf[:len(ss.outBuf)+len(data)]
+ copy(ss.outBuf[oldLen:], data)
+}
+
+var eraseUnderCursor = []byte{' ', keyEscape, '[', 'D'}
+
+func isPrintable(key int) bool {
+ return key >= 32 && key < 127
+}
+
+// moveCursorToPos appends data to ss.outBuf which will move the cursor to the
+// given, logical position in the text.
+func (ss *Shell) moveCursorToPos(pos int) {
+ x := len(ss.prompt) + pos
+ y := x / ss.termWidth
+ x = x % ss.termWidth
+
+ up := 0
+ if y < ss.cursorY {
+ up = ss.cursorY - y
+ }
+
+ down := 0
+ if y > ss.cursorY {
+ down = y - ss.cursorY
+ }
+
+ left := 0
+ if x < ss.cursorX {
+ left = ss.cursorX - x
+ }
+
+ right := 0
+ if x > ss.cursorX {
+ right = x - ss.cursorX
+ }
+
+ movement := make([]byte, 3*(up+down+left+right))
+ m := movement
+ for i := 0; i < up; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'A'
+ m = m[3:]
+ }
+ for i := 0; i < down; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'B'
+ m = m[3:]
+ }
+ for i := 0; i < left; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'D'
+ m = m[3:]
+ }
+ for i := 0; i < right; i++ {
+ m[0] = keyEscape
+ m[1] = '['
+ m[2] = 'C'
+ m = m[3:]
+ }
+
+ ss.cursorX = x
+ ss.cursorY = y
+ ss.queue(movement)
+}
+
+const maxLineLength = 4096
+
+// handleKey processes the given key and, optionally, returns a line of text
+// that the user has entered.
+func (ss *Shell) handleKey(key int) (line string, ok bool) {
+ switch key {
+ case keyBackspace:
+ if ss.pos == 0 {
+ return
+ }
+ ss.pos--
+
+ copy(ss.line[ss.pos:], ss.line[1+ss.pos:])
+ ss.line = ss.line[:len(ss.line)-1]
+ ss.writeLine(ss.line[ss.pos:])
+ ss.moveCursorToPos(ss.pos)
+ ss.queue(eraseUnderCursor)
+ case keyAltLeft:
+ // move left by a word.
+ if ss.pos == 0 {
+ return
+ }
+ ss.pos--
+ for ss.pos > 0 {
+ if ss.line[ss.pos] != ' ' {
+ break
+ }
+ ss.pos--
+ }
+ for ss.pos > 0 {
+ if ss.line[ss.pos] == ' ' {
+ ss.pos++
+ break
+ }
+ ss.pos--
+ }
+ ss.moveCursorToPos(ss.pos)
+ case keyAltRight:
+ // move right by a word.
+ for ss.pos < len(ss.line) {
+ if ss.line[ss.pos] == ' ' {
+ break
+ }
+ ss.pos++
+ }
+ for ss.pos < len(ss.line) {
+ if ss.line[ss.pos] != ' ' {
+ break
+ }
+ ss.pos++
+ }
+ ss.moveCursorToPos(ss.pos)
+ case keyLeft:
+ if ss.pos == 0 {
+ return
+ }
+ ss.pos--
+ ss.moveCursorToPos(ss.pos)
+ case keyRight:
+ if ss.pos == len(ss.line) {
+ return
+ }
+ ss.pos++
+ ss.moveCursorToPos(ss.pos)
+ case keyEnter:
+ ss.moveCursorToPos(len(ss.line))
+ ss.queue([]byte("\r\n"))
+ line = string(ss.line)
+ ok = true
+ ss.line = ss.line[:0]
+ ss.pos = 0
+ ss.cursorX = 0
+ ss.cursorY = 0
+ ss.maxLine = 0
+ default:
+ if !isPrintable(key) {
+ return
+ }
+ if len(ss.line) == maxLineLength {
+ return
+ }
+ if len(ss.line) == cap(ss.line) {
+ newLine := make([]byte, len(ss.line), 2*(1+len(ss.line)))
+ copy(newLine, ss.line)
+ ss.line = newLine
+ }
+ ss.line = ss.line[:len(ss.line)+1]
+ copy(ss.line[ss.pos+1:], ss.line[ss.pos:])
+ ss.line[ss.pos] = byte(key)
+ ss.writeLine(ss.line[ss.pos:])
+ ss.pos++
+ ss.moveCursorToPos(ss.pos)
+ }
+ return
+}
+
+func (ss *Shell) writeLine(line []byte) {
+ for len(line) != 0 {
+ if ss.cursorX == ss.termWidth {
+ ss.queue([]byte("\r\n"))
+ ss.cursorX = 0
+ ss.cursorY++
+ if ss.cursorY > ss.maxLine {
+ ss.maxLine = ss.cursorY
+ }
+ }
+
+ remainingOnLine := ss.termWidth - ss.cursorX
+ todo := len(line)
+ if todo > remainingOnLine {
+ todo = remainingOnLine
+ }
+ ss.queue(line[:todo])
+ ss.cursorX += todo
+ line = line[todo:]
+ }
+}
+
+func (ss *Shell) Write(buf []byte) (n int, err os.Error) {
+ return ss.c.Write(buf)
+}
+
+// ReadLine returns a line of input from the terminal.
+func (ss *Shell) ReadLine() (line string, err os.Error) {
+ ss.writeLine([]byte(ss.prompt))
+ ss.c.Write(ss.outBuf)
+ ss.outBuf = ss.outBuf[:0]
+
+ for {
+ // ss.remainder is a slice at the beginning of ss.inBuf
+ // containing a partial key sequence
+ readBuf := ss.inBuf[len(ss.remainder):]
+ var n int
+ n, err = ss.c.Read(readBuf)
+ if err != nil {
+ return
+ }
+
+ if err == nil {
+ ss.remainder = ss.inBuf[:n+len(ss.remainder)]
+ rest := ss.remainder
+ lineOk := false
+ for !lineOk {
+ var key int
+ key, rest = bytesToKey(rest)
+ if key < 0 {
+ break
+ }
+ if key == keyCtrlD {
+ return "", os.EOF
+ }
+ line, lineOk = ss.handleKey(key)
+ }
+ if len(rest) > 0 {
+ n := copy(ss.inBuf[:], rest)
+ ss.remainder = ss.inBuf[:n]
+ } else {
+ ss.remainder = nil
+ }
+ ss.c.Write(ss.outBuf)
+ ss.outBuf = ss.outBuf[:0]
+ if lineOk {
+ return
+ }
+ continue
+ }
+ }
+ panic("unreachable")
+}
diff --git a/libgo/go/exp/terminal/shell_test.go b/libgo/go/exp/terminal/shell_test.go
new file mode 100644
index 00000000000..2bbe4a4f8f9
--- /dev/null
+++ b/libgo/go/exp/terminal/shell_test.go
@@ -0,0 +1,110 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package terminal
+
+import (
+ "testing"
+ "os"
+)
+
+type MockTerminal struct {
+ toSend []byte
+ bytesPerRead int
+ received []byte
+}
+
+func (c *MockTerminal) Read(data []byte) (n int, err os.Error) {
+ n = len(data)
+ if n == 0 {
+ return
+ }
+ if n > len(c.toSend) {
+ n = len(c.toSend)
+ }
+ if n == 0 {
+ return 0, os.EOF
+ }
+ if c.bytesPerRead > 0 && n > c.bytesPerRead {
+ n = c.bytesPerRead
+ }
+ copy(data, c.toSend[:n])
+ c.toSend = c.toSend[n:]
+ return
+}
+
+func (c *MockTerminal) Write(data []byte) (n int, err os.Error) {
+ c.received = append(c.received, data...)
+ return len(data), nil
+}
+
+func TestClose(t *testing.T) {
+ c := &MockTerminal{}
+ ss := NewShell(c, "> ")
+ line, err := ss.ReadLine()
+ if line != "" {
+ t.Errorf("Expected empty line but got: %s", line)
+ }
+ if err != os.EOF {
+ t.Errorf("Error should have been EOF but got: %s", err)
+ }
+}
+
+var keyPressTests = []struct {
+ in string
+ line string
+ err os.Error
+}{
+ {
+ "",
+ "",
+ os.EOF,
+ },
+ {
+ "\r",
+ "",
+ nil,
+ },
+ {
+ "foo\r",
+ "foo",
+ nil,
+ },
+ {
+ "a\x1b[Cb\r", // right
+ "ab",
+ nil,
+ },
+ {
+ "a\x1b[Db\r", // left
+ "ba",
+ nil,
+ },
+ {
+ "a\177b\r", // backspace
+ "b",
+ nil,
+ },
+}
+
+func TestKeyPresses(t *testing.T) {
+ for i, test := range keyPressTests {
+ for j := 0; j < len(test.in); j++ {
+ c := &MockTerminal{
+ toSend: []byte(test.in),
+ bytesPerRead: j,
+ }
+ ss := NewShell(c, "> ")
+ line, err := ss.ReadLine()
+ if line != test.line {
+ t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
+ break
+ }
+ if err != test.err {
+ t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
+ break
+ }
+ }
+ }
+}
diff --git a/libgo/go/exp/terminal/terminal.go b/libgo/go/exp/terminal/terminal.go
new file mode 100644
index 00000000000..05a8990b041
--- /dev/null
+++ b/libgo/go/exp/terminal/terminal.go
@@ -0,0 +1,102 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package terminal provides support functions for dealing with terminals, as
+// commonly found on UNIX systems.
+//
+// Putting a terminal into raw mode is the most common requirement:
+//
+// oldState, err := terminal.MakeRaw(0)
+// if err != nil {
+// panic(err.String())
+// }
+// defer terminal.Restore(0, oldState)
+package terminal
+
+import (
+ "os"
+ "syscall"
+)
+
+// State contains the state of a terminal.
+type State struct {
+ termios syscall.Termios
+}
+
+// IsTerminal returns true if the given file descriptor is a terminal.
+func IsTerminal(fd int) bool {
+ var termios syscall.Termios
+ e := syscall.Tcgetattr(fd, &termios)
+ return e == 0
+}
+
+// MakeRaw put the terminal connected to the given file descriptor into raw
+// mode and returns the previous state of the terminal so that it can be
+// restored.
+func MakeRaw(fd int) (*State, os.Error) {
+ var oldState State
+ if e := syscall.Tcgetattr(fd, &oldState.termios); e != 0 {
+ return nil, os.Errno(e)
+ }
+
+ newState := oldState.termios
+ newState.Iflag &^= syscall.ISTRIP | syscall.INLCR | syscall.ICRNL | syscall.IGNCR | syscall.IXON | syscall.IXOFF
+ newState.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.ISIG
+ if e := syscall.Tcsetattr(fd, syscall.TCSANOW, &newState); e != 0 {
+ return nil, os.Errno(e)
+ }
+
+ return &oldState, nil
+}
+
+// Restore restores the terminal connected to the given file descriptor to a
+// previous state.
+func Restore(fd int, state *State) os.Error {
+ e := syscall.Tcsetattr(fd, syscall.TCSANOW, &state.termios)
+ return os.Errno(e)
+}
+
+// ReadPassword reads a line of input from a terminal without local echo. This
+// is commonly used for inputting passwords and other sensitive data. The slice
+// returned does not include the \n.
+func ReadPassword(fd int) ([]byte, os.Error) {
+ var oldState syscall.Termios
+ if e := syscall.Tcgetattr(fd, &oldState); e != 0 {
+ return nil, os.Errno(e)
+ }
+
+ newState := oldState
+ newState.Lflag &^= syscall.ECHO
+ if e := syscall.Tcsetattr(fd, syscall.TCSANOW, &newState); e != 0 {
+ return nil, os.Errno(e)
+ }
+
+ defer func() {
+ syscall.Tcsetattr(fd, syscall.TCSANOW, &oldState)
+ }()
+
+ var buf [16]byte
+ var ret []byte
+ for {
+ n, errno := syscall.Read(fd, buf[:])
+ if errno != 0 {
+ return nil, os.Errno(errno)
+ }
+ if n == 0 {
+ if len(ret) == 0 {
+ return nil, os.EOF
+ }
+ break
+ }
+ if buf[n-1] == '\n' {
+ n--
+ }
+ ret = append(ret, buf[:n]...)
+ if n < len(buf) {
+ break
+ }
+ }
+
+ return ret, nil
+}
diff --git a/libgo/go/go/types/check.go b/libgo/go/exp/types/check.go
index 87e3e93da73..87e3e93da73 100644
--- a/libgo/go/go/types/check.go
+++ b/libgo/go/exp/types/check.go
diff --git a/libgo/go/exp/types/check_test.go b/libgo/go/exp/types/check_test.go
new file mode 100644
index 00000000000..034acd00de5
--- /dev/null
+++ b/libgo/go/exp/types/check_test.go
@@ -0,0 +1,215 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements a typechecker test harness. The packages specified
+// in tests are typechecked. Error messages reported by the typechecker are
+// compared against the error messages expected in the test files.
+//
+// Expected errors are indicated in the test files by putting a comment
+// of the form /* ERROR "rx" */ immediately following an offending token.
+// The harness will verify that an error matching the regular expression
+// rx is reported at that source position. Consecutive comments may be
+// used to indicate multiple errors for the same token position.
+//
+// For instance, the following test file indicates that a "not declared"
+// error should be reported for the undeclared variable x:
+//
+// package p
+// func f() {
+// _ = x /* ERROR "not declared" */ + 1
+// }
+
+package types
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/scanner"
+ "go/token"
+ "io/ioutil"
+ "os"
+ "regexp"
+ "testing"
+)
+
+// The test filenames do not end in .go so that they are invisible
+// to gofmt since they contain comments that must not change their
+// positions relative to surrounding tokens.
+
+var tests = []struct {
+ name string
+ files []string
+}{
+ {"test0", []string{"testdata/test0.src"}},
+}
+
+var fset = token.NewFileSet()
+
+// TODO(gri) This functionality should be in token.Fileset.
+func getFile(filename string) *token.File {
+ for f := range fset.Files() {
+ if f.Name() == filename {
+ return f
+ }
+ }
+ return nil
+}
+
+// TODO(gri) This functionality should be in token.Fileset.
+func getPos(filename string, offset int) token.Pos {
+ if f := getFile(filename); f != nil {
+ return f.Pos(offset)
+ }
+ return token.NoPos
+}
+
+// TODO(gri) Need to revisit parser interface. We should be able to use parser.ParseFiles
+// or a similar function instead.
+func parseFiles(t *testing.T, testname string, filenames []string) (map[string]*ast.File, os.Error) {
+ files := make(map[string]*ast.File)
+ var errors scanner.ErrorList
+ for _, filename := range filenames {
+ if _, exists := files[filename]; exists {
+ t.Fatalf("%s: duplicate file %s", testname, filename)
+ }
+ file, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors)
+ if file == nil {
+ t.Fatalf("%s: could not parse file %s", testname, filename)
+ }
+ files[filename] = file
+ if err != nil {
+ // if the parser returns a non-scanner.ErrorList error
+ // the file couldn't be read in the first place and
+ // file == nil; in that case we shouldn't reach here
+ errors = append(errors, err.(scanner.ErrorList)...)
+ }
+
+ }
+ return files, errors
+}
+
+// ERROR comments must be of the form /* ERROR "rx" */ and rx is
+// a regular expression that matches the expected error message.
+//
+var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`)
+
+// expectedErrors collects the regular expressions of ERROR comments found
+// in files and returns them as a map of error positions to error messages.
+//
+func expectedErrors(t *testing.T, testname string, files map[string]*ast.File) map[token.Pos]string {
+ errors := make(map[token.Pos]string)
+ for filename := range files {
+ src, err := ioutil.ReadFile(filename)
+ if err != nil {
+ t.Fatalf("%s: could not read %s", testname, filename)
+ }
+
+ var s scanner.Scanner
+ // file was parsed already - do not add it again to the file
+ // set otherwise the position information returned here will
+ // not match the position information collected by the parser
+ s.Init(getFile(filename), src, nil, scanner.ScanComments)
+ var prev token.Pos // position of last non-comment token
+
+ scanFile:
+ for {
+ pos, tok, lit := s.Scan()
+ switch tok {
+ case token.EOF:
+ break scanFile
+ case token.COMMENT:
+ s := errRx.FindStringSubmatch(lit)
+ if len(s) == 2 {
+ errors[prev] = string(s[1])
+ }
+ default:
+ prev = pos
+ }
+ }
+ }
+ return errors
+}
+
+func eliminate(t *testing.T, expected map[token.Pos]string, errors os.Error) {
+ if errors == nil {
+ return
+ }
+ for _, error := range errors.(scanner.ErrorList) {
+ // error.Pos is a token.Position, but we want
+ // a token.Pos so we can do a map lookup
+ // TODO(gri) Need to move scanner.Errors over
+ // to use token.Pos and file set info.
+ pos := getPos(error.Pos.Filename, error.Pos.Offset)
+ if msg, found := expected[pos]; found {
+ // we expect a message at pos; check if it matches
+ rx, err := regexp.Compile(msg)
+ if err != nil {
+ t.Errorf("%s: %v", error.Pos, err)
+ continue
+ }
+ if match := rx.MatchString(error.Msg); !match {
+ t.Errorf("%s: %q does not match %q", error.Pos, error.Msg, msg)
+ continue
+ }
+ // we have a match - eliminate this error
+ delete(expected, pos)
+ } else {
+ // To keep in mind when analyzing failed test output:
+ // If the same error position occurs multiple times in errors,
+ // this message will be triggered (because the first error at
+ // the position removes this position from the expected errors).
+ t.Errorf("%s: no (multiple?) error expected, but found: %s", error.Pos, error.Msg)
+ }
+ }
+}
+
+func check(t *testing.T, testname string, testfiles []string) {
+ // TODO(gri) Eventually all these different phases should be
+ // subsumed into a single function call that takes
+ // a set of files and creates a fully resolved and
+ // type-checked AST.
+
+ files, err := parseFiles(t, testname, testfiles)
+
+ // we are expecting the following errors
+ // (collect these after parsing the files so that
+ // they are found in the file set)
+ errors := expectedErrors(t, testname, files)
+
+ // verify errors returned by the parser
+ eliminate(t, errors, err)
+
+ // verify errors returned after resolving identifiers
+ pkg, err := ast.NewPackage(fset, files, GcImporter, Universe)
+ eliminate(t, errors, err)
+
+ // verify errors returned by the typechecker
+ _, err = Check(fset, pkg)
+ eliminate(t, errors, err)
+
+ // there should be no expected errors left
+ if len(errors) > 0 {
+ t.Errorf("%s: %d errors not reported:", testname, len(errors))
+ for pos, msg := range errors {
+ t.Errorf("%s: %s\n", fset.Position(pos), msg)
+ }
+ }
+}
+
+func TestCheck(t *testing.T) {
+ // For easy debugging w/o changing the testing code,
+ // if there is a local test file, only test that file.
+ const testfile = "test.go"
+ if fi, err := os.Stat(testfile); err == nil && fi.IsRegular() {
+ fmt.Printf("WARNING: Testing only %s (remove it to run all tests)\n", testfile)
+ check(t, testfile, []string{testfile})
+ return
+ }
+
+ // Otherwise, run all the tests.
+ for _, test := range tests {
+ check(t, test.name, test.files)
+ }
+}
diff --git a/libgo/go/go/types/const.go b/libgo/go/exp/types/const.go
index 1ef95d9f952..1ef95d9f952 100644
--- a/libgo/go/go/types/const.go
+++ b/libgo/go/exp/types/const.go
diff --git a/libgo/go/go/types/exportdata.go b/libgo/go/exp/types/exportdata.go
index 383520320f4..383520320f4 100644
--- a/libgo/go/go/types/exportdata.go
+++ b/libgo/go/exp/types/exportdata.go
diff --git a/libgo/go/exp/types/gcimporter.go b/libgo/go/exp/types/gcimporter.go
new file mode 100644
index 00000000000..fe90f910807
--- /dev/null
+++ b/libgo/go/exp/types/gcimporter.go
@@ -0,0 +1,823 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements an ast.Importer for gc generated object files.
+// TODO(gri) Eventually move this into a separate package outside types.
+
+package types
+
+import (
+ "big"
+ "fmt"
+ "go/ast"
+ "go/token"
+ "io"
+ "os"
+ "path/filepath"
+ "runtime"
+ "scanner"
+ "strconv"
+)
+
+const trace = false // set to true for debugging
+
+var (
+ pkgRoot = filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH)
+ pkgExts = [...]string{".a", ".5", ".6", ".8"}
+)
+
+// findPkg returns the filename and package id for an import path.
+// If no file was found, an empty filename is returned.
+func findPkg(path string) (filename, id string) {
+ if len(path) == 0 {
+ return
+ }
+
+ id = path
+ var noext string
+ switch path[0] {
+ default:
+ // "x" -> "$GOROOT/pkg/$GOOS_$GOARCH/x.ext", "x"
+ noext = filepath.Join(pkgRoot, path)
+
+ case '.':
+ // "./x" -> "/this/directory/x.ext", "/this/directory/x"
+ cwd, err := os.Getwd()
+ if err != nil {
+ return
+ }
+ noext = filepath.Join(cwd, path)
+ id = noext
+
+ case '/':
+ // "/x" -> "/x.ext", "/x"
+ noext = path
+ }
+
+ // try extensions
+ for _, ext := range pkgExts {
+ filename = noext + ext
+ if f, err := os.Stat(filename); err == nil && f.IsRegular() {
+ return
+ }
+ }
+
+ filename = "" // not found
+ return
+}
+
+// gcParser parses the exports inside a gc compiler-produced
+// object/archive file and populates its scope with the results.
+type gcParser struct {
+ scanner scanner.Scanner
+ tok int // current token
+ lit string // literal string; only valid for Ident, Int, String tokens
+ id string // package id of imported package
+ imports map[string]*ast.Object // package id -> package object
+}
+
+func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
+ p.scanner.Init(src)
+ p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
+ p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
+ p.scanner.Whitespace = 1<<'\t' | 1<<' '
+ p.scanner.Filename = filename // for good error messages
+ p.next()
+ p.id = id
+ p.imports = imports
+}
+
+func (p *gcParser) next() {
+ p.tok = p.scanner.Scan()
+ switch p.tok {
+ case scanner.Ident, scanner.Int, scanner.String:
+ p.lit = p.scanner.TokenText()
+ default:
+ p.lit = ""
+ }
+ if trace {
+ fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
+ }
+}
+
+// GcImporter implements the ast.Importer signature.
+func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, err os.Error) {
+ if path == "unsafe" {
+ return Unsafe, nil
+ }
+
+ defer func() {
+ if r := recover(); r != nil {
+ err = r.(importError) // will re-panic if r is not an importError
+ if trace {
+ panic(err) // force a stack trace
+ }
+ }
+ }()
+
+ filename, id := findPkg(path)
+ if filename == "" {
+ err = os.NewError("can't find import: " + id)
+ return
+ }
+
+ if pkg = imports[id]; pkg != nil {
+ return // package was imported before
+ }
+
+ buf, err := ExportData(filename)
+ if err != nil {
+ return
+ }
+ defer buf.Close()
+
+ if trace {
+ fmt.Printf("importing %s (%s)\n", id, filename)
+ }
+
+ var p gcParser
+ p.init(filename, id, buf, imports)
+ pkg = p.parseExport()
+ return
+}
+
+// Declare inserts a named object of the given kind in scope.
+func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
+ // a type may have been declared before - if it exists
+ // already in the respective package scope, return that
+ // type
+ if kind == ast.Typ {
+ if obj := scope.Lookup(name); obj != nil {
+ assert(obj.Kind == ast.Typ)
+ return obj
+ }
+ }
+
+ // any other object must be a newly declared object -
+ // create it and insert it into the package scope
+ obj := ast.NewObj(kind, name)
+ if scope.Insert(obj) != nil {
+ p.errorf("already declared: %v %s", kind, obj.Name)
+ }
+
+ // a new type object is a named type and may be referred
+ // to before the underlying type is known - set it up
+ if kind == ast.Typ {
+ obj.Type = &Name{Obj: obj}
+ }
+
+ return obj
+}
+
+// ----------------------------------------------------------------------------
+// Error handling
+
+// Internal errors are boxed as importErrors.
+type importError struct {
+ pos scanner.Position
+ err os.Error
+}
+
+func (e importError) String() string {
+ return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
+}
+
+func (p *gcParser) error(err interface{}) {
+ if s, ok := err.(string); ok {
+ err = os.NewError(s)
+ }
+ // panic with a runtime.Error if err is not an os.Error
+ panic(importError{p.scanner.Pos(), err.(os.Error)})
+}
+
+func (p *gcParser) errorf(format string, args ...interface{}) {
+ p.error(fmt.Sprintf(format, args...))
+}
+
+func (p *gcParser) expect(tok int) string {
+ lit := p.lit
+ if p.tok != tok {
+ p.errorf("expected %q, got %q (%q)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
+ }
+ p.next()
+ return lit
+}
+
+func (p *gcParser) expectSpecial(tok string) {
+ sep := 'x' // not white space
+ i := 0
+ for i < len(tok) && p.tok == int(tok[i]) && sep > ' ' {
+ sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+ p.next()
+ i++
+ }
+ if i < len(tok) {
+ p.errorf("expected %q, got %q", tok, tok[0:i])
+ }
+}
+
+func (p *gcParser) expectKeyword(keyword string) {
+ lit := p.expect(scanner.Ident)
+ if lit != keyword {
+ p.errorf("expected keyword %s, got %q", keyword, lit)
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Import declarations
+
+// ImportPath = string_lit .
+//
+func (p *gcParser) parsePkgId() *ast.Object {
+ id, err := strconv.Unquote(p.expect(scanner.String))
+ if err != nil {
+ p.error(err)
+ }
+
+ switch id {
+ case "":
+ // id == "" stands for the imported package id
+ // (only known at time of package installation)
+ id = p.id
+ case "unsafe":
+ // package unsafe is not in the imports map - handle explicitly
+ return Unsafe
+ }
+
+ pkg := p.imports[id]
+ if pkg == nil {
+ scope = ast.NewScope(nil)
+ pkg = ast.NewObj(ast.Pkg, "")
+ pkg.Data = scope
+ p.imports[id] = pkg
+ }
+
+ return pkg
+}
+
+// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
+func (p *gcParser) parseDotIdent() string {
+ ident := ""
+ if p.tok != scanner.Int {
+ sep := 'x' // not white space
+ for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
+ ident += p.lit
+ sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
+ p.next()
+ }
+ }
+ if ident == "" {
+ p.expect(scanner.Ident) // use expect() for error handling
+ }
+ return ident
+}
+
+// ExportedName = "@" ImportPath "." dotIdentifier .
+//
+func (p *gcParser) parseExportedName() (*ast.Object, string) {
+ p.expect('@')
+ pkg := p.parsePkgId()
+ p.expect('.')
+ name := p.parseDotIdent()
+ return pkg, name
+}
+
+// ----------------------------------------------------------------------------
+// Types
+
+// BasicType = identifier .
+//
+func (p *gcParser) parseBasicType() Type {
+ obj := Universe.Lookup(p.expect(scanner.Ident))
+ if obj == nil || obj.Kind != ast.Typ {
+ p.errorf("not a basic type: %s", obj.Name)
+ }
+ return obj.Type.(Type)
+}
+
+// ArrayType = "[" int_lit "]" Type .
+//
+func (p *gcParser) parseArrayType() Type {
+ // "[" already consumed and lookahead known not to be "]"
+ lit := p.expect(scanner.Int)
+ p.expect(']')
+ elt := p.parseType()
+ n, err := strconv.Atoui64(lit)
+ if err != nil {
+ p.error(err)
+ }
+ return &Array{Len: n, Elt: elt}
+}
+
+// MapType = "map" "[" Type "]" Type .
+//
+func (p *gcParser) parseMapType() Type {
+ p.expectKeyword("map")
+ p.expect('[')
+ key := p.parseType()
+ p.expect(']')
+ elt := p.parseType()
+ return &Map{Key: key, Elt: elt}
+}
+
+// Name = identifier | "?" .
+//
+func (p *gcParser) parseName() (name string) {
+ switch p.tok {
+ case scanner.Ident:
+ name = p.lit
+ p.next()
+ case '?':
+ // anonymous
+ p.next()
+ default:
+ p.error("name expected")
+ }
+ return
+}
+
+// Field = Name Type [ string_lit ] .
+//
+func (p *gcParser) parseField() (fld *ast.Object, tag string) {
+ name := p.parseName()
+ ftyp := p.parseType()
+ if name == "" {
+ // anonymous field - ftyp must be T or *T and T must be a type name
+ if _, ok := Deref(ftyp).(*Name); !ok {
+ p.errorf("anonymous field expected")
+ }
+ }
+ if p.tok == scanner.String {
+ tag = p.expect(scanner.String)
+ }
+ fld = ast.NewObj(ast.Var, name)
+ fld.Type = ftyp
+ return
+}
+
+// StructType = "struct" "{" [ FieldList ] "}" .
+// FieldList = Field { ";" Field } .
+//
+func (p *gcParser) parseStructType() Type {
+ var fields []*ast.Object
+ var tags []string
+
+ parseField := func() {
+ fld, tag := p.parseField()
+ fields = append(fields, fld)
+ tags = append(tags, tag)
+ }
+
+ p.expectKeyword("struct")
+ p.expect('{')
+ if p.tok != '}' {
+ parseField()
+ for p.tok == ';' {
+ p.next()
+ parseField()
+ }
+ }
+ p.expect('}')
+
+ return &Struct{Fields: fields, Tags: tags}
+}
+
+// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
+//
+func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) {
+ name := p.parseName()
+ if name == "" {
+ name = "_" // cannot access unnamed identifiers
+ }
+ if p.tok == '.' {
+ p.expectSpecial("...")
+ isVariadic = true
+ }
+ ptyp := p.parseType()
+ // ignore argument tag
+ if p.tok == scanner.String {
+ p.expect(scanner.String)
+ }
+ par = ast.NewObj(ast.Var, name)
+ par.Type = ptyp
+ return
+}
+
+// Parameters = "(" [ ParameterList ] ")" .
+// ParameterList = { Parameter "," } Parameter .
+//
+func (p *gcParser) parseParameters() (list []*ast.Object, isVariadic bool) {
+ parseParameter := func() {
+ par, variadic := p.parseParameter()
+ list = append(list, par)
+ if variadic {
+ if isVariadic {
+ p.error("... not on final argument")
+ }
+ isVariadic = true
+ }
+ }
+
+ p.expect('(')
+ if p.tok != ')' {
+ parseParameter()
+ for p.tok == ',' {
+ p.next()
+ parseParameter()
+ }
+ }
+ p.expect(')')
+
+ return
+}
+
+// Signature = Parameters [ Result ] .
+// Result = Type | Parameters .
+//
+func (p *gcParser) parseSignature() *Func {
+ params, isVariadic := p.parseParameters()
+
+ // optional result type
+ var results []*ast.Object
+ switch p.tok {
+ case scanner.Ident, '[', '*', '<', '@':
+ // single, unnamed result
+ result := ast.NewObj(ast.Var, "_")
+ result.Type = p.parseType()
+ results = []*ast.Object{result}
+ case '(':
+ // named or multiple result(s)
+ var variadic bool
+ results, variadic = p.parseParameters()
+ if variadic {
+ p.error("... not permitted on result type")
+ }
+ }
+
+ return &Func{Params: params, Results: results, IsVariadic: isVariadic}
+}
+
+// MethodSpec = ( identifier | ExportedName ) Signature .
+//
+func (p *gcParser) parseMethodSpec() *ast.Object {
+ if p.tok == scanner.Ident {
+ p.expect(scanner.Ident)
+ } else {
+ p.parseExportedName()
+ }
+ p.parseSignature()
+
+ // TODO(gri) compute method object
+ return ast.NewObj(ast.Fun, "_")
+}
+
+// InterfaceType = "interface" "{" [ MethodList ] "}" .
+// MethodList = MethodSpec { ";" MethodSpec } .
+//
+func (p *gcParser) parseInterfaceType() Type {
+ var methods ObjList
+
+ parseMethod := func() {
+ meth := p.parseMethodSpec()
+ methods = append(methods, meth)
+ }
+
+ p.expectKeyword("interface")
+ p.expect('{')
+ if p.tok != '}' {
+ parseMethod()
+ for p.tok == ';' {
+ p.next()
+ parseMethod()
+ }
+ }
+ p.expect('}')
+
+ methods.Sort()
+ return &Interface{Methods: methods}
+}
+
+// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
+//
+func (p *gcParser) parseChanType() Type {
+ dir := ast.SEND | ast.RECV
+ if p.tok == scanner.Ident {
+ p.expectKeyword("chan")
+ if p.tok == '<' {
+ p.expectSpecial("<-")
+ dir = ast.SEND
+ }
+ } else {
+ p.expectSpecial("<-")
+ p.expectKeyword("chan")
+ dir = ast.RECV
+ }
+ elt := p.parseType()
+ return &Chan{Dir: dir, Elt: elt}
+}
+
+// Type =
+// BasicType | TypeName | ArrayType | SliceType | StructType |
+// PointerType | FuncType | InterfaceType | MapType | ChanType |
+// "(" Type ")" .
+// BasicType = ident .
+// TypeName = ExportedName .
+// SliceType = "[" "]" Type .
+// PointerType = "*" Type .
+// FuncType = "func" Signature .
+//
+func (p *gcParser) parseType() Type {
+ switch p.tok {
+ case scanner.Ident:
+ switch p.lit {
+ default:
+ return p.parseBasicType()
+ case "struct":
+ return p.parseStructType()
+ case "func":
+ // FuncType
+ p.next()
+ return p.parseSignature()
+ case "interface":
+ return p.parseInterfaceType()
+ case "map":
+ return p.parseMapType()
+ case "chan":
+ return p.parseChanType()
+ }
+ case '@':
+ // TypeName
+ pkg, name := p.parseExportedName()
+ return p.declare(pkg.Data.(*ast.Scope), ast.Typ, name).Type.(Type)
+ case '[':
+ p.next() // look ahead
+ if p.tok == ']' {
+ // SliceType
+ p.next()
+ return &Slice{Elt: p.parseType()}
+ }
+ return p.parseArrayType()
+ case '*':
+ // PointerType
+ p.next()
+ return &Pointer{Base: p.parseType()}
+ case '<':
+ return p.parseChanType()
+ case '(':
+ // "(" Type ")"
+ p.next()
+ typ := p.parseType()
+ p.expect(')')
+ return typ
+ }
+ p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
+ return nil
+}
+
+// ----------------------------------------------------------------------------
+// Declarations
+
+// ImportDecl = "import" identifier string_lit .
+//
+func (p *gcParser) parseImportDecl() {
+ p.expectKeyword("import")
+ // The identifier has no semantic meaning in the import data.
+ // It exists so that error messages can print the real package
+ // name: binary.ByteOrder instead of "encoding/binary".ByteOrder.
+ name := p.expect(scanner.Ident)
+ pkg := p.parsePkgId()
+ assert(pkg.Name == "" || pkg.Name == name)
+ pkg.Name = name
+}
+
+// int_lit = [ "+" | "-" ] { "0" ... "9" } .
+//
+func (p *gcParser) parseInt() (sign, val string) {
+ switch p.tok {
+ case '-':
+ p.next()
+ sign = "-"
+ case '+':
+ p.next()
+ }
+ val = p.expect(scanner.Int)
+ return
+}
+
+// number = int_lit [ "p" int_lit ] .
+//
+func (p *gcParser) parseNumber() Const {
+ // mantissa
+ sign, val := p.parseInt()
+ mant, ok := new(big.Int).SetString(sign+val, 10)
+ assert(ok)
+
+ if p.lit == "p" {
+ // exponent (base 2)
+ p.next()
+ sign, val = p.parseInt()
+ exp, err := strconv.Atoui(val)
+ if err != nil {
+ p.error(err)
+ }
+ if sign == "-" {
+ denom := big.NewInt(1)
+ denom.Lsh(denom, exp)
+ return Const{new(big.Rat).SetFrac(mant, denom)}
+ }
+ if exp > 0 {
+ mant.Lsh(mant, exp)
+ }
+ return Const{new(big.Rat).SetInt(mant)}
+ }
+
+ return Const{mant}
+}
+
+// ConstDecl = "const" ExportedName [ Type ] "=" Literal .
+// Literal = bool_lit | int_lit | float_lit | complex_lit | string_lit .
+// bool_lit = "true" | "false" .
+// complex_lit = "(" float_lit "+" float_lit ")" .
+// string_lit = `"` { unicode_char } `"` .
+//
+func (p *gcParser) parseConstDecl() {
+ p.expectKeyword("const")
+ pkg, name := p.parseExportedName()
+ obj := p.declare(pkg.Data.(*ast.Scope), ast.Con, name)
+ var x Const
+ var typ Type
+ if p.tok != '=' {
+ obj.Type = p.parseType()
+ }
+ p.expect('=')
+ switch p.tok {
+ case scanner.Ident:
+ // bool_lit
+ if p.lit != "true" && p.lit != "false" {
+ p.error("expected true or false")
+ }
+ x = Const{p.lit == "true"}
+ typ = Bool.Underlying
+ p.next()
+ case '-', scanner.Int:
+ // int_lit
+ x = p.parseNumber()
+ typ = Int.Underlying
+ if _, ok := x.val.(*big.Rat); ok {
+ typ = Float64.Underlying
+ }
+ case '(':
+ // complex_lit
+ p.next()
+ re := p.parseNumber()
+ p.expect('+')
+ im := p.parseNumber()
+ p.expect(')')
+ x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
+ typ = Complex128.Underlying
+ case scanner.String:
+ // string_lit
+ x = MakeConst(token.STRING, p.lit)
+ p.next()
+ typ = String.Underlying
+ default:
+ p.error("expected literal")
+ }
+ if obj.Type == nil {
+ obj.Type = typ
+ }
+ obj.Data = x
+}
+
+// TypeDecl = "type" ExportedName Type .
+//
+func (p *gcParser) parseTypeDecl() {
+ p.expectKeyword("type")
+ pkg, name := p.parseExportedName()
+ obj := p.declare(pkg.Data.(*ast.Scope), ast.Typ, name)
+
+ // The type object may have been imported before and thus already
+ // have a type associated with it. We still need to parse the type
+ // structure, but throw it away if the object already has a type.
+ // This ensures that all imports refer to the same type object for
+ // a given type declaration.
+ typ := p.parseType()
+
+ if name := obj.Type.(*Name); name.Underlying == nil {
+ assert(Underlying(typ) == typ)
+ name.Underlying = typ
+ }
+}
+
+// VarDecl = "var" ExportedName Type .
+//
+func (p *gcParser) parseVarDecl() {
+ p.expectKeyword("var")
+ pkg, name := p.parseExportedName()
+ obj := p.declare(pkg.Data.(*ast.Scope), ast.Var, name)
+ obj.Type = p.parseType()
+}
+
+// FuncBody = "{" ... "}" .
+//
+func (p *gcParser) parseFuncBody() {
+ p.expect('{')
+ for i := 1; i > 0; p.next() {
+ switch p.tok {
+ case '{':
+ i++
+ case '}':
+ i--
+ }
+ }
+}
+
+// FuncDecl = "func" ExportedName Signature [ FuncBody ] .
+//
+func (p *gcParser) parseFuncDecl() {
+ // "func" already consumed
+ pkg, name := p.parseExportedName()
+ obj := p.declare(pkg.Data.(*ast.Scope), ast.Fun, name)
+ obj.Type = p.parseSignature()
+ if p.tok == '{' {
+ p.parseFuncBody()
+ }
+}
+
+// MethodDecl = "func" Receiver identifier Signature .
+// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
+//
+func (p *gcParser) parseMethodDecl() {
+ // "func" already consumed
+ p.expect('(')
+ p.parseParameter() // receiver
+ p.expect(')')
+ p.expect(scanner.Ident)
+ p.parseSignature()
+ if p.tok == '{' {
+ p.parseFuncBody()
+ }
+}
+
+// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
+//
+func (p *gcParser) parseDecl() {
+ switch p.lit {
+ case "import":
+ p.parseImportDecl()
+ case "const":
+ p.parseConstDecl()
+ case "type":
+ p.parseTypeDecl()
+ case "var":
+ p.parseVarDecl()
+ case "func":
+ p.next() // look ahead
+ if p.tok == '(' {
+ p.parseMethodDecl()
+ } else {
+ p.parseFuncDecl()
+ }
+ }
+ p.expect('\n')
+}
+
+// ----------------------------------------------------------------------------
+// Export
+
+// Export = "PackageClause { Decl } "$$" .
+// PackageClause = "package" identifier [ "safe" ] "\n" .
+//
+func (p *gcParser) parseExport() *ast.Object {
+ p.expectKeyword("package")
+ name := p.expect(scanner.Ident)
+ if p.tok != '\n' {
+ // A package is safe if it was compiled with the -u flag,
+ // which disables the unsafe package.
+ // TODO(gri) remember "safe" package
+ p.expectKeyword("safe")
+ }
+ p.expect('\n')
+
+ assert(p.imports[p.id] == nil)
+ pkg := ast.NewObj(ast.Pkg, name)
+ pkg.Data = ast.NewScope(nil)
+ p.imports[p.id] = pkg
+
+ for p.tok != '$' && p.tok != scanner.EOF {
+ p.parseDecl()
+ }
+
+ if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
+ // don't call next()/expect() since reading past the
+ // export data may cause scanner errors (e.g. NUL chars)
+ p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
+ }
+
+ if n := p.scanner.ErrorCount; n != 0 {
+ p.errorf("expected no scanner errors, got %d", n)
+ }
+
+ return pkg
+}
diff --git a/libgo/go/go/types/gcimporter_test.go b/libgo/go/exp/types/gcimporter_test.go
index ec87f5d514b..ec87f5d514b 100644
--- a/libgo/go/go/types/gcimporter_test.go
+++ b/libgo/go/exp/types/gcimporter_test.go
diff --git a/libgo/go/go/types/testdata/exports.go b/libgo/go/exp/types/testdata/exports.go
index ed63bf9adec..ed63bf9adec 100644
--- a/libgo/go/go/types/testdata/exports.go
+++ b/libgo/go/exp/types/testdata/exports.go
diff --git a/libgo/go/go/types/types.go b/libgo/go/exp/types/types.go
index 3aa896892e3..3aa896892e3 100644
--- a/libgo/go/go/types/types.go
+++ b/libgo/go/exp/types/types.go
diff --git a/libgo/go/exp/types/universe.go b/libgo/go/exp/types/universe.go
new file mode 100644
index 00000000000..80db1278295
--- /dev/null
+++ b/libgo/go/exp/types/universe.go
@@ -0,0 +1,109 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// FILE UNDER CONSTRUCTION. ANY AND ALL PARTS MAY CHANGE.
+// This file implements the universe and unsafe package scopes.
+
+package types
+
+import "go/ast"
+
+var (
+ scope *ast.Scope // current scope to use for initialization
+ Universe *ast.Scope
+ Unsafe *ast.Object // package unsafe
+)
+
+func define(kind ast.ObjKind, name string) *ast.Object {
+ obj := ast.NewObj(kind, name)
+ if scope.Insert(obj) != nil {
+ panic("types internal error: double declaration")
+ }
+ return obj
+}
+
+func defType(name string) *Name {
+ obj := define(ast.Typ, name)
+ typ := &Name{Underlying: &Basic{}, Obj: obj}
+ obj.Type = typ
+ return typ
+}
+
+func defConst(name string) {
+ obj := define(ast.Con, name)
+ _ = obj // TODO(gri) fill in other properties
+}
+
+func defFun(name string) {
+ obj := define(ast.Fun, name)
+ _ = obj // TODO(gri) fill in other properties
+}
+
+var (
+ Bool,
+ Int,
+ Float64,
+ Complex128,
+ String *Name
+)
+
+func init() {
+ scope = ast.NewScope(nil)
+ Universe = scope
+
+ Bool = defType("bool")
+ defType("byte") // TODO(gri) should be an alias for uint8
+ defType("complex64")
+ Complex128 = defType("complex128")
+ defType("float32")
+ Float64 = defType("float64")
+ defType("int8")
+ defType("int16")
+ defType("int32")
+ defType("int64")
+ String = defType("string")
+ defType("uint8")
+ defType("uint16")
+ defType("uint32")
+ defType("uint64")
+ Int = defType("int")
+ defType("uint")
+ defType("uintptr")
+
+ defConst("true")
+ defConst("false")
+ defConst("iota")
+ defConst("nil")
+
+ defFun("append")
+ defFun("cap")
+ defFun("close")
+ defFun("complex")
+ defFun("copy")
+ defFun("delete")
+ defFun("imag")
+ defFun("len")
+ defFun("make")
+ defFun("new")
+ defFun("panic")
+ defFun("print")
+ defFun("println")
+ defFun("real")
+ defFun("recover")
+
+ scope = ast.NewScope(nil)
+ Unsafe = ast.NewObj(ast.Pkg, "unsafe")
+ Unsafe.Data = scope
+
+ defType("Pointer")
+
+ defFun("Alignof")
+ defFun("New")
+ defFun("NewArray")
+ defFun("Offsetof")
+ defFun("Reflect")
+ defFun("Sizeof")
+ defFun("Typeof")
+ defFun("Unreflect")
+}
diff --git a/libgo/go/exp/winfsnotify/winfsnotify.go b/libgo/go/exp/winfsnotify/winfsnotify.go
new file mode 100644
index 00000000000..c5dfe99ad71
--- /dev/null
+++ b/libgo/go/exp/winfsnotify/winfsnotify.go
@@ -0,0 +1,569 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package winfsnotify allows the user to receive
+// file system event notifications on Windows.
+package winfsnotify
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+ "syscall"
+ "unsafe"
+)
+
+// Event is the type of the notification messages
+// received on the watcher's Event channel.
+type Event struct {
+ Mask uint32 // Mask of events
+ Cookie uint32 // Unique cookie associating related events (for rename)
+ Name string // File name (optional)
+}
+
+const (
+ opAddWatch = iota
+ opRemoveWatch
+)
+
+const (
+ provisional uint64 = 1 << (32 + iota)
+)
+
+type input struct {
+ op int
+ path string
+ flags uint32
+ reply chan os.Error
+}
+
+type inode struct {
+ handle syscall.Handle
+ volume uint32
+ index uint64
+}
+
+type watch struct {
+ ov syscall.Overlapped
+ ino *inode // i-number
+ path string // Directory path
+ mask uint64 // Directory itself is being watched with these notify flags
+ names map[string]uint64 // Map of names being watched and their notify flags
+ rename string // Remembers the old name while renaming a file
+ buf [4096]byte
+}
+
+type indexMap map[uint64]*watch
+type watchMap map[uint32]indexMap
+
+// A Watcher waits for and receives event notifications
+// for a specific set of files and directories.
+type Watcher struct {
+ port syscall.Handle // Handle to completion port
+ watches watchMap // Map of watches (key: i-number)
+ input chan *input // Inputs to the reader are sent on this channel
+ Event chan *Event // Events are returned on this channel
+ Error chan os.Error // Errors are sent on this channel
+ isClosed bool // Set to true when Close() is first called
+ quit chan chan<- os.Error
+ cookie uint32
+}
+
+// NewWatcher creates and returns a Watcher.
+func NewWatcher() (*Watcher, os.Error) {
+ port, e := syscall.CreateIoCompletionPort(syscall.InvalidHandle, 0, 0, 0)
+ if e != 0 {
+ return nil, os.NewSyscallError("CreateIoCompletionPort", e)
+ }
+ w := &Watcher{
+ port: port,
+ watches: make(watchMap),
+ input: make(chan *input, 1),
+ Event: make(chan *Event, 50),
+ Error: make(chan os.Error),
+ quit: make(chan chan<- os.Error, 1),
+ }
+ go w.readEvents()
+ return w, nil
+}
+
+// Close closes a Watcher.
+// It sends a message to the reader goroutine to quit and removes all watches
+// associated with the watcher.
+func (w *Watcher) Close() os.Error {
+ if w.isClosed {
+ return nil
+ }
+ w.isClosed = true
+
+ // Send "quit" message to the reader goroutine
+ ch := make(chan os.Error)
+ w.quit <- ch
+ if err := w.wakeupReader(); err != nil {
+ return err
+ }
+ return <-ch
+}
+
+// AddWatch adds path to the watched file set.
+func (w *Watcher) AddWatch(path string, flags uint32) os.Error {
+ if w.isClosed {
+ return os.NewError("watcher already closed")
+ }
+ in := &input{
+ op: opAddWatch,
+ path: filepath.Clean(path),
+ flags: flags,
+ reply: make(chan os.Error),
+ }
+ w.input <- in
+ if err := w.wakeupReader(); err != nil {
+ return err
+ }
+ return <-in.reply
+}
+
+// Watch adds path to the watched file set, watching all events.
+func (w *Watcher) Watch(path string) os.Error {
+ return w.AddWatch(path, FS_ALL_EVENTS)
+}
+
+// RemoveWatch removes path from the watched file set.
+func (w *Watcher) RemoveWatch(path string) os.Error {
+ in := &input{
+ op: opRemoveWatch,
+ path: filepath.Clean(path),
+ reply: make(chan os.Error),
+ }
+ w.input <- in
+ if err := w.wakeupReader(); err != nil {
+ return err
+ }
+ return <-in.reply
+}
+
+func (w *Watcher) wakeupReader() os.Error {
+ e := syscall.PostQueuedCompletionStatus(w.port, 0, 0, nil)
+ if e != 0 {
+ return os.NewSyscallError("PostQueuedCompletionStatus", e)
+ }
+ return nil
+}
+
+func getDir(pathname string) (dir string, err os.Error) {
+ attr, e := syscall.GetFileAttributes(syscall.StringToUTF16Ptr(pathname))
+ if e != 0 {
+ return "", os.NewSyscallError("GetFileAttributes", e)
+ }
+ if attr&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
+ dir = pathname
+ } else {
+ dir, _ = filepath.Split(pathname)
+ dir = filepath.Clean(dir)
+ }
+ return
+}
+
+func getIno(path string) (ino *inode, err os.Error) {
+ h, e := syscall.CreateFile(syscall.StringToUTF16Ptr(path),
+ syscall.FILE_LIST_DIRECTORY,
+ syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE|syscall.FILE_SHARE_DELETE,
+ nil, syscall.OPEN_EXISTING,
+ syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OVERLAPPED, 0)
+ if e != 0 {
+ return nil, os.NewSyscallError("CreateFile", e)
+ }
+ var fi syscall.ByHandleFileInformation
+ if e = syscall.GetFileInformationByHandle(h, &fi); e != 0 {
+ syscall.CloseHandle(h)
+ return nil, os.NewSyscallError("GetFileInformationByHandle", e)
+ }
+ ino = &inode{
+ handle: h,
+ volume: fi.VolumeSerialNumber,
+ index: uint64(fi.FileIndexHigh)<<32 | uint64(fi.FileIndexLow),
+ }
+ return ino, nil
+}
+
+// Must run within the I/O thread.
+func (m watchMap) get(ino *inode) *watch {
+ if i := m[ino.volume]; i != nil {
+ return i[ino.index]
+ }
+ return nil
+}
+
+// Must run within the I/O thread.
+func (m watchMap) set(ino *inode, watch *watch) {
+ i := m[ino.volume]
+ if i == nil {
+ i = make(indexMap)
+ m[ino.volume] = i
+ }
+ i[ino.index] = watch
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) addWatch(pathname string, flags uint64) os.Error {
+ dir, err := getDir(pathname)
+ if err != nil {
+ return err
+ }
+ if flags&FS_ONLYDIR != 0 && pathname != dir {
+ return nil
+ }
+ ino, err := getIno(dir)
+ if err != nil {
+ return err
+ }
+ watchEntry := w.watches.get(ino)
+ if watchEntry == nil {
+ if _, e := syscall.CreateIoCompletionPort(ino.handle, w.port, 0, 0); e != 0 {
+ syscall.CloseHandle(ino.handle)
+ return os.NewSyscallError("CreateIoCompletionPort", e)
+ }
+ watchEntry = &watch{
+ ino: ino,
+ path: dir,
+ names: make(map[string]uint64),
+ }
+ w.watches.set(ino, watchEntry)
+ flags |= provisional
+ } else {
+ syscall.CloseHandle(ino.handle)
+ }
+ if pathname == dir {
+ watchEntry.mask |= flags
+ } else {
+ watchEntry.names[filepath.Base(pathname)] |= flags
+ }
+ if err = w.startRead(watchEntry); err != nil {
+ return err
+ }
+ if pathname == dir {
+ watchEntry.mask &= ^provisional
+ } else {
+ watchEntry.names[filepath.Base(pathname)] &= ^provisional
+ }
+ return nil
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) removeWatch(pathname string) os.Error {
+ dir, err := getDir(pathname)
+ if err != nil {
+ return err
+ }
+ ino, err := getIno(dir)
+ if err != nil {
+ return err
+ }
+ watch := w.watches.get(ino)
+ if watch == nil {
+ return fmt.Errorf("can't remove non-existent watch for: %s", pathname)
+ }
+ if pathname == dir {
+ w.sendEvent(watch.path, watch.mask&FS_IGNORED)
+ watch.mask = 0
+ } else {
+ name := filepath.Base(pathname)
+ w.sendEvent(watch.path+"/"+name, watch.names[name]&FS_IGNORED)
+ delete(watch.names, name)
+ }
+ return w.startRead(watch)
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) deleteWatch(watch *watch) {
+ for name, mask := range watch.names {
+ if mask&provisional == 0 {
+ w.sendEvent(watch.path+"/"+name, mask&FS_IGNORED)
+ }
+ delete(watch.names, name)
+ }
+ if watch.mask != 0 {
+ if watch.mask&provisional == 0 {
+ w.sendEvent(watch.path, watch.mask&FS_IGNORED)
+ }
+ watch.mask = 0
+ }
+}
+
+// Must run within the I/O thread.
+func (w *Watcher) startRead(watch *watch) os.Error {
+ if e := syscall.CancelIo(watch.ino.handle); e != 0 {
+ w.Error <- os.NewSyscallError("CancelIo", e)
+ w.deleteWatch(watch)
+ }
+ mask := toWindowsFlags(watch.mask)
+ for _, m := range watch.names {
+ mask |= toWindowsFlags(m)
+ }
+ if mask == 0 {
+ if e := syscall.CloseHandle(watch.ino.handle); e != 0 {
+ w.Error <- os.NewSyscallError("CloseHandle", e)
+ }
+ delete(w.watches[watch.ino.volume], watch.ino.index)
+ return nil
+ }
+ e := syscall.ReadDirectoryChanges(watch.ino.handle, &watch.buf[0],
+ uint32(unsafe.Sizeof(watch.buf)), false, mask, nil, &watch.ov, 0)
+ if e != 0 {
+ err := os.NewSyscallError("ReadDirectoryChanges", e)
+ if e == syscall.ERROR_ACCESS_DENIED && watch.mask&provisional == 0 {
+ // Watched directory was probably removed
+ if w.sendEvent(watch.path, watch.mask&FS_DELETE_SELF) {
+ if watch.mask&FS_ONESHOT != 0 {
+ watch.mask = 0
+ }
+ }
+ err = nil
+ }
+ w.deleteWatch(watch)
+ w.startRead(watch)
+ return err
+ }
+ return nil
+}
+
+// readEvents reads from the I/O completion port, converts the
+// received events into Event objects and sends them via the Event channel.
+// Entry point to the I/O thread.
+func (w *Watcher) readEvents() {
+ var (
+ n, key uint32
+ ov *syscall.Overlapped
+ )
+ runtime.LockOSThread()
+
+ for {
+ e := syscall.GetQueuedCompletionStatus(w.port, &n, &key, &ov, syscall.INFINITE)
+ watch := (*watch)(unsafe.Pointer(ov))
+
+ if watch == nil {
+ select {
+ case ch := <-w.quit:
+ for _, index := range w.watches {
+ for _, watch := range index {
+ w.deleteWatch(watch)
+ w.startRead(watch)
+ }
+ }
+ var err os.Error
+ if e := syscall.CloseHandle(w.port); e != 0 {
+ err = os.NewSyscallError("CloseHandle", e)
+ }
+ close(w.Event)
+ close(w.Error)
+ ch <- err
+ return
+ case in := <-w.input:
+ switch in.op {
+ case opAddWatch:
+ in.reply <- w.addWatch(in.path, uint64(in.flags))
+ case opRemoveWatch:
+ in.reply <- w.removeWatch(in.path)
+ }
+ default:
+ }
+ continue
+ }
+
+ switch e {
+ case syscall.ERROR_ACCESS_DENIED:
+ // Watched directory was probably removed
+ w.sendEvent(watch.path, watch.mask&FS_DELETE_SELF)
+ w.deleteWatch(watch)
+ w.startRead(watch)
+ continue
+ case syscall.ERROR_OPERATION_ABORTED:
+ // CancelIo was called on this handle
+ continue
+ default:
+ w.Error <- os.NewSyscallError("GetQueuedCompletionPort", e)
+ continue
+ case 0:
+ }
+
+ var offset uint32
+ for {
+ if n == 0 {
+ w.Event <- &Event{Mask: FS_Q_OVERFLOW}
+ w.Error <- os.NewError("short read in readEvents()")
+ break
+ }
+
+ // Point "raw" to the event in the buffer
+ raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset]))
+ buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))
+ name := syscall.UTF16ToString(buf[:raw.FileNameLength/2])
+ fullname := watch.path + "/" + name
+
+ var mask uint64
+ switch raw.Action {
+ case syscall.FILE_ACTION_REMOVED:
+ mask = FS_DELETE_SELF
+ case syscall.FILE_ACTION_MODIFIED:
+ mask = FS_MODIFY
+ case syscall.FILE_ACTION_RENAMED_OLD_NAME:
+ watch.rename = name
+ case syscall.FILE_ACTION_RENAMED_NEW_NAME:
+ if watch.names[watch.rename] != 0 {
+ watch.names[name] |= watch.names[watch.rename]
+ delete(watch.names, watch.rename)
+ mask = FS_MOVE_SELF
+ }
+ }
+
+ sendNameEvent := func() {
+ if w.sendEvent(fullname, watch.names[name]&mask) {
+ if watch.names[name]&FS_ONESHOT != 0 {
+ delete(watch.names, name)
+ }
+ }
+ }
+ if raw.Action != syscall.FILE_ACTION_RENAMED_NEW_NAME {
+ sendNameEvent()
+ }
+ if raw.Action == syscall.FILE_ACTION_REMOVED {
+ w.sendEvent(fullname, watch.names[name]&FS_IGNORED)
+ delete(watch.names, name)
+ }
+ if w.sendEvent(fullname, watch.mask&toFSnotifyFlags(raw.Action)) {
+ if watch.mask&FS_ONESHOT != 0 {
+ watch.mask = 0
+ }
+ }
+ if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME {
+ fullname = watch.path + "/" + watch.rename
+ sendNameEvent()
+ }
+
+ // Move to the next event in the buffer
+ if raw.NextEntryOffset == 0 {
+ break
+ }
+ offset += raw.NextEntryOffset
+ }
+
+ if err := w.startRead(watch); err != nil {
+ w.Error <- err
+ }
+ }
+}
+
+func (w *Watcher) sendEvent(name string, mask uint64) bool {
+ if mask == 0 {
+ return false
+ }
+ event := &Event{Mask: uint32(mask), Name: name}
+ if mask&FS_MOVE != 0 {
+ if mask&FS_MOVED_FROM != 0 {
+ w.cookie++
+ }
+ event.Cookie = w.cookie
+ }
+ select {
+ case ch := <-w.quit:
+ w.quit <- ch
+ case w.Event <- event:
+ }
+ return true
+}
+
+// String formats the event e in the form
+// "filename: 0xEventMask = FS_ACCESS|FS_ATTRIB_|..."
+func (e *Event) String() string {
+ var events string
+ m := e.Mask
+ for _, b := range eventBits {
+ if m&b.Value != 0 {
+ m &^= b.Value
+ events += "|" + b.Name
+ }
+ }
+ if m != 0 {
+ events += fmt.Sprintf("|%#x", m)
+ }
+ if len(events) > 0 {
+ events = " == " + events[1:]
+ }
+ return fmt.Sprintf("%q: %#x%s", e.Name, e.Mask, events)
+}
+
+func toWindowsFlags(mask uint64) uint32 {
+ var m uint32
+ if mask&FS_ACCESS != 0 {
+ m |= syscall.FILE_NOTIFY_CHANGE_LAST_ACCESS
+ }
+ if mask&FS_MODIFY != 0 {
+ m |= syscall.FILE_NOTIFY_CHANGE_LAST_WRITE
+ }
+ if mask&FS_ATTRIB != 0 {
+ m |= syscall.FILE_NOTIFY_CHANGE_ATTRIBUTES
+ }
+ if mask&(FS_MOVE|FS_CREATE|FS_DELETE) != 0 {
+ m |= syscall.FILE_NOTIFY_CHANGE_FILE_NAME | syscall.FILE_NOTIFY_CHANGE_DIR_NAME
+ }
+ return m
+}
+
+func toFSnotifyFlags(action uint32) uint64 {
+ switch action {
+ case syscall.FILE_ACTION_ADDED:
+ return FS_CREATE
+ case syscall.FILE_ACTION_REMOVED:
+ return FS_DELETE
+ case syscall.FILE_ACTION_MODIFIED:
+ return FS_MODIFY
+ case syscall.FILE_ACTION_RENAMED_OLD_NAME:
+ return FS_MOVED_FROM
+ case syscall.FILE_ACTION_RENAMED_NEW_NAME:
+ return FS_MOVED_TO
+ }
+ return 0
+}
+
+const (
+ // Options for AddWatch
+ FS_ONESHOT = 0x80000000
+ FS_ONLYDIR = 0x1000000
+
+ // Events
+ FS_ACCESS = 0x1
+ FS_ALL_EVENTS = 0xfff
+ FS_ATTRIB = 0x4
+ FS_CLOSE = 0x18
+ FS_CREATE = 0x100
+ FS_DELETE = 0x200
+ FS_DELETE_SELF = 0x400
+ FS_MODIFY = 0x2
+ FS_MOVE = 0xc0
+ FS_MOVED_FROM = 0x40
+ FS_MOVED_TO = 0x80
+ FS_MOVE_SELF = 0x800
+
+ // Special events
+ FS_IGNORED = 0x8000
+ FS_Q_OVERFLOW = 0x4000
+)
+
+var eventBits = []struct {
+ Value uint32
+ Name string
+}{
+ {FS_ACCESS, "FS_ACCESS"},
+ {FS_ATTRIB, "FS_ATTRIB"},
+ {FS_CREATE, "FS_CREATE"},
+ {FS_DELETE, "FS_DELETE"},
+ {FS_DELETE_SELF, "FS_DELETE_SELF"},
+ {FS_MODIFY, "FS_MODIFY"},
+ {FS_MOVED_FROM, "FS_MOVED_FROM"},
+ {FS_MOVED_TO, "FS_MOVED_TO"},
+ {FS_MOVE_SELF, "FS_MOVE_SELF"},
+ {FS_IGNORED, "FS_IGNORED"},
+ {FS_Q_OVERFLOW, "FS_Q_OVERFLOW"},
+}
diff --git a/libgo/go/exp/winfsnotify/winfsnotify_test.go b/libgo/go/exp/winfsnotify/winfsnotify_test.go
new file mode 100644
index 00000000000..edf2165c0ec
--- /dev/null
+++ b/libgo/go/exp/winfsnotify/winfsnotify_test.go
@@ -0,0 +1,124 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package winfsnotify
+
+import (
+ "os"
+ "time"
+ "testing"
+)
+
+func expect(t *testing.T, eventstream <-chan *Event, name string, mask uint32) {
+ t.Logf(`expected: "%s": 0x%x`, name, mask)
+ select {
+ case event := <-eventstream:
+ if event == nil {
+ t.Fatal("nil event received")
+ }
+ t.Logf("received: %s", event)
+ if event.Name != name || event.Mask != mask {
+ t.Fatal("did not receive expected event")
+ }
+ case <-time.After(1e9):
+ t.Fatal("timed out waiting for event")
+ }
+}
+
+func TestNotifyEvents(t *testing.T) {
+ watcher, err := NewWatcher()
+ if err != nil {
+ t.Fatalf("NewWatcher() failed: %s", err)
+ }
+
+ testDir := "TestNotifyEvents.testdirectory"
+ testFile := testDir + "/TestNotifyEvents.testfile"
+ testFile2 := testFile + ".new"
+ const mask = FS_ALL_EVENTS & ^(FS_ATTRIB|FS_CLOSE) | FS_IGNORED
+
+ // Add a watch for testDir
+ os.RemoveAll(testDir)
+ if err = os.Mkdir(testDir, 0777); err != nil {
+ t.Fatalf("Failed to create test directory", err)
+ }
+ defer os.RemoveAll(testDir)
+ err = watcher.AddWatch(testDir, mask)
+ if err != nil {
+ t.Fatalf("Watcher.Watch() failed: %s", err)
+ }
+
+ // Receive errors on the error channel on a separate goroutine
+ go func() {
+ for err := range watcher.Error {
+ t.Fatalf("error received: %s", err)
+ }
+ }()
+
+ // Create a file
+ file, err := os.Create(testFile)
+ if err != nil {
+ t.Fatalf("creating test file failed: %s", err)
+ }
+ expect(t, watcher.Event, testFile, FS_CREATE)
+
+ err = watcher.AddWatch(testFile, mask)
+ if err != nil {
+ t.Fatalf("Watcher.Watch() failed: %s", err)
+ }
+
+ if _, err = file.WriteString("hello, world"); err != nil {
+ t.Fatalf("failed to write to test file: %s", err)
+ }
+ if err = file.Sync(); err != nil {
+ t.Fatalf("failed to sync test file: %s", err)
+ }
+ expect(t, watcher.Event, testFile, FS_MODIFY)
+ expect(t, watcher.Event, testFile, FS_MODIFY)
+
+ if err = file.Close(); err != nil {
+ t.Fatalf("failed to close test file: %s", err)
+ }
+
+ if err = os.Rename(testFile, testFile2); err != nil {
+ t.Fatalf("failed to rename test file: %s", err)
+ }
+ expect(t, watcher.Event, testFile, FS_MOVED_FROM)
+ expect(t, watcher.Event, testFile2, FS_MOVED_TO)
+ expect(t, watcher.Event, testFile, FS_MOVE_SELF)
+
+ if err = os.RemoveAll(testDir); err != nil {
+ t.Fatalf("failed to remove test directory: %s", err)
+ }
+ expect(t, watcher.Event, testFile2, FS_DELETE_SELF)
+ expect(t, watcher.Event, testFile2, FS_IGNORED)
+ expect(t, watcher.Event, testFile2, FS_DELETE)
+ expect(t, watcher.Event, testDir, FS_DELETE_SELF)
+ expect(t, watcher.Event, testDir, FS_IGNORED)
+
+ t.Log("calling Close()")
+ if err = watcher.Close(); err != nil {
+ t.Fatalf("failed to close watcher: %s", err)
+ }
+}
+
+func TestNotifyClose(t *testing.T) {
+ watcher, _ := NewWatcher()
+ watcher.Close()
+
+ done := false
+ go func() {
+ watcher.Close()
+ done = true
+ }()
+
+ time.Sleep(50e6) // 50 ms
+ if !done {
+ t.Fatal("double Close() test failed: second Close() call didn't return")
+ }
+
+ err := watcher.Watch("_test")
+ if err == nil {
+ t.Fatal("expected error on Watch() after Close(), got nil")
+ }
+}
diff --git a/libgo/go/exp/wingui/gui.go b/libgo/go/exp/wingui/gui.go
index cf392934c5b..a2f16f282b1 100644
--- a/libgo/go/exp/wingui/gui.go
+++ b/libgo/go/exp/wingui/gui.go
@@ -25,13 +25,12 @@ func abortErrNo(funcname string, err int) {
// global vars
var (
- mh uint32
- bh uint32
+ mh syscall.Handle
+ bh syscall.Handle
)
// WinProc called by windows to notify us of all windows events we might be interested in.
-func WndProc(hwnd, msg uint32, wparam, lparam int32) uintptr {
- var rc int32
+func WndProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) (rc uintptr) {
switch msg {
case WM_CREATE:
var e int
@@ -49,7 +48,7 @@ func WndProc(hwnd, msg uint32, wparam, lparam int32) uintptr {
fmt.Printf("button handle is %x\n", bh)
rc = DefWindowProc(hwnd, msg, wparam, lparam)
case WM_COMMAND:
- switch uint32(lparam) {
+ switch syscall.Handle(lparam) {
case bh:
e := PostMessage(hwnd, WM_CLOSE, 0, 0)
if e != 0 {
@@ -66,7 +65,7 @@ func WndProc(hwnd, msg uint32, wparam, lparam int32) uintptr {
rc = DefWindowProc(hwnd, msg, wparam, lparam)
}
//fmt.Printf("WndProc(0x%08x, %d, 0x%08x, 0x%08x) (%d)\n", hwnd, msg, wparam, lparam, rc)
- return uintptr(rc)
+ return
}
func rungui() int {
diff --git a/libgo/go/exp/wingui/winapi.go b/libgo/go/exp/wingui/winapi.go
index 31b57a2cc86..32015287c92 100644
--- a/libgo/go/exp/wingui/winapi.go
+++ b/libgo/go/exp/wingui/winapi.go
@@ -6,6 +6,7 @@ package main
import (
"unsafe"
+ "syscall"
)
type Wndclassex struct {
@@ -14,25 +15,25 @@ type Wndclassex struct {
WndProc uintptr
ClsExtra int32
WndExtra int32
- Instance uint32
- Icon uint32
- Cursor uint32
- Background uint32
+ Instance syscall.Handle
+ Icon syscall.Handle
+ Cursor syscall.Handle
+ Background syscall.Handle
MenuName *uint16
ClassName *uint16
- IconSm uint32
+ IconSm syscall.Handle
}
type Point struct {
- X int32
- Y int32
+ X uintptr
+ Y uintptr
}
type Msg struct {
- Hwnd uint32
+ Hwnd syscall.Handle
Message uint32
- Wparam int32
- Lparam int32
+ Wparam uintptr
+ Lparam uintptr
Time uint32
Pt Point
}
@@ -109,22 +110,22 @@ var (
IDI_INFORMATION = IDI_ASTERISK
)
-//sys GetModuleHandle(modname *uint16) (handle uint32, errno int) = GetModuleHandleW
+//sys GetModuleHandle(modname *uint16) (handle syscall.Handle, errno int) = GetModuleHandleW
//sys RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) = user32.RegisterClassExW
-//sys CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent uint32, menu uint32, instance uint32, param uintptr) (hwnd uint32, errno int) = user32.CreateWindowExW
-//sys DefWindowProc(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) = user32.DefWindowProcW
-//sys DestroyWindow(hwnd uint32) (errno int) = user32.DestroyWindow
+//sys CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, errno int) = user32.CreateWindowExW
+//sys DefWindowProc(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) = user32.DefWindowProcW
+//sys DestroyWindow(hwnd syscall.Handle) (errno int) = user32.DestroyWindow
//sys PostQuitMessage(exitcode int32) = user32.PostQuitMessage
-//sys ShowWindow(hwnd uint32, cmdshow int32) (wasvisible bool) = user32.ShowWindow
-//sys UpdateWindow(hwnd uint32) (errno int) = user32.UpdateWindow
-//sys GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) [failretval==-1] = user32.GetMessageW
+//sys ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) = user32.ShowWindow
+//sys UpdateWindow(hwnd syscall.Handle) (errno int) = user32.UpdateWindow
+//sys GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) [failretval==-1] = user32.GetMessageW
//sys TranslateMessage(msg *Msg) (done bool) = user32.TranslateMessage
//sys DispatchMessage(msg *Msg) (ret int32) = user32.DispatchMessageW
-//sys LoadIcon(instance uint32, iconname *uint16) (icon uint32, errno int) = user32.LoadIconW
-//sys LoadCursor(instance uint32, cursorname *uint16) (cursor uint32, errno int) = user32.LoadCursorW
-//sys SetCursor(cursor uint32) (precursor uint32, errno int) = user32.SetCursor
-//sys SendMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) = user32.SendMessageW
-//sys PostMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (errno int) = user32.PostMessageW
+//sys LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, errno int) = user32.LoadIconW
+//sys LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, errno int) = user32.LoadCursorW
+//sys SetCursor(cursor syscall.Handle) (precursor syscall.Handle, errno int) = user32.SetCursor
+//sys SendMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) = user32.SendMessageW
+//sys PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (errno int) = user32.PostMessageW
func MakeIntResource(id uint16) *uint16 {
return (*uint16)(unsafe.Pointer(uintptr(id)))
diff --git a/libgo/go/exp/wingui/zwinapi.go b/libgo/go/exp/wingui/zwinapi.go
index 4c009dd69bc..38e93eea717 100644
--- a/libgo/go/exp/wingui/zwinapi.go
+++ b/libgo/go/exp/wingui/zwinapi.go
@@ -28,9 +28,9 @@ var (
procPostMessageW = moduser32.NewProc("PostMessageW")
)
-func GetModuleHandle(modname *uint16) (handle uint32, errno int) {
+func GetModuleHandle(modname *uint16) (handle syscall.Handle, errno int) {
r0, _, e1 := syscall.Syscall(procGetModuleHandleW.Addr(), 1, uintptr(unsafe.Pointer(modname)), 0, 0)
- handle = uint32(r0)
+ handle = syscall.Handle(r0)
if handle == 0 {
if e1 != 0 {
errno = int(e1)
@@ -58,9 +58,9 @@ func RegisterClassEx(wndclass *Wndclassex) (atom uint16, errno int) {
return
}
-func CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent uint32, menu uint32, instance uint32, param uintptr) (hwnd uint32, errno int) {
+func CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style uint32, x int32, y int32, width int32, height int32, wndparent syscall.Handle, menu syscall.Handle, instance syscall.Handle, param uintptr) (hwnd syscall.Handle, errno int) {
r0, _, e1 := syscall.Syscall12(procCreateWindowExW.Addr(), 12, uintptr(exstyle), uintptr(unsafe.Pointer(classname)), uintptr(unsafe.Pointer(windowname)), uintptr(style), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(wndparent), uintptr(menu), uintptr(instance), uintptr(param))
- hwnd = uint32(r0)
+ hwnd = syscall.Handle(r0)
if hwnd == 0 {
if e1 != 0 {
errno = int(e1)
@@ -73,13 +73,13 @@ func CreateWindowEx(exstyle uint32, classname *uint16, windowname *uint16, style
return
}
-func DefWindowProc(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) {
+func DefWindowProc(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) {
r0, _, _ := syscall.Syscall6(procDefWindowProcW.Addr(), 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
- lresult = int32(r0)
+ lresult = uintptr(r0)
return
}
-func DestroyWindow(hwnd uint32) (errno int) {
+func DestroyWindow(hwnd syscall.Handle) (errno int) {
r1, _, e1 := syscall.Syscall(procDestroyWindow.Addr(), 1, uintptr(hwnd), 0, 0)
if int(r1) == 0 {
if e1 != 0 {
@@ -98,13 +98,13 @@ func PostQuitMessage(exitcode int32) {
return
}
-func ShowWindow(hwnd uint32, cmdshow int32) (wasvisible bool) {
+func ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) {
r0, _, _ := syscall.Syscall(procShowWindow.Addr(), 2, uintptr(hwnd), uintptr(cmdshow), 0)
wasvisible = bool(r0 != 0)
return
}
-func UpdateWindow(hwnd uint32) (errno int) {
+func UpdateWindow(hwnd syscall.Handle) (errno int) {
r1, _, e1 := syscall.Syscall(procUpdateWindow.Addr(), 1, uintptr(hwnd), 0, 0)
if int(r1) == 0 {
if e1 != 0 {
@@ -118,7 +118,7 @@ func UpdateWindow(hwnd uint32) (errno int) {
return
}
-func GetMessage(msg *Msg, hwnd uint32, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) {
+func GetMessage(msg *Msg, hwnd syscall.Handle, MsgFilterMin uint32, MsgFilterMax uint32) (ret int32, errno int) {
r0, _, e1 := syscall.Syscall6(procGetMessageW.Addr(), 4, uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(MsgFilterMin), uintptr(MsgFilterMax), 0, 0)
ret = int32(r0)
if ret == -1 {
@@ -145,9 +145,9 @@ func DispatchMessage(msg *Msg) (ret int32) {
return
}
-func LoadIcon(instance uint32, iconname *uint16) (icon uint32, errno int) {
+func LoadIcon(instance syscall.Handle, iconname *uint16) (icon syscall.Handle, errno int) {
r0, _, e1 := syscall.Syscall(procLoadIconW.Addr(), 2, uintptr(instance), uintptr(unsafe.Pointer(iconname)), 0)
- icon = uint32(r0)
+ icon = syscall.Handle(r0)
if icon == 0 {
if e1 != 0 {
errno = int(e1)
@@ -160,9 +160,9 @@ func LoadIcon(instance uint32, iconname *uint16) (icon uint32, errno int) {
return
}
-func LoadCursor(instance uint32, cursorname *uint16) (cursor uint32, errno int) {
+func LoadCursor(instance syscall.Handle, cursorname *uint16) (cursor syscall.Handle, errno int) {
r0, _, e1 := syscall.Syscall(procLoadCursorW.Addr(), 2, uintptr(instance), uintptr(unsafe.Pointer(cursorname)), 0)
- cursor = uint32(r0)
+ cursor = syscall.Handle(r0)
if cursor == 0 {
if e1 != 0 {
errno = int(e1)
@@ -175,9 +175,9 @@ func LoadCursor(instance uint32, cursorname *uint16) (cursor uint32, errno int)
return
}
-func SetCursor(cursor uint32) (precursor uint32, errno int) {
+func SetCursor(cursor syscall.Handle) (precursor syscall.Handle, errno int) {
r0, _, e1 := syscall.Syscall(procSetCursor.Addr(), 1, uintptr(cursor), 0, 0)
- precursor = uint32(r0)
+ precursor = syscall.Handle(r0)
if precursor == 0 {
if e1 != 0 {
errno = int(e1)
@@ -190,13 +190,13 @@ func SetCursor(cursor uint32) (precursor uint32, errno int) {
return
}
-func SendMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (lresult int32) {
+func SendMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (lresult uintptr) {
r0, _, _ := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
- lresult = int32(r0)
+ lresult = uintptr(r0)
return
}
-func PostMessage(hwnd uint32, msg uint32, wparam int32, lparam int32) (errno int) {
+func PostMessage(hwnd syscall.Handle, msg uint32, wparam uintptr, lparam uintptr) (errno int) {
r1, _, e1 := syscall.Syscall6(procPostMessageW.Addr(), 4, uintptr(hwnd), uintptr(msg), uintptr(wparam), uintptr(lparam), 0, 0)
if int(r1) == 0 {
if e1 != 0 {
diff --git a/libgo/go/flag/flag.go b/libgo/go/flag/flag.go
index 01bbc377008..f13f7a45cd3 100644
--- a/libgo/go/flag/flag.go
+++ b/libgo/go/flag/flag.go
@@ -204,6 +204,7 @@ type FlagSet struct {
Usage func()
name string
+ parsed bool
actual map[string]*Flag
formal map[string]*Flag
args []string // arguments after flags
@@ -285,6 +286,9 @@ func (f *FlagSet) Set(name, value string) bool {
if !ok {
return false
}
+ if f.actual == nil {
+ f.actual = make(map[string]*Flag)
+ }
f.actual[name] = flag
return true
}
@@ -318,10 +322,15 @@ func defaultUsage(f *FlagSet) {
f.PrintDefaults()
}
+// NOTE: Usage is not just defaultUsage(commandLine)
+// because it serves (via godoc flag Usage) as the example
+// for how to write your own usage function.
+
// Usage prints to standard error a usage message documenting all defined command-line flags.
// The function is a variable that may be changed to point to a custom function.
var Usage = func() {
- defaultUsage(commandLine)
+ fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
+ PrintDefaults()
}
// NFlag returns the number of flags that have been set.
@@ -553,6 +562,9 @@ func (f *FlagSet) Var(value Value, name string, usage string) {
fmt.Fprintf(os.Stderr, "%s flag redefined: %s\n", f.name, name)
panic("flag redefinition") // Happens only if flags are declared with identical names
}
+ if f.formal == nil {
+ f.formal = make(map[string]*Flag)
+ }
f.formal[name] = flag
}
@@ -580,6 +592,8 @@ func (f *FlagSet) failf(format string, a ...interface{}) os.Error {
func (f *FlagSet) usage() {
if f == commandLine {
Usage()
+ } else if f.Usage == nil {
+ defaultUsage(f)
} else {
f.Usage()
}
@@ -651,6 +665,9 @@ func (f *FlagSet) parseOne() (bool, os.Error) {
return false, f.failf("invalid value %q for flag: -%s", value, name)
}
}
+ if f.actual == nil {
+ f.actual = make(map[string]*Flag)
+ }
f.actual[name] = flag
return true, nil
}
@@ -660,6 +677,7 @@ func (f *FlagSet) parseOne() (bool, os.Error) {
// are defined and before flags are accessed by the program.
// The return value will be ErrHelp if -help was set but not defined.
func (f *FlagSet) Parse(arguments []string) os.Error {
+ f.parsed = true
f.args = arguments
for {
seen, err := f.parseOne()
@@ -681,6 +699,11 @@ func (f *FlagSet) Parse(arguments []string) os.Error {
return nil
}
+// Parsed reports whether f.Parse has been called.
+func (f *FlagSet) Parsed() bool {
+ return f.parsed
+}
+
// Parse parses the command-line flags from os.Args[1:]. Must be called
// after all flags are defined and before flags are accessed by the program.
func Parse() {
@@ -688,6 +711,11 @@ func Parse() {
commandLine.Parse(os.Args[1:])
}
+// Parsed returns true if the command-line flags have been parsed.
+func Parsed() bool {
+ return commandLine.Parsed()
+}
+
// The default set of command-line flags, parsed from os.Args.
var commandLine = NewFlagSet(os.Args[0], ExitOnError)
@@ -696,10 +724,15 @@ var commandLine = NewFlagSet(os.Args[0], ExitOnError)
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
f := &FlagSet{
name: name,
- actual: make(map[string]*Flag),
- formal: make(map[string]*Flag),
errorHandling: errorHandling,
}
- f.Usage = func() { defaultUsage(f) }
return f
}
+
+// Init sets the name and error handling property for a flag set.
+// By default, the zero FlagSet uses an empty name and the
+// ContinueOnError error handling policy.
+func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
+ f.name = name
+ f.errorHandling = errorHandling
+}
diff --git a/libgo/go/flag/flag_test.go b/libgo/go/flag/flag_test.go
index 63d0a9fc894..f13531669c1 100644
--- a/libgo/go/flag/flag_test.go
+++ b/libgo/go/flag/flag_test.go
@@ -98,6 +98,9 @@ func TestUsage(t *testing.T) {
}
func testParse(f *FlagSet, t *testing.T) {
+ if f.Parsed() {
+ t.Error("f.Parse() = true before Parse")
+ }
boolFlag := f.Bool("bool", false, "bool value")
bool2Flag := f.Bool("bool2", false, "bool2 value")
intFlag := f.Int("int", 0, "int value")
@@ -121,6 +124,9 @@ func testParse(f *FlagSet, t *testing.T) {
if err := f.Parse(args); err != nil {
t.Fatal(err)
}
+ if !f.Parsed() {
+ t.Error("f.Parse() = false after Parse")
+ }
if *boolFlag != true {
t.Error("bool flag should be true, is ", *boolFlag)
}
@@ -174,7 +180,8 @@ func (f *flagVar) Set(value string) bool {
}
func TestUserDefined(t *testing.T) {
- flags := NewFlagSet("test", ContinueOnError)
+ var flags FlagSet
+ flags.Init("test", ContinueOnError)
var v flagVar
flags.Var(&v, "v", "usage")
if err := flags.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err != nil {
diff --git a/libgo/go/fmt/doc.go b/libgo/go/fmt/doc.go
index 35a11e19fa1..c993e57a40a 100644
--- a/libgo/go/fmt/doc.go
+++ b/libgo/go/fmt/doc.go
@@ -122,7 +122,7 @@
An analogous set of functions scans formatted text to yield
values. Scan, Scanf and Scanln read from os.Stdin; Fscan,
- Fscanf and Fscanln read from a specified os.Reader; Sscan,
+ Fscanf and Fscanln read from a specified io.Reader; Sscan,
Sscanf and Sscanln read from an argument string. Scanln,
Fscanln and Sscanln stop scanning at a newline and require that
the items be followed by one; Sscanf, Fscanf and Sscanf require
diff --git a/libgo/go/fmt/fmt_test.go b/libgo/go/fmt/fmt_test.go
index 1142c9f8ad7..030ad6187fa 100644
--- a/libgo/go/fmt/fmt_test.go
+++ b/libgo/go/fmt/fmt_test.go
@@ -5,6 +5,7 @@
package fmt_test
import (
+ "bytes"
. "fmt"
"io"
"math"
@@ -61,7 +62,7 @@ type I int
func (i I) String() string { return Sprintf("<%d>", int(i)) }
type B struct {
- i I
+ I I
j int
}
@@ -83,8 +84,8 @@ func (g G) GoString() string {
}
type S struct {
- f F // a struct field that Formats
- g G // a struct field that GoStrings
+ F F // a struct field that Formats
+ G G // a struct field that GoStrings
}
// A type with a String method with pointer receiver for testing %p
@@ -332,8 +333,8 @@ var fmttests = []struct {
{"%+v", A{1, 2, "a", []int{1, 2}}, `{i:1 j:2 s:a x:[1 2]}`},
// +v on structs with Stringable items
- {"%+v", B{1, 2}, `{i:<1> j:2}`},
- {"%+v", C{1, B{2, 3}}, `{i:1 B:{i:<2> j:3}}`},
+ {"%+v", B{1, 2}, `{I:<1> j:2}`},
+ {"%+v", C{1, B{2, 3}}, `{i:1 B:{I:<2> j:3}}`},
// q on Stringable items
{"%s", I(23), `<23>`},
@@ -348,8 +349,8 @@ var fmttests = []struct {
{"%#v", make(chan int), "(chan int)(0xPTR)"},
{"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"},
{"%#v", 1000000000, "1000000000"},
- {"%#v", map[string]int{"a": 1, "b": 2}, `map[string] int{"a":1, "b":2}`},
- {"%#v", map[string]B{"a": {1, 2}, "b": {3, 4}}, `map[string] fmt_test.B{"a":fmt_test.B{i:1, j:2}, "b":fmt_test.B{i:3, j:4}}`},
+ {"%#v", map[string]int{"a": 1}, `map[string] int{"a":1}`},
+ {"%#v", map[string]B{"a": {1, 2}}, `map[string] fmt_test.B{"a":fmt_test.B{I:1, j:2}}`},
{"%#v", []string{"a", "b"}, `[]string{"a", "b"}`},
// slices with other formats
@@ -384,11 +385,11 @@ var fmttests = []struct {
// Formatter
{"%x", F(1), "<x=F(1)>"},
{"%x", G(2), "2"},
- {"%+v", S{F(4), G(5)}, "{f:<v=F(4)> g:5}"},
+ {"%+v", S{F(4), G(5)}, "{F:<v=F(4)> G:5}"},
// GoStringer
{"%#v", G(6), "GoString(6)"},
- {"%#v", S{F(7), G(8)}, "fmt_test.S{f:<v=F(7)>, g:GoString(8)}"},
+ {"%#v", S{F(7), G(8)}, "fmt_test.S{F:<v=F(7)>, G:GoString(8)}"},
// %T
{"%T", (4 - 3i), "complex128"},
@@ -504,11 +505,38 @@ func TestCountMallocs(t *testing.T) {
runtime.UpdateMemStats()
mallocs = 0 - runtime.MemStats.Mallocs
for i := 0; i < 100; i++ {
+ Sprintf("%s", "hello")
+ }
+ runtime.UpdateMemStats()
+ mallocs += runtime.MemStats.Mallocs
+ Printf("mallocs per Sprintf(\"%%s\"): %d\n", mallocs/100)
+ runtime.UpdateMemStats()
+ mallocs = 0 - runtime.MemStats.Mallocs
+ for i := 0; i < 100; i++ {
Sprintf("%x %x", i, i)
}
runtime.UpdateMemStats()
mallocs += runtime.MemStats.Mallocs
Printf("mallocs per Sprintf(\"%%x %%x\"): %d\n", mallocs/100)
+ buf := new(bytes.Buffer)
+ runtime.UpdateMemStats()
+ mallocs = 0 - runtime.MemStats.Mallocs
+ for i := 0; i < 100; i++ {
+ buf.Reset()
+ Fprintf(buf, "%x %x %x", i, i, i)
+ }
+ runtime.UpdateMemStats()
+ mallocs += runtime.MemStats.Mallocs
+ Printf("mallocs per Fprintf(buf, \"%%x %%x %%x\"): %d\n", mallocs/100)
+ runtime.UpdateMemStats()
+ mallocs = 0 - runtime.MemStats.Mallocs
+ for i := 0; i < 100; i++ {
+ buf.Reset()
+ Fprintf(buf, "%s", "hello")
+ }
+ runtime.UpdateMemStats()
+ mallocs += runtime.MemStats.Mallocs
+ Printf("mallocs per Fprintf(buf, \"%%s\"): %d\n", mallocs/100)
}
type flagPrinter struct{}
diff --git a/libgo/go/fmt/print.go b/libgo/go/fmt/print.go
index 73873490807..7721e724115 100644
--- a/libgo/go/fmt/print.go
+++ b/libgo/go/fmt/print.go
@@ -9,6 +9,7 @@ import (
"io"
"os"
"reflect"
+ "sync"
"unicode"
"utf8"
)
@@ -73,39 +74,45 @@ type pp struct {
n int
panicking bool
buf bytes.Buffer
- runeBuf [utf8.UTFMax]byte
- fmt fmt
+ // value holds the current item, as a reflect.Value, and will be
+ // the zero Value if the item has not been reflected.
+ value reflect.Value
+ runeBuf [utf8.UTFMax]byte
+ fmt fmt
}
// A cache holds a set of reusable objects.
-// The buffered channel holds the currently available objects.
+// The slice is a stack (LIFO).
// If more are needed, the cache creates them by calling new.
type cache struct {
- saved chan interface{}
+ mu sync.Mutex
+ saved []interface{}
new func() interface{}
}
func (c *cache) put(x interface{}) {
- select {
- case c.saved <- x:
- // saved in cache
- default:
- // discard
+ c.mu.Lock()
+ if len(c.saved) < cap(c.saved) {
+ c.saved = append(c.saved, x)
}
+ c.mu.Unlock()
}
func (c *cache) get() interface{} {
- select {
- case x := <-c.saved:
- return x // reused from cache
- default:
+ c.mu.Lock()
+ n := len(c.saved)
+ if n == 0 {
+ c.mu.Unlock()
return c.new()
}
- panic("not reached")
+ x := c.saved[n-1]
+ c.saved = c.saved[0 : n-1]
+ c.mu.Unlock()
+ return x
}
func newCache(f func() interface{}) *cache {
- return &cache{make(chan interface{}, 100), f}
+ return &cache{saved: make([]interface{}, 0, 100), new: f}
}
var ppFree = newCache(func() interface{} { return new(pp) })
@@ -125,6 +132,7 @@ func (p *pp) free() {
return
}
p.buf.Reset()
+ p.value = reflect.Value{}
ppFree.put(p)
}
@@ -186,7 +194,7 @@ func Sprintf(format string, a ...interface{}) string {
}
// Errorf formats according to a format specifier and returns the string
-// converted to an os.ErrorString, which satisfies the os.Error interface.
+// as a value that satisfies os.Error.
func Errorf(format string, a ...interface{}) os.Error {
return os.NewError(Sprintf(format, a...))
}
@@ -258,10 +266,8 @@ func Sprintln(a ...interface{}) string {
// the thing inside the interface, not the interface itself.
func getField(v reflect.Value, i int) reflect.Value {
val := v.Field(i)
- if i := val; i.Kind() == reflect.Interface {
- if inter := i.Interface(); inter != nil {
- return reflect.ValueOf(inter)
- }
+ if val.Kind() == reflect.Interface && !val.IsNil() {
+ val = val.Elem()
}
return val
}
@@ -293,12 +299,17 @@ func (p *pp) badVerb(verb int, val interface{}) {
p.add('!')
p.add(verb)
p.add('(')
- if val == nil {
- p.buf.Write(nilAngleBytes)
- } else {
+ switch {
+ case val != nil:
p.buf.WriteString(reflect.TypeOf(val).String())
p.add('=')
p.printField(val, 'v', false, false, 0)
+ case p.value.IsValid():
+ p.buf.WriteString(p.value.Type().String())
+ p.add('=')
+ p.printValue(p.value, 'v', false, false, 0)
+ default:
+ p.buf.Write(nilAngleBytes)
}
p.add(')')
}
@@ -544,7 +555,7 @@ func (p *pp) fmtPointer(field interface{}, value reflect.Value, verb int, goSynt
}
if goSyntax {
p.add('(')
- p.buf.WriteString(reflect.TypeOf(field).String())
+ p.buf.WriteString(value.Type().String())
p.add(')')
p.add('(')
if u == 0 {
@@ -590,54 +601,69 @@ func (p *pp) catchPanic(val interface{}, verb int) {
}
}
-func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) {
- if field == nil {
- if verb == 'T' || verb == 'v' {
- p.buf.Write(nilAngleBytes)
- } else {
- p.badVerb(verb, field)
- }
- return false
- }
-
- // Special processing considerations.
- // %T (the value's type) and %p (its address) are special; we always do them first.
- switch verb {
- case 'T':
- p.printField(reflect.TypeOf(field).String(), 's', false, false, 0)
- return false
- case 'p':
- p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax)
- return false
- }
+func (p *pp) handleMethods(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString, handled bool) {
// Is it a Formatter?
if formatter, ok := field.(Formatter); ok {
+ handled = true
+ wasString = false
defer p.catchPanic(field, verb)
formatter.Format(p, verb)
- return false // this value is not a string
-
+ return
}
// Must not touch flags before Formatter looks at them.
if plus {
p.fmt.plus = false
}
+
// If we're doing Go syntax and the field knows how to supply it, take care of it now.
if goSyntax {
p.fmt.sharp = false
if stringer, ok := field.(GoStringer); ok {
+ wasString = false
+ handled = true
defer p.catchPanic(field, verb)
// Print the result of GoString unadorned.
p.fmtString(stringer.GoString(), 's', false, field)
- return false // this value is not a string
+ return
}
} else {
// Is it a Stringer?
if stringer, ok := field.(Stringer); ok {
+ wasString = false
+ handled = true
defer p.catchPanic(field, verb)
p.printField(stringer.String(), verb, plus, false, depth)
- return false // this value is not a string
+ return
}
}
+ handled = false
+ return
+}
+
+func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth int) (wasString bool) {
+ if field == nil {
+ if verb == 'T' || verb == 'v' {
+ p.buf.Write(nilAngleBytes)
+ } else {
+ p.badVerb(verb, field)
+ }
+ return false
+ }
+
+ // Special processing considerations.
+ // %T (the value's type) and %p (its address) are special; we always do them first.
+ switch verb {
+ case 'T':
+ p.printField(reflect.TypeOf(field).String(), 's', false, false, 0)
+ return false
+ case 'p':
+ p.fmtPointer(field, reflect.ValueOf(field), verb, goSyntax)
+ return false
+ }
+
+ if wasString, handled := p.handleMethods(field, verb, plus, goSyntax, depth); handled {
+ return wasString
+ }
// Some types can be done without reflection.
switch f := field.(type) {
@@ -698,30 +724,71 @@ func (p *pp) printField(field interface{}, verb int, plus, goSyntax bool, depth
}
// Need to use reflection
- value := reflect.ValueOf(field)
+ return p.printReflectValue(reflect.ValueOf(field), verb, plus, goSyntax, depth)
+}
+// printValue is like printField but starts with a reflect value, not an interface{} value.
+func (p *pp) printValue(value reflect.Value, verb int, plus, goSyntax bool, depth int) (wasString bool) {
+ if !value.IsValid() {
+ if verb == 'T' || verb == 'v' {
+ p.buf.Write(nilAngleBytes)
+ } else {
+ p.badVerb(verb, nil)
+ }
+ return false
+ }
+
+ // Special processing considerations.
+ // %T (the value's type) and %p (its address) are special; we always do them first.
+ switch verb {
+ case 'T':
+ p.printField(value.Type().String(), 's', false, false, 0)
+ return false
+ case 'p':
+ p.fmtPointer(nil, value, verb, goSyntax)
+ return false
+ }
+
+ // Handle values with special methods.
+ // Call always, even when field == nil, because handleMethods clears p.fmt.plus for us.
+ var field interface{}
+ if value.CanInterface() {
+ field = value.Interface()
+ }
+ if wasString, handled := p.handleMethods(field, verb, plus, goSyntax, depth); handled {
+ return wasString
+ }
+
+ return p.printReflectValue(value, verb, plus, goSyntax, depth)
+}
+
+// printReflectValue is the fallback for both printField and printValue.
+// It uses reflect to print the value.
+func (p *pp) printReflectValue(value reflect.Value, verb int, plus, goSyntax bool, depth int) (wasString bool) {
+ oldValue := p.value
+ p.value = value
BigSwitch:
switch f := value; f.Kind() {
case reflect.Bool:
- p.fmtBool(f.Bool(), verb, field)
+ p.fmtBool(f.Bool(), verb, nil)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- p.fmtInt64(f.Int(), verb, field)
+ p.fmtInt64(f.Int(), verb, nil)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
- p.fmtUint64(uint64(f.Uint()), verb, goSyntax, field)
+ p.fmtUint64(uint64(f.Uint()), verb, goSyntax, nil)
case reflect.Float32, reflect.Float64:
if f.Type().Size() == 4 {
- p.fmtFloat32(float32(f.Float()), verb, field)
+ p.fmtFloat32(float32(f.Float()), verb, nil)
} else {
- p.fmtFloat64(float64(f.Float()), verb, field)
+ p.fmtFloat64(float64(f.Float()), verb, nil)
}
case reflect.Complex64, reflect.Complex128:
if f.Type().Size() == 8 {
- p.fmtComplex64(complex64(f.Complex()), verb, field)
+ p.fmtComplex64(complex64(f.Complex()), verb, nil)
} else {
- p.fmtComplex128(complex128(f.Complex()), verb, field)
+ p.fmtComplex128(complex128(f.Complex()), verb, nil)
}
case reflect.String:
- p.fmtString(f.String(), verb, goSyntax, field)
+ p.fmtString(f.String(), verb, goSyntax, nil)
case reflect.Map:
if goSyntax {
p.buf.WriteString(f.Type().String())
@@ -738,9 +805,9 @@ BigSwitch:
p.buf.WriteByte(' ')
}
}
- p.printField(key.Interface(), verb, plus, goSyntax, depth+1)
+ p.printValue(key, verb, plus, goSyntax, depth+1)
p.buf.WriteByte(':')
- p.printField(f.MapIndex(key).Interface(), verb, plus, goSyntax, depth+1)
+ p.printValue(f.MapIndex(key), verb, plus, goSyntax, depth+1)
}
if goSyntax {
p.buf.WriteByte('}')
@@ -749,7 +816,7 @@ BigSwitch:
}
case reflect.Struct:
if goSyntax {
- p.buf.WriteString(reflect.TypeOf(field).String())
+ p.buf.WriteString(value.Type().String())
}
p.add('{')
v := f
@@ -768,20 +835,20 @@ BigSwitch:
p.buf.WriteByte(':')
}
}
- p.printField(getField(v, i).Interface(), verb, plus, goSyntax, depth+1)
+ p.printValue(getField(v, i), verb, plus, goSyntax, depth+1)
}
p.buf.WriteByte('}')
case reflect.Interface:
value := f.Elem()
if !value.IsValid() {
if goSyntax {
- p.buf.WriteString(reflect.TypeOf(field).String())
+ p.buf.WriteString(value.Type().String())
p.buf.Write(nilParenBytes)
} else {
p.buf.Write(nilAngleBytes)
}
} else {
- return p.printField(value.Interface(), verb, plus, goSyntax, depth+1)
+ wasString = p.printValue(value, verb, plus, goSyntax, depth+1)
}
case reflect.Array, reflect.Slice:
// Byte slices are special.
@@ -797,11 +864,12 @@ BigSwitch:
for i := range bytes {
bytes[i] = byte(f.Index(i).Uint())
}
- p.fmtBytes(bytes, verb, goSyntax, depth, field)
- return verb == 's'
+ p.fmtBytes(bytes, verb, goSyntax, depth, nil)
+ wasString = verb == 's'
+ break
}
if goSyntax {
- p.buf.WriteString(reflect.TypeOf(field).String())
+ p.buf.WriteString(value.Type().String())
p.buf.WriteByte('{')
} else {
p.buf.WriteByte('[')
@@ -814,7 +882,7 @@ BigSwitch:
p.buf.WriteByte(' ')
}
}
- p.printField(f.Index(i).Interface(), verb, plus, goSyntax, depth+1)
+ p.printValue(f.Index(i), verb, plus, goSyntax, depth+1)
}
if goSyntax {
p.buf.WriteByte('}')
@@ -829,17 +897,17 @@ BigSwitch:
switch a := f.Elem(); a.Kind() {
case reflect.Array, reflect.Slice:
p.buf.WriteByte('&')
- p.printField(a.Interface(), verb, plus, goSyntax, depth+1)
+ p.printValue(a, verb, plus, goSyntax, depth+1)
break BigSwitch
case reflect.Struct:
p.buf.WriteByte('&')
- p.printField(a.Interface(), verb, plus, goSyntax, depth+1)
+ p.printValue(a, verb, plus, goSyntax, depth+1)
break BigSwitch
}
}
if goSyntax {
p.buf.WriteByte('(')
- p.buf.WriteString(reflect.TypeOf(field).String())
+ p.buf.WriteString(value.Type().String())
p.buf.WriteByte(')')
p.buf.WriteByte('(')
if v == 0 {
@@ -856,11 +924,12 @@ BigSwitch:
}
p.fmt0x64(uint64(v), true)
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
- p.fmtPointer(field, value, verb, goSyntax)
+ p.fmtPointer(nil, value, verb, goSyntax)
default:
p.unknownType(f)
}
- return false
+ p.value = oldValue
+ return wasString
}
// intFromArg gets the fieldnumth element of a. On return, isInt reports whether the argument has type int.
diff --git a/libgo/go/go/ast/filter.go b/libgo/go/go/ast/filter.go
index 26733430d64..d7d4b4b6b6d 100644
--- a/libgo/go/go/ast/filter.go
+++ b/libgo/go/go/ast/filter.go
@@ -9,10 +9,44 @@ import "go/token"
// ----------------------------------------------------------------------------
// Export filtering
-func identListExports(list []*Ident) []*Ident {
+// exportFilter is a special filter function to extract exported nodes.
+func exportFilter(name string) bool {
+ return IsExported(name)
+}
+
+// FileExports trims the AST for a Go source file in place such that
+// only exported nodes remain: all top-level identifiers which are not exported
+// and their associated information (such as type, initial value, or function
+// body) are removed. Non-exported fields and methods of exported types are
+// stripped. The File.Comments list is not changed.
+//
+// FileExports returns true if there are exported declarationa;
+// it returns false otherwise.
+//
+func FileExports(src *File) bool {
+ return FilterFile(src, exportFilter)
+}
+
+// PackageExports trims the AST for a Go package in place such that
+// only exported nodes remain. The pkg.Files list is not changed, so that
+// file names and top-level package comments don't get lost.
+//
+// PackageExports returns true if there are exported declarations;
+// it returns false otherwise.
+//
+func PackageExports(pkg *Package) bool {
+ return FilterPackage(pkg, exportFilter)
+}
+
+// ----------------------------------------------------------------------------
+// General filtering
+
+type Filter func(string) bool
+
+func filterIdentList(list []*Ident, f Filter) []*Ident {
j := 0
for _, x := range list {
- if x.IsExported() {
+ if f(x.Name) {
list[j] = x
j++
}
@@ -38,33 +72,30 @@ func fieldName(x Expr) *Ident {
return nil
}
-func fieldListExports(fields *FieldList) (removedFields bool) {
+func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
if fields == nil {
- return
+ return false
}
list := fields.List
j := 0
for _, f := range list {
- exported := false
+ keepField := false
if len(f.Names) == 0 {
// anonymous field
- // (Note that a non-exported anonymous field
- // may still refer to a type with exported
- // fields, so this is not absolutely correct.
- // However, this cannot be done w/o complete
- // type information.)
name := fieldName(f.Type)
- exported = name != nil && name.IsExported()
+ keepField = name != nil && filter(name.Name)
} else {
n := len(f.Names)
- f.Names = identListExports(f.Names)
+ f.Names = filterIdentList(f.Names, filter)
if len(f.Names) < n {
removedFields = true
}
- exported = len(f.Names) > 0
+ keepField = len(f.Names) > 0
}
- if exported {
- typeExports(f.Type)
+ if keepField {
+ if filter == exportFilter {
+ filterType(f.Type, filter)
+ }
list[j] = f
j++
}
@@ -76,185 +107,75 @@ func fieldListExports(fields *FieldList) (removedFields bool) {
return
}
-func paramListExports(fields *FieldList) {
+func filterParamList(fields *FieldList, filter Filter) bool {
if fields == nil {
- return
+ return false
}
+ var b bool
for _, f := range fields.List {
- typeExports(f.Type)
+ if filterType(f.Type, filter) {
+ b = true
+ }
}
+ return b
}
-func typeExports(typ Expr) {
+func filterType(typ Expr, f Filter) bool {
switch t := typ.(type) {
+ case *Ident:
+ return f(t.Name)
+ case *ParenExpr:
+ return filterType(t.X, f)
case *ArrayType:
- typeExports(t.Elt)
+ return filterType(t.Elt, f)
case *StructType:
- if fieldListExports(t.Fields) {
+ if filterFieldList(t.Fields, f) {
t.Incomplete = true
}
+ return len(t.Fields.List) > 0
case *FuncType:
- paramListExports(t.Params)
- paramListExports(t.Results)
+ b1 := filterParamList(t.Params, f)
+ b2 := filterParamList(t.Results, f)
+ return b1 || b2
case *InterfaceType:
- if fieldListExports(t.Methods) {
+ if filterFieldList(t.Methods, f) {
t.Incomplete = true
}
+ return len(t.Methods.List) > 0
case *MapType:
- typeExports(t.Key)
- typeExports(t.Value)
+ b1 := filterType(t.Key, f)
+ b2 := filterType(t.Value, f)
+ return b1 || b2
case *ChanType:
- typeExports(t.Value)
- }
-}
-
-func specExports(spec Spec) bool {
- switch s := spec.(type) {
- case *ValueSpec:
- s.Names = identListExports(s.Names)
- if len(s.Names) > 0 {
- typeExports(s.Type)
- return true
- }
- case *TypeSpec:
- if s.Name.IsExported() {
- typeExports(s.Type)
- return true
- }
+ return filterType(t.Value, f)
}
return false
}
-func specListExports(list []Spec) []Spec {
- j := 0
- for _, s := range list {
- if specExports(s) {
- list[j] = s
- j++
- }
- }
- return list[0:j]
-}
-
-func declExports(decl Decl) bool {
- switch d := decl.(type) {
- case *GenDecl:
- d.Specs = specListExports(d.Specs)
- return len(d.Specs) > 0
- case *FuncDecl:
- d.Body = nil // strip body
- return d.Name.IsExported()
- }
- return false
-}
-
-// FileExports trims the AST for a Go source file in place such that only
-// exported nodes remain: all top-level identifiers which are not exported
-// and their associated information (such as type, initial value, or function
-// body) are removed. Non-exported fields and methods of exported types are
-// stripped, and the function bodies of exported functions are set to nil.
-// The File.comments list is not changed.
-//
-// FileExports returns true if there is an exported declaration; it returns
-// false otherwise.
-//
-func FileExports(src *File) bool {
- j := 0
- for _, d := range src.Decls {
- if declExports(d) {
- src.Decls[j] = d
- j++
- }
- }
- src.Decls = src.Decls[0:j]
- return j > 0
-}
-
-// PackageExports trims the AST for a Go package in place such that only
-// exported nodes remain. The pkg.Files list is not changed, so that file
-// names and top-level package comments don't get lost.
-//
-// PackageExports returns true if there is an exported declaration; it
-// returns false otherwise.
-//
-func PackageExports(pkg *Package) bool {
- hasExports := false
- for _, f := range pkg.Files {
- if FileExports(f) {
- hasExports = true
- }
- }
- return hasExports
-}
-
-// ----------------------------------------------------------------------------
-// General filtering
-
-type Filter func(string) bool
-
-func filterIdentList(list []*Ident, f Filter) []*Ident {
- j := 0
- for _, x := range list {
- if f(x.Name) {
- list[j] = x
- j++
- }
- }
- return list[0:j]
-}
-
-func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
- if fields == nil {
- return false
- }
- list := fields.List
- j := 0
- for _, f := range list {
- keepField := false
- if len(f.Names) == 0 {
- // anonymous field
- name := fieldName(f.Type)
- keepField = name != nil && filter(name.Name)
- } else {
- n := len(f.Names)
- f.Names = filterIdentList(f.Names, filter)
- if len(f.Names) < n {
- removedFields = true
- }
- keepField = len(f.Names) > 0
- }
- if keepField {
- list[j] = f
- j++
- }
- }
- if j < len(list) {
- removedFields = true
- }
- fields.List = list[0:j]
- return
-}
-
func filterSpec(spec Spec, f Filter) bool {
switch s := spec.(type) {
case *ValueSpec:
s.Names = filterIdentList(s.Names, f)
- return len(s.Names) > 0
+ if len(s.Names) > 0 {
+ if f == exportFilter {
+ filterType(s.Type, f)
+ }
+ return true
+ }
case *TypeSpec:
if f(s.Name.Name) {
+ if f == exportFilter {
+ filterType(s.Type, f)
+ }
return true
}
- switch t := s.Type.(type) {
- case *StructType:
- if filterFieldList(t.Fields, f) {
- t.Incomplete = true
- }
- return len(t.Fields.List) > 0
- case *InterfaceType:
- if filterFieldList(t.Methods, f) {
- t.Incomplete = true
- }
- return len(t.Methods.List) > 0
+ if f != exportFilter {
+ // For general filtering (not just exports),
+ // filter type even if name is not filtered
+ // out.
+ // If the type contains filtered elements,
+ // keep the declaration.
+ return filterType(s.Type, f)
}
}
return false
@@ -293,8 +214,8 @@ func FilterDecl(decl Decl, f Filter) bool {
// names from top-level declarations (including struct field and
// interface method names, but not from parameter lists) that don't
// pass through the filter f. If the declaration is empty afterwards,
-// the declaration is removed from the AST.
-// The File.comments list is not changed.
+// the declaration is removed from the AST. The File.Comments list
+// is not changed.
//
// FilterFile returns true if there are any top-level declarations
// left after filtering; it returns false otherwise.
@@ -311,13 +232,13 @@ func FilterFile(src *File, f Filter) bool {
return j > 0
}
-// FilterPackage trims the AST for a Go package in place by removing all
-// names from top-level declarations (including struct field and
+// FilterPackage trims the AST for a Go package in place by removing
+// all names from top-level declarations (including struct field and
// interface method names, but not from parameter lists) that don't
// pass through the filter f. If the declaration is empty afterwards,
-// the declaration is removed from the AST.
-// The pkg.Files list is not changed, so that file names and top-level
-// package comments don't get lost.
+// the declaration is removed from the AST. The pkg.Files list is not
+// changed, so that file names and top-level package comments don't get
+// lost.
//
// FilterPackage returns true if there are any top-level declarations
// left after filtering; it returns false otherwise.
@@ -344,6 +265,8 @@ const (
// If set, comments that are not associated with a specific
// AST node (as Doc or Comment) are excluded.
FilterUnassociatedComments
+ // If set, duplicate import declarations are excluded.
+ FilterImportDuplicates
)
// separator is an empty //-style comment that is interspersed between
@@ -459,6 +382,31 @@ func MergePackageFiles(pkg *Package, mode MergeMode) *File {
}
}
+ // Collect import specs from all package files.
+ var imports []*ImportSpec
+ if mode&FilterImportDuplicates != 0 {
+ seen := make(map[string]bool)
+ for _, f := range pkg.Files {
+ for _, imp := range f.Imports {
+ if path := imp.Path.Value; !seen[path] {
+ // TODO: consider handling cases where:
+ // - 2 imports exist with the same import path but
+ // have different local names (one should probably
+ // keep both of them)
+ // - 2 imports exist but only one has a comment
+ // - 2 imports exist and they both have (possibly
+ // different) comments
+ imports = append(imports, imp)
+ seen[path] = true
+ }
+ }
+ }
+ } else {
+ for _, f := range pkg.Files {
+ imports = append(imports, f.Imports...)
+ }
+ }
+
// Collect comments from all package files.
var comments []*CommentGroup
if mode&FilterUnassociatedComments == 0 {
@@ -469,7 +417,6 @@ func MergePackageFiles(pkg *Package, mode MergeMode) *File {
}
}
- // TODO(gri) need to compute pkgScope and unresolved identifiers!
- // TODO(gri) need to compute imports!
- return &File{doc, pos, NewIdent(pkg.Name), decls, nil, nil, nil, comments}
+ // TODO(gri) need to compute unresolved identifiers!
+ return &File{doc, pos, NewIdent(pkg.Name), decls, pkg.Scope, imports, nil, comments}
}
diff --git a/libgo/go/go/ast/print_test.go b/libgo/go/go/ast/print_test.go
index f4e8f7a78f7..a4bc3bb9dcd 100644
--- a/libgo/go/go/ast/print_test.go
+++ b/libgo/go/go/ast/print_test.go
@@ -41,10 +41,10 @@ var tests = []struct {
4 }`},
// structs
- {struct{ x, y int }{42, 991},
- `0 struct { x int; y int } {
- 1 . x: 42
- 2 . y: 991
+ {struct{ X, Y int }{42, 991},
+ `0 struct { X int; Y int } {
+ 1 . X: 42
+ 2 . Y: 991
3 }`},
}
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index e59d87672ca..68a4180c906 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -7,44 +7,84 @@ package build
import (
"exec"
"path/filepath"
+ "reflect"
+ "runtime"
+ "sort"
"testing"
)
-var buildPkgs = []string{
- "go/build/pkgtest",
- "go/build/cmdtest",
- "go/build/cgotest",
+func sortstr(x []string) []string {
+ sort.Strings(x)
+ return x
+}
+
+var buildPkgs = []struct {
+ dir string
+ info *DirInfo
+}{
+ {
+ "go/build/pkgtest",
+ &DirInfo{
+ GoFiles: []string{"pkgtest.go"},
+ SFiles: []string{"sqrt_" + runtime.GOARCH + ".s"},
+ Package: "pkgtest",
+ Imports: []string{"os"},
+ TestImports: []string{"fmt", "pkgtest"},
+ TestGoFiles: sortstr([]string{"sqrt_test.go", "sqrt_" + runtime.GOARCH + "_test.go"}),
+ XTestGoFiles: []string{"xsqrt_test.go"},
+ },
+ },
+ {
+ "go/build/cmdtest",
+ &DirInfo{
+ GoFiles: []string{"main.go"},
+ Package: "main",
+ Imports: []string{"go/build/pkgtest"},
+ },
+ },
+ {
+ "go/build/cgotest",
+ &DirInfo{
+ CgoFiles: []string{"cgotest.go"},
+ CFiles: []string{"cgotest.c"},
+ Imports: []string{"C", "unsafe"},
+ Package: "cgotest",
+ },
+ },
}
const cmdtestOutput = "3"
func TestBuild(t *testing.T) {
- for _, pkg := range buildPkgs {
+ for _, tt := range buildPkgs {
tree := Path[0] // Goroot
- dir := filepath.Join(tree.SrcDir(), pkg)
-
- info, err := ScanDir(dir, true)
+ dir := filepath.Join(tree.SrcDir(), tt.dir)
+ info, err := ScanDir(dir)
if err != nil {
- t.Error("ScanDir:", err)
+ t.Errorf("ScanDir(%#q): %v", tt.dir, err)
+ continue
+ }
+ if !reflect.DeepEqual(info, tt.info) {
+ t.Errorf("ScanDir(%#q) = %#v, want %#v\n", tt.dir, info, tt.info)
continue
}
- s, err := Build(tree, pkg, info)
+ s, err := Build(tree, tt.dir, info)
if err != nil {
- t.Error("Build:", err)
+ t.Errorf("Build(%#q): %v", tt.dir, err)
continue
}
if err := s.Run(); err != nil {
- t.Error("Run:", err)
+ t.Errorf("Run(%#q): %v", tt.dir, err)
continue
}
- if pkg == "go/build/cmdtest" {
+ if tt.dir == "go/build/cmdtest" {
bin := s.Output[0]
b, err := exec.Command(bin).CombinedOutput()
if err != nil {
- t.Errorf("exec: %s: %v", bin, err)
+ t.Errorf("exec %s: %v", bin, err)
continue
}
if string(b) != cmdtestOutput {
@@ -52,6 +92,7 @@ func TestBuild(t *testing.T) {
}
}
+ // Deferred because cmdtest depends on pkgtest.
defer func(s *Script) {
if err := s.Nuke(); err != nil {
t.Errorf("nuking: %v", err)
diff --git a/libgo/go/go/build/dir.go b/libgo/go/go/build/dir.go
index e0000b53446..3ee10ab3484 100644
--- a/libgo/go/go/build/dir.go
+++ b/libgo/go/go/build/dir.go
@@ -5,168 +5,559 @@
package build
import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/doc"
"go/parser"
"go/token"
+ "io/ioutil"
"log"
"os"
+ "path"
"path/filepath"
+ "runtime"
+ "sort"
"strconv"
"strings"
- "runtime"
+ "unicode"
)
+// A Context specifies the supporting context for a build.
+type Context struct {
+ GOARCH string // target architecture
+ GOOS string // target operating system
+ // TODO(rsc,adg): GOPATH
+
+ // By default, ScanDir uses the operating system's
+ // file system calls to read directories and files.
+ // Callers can override those calls to provide other
+ // ways to read data by setting ReadDir and ReadFile.
+ // ScanDir does not make any assumptions about the
+ // format of the strings dir and file: they can be
+ // slash-separated, backslash-separated, even URLs.
+
+ // ReadDir returns a slice of *os.FileInfo, sorted by Name,
+ // describing the content of the named directory.
+ // The dir argument is the argument to ScanDir.
+ // If ReadDir is nil, ScanDir uses io.ReadDir.
+ ReadDir func(dir string) (fi []*os.FileInfo, err os.Error)
+
+ // ReadFile returns the content of the file named file
+ // in the directory named dir. The dir argument is the
+ // argument to ScanDir, and the file argument is the
+ // Name field from an *os.FileInfo returned by ReadDir.
+ // The returned path is the full name of the file, to be
+ // used in error messages.
+ //
+ // If ReadFile is nil, ScanDir uses filepath.Join(dir, file)
+ // as the path and ioutil.ReadFile to read the data.
+ ReadFile func(dir, file string) (path string, content []byte, err os.Error)
+}
+
+func (ctxt *Context) readDir(dir string) ([]*os.FileInfo, os.Error) {
+ if f := ctxt.ReadDir; f != nil {
+ return f(dir)
+ }
+ return ioutil.ReadDir(dir)
+}
+
+func (ctxt *Context) readFile(dir, file string) (string, []byte, os.Error) {
+ if f := ctxt.ReadFile; f != nil {
+ return f(dir, file)
+ }
+ p := filepath.Join(dir, file)
+ content, err := ioutil.ReadFile(p)
+ return p, content, err
+}
+
+// The DefaultContext is the default Context for builds.
+// It uses the GOARCH and GOOS environment variables
+// if set, or else the compiled code's GOARCH and GOOS.
+var DefaultContext = Context{
+ GOARCH: envOr("GOARCH", runtime.GOARCH),
+ GOOS: envOr("GOOS", runtime.GOOS),
+}
+
+func envOr(name, def string) string {
+ s := os.Getenv(name)
+ if s == "" {
+ return def
+ }
+ return s
+}
+
type DirInfo struct {
+ Package string // Name of package in dir
+ PackageComment *ast.CommentGroup // Package comments from GoFiles
+ ImportPath string // Import path of package in dir
+ Imports []string // All packages imported by GoFiles
+
+ // Source files
GoFiles []string // .go files in dir (excluding CgoFiles)
- CgoFiles []string // .go files that import "C"
CFiles []string // .c files in dir
SFiles []string // .s files in dir
- Imports []string // All packages imported by goFiles
- PkgName string // Name of package in dir
+ CgoFiles []string // .go files that import "C"
+
+ // Cgo directives
+ CgoPkgConfig []string // Cgo pkg-config directives
+ CgoCFLAGS []string // Cgo CFLAGS directives
+ CgoLDFLAGS []string // Cgo LDFLAGS directives
+
+ // Test information
+ TestGoFiles []string // _test.go files in package
+ XTestGoFiles []string // _test.go files outside package
+ TestImports []string // All packages imported by (X)TestGoFiles
}
func (d *DirInfo) IsCommand() bool {
- return d.PkgName == "main"
+ // TODO(rsc): This is at least a little bogus.
+ return d.Package == "main"
+}
+
+// ScanDir calls DefaultContext.ScanDir.
+func ScanDir(dir string) (info *DirInfo, err os.Error) {
+ return DefaultContext.ScanDir(dir)
}
// ScanDir returns a structure with details about the Go content found
// in the given directory. The file lists exclude:
//
-// - files in package main (unless allowMain is true)
+// - files in package main (unless no other package is found)
// - files in package documentation
// - files ending in _test.go
-// - files starting with _ or .
+// - files starting with _ or .
//
-// Only files that satisfy the goodOSArch function are included.
-func ScanDir(dir string, allowMain bool) (info *DirInfo, err os.Error) {
- f, err := os.Open(dir)
- if err != nil {
- return nil, err
- }
- dirs, err := f.Readdir(-1)
- f.Close()
+func (ctxt *Context) ScanDir(dir string) (info *DirInfo, err os.Error) {
+ dirs, err := ctxt.readDir(dir)
if err != nil {
return nil, err
}
var di DirInfo
imported := make(map[string]bool)
+ testImported := make(map[string]bool)
fset := token.NewFileSet()
- for i := range dirs {
- d := &dirs[i]
+ for _, d := range dirs {
+ if !d.IsRegular() {
+ continue
+ }
if strings.HasPrefix(d.Name, "_") ||
strings.HasPrefix(d.Name, ".") {
continue
}
- if !goodOSArch(d.Name) {
+ if !ctxt.goodOSArchFile(d.Name) {
continue
}
- switch filepath.Ext(d.Name) {
- case ".go":
- if strings.HasSuffix(d.Name, "_test.go") {
- continue
- }
+ ext := path.Ext(d.Name)
+ switch ext {
+ case ".go", ".c", ".s":
+ // tentatively okay
+ default:
+ // skip
+ continue
+ }
+
+ // Look for +build comments to accept or reject the file.
+ filename, data, err := ctxt.readFile(dir, d.Name)
+ if err != nil {
+ return nil, err
+ }
+ if !ctxt.shouldBuild(data) {
+ continue
+ }
+
+ // Going to save the file. For non-Go files, can stop here.
+ switch ext {
case ".c":
di.CFiles = append(di.CFiles, d.Name)
continue
case ".s":
di.SFiles = append(di.SFiles, d.Name)
continue
- default:
- continue
}
- filename := filepath.Join(dir, d.Name)
- pf, err := parser.ParseFile(fset, filename, nil, parser.ImportsOnly)
+ pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
if err != nil {
return nil, err
}
- s := string(pf.Name.Name)
- if s == "main" && !allowMain {
+
+ pkg := string(pf.Name.Name)
+ if pkg == "main" && di.Package != "" && di.Package != "main" {
continue
}
- if s == "documentation" {
+ if pkg == "documentation" {
continue
}
- if di.PkgName == "" {
- di.PkgName = s
- } else if di.PkgName != s {
- // Only if all files in the directory are in package main
- // do we return PkgName=="main".
- // A mix of main and another package reverts
- // to the original (allowMain=false) behaviour.
- if s == "main" || di.PkgName == "main" {
- return ScanDir(dir, false)
+
+ isTest := strings.HasSuffix(d.Name, "_test.go")
+ if isTest && strings.HasSuffix(pkg, "_test") {
+ pkg = pkg[:len(pkg)-len("_test")]
+ }
+
+ if pkg != di.Package && di.Package == "main" {
+ // Found non-main package but was recording
+ // information about package main. Reset.
+ di = DirInfo{}
+ }
+ if di.Package == "" {
+ di.Package = pkg
+ } else if pkg != di.Package {
+ return nil, fmt.Errorf("%s: found packages %s and %s", dir, pkg, di.Package)
+ }
+ if pf.Doc != nil {
+ if di.PackageComment != nil {
+ di.PackageComment.List = append(di.PackageComment.List, pf.Doc.List...)
+ } else {
+ di.PackageComment = pf.Doc
}
- return nil, os.NewError("multiple package names in " + dir)
}
+
+ // Record imports and information about cgo.
isCgo := false
- for _, spec := range pf.Imports {
- quoted := string(spec.Path.Value)
- path, err := strconv.Unquote(quoted)
- if err != nil {
- log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
+ for _, decl := range pf.Decls {
+ d, ok := decl.(*ast.GenDecl)
+ if !ok {
+ continue
}
- imported[path] = true
- if path == "C" {
- isCgo = true
+ for _, dspec := range d.Specs {
+ spec, ok := dspec.(*ast.ImportSpec)
+ if !ok {
+ continue
+ }
+ quoted := string(spec.Path.Value)
+ path, err := strconv.Unquote(quoted)
+ if err != nil {
+ log.Panicf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
+ }
+ if isTest {
+ testImported[path] = true
+ } else {
+ imported[path] = true
+ }
+ if path == "C" {
+ if isTest {
+ return nil, fmt.Errorf("%s: use of cgo in test not supported", filename)
+ }
+ cg := spec.Doc
+ if cg == nil && len(d.Specs) == 1 {
+ cg = d.Doc
+ }
+ if cg != nil {
+ if err := ctxt.saveCgo(filename, &di, cg); err != nil {
+ return nil, err
+ }
+ }
+ isCgo = true
+ }
}
}
if isCgo {
di.CgoFiles = append(di.CgoFiles, d.Name)
+ } else if isTest {
+ if pkg == string(pf.Name.Name) {
+ di.TestGoFiles = append(di.TestGoFiles, d.Name)
+ } else {
+ di.XTestGoFiles = append(di.XTestGoFiles, d.Name)
+ }
} else {
di.GoFiles = append(di.GoFiles, d.Name)
}
}
+ if di.Package == "" {
+ return nil, fmt.Errorf("%s: no Go source files", dir)
+ }
di.Imports = make([]string, len(imported))
i := 0
for p := range imported {
di.Imports[i] = p
i++
}
+ di.TestImports = make([]string, len(testImported))
+ i = 0
+ for p := range testImported {
+ di.TestImports[i] = p
+ i++
+ }
+ // File name lists are sorted because ReadDir sorts.
+ sort.Strings(di.Imports)
+ sort.Strings(di.TestImports)
return &di, nil
}
-// goodOSArch returns false if the filename contains a $GOOS or $GOARCH
+var slashslash = []byte("//")
+var plusBuild = []byte("+build")
+
+// shouldBuild reports whether it is okay to use this file,
+// The rule is that in the file's leading run of // comments
+// and blank lines, which must be followed by a blank line
+// (to avoid including a Go package clause doc comment),
+// lines beginning with '// +build' are taken as build directives.
+//
+// The file is accepted only if each such line lists something
+// matching the file. For example:
+//
+// // +build windows linux
+//
+// marks the file as applicable only on Windows and Linux.
+//
+func (ctxt *Context) shouldBuild(content []byte) bool {
+ // Pass 1. Identify leading run of // comments and blank lines,
+ // which must be followed by a blank line.
+ end := 0
+ p := content
+ for len(p) > 0 {
+ line := p
+ if i := bytes.IndexByte(line, '\n'); i >= 0 {
+ line, p = line[:i], p[i+1:]
+ } else {
+ p = p[len(p):]
+ }
+ line = bytes.TrimSpace(line)
+ if len(line) == 0 { // Blank line
+ end = cap(content) - cap(line) // &line[0] - &content[0]
+ continue
+ }
+ if !bytes.HasPrefix(line, slashslash) { // Not comment line
+ break
+ }
+ }
+ content = content[:end]
+
+ // Pass 2. Process each line in the run.
+ p = content
+ for len(p) > 0 {
+ line := p
+ if i := bytes.IndexByte(line, '\n'); i >= 0 {
+ line, p = line[:i], p[i+1:]
+ } else {
+ p = p[len(p):]
+ }
+ line = bytes.TrimSpace(line)
+ if bytes.HasPrefix(line, slashslash) {
+ line = bytes.TrimSpace(line[len(slashslash):])
+ if len(line) > 0 && line[0] == '+' {
+ // Looks like a comment +line.
+ f := strings.Fields(string(line))
+ if f[0] == "+build" {
+ ok := false
+ for _, tok := range f[1:] {
+ if ctxt.matchOSArch(tok) {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ return false // this one doesn't match
+ }
+ }
+ }
+ }
+ }
+ return true // everything matches
+}
+
+// saveCgo saves the information from the #cgo lines in the import "C" comment.
+// These lines set CFLAGS and LDFLAGS and pkg-config directives that affect
+// the way cgo's C code is built.
+//
+// TODO(rsc): This duplicates code in cgo.
+// Once the dust settles, remove this code from cgo.
+func (ctxt *Context) saveCgo(filename string, di *DirInfo, cg *ast.CommentGroup) os.Error {
+ text := doc.CommentText(cg)
+ for _, line := range strings.Split(text, "\n") {
+ orig := line
+
+ // Line is
+ // #cgo [GOOS/GOARCH...] LDFLAGS: stuff
+ //
+ line = strings.TrimSpace(line)
+ if len(line) < 5 || line[:4] != "#cgo" || (line[4] != ' ' && line[4] != '\t') {
+ continue
+ }
+
+ // Split at colon.
+ line = strings.TrimSpace(line[4:])
+ i := strings.Index(line, ":")
+ if i < 0 {
+ return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+ }
+ line, argstr := line[:i], line[i+1:]
+
+ // Parse GOOS/GOARCH stuff.
+ f := strings.Fields(line)
+ if len(f) < 1 {
+ return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+ }
+
+ cond, verb := f[:len(f)-1], f[len(f)-1]
+ if len(cond) > 0 {
+ ok := false
+ for _, c := range cond {
+ if ctxt.matchOSArch(c) {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ continue
+ }
+ }
+
+ args, err := splitQuoted(argstr)
+ if err != nil {
+ return fmt.Errorf("%s: invalid #cgo line: %s", filename, orig)
+ }
+ for _, arg := range args {
+ if !safeName(arg) {
+ return fmt.Errorf("%s: malformed #cgo argument: %s", filename, arg)
+ }
+ }
+
+ switch verb {
+ case "CFLAGS":
+ di.CgoCFLAGS = append(di.CgoCFLAGS, args...)
+ case "LDFLAGS":
+ di.CgoLDFLAGS = append(di.CgoLDFLAGS, args...)
+ case "pkg-config":
+ di.CgoPkgConfig = append(di.CgoPkgConfig, args...)
+ default:
+ return fmt.Errorf("%s: invalid #cgo verb: %s", filename, orig)
+ }
+ }
+ return nil
+}
+
+var safeBytes = []byte("+-.,/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz")
+
+func safeName(s string) bool {
+ if s == "" {
+ return false
+ }
+ for i := 0; i < len(s); i++ {
+ if c := s[i]; c < 0x80 && bytes.IndexByte(safeBytes, c) < 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// splitQuoted splits the string s around each instance of one or more consecutive
+// white space characters while taking into account quotes and escaping, and
+// returns an array of substrings of s or an empty list if s contains only white space.
+// Single quotes and double quotes are recognized to prevent splitting within the
+// quoted region, and are removed from the resulting substrings. If a quote in s
+// isn't closed err will be set and r will have the unclosed argument as the
+// last element. The backslash is used for escaping.
+//
+// For example, the following string:
+//
+// a b:"c d" 'e''f' "g\""
+//
+// Would be parsed as:
+//
+// []string{"a", "b:c d", "ef", `g"`}
+//
+func splitQuoted(s string) (r []string, err os.Error) {
+ var args []string
+ arg := make([]int, len(s))
+ escaped := false
+ quoted := false
+ quote := 0
+ i := 0
+ for _, rune := range s {
+ switch {
+ case escaped:
+ escaped = false
+ case rune == '\\':
+ escaped = true
+ continue
+ case quote != 0:
+ if rune == quote {
+ quote = 0
+ continue
+ }
+ case rune == '"' || rune == '\'':
+ quoted = true
+ quote = rune
+ continue
+ case unicode.IsSpace(rune):
+ if quoted || i > 0 {
+ quoted = false
+ args = append(args, string(arg[:i]))
+ i = 0
+ }
+ continue
+ }
+ arg[i] = rune
+ i++
+ }
+ if quoted || i > 0 {
+ args = append(args, string(arg[:i]))
+ }
+ if quote != 0 {
+ err = os.NewError("unclosed quote")
+ } else if escaped {
+ err = os.NewError("unfinished escaping")
+ }
+ return args, err
+}
+
+// matchOSArch returns true if the name is one of:
+//
+// $GOOS
+// $GOARCH
+// $GOOS/$GOARCH
+//
+func (ctxt *Context) matchOSArch(name string) bool {
+ if name == ctxt.GOOS || name == ctxt.GOARCH {
+ return true
+ }
+ i := strings.Index(name, "/")
+ return i >= 0 && name[:i] == ctxt.GOOS && name[i+1:] == ctxt.GOARCH
+}
+
+// goodOSArchFile returns false if the name contains a $GOOS or $GOARCH
// suffix which does not match the current system.
-// The recognized filename formats are:
+// The recognized name formats are:
//
// name_$(GOOS).*
// name_$(GOARCH).*
// name_$(GOOS)_$(GOARCH).*
+// name_$(GOOS)_test.*
+// name_$(GOARCH)_test.*
+// name_$(GOOS)_$(GOARCH)_test.*
//
-func goodOSArch(filename string) bool {
- if dot := strings.Index(filename, "."); dot != -1 {
- filename = filename[:dot]
+func (ctxt *Context) goodOSArchFile(name string) bool {
+ if dot := strings.Index(name, "."); dot != -1 {
+ name = name[:dot]
+ }
+ l := strings.Split(name, "_")
+ if n := len(l); n > 0 && l[n-1] == "test" {
+ l = l[:n-1]
}
- l := strings.Split(filename, "_")
n := len(l)
- if n == 0 {
- return true
+ if n >= 2 && knownOS[l[n-2]] && knownArch[l[n-1]] {
+ return l[n-2] == ctxt.GOOS && l[n-1] == ctxt.GOARCH
}
- if good, known := goodOS[l[n-1]]; known {
- return good
+ if n >= 1 && knownOS[l[n-1]] {
+ return l[n-1] == ctxt.GOOS
}
- if good, known := goodArch[l[n-1]]; known {
- if !good || n < 2 {
- return false
- }
- good, known = goodOS[l[n-2]]
- return good || !known
+ if n >= 1 && knownArch[l[n-1]] {
+ return l[n-1] == ctxt.GOARCH
}
return true
}
-var goodOS = make(map[string]bool)
-var goodArch = make(map[string]bool)
+var knownOS = make(map[string]bool)
+var knownArch = make(map[string]bool)
func init() {
- goodOS = make(map[string]bool)
- goodArch = make(map[string]bool)
for _, v := range strings.Fields(goosList) {
- goodOS[v] = v == runtime.GOOS
+ knownOS[v] = true
}
for _, v := range strings.Fields(goarchList) {
- goodArch[v] = v == runtime.GOARCH
+ knownArch[v] = true
}
}
diff --git a/libgo/go/go/build/pkgtest/pkgtest.go b/libgo/go/go/build/pkgtest/pkgtest.go
index 9322f5ebd71..03ebb9893aa 100644
--- a/libgo/go/go/build/pkgtest/pkgtest.go
+++ b/libgo/go/go/build/pkgtest/pkgtest.go
@@ -4,6 +4,10 @@
package pkgtest
-func Foo() {}
+import "os"
+
+func Foo() os.Error {
+ return nil
+}
func Sqrt(x float64) float64
diff --git a/libgo/go/go/build/pkgtest/sqrt_386_test.go b/libgo/go/go/build/pkgtest/sqrt_386_test.go
new file mode 100644
index 00000000000..26b483fa0ba
--- /dev/null
+++ b/libgo/go/go/build/pkgtest/sqrt_386_test.go
@@ -0,0 +1 @@
+package pkgtest
diff --git a/libgo/go/go/build/pkgtest/sqrt_amd64_test.go b/libgo/go/go/build/pkgtest/sqrt_amd64_test.go
new file mode 100644
index 00000000000..26b483fa0ba
--- /dev/null
+++ b/libgo/go/go/build/pkgtest/sqrt_amd64_test.go
@@ -0,0 +1 @@
+package pkgtest
diff --git a/libgo/go/go/build/pkgtest/sqrt_arm_test.go b/libgo/go/go/build/pkgtest/sqrt_arm_test.go
new file mode 100644
index 00000000000..26b483fa0ba
--- /dev/null
+++ b/libgo/go/go/build/pkgtest/sqrt_arm_test.go
@@ -0,0 +1 @@
+package pkgtest
diff --git a/libgo/go/go/build/pkgtest/sqrt_test.go b/libgo/go/go/build/pkgtest/sqrt_test.go
new file mode 100644
index 00000000000..95fb625525c
--- /dev/null
+++ b/libgo/go/go/build/pkgtest/sqrt_test.go
@@ -0,0 +1,5 @@
+package pkgtest
+
+import "fmt"
+
+var _ = fmt.Printf
diff --git a/libgo/go/go/build/pkgtest/xsqrt_test.go b/libgo/go/go/build/pkgtest/xsqrt_test.go
new file mode 100644
index 00000000000..77e903d96ca
--- /dev/null
+++ b/libgo/go/go/build/pkgtest/xsqrt_test.go
@@ -0,0 +1,5 @@
+package pkgtest_test
+
+import "pkgtest"
+
+var _ = pkgtest.Foo
diff --git a/libgo/go/go/build/syslist_test.go b/libgo/go/go/build/syslist_test.go
index eb0e5dcb6b2..d27630d758d 100644
--- a/libgo/go/go/build/syslist_test.go
+++ b/libgo/go/go/build/syslist_test.go
@@ -55,8 +55,8 @@ var tests = []GoodFileTest{
func TestGoodOSArch(t *testing.T) {
for _, test := range tests {
- if goodOSArch(test.name) != test.result {
- t.Fatalf("goodOSArch(%q) != %v", test.name, test.result)
+ if DefaultContext.goodOSArchFile(test.name) != test.result {
+ t.Fatalf("goodOSArchFile(%q) != %v", test.name, test.result)
}
}
}
diff --git a/libgo/go/go/doc/example.go b/libgo/go/go/doc/example.go
new file mode 100644
index 00000000000..7fdf0bcff66
--- /dev/null
+++ b/libgo/go/go/doc/example.go
@@ -0,0 +1,56 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Extract example functions from package ASTs.
+
+package doc
+
+import (
+ "go/ast"
+ "strings"
+ "unicode"
+ "utf8"
+)
+
+type Example struct {
+ Name string // name of the item being demonstrated
+ Body *ast.BlockStmt // code
+ Output string // expected output
+}
+
+func Examples(pkg *ast.Package) []*Example {
+ var examples []*Example
+ for _, src := range pkg.Files {
+ for _, decl := range src.Decls {
+ f, ok := decl.(*ast.FuncDecl)
+ if !ok {
+ continue
+ }
+ name := f.Name.Name
+ if !isTest(name, "Example") {
+ continue
+ }
+ examples = append(examples, &Example{
+ Name: name[len("Example"):],
+ Body: f.Body,
+ Output: CommentText(f.Doc),
+ })
+ }
+ }
+ return examples
+}
+
+// isTest tells whether name looks like a test, example, or benchmark.
+// It is a Test (say) if there is a character after Test that is not a
+// lower-case letter. (We don't want Testiness.)
+func isTest(name, prefix string) bool {
+ if !strings.HasPrefix(name, prefix) {
+ return false
+ }
+ if len(name) == len(prefix) { // "Test" is ok
+ return true
+ }
+ rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
+ return !unicode.IsLower(rune)
+}
diff --git a/libgo/go/go/parser/parser.go b/libgo/go/go/parser/parser.go
index 9c14d166732..be82b2f801a 100644
--- a/libgo/go/go/parser/parser.go
+++ b/libgo/go/go/parser/parser.go
@@ -587,7 +587,6 @@ func (p *parser) parseStructType() *ast.StructType {
}
rbrace := p.expect(token.RBRACE)
- // TODO(gri): store struct scope in AST
return &ast.StructType{pos, &ast.FieldList{lbrace, list, rbrace}, false}
}
@@ -611,9 +610,6 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
p.error(pos, "'...' parameter is missing type")
typ = &ast.BadExpr{pos, p.pos}
}
- if p.tok != token.RPAREN {
- p.error(pos, "can use '...' with last parameter type only")
- }
return &ast.Ellipsis{pos, typ}
}
return p.tryIdentOrType(false)
@@ -636,21 +632,21 @@ func (p *parser) parseVarList(isParam bool) (list []ast.Expr, typ ast.Expr) {
}
// a list of identifiers looks like a list of type names
- for {
- // parseVarType accepts any type (including parenthesized ones)
- // even though the syntax does not permit them here: we
- // accept them all for more robust parsing and complain
- // afterwards
- list = append(list, p.parseVarType(isParam))
+ //
+ // parse/tryVarType accepts any type (including parenthesized
+ // ones) even though the syntax does not permit them here: we
+ // accept them all for more robust parsing and complain later
+ for typ := p.parseVarType(isParam); typ != nil; {
+ list = append(list, typ)
if p.tok != token.COMMA {
break
}
p.next()
+ typ = p.tryVarType(isParam) // maybe nil as in: func f(int,) {}
}
// if we had a list of identifiers, it must be followed by a type
- typ = p.tryVarType(isParam)
- if typ != nil {
+ if typ = p.tryVarType(isParam); typ != nil {
p.resolve(typ)
}
@@ -800,7 +796,6 @@ func (p *parser) parseInterfaceType() *ast.InterfaceType {
}
rbrace := p.expect(token.RBRACE)
- // TODO(gri): store interface scope in AST
return &ast.InterfaceType{pos, &ast.FieldList{lbrace, list, rbrace}, false}
}
@@ -1436,14 +1431,14 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
case token.ARROW:
// send statement
arrow := p.pos
- p.next() // consume "<-"
+ p.next()
y := p.parseRhs()
return &ast.SendStmt{x[0], arrow, y}, false
case token.INC, token.DEC:
// increment or decrement
s := &ast.IncDecStmt{x[0], p.pos, p.tok}
- p.next() // consume "++" or "--"
+ p.next()
return s, false
}
@@ -1591,7 +1586,7 @@ func (p *parser) parseTypeList() (list []ast.Expr) {
return
}
-func (p *parser) parseCaseClause(exprSwitch bool) *ast.CaseClause {
+func (p *parser) parseCaseClause(typeSwitch bool) *ast.CaseClause {
if p.trace {
defer un(trace(p, "CaseClause"))
}
@@ -1600,10 +1595,10 @@ func (p *parser) parseCaseClause(exprSwitch bool) *ast.CaseClause {
var list []ast.Expr
if p.tok == token.CASE {
p.next()
- if exprSwitch {
- list = p.parseRhsList()
- } else {
+ if typeSwitch {
list = p.parseTypeList()
+ } else {
+ list = p.parseRhsList()
}
} else {
p.expect(token.DEFAULT)
@@ -1617,15 +1612,19 @@ func (p *parser) parseCaseClause(exprSwitch bool) *ast.CaseClause {
return &ast.CaseClause{pos, list, colon, body}
}
-func isExprSwitch(s ast.Stmt) bool {
- if s == nil {
- return true
- }
- if e, ok := s.(*ast.ExprStmt); ok {
- if a, ok := e.X.(*ast.TypeAssertExpr); ok {
- return a.Type != nil // regular type assertion
- }
- return true
+func isTypeSwitchAssert(x ast.Expr) bool {
+ a, ok := x.(*ast.TypeAssertExpr)
+ return ok && a.Type == nil
+}
+
+func isTypeSwitchGuard(s ast.Stmt) bool {
+ switch t := s.(type) {
+ case *ast.ExprStmt:
+ // x.(nil)
+ return isTypeSwitchAssert(t.X)
+ case *ast.AssignStmt:
+ // v := x.(nil)
+ return len(t.Lhs) == 1 && t.Tok == token.DEFINE && len(t.Rhs) == 1 && isTypeSwitchAssert(t.Rhs[0])
}
return false
}
@@ -1651,28 +1650,41 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
s1 = s2
s2 = nil
if p.tok != token.LBRACE {
+ // A TypeSwitchGuard may declare a variable in addition
+ // to the variable declared in the initial SimpleStmt.
+ // Introduce extra scope to avoid redeclaration errors:
+ //
+ // switch t := 0; t := x.(T) { ... }
+ //
+ // (this code is not valid Go because the first t will
+ // cannot be accessed and thus is never used, the extra
+ // scope is needed for the correct error message).
+ //
+ // If we don't have a type switch, s2 must be an expression.
+ // Having the extra nested but empty scope won't affect it.
+ p.openScope()
+ defer p.closeScope()
s2, _ = p.parseSimpleStmt(basic)
}
}
p.exprLev = prevLev
}
- exprSwitch := isExprSwitch(s2)
+ typeSwitch := isTypeSwitchGuard(s2)
lbrace := p.expect(token.LBRACE)
var list []ast.Stmt
for p.tok == token.CASE || p.tok == token.DEFAULT {
- list = append(list, p.parseCaseClause(exprSwitch))
+ list = append(list, p.parseCaseClause(typeSwitch))
}
rbrace := p.expect(token.RBRACE)
p.expectSemi()
body := &ast.BlockStmt{lbrace, list, rbrace}
- if exprSwitch {
- return &ast.SwitchStmt{pos, s1, p.makeExpr(s2), body}
+ if typeSwitch {
+ return &ast.TypeSwitchStmt{pos, s1, s2, body}
}
- // type switch
- // TODO(gri): do all the checks!
- return &ast.TypeSwitchStmt{pos, s1, s2, body}
+
+ return &ast.SwitchStmt{pos, s1, p.makeExpr(s2), body}
}
func (p *parser) parseCommClause() *ast.CommClause {
@@ -2001,14 +2013,12 @@ func (p *parser) parseReceiver(scope *ast.Scope) *ast.FieldList {
defer un(trace(p, "Receiver"))
}
- pos := p.pos
par := p.parseParameters(scope, false)
// must have exactly one receiver
if par.NumFields() != 1 {
- p.errorExpected(pos, "exactly one receiver")
- // TODO determine a better range for BadExpr below
- par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{pos, pos}}}
+ p.errorExpected(par.Opening, "exactly one receiver")
+ par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{par.Opening, par.Closing + 1}}}
return par
}
diff --git a/libgo/go/go/parser/parser_test.go b/libgo/go/go/parser/parser_test.go
index 39a78e5156e..9705dcff250 100644
--- a/libgo/go/go/parser/parser_test.go
+++ b/libgo/go/go/parser/parser_test.go
@@ -26,6 +26,9 @@ var illegalInputs = []interface{}{
`package p; func f() { for _ = range x ; ; {} };`,
`package p; func f() { for ; ; _ = range x {} };`,
`package p; func f() { for ; _ = range x ; {} };`,
+ `package p; func f() { switch t = t.(type) {} };`,
+ `package p; func f() { switch t, t = t.(type) {} };`,
+ `package p; func f() { switch t = t.(type), t {} };`,
`package p; var a = [1]int; /* illegal expression */`,
`package p; var a = [...]int; /* illegal expression */`,
`package p; var a = struct{} /* illegal expression */`,
@@ -61,6 +64,9 @@ var validPrograms = []interface{}{
`package p; func f(...T);`,
`package p; func f(float, ...int);`,
`package p; func f(x int, a ...int) { f(0, a...); f(1, a...,) };`,
+ `package p; func f(int,) {};`,
+ `package p; func f(...int,) {};`,
+ `package p; func f(x ...int,) {};`,
`package p; type T []int; var a []bool; func f() { if a[T{42}[0]] {} };`,
`package p; type T []int; func g(int) bool { return true }; func f() { if g(T{42}[0]) {} };`,
`package p; type T []int; func f() { for _ = range []int{T{42}[0]} {} };`,
@@ -74,7 +80,7 @@ var validPrograms = []interface{}{
func TestParseValidPrograms(t *testing.T) {
for _, src := range validPrograms {
- _, err := ParseFile(fset, "", src, 0)
+ _, err := ParseFile(fset, "", src, SpuriousErrors)
if err != nil {
t.Errorf("ParseFile(%q): %v", src, err)
}
diff --git a/libgo/go/go/printer/nodes.go b/libgo/go/go/printer/nodes.go
index 9cd975ec1be..364530634aa 100644
--- a/libgo/go/go/printer/nodes.go
+++ b/libgo/go/go/printer/nodes.go
@@ -269,6 +269,7 @@ func (p *printer) exprList(prev0 token.Pos, list []ast.Expr, depth int, mode exp
func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
p.print(fields.Opening, token.LPAREN)
if len(fields.List) > 0 {
+ ws := indent
var prevLine, line int
for i, par := range fields.List {
if i > 0 {
@@ -278,19 +279,30 @@ func (p *printer) parameters(fields *ast.FieldList, multiLine *bool) {
} else {
line = p.fset.Position(par.Type.Pos()).Line
}
- if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ignore, true) {
+ if 0 < prevLine && prevLine < line && p.linebreak(line, 0, ws, true) {
+ ws = ignore
*multiLine = true
} else {
p.print(blank)
}
}
if len(par.Names) > 0 {
- p.identList(par.Names, false, multiLine)
+ // Very subtle: If we indented before (ws == ignore), identList
+ // won't indent again. If we didn't (ws == indent), identList will
+ // indent if the identList spans multiple lines, and it will outdent
+ // again at the end (and still ws == indent). Thus, a subsequent indent
+ // by a linebreak call after a type, or in the next multi-line identList
+ // will do the right thing.
+ p.identList(par.Names, ws == indent, multiLine)
p.print(blank)
}
p.expr(par.Type, multiLine)
prevLine = p.fset.Position(par.Type.Pos()).Line
}
+ if ws == ignore {
+ // unindent if we indented
+ p.print(unindent)
+ }
}
p.print(fields.Closing, token.RPAREN)
}
diff --git a/libgo/go/go/printer/printer.go b/libgo/go/go/printer/printer.go
index 871fefa0c8f..bfabd749abb 100644
--- a/libgo/go/go/printer/printer.go
+++ b/libgo/go/go/printer/printer.go
@@ -13,7 +13,6 @@ import (
"io"
"os"
"path/filepath"
- "runtime"
"tabwriter"
)
@@ -55,12 +54,17 @@ const (
noExtraLinebreak
)
+// local error wrapper so we can distinguish os.Errors we want to return
+// as errors from genuine panics (which we don't want to return as errors)
+type osError struct {
+ err os.Error
+}
+
type printer struct {
// Configuration (does not change after initialization)
output io.Writer
Config
- fset *token.FileSet
- errors chan os.Error
+ fset *token.FileSet
// Current state
written int // number of bytes written
@@ -95,7 +99,6 @@ func (p *printer) init(output io.Writer, cfg *Config, fset *token.FileSet, nodeS
p.output = output
p.Config = *cfg
p.fset = fset
- p.errors = make(chan os.Error)
p.wsbuf = make([]whiteSpace, 0, 16) // whitespace sequences are short
p.nodeSizes = nodeSizes
}
@@ -143,8 +146,7 @@ func (p *printer) write0(data []byte) {
n, err := p.output.Write(data)
p.written += n
if err != nil {
- p.errors <- err
- runtime.Goexit()
+ panic(osError{err})
}
}
}
@@ -923,7 +925,7 @@ type Config struct {
}
// fprint implements Fprint and takes a nodesSizes map for setting up the printer state.
-func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{}, nodeSizes map[ast.Node]int) (int, os.Error) {
+func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{}, nodeSizes map[ast.Node]int) (written int, err os.Error) {
// redirect output through a trimmer to eliminate trailing whitespace
// (Input to a tabwriter must be untrimmed since trailing tabs provide
// formatting information. The tabwriter could provide trimming
@@ -950,47 +952,50 @@ func (cfg *Config) fprint(output io.Writer, fset *token.FileSet, node interface{
output = tw
}
- // setup printer and print node
+ // setup printer
var p printer
p.init(output, cfg, fset, nodeSizes)
- go func() {
- switch n := node.(type) {
- case ast.Expr:
- p.useNodeComments = true
- p.expr(n, ignoreMultiLine)
- case ast.Stmt:
- p.useNodeComments = true
- // A labeled statement will un-indent to position the
- // label. Set indent to 1 so we don't get indent "underflow".
- if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
- p.indent = 1
- }
- p.stmt(n, false, ignoreMultiLine)
- case ast.Decl:
- p.useNodeComments = true
- p.decl(n, ignoreMultiLine)
- case ast.Spec:
- p.useNodeComments = true
- p.spec(n, 1, false, ignoreMultiLine)
- case *ast.File:
- p.comments = n.Comments
- p.useNodeComments = n.Comments == nil
- p.file(n)
- default:
- p.errors <- fmt.Errorf("printer.Fprint: unsupported node type %T", n)
- runtime.Goexit()
+ defer func() {
+ written = p.written
+ if e := recover(); e != nil {
+ err = e.(osError).err // re-panics if it's not a local osError
}
- p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF)
- p.errors <- nil // no errors
}()
- err := <-p.errors // wait for completion of goroutine
+
+ // print node
+ switch n := node.(type) {
+ case ast.Expr:
+ p.useNodeComments = true
+ p.expr(n, ignoreMultiLine)
+ case ast.Stmt:
+ p.useNodeComments = true
+ // A labeled statement will un-indent to position the
+ // label. Set indent to 1 so we don't get indent "underflow".
+ if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
+ p.indent = 1
+ }
+ p.stmt(n, false, ignoreMultiLine)
+ case ast.Decl:
+ p.useNodeComments = true
+ p.decl(n, ignoreMultiLine)
+ case ast.Spec:
+ p.useNodeComments = true
+ p.spec(n, 1, false, ignoreMultiLine)
+ case *ast.File:
+ p.comments = n.Comments
+ p.useNodeComments = n.Comments == nil
+ p.file(n)
+ default:
+ panic(osError{fmt.Errorf("printer.Fprint: unsupported node type %T", n)})
+ }
+ p.flush(token.Position{Offset: infinity, Line: infinity}, token.EOF)
// flush tabwriter, if any
if tw != nil {
tw.Flush() // ignore errors
}
- return p.written, err
+ return
}
// Fprint "pretty-prints" an AST node to output and returns the number
diff --git a/libgo/go/go/printer/printer_test.go b/libgo/go/go/printer/printer_test.go
index ff2d906b560..a644aa383ab 100644
--- a/libgo/go/go/printer/printer_test.go
+++ b/libgo/go/go/printer/printer_test.go
@@ -7,10 +7,10 @@ package printer
import (
"bytes"
"flag"
- "io/ioutil"
"go/ast"
"go/parser"
"go/token"
+ "io/ioutil"
"path/filepath"
"testing"
"time"
@@ -192,3 +192,15 @@ func TestLineComments(t *testing.T) {
t.Errorf("got %d, expected %d\n", nlines, expected)
}
}
+
+// Verify that the printer can be invoked during initialization.
+func init() {
+ const name = "foobar"
+ var buf bytes.Buffer
+ if err := Fprint(&buf, fset, &ast.Ident{Name: name}); err != nil {
+ panic(err)
+ }
+ if s := buf.String(); s != name {
+ panic("got " + s + ", want " + name)
+ }
+}
diff --git a/libgo/go/go/printer/testdata/declarations.golden b/libgo/go/go/printer/testdata/declarations.golden
index 970533e8cfb..bfa2568c21f 100644
--- a/libgo/go/go/printer/testdata/declarations.golden
+++ b/libgo/go/go/printer/testdata/declarations.golden
@@ -692,56 +692,119 @@ func _(x ...chan int)
// these parameter lists must remain multi-line since they are multi-line in the source
func _(bool,
-int) {
+ int) {
}
func _(x bool,
-y int) {
+ y int) {
}
func _(x,
-y bool) {
+ y bool) {
}
func _(bool, // comment
-int) {
+ int) {
}
func _(x bool, // comment
-y int) {
+ y int) {
}
func _(x, // comment
-y bool) {
+ y bool) {
}
func _(bool, // comment
-// comment
-int) {
+ // comment
+ int) {
}
func _(x bool, // comment
-// comment
-y int) {
+ // comment
+ y int) {
}
func _(x, // comment
-// comment
-y bool) {
+ // comment
+ y bool) {
}
func _(bool,
-// comment
-int) {
+ // comment
+ int) {
}
func _(x bool,
-// comment
-y int) {
+ // comment
+ y int) {
}
func _(x,
-// comment
-y bool) {
+ // comment
+ y bool) {
}
func _(x, // comment
-y, // comment
-z bool) {
+ y, // comment
+ z bool) {
}
func _(x, // comment
-y, // comment
-z bool) {
+ y, // comment
+ z bool) {
}
func _(x int, // comment
-y float, // comment
-z bool) {
+ y float, // comment
+ z bool) {
+}
+
+// properly indent multi-line signatures
+func ManageStatus(in <-chan *Status, req <-chan Request,
+ stat chan<- *TargetInfo,
+ TargetHistorySize int) {
+}
+
+func MultiLineSignature0(a, b, c int) {
+}
+
+func MultiLineSignature1(a, b, c int,
+ u, v, w float) {
+}
+
+func MultiLineSignature2(a, b,
+ c int) {
+}
+
+func MultiLineSignature3(a, b,
+ c int, u, v,
+ w float,
+ x ...int) {
+}
+
+func MultiLineSignature4(a, b, c int,
+ u, v,
+ w float,
+ x ...int) {
+}
+
+func MultiLineSignature5(a, b, c int,
+ u, v, w float,
+ p, q,
+ r string,
+ x ...int) {
+}
+
+// make sure it also works for methods in interfaces
+type _ interface {
+ MultiLineSignature0(a, b, c int)
+
+ MultiLineSignature1(a, b, c int,
+ u, v, w float)
+
+ MultiLineSignature2(a, b,
+ c int)
+
+ MultiLineSignature3(a, b,
+ c int, u, v,
+ w float,
+ x ...int)
+
+ MultiLineSignature4(a, b, c int,
+ u, v,
+ w float,
+ x ...int)
+
+ MultiLineSignature5(a, b, c int,
+ u, v, w float,
+ p, q,
+ r string,
+ x ...int)
}
diff --git a/libgo/go/go/printer/testdata/declarations.input b/libgo/go/go/printer/testdata/declarations.input
index c6134096bf1..1d69c57b517 100644
--- a/libgo/go/go/printer/testdata/declarations.input
+++ b/libgo/go/go/printer/testdata/declarations.input
@@ -755,3 +755,79 @@ func _(x int, // comment
y float, // comment
z bool) {
}
+
+
+// properly indent multi-line signatures
+func ManageStatus(in <-chan *Status, req <-chan Request,
+stat chan<- *TargetInfo,
+TargetHistorySize int) {
+}
+
+func MultiLineSignature0(
+a, b, c int,
+) {}
+
+func MultiLineSignature1(
+a, b, c int,
+u, v, w float,
+) {}
+
+func MultiLineSignature2(
+a, b,
+c int,
+) {}
+
+func MultiLineSignature3(
+a, b,
+c int, u, v,
+w float,
+ x ...int) {}
+
+func MultiLineSignature4(
+a, b, c int,
+u, v,
+w float,
+ x ...int) {}
+
+func MultiLineSignature5(
+a, b, c int,
+u, v, w float,
+p, q,
+r string,
+ x ...int) {}
+
+// make sure it also works for methods in interfaces
+type _ interface {
+MultiLineSignature0(
+a, b, c int,
+)
+
+MultiLineSignature1(
+a, b, c int,
+u, v, w float,
+)
+
+MultiLineSignature2(
+a, b,
+c int,
+)
+
+MultiLineSignature3(
+a, b,
+c int, u, v,
+w float,
+ x ...int)
+
+MultiLineSignature4(
+a, b, c int,
+u, v,
+w float,
+ x ...int)
+
+MultiLineSignature5(
+a, b, c int,
+u, v, w float,
+p, q,
+r string,
+ x ...int)
+}
diff --git a/libgo/go/go/scanner/scanner.go b/libgo/go/go/scanner/scanner.go
index 7f3dd237328..589ec68a678 100644
--- a/libgo/go/go/scanner/scanner.go
+++ b/libgo/go/go/scanner/scanner.go
@@ -90,9 +90,8 @@ func (S *Scanner) next() {
// They control scanner behavior.
//
const (
- ScanComments = 1 << iota // return comments as COMMENT tokens
- AllowIllegalChars // do not report an error for illegal chars
- InsertSemis // automatically insert semicolons
+ ScanComments = 1 << iota // return comments as COMMENT tokens
+ InsertSemis // automatically insert semicolons
)
// Init prepares the scanner S to tokenize the text src by setting the
@@ -152,7 +151,7 @@ func (S *Scanner) interpretLineComment(text []byte) {
filename = filepath.Join(S.dir, filename)
}
// update scanner position
- S.file.AddLineInfo(S.lineOffset, filename, line-1) // -1 since comment applies to next line
+ S.file.AddLineInfo(S.lineOffset+len(text)+1, filename, line) // +len(text)+1 since comment applies to next line
}
}
}
@@ -652,9 +651,7 @@ scanAgain:
case '|':
tok = S.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR)
default:
- if S.mode&AllowIllegalChars == 0 {
- S.error(offs, fmt.Sprintf("illegal character %#U", ch))
- }
+ S.error(offs, fmt.Sprintf("illegal character %#U", ch))
insertSemi = S.insertSemi // preserve insertSemi info
}
}
diff --git a/libgo/go/go/scanner/scanner_test.go b/libgo/go/go/scanner/scanner_test.go
index eb9e1cb818a..0c2cbe6dc02 100644
--- a/libgo/go/go/scanner/scanner_test.go
+++ b/libgo/go/go/scanner/scanner_test.go
@@ -420,14 +420,14 @@ var lines = []string{
func TestSemis(t *testing.T) {
for _, line := range lines {
- checkSemi(t, line, AllowIllegalChars|InsertSemis)
- checkSemi(t, line, AllowIllegalChars|InsertSemis|ScanComments)
+ checkSemi(t, line, InsertSemis)
+ checkSemi(t, line, InsertSemis|ScanComments)
// if the input ended in newlines, the input must tokenize the
// same with or without those newlines
for i := len(line) - 1; i >= 0 && line[i] == '\n'; i-- {
- checkSemi(t, line[0:i], AllowIllegalChars|InsertSemis)
- checkSemi(t, line[0:i], AllowIllegalChars|InsertSemis|ScanComments)
+ checkSemi(t, line[0:i], InsertSemis)
+ checkSemi(t, line[0:i], InsertSemis|ScanComments)
}
}
}
@@ -529,27 +529,6 @@ func TestInit(t *testing.T) {
}
}
-func TestIllegalChars(t *testing.T) {
- var s Scanner
-
- const src = "*?*$*@*"
- file := fset.AddFile("", fset.Base(), len(src))
- s.Init(file, []byte(src), &testErrorHandler{t}, AllowIllegalChars)
- for offs, ch := range src {
- pos, tok, lit := s.Scan()
- if poffs := file.Offset(pos); poffs != offs {
- t.Errorf("bad position for %s: got %d, expected %d", lit, poffs, offs)
- }
- if tok == token.ILLEGAL && lit != string(ch) {
- t.Errorf("bad token: got %s, expected %s", lit, string(ch))
- }
- }
-
- if s.ErrorCount != 0 {
- t.Errorf("found %d errors", s.ErrorCount)
- }
-}
-
func TestStdErrorHander(t *testing.T) {
const src = "@\n" + // illegal character, cause an error
"@ @\n" + // two errors on the same line
diff --git a/libgo/go/go/token/position.go b/libgo/go/go/token/position.go
index c559e19f886..8cf3dcd25a2 100644
--- a/libgo/go/go/token/position.go
+++ b/libgo/go/go/token/position.go
@@ -86,9 +86,11 @@ func searchFiles(a []*File, x int) int {
}
func (s *FileSet) file(p Pos) *File {
+ // common case: p is in last file touched
if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size {
return f
}
+ // p is not in last file touched - search all files
if i := searchFiles(s.files, int(p)); i >= 0 {
f := s.files[i]
// f.base <= int(p) by definition of searchFiles
@@ -123,10 +125,6 @@ func (f *File) position(p Pos) (pos Position) {
// Position converts a Pos in the fileset into a general Position.
func (s *FileSet) Position(p Pos) (pos Position) {
if p != NoPos {
- // TODO(gri) consider optimizing the case where p
- // is in the last file added, or perhaps
- // looked at - will eliminate one level
- // of search
s.mutex.RLock()
if f := s.file(p); f != nil {
pos = f.position(p)
@@ -136,10 +134,14 @@ func (s *FileSet) Position(p Pos) (pos Position) {
return
}
+// A lineInfo object describes alternative file and line number
+// information (such as provided via a //line comment in a .go
+// file) for a given file offset.
type lineInfo struct {
- offset int
- filename string
- line int
+ // fields are exported to make them accessible to gob
+ Offset int
+ Filename string
+ Line int
}
// AddLineInfo adds alternative file and line number information for
@@ -152,7 +154,7 @@ type lineInfo struct {
//
func (f *File) AddLineInfo(offset int, filename string, line int) {
f.set.mutex.Lock()
- if i := len(f.infos); i == 0 || f.infos[i-1].offset < offset && offset < f.size {
+ if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size {
f.infos = append(f.infos, lineInfo{offset, filename, line})
}
f.set.mutex.Unlock()
@@ -317,7 +319,7 @@ func searchInts(a []int, x int) int {
}
func searchLineInfos(a []lineInfo, x int) int {
- return sort.Search(len(a), func(i int) bool { return a[i].offset > x }) - 1
+ return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1
}
// info returns the file name, line, and column number for a file offset.
@@ -330,9 +332,9 @@ func (f *File) info(offset int) (filename string, line, column int) {
// almost no files have extra line infos
if i := searchLineInfos(f.infos, offset); i >= 0 {
alt := &f.infos[i]
- filename = alt.filename
- if i := searchInts(f.lines, alt.offset); i >= 0 {
- line += alt.line - i - 1
+ filename = alt.Filename
+ if i := searchInts(f.lines, alt.Offset); i >= 0 {
+ line += alt.Line - i - 1
}
}
}
diff --git a/libgo/go/go/token/serialize.go b/libgo/go/go/token/serialize.go
new file mode 100644
index 00000000000..5fb47f7cbb2
--- /dev/null
+++ b/libgo/go/go/token/serialize.go
@@ -0,0 +1,71 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package token
+
+import (
+ "gob"
+ "io"
+ "os"
+)
+
+type serializedFile struct {
+ // fields correspond 1:1 to fields with same (lower-case) name in File
+ Name string
+ Base int
+ Size int
+ Lines []int
+ Infos []lineInfo
+}
+
+type serializedFileSet struct {
+ Base int
+ Files []serializedFile
+}
+
+func (s *serializedFileSet) Read(r io.Reader) os.Error {
+ return gob.NewDecoder(r).Decode(s)
+}
+
+func (s *serializedFileSet) Write(w io.Writer) os.Error {
+ return gob.NewEncoder(w).Encode(s)
+}
+
+// Read reads the fileset from r into s; s must not be nil.
+// If r does not also implement io.ByteReader, it will be wrapped in a bufio.Reader.
+func (s *FileSet) Read(r io.Reader) os.Error {
+ var ss serializedFileSet
+ if err := ss.Read(r); err != nil {
+ return err
+ }
+
+ s.mutex.Lock()
+ s.base = ss.Base
+ files := make([]*File, len(ss.Files))
+ for i := 0; i < len(ss.Files); i++ {
+ f := &ss.Files[i]
+ files[i] = &File{s, f.Name, f.Base, f.Size, f.Lines, f.Infos}
+ }
+ s.files = files
+ s.last = nil
+ s.mutex.Unlock()
+
+ return nil
+}
+
+// Write writes the fileset s to w.
+func (s *FileSet) Write(w io.Writer) os.Error {
+ var ss serializedFileSet
+
+ s.mutex.Lock()
+ ss.Base = s.base
+ files := make([]serializedFile, len(s.files))
+ for i, f := range s.files {
+ files[i] = serializedFile{f.name, f.base, f.size, f.lines, f.infos}
+ }
+ ss.Files = files
+ s.mutex.Unlock()
+
+ return ss.Write(w)
+}
diff --git a/libgo/go/go/token/serialize_test.go b/libgo/go/go/token/serialize_test.go
new file mode 100644
index 00000000000..24e419abf6d
--- /dev/null
+++ b/libgo/go/go/token/serialize_test.go
@@ -0,0 +1,105 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package token
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "testing"
+)
+
+// equal returns nil if p and q describe the same file set;
+// otherwise it returns an error describing the discrepancy.
+func equal(p, q *FileSet) os.Error {
+ if p == q {
+ // avoid deadlock if p == q
+ return nil
+ }
+
+ // not strictly needed for the test
+ p.mutex.Lock()
+ q.mutex.Lock()
+ defer q.mutex.Unlock()
+ defer p.mutex.Unlock()
+
+ if p.base != q.base {
+ return fmt.Errorf("different bases: %d != %d", p.base, q.base)
+ }
+
+ if len(p.files) != len(q.files) {
+ return fmt.Errorf("different number of files: %d != %d", len(p.files), len(q.files))
+ }
+
+ for i, f := range p.files {
+ g := q.files[i]
+ if f.set != p {
+ return fmt.Errorf("wrong fileset for %q", f.name)
+ }
+ if g.set != q {
+ return fmt.Errorf("wrong fileset for %q", g.name)
+ }
+ if f.name != g.name {
+ return fmt.Errorf("different filenames: %q != %q", f.name, g.name)
+ }
+ if f.base != g.base {
+ return fmt.Errorf("different base for %q: %d != %d", f.name, f.base, g.base)
+ }
+ if f.size != g.size {
+ return fmt.Errorf("different size for %q: %d != %d", f.name, f.size, g.size)
+ }
+ for j, l := range f.lines {
+ m := g.lines[j]
+ if l != m {
+ return fmt.Errorf("different offsets for %q", f.name)
+ }
+ }
+ for j, l := range f.infos {
+ m := g.infos[j]
+ if l.Offset != m.Offset || l.Filename != m.Filename || l.Line != m.Line {
+ return fmt.Errorf("different infos for %q", f.name)
+ }
+ }
+ }
+
+ // we don't care about .last - it's just a cache
+ return nil
+}
+
+func checkSerialize(t *testing.T, p *FileSet) {
+ var buf bytes.Buffer
+ if err := p.Write(&buf); err != nil {
+ t.Errorf("writing fileset failed: %s", err)
+ return
+ }
+ q := NewFileSet()
+ if err := q.Read(&buf); err != nil {
+ t.Errorf("reading fileset failed: %s", err)
+ return
+ }
+ if err := equal(p, q); err != nil {
+ t.Errorf("filesets not identical: %s", err)
+ }
+}
+
+func TestSerialization(t *testing.T) {
+ p := NewFileSet()
+ checkSerialize(t, p)
+ // add some files
+ for i := 0; i < 10; i++ {
+ f := p.AddFile(fmt.Sprintf("file%d", i), p.Base()+i, i*100)
+ checkSerialize(t, p)
+ // add some lines and alternative file infos
+ line := 1000
+ for offs := 0; offs < f.Size(); offs += 40 + i {
+ f.AddLine(offs)
+ if offs%7 == 0 {
+ f.AddLineInfo(offs, fmt.Sprintf("file%d", offs), line)
+ line += 33
+ }
+ }
+ checkSerialize(t, p)
+ }
+}
diff --git a/libgo/go/go/typechecker/scope.go b/libgo/go/go/typechecker/scope.go
deleted file mode 100644
index d73d1a45048..00000000000
--- a/libgo/go/go/typechecker/scope.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// DEPRECATED FILE - WILL GO AWAY EVENTUALLY.
-//
-// Scope handling is now done in go/parser.
-// The functionality here is only present to
-// keep the typechecker running for now.
-
-package typechecker
-
-import "go/ast"
-
-func (tc *typechecker) openScope() *ast.Scope {
- tc.topScope = ast.NewScope(tc.topScope)
- return tc.topScope
-}
-
-func (tc *typechecker) closeScope() {
- tc.topScope = tc.topScope.Outer
-}
-
-// declInScope declares an object of a given kind and name in scope and sets the object's Decl and N fields.
-// It returns the newly allocated object. If an object with the same name already exists in scope, an error
-// is reported and the object is not inserted.
-func (tc *typechecker) declInScope(scope *ast.Scope, kind ast.ObjKind, name *ast.Ident, decl interface{}, n int) *ast.Object {
- obj := ast.NewObj(kind, name.Name)
- obj.Decl = decl
- //obj.N = n
- name.Obj = obj
- if name.Name != "_" {
- if alt := scope.Insert(obj); alt != nil {
- tc.Errorf(name.Pos(), "%s already declared at %s", name.Name, tc.fset.Position(alt.Pos()).String())
- }
- }
- return obj
-}
-
-// decl is the same as declInScope(tc.topScope, ...)
-func (tc *typechecker) decl(kind ast.ObjKind, name *ast.Ident, decl interface{}, n int) *ast.Object {
- return tc.declInScope(tc.topScope, kind, name, decl, n)
-}
-
-// find returns the object with the given name if visible in the current scope hierarchy.
-// If no such object is found, an error is reported and a bad object is returned instead.
-func (tc *typechecker) find(name *ast.Ident) (obj *ast.Object) {
- for s := tc.topScope; s != nil && obj == nil; s = s.Outer {
- obj = s.Lookup(name.Name)
- }
- if obj == nil {
- tc.Errorf(name.Pos(), "%s not declared", name.Name)
- obj = ast.NewObj(ast.Bad, name.Name)
- }
- name.Obj = obj
- return
-}
-
-// findField returns the object with the given name if visible in the type's scope.
-// If no such object is found, an error is reported and a bad object is returned instead.
-func (tc *typechecker) findField(typ *Type, name *ast.Ident) (obj *ast.Object) {
- // TODO(gri) This is simplistic at the moment and ignores anonymous fields.
- obj = typ.Scope.Lookup(name.Name)
- if obj == nil {
- tc.Errorf(name.Pos(), "%s not declared", name.Name)
- obj = ast.NewObj(ast.Bad, name.Name)
- }
- return
-}
diff --git a/libgo/go/go/typechecker/testdata/test0.src b/libgo/go/go/typechecker/testdata/test0.src
deleted file mode 100644
index 4e317f21464..00000000000
--- a/libgo/go/go/typechecker/testdata/test0.src
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// type declarations
-
-package P0
-
-type (
- B bool
- I int32
- A [10]P
- T struct {
- x, y P
- }
- P *T
- R *R
- F func(A) I
- Y interface {
- f(A) I
- }
- S []P
- M map[I]F
- C chan<- I
-)
-
-type (
- a/* ERROR "illegal cycle" */ a
- a/* ERROR "already declared" */ int
-
- b/* ERROR "illegal cycle" */ c
- c d
- d e
- e b /* ERROR "not a type" */
-
- t *t
-
- U V
- V W
- W *U
-
- P1 *S2
- P2 P1
-
- S1 struct {
- a, b, c int
- u, v, a/* ERROR "already declared" */ float
- }
- S2/* ERROR "illegal cycle" */ struct {
- x S2
- }
-
- L1 []L1
- L2 []int
-
- A1 [10]int
- A2/* ERROR "illegal cycle" */ [10]A2
- A3/* ERROR "illegal cycle" */ [10]struct {
- x A4
- }
- A4 [10]A3
-
- F1 func()
- F2 func(x, y, z float)
- F3 func(x, y, x /* ERROR "already declared" */ float)
- F4 func() (x, y, x /* ERROR "already declared" */ float)
- F5 func(x int) (x /* ERROR "already declared" */ float)
-
- I1 interface{}
- I2 interface {
- m1()
- }
- I3 interface {
- m1()
- m1 /* ERROR "already declared" */ ()
- }
- I4 interface {
- m1(x, y, x /* ERROR "already declared" */ float)
- m2() (x, y, x /* ERROR "already declared" */ float)
- m3(x int) (x /* ERROR "already declared" */ float)
- }
- I5 interface {
- m1(I5)
- }
-
- C1 chan int
- C2 <-chan int
- C3 chan<- C3
-
- M1 map[Last]string
- M2 map[string]M2
-
- Last int
-)
diff --git a/libgo/go/go/typechecker/testdata/test1.src b/libgo/go/go/typechecker/testdata/test1.src
deleted file mode 100644
index b5531fb9f5b..00000000000
--- a/libgo/go/go/typechecker/testdata/test1.src
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// const and var declarations
-
-package P1
-
-const (
- c1 = 0
- c2 int = 0
- c3, c4 = 0
-)
diff --git a/libgo/go/go/typechecker/testdata/test3.src b/libgo/go/go/typechecker/testdata/test3.src
deleted file mode 100644
index 2e1a9fa8f5b..00000000000
--- a/libgo/go/go/typechecker/testdata/test3.src
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package P3
-
-// function and method signatures
-
-func _() {}
-func _() {}
-func _(x, x /* ERROR "already declared" */ int) {}
-
-func f() {}
-func f /* ERROR "already declared" */ () {}
-
-func (*foo /* ERROR "invalid receiver" */ ) m() {}
-func (bar /* ERROR "not a type" */ ) m() {}
-
-func f1(x, _, _ int) (_, _ float) {}
-func f2(x, y, x /* ERROR "already declared" */ int) {}
-func f3(x, y int) (a, b, x /* ERROR "already declared" */ int) {}
-
-func (x *T) m1() {}
-func (x *T) m1 /* ERROR "already declared" */ () {}
-func (x T) m1 /* ERROR "already declared" */ () {}
-func (T) m1 /* ERROR "already declared" */ () {}
-
-func (x *T) m2(u, x /* ERROR "already declared" */ int) {}
-func (x *T) m3(a, b, c int) (u, x /* ERROR "already declared" */ int) {}
-// The following are disabled for now because the typechecker
-// in in the process of being rewritten and cannot handle them
-// at the moment
-//func (T) _(x, x /* "already declared" */ int) {}
-//func (T) _() (x, x /* "already declared" */ int) {}
-
-//func (PT) _() {}
-
-var bar int
-
-type T struct{}
-type PT (T)
diff --git a/libgo/go/go/typechecker/testdata/test4.src b/libgo/go/go/typechecker/testdata/test4.src
deleted file mode 100644
index 94d3558f9cd..00000000000
--- a/libgo/go/go/typechecker/testdata/test4.src
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Constant declarations
-
-package P4
-
-const (
- c0 = 0
-)
diff --git a/libgo/go/go/typechecker/type.go b/libgo/go/go/typechecker/type.go
deleted file mode 100644
index 1b88eb54b85..00000000000
--- a/libgo/go/go/typechecker/type.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package typechecker
-
-import "go/ast"
-
-// A Type represents a Go type.
-type Type struct {
- Form Form
- Obj *ast.Object // corresponding type name, or nil
- Scope *ast.Scope // fields and methods, always present
- N uint // basic type id, array length, number of function results, or channel direction
- Key, Elt *Type // map key and array, pointer, slice, map or channel element
- Params *ast.Scope // function (receiver, input and result) parameters, tuple expressions (results of function calls), or nil
- Expr ast.Expr // corresponding AST expression
-}
-
-// NewType creates a new type of a given form.
-func NewType(form Form) *Type {
- return &Type{Form: form, Scope: ast.NewScope(nil)}
-}
-
-// Form describes the form of a type.
-type Form int
-
-// The list of possible type forms.
-const (
- BadType Form = iota // for error handling
- Unresolved // type not fully setup
- Basic
- Array
- Struct
- Pointer
- Function
- Method
- Interface
- Slice
- Map
- Channel
- Tuple
-)
-
-var formStrings = [...]string{
- BadType: "badType",
- Unresolved: "unresolved",
- Basic: "basic",
- Array: "array",
- Struct: "struct",
- Pointer: "pointer",
- Function: "function",
- Method: "method",
- Interface: "interface",
- Slice: "slice",
- Map: "map",
- Channel: "channel",
- Tuple: "tuple",
-}
-
-func (form Form) String() string { return formStrings[form] }
-
-// The list of basic type id's.
-const (
- Bool = iota
- Byte
- Uint
- Int
- Float
- Complex
- Uintptr
- String
-
- Uint8
- Uint16
- Uint32
- Uint64
-
- Int8
- Int16
- Int32
- Int64
-
- Float32
- Float64
-
- Complex64
- Complex128
-
- // TODO(gri) ideal types are missing
-)
-
-var BasicTypes = map[uint]string{
- Bool: "bool",
- Byte: "byte",
- Uint: "uint",
- Int: "int",
- Float: "float",
- Complex: "complex",
- Uintptr: "uintptr",
- String: "string",
-
- Uint8: "uint8",
- Uint16: "uint16",
- Uint32: "uint32",
- Uint64: "uint64",
-
- Int8: "int8",
- Int16: "int16",
- Int32: "int32",
- Int64: "int64",
-
- Float32: "float32",
- Float64: "float64",
-
- Complex64: "complex64",
- Complex128: "complex128",
-}
diff --git a/libgo/go/go/typechecker/typechecker.go b/libgo/go/go/typechecker/typechecker.go
deleted file mode 100644
index 24480165bde..00000000000
--- a/libgo/go/go/typechecker/typechecker.go
+++ /dev/null
@@ -1,468 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// DEPRECATED PACKAGE - SEE go/types INSTEAD.
-// This package implements typechecking of a Go AST.
-// The result of the typecheck is an augmented AST
-// with object and type information for each identifier.
-//
-package typechecker
-
-import (
- "fmt"
- "go/ast"
- "go/token"
- "go/scanner"
- "os"
-)
-
-// TODO(gri) don't report errors for objects/types that are marked as bad.
-
-
-const debug = true // set for debugging output
-
-// An importer takes an import path and returns the data describing the
-// respective package's exported interface. The data format is TBD.
-//
-type Importer func(path string) ([]byte, os.Error)
-
-// CheckPackage typechecks a package and augments the AST by setting
-// *ast.Object, *ast.Type, and *ast.Scope fields accordingly. If an
-// importer is provided, it is used to handle imports, otherwise they
-// are ignored (likely leading to typechecking errors).
-//
-// If errors are reported, the AST may be incompletely augmented (fields
-// may be nil) or contain incomplete object, type, or scope information.
-//
-func CheckPackage(fset *token.FileSet, pkg *ast.Package, importer Importer) os.Error {
- var tc typechecker
- tc.fset = fset
- tc.importer = importer
- tc.checkPackage(pkg)
- return tc.GetError(scanner.Sorted)
-}
-
-// CheckFile typechecks a single file, but otherwise behaves like
-// CheckPackage. If the complete package consists of more than just
-// one file, the file may not typecheck without errors.
-//
-func CheckFile(fset *token.FileSet, file *ast.File, importer Importer) os.Error {
- // create a single-file dummy package
- pkg := &ast.Package{file.Name.Name, nil, nil, map[string]*ast.File{fset.Position(file.Name.NamePos).Filename: file}}
- return CheckPackage(fset, pkg, importer)
-}
-
-// ----------------------------------------------------------------------------
-// Typechecker state
-
-type typechecker struct {
- fset *token.FileSet
- scanner.ErrorVector
- importer Importer
- globals []*ast.Object // list of global objects
- topScope *ast.Scope // current top-most scope
- cyclemap map[*ast.Object]bool // for cycle detection
- iota int // current value of iota
-}
-
-func (tc *typechecker) Errorf(pos token.Pos, format string, args ...interface{}) {
- tc.Error(tc.fset.Position(pos), fmt.Sprintf(format, args...))
-}
-
-func assert(pred bool) {
- if !pred {
- panic("internal error")
- }
-}
-
-/*
-Typechecking is done in several phases:
-
-phase 1: declare all global objects; also collect all function and method declarations
- - all objects have kind, name, decl fields; the decl field permits
- quick lookup of an object's declaration
- - constant objects have an iota value
- - type objects have unresolved types with empty scopes, all others have nil types
- - report global double declarations
-
-phase 2: bind methods to their receiver base types
- - receiver base types must be declared in the package, thus for
- each method a corresponding (unresolved) type must exist
- - report method double declarations and errors with base types
-
-phase 3: resolve all global objects
- - sequentially iterate through all objects in the global scope
- - resolve types for all unresolved types and assign types to
- all attached methods
- - assign types to all other objects, possibly by evaluating
- constant and initializer expressions
- - resolution may recurse; a cyclemap is used to detect cycles
- - report global typing errors
-
-phase 4: sequentially typecheck function and method bodies
- - all global objects are declared and have types and values;
- all methods have types
- - sequentially process statements in each body; any object
- referred to must be fully defined at this point
- - report local typing errors
-*/
-
-func (tc *typechecker) checkPackage(pkg *ast.Package) {
- // setup package scope
- tc.topScope = Universe
- tc.openScope()
- defer tc.closeScope()
-
- // TODO(gri) there's no file scope at the moment since we ignore imports
-
- // phase 1: declare all global objects; also collect all function and method declarations
- var funcs []*ast.FuncDecl
- for _, file := range pkg.Files {
- for _, decl := range file.Decls {
- tc.declGlobal(decl)
- if f, isFunc := decl.(*ast.FuncDecl); isFunc {
- funcs = append(funcs, f)
- }
- }
- }
-
- // phase 2: bind methods to their receiver base types
- for _, m := range funcs {
- if m.Recv != nil {
- tc.bindMethod(m)
- }
- }
-
- // phase 3: resolve all global objects
- tc.cyclemap = make(map[*ast.Object]bool)
- for _, obj := range tc.globals {
- tc.resolve(obj)
- }
- assert(len(tc.cyclemap) == 0)
-
- // 4: sequentially typecheck function and method bodies
- for _, f := range funcs {
- ftype, _ := f.Name.Obj.Type.(*Type)
- tc.checkBlock(f.Body.List, ftype)
- }
-
- pkg.Scope = tc.topScope
-}
-
-func (tc *typechecker) declGlobal(global ast.Decl) {
- switch d := global.(type) {
- case *ast.BadDecl:
- // ignore
-
- case *ast.GenDecl:
- iota := 0
- var prev *ast.ValueSpec
- for _, spec := range d.Specs {
- switch s := spec.(type) {
- case *ast.ImportSpec:
- // TODO(gri) imports go into file scope
- case *ast.ValueSpec:
- switch d.Tok {
- case token.CONST:
- if s.Values == nil {
- // create a new spec with type and values from the previous one
- if prev != nil {
- s = &ast.ValueSpec{s.Doc, s.Names, prev.Type, prev.Values, s.Comment}
- } else {
- // TODO(gri) this should probably go into the const decl code
- tc.Errorf(s.Pos(), "missing initializer for const %s", s.Names[0].Name)
- }
- }
- for _, name := range s.Names {
- tc.globals = append(tc.globals, tc.decl(ast.Con, name, s, iota))
- }
- case token.VAR:
- for _, name := range s.Names {
- tc.globals = append(tc.globals, tc.decl(ast.Var, name, s, 0))
- }
- default:
- panic("unreachable")
- }
- prev = s
- iota++
- case *ast.TypeSpec:
- obj := tc.decl(ast.Typ, s.Name, s, 0)
- tc.globals = append(tc.globals, obj)
- // give all type objects an unresolved type so
- // that we can collect methods in the type scope
- typ := NewType(Unresolved)
- obj.Type = typ
- typ.Obj = obj
- default:
- panic("unreachable")
- }
- }
-
- case *ast.FuncDecl:
- if d.Recv == nil {
- tc.globals = append(tc.globals, tc.decl(ast.Fun, d.Name, d, 0))
- }
-
- default:
- panic("unreachable")
- }
-}
-
-// If x is of the form *T, deref returns T, otherwise it returns x.
-func deref(x ast.Expr) ast.Expr {
- if p, isPtr := x.(*ast.StarExpr); isPtr {
- x = p.X
- }
- return x
-}
-
-func (tc *typechecker) bindMethod(method *ast.FuncDecl) {
- // a method is declared in the receiver base type's scope
- var scope *ast.Scope
- base := deref(method.Recv.List[0].Type)
- if name, isIdent := base.(*ast.Ident); isIdent {
- // if base is not an *ast.Ident, we had a syntax
- // error and the parser reported an error already
- obj := tc.topScope.Lookup(name.Name)
- if obj == nil {
- tc.Errorf(name.Pos(), "invalid receiver: %s is not declared in this package", name.Name)
- } else if obj.Kind != ast.Typ {
- tc.Errorf(name.Pos(), "invalid receiver: %s is not a type", name.Name)
- } else {
- typ := obj.Type.(*Type)
- assert(typ.Form == Unresolved)
- scope = typ.Scope
- }
- }
- if scope == nil {
- // no receiver type found; use a dummy scope
- // (we still want to type-check the method
- // body, so make sure there is a name object
- // and type)
- // TODO(gri) should we record the scope so
- // that we don't lose the receiver for type-
- // checking of the method body?
- scope = ast.NewScope(nil)
- }
- tc.declInScope(scope, ast.Fun, method.Name, method, 0)
-}
-
-func (tc *typechecker) resolve(obj *ast.Object) {
- // check for declaration cycles
- if tc.cyclemap[obj] {
- tc.Errorf(obj.Pos(), "illegal cycle in declaration of %s", obj.Name)
- obj.Kind = ast.Bad
- return
- }
- tc.cyclemap[obj] = true
- defer func() {
- tc.cyclemap[obj] = false, false
- }()
-
- // resolve non-type objects
- typ, _ := obj.Type.(*Type)
- if typ == nil {
- switch obj.Kind {
- case ast.Bad:
- // ignore
-
- case ast.Con:
- tc.declConst(obj)
-
- case ast.Var:
- tc.declVar(obj)
- obj.Type = tc.typeFor(nil, obj.Decl.(*ast.ValueSpec).Type, false)
-
- case ast.Fun:
- obj.Type = NewType(Function)
- t := obj.Decl.(*ast.FuncDecl).Type
- tc.declSignature(obj.Type.(*Type), nil, t.Params, t.Results)
-
- default:
- // type objects have non-nil types when resolve is called
- if debug {
- fmt.Printf("kind = %s\n", obj.Kind)
- }
- panic("unreachable")
- }
- return
- }
-
- // resolve type objects
- if typ.Form == Unresolved {
- tc.typeFor(typ, typ.Obj.Decl.(*ast.TypeSpec).Type, false)
-
- // provide types for all methods
- for _, obj := range typ.Scope.Objects {
- if obj.Kind == ast.Fun {
- assert(obj.Type == nil)
- obj.Type = NewType(Method)
- f := obj.Decl.(*ast.FuncDecl)
- t := f.Type
- tc.declSignature(obj.Type.(*Type), f.Recv, t.Params, t.Results)
- }
- }
- }
-}
-
-func (tc *typechecker) checkBlock(body []ast.Stmt, ftype *Type) {
- tc.openScope()
- defer tc.closeScope()
-
- // inject function/method parameters into block scope, if any
- if ftype != nil {
- for _, par := range ftype.Params.Objects {
- if par.Name != "_" {
- alt := tc.topScope.Insert(par)
- assert(alt == nil) // ftype has no double declarations
- }
- }
- }
-
- for _, stmt := range body {
- tc.checkStmt(stmt)
- }
-}
-
-// ----------------------------------------------------------------------------
-// Types
-
-// unparen removes parentheses around x, if any.
-func unparen(x ast.Expr) ast.Expr {
- if ux, hasParens := x.(*ast.ParenExpr); hasParens {
- return unparen(ux.X)
- }
- return x
-}
-
-func (tc *typechecker) declFields(scope *ast.Scope, fields *ast.FieldList, ref bool) (n uint) {
- if fields != nil {
- for _, f := range fields.List {
- typ := tc.typeFor(nil, f.Type, ref)
- for _, name := range f.Names {
- fld := tc.declInScope(scope, ast.Var, name, f, 0)
- fld.Type = typ
- n++
- }
- }
- }
- return n
-}
-
-func (tc *typechecker) declSignature(typ *Type, recv, params, results *ast.FieldList) {
- assert((typ.Form == Method) == (recv != nil))
- typ.Params = ast.NewScope(nil)
- tc.declFields(typ.Params, recv, true)
- tc.declFields(typ.Params, params, true)
- typ.N = tc.declFields(typ.Params, results, true)
-}
-
-func (tc *typechecker) typeFor(def *Type, x ast.Expr, ref bool) (typ *Type) {
- x = unparen(x)
-
- // type name
- if t, isIdent := x.(*ast.Ident); isIdent {
- obj := tc.find(t)
-
- if obj.Kind != ast.Typ {
- tc.Errorf(t.Pos(), "%s is not a type", t.Name)
- if def == nil {
- typ = NewType(BadType)
- } else {
- typ = def
- typ.Form = BadType
- }
- typ.Expr = x
- return
- }
-
- if !ref {
- tc.resolve(obj) // check for cycles even if type resolved
- }
- typ = obj.Type.(*Type)
-
- if def != nil {
- // new type declaration: copy type structure
- def.Form = typ.Form
- def.N = typ.N
- def.Key, def.Elt = typ.Key, typ.Elt
- def.Params = typ.Params
- def.Expr = x
- typ = def
- }
- return
- }
-
- // type literal
- typ = def
- if typ == nil {
- typ = NewType(BadType)
- }
- typ.Expr = x
-
- switch t := x.(type) {
- case *ast.SelectorExpr:
- if debug {
- fmt.Println("qualified identifier unimplemented")
- }
- typ.Form = BadType
-
- case *ast.StarExpr:
- typ.Form = Pointer
- typ.Elt = tc.typeFor(nil, t.X, true)
-
- case *ast.ArrayType:
- if t.Len != nil {
- typ.Form = Array
- // TODO(gri) compute the real length
- // (this may call resolve recursively)
- (*typ).N = 42
- } else {
- typ.Form = Slice
- }
- typ.Elt = tc.typeFor(nil, t.Elt, t.Len == nil)
-
- case *ast.StructType:
- typ.Form = Struct
- tc.declFields(typ.Scope, t.Fields, false)
-
- case *ast.FuncType:
- typ.Form = Function
- tc.declSignature(typ, nil, t.Params, t.Results)
-
- case *ast.InterfaceType:
- typ.Form = Interface
- tc.declFields(typ.Scope, t.Methods, true)
-
- case *ast.MapType:
- typ.Form = Map
- typ.Key = tc.typeFor(nil, t.Key, true)
- typ.Elt = tc.typeFor(nil, t.Value, true)
-
- case *ast.ChanType:
- typ.Form = Channel
- typ.N = uint(t.Dir)
- typ.Elt = tc.typeFor(nil, t.Value, true)
-
- default:
- if debug {
- fmt.Printf("x is %T\n", x)
- }
- panic("unreachable")
- }
-
- return
-}
-
-// ----------------------------------------------------------------------------
-// TODO(gri) implement these place holders
-
-func (tc *typechecker) declConst(*ast.Object) {
-}
-
-func (tc *typechecker) declVar(*ast.Object) {
-}
-
-func (tc *typechecker) checkStmt(ast.Stmt) {
-}
diff --git a/libgo/go/go/typechecker/typechecker_test.go b/libgo/go/go/typechecker/typechecker_test.go
deleted file mode 100644
index 4bad4499a47..00000000000
--- a/libgo/go/go/typechecker/typechecker_test.go
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file implements a simple typechecker test harness. Packages found
-// in the testDir directory are typechecked. Error messages reported by
-// the typechecker are compared against the error messages expected for
-// the test files.
-//
-// Expected errors are indicated in the test files by putting a comment
-// of the form /* ERROR "rx" */ immediately following an offending token.
-// The harness will verify that an error matching the regular expression
-// rx is reported at that source position. Consecutive comments may be
-// used to indicate multiple errors for the same token position.
-//
-// For instance, the following test file indicates that a "not declared"
-// error should be reported for the undeclared variable x:
-//
-// package P0
-// func f() {
-// _ = x /* ERROR "not declared" */ + 1
-// }
-//
-// If the -pkg flag is set, only packages with package names matching
-// the regular expression provided via the flag value are tested.
-
-package typechecker
-
-import (
- "flag"
- "fmt"
- "go/ast"
- "go/parser"
- "go/scanner"
- "go/token"
- "io/ioutil"
- "os"
- "regexp"
- "sort"
- "strings"
- "testing"
-)
-
-const testDir = "./testdata" // location of test packages
-
-var fset = token.NewFileSet()
-
-var (
- pkgPat = flag.String("pkg", ".*", "regular expression to select test packages by package name")
- trace = flag.Bool("trace", false, "print package names")
-)
-
-// ERROR comments must be of the form /* ERROR "rx" */ and rx is
-// a regular expression that matches the expected error message.
-var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`)
-
-// expectedErrors collects the regular expressions of ERROR comments
-// found in the package files of pkg and returns them in sorted order
-// (by filename and position).
-func expectedErrors(t *testing.T, pkg *ast.Package) (list scanner.ErrorList) {
- // scan all package files
- for filename := range pkg.Files {
- src, err := ioutil.ReadFile(filename)
- if err != nil {
- t.Fatalf("expectedErrors(%s): %v", pkg.Name, err)
- }
-
- var s scanner.Scanner
- file := fset.AddFile(filename, fset.Base(), len(src))
- s.Init(file, src, nil, scanner.ScanComments)
- var prev token.Pos // position of last non-comment token
- loop:
- for {
- pos, tok, lit := s.Scan()
- switch tok {
- case token.EOF:
- break loop
- case token.COMMENT:
- s := errRx.FindStringSubmatch(lit)
- if len(s) == 2 {
- list = append(list, &scanner.Error{fset.Position(prev), string(s[1])})
- }
- default:
- prev = pos
- }
- }
- }
- sort.Sort(list) // multiple files may not be sorted
- return
-}
-
-func testFilter(f *os.FileInfo) bool {
- return strings.HasSuffix(f.Name, ".src") && f.Name[0] != '.'
-}
-
-func checkError(t *testing.T, expected, found *scanner.Error) {
- rx, err := regexp.Compile(expected.Msg)
- if err != nil {
- t.Errorf("%s: %v", expected.Pos, err)
- return
- }
-
- match := rx.MatchString(found.Msg)
-
- if expected.Pos.Offset != found.Pos.Offset {
- if match {
- t.Errorf("%s: expected error should have been at %s", expected.Pos, found.Pos)
- } else {
- t.Errorf("%s: error matching %q expected", expected.Pos, expected.Msg)
- return
- }
- }
-
- if !match {
- t.Errorf("%s: %q does not match %q", expected.Pos, expected.Msg, found.Msg)
- }
-}
-
-func TestTypeCheck(t *testing.T) {
- flag.Parse()
- pkgRx, err := regexp.Compile(*pkgPat)
- if err != nil {
- t.Fatalf("illegal flag value %q: %s", *pkgPat, err)
- }
-
- pkgs, err := parser.ParseDir(fset, testDir, testFilter, 0)
- if err != nil {
- scanner.PrintError(os.Stderr, err)
- t.Fatalf("packages in %s contain syntax errors", testDir)
- }
-
- for _, pkg := range pkgs {
- if !pkgRx.MatchString(pkg.Name) {
- continue // only test selected packages
- }
-
- if *trace {
- fmt.Println(pkg.Name)
- }
-
- xlist := expectedErrors(t, pkg)
- err := CheckPackage(fset, pkg, nil)
- if err != nil {
- if elist, ok := err.(scanner.ErrorList); ok {
- // verify that errors match
- for i := 0; i < len(xlist) && i < len(elist); i++ {
- checkError(t, xlist[i], elist[i])
- }
- // the correct number or errors must have been found
- if len(xlist) != len(elist) {
- fmt.Fprintf(os.Stderr, "%s\n", pkg.Name)
- scanner.PrintError(os.Stderr, elist)
- fmt.Fprintln(os.Stderr)
- t.Errorf("TypeCheck(%s): %d errors expected but %d reported", pkg.Name, len(xlist), len(elist))
- }
- } else {
- t.Errorf("TypeCheck(%s): %v", pkg.Name, err)
- }
- } else if len(xlist) > 0 {
- t.Errorf("TypeCheck(%s): %d errors expected but 0 reported", pkg.Name, len(xlist))
- }
- }
-}
diff --git a/libgo/go/go/typechecker/universe.go b/libgo/go/go/typechecker/universe.go
deleted file mode 100644
index 81c14a05e57..00000000000
--- a/libgo/go/go/typechecker/universe.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package typechecker
-
-import "go/ast"
-
-// TODO(gri) should this be in package ast?
-
-// The Universe scope contains all predeclared identifiers.
-var Universe *ast.Scope
-
-func def(obj *ast.Object) {
- alt := Universe.Insert(obj)
- if alt != nil {
- panic("object declared twice")
- }
-}
-
-func init() {
- Universe = ast.NewScope(nil)
-
- // basic types
- for n, name := range BasicTypes {
- typ := NewType(Basic)
- typ.N = n
- obj := ast.NewObj(ast.Typ, name)
- obj.Type = typ
- typ.Obj = obj
- def(obj)
- }
-
- // built-in functions
- // TODO(gri) implement this
-}
diff --git a/libgo/go/go/types/check_test.go b/libgo/go/go/types/check_test.go
deleted file mode 100644
index 8be653fcb66..00000000000
--- a/libgo/go/go/types/check_test.go
+++ /dev/null
@@ -1,215 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file implements a typechecker test harness. The packages specified
-// in tests are typechecked. Error messages reported by the typechecker are
-// compared against the error messages expected in the test files.
-//
-// Expected errors are indicated in the test files by putting a comment
-// of the form /* ERROR "rx" */ immediately following an offending token.
-// The harness will verify that an error matching the regular expression
-// rx is reported at that source position. Consecutive comments may be
-// used to indicate multiple errors for the same token position.
-//
-// For instance, the following test file indicates that a "not declared"
-// error should be reported for the undeclared variable x:
-//
-// package p
-// func f() {
-// _ = x /* ERROR "not declared" */ + 1
-// }
-
-package types
-
-import (
- "fmt"
- "go/ast"
- "go/parser"
- "go/scanner"
- "go/token"
- "io/ioutil"
- "os"
- "regexp"
- "testing"
-)
-
-// The test filenames do not end in .go so that they are invisible
-// to gofmt since they contain comments that must not change their
-// positions relative to surrounding tokens.
-
-var tests = []struct {
- name string
- files []string
-}{
- {"test0", []string{"testdata/test0.src"}},
-}
-
-var fset = token.NewFileSet()
-
-// TODO(gri) This functionality should be in token.Fileset.
-func getFile(filename string) *token.File {
- for f := range fset.Files() {
- if f.Name() == filename {
- return f
- }
- }
- return nil
-}
-
-// TODO(gri) This functionality should be in token.Fileset.
-func getPos(filename string, offset int) token.Pos {
- if f := getFile(filename); f != nil {
- return f.Pos(offset)
- }
- return token.NoPos
-}
-
-// TODO(gri) Need to revisit parser interface. We should be able to use parser.ParseFiles
-// or a similar function instead.
-func parseFiles(t *testing.T, testname string, filenames []string) (map[string]*ast.File, os.Error) {
- files := make(map[string]*ast.File)
- var errors scanner.ErrorList
- for _, filename := range filenames {
- if _, exists := files[filename]; exists {
- t.Fatalf("%s: duplicate file %s", testname, filename)
- }
- file, err := parser.ParseFile(fset, filename, nil, parser.DeclarationErrors)
- if file == nil {
- t.Fatalf("%s: could not parse file %s", testname, filename)
- }
- files[filename] = file
- if err != nil {
- // if the parser returns a non-scanner.ErrorList error
- // the file couldn't be read in the first place and
- // file == nil; in that case we shouldn't reach here
- errors = append(errors, err.(scanner.ErrorList)...)
- }
-
- }
- return files, errors
-}
-
-// ERROR comments must be of the form /* ERROR "rx" */ and rx is
-// a regular expression that matches the expected error message.
-//
-var errRx = regexp.MustCompile(`^/\* *ERROR *"([^"]*)" *\*/$`)
-
-// expectedErrors collects the regular expressions of ERROR comments found
-// in files and returns them as a map of error positions to error messages.
-//
-func expectedErrors(t *testing.T, testname string, files map[string]*ast.File) map[token.Pos]string {
- errors := make(map[token.Pos]string)
- for filename := range files {
- src, err := ioutil.ReadFile(filename)
- if err != nil {
- t.Fatalf("%s: could not read %s", testname, filename)
- }
-
- var s scanner.Scanner
- // file was parsed already - do not add it again to the file
- // set otherwise the position information returned here will
- // not match the position information collected by the parser
- s.Init(getFile(filename), src, nil, scanner.ScanComments)
- var prev token.Pos // position of last non-comment token
-
- scanFile:
- for {
- pos, tok, lit := s.Scan()
- switch tok {
- case token.EOF:
- break scanFile
- case token.COMMENT:
- s := errRx.FindStringSubmatch(lit)
- if len(s) == 2 {
- errors[prev] = string(s[1])
- }
- default:
- prev = pos
- }
- }
- }
- return errors
-}
-
-func eliminate(t *testing.T, expected map[token.Pos]string, errors os.Error) {
- if errors == nil {
- return
- }
- for _, error := range errors.(scanner.ErrorList) {
- // error.Pos is a token.Position, but we want
- // a token.Pos so we can do a map lookup
- // TODO(gri) Need to move scanner.Errors over
- // to use token.Pos and file set info.
- pos := getPos(error.Pos.Filename, error.Pos.Offset)
- if msg, found := expected[pos]; found {
- // we expect a message at pos; check if it matches
- rx, err := regexp.Compile(msg)
- if err != nil {
- t.Errorf("%s: %v", error.Pos, err)
- continue
- }
- if match := rx.MatchString(error.Msg); !match {
- t.Errorf("%s: %q does not match %q", error.Pos, error.Msg, msg)
- continue
- }
- // we have a match - eliminate this error
- expected[pos] = "", false
- } else {
- // To keep in mind when analyzing failed test output:
- // If the same error position occurs multiple times in errors,
- // this message will be triggered (because the first error at
- // the position removes this position from the expected errors).
- t.Errorf("%s: no (multiple?) error expected, but found: %s", error.Pos, error.Msg)
- }
- }
-}
-
-func check(t *testing.T, testname string, testfiles []string) {
- // TODO(gri) Eventually all these different phases should be
- // subsumed into a single function call that takes
- // a set of files and creates a fully resolved and
- // type-checked AST.
-
- files, err := parseFiles(t, testname, testfiles)
-
- // we are expecting the following errors
- // (collect these after parsing the files so that
- // they are found in the file set)
- errors := expectedErrors(t, testname, files)
-
- // verify errors returned by the parser
- eliminate(t, errors, err)
-
- // verify errors returned after resolving identifiers
- pkg, err := ast.NewPackage(fset, files, GcImporter, Universe)
- eliminate(t, errors, err)
-
- // verify errors returned by the typechecker
- _, err = Check(fset, pkg)
- eliminate(t, errors, err)
-
- // there should be no expected errors left
- if len(errors) > 0 {
- t.Errorf("%s: %d errors not reported:", testname, len(errors))
- for pos, msg := range errors {
- t.Errorf("%s: %s\n", fset.Position(pos), msg)
- }
- }
-}
-
-func TestCheck(t *testing.T) {
- // For easy debugging w/o changing the testing code,
- // if there is a local test file, only test that file.
- const testfile = "test.go"
- if fi, err := os.Stat(testfile); err == nil && fi.IsRegular() {
- fmt.Printf("WARNING: Testing only %s (remove it to run all tests)\n", testfile)
- check(t, testfile, []string{testfile})
- return
- }
-
- // Otherwise, run all the tests.
- for _, test := range tests {
- check(t, test.name, test.files)
- }
-}
diff --git a/libgo/go/go/types/gcimporter.go b/libgo/go/go/types/gcimporter.go
deleted file mode 100644
index 6ab1806b643..00000000000
--- a/libgo/go/go/types/gcimporter.go
+++ /dev/null
@@ -1,799 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This file implements an ast.Importer for gc generated object files.
-// TODO(gri) Eventually move this into a separate package outside types.
-
-package types
-
-import (
- "big"
- "fmt"
- "go/ast"
- "go/token"
- "io"
- "os"
- "path/filepath"
- "runtime"
- "scanner"
- "strconv"
-)
-
-const trace = false // set to true for debugging
-
-var (
- pkgRoot = filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH)
- pkgExts = [...]string{".a", ".5", ".6", ".8"}
-)
-
-// findPkg returns the filename and package id for an import path.
-// If no file was found, an empty filename is returned.
-func findPkg(path string) (filename, id string) {
- if len(path) == 0 {
- return
- }
-
- id = path
- var noext string
- switch path[0] {
- default:
- // "x" -> "$GOROOT/pkg/$GOOS_$GOARCH/x.ext", "x"
- noext = filepath.Join(pkgRoot, path)
-
- case '.':
- // "./x" -> "/this/directory/x.ext", "/this/directory/x"
- cwd, err := os.Getwd()
- if err != nil {
- return
- }
- noext = filepath.Join(cwd, path)
- id = noext
-
- case '/':
- // "/x" -> "/x.ext", "/x"
- noext = path
- }
-
- // try extensions
- for _, ext := range pkgExts {
- filename = noext + ext
- if f, err := os.Stat(filename); err == nil && f.IsRegular() {
- return
- }
- }
-
- filename = "" // not found
- return
-}
-
-// gcParser parses the exports inside a gc compiler-produced
-// object/archive file and populates its scope with the results.
-type gcParser struct {
- scanner scanner.Scanner
- tok int // current token
- lit string // literal string; only valid for Ident, Int, String tokens
- id string // package id of imported package
- imports map[string]*ast.Object // package id -> package object
-}
-
-func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
- p.scanner.Init(src)
- p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
- p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
- p.scanner.Whitespace = 1<<'\t' | 1<<' '
- p.scanner.Filename = filename // for good error messages
- p.next()
- p.id = id
- p.imports = imports
-}
-
-func (p *gcParser) next() {
- p.tok = p.scanner.Scan()
- switch p.tok {
- case scanner.Ident, scanner.Int, scanner.String:
- p.lit = p.scanner.TokenText()
- default:
- p.lit = ""
- }
- if trace {
- fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
- }
-}
-
-// GcImporter implements the ast.Importer signature.
-func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, err os.Error) {
- if path == "unsafe" {
- return Unsafe, nil
- }
-
- defer func() {
- if r := recover(); r != nil {
- err = r.(importError) // will re-panic if r is not an importError
- if trace {
- panic(err) // force a stack trace
- }
- }
- }()
-
- filename, id := findPkg(path)
- if filename == "" {
- err = os.NewError("can't find import: " + id)
- return
- }
-
- if pkg = imports[id]; pkg != nil {
- return // package was imported before
- }
-
- buf, err := ExportData(filename)
- if err != nil {
- return
- }
- defer buf.Close()
-
- if trace {
- fmt.Printf("importing %s (%s)\n", id, filename)
- }
-
- var p gcParser
- p.init(filename, id, buf, imports)
- pkg = p.parseExport()
- return
-}
-
-// ----------------------------------------------------------------------------
-// Error handling
-
-// Internal errors are boxed as importErrors.
-type importError struct {
- pos scanner.Position
- err os.Error
-}
-
-func (e importError) String() string {
- return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
-}
-
-func (p *gcParser) error(err interface{}) {
- if s, ok := err.(string); ok {
- err = os.NewError(s)
- }
- // panic with a runtime.Error if err is not an os.Error
- panic(importError{p.scanner.Pos(), err.(os.Error)})
-}
-
-func (p *gcParser) errorf(format string, args ...interface{}) {
- p.error(fmt.Sprintf(format, args...))
-}
-
-func (p *gcParser) expect(tok int) string {
- lit := p.lit
- if p.tok != tok {
- p.errorf("expected %q, got %q (%q)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
- }
- p.next()
- return lit
-}
-
-func (p *gcParser) expectSpecial(tok string) {
- sep := 'x' // not white space
- i := 0
- for i < len(tok) && p.tok == int(tok[i]) && sep > ' ' {
- sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
- p.next()
- i++
- }
- if i < len(tok) {
- p.errorf("expected %q, got %q", tok, tok[0:i])
- }
-}
-
-func (p *gcParser) expectKeyword(keyword string) {
- lit := p.expect(scanner.Ident)
- if lit != keyword {
- p.errorf("expected keyword %s, got %q", keyword, lit)
- }
-}
-
-// ----------------------------------------------------------------------------
-// Import declarations
-
-// ImportPath = string_lit .
-//
-func (p *gcParser) parsePkgId() *ast.Object {
- id, err := strconv.Unquote(p.expect(scanner.String))
- if err != nil {
- p.error(err)
- }
-
- switch id {
- case "":
- // id == "" stands for the imported package id
- // (only known at time of package installation)
- id = p.id
- case "unsafe":
- // package unsafe is not in the imports map - handle explicitly
- return Unsafe
- }
-
- pkg := p.imports[id]
- if pkg == nil {
- scope = ast.NewScope(nil)
- pkg = ast.NewObj(ast.Pkg, "")
- pkg.Data = scope
- p.imports[id] = pkg
- }
-
- return pkg
-}
-
-// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
-func (p *gcParser) parseDotIdent() string {
- ident := ""
- if p.tok != scanner.Int {
- sep := 'x' // not white space
- for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
- ident += p.lit
- sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
- p.next()
- }
- }
- if ident == "" {
- p.expect(scanner.Ident) // use expect() for error handling
- }
- return ident
-}
-
-// ExportedName = ImportPath "." dotIdentifier .
-//
-func (p *gcParser) parseExportedName(kind ast.ObjKind) *ast.Object {
- pkg := p.parsePkgId()
- p.expect('.')
- name := p.parseDotIdent()
-
- // a type may have been declared before - if it exists
- // already in the respective package scope, return that
- // type
- scope := pkg.Data.(*ast.Scope)
- if kind == ast.Typ {
- if obj := scope.Lookup(name); obj != nil {
- assert(obj.Kind == ast.Typ)
- return obj
- }
- }
-
- // any other object must be a newly declared object -
- // create it and insert it into the package scope
- obj := ast.NewObj(kind, name)
- if scope.Insert(obj) != nil {
- p.errorf("already declared: %s", obj.Name)
- }
-
- // a new type object is a named type and may be referred
- // to before the underlying type is known - set it up
- if kind == ast.Typ {
- obj.Type = &Name{Obj: obj}
- }
-
- return obj
-}
-
-// ----------------------------------------------------------------------------
-// Types
-
-// BasicType = identifier .
-//
-func (p *gcParser) parseBasicType() Type {
- obj := Universe.Lookup(p.expect(scanner.Ident))
- if obj == nil || obj.Kind != ast.Typ {
- p.errorf("not a basic type: %s", obj.Name)
- }
- return obj.Type.(Type)
-}
-
-// ArrayType = "[" int_lit "]" Type .
-//
-func (p *gcParser) parseArrayType() Type {
- // "[" already consumed and lookahead known not to be "]"
- lit := p.expect(scanner.Int)
- p.expect(']')
- elt := p.parseType()
- n, err := strconv.Atoui64(lit)
- if err != nil {
- p.error(err)
- }
- return &Array{Len: n, Elt: elt}
-}
-
-// MapType = "map" "[" Type "]" Type .
-//
-func (p *gcParser) parseMapType() Type {
- p.expectKeyword("map")
- p.expect('[')
- key := p.parseType()
- p.expect(']')
- elt := p.parseType()
- return &Map{Key: key, Elt: elt}
-}
-
-// Name = identifier | "?" .
-//
-func (p *gcParser) parseName() (name string) {
- switch p.tok {
- case scanner.Ident:
- name = p.lit
- p.next()
- case '?':
- // anonymous
- p.next()
- default:
- p.error("name expected")
- }
- return
-}
-
-// Field = Name Type [ ":" string_lit ] .
-//
-func (p *gcParser) parseField() (fld *ast.Object, tag string) {
- name := p.parseName()
- ftyp := p.parseType()
- if name == "" {
- // anonymous field - ftyp must be T or *T and T must be a type name
- if _, ok := Deref(ftyp).(*Name); !ok {
- p.errorf("anonymous field expected")
- }
- }
- if p.tok == ':' {
- p.next()
- tag = p.expect(scanner.String)
- }
- fld = ast.NewObj(ast.Var, name)
- fld.Type = ftyp
- return
-}
-
-// StructType = "struct" "{" [ FieldList ] "}" .
-// FieldList = Field { ";" Field } .
-//
-func (p *gcParser) parseStructType() Type {
- var fields []*ast.Object
- var tags []string
-
- parseField := func() {
- fld, tag := p.parseField()
- fields = append(fields, fld)
- tags = append(tags, tag)
- }
-
- p.expectKeyword("struct")
- p.expect('{')
- if p.tok != '}' {
- parseField()
- for p.tok == ';' {
- p.next()
- parseField()
- }
- }
- p.expect('}')
-
- return &Struct{Fields: fields, Tags: tags}
-}
-
-// Parameter = ( identifier | "?" ) [ "..." ] Type [ ":" string_lit ] .
-//
-func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) {
- name := p.parseName()
- if name == "" {
- name = "_" // cannot access unnamed identifiers
- }
- if p.tok == '.' {
- p.expectSpecial("...")
- isVariadic = true
- }
- ptyp := p.parseType()
- // ignore argument tag
- if p.tok == ':' {
- p.next()
- p.expect(scanner.String)
- }
- par = ast.NewObj(ast.Var, name)
- par.Type = ptyp
- return
-}
-
-// Parameters = "(" [ ParameterList ] ")" .
-// ParameterList = { Parameter "," } Parameter .
-//
-func (p *gcParser) parseParameters() (list []*ast.Object, isVariadic bool) {
- parseParameter := func() {
- par, variadic := p.parseParameter()
- list = append(list, par)
- if variadic {
- if isVariadic {
- p.error("... not on final argument")
- }
- isVariadic = true
- }
- }
-
- p.expect('(')
- if p.tok != ')' {
- parseParameter()
- for p.tok == ',' {
- p.next()
- parseParameter()
- }
- }
- p.expect(')')
-
- return
-}
-
-// Signature = Parameters [ Result ] .
-// Result = Type | Parameters .
-//
-func (p *gcParser) parseSignature() *Func {
- params, isVariadic := p.parseParameters()
-
- // optional result type
- var results []*ast.Object
- switch p.tok {
- case scanner.Ident, scanner.String, '[', '*', '<':
- // single, unnamed result
- result := ast.NewObj(ast.Var, "_")
- result.Type = p.parseType()
- results = []*ast.Object{result}
- case '(':
- // named or multiple result(s)
- var variadic bool
- results, variadic = p.parseParameters()
- if variadic {
- p.error("... not permitted on result type")
- }
- }
-
- return &Func{Params: params, Results: results, IsVariadic: isVariadic}
-}
-
-// MethodSpec = identifier Signature .
-//
-func (p *gcParser) parseMethodSpec() *ast.Object {
- if p.tok == scanner.Ident {
- p.expect(scanner.Ident)
- } else {
- // TODO(gri) should this be parseExportedName here?
- p.parsePkgId()
- p.expect('.')
- p.parseDotIdent()
- }
- p.parseSignature()
-
- // TODO(gri) compute method object
- return ast.NewObj(ast.Fun, "_")
-}
-
-// InterfaceType = "interface" "{" [ MethodList ] "}" .
-// MethodList = MethodSpec { ";" MethodSpec } .
-//
-func (p *gcParser) parseInterfaceType() Type {
- var methods ObjList
-
- parseMethod := func() {
- meth := p.parseMethodSpec()
- methods = append(methods, meth)
- }
-
- p.expectKeyword("interface")
- p.expect('{')
- if p.tok != '}' {
- parseMethod()
- for p.tok == ';' {
- p.next()
- parseMethod()
- }
- }
- p.expect('}')
-
- methods.Sort()
- return &Interface{Methods: methods}
-}
-
-// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
-//
-func (p *gcParser) parseChanType() Type {
- dir := ast.SEND | ast.RECV
- if p.tok == scanner.Ident {
- p.expectKeyword("chan")
- if p.tok == '<' {
- p.expectSpecial("<-")
- dir = ast.SEND
- }
- } else {
- p.expectSpecial("<-")
- p.expectKeyword("chan")
- dir = ast.RECV
- }
- elt := p.parseType()
- return &Chan{Dir: dir, Elt: elt}
-}
-
-// Type =
-// BasicType | TypeName | ArrayType | SliceType | StructType |
-// PointerType | FuncType | InterfaceType | MapType | ChanType |
-// "(" Type ")" .
-// BasicType = ident .
-// TypeName = ExportedName .
-// SliceType = "[" "]" Type .
-// PointerType = "*" Type .
-// FuncType = "func" Signature .
-//
-func (p *gcParser) parseType() Type {
- switch p.tok {
- case scanner.Ident:
- switch p.lit {
- default:
- return p.parseBasicType()
- case "struct":
- return p.parseStructType()
- case "func":
- // FuncType
- p.next()
- return p.parseSignature()
- case "interface":
- return p.parseInterfaceType()
- case "map":
- return p.parseMapType()
- case "chan":
- return p.parseChanType()
- }
- case scanner.String:
- // TypeName
- return p.parseExportedName(ast.Typ).Type.(Type)
- case '[':
- p.next() // look ahead
- if p.tok == ']' {
- // SliceType
- p.next()
- return &Slice{Elt: p.parseType()}
- }
- return p.parseArrayType()
- case '*':
- // PointerType
- p.next()
- return &Pointer{Base: p.parseType()}
- case '<':
- return p.parseChanType()
- case '(':
- // "(" Type ")"
- p.next()
- typ := p.parseType()
- p.expect(')')
- return typ
- }
- p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
- return nil
-}
-
-// ----------------------------------------------------------------------------
-// Declarations
-
-// ImportDecl = "import" identifier string_lit .
-//
-func (p *gcParser) parseImportDecl() {
- p.expectKeyword("import")
- // The identifier has no semantic meaning in the import data.
- // It exists so that error messages can print the real package
- // name: binary.ByteOrder instead of "encoding/binary".ByteOrder.
- name := p.expect(scanner.Ident)
- pkg := p.parsePkgId()
- assert(pkg.Name == "" || pkg.Name == name)
- pkg.Name = name
-}
-
-// int_lit = [ "+" | "-" ] { "0" ... "9" } .
-//
-func (p *gcParser) parseInt() (sign, val string) {
- switch p.tok {
- case '-':
- p.next()
- sign = "-"
- case '+':
- p.next()
- }
- val = p.expect(scanner.Int)
- return
-}
-
-// number = int_lit [ "p" int_lit ] .
-//
-func (p *gcParser) parseNumber() Const {
- // mantissa
- sign, val := p.parseInt()
- mant, ok := new(big.Int).SetString(sign+val, 10)
- assert(ok)
-
- if p.lit == "p" {
- // exponent (base 2)
- p.next()
- sign, val = p.parseInt()
- exp, err := strconv.Atoui(val)
- if err != nil {
- p.error(err)
- }
- if sign == "-" {
- denom := big.NewInt(1)
- denom.Lsh(denom, exp)
- return Const{new(big.Rat).SetFrac(mant, denom)}
- }
- if exp > 0 {
- mant.Lsh(mant, exp)
- }
- return Const{new(big.Rat).SetInt(mant)}
- }
-
- return Const{mant}
-}
-
-// ConstDecl = "const" ExportedName [ Type ] "=" Literal .
-// Literal = bool_lit | int_lit | float_lit | complex_lit | string_lit .
-// bool_lit = "true" | "false" .
-// complex_lit = "(" float_lit "+" float_lit ")" .
-// string_lit = `"` { unicode_char } `"` .
-//
-func (p *gcParser) parseConstDecl() {
- p.expectKeyword("const")
- obj := p.parseExportedName(ast.Con)
- var x Const
- var typ Type
- if p.tok != '=' {
- obj.Type = p.parseType()
- }
- p.expect('=')
- switch p.tok {
- case scanner.Ident:
- // bool_lit
- if p.lit != "true" && p.lit != "false" {
- p.error("expected true or false")
- }
- x = Const{p.lit == "true"}
- typ = Bool.Underlying
- p.next()
- case '-', scanner.Int:
- // int_lit
- x = p.parseNumber()
- typ = Int.Underlying
- if _, ok := x.val.(*big.Rat); ok {
- typ = Float64.Underlying
- }
- case '(':
- // complex_lit
- p.next()
- re := p.parseNumber()
- p.expect('+')
- im := p.parseNumber()
- p.expect(')')
- x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
- typ = Complex128.Underlying
- case scanner.String:
- // string_lit
- x = MakeConst(token.STRING, p.lit)
- p.next()
- typ = String.Underlying
- default:
- p.error("expected literal")
- }
- if obj.Type == nil {
- obj.Type = typ
- }
- obj.Data = x
-}
-
-// TypeDecl = "type" ExportedName Type .
-//
-func (p *gcParser) parseTypeDecl() {
- p.expectKeyword("type")
- obj := p.parseExportedName(ast.Typ)
-
- // The type object may have been imported before and thus already
- // have a type associated with it. We still need to parse the type
- // structure, but throw it away if the object already has a type.
- // This ensures that all imports refer to the same type object for
- // a given type declaration.
- typ := p.parseType()
-
- if name := obj.Type.(*Name); name.Underlying == nil {
- assert(Underlying(typ) == typ)
- name.Underlying = typ
- }
-}
-
-// VarDecl = "var" ExportedName Type .
-//
-func (p *gcParser) parseVarDecl() {
- p.expectKeyword("var")
- obj := p.parseExportedName(ast.Var)
- obj.Type = p.parseType()
-}
-
-// FuncDecl = "func" ExportedName Signature .
-//
-func (p *gcParser) parseFuncDecl() {
- // "func" already consumed
- obj := p.parseExportedName(ast.Fun)
- obj.Type = p.parseSignature()
-}
-
-// MethodDecl = "func" Receiver identifier Signature .
-// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
-//
-func (p *gcParser) parseMethodDecl() {
- // "func" already consumed
- p.expect('(')
- p.parseParameter() // receiver
- p.expect(')')
- p.expect(scanner.Ident)
- p.parseSignature()
-}
-
-// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
-//
-func (p *gcParser) parseDecl() {
- switch p.lit {
- case "import":
- p.parseImportDecl()
- case "const":
- p.parseConstDecl()
- case "type":
- p.parseTypeDecl()
- case "var":
- p.parseVarDecl()
- case "func":
- p.next() // look ahead
- if p.tok == '(' {
- p.parseMethodDecl()
- } else {
- p.parseFuncDecl()
- }
- }
- p.expect('\n')
-}
-
-// ----------------------------------------------------------------------------
-// Export
-
-// Export = "PackageClause { Decl } "$$" .
-// PackageClause = "package" identifier [ "safe" ] "\n" .
-//
-func (p *gcParser) parseExport() *ast.Object {
- p.expectKeyword("package")
- name := p.expect(scanner.Ident)
- if p.tok != '\n' {
- // A package is safe if it was compiled with the -u flag,
- // which disables the unsafe package.
- // TODO(gri) remember "safe" package
- p.expectKeyword("safe")
- }
- p.expect('\n')
-
- assert(p.imports[p.id] == nil)
- pkg := ast.NewObj(ast.Pkg, name)
- pkg.Data = ast.NewScope(nil)
- p.imports[p.id] = pkg
-
- for p.tok != '$' && p.tok != scanner.EOF {
- p.parseDecl()
- }
-
- if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
- // don't call next()/expect() since reading past the
- // export data may cause scanner errors (e.g. NUL chars)
- p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
- }
-
- if n := p.scanner.ErrorCount; n != 0 {
- p.errorf("expected no scanner errors, got %d", n)
- }
-
- return pkg
-}
diff --git a/libgo/go/go/types/testdata/test0.src b/libgo/go/go/types/testdata/test0.src
deleted file mode 100644
index 84a1abe2701..00000000000
--- a/libgo/go/go/types/testdata/test0.src
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// type declarations
-
-package test0
-
-import "unsafe"
-
-const pi = 3.1415
-
-type (
- N undeclared /* ERROR "undeclared" */
- B bool
- I int32
- A [10]P
- T struct {
- x, y P
- }
- P *T
- R (*R)
- F func(A) I
- Y interface {
- f(A) I
- }
- S [](((P)))
- M map[I]F
- C chan<- I
-)
-
-
-type (
- p1 pi /* ERROR "not a package" */ .foo
- p2 unsafe.Pointer
-)
-
-
-type (
- Pi pi /* ERROR "not a type" */
-
- a /* DISABLED "illegal cycle" */ a
- a /* ERROR "redeclared" */ int
-
- // where the cycle error appears depends on the
- // order in which declarations are processed
- // (which depends on the order in which a map
- // is iterated through)
- b c
- c /* DISABLED "illegal cycle" */ d
- d e
- e b
-
- t *t
-
- U V
- V *W
- W U
-
- P1 *S2
- P2 P1
-
- S0 struct {
- }
- S1 struct {
- a, b, c int
- u, v, a /* ERROR "redeclared" */ float32
- }
- S2 struct {
- U // anonymous field
- // TODO(gri) recognize double-declaration below
- // U /* ERROR "redeclared" */ int
- }
- S3 struct {
- x S2
- }
- S4/* DISABLED "illegal cycle" */ struct {
- S4
- }
- S5 struct {
- S6
- }
- S6 /* DISABLED "illegal cycle" */ struct {
- field S7
- }
- S7 struct {
- S5
- }
-
- L1 []L1
- L2 []int
-
- A1 [10]int
- A2 /* DISABLED "illegal cycle" */ [10]A2
- A3 /* DISABLED "illegal cycle" */ [10]struct {
- x A4
- }
- A4 [10]A3
-
- F1 func()
- F2 func(x, y, z float32)
- F3 func(x, y, x /* ERROR "redeclared" */ float32)
- F4 func() (x, y, x /* ERROR "redeclared" */ float32)
- F5 func(x int) (x /* ERROR "redeclared" */ float32)
- F6 func(x ...int)
-
- I1 interface{}
- I2 interface {
- m1()
- }
- I3 interface {
- m1()
- m1 /* ERROR "redeclared" */ ()
- }
- I4 interface {
- m1(x, y, x /* ERROR "redeclared" */ float32)
- m2() (x, y, x /* ERROR "redeclared" */ float32)
- m3(x int) (x /* ERROR "redeclared" */ float32)
- }
- I5 interface {
- m1(I5)
- }
- I6 interface {
- S0 /* ERROR "non-interface" */
- }
- I7 interface {
- I1
- I1
- }
- I8 /* DISABLED "illegal cycle" */ interface {
- I8
- }
- I9 /* DISABLED "illegal cycle" */ interface {
- I10
- }
- I10 interface {
- I11
- }
- I11 interface {
- I9
- }
-
- C1 chan int
- C2 <-chan int
- C3 chan<- C3
- C4 chan C5
- C5 chan C6
- C6 chan C4
-
- M1 map[Last]string
- M2 map[string]M2
-
- Last int
-)
diff --git a/libgo/go/go/types/universe.go b/libgo/go/go/types/universe.go
deleted file mode 100644
index 6ae88e5f9c2..00000000000
--- a/libgo/go/go/types/universe.go
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// FILE UNDER CONSTRUCTION. ANY AND ALL PARTS MAY CHANGE.
-// This file implements the universe and unsafe package scopes.
-
-package types
-
-import "go/ast"
-
-var (
- scope *ast.Scope // current scope to use for initialization
- Universe *ast.Scope
- Unsafe *ast.Object // package unsafe
-)
-
-func define(kind ast.ObjKind, name string) *ast.Object {
- obj := ast.NewObj(kind, name)
- if scope.Insert(obj) != nil {
- panic("types internal error: double declaration")
- }
- return obj
-}
-
-func defType(name string) *Name {
- obj := define(ast.Typ, name)
- typ := &Name{Underlying: &Basic{}, Obj: obj}
- obj.Type = typ
- return typ
-}
-
-func defConst(name string) {
- obj := define(ast.Con, name)
- _ = obj // TODO(gri) fill in other properties
-}
-
-func defFun(name string) {
- obj := define(ast.Fun, name)
- _ = obj // TODO(gri) fill in other properties
-}
-
-var (
- Bool,
- Int,
- Float64,
- Complex128,
- String *Name
-)
-
-func init() {
- scope = ast.NewScope(nil)
- Universe = scope
-
- Bool = defType("bool")
- defType("byte") // TODO(gri) should be an alias for uint8
- defType("complex64")
- Complex128 = defType("complex128")
- defType("float32")
- Float64 = defType("float64")
- defType("int8")
- defType("int16")
- defType("int32")
- defType("int64")
- String = defType("string")
- defType("uint8")
- defType("uint16")
- defType("uint32")
- defType("uint64")
- Int = defType("int")
- defType("uint")
- defType("uintptr")
-
- defConst("true")
- defConst("false")
- defConst("iota")
- defConst("nil")
-
- defFun("append")
- defFun("cap")
- defFun("close")
- defFun("complex")
- defFun("copy")
- defFun("imag")
- defFun("len")
- defFun("make")
- defFun("new")
- defFun("panic")
- defFun("print")
- defFun("println")
- defFun("real")
- defFun("recover")
-
- scope = ast.NewScope(nil)
- Unsafe = ast.NewObj(ast.Pkg, "unsafe")
- Unsafe.Data = scope
-
- defType("Pointer")
-
- defFun("Alignof")
- defFun("New")
- defFun("NewArray")
- defFun("Offsetof")
- defFun("Reflect")
- defFun("Sizeof")
- defFun("Typeof")
- defFun("Unreflect")
-}
diff --git a/libgo/go/gob/codec_test.go b/libgo/go/gob/codec_test.go
index a5fb91cda78..2bcbf82a309 100644
--- a/libgo/go/gob/codec_test.go
+++ b/libgo/go/gob/codec_test.go
@@ -544,7 +544,7 @@ func TestScalarDecInstructions(t *testing.T) {
var data struct {
a []byte
}
- instr := &decInstr{decUint8Array, 6, 0, 0, ovfl}
+ instr := &decInstr{decUint8Slice, 6, 0, 0, ovfl}
state := newDecodeStateFromData(bytesResult)
execDec("bytes", instr, state, t, unsafe.Pointer(&data))
if string(data.a) != "hello" {
diff --git a/libgo/go/gob/decode.go b/libgo/go/gob/decode.go
index bf7cb95f22c..f480087836e 100644
--- a/libgo/go/gob/decode.go
+++ b/libgo/go/gob/decode.go
@@ -70,13 +70,12 @@ func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err os.Erro
if b <= 0x7f {
return uint64(b), width, nil
}
- nb := -int(int8(b))
- if nb > uint64Size {
+ n := -int(int8(b))
+ if n > uint64Size {
err = errBadUint
return
}
- var n int
- n, err = io.ReadFull(r, buf[0:nb])
+ width, err = io.ReadFull(r, buf[0:n])
if err != nil {
if err == os.EOF {
err = io.ErrUnexpectedEOF
@@ -84,11 +83,10 @@ func decodeUintReader(r io.Reader, buf []byte) (x uint64, width int, err os.Erro
return
}
// Could check that the high byte is zero but it's not worth it.
- for i := 0; i < n; i++ {
- x <<= 8
- x |= uint64(buf[i])
- width++
+ for _, b := range buf[0:width] {
+ x = x<<8 | uint64(b)
}
+ width++ // +1 for length byte
return
}
@@ -102,19 +100,18 @@ func (state *decoderState) decodeUint() (x uint64) {
if b <= 0x7f {
return uint64(b)
}
- nb := -int(int8(b))
- if nb > uint64Size {
+ n := -int(int8(b))
+ if n > uint64Size {
error(errBadUint)
}
- n, err := state.b.Read(state.buf[0:nb])
+ width, err := state.b.Read(state.buf[0:n])
if err != nil {
error(err)
}
// Don't need to check error; it's safe to loop regardless.
// Could check that the high byte is zero but it's not worth it.
- for i := 0; i < n; i++ {
- x <<= 8
- x |= uint64(state.buf[i])
+ for _, b := range state.buf[0:width] {
+ x = x<<8 | uint64(b)
}
return x
}
@@ -385,19 +382,29 @@ func decComplex128(i *decInstr, state *decoderState, p unsafe.Pointer) {
*(*complex128)(p) = complex(real, imag)
}
-// decUint8Array decodes byte array and stores through p a slice header
+// decUint8Slice decodes a byte slice and stores through p a slice header
// describing the data.
-// uint8 arrays are encoded as an unsigned count followed by the raw bytes.
-func decUint8Array(i *decInstr, state *decoderState, p unsafe.Pointer) {
+// uint8 slices are encoded as an unsigned count followed by the raw bytes.
+func decUint8Slice(i *decInstr, state *decoderState, p unsafe.Pointer) {
if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.Pointer(new([]uint8))
}
p = *(*unsafe.Pointer)(p)
}
- b := make([]uint8, state.decodeUint())
- state.b.Read(b)
- *(*[]uint8)(p) = b
+ n := int(state.decodeUint())
+ if n < 0 {
+ errorf("negative length decoding []byte")
+ }
+ slice := (*[]uint8)(p)
+ if cap(*slice) < n {
+ *slice = make([]uint8, n)
+ } else {
+ *slice = (*slice)[0:n]
+ }
+ if _, err := state.b.Read(*slice); err != nil {
+ errorf("error decoding []byte: %s", err)
+ }
}
// decString decodes byte array and stores through p a string header
@@ -457,20 +464,17 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
// decodeSingle decodes a top-level value that is not a struct and stores it through p.
// Such values are preceded by a zero, making them have the memory layout of a
// struct field (although with an illegal field number).
-func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, p uintptr) (err os.Error) {
- indir := ut.indir
- if ut.isGobDecoder {
- indir = int(ut.decIndir)
- }
- p = allocate(ut.base, p, indir)
+func (dec *Decoder) decodeSingle(engine *decEngine, ut *userTypeInfo, basep uintptr) (err os.Error) {
state := dec.newDecoderState(&dec.buf)
state.fieldnum = singletonField
- basep := p
delta := int(state.decodeUint())
if delta != 0 {
errorf("decode: corrupted data: non-zero delta for singleton")
}
instr := &engine.instr[singletonField]
+ if instr.indir != ut.indir {
+ return os.NewError("gob: internal error: inconsistent indirection")
+ }
ptr := unsafe.Pointer(basep) // offset will be zero
if instr.indir > 1 {
ptr = decIndirect(ptr, instr.indir)
@@ -653,12 +657,15 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt
}
p = *(*uintptr)(up)
}
- // Allocate storage for the slice elements, that is, the underlying array.
+ // Allocate storage for the slice elements, that is, the underlying array,
+ // if the existing slice does not have the capacity.
// Always write a header at p.
hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p))
- hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n))
+ if hdrp.Cap < n {
+ hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n))
+ hdrp.Cap = n
+ }
hdrp.Len = n
- hdrp.Cap = n
dec.decodeArrayHelper(state, hdrp.Data, elemOp, elemWid, n, elemIndir, ovfl)
}
@@ -842,7 +849,7 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
case reflect.Slice:
name = "element of " + name
if t.Elem().Kind() == reflect.Uint8 {
- op = decUint8Array
+ op = decUint8Slice
break
}
var elemId typeId
@@ -1056,10 +1063,7 @@ func (dec *Decoder) typeString(remoteId typeId) string {
// compileSingle compiles the decoder engine for a non-struct top-level value, including
// GobDecoders.
func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *decEngine, err os.Error) {
- rt := ut.base
- if ut.isGobDecoder {
- rt = ut.user
- }
+ rt := ut.user
engine = new(decEngine)
engine.instr = make([]decInstr, 1) // one item
name := rt.String() // best we can do
@@ -1150,7 +1154,7 @@ func (dec *Decoder) getDecEnginePtr(remoteId typeId, ut *userTypeInfo) (enginePt
decoderMap[remoteId] = enginePtr
*enginePtr, err = dec.compileDec(remoteId, ut)
if err != nil {
- decoderMap[remoteId] = nil, false
+ delete(decoderMap, remoteId)
}
}
return
@@ -1175,7 +1179,7 @@ func (dec *Decoder) getIgnoreEnginePtr(wireId typeId) (enginePtr **decEngine, er
*enginePtr, err = dec.compileIgnoreSingle(wireId)
}
if err != nil {
- dec.ignorerCache[wireId] = nil, false
+ delete(dec.ignorerCache, wireId)
}
}
return
@@ -1189,7 +1193,7 @@ func (dec *Decoder) decodeValue(wireId typeId, val reflect.Value) {
dec.decodeIgnoredValue(wireId)
return
}
- // Dereference down to the underlying struct type.
+ // Dereference down to the underlying type.
ut := userType(val.Type())
base := ut.base
var enginePtr **decEngine
diff --git a/libgo/go/gob/decoder.go b/libgo/go/gob/decoder.go
index 28194713225..5efcea8bc16 100644
--- a/libgo/go/gob/decoder.go
+++ b/libgo/go/gob/decoder.go
@@ -29,9 +29,15 @@ type Decoder struct {
}
// NewDecoder returns a new decoder that reads from the io.Reader.
+// If r does not also implement io.ByteReader, it will be wrapped in a
+// bufio.Reader.
func NewDecoder(r io.Reader) *Decoder {
dec := new(Decoder)
- dec.r = bufio.NewReader(r)
+ // We use the ability to read bytes as a plausible surrogate for buffering.
+ if _, ok := r.(io.ByteReader); !ok {
+ r = bufio.NewReader(r)
+ }
+ dec.r = r
dec.wireType = make(map[typeId]*wireType)
dec.decoderCache = make(map[reflect.Type]map[typeId]**decEngine)
dec.ignorerCache = make(map[typeId]**decEngine)
@@ -58,6 +64,8 @@ func (dec *Decoder) recvType(id typeId) {
dec.wireType[id] = wire
}
+var errBadCount = gobError{os.NewError("invalid message length")}
+
// recvMessage reads the next count-delimited item from the input. It is the converse
// of Encoder.writeMessage. It returns false on EOF or other error reading the message.
func (dec *Decoder) recvMessage() bool {
@@ -67,6 +75,10 @@ func (dec *Decoder) recvMessage() bool {
dec.err = err
return false
}
+ if nbytes >= 1<<31 {
+ dec.err = errBadCount
+ return false
+ }
dec.readMessage(int(nbytes))
return dec.err == nil
}
diff --git a/libgo/go/gob/doc.go b/libgo/go/gob/doc.go
index a9284ced7f9..05ebef19593 100644
--- a/libgo/go/gob/doc.go
+++ b/libgo/go/gob/doc.go
@@ -68,7 +68,10 @@ the destination variable must be able to represent the value or the decode
operation will fail.
Structs, arrays and slices are also supported. Strings and arrays of bytes are
-supported with a special, efficient representation (see below).
+supported with a special, efficient representation (see below). When a slice is
+decoded, if the existing slice has capacity the slice will be extended in place;
+if not, a new array is allocated. Regardless, the length of the resuling slice
+reports the number of elements decoded.
Functions and channels cannot be sent in a gob. Attempting
to encode a value that contains one will fail.
diff --git a/libgo/go/gob/encode.go b/libgo/go/gob/encode.go
index 317014efdad..6bb54588098 100644
--- a/libgo/go/gob/encode.go
+++ b/libgo/go/gob/encode.go
@@ -59,15 +59,14 @@ func (state *encoderState) encodeUint(x uint64) {
}
return
}
- var n, m int
- m = uint64Size
- for n = 1; x > 0; n++ {
- state.buf[m] = uint8(x)
+ i := uint64Size
+ for x > 0 {
+ state.buf[i] = uint8(x)
x >>= 8
- m--
+ i--
}
- state.buf[m] = uint8(-(n - 1))
- n, err := state.b.Write(state.buf[m : uint64Size+1])
+ state.buf[i] = uint8(i - uint64Size) // = loop count, negated
+ _, err := state.b.Write(state.buf[i : uint64Size+1])
if err != nil {
error(err)
}
@@ -454,6 +453,7 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
// should be written to b, before the encoded value.
enc.pushWriter(b)
data := new(bytes.Buffer)
+ data.Write(spaceForLength)
enc.encode(data, iv.Elem(), ut)
if enc.err != nil {
error(enc.err)
diff --git a/libgo/go/gob/encoder.go b/libgo/go/gob/encoder.go
index 96101d92bab..878d082c948 100644
--- a/libgo/go/gob/encoder.go
+++ b/libgo/go/gob/encoder.go
@@ -20,11 +20,16 @@ type Encoder struct {
sent map[reflect.Type]typeId // which types we've already sent
countState *encoderState // stage for writing counts
freeList *encoderState // list of free encoderStates; avoids reallocation
- buf []byte // for collecting the output.
byteBuf bytes.Buffer // buffer for top-level encoderState
err os.Error
}
+// Before we encode a message, we reserve space at the head of the
+// buffer in which to encode its length. This means we can use the
+// buffer to assemble the message without another allocation.
+const maxLength = 9 // Maximum size of an encoded length.
+var spaceForLength = make([]byte, maxLength)
+
// NewEncoder returns a new encoder that will transmit on the io.Writer.
func NewEncoder(w io.Writer) *Encoder {
enc := new(Encoder)
@@ -61,20 +66,22 @@ func (enc *Encoder) setError(err os.Error) {
// writeMessage sends the data item preceded by a unsigned count of its length.
func (enc *Encoder) writeMessage(w io.Writer, b *bytes.Buffer) {
- enc.countState.encodeUint(uint64(b.Len()))
- // Build the buffer.
- countLen := enc.countState.b.Len()
- total := countLen + b.Len()
- if total > len(enc.buf) {
- enc.buf = make([]byte, total+1000) // extra for growth
- }
- // Place the length before the data.
- // TODO(r): avoid the extra copy here.
- enc.countState.b.Read(enc.buf[0:countLen])
- // Now the data.
- b.Read(enc.buf[countLen:total])
+ // Space has been reserved for the length at the head of the message.
+ // This is a little dirty: we grab the slice from the bytes.Buffer and massage
+ // it by hand.
+ message := b.Bytes()
+ messageLen := len(message) - maxLength
+ // Encode the length.
+ enc.countState.b.Reset()
+ enc.countState.encodeUint(uint64(messageLen))
+ // Copy the length to be a prefix of the message.
+ offset := maxLength - enc.countState.b.Len()
+ copy(message[offset:], enc.countState.b.Bytes())
// Write the data.
- _, err := w.Write(enc.buf[0:total])
+ _, err := w.Write(message[offset:])
+ // Drain the buffer and restore the space at the front for the count of the next message.
+ b.Reset()
+ b.Write(spaceForLength)
if err != nil {
enc.setError(err)
}
@@ -224,6 +231,7 @@ func (enc *Encoder) EncodeValue(value reflect.Value) os.Error {
enc.err = nil
enc.byteBuf.Reset()
+ enc.byteBuf.Write(spaceForLength)
state := enc.newEncoderState(&enc.byteBuf)
enc.sendTypeDescriptor(enc.writer(), state, ut)
diff --git a/libgo/go/gob/encoder_test.go b/libgo/go/gob/encoder_test.go
index f5ee423cb2b..a774438d388 100644
--- a/libgo/go/gob/encoder_test.go
+++ b/libgo/go/gob/encoder_test.go
@@ -575,6 +575,91 @@ func TestGobMapInterfaceEncode(t *testing.T) {
enc := NewEncoder(buf)
err := enc.Encode(m)
if err != nil {
- t.Errorf("gob.Encode map: %s", err)
+ t.Errorf("encode map: %s", err)
+ }
+}
+
+func TestSliceReusesMemory(t *testing.T) {
+ buf := bytes.NewBuffer(nil)
+ // Bytes
+ {
+ x := []byte("abcd")
+ enc := NewEncoder(buf)
+ err := enc.Encode(x)
+ if err != nil {
+ t.Errorf("bytes: encode: %s", err)
+ }
+ // Decode into y, which is big enough.
+ y := []byte("ABCDE")
+ addr := &y[0]
+ dec := NewDecoder(buf)
+ err = dec.Decode(&y)
+ if err != nil {
+ t.Fatal("bytes: decode:", err)
+ }
+ if !bytes.Equal(x, y) {
+ t.Errorf("bytes: expected %q got %q\n", x, y)
+ }
+ if addr != &y[0] {
+ t.Errorf("bytes: unnecessary reallocation")
+ }
+ }
+ // general slice
+ {
+ x := []int("abcd")
+ enc := NewEncoder(buf)
+ err := enc.Encode(x)
+ if err != nil {
+ t.Errorf("ints: encode: %s", err)
+ }
+ // Decode into y, which is big enough.
+ y := []int("ABCDE")
+ addr := &y[0]
+ dec := NewDecoder(buf)
+ err = dec.Decode(&y)
+ if err != nil {
+ t.Fatal("ints: decode:", err)
+ }
+ if !reflect.DeepEqual(x, y) {
+ t.Errorf("ints: expected %q got %q\n", x, y)
+ }
+ if addr != &y[0] {
+ t.Errorf("ints: unnecessary reallocation")
+ }
+ }
+}
+
+// Used to crash: negative count in recvMessage.
+func TestBadCount(t *testing.T) {
+ b := []byte{0xfb, 0xa5, 0x82, 0x2f, 0xca, 0x1}
+ if err := NewDecoder(bytes.NewBuffer(b)).Decode(nil); err == nil {
+ t.Error("expected error from bad count")
+ } else if err.String() != errBadCount.String() {
+ t.Error("expected bad count error; got", err)
+ }
+}
+
+// Verify that sequential Decoders built on a single input will
+// succeed if the input implements ReadByte and there is no
+// type information in the stream.
+func TestSequentialDecoder(t *testing.T) {
+ b := new(bytes.Buffer)
+ enc := NewEncoder(b)
+ const count = 10
+ for i := 0; i < count; i++ {
+ s := fmt.Sprintf("%d", i)
+ if err := enc.Encode(s); err != nil {
+ t.Error("encoder fail:", err)
+ }
+ }
+ for i := 0; i < count; i++ {
+ dec := NewDecoder(b)
+ var s string
+ if err := dec.Decode(&s); err != nil {
+ t.Fatal("decoder fail:", err)
+ }
+ if s != fmt.Sprintf("%d", i) {
+ t.Fatalf("decode expected %d got %s", i, s)
+ }
}
}
diff --git a/libgo/go/gob/gobencdec_test.go b/libgo/go/gob/gobencdec_test.go
index 371a43c8f54..01addbe2359 100644
--- a/libgo/go/gob/gobencdec_test.go
+++ b/libgo/go/gob/gobencdec_test.go
@@ -424,7 +424,7 @@ func TestGobEncoderNonStructSingleton(t *testing.T) {
t.Fatal("decode error:", err)
}
if x != 1234 {
- t.Errorf("expected 1234 got %c", x)
+ t.Errorf("expected 1234 got %d", x)
}
}
@@ -488,3 +488,40 @@ func TestGobEncoderIgnoreNilEncoder(t *testing.T) {
t.Errorf("expected x.G = nil, got %v", x.G)
}
}
+
+type gobDecoderBug0 struct {
+ foo, bar string
+}
+
+func (br *gobDecoderBug0) String() string {
+ return br.foo + "-" + br.bar
+}
+
+func (br *gobDecoderBug0) GobEncode() ([]byte, os.Error) {
+ return []byte(br.String()), nil
+}
+
+func (br *gobDecoderBug0) GobDecode(b []byte) os.Error {
+ br.foo = "foo"
+ br.bar = "bar"
+ return nil
+}
+
+// This was a bug: the receiver has a different indirection level
+// than the variable.
+func TestGobEncoderExtraIndirect(t *testing.T) {
+ gdb := &gobDecoderBug0{"foo", "bar"}
+ buf := new(bytes.Buffer)
+ e := NewEncoder(buf)
+ if err := e.Encode(gdb); err != nil {
+ t.Fatalf("encode: %v", err)
+ }
+ d := NewDecoder(buf)
+ var got *gobDecoderBug0
+ if err := d.Decode(&got); err != nil {
+ t.Fatalf("decode: %v", err)
+ }
+ if got.foo != gdb.foo || got.bar != gdb.bar {
+ t.Errorf("got = %q, want %q", got, gdb)
+ }
+}
diff --git a/libgo/go/gob/type.go b/libgo/go/gob/type.go
index b2f716c4b5d..870101e20ca 100644
--- a/libgo/go/gob/type.go
+++ b/libgo/go/gob/type.go
@@ -405,7 +405,7 @@ func newTypeObject(name string, ut *userTypeInfo, rt reflect.Type) (gobType, os.
var type0, type1 gobType
defer func() {
if err != nil {
- types[rt] = nil, false
+ delete(types, rt)
}
}()
// Install the top-level type before the subtypes (e.g. struct before
diff --git a/libgo/go/html/escape.go b/libgo/go/html/escape.go
index 0de97c5ac1b..e9edc474da5 100644
--- a/libgo/go/html/escape.go
+++ b/libgo/go/html/escape.go
@@ -6,6 +6,7 @@ package html
import (
"bytes"
+ "os"
"strings"
"utf8"
)
@@ -182,12 +183,24 @@ func unescape(b []byte) []byte {
return b
}
+// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
+func lower(b []byte) []byte {
+ for i, c := range b {
+ if 'A' <= c && c <= 'Z' {
+ b[i] = c + 'a' - 'A'
+ }
+ }
+ return b
+}
+
const escapedChars = `&'<>"`
-func escape(buf *bytes.Buffer, s string) {
+func escape(w writer, s string) os.Error {
i := strings.IndexAny(s, escapedChars)
for i != -1 {
- buf.WriteString(s[0:i])
+ if _, err := w.WriteString(s[:i]); err != nil {
+ return err
+ }
var esc string
switch s[i] {
case '&':
@@ -204,10 +217,13 @@ func escape(buf *bytes.Buffer, s string) {
panic("unrecognized escape character")
}
s = s[i+1:]
- buf.WriteString(esc)
+ if _, err := w.WriteString(esc); err != nil {
+ return err
+ }
i = strings.IndexAny(s, escapedChars)
}
- buf.WriteString(s)
+ _, err := w.WriteString(s)
+ return err
}
// EscapeString escapes special characters like "<" to become "&lt;". It
diff --git a/libgo/go/html/parse.go b/libgo/go/html/parse.go
index 519ebe587b9..582437f7673 100644
--- a/libgo/go/html/parse.go
+++ b/libgo/go/html/parse.go
@@ -29,6 +29,9 @@ type parser struct {
head, form *Node
// Other parsing state flags (section 11.2.3.5).
scripting, framesetOK bool
+ // originalIM is the insertion mode to go back to after completing a text
+ // or inTableText insertion mode.
+ originalIM insertionMode
}
func (p *parser) top() *Node {
@@ -64,21 +67,37 @@ var (
// popUntil([]string{"html, "table"}, "table") would return true and leave:
// ["html", "body", "font"]
func (p *parser) popUntil(stopTags []string, matchTags ...string) bool {
+ if i := p.indexOfElementInScope(stopTags, matchTags...); i != -1 {
+ p.oe = p.oe[:i]
+ return true
+ }
+ return false
+}
+
+// indexOfElementInScope returns the index in p.oe of the highest element
+// whose tag is in matchTags that is in scope according to stopTags.
+// If no matching element is in scope, it returns -1.
+func (p *parser) indexOfElementInScope(stopTags []string, matchTags ...string) int {
for i := len(p.oe) - 1; i >= 0; i-- {
tag := p.oe[i].Data
for _, t := range matchTags {
if t == tag {
- p.oe = p.oe[:i]
- return true
+ return i
}
}
for _, t := range stopTags {
if t == tag {
- return false
+ return -1
}
}
}
- return false
+ return -1
+}
+
+// elementInScope is like popUntil, except that it doesn't modify the stack of
+// open elements.
+func (p *parser) elementInScope(stopTags []string, matchTags ...string) bool {
+ return p.indexOfElementInScope(stopTags, matchTags...) != -1
}
// addChild adds a child node n to the top element, and pushes n onto the stack
@@ -198,12 +217,23 @@ type insertionMode func(*parser) (insertionMode, bool)
// Section 11.2.3.1, "using the rules for".
func useTheRulesFor(p *parser, actual, delegate insertionMode) (insertionMode, bool) {
im, consumed := delegate(p)
+ // TODO: do we need to update p.originalMode if it equals delegate?
if im != delegate {
return im, consumed
}
return actual, consumed
}
+// setOriginalIM sets the insertion mode to return to after completing a text or
+// inTableText insertion mode.
+// Section 11.2.3.1, "using the rules for".
+func (p *parser) setOriginalIM(im insertionMode) {
+ if p.originalIM != nil {
+ panic("html: bad parser state: originalIM was set twice")
+ }
+ p.originalIM = im
+}
+
// Section 11.2.5.4.1.
func initialIM(p *parser) (insertionMode, bool) {
if p.tok.Type == DoctypeToken {
@@ -302,8 +332,10 @@ func inHeadIM(p *parser) (insertionMode, bool) {
switch p.tok.Data {
case "meta":
// TODO.
- case "script":
- // TODO.
+ case "script", "title":
+ p.addElement(p.tok.Data, p.tok.Attr)
+ p.setOriginalIM(inHeadIM)
+ return textIM, true
default:
implied = true
}
@@ -365,7 +397,6 @@ func afterHeadIM(p *parser) (insertionMode, bool) {
// Section 11.2.5.4.7.
func inBodyIM(p *parser) (insertionMode, bool) {
- var endP bool
switch p.tok.Type {
case TextToken:
p.reconstructActiveFormattingElements()
@@ -374,15 +405,10 @@ func inBodyIM(p *parser) (insertionMode, bool) {
case StartTagToken:
switch p.tok.Data {
case "address", "article", "aside", "blockquote", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "menu", "nav", "ol", "p", "section", "summary", "ul":
- // TODO: Do the proper "does the stack of open elements has a p element in button scope" algorithm in section 11.2.3.2.
- n := p.top()
- if n.Type == ElementNode && n.Data == "p" {
- endP = true
- } else {
- p.addElement(p.tok.Data, p.tok.Attr)
- }
+ p.popUntil(buttonScopeStopTags, "p")
+ p.addElement(p.tok.Data, p.tok.Attr)
case "h1", "h2", "h3", "h4", "h5", "h6":
- // TODO: auto-insert </p> if necessary.
+ p.popUntil(buttonScopeStopTags, "p")
switch n := p.top(); n.Data {
case "h1", "h2", "h3", "h4", "h5", "h6":
p.oe.pop()
@@ -399,6 +425,11 @@ func inBodyIM(p *parser) (insertionMode, bool) {
case "b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u":
p.reconstructActiveFormattingElements()
p.addFormattingElement(p.tok.Data, p.tok.Attr)
+ case "applet", "marquee", "object":
+ p.reconstructActiveFormattingElements()
+ p.addElement(p.tok.Data, p.tok.Attr)
+ p.afe = append(p.afe, &scopeMarker)
+ p.framesetOK = false
case "area", "br", "embed", "img", "input", "keygen", "wbr":
p.reconstructActiveFormattingElements()
p.addElement(p.tok.Data, p.tok.Attr)
@@ -406,12 +437,12 @@ func inBodyIM(p *parser) (insertionMode, bool) {
p.acknowledgeSelfClosingTag()
p.framesetOK = false
case "table":
- // TODO: auto-insert </p> if necessary, depending on quirks mode.
+ p.popUntil(buttonScopeStopTags, "p") // TODO: skip this step in quirks mode.
p.addElement(p.tok.Data, p.tok.Attr)
p.framesetOK = false
return inTableIM, true
case "hr":
- // TODO: auto-insert </p> if necessary.
+ p.popUntil(buttonScopeStopTags, "p")
p.addElement(p.tok.Data, p.tok.Attr)
p.oe.pop()
p.acknowledgeSelfClosingTag()
@@ -425,6 +456,11 @@ func inBodyIM(p *parser) (insertionMode, bool) {
case "body":
// TODO: autoclose the stack of open elements.
return afterBodyIM, true
+ case "p":
+ if !p.elementInScope(buttonScopeStopTags, "p") {
+ p.addElement("p", nil)
+ }
+ p.popUntil(buttonScopeStopTags, "p")
case "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u":
p.inBodyEndTagFormatting(p.tok.Data)
default:
@@ -434,14 +470,8 @@ func inBodyIM(p *parser) (insertionMode, bool) {
}
}
}
- if endP {
- // TODO: do the proper algorithm.
- n := p.oe.pop()
- if n.Type != ElementNode || n.Data != "p" {
- panic("unreachable")
- }
- }
- return inBodyIM, !endP
+
+ return inBodyIM, true
}
func (p *parser) inBodyEndTagFormatting(tag string) {
@@ -560,6 +590,20 @@ func (p *parser) inBodyEndTagFormatting(tag string) {
}
}
+// Section 11.2.5.4.8.
+func textIM(p *parser) (insertionMode, bool) {
+ switch p.tok.Type {
+ case TextToken:
+ p.addText(p.tok.Data)
+ return textIM, true
+ case EndTagToken:
+ p.oe.pop()
+ }
+ o := p.originalIM
+ p.originalIM = nil
+ return o, p.tok.Type == EndTagToken
+}
+
// Section 11.2.5.4.9.
func inTableIM(p *parser) (insertionMode, bool) {
var (
diff --git a/libgo/go/html/parse_test.go b/libgo/go/html/parse_test.go
index 7d918d25086..564580c78b2 100644
--- a/libgo/go/html/parse_test.go
+++ b/libgo/go/html/parse_test.go
@@ -80,13 +80,13 @@ func dumpLevel(w io.Writer, n *Node, level int) os.Error {
case DocumentNode:
return os.NewError("unexpected DocumentNode")
case ElementNode:
- fmt.Fprintf(w, "<%s>", EscapeString(n.Data))
+ fmt.Fprintf(w, "<%s>", n.Data)
case TextNode:
- fmt.Fprintf(w, "%q", EscapeString(n.Data))
+ fmt.Fprintf(w, "%q", n.Data)
case CommentNode:
return os.NewError("COMMENT")
case DoctypeNode:
- fmt.Fprintf(w, "<!DOCTYPE %s>", EscapeString(n.Data))
+ fmt.Fprintf(w, "<!DOCTYPE %s>", n.Data)
case scopeMarkerNode:
return os.NewError("unexpected scopeMarkerNode")
default:
@@ -123,7 +123,7 @@ func TestParser(t *testing.T) {
rc := make(chan io.Reader)
go readDat(filename, rc)
// TODO(nigeltao): Process all test cases, not just a subset.
- for i := 0; i < 25; i++ {
+ for i := 0; i < 27; i++ {
// Parse the #data section.
b, err := ioutil.ReadAll(<-rc)
if err != nil {
@@ -134,7 +134,7 @@ func TestParser(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- actual, err := dump(doc)
+ got, err := dump(doc)
if err != nil {
t.Fatal(err)
}
@@ -147,9 +147,26 @@ func TestParser(t *testing.T) {
if err != nil {
t.Fatal(err)
}
- expected := string(b)
- if actual != expected {
- t.Errorf("%s test #%d %q, actual vs expected:\n----\n%s----\n%s----", filename, i, text, actual, expected)
+ if want := string(b); got != want {
+ t.Errorf("%s test #%d %q, got vs want:\n----\n%s----\n%s----", filename, i, text, got, want)
+ continue
+ }
+ // Check that rendering and re-parsing results in an identical tree.
+ pr, pw := io.Pipe()
+ go func() {
+ pw.CloseWithError(Render(pw, doc))
+ }()
+ doc1, err := Parse(pr)
+ if err != nil {
+ t.Fatal(err)
+ }
+ got1, err := dump(doc1)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if got != got1 {
+ t.Errorf("%s test #%d %q, got vs got1:\n----\n%s----\n%s----", filename, i, text, got, got1)
+ continue
}
}
}
diff --git a/libgo/go/html/render.go b/libgo/go/html/render.go
new file mode 100644
index 00000000000..e1ec66ff1ac
--- /dev/null
+++ b/libgo/go/html/render.go
@@ -0,0 +1,169 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "os"
+)
+
+type writer interface {
+ io.Writer
+ WriteByte(byte) os.Error
+ WriteString(string) (int, os.Error)
+}
+
+// Render renders the parse tree n to the given writer.
+//
+// For 'well-formed' parse trees, calling Parse on the output of Render will
+// result in a clone of the original tree.
+//
+// 'Well-formed' is not formally specified, but calling Parse on arbitrary
+// input results in a 'well-formed' parse tree if Parse does not return an
+// error. Programmatically constructed trees are typically also 'well-formed',
+// but it is possible to construct a tree that, when rendered and re-parsed,
+// results in a different tree. A simple example is that a solitary text node
+// would become a tree containing <html>, <head> and <body> elements. Another
+// example is that the programmatic equivalent of "a<head>b</head>c" becomes
+// "<html><head><head/><body>abc</body></html>".
+//
+// Comment nodes are elided from the output, analogous to Parse skipping over
+// any <!--comment--> input.
+func Render(w io.Writer, n *Node) os.Error {
+ if x, ok := w.(writer); ok {
+ return render(x, n)
+ }
+ buf := bufio.NewWriter(w)
+ if err := render(buf, n); err != nil {
+ return err
+ }
+ return buf.Flush()
+}
+
+func render(w writer, n *Node) os.Error {
+ // Render non-element nodes; these are the easy cases.
+ switch n.Type {
+ case ErrorNode:
+ return os.NewError("html: cannot render an ErrorNode node")
+ case TextNode:
+ return escape(w, n.Data)
+ case DocumentNode:
+ for _, c := range n.Child {
+ if err := render(w, c); err != nil {
+ return err
+ }
+ }
+ return nil
+ case ElementNode:
+ // No-op.
+ case CommentNode:
+ return nil
+ case DoctypeNode:
+ if _, err := w.WriteString("<!DOCTYPE "); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ return w.WriteByte('>')
+ default:
+ return os.NewError("html: unknown node type")
+ }
+
+ // Render the <xxx> opening tag.
+ if err := w.WriteByte('<'); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ for _, a := range n.Attr {
+ if err := w.WriteByte(' '); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(a.Key); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(`="`); err != nil {
+ return err
+ }
+ if err := escape(w, a.Val); err != nil {
+ return err
+ }
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ }
+ if voidElements[n.Data] {
+ if len(n.Child) != 0 {
+ return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
+ }
+ _, err := w.WriteString("/>")
+ return err
+ }
+ if err := w.WriteByte('>'); err != nil {
+ return err
+ }
+
+ // Render any child nodes.
+ switch n.Data {
+ case "noembed", "noframes", "noscript", "script", "style":
+ for _, c := range n.Child {
+ if c.Type != TextNode {
+ return fmt.Errorf("html: raw text element <%s> has non-text child node", n.Data)
+ }
+ if _, err := w.WriteString(c.Data); err != nil {
+ return err
+ }
+ }
+ case "textarea", "title":
+ for _, c := range n.Child {
+ if c.Type != TextNode {
+ return fmt.Errorf("html: RCDATA element <%s> has non-text child node", n.Data)
+ }
+ if err := render(w, c); err != nil {
+ return err
+ }
+ }
+ default:
+ for _, c := range n.Child {
+ if err := render(w, c); err != nil {
+ return err
+ }
+ }
+ }
+
+ // Render the </xxx> closing tag.
+ if _, err := w.WriteString("</"); err != nil {
+ return err
+ }
+ if _, err := w.WriteString(n.Data); err != nil {
+ return err
+ }
+ return w.WriteByte('>')
+}
+
+// Section 13.1.2, "Elements", gives this list of void elements. Void elements
+// are those that can't have any contents.
+var voidElements = map[string]bool{
+ "area": true,
+ "base": true,
+ "br": true,
+ "col": true,
+ "command": true,
+ "embed": true,
+ "hr": true,
+ "img": true,
+ "input": true,
+ "keygen": true,
+ "link": true,
+ "meta": true,
+ "param": true,
+ "source": true,
+ "track": true,
+ "wbr": true,
+}
diff --git a/libgo/go/html/render_test.go b/libgo/go/html/render_test.go
new file mode 100644
index 00000000000..d166a3b8736
--- /dev/null
+++ b/libgo/go/html/render_test.go
@@ -0,0 +1,111 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package html
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestRenderer(t *testing.T) {
+ n := &Node{
+ Type: ElementNode,
+ Data: "html",
+ Child: []*Node{
+ &Node{
+ Type: ElementNode,
+ Data: "head",
+ },
+ &Node{
+ Type: ElementNode,
+ Data: "body",
+ Child: []*Node{
+ &Node{
+ Type: TextNode,
+ Data: "0<1",
+ },
+ &Node{
+ Type: ElementNode,
+ Data: "p",
+ Attr: []Attribute{
+ Attribute{
+ Key: "id",
+ Val: "A",
+ },
+ Attribute{
+ Key: "foo",
+ Val: `abc"def`,
+ },
+ },
+ Child: []*Node{
+ &Node{
+ Type: TextNode,
+ Data: "2",
+ },
+ &Node{
+ Type: ElementNode,
+ Data: "b",
+ Attr: []Attribute{
+ Attribute{
+ Key: "empty",
+ Val: "",
+ },
+ },
+ Child: []*Node{
+ &Node{
+ Type: TextNode,
+ Data: "3",
+ },
+ },
+ },
+ &Node{
+ Type: ElementNode,
+ Data: "i",
+ Attr: []Attribute{
+ Attribute{
+ Key: "backslash",
+ Val: `\`,
+ },
+ },
+ Child: []*Node{
+ &Node{
+ Type: TextNode,
+ Data: "&4",
+ },
+ },
+ },
+ },
+ },
+ &Node{
+ Type: TextNode,
+ Data: "5",
+ },
+ &Node{
+ Type: ElementNode,
+ Data: "blockquote",
+ },
+ &Node{
+ Type: ElementNode,
+ Data: "br",
+ },
+ &Node{
+ Type: TextNode,
+ Data: "6",
+ },
+ },
+ },
+ },
+ }
+ want := `<html><head></head><body>0&lt;1<p id="A" foo="abc&quot;def">` +
+ `2<b empty="">3</b><i backslash="\">&amp;4</i></p>` +
+ `5<blockquote></blockquote><br/>6</body></html>`
+ b := new(bytes.Buffer)
+ if err := Render(b, n); err != nil {
+ t.Fatal(err)
+ }
+ if got := b.String(); got != want {
+ t.Errorf("got vs want:\n%s\n%s\n", got, want)
+ }
+}
diff --git a/libgo/go/html/token.go b/libgo/go/html/token.go
index d266b3a300b..2826f95f17f 100644
--- a/libgo/go/html/token.go
+++ b/libgo/go/html/token.go
@@ -9,6 +9,7 @@ import (
"io"
"os"
"strconv"
+ "strings"
)
// A TokenType is the type of a Token.
@@ -100,13 +101,19 @@ func (t Token) String() string {
case SelfClosingTagToken:
return "<" + t.tagString() + "/>"
case CommentToken:
- return "<!--" + EscapeString(t.Data) + "-->"
+ return "<!--" + t.Data + "-->"
case DoctypeToken:
- return "<!DOCTYPE " + EscapeString(t.Data) + ">"
+ return "<!DOCTYPE " + t.Data + ">"
}
return "Invalid(" + strconv.Itoa(int(t.Type)) + ")"
}
+// span is a range of bytes in a Tokenizer's buffer. The start is inclusive,
+// the end is exclusive.
+type span struct {
+ start, end int
+}
+
// A Tokenizer returns a stream of HTML Tokens.
type Tokenizer struct {
// If ReturnComments is set, Next returns comment tokens;
@@ -115,7 +122,7 @@ type Tokenizer struct {
// r is the source of the HTML text.
r io.Reader
- // tt is the TokenType of the most recently read token.
+ // tt is the TokenType of the current token.
tt TokenType
// err is the first error encountered during tokenization. It is possible
// for tt != Error && err != nil to hold: this means that Next returned a
@@ -125,10 +132,26 @@ type Tokenizer struct {
// subsequent Next calls would return an ErrorToken.
// err is never reset. Once it becomes non-nil, it stays non-nil.
err os.Error
- // buf[p0:p1] holds the raw data of the most recent token.
- // buf[p1:] is buffered input that will yield future tokens.
- p0, p1 int
- buf []byte
+ // buf[raw.start:raw.end] holds the raw bytes of the current token.
+ // buf[raw.end:] is buffered input that will yield future tokens.
+ raw span
+ buf []byte
+ // buf[data.start:data.end] holds the raw bytes of the current token's data:
+ // a text token's text, a tag token's tag name, etc.
+ data span
+ // pendingAttr is the attribute key and value currently being tokenized.
+ // When complete, pendingAttr is pushed onto attr. nAttrReturned is
+ // incremented on each call to TagAttr.
+ pendingAttr [2]span
+ attr [][2]span
+ nAttrReturned int
+ // rawTag is the "script" in "</script>" that closes the next token. If
+ // non-empty, the subsequent call to Next will return a raw or RCDATA text
+ // token: one that treats "<p>" as text instead of an element.
+ // rawTag's contents are lower-cased.
+ rawTag string
+ // textIsRaw is whether the current text token's data is not escaped.
+ textIsRaw bool
}
// Error returns the error associated with the most recent ErrorToken token.
@@ -140,33 +163,42 @@ func (z *Tokenizer) Error() os.Error {
return z.err
}
-// Raw returns the unmodified text of the current token. Calling Next, Token,
-// Text, TagName or TagAttr may change the contents of the returned slice.
-func (z *Tokenizer) Raw() []byte {
- return z.buf[z.p0:z.p1]
-}
-
// readByte returns the next byte from the input stream, doing a buffered read
-// from z.r into z.buf if necessary. z.buf[z.p0:z.p1] remains a contiguous byte
+// from z.r into z.buf if necessary. z.buf[z.raw.start:z.raw.end] remains a contiguous byte
// slice that holds all the bytes read so far for the current token.
// It sets z.err if the underlying reader returns an error.
// Pre-condition: z.err == nil.
func (z *Tokenizer) readByte() byte {
- if z.p1 >= len(z.buf) {
+ if z.raw.end >= len(z.buf) {
// Our buffer is exhausted and we have to read from z.r.
- // We copy z.buf[z.p0:z.p1] to the beginning of z.buf. If the length
- // z.p1 - z.p0 is more than half the capacity of z.buf, then we
+ // We copy z.buf[z.raw.start:z.raw.end] to the beginning of z.buf. If the length
+ // z.raw.end - z.raw.start is more than half the capacity of z.buf, then we
// allocate a new buffer before the copy.
c := cap(z.buf)
- d := z.p1 - z.p0
+ d := z.raw.end - z.raw.start
var buf1 []byte
if 2*d > c {
buf1 = make([]byte, d, 2*c)
} else {
buf1 = z.buf[:d]
}
- copy(buf1, z.buf[z.p0:z.p1])
- z.p0, z.p1, z.buf = 0, d, buf1[:d]
+ copy(buf1, z.buf[z.raw.start:z.raw.end])
+ if x := z.raw.start; x != 0 {
+ // Adjust the data/attr spans to refer to the same contents after the copy.
+ z.data.start -= x
+ z.data.end -= x
+ z.pendingAttr[0].start -= x
+ z.pendingAttr[0].end -= x
+ z.pendingAttr[1].start -= x
+ z.pendingAttr[1].end -= x
+ for i := range z.attr {
+ z.attr[i][0].start -= x
+ z.attr[i][0].end -= x
+ z.attr[i][1].start -= x
+ z.attr[i][1].end -= x
+ }
+ }
+ z.raw.start, z.raw.end, z.buf = 0, d, buf1[:d]
// Now that we have copied the live bytes to the start of the buffer,
// we read from z.r into the remainder.
n, err := z.r.Read(buf1[d:cap(buf1)])
@@ -176,297 +208,467 @@ func (z *Tokenizer) readByte() byte {
}
z.buf = buf1[:d+n]
}
- x := z.buf[z.p1]
- z.p1++
+ x := z.buf[z.raw.end]
+ z.raw.end++
return x
}
-// readTo keeps reading bytes until x is found or a read error occurs. If an
-// error does occur, z.err is set to that error.
-// Pre-condition: z.err == nil.
-func (z *Tokenizer) readTo(x uint8) {
+// skipWhiteSpace skips past any white space.
+func (z *Tokenizer) skipWhiteSpace() {
+ if z.err != nil {
+ return
+ }
for {
c := z.readByte()
if z.err != nil {
return
}
switch c {
- case x:
+ case ' ', '\n', '\r', '\t', '\f':
+ // No-op.
+ default:
+ z.raw.end--
return
- case '\\':
- z.readByte()
+ }
+ }
+}
+
+// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and
+// is typically something like "script" or "textarea".
+func (z *Tokenizer) readRawOrRCDATA() {
+loop:
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c != '<' {
+ continue loop
+ }
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c != '/' {
+ continue loop
+ }
+ for i := 0; i < len(z.rawTag); i++ {
+ c = z.readByte()
if z.err != nil {
- return
+ break loop
+ }
+ if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') {
+ continue loop
}
}
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/', '>':
+ // The 3 is 2 for the leading "</" plus 1 for the trailing character c.
+ z.raw.end -= 3 + len(z.rawTag)
+ break loop
+ case '<':
+ // Step back one, to catch "</foo</foo>".
+ z.raw.end--
+ }
}
+ z.data.end = z.raw.end
+ // A textarea's or title's RCDATA can contain escaped entities.
+ z.textIsRaw = z.rawTag != "textarea" && z.rawTag != "title"
+ z.rawTag = ""
}
-// nextComment reads the next token starting with "<!--".
-// The opening "<!--" has already been consumed.
-// Pre-condition: z.tt == TextToken && z.err == nil && z.p0 + 4 <= z.p1.
-func (z *Tokenizer) nextComment() {
- // <!--> is a valid comment.
+// readComment reads the next comment token starting with "<!--". The opening
+// "<!--" has already been consumed.
+func (z *Tokenizer) readComment() {
+ z.data.start = z.raw.end
+ defer func() {
+ if z.data.end < z.data.start {
+ // It's a comment with no data, like <!-->.
+ z.data.end = z.data.start
+ }
+ }()
for dashCount := 2; ; {
c := z.readByte()
if z.err != nil {
+ z.data.end = z.raw.end
return
}
switch c {
case '-':
dashCount++
+ continue
case '>':
if dashCount >= 2 {
- z.tt = CommentToken
+ z.data.end = z.raw.end - len("-->")
return
}
- dashCount = 0
- default:
- dashCount = 0
+ case '!':
+ if dashCount >= 2 {
+ c = z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return
+ }
+ if c == '>' {
+ z.data.end = z.raw.end - len("--!>")
+ return
+ }
+ }
}
+ dashCount = 0
}
}
-// nextMarkupDeclaration reads the next token starting with "<!".
-// It might be a "<!--comment-->", a "<!DOCTYPE foo>", or "<!malformed text".
-// The opening "<!" has already been consumed.
-// Pre-condition: z.tt == TextToken && z.err == nil && z.p0 + 2 <= z.p1.
-func (z *Tokenizer) nextMarkupDeclaration() {
+// readUntilCloseAngle reads until the next ">".
+func (z *Tokenizer) readUntilCloseAngle() {
+ z.data.start = z.raw.end
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.data.end = z.raw.end
+ return
+ }
+ if c == '>' {
+ z.data.end = z.raw.end - len(">")
+ return
+ }
+ }
+}
+
+// readMarkupDeclaration reads the next token starting with "<!". It might be
+// a "<!--comment-->", a "<!DOCTYPE foo>", or "<!a bogus comment". The opening
+// "<!" has already been consumed.
+func (z *Tokenizer) readMarkupDeclaration() TokenType {
+ z.data.start = z.raw.end
var c [2]byte
for i := 0; i < 2; i++ {
c[i] = z.readByte()
if z.err != nil {
- return
+ z.data.end = z.raw.end
+ return CommentToken
}
}
if c[0] == '-' && c[1] == '-' {
- z.nextComment()
- return
+ z.readComment()
+ return CommentToken
}
- z.p1 -= 2
- const s = "DOCTYPE "
- for i := 0; ; i++ {
+ z.raw.end -= 2
+ const s = "DOCTYPE"
+ for i := 0; i < len(s); i++ {
c := z.readByte()
if z.err != nil {
- return
+ z.data.end = z.raw.end
+ return CommentToken
}
- // Capitalize c.
- if 'a' <= c && c <= 'z' {
- c = 'A' + (c - 'a')
- }
- if i < len(s) && c != s[i] {
- z.nextText()
- return
- }
- if c == '>' {
- if i >= len(s) {
- z.tt = DoctypeToken
- }
- return
+ if c != s[i] && c != s[i]+('a'-'A') {
+ // Back up to read the fragment of "DOCTYPE" again.
+ z.raw.end = z.data.start
+ z.readUntilCloseAngle()
+ return CommentToken
}
}
+ if z.skipWhiteSpace(); z.err != nil {
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ return DoctypeToken
+ }
+ z.readUntilCloseAngle()
+ return DoctypeToken
}
-// nextTag reads the next token starting with "<". It might be a "<startTag>",
-// an "</endTag>", a "<!markup declaration>", or "<malformed text".
-// The opening "<" has already been consumed.
-// Pre-condition: z.tt == TextToken && z.err == nil && z.p0 + 1 <= z.p1.
-func (z *Tokenizer) nextTag() {
- c := z.readByte()
- if z.err != nil {
- return
- }
- switch {
- case c == '/':
- z.tt = EndTagToken
- // Lower-cased characters are more common in tag names, so we check for them first.
- case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
- z.tt = StartTagToken
- case c == '!':
- z.nextMarkupDeclaration()
- return
- case c == '?':
- z.tt, z.err = ErrorToken, os.NewError("html: TODO: implement XML processing instructions")
- return
- default:
- z.tt, z.err = ErrorToken, os.NewError("html: TODO: handle malformed tags")
- return
+// readStartTag reads the next start tag token. The opening "<a" has already
+// been consumed, where 'a' means anything in [A-Za-z].
+func (z *Tokenizer) readStartTag() TokenType {
+ z.attr = z.attr[:0]
+ z.nAttrReturned = 0
+ // Read the tag name and attribute key/value pairs.
+ z.readTagName()
+ if z.skipWhiteSpace(); z.err != nil {
+ return ErrorToken
}
for {
c := z.readByte()
- if z.err != nil {
- return
+ if z.err != nil || c == '>' {
+ break
}
- switch c {
- case '"', '\'':
- z.readTo(c)
- if z.err != nil {
- return
- }
- case '>':
- if z.buf[z.p1-2] == '/' && z.tt == StartTagToken {
- z.tt = SelfClosingTagToken
+ z.raw.end--
+ z.readTagAttrKey()
+ z.readTagAttrVal()
+ // Save pendingAttr if it has a non-empty key.
+ if z.pendingAttr[0].start != z.pendingAttr[0].end {
+ z.attr = append(z.attr, z.pendingAttr)
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ break
+ }
+ }
+ // Any "<noembed>", "<noframes>", "<noscript>", "<script>", "<style>",
+ // "<textarea>" or "<title>" tag flags the tokenizer's next token as raw.
+ // The tag name lengths of these special cases ranges in [5, 8].
+ if x := z.data.end - z.data.start; 5 <= x && x <= 8 {
+ switch z.buf[z.data.start] {
+ case 'n', 's', 't', 'N', 'S', 'T':
+ switch s := strings.ToLower(string(z.buf[z.data.start:z.data.end])); s {
+ case "noembed", "noframes", "noscript", "script", "style", "textarea", "title":
+ z.rawTag = s
}
+ }
+ }
+ // Look for a self-closing token like "<br/>".
+ if z.err == nil && z.buf[z.raw.end-2] == '/' {
+ return SelfClosingTagToken
+ }
+ return StartTagToken
+}
+
+// readEndTag reads the next end tag token. The opening "</a" has already
+// been consumed, where 'a' means anything in [A-Za-z].
+func (z *Tokenizer) readEndTag() {
+ z.attr = z.attr[:0]
+ z.nAttrReturned = 0
+ z.readTagName()
+ for {
+ c := z.readByte()
+ if z.err != nil || c == '>' {
return
}
}
}
-// nextText reads all text up until an '<'.
-// Pre-condition: z.tt == TextToken && z.err == nil && z.p0 + 1 <= z.p1.
-func (z *Tokenizer) nextText() {
+// readTagName sets z.data to the "div" in "<div k=v>". The reader (z.raw.end)
+// is positioned such that the first byte of the tag name (the "d" in "<div")
+// has already been consumed.
+func (z *Tokenizer) readTagName() {
+ z.data.start = z.raw.end - 1
for {
c := z.readByte()
if z.err != nil {
+ z.data.end = z.raw.end
return
}
- if c == '<' {
- z.p1--
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f':
+ z.data.end = z.raw.end - 1
+ return
+ case '/', '>':
+ z.raw.end--
+ z.data.end = z.raw.end
return
}
}
}
-// Next scans the next token and returns its type.
-func (z *Tokenizer) Next() TokenType {
+// readTagAttrKey sets z.pendingAttr[0] to the "k" in "<div k=v>".
+// Precondition: z.err == nil.
+func (z *Tokenizer) readTagAttrKey() {
+ z.pendingAttr[0].start = z.raw.end
for {
- if z.err != nil {
- z.tt = ErrorToken
- return z.tt
- }
- z.p0 = z.p1
c := z.readByte()
if z.err != nil {
- z.tt = ErrorToken
- return z.tt
+ z.pendingAttr[0].end = z.raw.end
+ return
}
- // We assume that the next token is text unless proven otherwise.
- z.tt = TextToken
- if c != '<' {
- z.nextText()
- } else {
- z.nextTag()
- if z.tt == CommentToken && !z.ReturnComments {
- continue
- }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f', '/':
+ z.pendingAttr[0].end = z.raw.end - 1
+ return
+ case '=', '>':
+ z.raw.end--
+ z.pendingAttr[0].end = z.raw.end
+ return
}
- return z.tt
}
- panic("unreachable")
}
-// trim returns the largest j such that z.buf[i:j] contains only white space,
-// or only white space plus the final ">" or "/>" of the raw data.
-func (z *Tokenizer) trim(i int) int {
- k := z.p1
- for ; i < k; i++ {
- switch z.buf[i] {
- case ' ', '\n', '\t', '\f':
- continue
- case '>':
- if i == k-1 {
- return k
+// readTagAttrVal sets z.pendingAttr[1] to the "v" in "<div k=v>".
+func (z *Tokenizer) readTagAttrVal() {
+ z.pendingAttr[1].start = z.raw.end
+ z.pendingAttr[1].end = z.raw.end
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
+ c := z.readByte()
+ if z.err != nil {
+ return
+ }
+ if c != '=' {
+ z.raw.end--
+ return
+ }
+ if z.skipWhiteSpace(); z.err != nil {
+ return
+ }
+ quote := z.readByte()
+ if z.err != nil {
+ return
+ }
+ switch quote {
+ case '>':
+ z.raw.end--
+ return
+
+ case '\'', '"':
+ z.pendingAttr[1].start = z.raw.end
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.pendingAttr[1].end = z.raw.end
+ return
}
- case '/':
- if i == k-2 {
- return k
+ if c == quote {
+ z.pendingAttr[1].end = z.raw.end - 1
+ return
}
}
- return i
- }
- return k
-}
-// tagName finds the tag name at the start of z.buf[i:] and returns that name
-// lower-cased, as well as the trimmed cursor location afterwards.
-func (z *Tokenizer) tagName(i int) ([]byte, int) {
- i0 := i
-loop:
- for ; i < z.p1; i++ {
- c := z.buf[i]
- switch c {
- case ' ', '\n', '\t', '\f', '/', '>':
- break loop
- }
- if 'A' <= c && c <= 'Z' {
- z.buf[i] = c + 'a' - 'A'
+ default:
+ z.pendingAttr[1].start = z.raw.end - 1
+ for {
+ c := z.readByte()
+ if z.err != nil {
+ z.pendingAttr[1].end = z.raw.end
+ return
+ }
+ switch c {
+ case ' ', '\n', '\r', '\t', '\f':
+ z.pendingAttr[1].end = z.raw.end - 1
+ return
+ case '>':
+ z.raw.end--
+ z.pendingAttr[1].end = z.raw.end
+ return
+ }
}
}
- return z.buf[i0:i], z.trim(i)
}
-// unquotedAttrVal finds the unquoted attribute value at the start of z.buf[i:]
-// and returns that value, as well as the trimmed cursor location afterwards.
-func (z *Tokenizer) unquotedAttrVal(i int) ([]byte, int) {
- i0 := i
+// next scans the next token and returns its type.
+func (z *Tokenizer) next() TokenType {
+ if z.err != nil {
+ return ErrorToken
+ }
+ z.raw.start = z.raw.end
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ if z.rawTag != "" {
+ z.readRawOrRCDATA()
+ return TextToken
+ }
+ z.textIsRaw = false
+
loop:
- for ; i < z.p1; i++ {
- switch z.buf[i] {
- case ' ', '\n', '\t', '\f', '>':
+ for {
+ c := z.readByte()
+ if z.err != nil {
break loop
- case '&':
- // TODO: unescape the entity.
}
- }
- return z.buf[i0:i], z.trim(i)
-}
-
-// attrName finds the largest attribute name at the start
-// of z.buf[i:] and returns it lower-cased, as well
-// as the trimmed cursor location after that name.
-//
-// http://dev.w3.org/html5/spec/Overview.html#syntax-attribute-name
-// TODO: unicode characters
-func (z *Tokenizer) attrName(i int) ([]byte, int) {
- for z.buf[i] == '/' {
- i++
- if z.buf[i] == '>' {
- return nil, z.trim(i)
+ if c != '<' {
+ continue loop
}
- }
- i0 := i
-loop:
- for ; i < z.p1; i++ {
- c := z.buf[i]
- switch c {
- case '>', '/', '=':
+
+ // Check if the '<' we have just read is part of a tag, comment
+ // or doctype. If not, it's part of the accumulated text token.
+ c = z.readByte()
+ if z.err != nil {
break loop
}
+ var tokenType TokenType
switch {
- case 'A' <= c && c <= 'Z':
- z.buf[i] = c + 'a' - 'A'
- case c > ' ' && c < 0x7f:
- // No-op.
+ case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
+ tokenType = StartTagToken
+ case c == '/':
+ tokenType = EndTagToken
+ case c == '!' || c == '?':
+ // We use CommentToken to mean any of "<!--actual comments-->",
+ // "<!DOCTYPE declarations>" and "<?xml processing instructions?>".
+ tokenType = CommentToken
default:
- break loop
+ continue
+ }
+
+ // We have a non-text token, but we might have accumulated some text
+ // before that. If so, we return the text first, and return the non-
+ // text token on the subsequent call to Next.
+ if x := z.raw.end - len("<a"); z.raw.start < x {
+ z.raw.end = x
+ z.data.end = x
+ return TextToken
+ }
+ switch tokenType {
+ case StartTagToken:
+ return z.readStartTag()
+ case EndTagToken:
+ c = z.readByte()
+ if z.err != nil {
+ break loop
+ }
+ if c == '>' {
+ // "</>" does not generate a token at all.
+ // Reset the tokenizer state and start again.
+ z.raw.start = z.raw.end
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ continue loop
+ }
+ if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
+ z.readEndTag()
+ return EndTagToken
+ }
+ z.raw.end--
+ z.readUntilCloseAngle()
+ return CommentToken
+ case CommentToken:
+ if c == '!' {
+ return z.readMarkupDeclaration()
+ }
+ z.raw.end--
+ z.readUntilCloseAngle()
+ return CommentToken
+ }
+ }
+ if z.raw.start < z.raw.end {
+ z.data.end = z.raw.end
+ return TextToken
+ }
+ return ErrorToken
+}
+
+// Next scans the next token and returns its type.
+func (z *Tokenizer) Next() TokenType {
+ for {
+ z.tt = z.next()
+ // TODO: remove the ReturnComments option. A tokenizer should
+ // always return comment tags.
+ if z.tt == CommentToken && !z.ReturnComments {
+ continue
}
+ return z.tt
}
- return z.buf[i0:i], z.trim(i)
+ panic("unreachable")
+}
+
+// Raw returns the unmodified text of the current token. Calling Next, Token,
+// Text, TagName or TagAttr may change the contents of the returned slice.
+func (z *Tokenizer) Raw() []byte {
+ return z.buf[z.raw.start:z.raw.end]
}
// Text returns the unescaped text of a text, comment or doctype token. The
// contents of the returned slice may change on the next call to Next.
func (z *Tokenizer) Text() []byte {
- var i0, i1 int
switch z.tt {
- case TextToken:
- i0 = z.p0
- i1 = z.p1
- case CommentToken:
- // Trim the "<!--" from the left and the "-->" from the right.
- // "<!-->" is a valid comment, so the adjusted endpoints might overlap.
- i0 = z.p0 + 4
- i1 = z.p1 - 3
- case DoctypeToken:
- // Trim the "<!DOCTYPE " from the left and the ">" from the right.
- i0 = z.p0 + 10
- i1 = z.p1 - 1
- default:
- return nil
- }
- z.p0 = z.p1
- if i0 < i1 {
- return unescape(z.buf[i0:i1])
+ case TextToken, CommentToken, DoctypeToken:
+ s := z.buf[z.data.start:z.data.end]
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ if !z.textIsRaw {
+ s = unescape(s)
+ }
+ return s
}
return nil
}
@@ -475,73 +677,33 @@ func (z *Tokenizer) Text() []byte {
// `<IMG SRC="foo">`) and whether the tag has attributes.
// The contents of the returned slice may change on the next call to Next.
func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
- i := z.p0 + 1
- if i >= z.p1 {
- z.p0 = z.p1
- return nil, false
- }
- if z.buf[i] == '/' {
- i++
+ if z.data.start < z.data.end {
+ switch z.tt {
+ case StartTagToken, EndTagToken, SelfClosingTagToken:
+ s := z.buf[z.data.start:z.data.end]
+ z.data.start = z.raw.end
+ z.data.end = z.raw.end
+ return lower(s), z.nAttrReturned < len(z.attr)
+ }
}
- name, z.p0 = z.tagName(i)
- hasAttr = z.p0 != z.p1
- return
+ return nil, false
}
// TagAttr returns the lower-cased key and unescaped value of the next unparsed
// attribute for the current tag token and whether there are more attributes.
// The contents of the returned slices may change on the next call to Next.
func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
- key, i := z.attrName(z.p0)
- // Check for an empty attribute value.
- if i == z.p1 {
- z.p0 = i
- return
- }
- // Get past the equals and quote characters.
- if z.buf[i] != '=' {
- z.p0, moreAttr = i, true
- return
- }
- i = z.trim(i + 1)
- if i == z.p1 {
- z.p0 = i
- return
- }
- closeQuote := z.buf[i]
- if closeQuote != '\'' && closeQuote != '"' {
- val, z.p0 = z.unquotedAttrVal(i)
- moreAttr = z.p0 != z.p1
- return
- }
- i = z.trim(i + 1)
- // Copy and unescape everything up to the closing quote.
- dst, src := i, i
-loop:
- for src < z.p1 {
- c := z.buf[src]
- switch c {
- case closeQuote:
- src++
- break loop
- case '&':
- dst, src = unescapeEntity(z.buf, dst, src, true)
- case '\\':
- if src == z.p1 {
- z.buf[dst] = '\\'
- dst++
- } else {
- z.buf[dst] = z.buf[src+1]
- dst, src = dst+1, src+2
- }
- default:
- z.buf[dst] = c
- dst, src = dst+1, src+1
+ if z.nAttrReturned < len(z.attr) {
+ switch z.tt {
+ case StartTagToken, SelfClosingTagToken:
+ x := z.attr[z.nAttrReturned]
+ z.nAttrReturned++
+ key = z.buf[x[0].start:x[0].end]
+ val = z.buf[x[1].start:x[1].end]
+ return lower(key), unescape(val), z.nAttrReturned < len(z.attr)
}
}
- val, z.p0 = z.buf[i:dst], z.trim(src)
- moreAttr = z.p0 != z.p1
- return
+ return nil, nil, false
}
// Token returns the next Token. The result's Data and Attr values remain valid
@@ -551,7 +713,7 @@ func (z *Tokenizer) Token() Token {
switch z.tt {
case TextToken, CommentToken, DoctypeToken:
t.Data = string(z.Text())
- case StartTagToken, EndTagToken, SelfClosingTagToken:
+ case StartTagToken, SelfClosingTagToken:
var attr []Attribute
name, moreAttr := z.TagName()
for moreAttr {
@@ -561,6 +723,9 @@ func (z *Tokenizer) Token() Token {
}
t.Data = string(name)
t.Attr = attr
+ case EndTagToken:
+ name, _ := z.TagName()
+ t.Data = string(name)
}
return t
}
diff --git a/libgo/go/html/token_test.go b/libgo/go/html/token_test.go
index 0a0beb201b3..310cd97d670 100644
--- a/libgo/go/html/token_test.go
+++ b/libgo/go/html/token_test.go
@@ -21,6 +21,11 @@ type tokenTest struct {
}
var tokenTests = []tokenTest{
+ {
+ "empty",
+ "",
+ "",
+ },
// A single text node. The tokenizer should not break text nodes on whitespace,
// nor should it normalize whitespace within a text node.
{
@@ -41,6 +46,88 @@ var tokenTests = []tokenTest{
"<a>b<c/>d</e>",
"<a>$b$<c/>$d$</e>",
},
+ // Angle brackets that aren't a tag.
+ {
+ "not a tag #0",
+ "<",
+ "&lt;",
+ },
+ {
+ "not a tag #1",
+ "</",
+ "&lt;/",
+ },
+ {
+ "not a tag #2",
+ "</>",
+ "",
+ },
+ {
+ "not a tag #3",
+ "a</>b",
+ "a$b",
+ },
+ {
+ "not a tag #4",
+ "</ >",
+ "<!-- -->",
+ },
+ {
+ "not a tag #5",
+ "</.",
+ "<!--.-->",
+ },
+ {
+ "not a tag #6",
+ "</.>",
+ "<!--.-->",
+ },
+ {
+ "not a tag #7",
+ "a < b",
+ "a &lt; b",
+ },
+ {
+ "not a tag #8",
+ "<.>",
+ "&lt;.&gt;",
+ },
+ {
+ "not a tag #9",
+ "a<<<b>>>c",
+ "a&lt;&lt;$<b>$&gt;&gt;c",
+ },
+ {
+ "not a tag #10",
+ "if x<0 and y < 0 then x*y>0",
+ "if x&lt;0 and y &lt; 0 then x*y&gt;0",
+ },
+ // EOF in a tag name.
+ {
+ "tag name eof #0",
+ "<a",
+ "",
+ },
+ {
+ "tag name eof #1",
+ "<a ",
+ "",
+ },
+ {
+ "tag name eof #2",
+ "a<b",
+ "a",
+ },
+ {
+ "tag name eof #3",
+ "<a><b",
+ "<a>",
+ },
+ {
+ "tag name eof #4",
+ `<a x`,
+ `<a x="">`,
+ },
// Some malformed tags that are missing a '>'.
{
"malformed tag #0",
@@ -54,70 +141,198 @@ var tokenTests = []tokenTest{
},
{
"malformed tag #2",
+ `<p id`,
+ `<p id="">`,
+ },
+ {
+ "malformed tag #3",
+ `<p id=`,
+ `<p id="">`,
+ },
+ {
+ "malformed tag #4",
+ `<p id=>`,
+ `<p id="">`,
+ },
+ {
+ "malformed tag #5",
+ `<p id=0`,
+ `<p id="0">`,
+ },
+ {
+ "malformed tag #6",
`<p id=0</p>`,
`<p id="0&lt;/p">`,
},
{
- "malformed tag #3",
+ "malformed tag #7",
`<p id="0</p>`,
`<p id="0&lt;/p&gt;">`,
},
{
- "malformed tag #4",
+ "malformed tag #8",
`<p id="0"</p>`,
`<p id="0" <="" p="">`,
},
+ // Raw text and RCDATA.
+ {
+ "basic raw text",
+ "<script><a></b></script>",
+ "<script>$&lt;a&gt;&lt;/b&gt;$</script>",
+ },
+ {
+ "unfinished script end tag",
+ "<SCRIPT>a</SCR",
+ "<script>$a&lt;/SCR",
+ },
+ {
+ "broken script end tag",
+ "<SCRIPT>a</SCR ipt>",
+ "<script>$a&lt;/SCR ipt&gt;",
+ },
+ {
+ "EOF in script end tag",
+ "<SCRIPT>a</SCRipt",
+ "<script>$a&lt;/SCRipt",
+ },
+ {
+ "scriptx end tag",
+ "<SCRIPT>a</SCRiptx",
+ "<script>$a&lt;/SCRiptx",
+ },
+ {
+ "' ' completes script end tag",
+ "<SCRIPT>a</SCRipt ",
+ "<script>$a$</script>",
+ },
+ {
+ "'>' completes script end tag",
+ "<SCRIPT>a</SCRipt>",
+ "<script>$a$</script>",
+ },
+ {
+ "self-closing script end tag",
+ "<SCRIPT>a</SCRipt/>",
+ "<script>$a$</script>",
+ },
+ {
+ "nested script tag",
+ "<SCRIPT>a</SCRipt<script>",
+ "<script>$a&lt;/SCRipt&lt;script&gt;",
+ },
+ {
+ "script end tag after unfinished",
+ "<SCRIPT>a</SCRipt</script>",
+ "<script>$a&lt;/SCRipt$</script>",
+ },
+ {
+ "script/style mismatched tags",
+ "<script>a</style>",
+ "<script>$a&lt;/style&gt;",
+ },
+ {
+ "style element with entity",
+ "<style>&apos;",
+ "<style>$&amp;apos;",
+ },
+ {
+ "textarea with tag",
+ "<textarea><div></textarea>",
+ "<textarea>$&lt;div&gt;$</textarea>",
+ },
+ {
+ "title with tag and entity",
+ "<title><b>K&amp;R C</b></title>",
+ "<title>$&lt;b&gt;K&amp;R C&lt;/b&gt;$</title>",
+ },
+ // DOCTYPE tests.
+ {
+ "Proper DOCTYPE",
+ "<!DOCTYPE html>",
+ "<!DOCTYPE html>",
+ },
+ {
+ "DOCTYPE with no space",
+ "<!doctypehtml>",
+ "<!DOCTYPE html>",
+ },
+ {
+ "DOCTYPE with two spaces",
+ "<!doctype html>",
+ "<!DOCTYPE html>",
+ },
+ {
+ "looks like DOCTYPE but isn't",
+ "<!DOCUMENT html>",
+ "<!--DOCUMENT html-->",
+ },
+ {
+ "DOCTYPE at EOF",
+ "<!DOCtype",
+ "<!DOCTYPE >",
+ },
+ // XML processing instructions.
+ {
+ "XML processing instruction",
+ "<?xml?>",
+ "<!--?xml?-->",
+ },
// Comments.
{
"comment0",
"abc<b><!-- skipme --></b>def",
- "abc$<b>$</b>$def",
+ "abc$<b>$<!-- skipme -->$</b>$def",
},
{
"comment1",
"a<!-->z",
- "a$z",
+ "a$<!---->$z",
},
{
"comment2",
"a<!--->z",
- "a$z",
+ "a$<!---->$z",
},
{
"comment3",
"a<!--x>-->z",
- "a$z",
+ "a$<!--x>-->$z",
},
{
"comment4",
"a<!--x->-->z",
- "a$z",
+ "a$<!--x->-->$z",
},
{
"comment5",
"a<!>z",
- "a$&lt;!&gt;z",
+ "a$<!---->$z",
},
{
"comment6",
"a<!->z",
- "a$&lt;!-&gt;z",
+ "a$<!----->$z",
},
{
"comment7",
"a<!---<>z",
- "a$&lt;!---&lt;&gt;z",
+ "a$<!---<>z-->",
},
{
"comment8",
"a<!--z",
- "a$&lt;!--z",
+ "a$<!--z-->",
+ },
+ {
+ "comment9",
+ "a<!--x--!>z",
+ "a$<!--x-->$z",
},
// An attribute with a backslash.
{
"backslash",
`<p id="a\"b">`,
- `<p id="a&quot;b">`,
+ `<p id="a\" b"="">`,
},
// Entities, tag name and attribute key lower-casing, and whitespace
// normalization within a tag.
@@ -133,11 +348,14 @@ var tokenTests = []tokenTest{
`<a b="c&noSuchEntity;d">&lt;&alsoDoesntExist;&`,
`<a b="c&amp;noSuchEntity;d">$&lt;&amp;alsoDoesntExist;&amp;`,
},
- {
- "entity without semicolon",
- `&notit;&notin;<a b="q=z&amp=5&notice=hello&not;=world">`,
- `¬it;∉$<a b="q=z&amp;amp=5&amp;notice=hello¬=world">`,
- },
+ /*
+ // TODO: re-enable this test when it works. This input/output matches html5lib's behavior.
+ {
+ "entity without semicolon",
+ `&notit;&notin;<a b="q=z&amp=5&notice=hello&not;=world">`,
+ `¬it;∉$<a b="q=z&amp;amp=5&amp;notice=hello¬=world">`,
+ },
+ */
{
"entity with digits",
"&frac12;",
@@ -190,21 +408,34 @@ var tokenTests = []tokenTest{
`<meta http-equiv="content-type">`,
`<meta http-equiv="content-type">`,
},
+ {
+ "Mixed attributes",
+ `a<P V="0 1" w='2' X=3 y>z`,
+ `a$<p v="0 1" w="2" x="3" y="">$z`,
+ },
+ {
+ "Attributes with a solitary single quote",
+ `<p id=can't><p id=won't>`,
+ `<p id="can&apos;t">$<p id="won&apos;t">`,
+ },
}
func TestTokenizer(t *testing.T) {
loop:
for _, tt := range tokenTests {
- z := NewTokenizer(bytes.NewBuffer([]byte(tt.html)))
- for i, s := range strings.Split(tt.golden, "$") {
- if z.Next() == ErrorToken {
- t.Errorf("%s token %d: want %q got error %v", tt.desc, i, s, z.Error())
- continue loop
- }
- actual := z.Token().String()
- if s != actual {
- t.Errorf("%s token %d: want %q got %q", tt.desc, i, s, actual)
- continue loop
+ z := NewTokenizer(strings.NewReader(tt.html))
+ z.ReturnComments = true
+ if tt.golden != "" {
+ for i, s := range strings.Split(tt.golden, "$") {
+ if z.Next() == ErrorToken {
+ t.Errorf("%s token %d: want %q got error %v", tt.desc, i, s, z.Error())
+ continue loop
+ }
+ actual := z.Token().String()
+ if s != actual {
+ t.Errorf("%s token %d: want %q got %q", tt.desc, i, s, actual)
+ continue loop
+ }
}
}
z.Next()
diff --git a/libgo/go/http/cgi/child.go b/libgo/go/http/cgi/child.go
index 8d0eca8d55b..bf14c04a843 100644
--- a/libgo/go/http/cgi/child.go
+++ b/libgo/go/http/cgi/child.go
@@ -93,20 +93,20 @@ func RequestFromMap(params map[string]string) (*http.Request, os.Error) {
if r.Host != "" {
// Hostname is provided, so we can reasonably construct a URL,
// even if we have to assume 'http' for the scheme.
- r.RawURL = "http://" + r.Host + params["REQUEST_URI"]
- url, err := url.Parse(r.RawURL)
+ rawurl := "http://" + r.Host + params["REQUEST_URI"]
+ url, err := url.Parse(rawurl)
if err != nil {
- return nil, os.NewError("cgi: failed to parse host and REQUEST_URI into a URL: " + r.RawURL)
+ return nil, os.NewError("cgi: failed to parse host and REQUEST_URI into a URL: " + rawurl)
}
r.URL = url
}
// Fallback logic if we don't have a Host header or the URL
// failed to parse
if r.URL == nil {
- r.RawURL = params["REQUEST_URI"]
- url, err := url.Parse(r.RawURL)
+ uriStr := params["REQUEST_URI"]
+ url, err := url.Parse(uriStr)
if err != nil {
- return nil, os.NewError("cgi: failed to parse REQUEST_URI into a URL: " + r.RawURL)
+ return nil, os.NewError("cgi: failed to parse REQUEST_URI into a URL: " + uriStr)
}
r.URL = url
}
diff --git a/libgo/go/http/cgi/child_test.go b/libgo/go/http/cgi/child_test.go
index eee043bc90d..ec53ab851ba 100644
--- a/libgo/go/http/cgi/child_test.go
+++ b/libgo/go/http/cgi/child_test.go
@@ -49,9 +49,6 @@ func TestRequest(t *testing.T) {
if g, e := req.Header.Get("Foo-Bar"), "baz"; e != g {
t.Errorf("expected Foo-Bar %q; got %q", e, g)
}
- if g, e := req.RawURL, "http://example.com/path?a=b"; e != g {
- t.Errorf("expected RawURL %q; got %q", e, g)
- }
if g, e := req.URL.String(), "http://example.com/path?a=b"; e != g {
t.Errorf("expected URL %q; got %q", e, g)
}
@@ -81,9 +78,6 @@ func TestRequestWithoutHost(t *testing.T) {
if err != nil {
t.Fatalf("RequestFromMap: %v", err)
}
- if g, e := req.RawURL, "/path?a=b"; e != g {
- t.Errorf("expected RawURL %q; got %q", e, g)
- }
if req.URL == nil {
t.Fatalf("unexpected nil URL")
}
diff --git a/libgo/go/http/cgi/host.go b/libgo/go/http/cgi/host.go
index f7de89f9974..9ea4c9d8bf2 100644
--- a/libgo/go/http/cgi/host.go
+++ b/libgo/go/http/cgi/host.go
@@ -32,13 +32,14 @@ import (
var trailingPort = regexp.MustCompile(`:([0-9]+)$`)
var osDefaultInheritEnv = map[string][]string{
- "darwin": []string{"DYLD_LIBRARY_PATH"},
- "freebsd": []string{"LD_LIBRARY_PATH"},
- "hpux": []string{"LD_LIBRARY_PATH", "SHLIB_PATH"},
- "irix": []string{"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"},
- "linux": []string{"LD_LIBRARY_PATH"},
- "solaris": []string{"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"},
- "windows": []string{"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"},
+ "darwin": {"DYLD_LIBRARY_PATH"},
+ "freebsd": {"LD_LIBRARY_PATH"},
+ "hpux": {"LD_LIBRARY_PATH", "SHLIB_PATH"},
+ "irix": {"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"},
+ "linux": {"LD_LIBRARY_PATH"},
+ "openbsd": {"LD_LIBRARY_PATH"},
+ "solaris": {"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"},
+ "windows": {"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"},
}
// Handler runs an executable in a subprocess with a CGI environment.
@@ -68,6 +69,31 @@ type Handler struct {
PathLocationHandler http.Handler
}
+// removeLeadingDuplicates remove leading duplicate in environments.
+// It's possible to override environment like following.
+// cgi.Handler{
+// ...
+// Env: []string{"SCRIPT_FILENAME=foo.php"},
+// }
+func removeLeadingDuplicates(env []string) (ret []string) {
+ n := len(env)
+ for i := 0; i < n; i++ {
+ e := env[i]
+ s := strings.SplitN(e, "=", 2)[0]
+ found := false
+ for j := i + 1; j < n; j++ {
+ if s == strings.SplitN(env[j], "=", 2)[0] {
+ found = true
+ break
+ }
+ }
+ if !found {
+ ret = append(ret, e)
+ }
+ }
+ return
+}
+
func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
root := h.Root
if root == "" {
@@ -149,6 +175,8 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}
}
+ env = removeLeadingDuplicates(env)
+
var cwd, path string
if h.Dir != "" {
path = h.Path
@@ -294,7 +322,6 @@ func (h *Handler) handleInternalRedirect(rw http.ResponseWriter, req *http.Reque
newReq := &http.Request{
Method: "GET",
URL: url,
- RawURL: path,
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
diff --git a/libgo/go/http/cgi/host_test.go b/libgo/go/http/cgi/host_test.go
index ff46631383b..6c0f1a09747 100644
--- a/libgo/go/http/cgi/host_test.go
+++ b/libgo/go/http/cgi/host_test.go
@@ -451,3 +451,32 @@ func TestDirWindows(t *testing.T) {
}
runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
}
+
+func TestEnvOverride(t *testing.T) {
+ cgifile, _ := filepath.Abs("testdata/test.cgi")
+
+ var perl string
+ var err os.Error
+ perl, err = exec.LookPath("perl")
+ if err != nil {
+ return
+ }
+ perl, _ = filepath.Abs(perl)
+
+ cwd, _ := os.Getwd()
+ h := &Handler{
+ Path: perl,
+ Root: "/test.cgi",
+ Dir: cwd,
+ Args: []string{cgifile},
+ Env: []string{
+ "SCRIPT_FILENAME=" + cgifile,
+ "REQUEST_URI=/foo/bar"},
+ }
+ expectedMap := map[string]string{
+ "cwd": cwd,
+ "env-SCRIPT_FILENAME": cgifile,
+ "env-REQUEST_URI": "/foo/bar",
+ }
+ runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
diff --git a/libgo/go/http/chunked.go b/libgo/go/http/chunked.go
index 6c23e691f02..eff9ae288ea 100644
--- a/libgo/go/http/chunked.go
+++ b/libgo/go/http/chunked.go
@@ -5,11 +5,11 @@
package http
import (
+ "bufio"
"io"
"log"
"os"
"strconv"
- "bufio"
)
// NewChunkedWriter returns a new writer that translates writes into HTTP
diff --git a/libgo/go/http/client.go b/libgo/go/http/client.go
index 44b3443fc40..3fa4a056ad8 100644
--- a/libgo/go/http/client.go
+++ b/libgo/go/http/client.go
@@ -56,9 +56,10 @@ type RoundTripper interface {
// higher-level protocol details such as redirects,
// authentication, or cookies.
//
- // RoundTrip may modify the request. The request Headers field is
- // guaranteed to be initialized.
- RoundTrip(req *Request) (resp *Response, err os.Error)
+ // RoundTrip should not modify the request, except for
+ // consuming the Body. The request's URL and Header fields
+ // are guaranteed to be initialized.
+ RoundTrip(*Request) (*Response, os.Error)
}
// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
@@ -76,7 +77,12 @@ type readClose struct {
// Do sends an HTTP request and returns an HTTP response, following
// policy (e.g. redirects, cookies, auth) as configured on the client.
//
-// Callers should close resp.Body when done reading from it.
+// A non-nil response always contains a non-nil resp.Body.
+//
+// Callers should close resp.Body when done reading from it. If
+// resp.Body is not closed, the Client's underlying RoundTripper
+// (typically Transport) may not be able to re-use a persistent TCP
+// connection to the server for a subsequent "keep-alive" request.
//
// Generally Get, Post, or PostForm will be used instead of Do.
func (c *Client) Do(req *Request) (resp *Response, err os.Error) {
@@ -91,11 +97,15 @@ func send(req *Request, t RoundTripper) (resp *Response, err os.Error) {
if t == nil {
t = DefaultTransport
if t == nil {
- err = os.NewError("no http.Client.Transport or http.DefaultTransport")
+ err = os.NewError("http: no Client.Transport or DefaultTransport")
return
}
}
+ if req.URL == nil {
+ return nil, os.NewError("http: nil Request.URL")
+ }
+
// Most the callers of send (Get, Post, et al) don't need
// Headers, leaving it uninitialized. We guarantee to the
// Transport that this has been initialized, though.
@@ -105,9 +115,6 @@ func send(req *Request, t RoundTripper) (resp *Response, err os.Error) {
info := req.URL.RawUserinfo
if len(info) > 0 {
- if req.Header == nil {
- req.Header = make(Header)
- }
req.Header.Set("Authorization", "Basic "+base64.URLEncoding.EncodeToString([]byte(info)))
}
return t.RoundTrip(req)
@@ -166,6 +173,10 @@ func (c *Client) doFollowingRedirects(ireq *Request) (r *Response, err os.Error)
}
var via []*Request
+ if ireq.URL == nil {
+ return nil, os.NewError("http: nil Request.URL")
+ }
+
req := ireq
urlStr := "" // next relative or absolute URL to fetch (after first request)
for redirect := 0; ; redirect++ {
diff --git a/libgo/go/http/client_test.go b/libgo/go/http/client_test.go
index 8efb1d989df..0ad6cd7c2f3 100644
--- a/libgo/go/http/client_test.go
+++ b/libgo/go/http/client_test.go
@@ -132,7 +132,9 @@ func TestPostFormRequestFormat(t *testing.T) {
if tr.req.Close {
t.Error("got Close true, want false")
}
- expectedBody := "bar=baz&foo=bar&foo=bar2"
+ // Depending on map iteration, body can be either of these.
+ expectedBody := "foo=bar&foo=bar2&bar=baz"
+ expectedBody1 := "bar=baz&foo=bar&foo=bar2"
if g, e := tr.req.ContentLength, int64(len(expectedBody)); g != e {
t.Errorf("got ContentLength %d, want %d", g, e)
}
@@ -140,8 +142,8 @@ func TestPostFormRequestFormat(t *testing.T) {
if err != nil {
t.Fatalf("ReadAll on req.Body: %v", err)
}
- if g := string(bodyb); g != expectedBody {
- t.Errorf("got body %q, want %q", g, expectedBody)
+ if g := string(bodyb); g != expectedBody && g != expectedBody1 {
+ t.Errorf("got body %q, want %q or %q", g, expectedBody, expectedBody1)
}
}
diff --git a/libgo/go/http/cookie.go b/libgo/go/http/cookie.go
index fe70431bbbc..69350143248 100644
--- a/libgo/go/http/cookie.go
+++ b/libgo/go/http/cookie.go
@@ -207,17 +207,16 @@ func readCookies(h Header, filter string) []*Cookie {
return cookies
}
+var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
+
func sanitizeName(n string) string {
- n = strings.Replace(n, "\n", "-", -1)
- n = strings.Replace(n, "\r", "-", -1)
- return n
+ return cookieNameSanitizer.Replace(n)
}
+var cookieValueSanitizer = strings.NewReplacer("\n", " ", "\r", " ", ";", " ")
+
func sanitizeValue(v string) string {
- v = strings.Replace(v, "\n", " ", -1)
- v = strings.Replace(v, "\r", " ", -1)
- v = strings.Replace(v, ";", " ", -1)
- return v
+ return cookieValueSanitizer.Replace(v)
}
func unquoteCookieValue(v string) string {
diff --git a/libgo/go/http/cookie_test.go b/libgo/go/http/cookie_test.go
index d7aeda0be17..5de6aab611f 100644
--- a/libgo/go/http/cookie_test.go
+++ b/libgo/go/http/cookie_test.go
@@ -124,7 +124,7 @@ var readSetCookiesTests = []struct {
Path: "/",
Domain: ".google.ch",
HttpOnly: true,
- Expires: time.Time{Year: 2011, Month: 11, Day: 23, Hour: 1, Minute: 5, Second: 3, Weekday: 3, ZoneOffset: 0, Zone: "GMT"},
+ Expires: time.Time{Year: 2011, Month: 11, Day: 23, Hour: 1, Minute: 5, Second: 3, ZoneOffset: 0, Zone: "GMT"},
RawExpires: "Wed, 23-Nov-2011 01:05:03 GMT",
Raw: "NID=99=YsDT5i3E-CXax-; expires=Wed, 23-Nov-2011 01:05:03 GMT; path=/; domain=.google.ch; HttpOnly",
}},
diff --git a/libgo/go/http/dump.go b/libgo/go/http/dump.go
index 358980f7cae..f78df577104 100644
--- a/libgo/go/http/dump.go
+++ b/libgo/go/http/dump.go
@@ -44,7 +44,7 @@ func DumpRequest(req *Request, body bool) (dump []byte, err os.Error) {
return
}
}
- err = req.Write(&b)
+ err = req.dumpWrite(&b)
req.Body = save
if err != nil {
return
diff --git a/libgo/go/http/fcgi/child.go b/libgo/go/http/fcgi/child.go
index 19718824c96..61dd3fbdc43 100644
--- a/libgo/go/http/fcgi/child.go
+++ b/libgo/go/http/fcgi/child.go
@@ -194,7 +194,7 @@ func (c *child) serve() {
case typeData:
// If the filter role is implemented, read the data stream here.
case typeAbortRequest:
- requests[rec.h.Id] = nil, false
+ delete(requests, rec.h.Id)
c.conn.writeEndRequest(rec.h.Id, 0, statusRequestComplete)
if !req.keepConn {
// connection will close upon return
diff --git a/libgo/go/http/fcgi/fcgi_test.go b/libgo/go/http/fcgi/fcgi_test.go
index 16a6243295e..5c8e46bd75a 100644
--- a/libgo/go/http/fcgi/fcgi_test.go
+++ b/libgo/go/http/fcgi/fcgi_test.go
@@ -53,13 +53,13 @@ var streamTests = []struct {
{"two records", typeStdin, 300, make([]byte, 66000),
bytes.Join([][]byte{
// header for the first record
- []byte{1, typeStdin, 0x01, 0x2C, 0xFF, 0xFF, 1, 0},
+ {1, typeStdin, 0x01, 0x2C, 0xFF, 0xFF, 1, 0},
make([]byte, 65536),
// header for the second
- []byte{1, typeStdin, 0x01, 0x2C, 0x01, 0xD1, 7, 0},
+ {1, typeStdin, 0x01, 0x2C, 0x01, 0xD1, 7, 0},
make([]byte, 472),
// header for the empty record
- []byte{1, typeStdin, 0x01, 0x2C, 0, 0, 0, 0},
+ {1, typeStdin, 0x01, 0x2C, 0, 0, 0, 0},
},
nil),
},
diff --git a/libgo/go/http/filetransport.go b/libgo/go/http/filetransport.go
new file mode 100644
index 00000000000..78f3aa2d69d
--- /dev/null
+++ b/libgo/go/http/filetransport.go
@@ -0,0 +1,124 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http
+
+import (
+ "fmt"
+ "io"
+ "os"
+)
+
+// fileTransport implements RoundTripper for the 'file' protocol.
+type fileTransport struct {
+ fh fileHandler
+}
+
+// NewFileTransport returns a new RoundTripper, serving the provided
+// FileSystem. The returned RoundTripper ignores the URL host in its
+// incoming requests, as well as most other properties of the
+// request.
+//
+// The typical use case for NewFileTransport is to register the "file"
+// protocol with a Transport, as in:
+//
+// t := &http.Transport{}
+// t.RegisterProtocol("file", http.NewFileTransport(http.Dir("/")))
+// c := &http.Client{Transport: t}
+// res, err := c.Get("file:///etc/passwd")
+// ...
+func NewFileTransport(fs FileSystem) RoundTripper {
+ return fileTransport{fileHandler{fs}}
+}
+
+func (t fileTransport) RoundTrip(req *Request) (resp *Response, err os.Error) {
+ // We start ServeHTTP in a goroutine, which may take a long
+ // time if the file is large. The newPopulateResponseWriter
+ // call returns a channel which either ServeHTTP or finish()
+ // sends our *Response on, once the *Response itself has been
+ // populated (even if the body itself is still being
+ // written to the res.Body, a pipe)
+ rw, resc := newPopulateResponseWriter()
+ go func() {
+ t.fh.ServeHTTP(rw, req)
+ rw.finish()
+ }()
+ return <-resc, nil
+}
+
+func newPopulateResponseWriter() (*populateResponse, <-chan *Response) {
+ pr, pw := io.Pipe()
+ rw := &populateResponse{
+ ch: make(chan *Response),
+ pw: pw,
+ res: &Response{
+ Proto: "HTTP/1.0",
+ ProtoMajor: 1,
+ Header: make(Header),
+ Close: true,
+ Body: pr,
+ },
+ }
+ return rw, rw.ch
+}
+
+// populateResponse is a ResponseWriter that populates the *Response
+// in res, and writes its body to a pipe connected to the response
+// body. Once writes begin or finish() is called, the response is sent
+// on ch.
+type populateResponse struct {
+ res *Response
+ ch chan *Response
+ wroteHeader bool
+ hasContent bool
+ sentResponse bool
+ pw *io.PipeWriter
+}
+
+func (pr *populateResponse) finish() {
+ if !pr.wroteHeader {
+ pr.WriteHeader(500)
+ }
+ if !pr.sentResponse {
+ pr.sendResponse()
+ }
+ pr.pw.Close()
+}
+
+func (pr *populateResponse) sendResponse() {
+ if pr.sentResponse {
+ return
+ }
+ pr.sentResponse = true
+
+ if pr.hasContent {
+ pr.res.ContentLength = -1
+ }
+ pr.ch <- pr.res
+}
+
+func (pr *populateResponse) Header() Header {
+ return pr.res.Header
+}
+
+func (pr *populateResponse) WriteHeader(code int) {
+ if pr.wroteHeader {
+ return
+ }
+ pr.wroteHeader = true
+
+ pr.res.StatusCode = code
+ pr.res.Status = fmt.Sprintf("%d %s", code, StatusText(code))
+}
+
+func (pr *populateResponse) Write(p []byte) (n int, err os.Error) {
+ if !pr.wroteHeader {
+ pr.WriteHeader(StatusOK)
+ }
+ pr.hasContent = true
+ if !pr.sentResponse {
+ pr.sendResponse()
+ }
+ return pr.pw.Write(p)
+}
diff --git a/libgo/go/http/filetransport_test.go b/libgo/go/http/filetransport_test.go
new file mode 100644
index 00000000000..2634243f723
--- /dev/null
+++ b/libgo/go/http/filetransport_test.go
@@ -0,0 +1,63 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http_test
+
+import (
+ "http"
+ "io/ioutil"
+ "path/filepath"
+ "os"
+ "testing"
+)
+
+func checker(t *testing.T) func(string, os.Error) {
+ return func(call string, err os.Error) {
+ if err == nil {
+ return
+ }
+ t.Fatalf("%s: %v", call, err)
+ }
+}
+
+func TestFileTransport(t *testing.T) {
+ check := checker(t)
+
+ dname, err := ioutil.TempDir("", "")
+ check("TempDir", err)
+ fname := filepath.Join(dname, "foo.txt")
+ err = ioutil.WriteFile(fname, []byte("Bar"), 0644)
+ check("WriteFile", err)
+
+ tr := &http.Transport{}
+ tr.RegisterProtocol("file", http.NewFileTransport(http.Dir(dname)))
+ c := &http.Client{Transport: tr}
+
+ fooURLs := []string{"file:///foo.txt", "file://../foo.txt"}
+ for _, urlstr := range fooURLs {
+ res, err := c.Get(urlstr)
+ check("Get "+urlstr, err)
+ if res.StatusCode != 200 {
+ t.Errorf("for %s, StatusCode = %d, want 200", urlstr, res.StatusCode)
+ }
+ if res.ContentLength != -1 {
+ t.Errorf("for %s, ContentLength = %d, want -1", urlstr, res.ContentLength)
+ }
+ if res.Body == nil {
+ t.Fatalf("for %s, nil Body", urlstr)
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ check("ReadAll "+urlstr, err)
+ if string(slurp) != "Bar" {
+ t.Errorf("for %s, got content %q, want %q", urlstr, string(slurp), "Bar")
+ }
+ }
+
+ const badURL = "file://../no-exist.txt"
+ res, err := c.Get(badURL)
+ check("Get "+badURL, err)
+ if res.StatusCode != 404 {
+ t.Errorf("for %s, StatusCode = %d, want 404", badURL, res.StatusCode)
+ }
+}
diff --git a/libgo/go/http/fs.go b/libgo/go/http/fs.go
index 2c7c636fda0..6d716654a23 100644
--- a/libgo/go/http/fs.go
+++ b/libgo/go/http/fs.go
@@ -219,7 +219,7 @@ func serveFile(w ResponseWriter, r *Request, fs FileSystem, name string, redirec
w.WriteHeader(code)
if r.Method != "HEAD" {
- io.Copyn(w, f, size)
+ io.CopyN(w, f, size)
}
}
diff --git a/libgo/go/http/header.go b/libgo/go/http/header.go
index 08b07713041..aaaa92a2ef7 100644
--- a/libgo/go/http/header.go
+++ b/libgo/go/http/header.go
@@ -47,6 +47,8 @@ func (h Header) Write(w io.Writer) os.Error {
return h.WriteSubset(w, nil)
}
+var headerNewlineToSpace = strings.NewReplacer("\n", " ", "\r", " ")
+
// WriteSubset writes a header in wire format.
// If exclude is not nil, keys where exclude[key] == true are not written.
func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) os.Error {
@@ -59,8 +61,7 @@ func (h Header) WriteSubset(w io.Writer, exclude map[string]bool) os.Error {
sort.Strings(keys)
for _, k := range keys {
for _, v := range h[k] {
- v = strings.Replace(v, "\n", " ", -1)
- v = strings.Replace(v, "\r", " ", -1)
+ v = headerNewlineToSpace.Replace(v)
v = strings.TrimSpace(v)
if _, err := fmt.Fprintf(w, "%s: %s\r\n", k, v); err != nil {
return err
diff --git a/libgo/go/http/httptest/server.go b/libgo/go/http/httptest/server.go
index 2ec36d04cf6..43a48ebbd1c 100644
--- a/libgo/go/http/httptest/server.go
+++ b/libgo/go/http/httptest/server.go
@@ -23,6 +23,10 @@ type Server struct {
URL string // base URL of form http://ipaddr:port with no trailing slash
Listener net.Listener
TLS *tls.Config // nil if not using using TLS
+
+ // Config may be changed after calling NewUnstartedServer and
+ // before Start or StartTLS.
+ Config *http.Server
}
// historyListener keeps track of all connections that it's ever
@@ -41,6 +45,13 @@ func (hs *historyListener) Accept() (c net.Conn, err os.Error) {
}
func newLocalListener() net.Listener {
+ if *serve != "" {
+ l, err := net.Listen("tcp", *serve)
+ if err != nil {
+ panic(fmt.Sprintf("httptest: failed to listen on %v: %v", *serve, err))
+ }
+ return l
+ }
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
@@ -59,51 +70,66 @@ var serve = flag.String("httptest.serve", "", "if non-empty, httptest.NewServer
// NewServer starts and returns a new Server.
// The caller should call Close when finished, to shut it down.
func NewServer(handler http.Handler) *Server {
- ts := new(Server)
- var l net.Listener
- if *serve != "" {
- var err os.Error
- l, err = net.Listen("tcp", *serve)
- if err != nil {
- panic(fmt.Sprintf("httptest: failed to listen on %v: %v", *serve, err))
- }
- } else {
- l = newLocalListener()
+ ts := NewUnstartedServer(handler)
+ ts.Start()
+ return ts
+}
+
+// NewUnstartedServer returns a new Server but doesn't start it.
+//
+// After changing its configuration, the caller should call Start or
+// StartTLS.
+//
+// The caller should call Close when finished, to shut it down.
+func NewUnstartedServer(handler http.Handler) *Server {
+ return &Server{
+ Listener: newLocalListener(),
+ Config: &http.Server{Handler: handler},
}
- ts.Listener = &historyListener{l, make([]net.Conn, 0)}
- ts.URL = "http://" + l.Addr().String()
- server := &http.Server{Handler: handler}
- go server.Serve(ts.Listener)
+}
+
+// Start starts a server from NewUnstartedServer.
+func (s *Server) Start() {
+ if s.URL != "" {
+ panic("Server already started")
+ }
+ s.Listener = &historyListener{s.Listener, make([]net.Conn, 0)}
+ s.URL = "http://" + s.Listener.Addr().String()
+ go s.Config.Serve(s.Listener)
if *serve != "" {
- fmt.Println(os.Stderr, "httptest: serving on", ts.URL)
+ fmt.Println(os.Stderr, "httptest: serving on", s.URL)
select {}
}
- return ts
}
-// NewTLSServer starts and returns a new Server using TLS.
-// The caller should call Close when finished, to shut it down.
-func NewTLSServer(handler http.Handler) *Server {
- l := newLocalListener()
- ts := new(Server)
-
+// StartTLS starts TLS on a server from NewUnstartedServer.
+func (s *Server) StartTLS() {
+ if s.URL != "" {
+ panic("Server already started")
+ }
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
if err != nil {
panic(fmt.Sprintf("httptest: NewTLSServer: %v", err))
}
- ts.TLS = &tls.Config{
+ s.TLS = &tls.Config{
Rand: rand.Reader,
Time: time.Seconds,
NextProtos: []string{"http/1.1"},
Certificates: []tls.Certificate{cert},
}
- tlsListener := tls.NewListener(l, ts.TLS)
+ tlsListener := tls.NewListener(s.Listener, s.TLS)
+
+ s.Listener = &historyListener{tlsListener, make([]net.Conn, 0)}
+ s.URL = "https://" + s.Listener.Addr().String()
+ go s.Config.Serve(s.Listener)
+}
- ts.Listener = &historyListener{tlsListener, make([]net.Conn, 0)}
- ts.URL = "https://" + l.Addr().String()
- server := &http.Server{Handler: handler}
- go server.Serve(ts.Listener)
+// NewTLSServer starts and returns a new Server using TLS.
+// The caller should call Close when finished, to shut it down.
+func NewTLSServer(handler http.Handler) *Server {
+ ts := NewUnstartedServer(handler)
+ ts.StartTLS()
return ts
}
diff --git a/libgo/go/http/persist.go b/libgo/go/http/persist.go
index 78bf9058f3c..f73e6c63c56 100644
--- a/libgo/go/http/persist.go
+++ b/libgo/go/http/persist.go
@@ -165,7 +165,7 @@ func (sc *ServerConn) Write(req *Request, resp *Response) os.Error {
// Retrieve the pipeline ID of this request/response pair
sc.lk.Lock()
id, ok := sc.pipereq[req]
- sc.pipereq[req] = 0, false
+ delete(sc.pipereq, req)
if !ok {
sc.lk.Unlock()
return ErrPipeline
@@ -353,7 +353,7 @@ func (cc *ClientConn) readUsing(req *Request, readRes func(*bufio.Reader, *Reque
// Retrieve the pipeline ID of this request/response pair
cc.lk.Lock()
id, ok := cc.pipereq[req]
- cc.pipereq[req] = 0, false
+ delete(cc.pipereq, req)
if !ok {
cc.lk.Unlock()
return nil, ErrPipeline
diff --git a/libgo/go/http/readrequest_test.go b/libgo/go/http/readrequest_test.go
index f6dc99e2e08..6d9042aceb6 100644
--- a/libgo/go/http/readrequest_test.go
+++ b/libgo/go/http/readrequest_test.go
@@ -40,7 +40,6 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
- RawURL: "http://www.techcrunch.com/",
URL: &url.URL{
Raw: "http://www.techcrunch.com/",
Scheme: "http",
@@ -83,7 +82,6 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
- RawURL: "/",
URL: &url.URL{
Raw: "/",
Path: "/",
@@ -110,7 +108,6 @@ var reqTests = []reqTest{
&Request{
Method: "GET",
- RawURL: "//user@host/is/actually/a/path/",
URL: &url.URL{
Raw: "//user@host/is/actually/a/path/",
Scheme: "",
diff --git a/libgo/go/http/request.go b/libgo/go/http/request.go
index ed41fa45c13..02317e0c419 100644
--- a/libgo/go/http/request.go
+++ b/libgo/go/http/request.go
@@ -64,18 +64,24 @@ func (e *badStringError) String() string { return fmt.Sprintf("%s %q", e.what, e
// Headers that Request.Write handles itself and should be skipped.
var reqWriteExcludeHeader = map[string]bool{
- "Host": true,
+ "Host": true, // not in Header map anyway
"User-Agent": true,
"Content-Length": true,
"Transfer-Encoding": true,
"Trailer": true,
}
+var reqWriteExcludeHeaderDump = map[string]bool{
+ "Host": true, // not in Header map anyway
+ "Content-Length": true,
+ "Transfer-Encoding": true,
+ "Trailer": true,
+}
+
// A Request represents a parsed HTTP request header.
type Request struct {
- Method string // GET, POST, PUT, etc.
- RawURL string // The raw URL given in the request.
- URL *url.URL // Parsed URL.
+ Method string // GET, POST, PUT, etc.
+ URL *url.URL
// The protocol version for incoming requests.
// Outgoing requests always use HTTP/1.1.
@@ -234,8 +240,8 @@ func (r *Request) multipartReader() (*multipart.Reader, os.Error) {
if v == "" {
return nil, ErrNotMultipart
}
- d, params := mime.ParseMediaType(v)
- if d != "multipart/form-data" {
+ d, params, err := mime.ParseMediaType(v)
+ if err != nil || d != "multipart/form-data" {
return nil, ErrNotMultipart
}
boundary, ok := params["boundary"]
@@ -258,7 +264,7 @@ const defaultUserAgent = "Go http package"
// Write writes an HTTP/1.1 request -- header and body -- in wire format.
// This method consults the following fields of req:
// Host
-// RawURL, if non-empty, or else URL
+// URL
// Method (defaults to "GET")
// Header
// ContentLength
@@ -269,19 +275,66 @@ const defaultUserAgent = "Go http package"
// hasn't been set to "identity", Write adds "Transfer-Encoding:
// chunked" to the header. Body is closed after it is sent.
func (req *Request) Write(w io.Writer) os.Error {
- return req.write(w, false)
+ return req.write(w, false, nil)
}
// WriteProxy is like Write but writes the request in the form
-// expected by an HTTP proxy. It includes the scheme and host
-// name in the URI instead of using a separate Host: header line.
-// If req.RawURL is non-empty, WriteProxy uses it unchanged
-// instead of URL but still omits the Host: header.
+// expected by an HTTP proxy. In particular, WriteProxy writes the
+// initial Request-URI line of the request with an absolute URI, per
+// section 5.1.2 of RFC 2616, including the scheme and host. In
+// either case, WriteProxy also writes a Host header, using either
+// req.Host or req.URL.Host.
func (req *Request) WriteProxy(w io.Writer) os.Error {
- return req.write(w, true)
+ return req.write(w, true, nil)
+}
+
+func (req *Request) dumpWrite(w io.Writer) os.Error {
+ // TODO(bradfitz): RawPath here?
+ urlStr := valueOrDefault(req.URL.EncodedPath(), "/")
+ if req.URL.RawQuery != "" {
+ urlStr += "?" + req.URL.RawQuery
+ }
+
+ bw := bufio.NewWriter(w)
+ fmt.Fprintf(bw, "%s %s HTTP/%d.%d\r\n", valueOrDefault(req.Method, "GET"), urlStr,
+ req.ProtoMajor, req.ProtoMinor)
+
+ host := req.Host
+ if host == "" && req.URL != nil {
+ host = req.URL.Host
+ }
+ if host != "" {
+ fmt.Fprintf(bw, "Host: %s\r\n", host)
+ }
+
+ // Process Body,ContentLength,Close,Trailer
+ tw, err := newTransferWriter(req)
+ if err != nil {
+ return err
+ }
+ err = tw.WriteHeader(bw)
+ if err != nil {
+ return err
+ }
+
+ err = req.Header.WriteSubset(bw, reqWriteExcludeHeaderDump)
+ if err != nil {
+ return err
+ }
+
+ io.WriteString(bw, "\r\n")
+
+ // Write body and trailer
+ err = tw.WriteBody(bw)
+ if err != nil {
+ return err
+ }
+ bw.Flush()
+ return nil
}
-func (req *Request) write(w io.Writer, usingProxy bool) os.Error {
+// extraHeaders may be nil
+func (req *Request) write(w io.Writer, usingProxy bool, extraHeaders Header) os.Error {
host := req.Host
if host == "" {
if req.URL == nil {
@@ -290,9 +343,12 @@ func (req *Request) write(w io.Writer, usingProxy bool) os.Error {
host = req.URL.Host
}
- urlStr := req.RawURL
+ urlStr := req.URL.RawPath
+ if strings.HasPrefix(urlStr, "?") {
+ urlStr = "/" + urlStr // Issue 2344
+ }
if urlStr == "" {
- urlStr = valueOrDefault(req.URL.EncodedPath(), "/")
+ urlStr = valueOrDefault(req.URL.RawPath, valueOrDefault(req.URL.EncodedPath(), "/"))
if req.URL.RawQuery != "" {
urlStr += "?" + req.URL.RawQuery
}
@@ -303,6 +359,7 @@ func (req *Request) write(w io.Writer, usingProxy bool) os.Error {
urlStr = req.URL.Scheme + "://" + host + urlStr
}
}
+ // TODO(bradfitz): escape at least newlines in urlStr?
bw := bufio.NewWriter(w)
fmt.Fprintf(bw, "%s %s HTTP/1.1\r\n", valueOrDefault(req.Method, "GET"), urlStr)
@@ -338,6 +395,13 @@ func (req *Request) write(w io.Writer, usingProxy bool) os.Error {
return err
}
+ if extraHeaders != nil {
+ err = extraHeaders.Write(bw)
+ if err != nil {
+ return err
+ }
+ }
+
io.WriteString(bw, "\r\n")
// Write body and trailer
@@ -542,13 +606,14 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
if f = strings.SplitN(s, " ", 3); len(f) < 3 {
return nil, &badStringError{"malformed HTTP request", s}
}
- req.Method, req.RawURL, req.Proto = f[0], f[1], f[2]
+ var rawurl string
+ req.Method, rawurl, req.Proto = f[0], f[1], f[2]
var ok bool
if req.ProtoMajor, req.ProtoMinor, ok = ParseHTTPVersion(req.Proto); !ok {
return nil, &badStringError{"malformed HTTP version", req.Proto}
}
- if req.URL, err = url.ParseRequest(req.RawURL); err != nil {
+ if req.URL, err = url.ParseRequest(rawurl); err != nil {
return nil, err
}
@@ -608,27 +673,77 @@ func ReadRequest(b *bufio.Reader) (req *Request, err os.Error) {
return req, nil
}
-// ParseForm parses the raw query.
-// For POST requests, it also parses the request body as a form.
+// MaxBytesReader is similar to io.LimitReader but is intended for
+// limiting the size of incoming request bodies. In contrast to
+// io.LimitReader, MaxBytesReader's result is a ReadCloser, returns a
+// non-EOF error for a Read beyond the limit, and Closes the
+// underlying reader when its Close method is called.
+//
+// MaxBytesReader prevents clients from accidentally or maliciously
+// sending a large request and wasting server resources.
+func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser {
+ return &maxBytesReader{w: w, r: r, n: n}
+}
+
+type maxBytesReader struct {
+ w ResponseWriter
+ r io.ReadCloser // underlying reader
+ n int64 // max bytes remaining
+ stopped bool
+}
+
+func (l *maxBytesReader) Read(p []byte) (n int, err os.Error) {
+ if l.n <= 0 {
+ if !l.stopped {
+ l.stopped = true
+ if res, ok := l.w.(*response); ok {
+ res.requestTooLarge()
+ }
+ }
+ return 0, os.NewError("http: request body too large")
+ }
+ if int64(len(p)) > l.n {
+ p = p[:l.n]
+ }
+ n, err = l.r.Read(p)
+ l.n -= int64(n)
+ return
+}
+
+func (l *maxBytesReader) Close() os.Error {
+ return l.r.Close()
+}
+
+// ParseForm parses the raw query from the URL.
+//
+// For POST or PUT requests, it also parses the request body as a form.
+// If the request Body's size has not already been limited by MaxBytesReader,
+// the size is capped at 10MB.
+//
// ParseMultipartForm calls ParseForm automatically.
// It is idempotent.
func (r *Request) ParseForm() (err os.Error) {
if r.Form != nil {
return
}
-
if r.URL != nil {
r.Form, err = url.ParseQuery(r.URL.RawQuery)
}
- if r.Method == "POST" {
+ if r.Method == "POST" || r.Method == "PUT" {
if r.Body == nil {
return os.NewError("missing form body")
}
ct := r.Header.Get("Content-Type")
- switch strings.SplitN(ct, ";", 2)[0] {
- case "text/plain", "application/x-www-form-urlencoded", "":
- const maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
- b, e := ioutil.ReadAll(io.LimitReader(r.Body, maxFormSize+1))
+ ct, _, err := mime.ParseMediaType(ct)
+ switch {
+ case ct == "text/plain" || ct == "application/x-www-form-urlencoded" || ct == "":
+ var reader io.Reader = r.Body
+ maxFormSize := int64(1<<63 - 1)
+ if _, ok := r.Body.(*maxBytesReader); !ok {
+ maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
+ reader = io.LimitReader(r.Body, maxFormSize+1)
+ }
+ b, e := ioutil.ReadAll(reader)
if e != nil {
if err == nil {
err = e
@@ -652,8 +767,13 @@ func (r *Request) ParseForm() (err os.Error) {
r.Form.Add(k, value)
}
}
- case "multipart/form-data":
- // handled by ParseMultipartForm
+ case ct == "multipart/form-data":
+ // handled by ParseMultipartForm (which is calling us, or should be)
+ // TODO(bradfitz): there are too many possible
+ // orders to call too many functions here.
+ // Clean this up and write more tests.
+ // request_test.go contains the start of this,
+ // in TestRequestMultipartCallOrder.
default:
return &badStringError{"unknown Content-Type", ct}
}
diff --git a/libgo/go/http/request_test.go b/libgo/go/http/request_test.go
index 869cd57b696..175d6f170b8 100644
--- a/libgo/go/http/request_test.go
+++ b/libgo/go/http/request_test.go
@@ -20,57 +20,6 @@ import (
"url"
)
-type stringMultimap map[string][]string
-
-type parseTest struct {
- query string
- out stringMultimap
-}
-
-var parseTests = []parseTest{
- {
- query: "a=1&b=2",
- out: stringMultimap{"a": []string{"1"}, "b": []string{"2"}},
- },
- {
- query: "a=1&a=2&a=banana",
- out: stringMultimap{"a": []string{"1", "2", "banana"}},
- },
- {
- query: "ascii=%3Ckey%3A+0x90%3E",
- out: stringMultimap{"ascii": []string{"<key: 0x90>"}},
- },
-}
-
-func TestParseForm(t *testing.T) {
- for i, test := range parseTests {
- form, err := url.ParseQuery(test.query)
- if err != nil {
- t.Errorf("test %d: Unexpected error: %v", i, err)
- continue
- }
- if len(form) != len(test.out) {
- t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out))
- }
- for k, evs := range test.out {
- vs, ok := form[k]
- if !ok {
- t.Errorf("test %d: Missing key %q", i, k)
- continue
- }
- if len(vs) != len(evs) {
- t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs))
- continue
- }
- for j, ev := range evs {
- if v := vs[j]; v != ev {
- t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev)
- }
- }
- }
- }
-}
-
func TestQuery(t *testing.T) {
req := &Request{Method: "GET"}
req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
diff --git a/libgo/go/http/requestwrite_test.go b/libgo/go/http/requestwrite_test.go
index 458f0bd7f4b..194f6dd213c 100644
--- a/libgo/go/http/requestwrite_test.go
+++ b/libgo/go/http/requestwrite_test.go
@@ -16,18 +16,22 @@ import (
)
type reqWriteTest struct {
- Req Request
- Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
- Raw string
- RawProxy string
+ Req Request
+ Body interface{} // optional []byte or func() io.ReadCloser to populate Req.Body
+
+ // Any of these three may be empty to skip that test.
+ WantWrite string // Request.Write
+ WantProxy string // Request.WriteProxy
+ WantDump string // DumpRequest
+
+ WantError os.Error // wanted error from Request.Write
}
var reqWriteTests = []reqWriteTest{
// HTTP/1.1 => chunked coding; no body; no trailer
{
- Request{
+ Req: Request{
Method: "GET",
- RawURL: "http://www.techcrunch.com/",
URL: &url.URL{
Raw: "http://www.techcrunch.com/",
Scheme: "http",
@@ -57,9 +61,7 @@ var reqWriteTests = []reqWriteTest{
Form: map[string][]string{},
},
- nil,
-
- "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
+ WantWrite: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
"Host: www.techcrunch.com\r\n" +
"User-Agent: Fake\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
@@ -69,7 +71,7 @@ var reqWriteTests = []reqWriteTest{
"Keep-Alive: 300\r\n" +
"Proxy-Connection: keep-alive\r\n\r\n",
- "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
+ WantProxy: "GET http://www.techcrunch.com/ HTTP/1.1\r\n" +
"Host: www.techcrunch.com\r\n" +
"User-Agent: Fake\r\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" +
@@ -81,7 +83,7 @@ var reqWriteTests = []reqWriteTest{
},
// HTTP/1.1 => chunked coding; body; empty trailer
{
- Request{
+ Req: Request{
Method: "GET",
URL: &url.URL{
Scheme: "http",
@@ -94,23 +96,28 @@ var reqWriteTests = []reqWriteTest{
TransferEncoding: []string{"chunked"},
},
- []byte("abcdef"),
+ Body: []byte("abcdef"),
- "GET /search HTTP/1.1\r\n" +
+ WantWrite: "GET /search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
"User-Agent: Go http package\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("abcdef") + chunk(""),
- "GET http://www.google.com/search HTTP/1.1\r\n" +
+ WantProxy: "GET http://www.google.com/search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
"User-Agent: Go http package\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("abcdef") + chunk(""),
+
+ WantDump: "GET /search HTTP/1.1\r\n" +
+ "Host: www.google.com\r\n" +
+ "Transfer-Encoding: chunked\r\n\r\n" +
+ chunk("abcdef") + chunk(""),
},
// HTTP/1.1 POST => chunked coding; body; empty trailer
{
- Request{
+ Req: Request{
Method: "POST",
URL: &url.URL{
Scheme: "http",
@@ -124,16 +131,16 @@ var reqWriteTests = []reqWriteTest{
TransferEncoding: []string{"chunked"},
},
- []byte("abcdef"),
+ Body: []byte("abcdef"),
- "POST /search HTTP/1.1\r\n" +
+ WantWrite: "POST /search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
"User-Agent: Go http package\r\n" +
"Connection: close\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("abcdef") + chunk(""),
- "POST http://www.google.com/search HTTP/1.1\r\n" +
+ WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
"User-Agent: Go http package\r\n" +
"Connection: close\r\n" +
@@ -143,7 +150,7 @@ var reqWriteTests = []reqWriteTest{
// HTTP/1.1 POST with Content-Length, no chunking
{
- Request{
+ Req: Request{
Method: "POST",
URL: &url.URL{
Scheme: "http",
@@ -157,9 +164,9 @@ var reqWriteTests = []reqWriteTest{
ContentLength: 6,
},
- []byte("abcdef"),
+ Body: []byte("abcdef"),
- "POST /search HTTP/1.1\r\n" +
+ WantWrite: "POST /search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
"User-Agent: Go http package\r\n" +
"Connection: close\r\n" +
@@ -167,7 +174,7 @@ var reqWriteTests = []reqWriteTest{
"\r\n" +
"abcdef",
- "POST http://www.google.com/search HTTP/1.1\r\n" +
+ WantProxy: "POST http://www.google.com/search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
"User-Agent: Go http package\r\n" +
"Connection: close\r\n" +
@@ -178,9 +185,9 @@ var reqWriteTests = []reqWriteTest{
// HTTP/1.1 POST with Content-Length in headers
{
- Request{
+ Req: Request{
Method: "POST",
- RawURL: "http://example.com/",
+ URL: mustParseURL("http://example.com/"),
Host: "example.com",
Header: Header{
"Content-Length": []string{"10"}, // ignored
@@ -188,16 +195,16 @@ var reqWriteTests = []reqWriteTest{
ContentLength: 6,
},
- []byte("abcdef"),
+ Body: []byte("abcdef"),
- "POST http://example.com/ HTTP/1.1\r\n" +
+ WantWrite: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go http package\r\n" +
"Content-Length: 6\r\n" +
"\r\n" +
"abcdef",
- "POST http://example.com/ HTTP/1.1\r\n" +
+ WantProxy: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go http package\r\n" +
"Content-Length: 6\r\n" +
@@ -207,21 +214,13 @@ var reqWriteTests = []reqWriteTest{
// default to HTTP/1.1
{
- Request{
+ Req: Request{
Method: "GET",
- RawURL: "/search",
+ URL: mustParseURL("/search"),
Host: "www.google.com",
},
- nil,
-
- "GET /search HTTP/1.1\r\n" +
- "Host: www.google.com\r\n" +
- "User-Agent: Go http package\r\n" +
- "\r\n",
-
- // Looks weird but RawURL overrides what WriteProxy would choose.
- "GET /search HTTP/1.1\r\n" +
+ WantWrite: "GET /search HTTP/1.1\r\n" +
"Host: www.google.com\r\n" +
"User-Agent: Go http package\r\n" +
"\r\n",
@@ -229,53 +228,125 @@ var reqWriteTests = []reqWriteTest{
// Request with a 0 ContentLength and a 0 byte body.
{
- Request{
+ Req: Request{
Method: "POST",
- RawURL: "/",
+ URL: mustParseURL("/"),
Host: "example.com",
ProtoMajor: 1,
ProtoMinor: 1,
ContentLength: 0, // as if unset by user
},
- func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
+ Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
- "POST / HTTP/1.1\r\n" +
+ // RFC 2616 Section 14.13 says Content-Length should be specified
+ // unless body is prohibited by the request method.
+ // Also, nginx expects it for POST and PUT.
+ WantWrite: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go http package\r\n" +
+ "Content-Length: 0\r\n" +
"\r\n",
- "POST / HTTP/1.1\r\n" +
+ WantProxy: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go http package\r\n" +
+ "Content-Length: 0\r\n" +
"\r\n",
},
// Request with a 0 ContentLength and a 1 byte body.
{
- Request{
+ Req: Request{
Method: "POST",
- RawURL: "/",
+ URL: mustParseURL("/"),
Host: "example.com",
ProtoMajor: 1,
ProtoMinor: 1,
ContentLength: 0, // as if unset by user
},
- func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
+ Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
- "POST / HTTP/1.1\r\n" +
+ WantWrite: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go http package\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("x") + chunk(""),
- "POST / HTTP/1.1\r\n" +
+ WantProxy: "POST / HTTP/1.1\r\n" +
"Host: example.com\r\n" +
"User-Agent: Go http package\r\n" +
"Transfer-Encoding: chunked\r\n\r\n" +
chunk("x") + chunk(""),
},
+
+ // Request with a ContentLength of 10 but a 5 byte body.
+ {
+ Req: Request{
+ Method: "POST",
+ URL: mustParseURL("/"),
+ Host: "example.com",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ ContentLength: 10, // but we're going to send only 5 bytes
+ },
+ Body: []byte("12345"),
+ WantError: os.NewError("http: Request.ContentLength=10 with Body length 5"),
+ },
+
+ // Request with a ContentLength of 4 but an 8 byte body.
+ {
+ Req: Request{
+ Method: "POST",
+ URL: mustParseURL("/"),
+ Host: "example.com",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ ContentLength: 4, // but we're going to try to send 8 bytes
+ },
+ Body: []byte("12345678"),
+ WantError: os.NewError("http: Request.ContentLength=4 with Body length 8"),
+ },
+
+ // Request with a 5 ContentLength and nil body.
+ {
+ Req: Request{
+ Method: "POST",
+ URL: mustParseURL("/"),
+ Host: "example.com",
+ ProtoMajor: 1,
+ ProtoMinor: 1,
+ ContentLength: 5, // but we'll omit the body
+ },
+ WantError: os.NewError("http: Request.ContentLength=5 with nil Body"),
+ },
+
+ // Verify that DumpRequest preserves the HTTP version number, doesn't add a Host,
+ // and doesn't add a User-Agent.
+ {
+ Req: Request{
+ Method: "GET",
+ URL: mustParseURL("/foo"),
+ ProtoMajor: 1,
+ ProtoMinor: 0,
+ Header: Header{
+ "X-Foo": []string{"X-Bar"},
+ },
+ },
+
+ // We can dump it:
+ WantDump: "GET /foo HTTP/1.0\r\n" +
+ "X-Foo: X-Bar\r\n\r\n",
+
+ // .. but we can't call Request.Write on it, due to its lack of Host header.
+ // TODO(bradfitz): there might be an argument to allow this, but for now I'd
+ // rather let HTTP/1.0 continue to die.
+ WantWrite: "GET /foo HTTP/1.1\r\n" +
+ "Host: \r\n" +
+ "User-Agent: Go http package\r\n" +
+ "X-Foo: X-Bar\r\n\r\n",
+ },
}
func TestRequestWrite(t *testing.T) {
@@ -283,6 +354,9 @@ func TestRequestWrite(t *testing.T) {
tt := &reqWriteTests[i]
setBody := func() {
+ if tt.Body == nil {
+ return
+ }
switch b := tt.Body.(type) {
case []byte:
tt.Req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
@@ -290,37 +364,55 @@ func TestRequestWrite(t *testing.T) {
tt.Req.Body = b()
}
}
- if tt.Body != nil {
- setBody()
- }
+ setBody()
if tt.Req.Header == nil {
tt.Req.Header = make(Header)
}
+
var braw bytes.Buffer
err := tt.Req.Write(&braw)
- if err != nil {
- t.Errorf("error writing #%d: %s", i, err)
+ if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.WantError); g != e {
+ t.Errorf("writing #%d, err = %q, want %q", i, g, e)
continue
}
- sraw := braw.String()
- if sraw != tt.Raw {
- t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, tt.Raw, sraw)
+ if err != nil {
continue
}
- if tt.Body != nil {
- setBody()
+ if tt.WantWrite != "" {
+ sraw := braw.String()
+ if sraw != tt.WantWrite {
+ t.Errorf("Test %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantWrite, sraw)
+ continue
+ }
}
- var praw bytes.Buffer
- err = tt.Req.WriteProxy(&praw)
- if err != nil {
- t.Errorf("error writing #%d: %s", i, err)
- continue
+
+ if tt.WantProxy != "" {
+ setBody()
+ var praw bytes.Buffer
+ err = tt.Req.WriteProxy(&praw)
+ if err != nil {
+ t.Errorf("WriteProxy #%d: %s", i, err)
+ continue
+ }
+ sraw := praw.String()
+ if sraw != tt.WantProxy {
+ t.Errorf("Test Proxy %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantProxy, sraw)
+ continue
+ }
}
- sraw = praw.String()
- if sraw != tt.RawProxy {
- t.Errorf("Test Proxy %d, expecting:\n%s\nGot:\n%s\n", i, tt.RawProxy, sraw)
- continue
+
+ if tt.WantDump != "" {
+ setBody()
+ dump, err := DumpRequest(&tt.Req, true)
+ if err != nil {
+ t.Errorf("DumpRequest #%d: %s", i, err)
+ continue
+ }
+ if string(dump) != tt.WantDump {
+ t.Errorf("DumpRequest %d, expecting:\n%s\nGot:\n%s\n", i, tt.WantDump, string(dump))
+ continue
+ }
}
}
}
@@ -368,3 +460,11 @@ func TestRequestWriteClosesBody(t *testing.T) {
func chunk(s string) string {
return fmt.Sprintf("%x\r\n%s\r\n", len(s), s)
}
+
+func mustParseURL(s string) *url.URL {
+ u, err := url.Parse(s)
+ if err != nil {
+ panic(fmt.Sprintf("Error parsing URL %q: %v", s, err))
+ }
+ return u
+}
diff --git a/libgo/go/http/response.go b/libgo/go/http/response.go
index 915327a69ec..56c65b53c7a 100644
--- a/libgo/go/http/response.go
+++ b/libgo/go/http/response.go
@@ -13,6 +13,7 @@ import (
"os"
"strconv"
"strings"
+ "url"
)
var respExcludeHeader = map[string]bool{
@@ -41,6 +42,10 @@ type Response struct {
Header Header
// Body represents the response body.
+ //
+ // The http Client and Transport guarantee that Body is always
+ // non-nil, even on responses without a body or responses with
+ // a zero-lengthed body.
Body io.ReadCloser
// ContentLength records the length of the associated content. The
@@ -73,6 +78,23 @@ func (r *Response) Cookies() []*Cookie {
return readSetCookies(r.Header)
}
+var ErrNoLocation = os.NewError("http: no Location header in response")
+
+// Location returns the URL of the response's "Location" header,
+// if present. Relative redirects are resolved relative to
+// the Response's Request. ErrNoLocation is returned if no
+// Location header is present.
+func (r *Response) Location() (*url.URL, os.Error) {
+ lv := r.Header.Get("Location")
+ if lv == "" {
+ return nil, ErrNoLocation
+ }
+ if r.Request != nil && r.Request.URL != nil {
+ return r.Request.URL.Parse(lv)
+ }
+ return url.Parse(lv)
+}
+
// ReadResponse reads and returns an HTTP response from r. The
// req parameter specifies the Request that corresponds to
// this Response. Clients must call resp.Body.Close when finished
diff --git a/libgo/go/http/response_test.go b/libgo/go/http/response_test.go
index 1d4a2342358..86494bf4ae9 100644
--- a/libgo/go/http/response_test.go
+++ b/libgo/go/http/response_test.go
@@ -15,6 +15,7 @@ import (
"io/ioutil"
"reflect"
"testing"
+ "url"
)
type respTest struct {
@@ -395,3 +396,52 @@ func diff(t *testing.T, prefix string, have, want interface{}) {
}
}
}
+
+type responseLocationTest struct {
+ location string // Response's Location header or ""
+ requrl string // Response.Request.URL or ""
+ want string
+ wantErr os.Error
+}
+
+var responseLocationTests = []responseLocationTest{
+ {"/foo", "http://bar.com/baz", "http://bar.com/foo", nil},
+ {"http://foo.com/", "http://bar.com/baz", "http://foo.com/", nil},
+ {"", "http://bar.com/baz", "", ErrNoLocation},
+}
+
+func TestLocationResponse(t *testing.T) {
+ for i, tt := range responseLocationTests {
+ res := new(Response)
+ res.Header = make(Header)
+ res.Header.Set("Location", tt.location)
+ if tt.requrl != "" {
+ res.Request = &Request{}
+ var err os.Error
+ res.Request.URL, err = url.Parse(tt.requrl)
+ if err != nil {
+ t.Fatalf("bad test URL %q: %v", tt.requrl, err)
+ }
+ }
+
+ got, err := res.Location()
+ if tt.wantErr != nil {
+ if err == nil {
+ t.Errorf("%d. err=nil; want %q", i, tt.wantErr)
+ continue
+ }
+ if g, e := err.String(), tt.wantErr.String(); g != e {
+ t.Errorf("%d. err=%q; want %q", i, g, e)
+ continue
+ }
+ continue
+ }
+ if err != nil {
+ t.Errorf("%d. err=%q", i, err)
+ continue
+ }
+ if g, e := got.String(), tt.want; g != e {
+ t.Errorf("%d. Location=%q; want %q", i, g, e)
+ }
+ }
+}
diff --git a/libgo/go/http/serve_test.go b/libgo/go/http/serve_test.go
index ac040334596..2ff66d5ce55 100644
--- a/libgo/go/http/serve_test.go
+++ b/libgo/go/http/serve_test.go
@@ -9,14 +9,15 @@ package http_test
import (
"bufio"
"bytes"
+ "crypto/tls"
"fmt"
. "http"
"http/httptest"
"io"
"io/ioutil"
"log"
- "os"
"net"
+ "os"
"reflect"
"strings"
"syscall"
@@ -356,18 +357,17 @@ func TestIdentityResponse(t *testing.T) {
if err != nil {
t.Fatalf("error writing: %v", err)
}
- // The next ReadAll will hang for a failing test, so use a Timer instead
- // to fail more traditionally
- timer := time.AfterFunc(2e9, func() {
- t.Fatalf("Timeout expired in ReadAll.")
+
+ // The ReadAll will hang for a failing test, so use a Timer to
+ // fail explicitly.
+ goTimeout(t, 2e9, func() {
+ got, _ := ioutil.ReadAll(conn)
+ expectedSuffix := "\r\n\r\ntoo short"
+ if !strings.HasSuffix(string(got), expectedSuffix) {
+ t.Errorf("Expected output to end with %q; got response body %q",
+ expectedSuffix, string(got))
+ }
})
- defer timer.Stop()
- got, _ := ioutil.ReadAll(conn)
- expectedSuffix := "\r\n\r\ntoo short"
- if !strings.HasSuffix(string(got), expectedSuffix) {
- t.Fatalf("Expected output to end with %q; got response body %q",
- expectedSuffix, string(got))
- }
}
func testTcpConnectionCloses(t *testing.T, req string, h Handler) {
@@ -535,6 +535,25 @@ func TestHeadResponses(t *testing.T) {
}
}
+func TestTLSHandshakeTimeout(t *testing.T) {
+ ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+ ts.Config.ReadTimeout = 250e6
+ ts.StartTLS()
+ defer ts.Close()
+ conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
+ }
+ defer conn.Close()
+ goTimeout(t, 10e9, func() {
+ var buf [1]byte
+ n, err := conn.Read(buf[:])
+ if err == nil || n != 0 {
+ t.Errorf("Read = %d, %v; want an error and no bytes", n, err)
+ }
+ })
+}
+
func TestTLSServer(t *testing.T) {
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if r.TLS != nil {
@@ -545,23 +564,46 @@ func TestTLSServer(t *testing.T) {
}
}))
defer ts.Close()
- if !strings.HasPrefix(ts.URL, "https://") {
- t.Fatalf("expected test TLS server to start with https://, got %q", ts.URL)
- }
- res, err := Get(ts.URL)
+
+ // Connect an idle TCP connection to this server before we run
+ // our real tests. This idle connection used to block forever
+ // in the TLS handshake, preventing future connections from
+ // being accepted. It may prevent future accidental blocking
+ // in newConn.
+ idleConn, err := net.Dial("tcp", ts.Listener.Addr().String())
if err != nil {
- t.Fatal(err)
- }
- if res == nil {
- t.Fatalf("got nil Response")
- }
- defer res.Body.Close()
- if res.Header.Get("X-TLS-Set") != "true" {
- t.Errorf("expected X-TLS-Set response header")
- }
- if res.Header.Get("X-TLS-HandshakeComplete") != "true" {
- t.Errorf("expected X-TLS-HandshakeComplete header")
+ t.Fatalf("Dial: %v", err)
}
+ defer idleConn.Close()
+ goTimeout(t, 10e9, func() {
+ if !strings.HasPrefix(ts.URL, "https://") {
+ t.Errorf("expected test TLS server to start with https://, got %q", ts.URL)
+ return
+ }
+ noVerifyTransport := &Transport{
+ TLSClientConfig: &tls.Config{
+ InsecureSkipVerify: true,
+ },
+ }
+ client := &Client{Transport: noVerifyTransport}
+ res, err := client.Get(ts.URL)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if res == nil {
+ t.Errorf("got nil Response")
+ return
+ }
+ defer res.Body.Close()
+ if res.Header.Get("X-TLS-Set") != "true" {
+ t.Errorf("expected X-TLS-Set response header")
+ return
+ }
+ if res.Header.Get("X-TLS-HandshakeComplete") != "true" {
+ t.Errorf("expected X-TLS-HandshakeComplete header")
+ }
+ })
}
type serverExpectTest struct {
@@ -646,9 +688,11 @@ func TestServerExpect(t *testing.T) {
}
}
-func TestServerConsumesRequestBody(t *testing.T) {
+// Under a ~256KB (maxPostHandlerReadBytes) threshold, the server
+// should consume client request bodies that a handler didn't read.
+func TestServerUnreadRequestBodyLittle(t *testing.T) {
conn := new(testConn)
- body := strings.Repeat("x", 1<<20)
+ body := strings.Repeat("x", 100<<10)
conn.readBuf.Write([]byte(fmt.Sprintf(
"POST / HTTP/1.1\r\n"+
"Host: test\r\n"+
@@ -660,14 +704,49 @@ func TestServerConsumesRequestBody(t *testing.T) {
ls := &oneConnListener{conn}
go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+ defer close(done)
if conn.readBuf.Len() < len(body)/2 {
- t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
+ t.Errorf("on request, read buffer length is %d; expected about 100 KB", conn.readBuf.Len())
}
rw.WriteHeader(200)
if g, e := conn.readBuf.Len(), 0; g != e {
t.Errorf("after WriteHeader, read buffer length is %d; want %d", g, e)
}
- done <- true
+ if c := rw.Header().Get("Connection"); c != "" {
+ t.Errorf(`Connection header = %q; want ""`, c)
+ }
+ }))
+ <-done
+}
+
+// Over a ~256KB (maxPostHandlerReadBytes) threshold, the server
+// should ignore client request bodies that a handler didn't read
+// and close the connection.
+func TestServerUnreadRequestBodyLarge(t *testing.T) {
+ conn := new(testConn)
+ body := strings.Repeat("x", 1<<20)
+ conn.readBuf.Write([]byte(fmt.Sprintf(
+ "POST / HTTP/1.1\r\n"+
+ "Host: test\r\n"+
+ "Content-Length: %d\r\n"+
+ "\r\n", len(body))))
+ conn.readBuf.Write([]byte(body))
+
+ done := make(chan bool)
+
+ ls := &oneConnListener{conn}
+ go Serve(ls, HandlerFunc(func(rw ResponseWriter, req *Request) {
+ defer close(done)
+ if conn.readBuf.Len() < len(body)/2 {
+ t.Errorf("on request, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
+ }
+ rw.WriteHeader(200)
+ if conn.readBuf.Len() < len(body)/2 {
+ t.Errorf("post-WriteHeader, read buffer length is %d; expected about 1MB", conn.readBuf.Len())
+ }
+ if c := rw.Header().Get("Connection"); c != "close" {
+ t.Errorf(`Connection header = %q; want "close"`, c)
+ }
}))
<-done
}
@@ -785,6 +864,14 @@ func TestZeroLengthPostAndResponse(t *testing.T) {
}
func TestHandlerPanic(t *testing.T) {
+ testHandlerPanic(t, false)
+}
+
+func TestHandlerPanicWithHijack(t *testing.T) {
+ testHandlerPanic(t, true)
+}
+
+func testHandlerPanic(t *testing.T, withHijack bool) {
// Unlike the other tests that set the log output to ioutil.Discard
// to quiet the output, this test uses a pipe. The pipe serves three
// purposes:
@@ -805,7 +892,14 @@ func TestHandlerPanic(t *testing.T) {
log.SetOutput(pw)
defer log.SetOutput(os.Stderr)
- ts := httptest.NewServer(HandlerFunc(func(ResponseWriter, *Request) {
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ if withHijack {
+ rwc, _, err := w.(Hijacker).Hijack()
+ if err != nil {
+ t.Logf("unexpected error: %v", err)
+ }
+ defer rwc.Close()
+ }
panic("intentional death for testing")
}))
defer ts.Close()
@@ -891,9 +985,110 @@ func TestRequestLimit(t *testing.T) {
// we do support it (at least currently), so we expect a response below.
t.Fatalf("Do: %v", err)
}
- if res.StatusCode != 400 {
- t.Fatalf("expected 400 response status; got: %d %s", res.StatusCode, res.Status)
+ if res.StatusCode != 413 {
+ t.Fatalf("expected 413 response status; got: %d %s", res.StatusCode, res.Status)
+ }
+}
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (n int, err os.Error) {
+ for i := range p {
+ p[i] = byte(b)
+ }
+ return len(p), nil
+}
+
+type countReader struct {
+ r io.Reader
+ n *int64
+}
+
+func (cr countReader) Read(p []byte) (n int, err os.Error) {
+ n, err = cr.r.Read(p)
+ *cr.n += int64(n)
+ return
+}
+
+func TestRequestBodyLimit(t *testing.T) {
+ const limit = 1 << 20
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
+ r.Body = MaxBytesReader(w, r.Body, limit)
+ n, err := io.Copy(ioutil.Discard, r.Body)
+ if err == nil {
+ t.Errorf("expected error from io.Copy")
+ }
+ if n != limit {
+ t.Errorf("io.Copy = %d, want %d", n, limit)
+ }
+ }))
+ defer ts.Close()
+
+ nWritten := int64(0)
+ req, _ := NewRequest("POST", ts.URL, io.LimitReader(countReader{neverEnding('a'), &nWritten}, limit*200))
+
+ // Send the POST, but don't care it succeeds or not. The
+ // remote side is going to reply and then close the TCP
+ // connection, and HTTP doesn't really define if that's
+ // allowed or not. Some HTTP clients will get the response
+ // and some (like ours, currently) will complain that the
+ // request write failed, without reading the response.
+ //
+ // But that's okay, since what we're really testing is that
+ // the remote side hung up on us before we wrote too much.
+ _, _ = DefaultClient.Do(req)
+
+ if nWritten > limit*100 {
+ t.Errorf("handler restricted the request body to %d bytes, but client managed to write %d",
+ limit, nWritten)
+ }
+}
+
+// TestClientWriteShutdown tests that if the client shuts down the write
+// side of their TCP connection, the server doesn't send a 400 Bad Request.
+func TestClientWriteShutdown(t *testing.T) {
+ ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {}))
+ defer ts.Close()
+ conn, err := net.Dial("tcp", ts.Listener.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
}
+ err = conn.(*net.TCPConn).CloseWrite()
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
+ }
+ donec := make(chan bool)
+ go func() {
+ defer close(donec)
+ bs, err := ioutil.ReadAll(conn)
+ if err != nil {
+ t.Fatalf("ReadAll: %v", err)
+ }
+ got := string(bs)
+ if got != "" {
+ t.Errorf("read %q from server; want nothing", got)
+ }
+ }()
+ select {
+ case <-donec:
+ case <-time.After(10e9):
+ t.Fatalf("timeout")
+ }
+}
+
+// goTimeout runs f, failing t if f takes more than ns to complete.
+func goTimeout(t *testing.T, ns int64, f func()) {
+ ch := make(chan bool, 2)
+ timer := time.AfterFunc(ns, func() {
+ t.Errorf("Timeout expired after %d ns", ns)
+ ch <- true
+ })
+ defer timer.Stop()
+ go func() {
+ defer func() { ch <- true }()
+ f()
+ }()
+ <-ch
}
type errorListener struct {
diff --git a/libgo/go/http/server.go b/libgo/go/http/server.go
index b634e27d6df..9792c60e7b6 100644
--- a/libgo/go/http/server.go
+++ b/libgo/go/http/server.go
@@ -16,6 +16,7 @@ import (
"crypto/tls"
"fmt"
"io"
+ "io/ioutil"
"log"
"net"
"os"
@@ -122,27 +123,46 @@ type response struct {
// "Connection: keep-alive" response header and a
// Content-Length.
closeAfterReply bool
+
+ // requestBodyLimitHit is set by requestTooLarge when
+ // maxBytesReader hits its max size. It is checked in
+ // WriteHeader, to make sure we don't consume the the
+ // remaining request body to try to advance to the next HTTP
+ // request. Instead, when this is set, we stop doing
+ // subsequent requests on this connection and stop reading
+ // input from it.
+ requestBodyLimitHit bool
+}
+
+// requestTooLarge is called by maxBytesReader when too much input has
+// been read from the client.
+func (w *response) requestTooLarge() {
+ w.closeAfterReply = true
+ w.requestBodyLimitHit = true
+ if !w.wroteHeader {
+ w.Header().Set("Connection", "close")
+ }
}
type writerOnly struct {
io.Writer
}
-func (r *response) ReadFrom(src io.Reader) (n int64, err os.Error) {
- // Flush before checking r.chunking, as Flush will call
+func (w *response) ReadFrom(src io.Reader) (n int64, err os.Error) {
+ // Flush before checking w.chunking, as Flush will call
// WriteHeader if it hasn't been called yet, and WriteHeader
- // is what sets r.chunking.
- r.Flush()
- if !r.chunking && r.bodyAllowed() && !r.needSniff {
- if rf, ok := r.conn.rwc.(io.ReaderFrom); ok {
+ // is what sets w.chunking.
+ w.Flush()
+ if !w.chunking && w.bodyAllowed() && !w.needSniff {
+ if rf, ok := w.conn.rwc.(io.ReaderFrom); ok {
n, err = rf.ReadFrom(src)
- r.written += n
+ w.written += n
return
}
}
// Fall back to default io.Copy implementation.
- // Use wrapper to hide r.ReadFrom from io.Copy.
- return io.Copy(writerOnly{r}, src)
+ // Use wrapper to hide w.ReadFrom from io.Copy.
+ return io.Copy(writerOnly{w}, src)
}
// noLimit is an effective infinite upper bound for io.LimitedReader
@@ -159,13 +179,6 @@ func (srv *Server) newConn(rwc net.Conn) (c *conn, err os.Error) {
br := bufio.NewReader(c.lr)
bw := bufio.NewWriter(rwc)
c.buf = bufio.NewReadWriter(br, bw)
-
- if tlsConn, ok := rwc.(*tls.Conn); ok {
- tlsConn.Handshake()
- c.tlsState = new(tls.ConnectionState)
- *c.tlsState = tlsConn.ConnectionState()
- }
-
return c, nil
}
@@ -245,6 +258,17 @@ func (w *response) Header() Header {
return w.header
}
+// maxPostHandlerReadBytes is the max number of Request.Body bytes not
+// consumed by a handler that the server will read from the a client
+// in order to keep a connection alive. If there are more bytes than
+// this then the server to be paranoid instead sends a "Connection:
+// close" response.
+//
+// This number is approximately what a typical machine's TCP buffer
+// size is anyway. (if we have the bytes on the machine, we might as
+// well read them)
+const maxPostHandlerReadBytes = 256 << 10
+
func (w *response) WriteHeader(code int) {
if w.conn.hijacked {
log.Print("http: response.WriteHeader on hijacked connection")
@@ -254,18 +278,54 @@ func (w *response) WriteHeader(code int) {
log.Print("http: multiple response.WriteHeader calls")
return
}
+ w.wroteHeader = true
+ w.status = code
+
+ // Check for a explicit (and valid) Content-Length header.
+ var hasCL bool
+ var contentLength int64
+ if clenStr := w.header.Get("Content-Length"); clenStr != "" {
+ var err os.Error
+ contentLength, err = strconv.Atoi64(clenStr)
+ if err == nil {
+ hasCL = true
+ } else {
+ log.Printf("http: invalid Content-Length of %q sent", clenStr)
+ w.header.Del("Content-Length")
+ }
+ }
+
+ if w.req.wantsHttp10KeepAlive() && (w.req.Method == "HEAD" || hasCL) {
+ _, connectionHeaderSet := w.header["Connection"]
+ if !connectionHeaderSet {
+ w.header.Set("Connection", "keep-alive")
+ }
+ } else if !w.req.ProtoAtLeast(1, 1) {
+ // Client did not ask to keep connection alive.
+ w.closeAfterReply = true
+ }
+
+ if w.header.Get("Connection") == "close" {
+ w.closeAfterReply = true
+ }
// Per RFC 2616, we should consume the request body before
- // replying, if the handler hasn't already done so.
- if w.req.ContentLength != 0 {
+ // replying, if the handler hasn't already done so. But we
+ // don't want to do an unbounded amount of reading here for
+ // DoS reasons, so we only try up to a threshold.
+ if w.req.ContentLength != 0 && !w.closeAfterReply {
ecr, isExpecter := w.req.Body.(*expectContinueReader)
if !isExpecter || ecr.resp.wroteContinue {
- w.req.Body.Close()
+ n, _ := io.CopyN(ioutil.Discard, w.req.Body, maxPostHandlerReadBytes+1)
+ if n >= maxPostHandlerReadBytes {
+ w.requestTooLarge()
+ w.header.Set("Connection", "close")
+ } else {
+ w.req.Body.Close()
+ }
}
}
- w.wroteHeader = true
- w.status = code
if code == StatusNotModified {
// Must not have body.
for _, header := range []string{"Content-Type", "Content-Length", "Transfer-Encoding"} {
@@ -288,20 +348,6 @@ func (w *response) WriteHeader(code int) {
w.Header().Set("Date", time.UTC().Format(TimeFormat))
}
- // Check for a explicit (and valid) Content-Length header.
- var hasCL bool
- var contentLength int64
- if clenStr := w.header.Get("Content-Length"); clenStr != "" {
- var err os.Error
- contentLength, err = strconv.Atoi64(clenStr)
- if err == nil {
- hasCL = true
- } else {
- log.Printf("http: invalid Content-Length of %q sent", clenStr)
- w.header.Del("Content-Length")
- }
- }
-
te := w.header.Get("Transfer-Encoding")
hasTE := te != ""
if hasCL && hasTE && te != "identity" {
@@ -334,20 +380,6 @@ func (w *response) WriteHeader(code int) {
w.header.Del("Transfer-Encoding") // in case already set
}
- if w.req.wantsHttp10KeepAlive() && (w.req.Method == "HEAD" || hasCL) {
- _, connectionHeaderSet := w.header["Connection"]
- if !connectionHeaderSet {
- w.header.Set("Connection", "keep-alive")
- }
- } else if !w.req.ProtoAtLeast(1, 1) {
- // Client did not ask to keep connection alive.
- w.closeAfterReply = true
- }
-
- if w.header.Get("Connection") == "close" {
- w.closeAfterReply = true
- }
-
// Cannot use Content-Length with non-identity Transfer-Encoding.
if w.chunking {
w.header.Del("Content-Length")
@@ -472,55 +504,6 @@ func (w *response) Write(data []byte) (n int, err os.Error) {
return m + n, err
}
-// If this is an error reply (4xx or 5xx)
-// and the handler wrote some data explaining the error,
-// some browsers (i.e., Chrome, Internet Explorer)
-// will show their own error instead unless the error is
-// long enough. The minimum lengths used in those
-// browsers are in the 256-512 range.
-// Pad to 1024 bytes.
-func errorKludge(w *response) {
- const min = 1024
-
- // Is this an error?
- if kind := w.status / 100; kind != 4 && kind != 5 {
- return
- }
-
- // Did the handler supply any info? Enough?
- if w.written == 0 || w.written >= min {
- return
- }
-
- // Is it a broken browser?
- var msg string
- switch agent := w.req.UserAgent(); {
- case strings.Contains(agent, "MSIE"):
- msg = "Internet Explorer"
- case strings.Contains(agent, "Chrome/"):
- msg = "Chrome"
- default:
- return
- }
- msg += " would ignore this error page if this text weren't here.\n"
-
- // Is it text? ("Content-Type" is always in the map)
- baseType := strings.SplitN(w.header.Get("Content-Type"), ";", 2)[0]
- switch baseType {
- case "text/html":
- io.WriteString(w, "<!-- ")
- for w.written < min {
- io.WriteString(w, msg)
- }
- io.WriteString(w, " -->")
- case "text/plain":
- io.WriteString(w, "\n")
- for w.written < min {
- io.WriteString(w, msg)
- }
- }
-}
-
func (w *response) finishRequest() {
// If this was an HTTP/1.0 request with keep-alive and we sent a Content-Length
// back, we can make this a keep-alive response ...
@@ -536,14 +519,17 @@ func (w *response) finishRequest() {
if w.needSniff {
w.sniff()
}
- errorKludge(w)
if w.chunking {
io.WriteString(w.conn.buf, "0\r\n")
// trailer key/value pairs, followed by blank line
io.WriteString(w.conn.buf, "\r\n")
}
w.conn.buf.Flush()
- w.req.Body.Close()
+ // Close the body, unless we're about to close the whole TCP connection
+ // anyway.
+ if !w.closeAfterReply {
+ w.req.Body.Close()
+ }
if w.req.MultipartForm != nil {
w.req.MultipartForm.RemoveAll()
}
@@ -581,7 +567,9 @@ func (c *conn) serve() {
if err == nil {
return
}
- c.rwc.Close()
+ if c.rwc != nil { // may be nil if connection hijacked
+ c.rwc.Close()
+ }
var buf bytes.Buffer
fmt.Fprintf(&buf, "http: panic serving %v: %v\n", c.remoteAddr, err)
@@ -589,17 +577,32 @@ func (c *conn) serve() {
log.Print(buf.String())
}()
+ if tlsConn, ok := c.rwc.(*tls.Conn); ok {
+ if err := tlsConn.Handshake(); err != nil {
+ c.close()
+ return
+ }
+ c.tlsState = new(tls.ConnectionState)
+ *c.tlsState = tlsConn.ConnectionState()
+ }
+
for {
w, err := c.readRequest()
if err != nil {
+ msg := "400 Bad Request"
if err == errTooLarge {
// Their HTTP client may or may not be
// able to read this if we're
// responding to them and hanging up
// while they're still writing their
// request. Undefined behavior.
- fmt.Fprintf(c.rwc, "HTTP/1.1 400 Request Too Large\r\n\r\n")
+ msg = "413 Request Entity Too Large"
+ } else if err == io.ErrUnexpectedEOF {
+ break // Don't reply
+ } else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
+ break // Don't reply
}
+ fmt.Fprintf(c.rwc, "HTTP/1.1 %s\r\n\r\n", msg)
break
}
@@ -774,13 +777,16 @@ func Redirect(w ResponseWriter, r *Request, urlStr string, code int) {
}
}
+var htmlReplacer = strings.NewReplacer(
+ "&", "&amp;",
+ "<", "&lt;",
+ ">", "&gt;",
+ `"`, "&quot;",
+ "'", "&apos;",
+)
+
func htmlEscape(s string) string {
- s = strings.Replace(s, "&", "&amp;", -1)
- s = strings.Replace(s, "<", "&lt;", -1)
- s = strings.Replace(s, ">", "&gt;", -1)
- s = strings.Replace(s, "\"", "&quot;", -1)
- s = strings.Replace(s, "'", "&apos;", -1)
- return s
+ return htmlReplacer.Replace(s)
}
// Redirect to a fixed URL
diff --git a/libgo/go/http/spdy/read.go b/libgo/go/http/spdy/read.go
deleted file mode 100644
index c6b6ab3af84..00000000000
--- a/libgo/go/http/spdy/read.go
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package spdy
-
-import (
- "compress/zlib"
- "encoding/binary"
- "http"
- "io"
- "os"
- "strings"
-)
-
-func (frame *SynStreamFrame) read(h ControlFrameHeader, f *Framer) os.Error {
- return f.readSynStreamFrame(h, frame)
-}
-
-func (frame *SynReplyFrame) read(h ControlFrameHeader, f *Framer) os.Error {
- return f.readSynReplyFrame(h, frame)
-}
-
-func (frame *RstStreamFrame) read(h ControlFrameHeader, f *Framer) os.Error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- if err := binary.Read(f.r, binary.BigEndian, &frame.Status); err != nil {
- return err
- }
- return nil
-}
-
-func (frame *SettingsFrame) read(h ControlFrameHeader, f *Framer) os.Error {
- frame.CFHeader = h
- var numSettings uint32
- if err := binary.Read(f.r, binary.BigEndian, &numSettings); err != nil {
- return err
- }
- frame.FlagIdValues = make([]SettingsFlagIdValue, numSettings)
- for i := uint32(0); i < numSettings; i++ {
- if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Id); err != nil {
- return err
- }
- frame.FlagIdValues[i].Flag = SettingsFlag((frame.FlagIdValues[i].Id & 0xff000000) >> 24)
- frame.FlagIdValues[i].Id &= 0xffffff
- if err := binary.Read(f.r, binary.BigEndian, &frame.FlagIdValues[i].Value); err != nil {
- return err
- }
- }
- return nil
-}
-
-func (frame *NoopFrame) read(h ControlFrameHeader, f *Framer) os.Error {
- frame.CFHeader = h
- return nil
-}
-
-func (frame *PingFrame) read(h ControlFrameHeader, f *Framer) os.Error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.Id); err != nil {
- return err
- }
- return nil
-}
-
-func (frame *GoAwayFrame) read(h ControlFrameHeader, f *Framer) os.Error {
- frame.CFHeader = h
- if err := binary.Read(f.r, binary.BigEndian, &frame.LastGoodStreamId); err != nil {
- return err
- }
- return nil
-}
-
-func (frame *HeadersFrame) read(h ControlFrameHeader, f *Framer) os.Error {
- return f.readHeadersFrame(h, frame)
-}
-
-func newControlFrame(frameType ControlFrameType) (controlFrame, os.Error) {
- ctor, ok := cframeCtor[frameType]
- if !ok {
- return nil, &Error{Err: InvalidControlFrame}
- }
- return ctor(), nil
-}
-
-var cframeCtor = map[ControlFrameType]func() controlFrame{
- TypeSynStream: func() controlFrame { return new(SynStreamFrame) },
- TypeSynReply: func() controlFrame { return new(SynReplyFrame) },
- TypeRstStream: func() controlFrame { return new(RstStreamFrame) },
- TypeSettings: func() controlFrame { return new(SettingsFrame) },
- TypeNoop: func() controlFrame { return new(NoopFrame) },
- TypePing: func() controlFrame { return new(PingFrame) },
- TypeGoAway: func() controlFrame { return new(GoAwayFrame) },
- TypeHeaders: func() controlFrame { return new(HeadersFrame) },
- // TODO(willchan): Add TypeWindowUpdate
-}
-
-func (f *Framer) uncorkHeaderDecompressor(payloadSize int64) os.Error {
- if f.headerDecompressor != nil {
- f.headerReader.N = payloadSize
- return nil
- }
- f.headerReader = io.LimitedReader{R: f.r, N: payloadSize}
- decompressor, err := zlib.NewReaderDict(&f.headerReader, []byte(HeaderDictionary))
- if err != nil {
- return err
- }
- f.headerDecompressor = decompressor
- return nil
-}
-
-// ReadFrame reads SPDY encoded data and returns a decompressed Frame.
-func (f *Framer) ReadFrame() (Frame, os.Error) {
- var firstWord uint32
- if err := binary.Read(f.r, binary.BigEndian, &firstWord); err != nil {
- return nil, err
- }
- if (firstWord & 0x80000000) != 0 {
- frameType := ControlFrameType(firstWord & 0xffff)
- version := uint16(0x7fff & (firstWord >> 16))
- return f.parseControlFrame(version, frameType)
- }
- return f.parseDataFrame(firstWord & 0x7fffffff)
-}
-
-func (f *Framer) parseControlFrame(version uint16, frameType ControlFrameType) (Frame, os.Error) {
- var length uint32
- if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- flags := ControlFlags((length & 0xff000000) >> 24)
- length &= 0xffffff
- header := ControlFrameHeader{version, frameType, flags, length}
- cframe, err := newControlFrame(frameType)
- if err != nil {
- return nil, err
- }
- if err = cframe.read(header, f); err != nil {
- return nil, err
- }
- return cframe, nil
-}
-
-func parseHeaderValueBlock(r io.Reader, streamId uint32) (http.Header, os.Error) {
- var numHeaders uint16
- if err := binary.Read(r, binary.BigEndian, &numHeaders); err != nil {
- return nil, err
- }
- var e os.Error
- h := make(http.Header, int(numHeaders))
- for i := 0; i < int(numHeaders); i++ {
- var length uint16
- if err := binary.Read(r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- nameBytes := make([]byte, length)
- if _, err := io.ReadFull(r, nameBytes); err != nil {
- return nil, err
- }
- name := string(nameBytes)
- if name != strings.ToLower(name) {
- e = &Error{UnlowercasedHeaderName, streamId}
- name = strings.ToLower(name)
- }
- if h[name] != nil {
- e = &Error{DuplicateHeaders, streamId}
- }
- if err := binary.Read(r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- value := make([]byte, length)
- if _, err := io.ReadFull(r, value); err != nil {
- return nil, err
- }
- valueList := strings.Split(string(value), "\x00")
- for _, v := range valueList {
- h.Add(name, v)
- }
- }
- if e != nil {
- return h, e
- }
- return h, nil
-}
-
-func (f *Framer) readSynStreamFrame(h ControlFrameHeader, frame *SynStreamFrame) os.Error {
- frame.CFHeader = h
- var err os.Error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- if err = binary.Read(f.r, binary.BigEndian, &frame.AssociatedToStreamId); err != nil {
- return err
- }
- if err = binary.Read(f.r, binary.BigEndian, &frame.Priority); err != nil {
- return err
- }
- frame.Priority >>= 14
-
- reader := f.r
- if !f.headerCompressionDisabled {
- f.uncorkHeaderDecompressor(int64(h.length - 10))
- reader = f.headerDecompressor
- }
-
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
- // Remove this condition when we bump Version to 3.
- if Version >= 3 {
- for h, _ := range frame.Headers {
- if invalidReqHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- }
- return nil
-}
-
-func (f *Framer) readSynReplyFrame(h ControlFrameHeader, frame *SynReplyFrame) os.Error {
- frame.CFHeader = h
- var err os.Error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- var unused uint16
- if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
- return err
- }
- reader := f.r
- if !f.headerCompressionDisabled {
- f.uncorkHeaderDecompressor(int64(h.length - 6))
- reader = f.headerDecompressor
- }
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
- // Remove this condition when we bump Version to 3.
- if Version >= 3 {
- for h, _ := range frame.Headers {
- if invalidRespHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- }
- return nil
-}
-
-func (f *Framer) readHeadersFrame(h ControlFrameHeader, frame *HeadersFrame) os.Error {
- frame.CFHeader = h
- var err os.Error
- if err = binary.Read(f.r, binary.BigEndian, &frame.StreamId); err != nil {
- return err
- }
- var unused uint16
- if err = binary.Read(f.r, binary.BigEndian, &unused); err != nil {
- return err
- }
- reader := f.r
- if !f.headerCompressionDisabled {
- f.uncorkHeaderDecompressor(int64(h.length - 6))
- reader = f.headerDecompressor
- }
- frame.Headers, err = parseHeaderValueBlock(reader, frame.StreamId)
- if !f.headerCompressionDisabled && ((err == os.EOF && f.headerReader.N == 0) || f.headerReader.N != 0) {
- err = &Error{WrongCompressedPayloadSize, 0}
- }
- if err != nil {
- return err
- }
-
- // Remove this condition when we bump Version to 3.
- if Version >= 3 {
- var invalidHeaders map[string]bool
- if frame.StreamId%2 == 0 {
- invalidHeaders = invalidReqHeaders
- } else {
- invalidHeaders = invalidRespHeaders
- }
- for h, _ := range frame.Headers {
- if invalidHeaders[h] {
- return &Error{InvalidHeaderPresent, frame.StreamId}
- }
- }
- }
- return nil
-}
-
-func (f *Framer) parseDataFrame(streamId uint32) (*DataFrame, os.Error) {
- var length uint32
- if err := binary.Read(f.r, binary.BigEndian, &length); err != nil {
- return nil, err
- }
- var frame DataFrame
- frame.StreamId = streamId
- frame.Flags = DataFlags(length >> 24)
- length &= 0xffffff
- frame.Data = make([]byte, length)
- if _, err := io.ReadFull(f.r, frame.Data); err != nil {
- return nil, err
- }
- return &frame, nil
-}
diff --git a/libgo/go/http/transfer.go b/libgo/go/http/transfer.go
index b65d99a6fd0..868a1143fd9 100644
--- a/libgo/go/http/transfer.go
+++ b/libgo/go/http/transfer.go
@@ -7,6 +7,7 @@ package http
import (
"bytes"
"bufio"
+ "fmt"
"io"
"io/ioutil"
"os"
@@ -18,10 +19,11 @@ import (
// sanitizes them without changing the user object and provides methods for
// writing the respective header, body and trailer in wire format.
type transferWriter struct {
+ Method string
Body io.Reader
BodyCloser io.Closer
ResponseToHEAD bool
- ContentLength int64
+ ContentLength int64 // -1 means unknown, 0 means exactly none
Close bool
TransferEncoding []string
Trailer Header
@@ -34,6 +36,10 @@ func newTransferWriter(r interface{}) (t *transferWriter, err os.Error) {
atLeastHTTP11 := false
switch rr := r.(type) {
case *Request:
+ if rr.ContentLength != 0 && rr.Body == nil {
+ return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
+ }
+ t.Method = rr.Method
t.Body = rr.Body
t.BodyCloser = rr.Body
t.ContentLength = rr.ContentLength
@@ -64,6 +70,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err os.Error) {
}
}
case *Response:
+ t.Method = rr.Request.Method
t.Body = rr.Body
t.BodyCloser = rr.Body
t.ContentLength = rr.ContentLength
@@ -105,6 +112,27 @@ func noBodyExpected(requestMethod string) bool {
return requestMethod == "HEAD"
}
+func (t *transferWriter) shouldSendContentLength() bool {
+ if chunked(t.TransferEncoding) {
+ return false
+ }
+ if t.ContentLength > 0 {
+ return true
+ }
+ if t.ResponseToHEAD {
+ return true
+ }
+ // Many servers expect a Content-Length for these methods
+ if t.Method == "POST" || t.Method == "PUT" {
+ return true
+ }
+ if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
+ return true
+ }
+
+ return false
+}
+
func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
if t.Close {
_, err = io.WriteString(w, "Connection: close\r\n")
@@ -116,14 +144,14 @@ func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
// Write Content-Length and/or Transfer-Encoding whose values are a
// function of the sanitized field triple (Body, ContentLength,
// TransferEncoding)
- if chunked(t.TransferEncoding) {
- _, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
+ if t.shouldSendContentLength() {
+ io.WriteString(w, "Content-Length: ")
+ _, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
if err != nil {
return
}
- } else if t.ContentLength > 0 || t.ResponseToHEAD || (t.ContentLength == 0 && isIdentity(t.TransferEncoding)) {
- io.WriteString(w, "Content-Length: ")
- _, err = io.WriteString(w, strconv.Itoa64(t.ContentLength)+"\r\n")
+ } else if chunked(t.TransferEncoding) {
+ _, err = io.WriteString(w, "Transfer-Encoding: chunked\r\n")
if err != nil {
return
}
@@ -154,6 +182,8 @@ func (t *transferWriter) WriteHeader(w io.Writer) (err os.Error) {
}
func (t *transferWriter) WriteBody(w io.Writer) (err os.Error) {
+ var ncopy int64
+
// Write body
if t.Body != nil {
if chunked(t.TransferEncoding) {
@@ -163,9 +193,14 @@ func (t *transferWriter) WriteBody(w io.Writer) (err os.Error) {
err = cw.Close()
}
} else if t.ContentLength == -1 {
- _, err = io.Copy(w, t.Body)
+ ncopy, err = io.Copy(w, t.Body)
} else {
- _, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
+ ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
+ nextra, err := io.Copy(ioutil.Discard, t.Body)
+ if err != nil {
+ return err
+ }
+ ncopy += nextra
}
if err != nil {
return err
@@ -175,6 +210,11 @@ func (t *transferWriter) WriteBody(w io.Writer) (err os.Error) {
}
}
+ if t.ContentLength != -1 && t.ContentLength != ncopy {
+ return fmt.Errorf("http: Request.ContentLength=%d with Body length %d",
+ t.ContentLength, ncopy)
+ }
+
// TODO(petar): Place trailer writer code here.
if chunked(t.TransferEncoding) {
// Last chunk, empty trailer
@@ -326,7 +366,7 @@ func fixTransferEncoding(requestMethod string, header Header) ([]string, os.Erro
return nil, nil
}
- header["Transfer-Encoding"] = nil, false
+ delete(header, "Transfer-Encoding")
// Head responses have no bodies, so the transfer encoding
// should be ignored.
@@ -359,7 +399,7 @@ func fixTransferEncoding(requestMethod string, header Header) ([]string, os.Erro
// Chunked encoding trumps Content-Length. See RFC 2616
// Section 4.4. Currently len(te) > 0 implies chunked
// encoding.
- header["Content-Length"] = nil, false
+ delete(header, "Content-Length")
return te, nil
}
@@ -478,6 +518,8 @@ type body struct {
r *bufio.Reader // underlying wire-format reader for the trailer
closing bool // is the connection to be closed after reading body?
closed bool
+
+ res *response // response writer for server requests, else nil
}
// ErrBodyReadAfterClose is returned when reading a Request Body after
@@ -506,6 +548,15 @@ func (b *body) Close() os.Error {
return nil
}
+ // In a server request, don't continue reading from the client
+ // if we've already hit the maximum body size set by the
+ // handler. If this is set, that also means the TCP connection
+ // is about to be closed, so getting to the next HTTP request
+ // in the stream is not necessary.
+ if b.res != nil && b.res.requestBodyLimitHit {
+ return nil
+ }
+
if _, err := io.Copy(ioutil.Discard, b); err != nil {
return err
}
diff --git a/libgo/go/http/transport.go b/libgo/go/http/transport.go
index 4302ffab1e3..0914af7e5cf 100644
--- a/libgo/go/http/transport.go
+++ b/libgo/go/http/transport.go
@@ -54,6 +54,10 @@ type Transport struct {
// If Dial is nil, net.Dial is used.
Dial func(net, addr string) (c net.Conn, err os.Error)
+ // TLSClientConfig specifies the TLS configuration to use with
+ // tls.Client. If nil, the default configuration is used.
+ TLSClientConfig *tls.Config
+
DisableKeepAlives bool
DisableCompression bool
@@ -96,12 +100,27 @@ func ProxyURL(fixedURL *url.URL) func(*Request) (*url.URL, os.Error) {
}
}
+// transportRequest is a wrapper around a *Request that adds
+// optional extra headers to write.
+type transportRequest struct {
+ *Request // original request, not to be mutated
+ extra Header // extra headers to write, or nil
+}
+
+func (tr *transportRequest) extraHeaders() Header {
+ if tr.extra == nil {
+ tr.extra = make(Header)
+ }
+ return tr.extra
+}
+
// RoundTrip implements the RoundTripper interface.
func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) {
if req.URL == nil {
- if req.URL, err = url.Parse(req.RawURL); err != nil {
- return
- }
+ return nil, os.NewError("http: nil Request.URL")
+ }
+ if req.Header == nil {
+ return nil, os.NewError("http: nil Request.Header")
}
if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
t.lk.Lock()
@@ -115,8 +134,8 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) {
}
return rt.RoundTrip(req)
}
-
- cm, err := t.connectMethodForRequest(req)
+ treq := &transportRequest{Request: req}
+ cm, err := t.connectMethodForRequest(treq)
if err != nil {
return nil, err
}
@@ -130,7 +149,7 @@ func (t *Transport) RoundTrip(req *Request) (resp *Response, err os.Error) {
return nil, err
}
- return pconn.roundTrip(req)
+ return pconn.roundTrip(treq)
}
// RegisterProtocol registers a new protocol with scheme.
@@ -183,14 +202,14 @@ func getenvEitherCase(k string) string {
return os.Getenv(strings.ToLower(k))
}
-func (t *Transport) connectMethodForRequest(req *Request) (*connectMethod, os.Error) {
+func (t *Transport) connectMethodForRequest(treq *transportRequest) (*connectMethod, os.Error) {
cm := &connectMethod{
- targetScheme: req.URL.Scheme,
- targetAddr: canonicalAddr(req.URL),
+ targetScheme: treq.URL.Scheme,
+ targetAddr: canonicalAddr(treq.URL),
}
if t.Proxy != nil {
var err os.Error
- cm.proxyURL, err = t.Proxy(req)
+ cm.proxyURL, err = t.Proxy(treq.Request)
if err != nil {
return nil, err
}
@@ -247,7 +266,7 @@ func (t *Transport) getIdleConn(cm *connectMethod) (pconn *persistConn) {
}
if len(pconns) == 1 {
pconn = pconns[0]
- t.idleConn[key] = nil, false
+ delete(t.idleConn, key)
} else {
// 2 or more cached connections; pop last
// TODO: queue?
@@ -293,25 +312,21 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) {
conn: conn,
reqch: make(chan requestAndChan, 50),
}
- newClientConnFunc := NewClientConn
switch {
case cm.proxyURL == nil:
// Do nothing.
case cm.targetScheme == "http":
- newClientConnFunc = NewProxyClientConn
+ pconn.isProxy = true
if pa != "" {
- pconn.mutateRequestFunc = func(req *Request) {
- if req.Header == nil {
- req.Header = make(Header)
- }
- req.Header.Set("Proxy-Authorization", pa)
+ pconn.mutateHeaderFunc = func(h Header) {
+ h.Set("Proxy-Authorization", pa)
}
}
case cm.targetScheme == "https":
connectReq := &Request{
Method: "CONNECT",
- RawURL: cm.targetAddr,
+ URL: &url.URL{RawPath: cm.targetAddr},
Host: cm.targetAddr,
Header: make(Header),
}
@@ -338,7 +353,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) {
if cm.targetScheme == "https" {
// Initiate TLS and check remote host name against certificate.
- conn = tls.Client(conn, nil)
+ conn = tls.Client(conn, t.TLSClientConfig)
if err = conn.(*tls.Conn).Handshake(); err != nil {
return nil, err
}
@@ -349,7 +364,7 @@ func (t *Transport) getConn(cm *connectMethod) (*persistConn, os.Error) {
}
pconn.br = bufio.NewReader(pconn.conn)
- pconn.cc = newClientConnFunc(conn, pconn.br)
+ pconn.cc = NewClientConn(conn, pconn.br)
go pconn.readLoop()
return pconn, nil
}
@@ -445,30 +460,21 @@ func (cm *connectMethod) tlsHost() string {
return h
}
-type readResult struct {
- res *Response // either res or err will be set
- err os.Error
-}
-
-type writeRequest struct {
- // Set by client (in pc.roundTrip)
- req *Request
- resch chan *readResult
-
- // Set by writeLoop if an error writing headers.
- writeErr os.Error
-}
-
// persistConn wraps a connection, usually a persistent one
// (but may be used for non-keep-alive requests as well)
type persistConn struct {
- t *Transport
- cacheKey string // its connectMethod.String()
- conn net.Conn
- cc *ClientConn
- br *bufio.Reader
- reqch chan requestAndChan // written by roundTrip(); read by readLoop()
- mutateRequestFunc func(*Request) // nil or func to modify each outbound request
+ t *Transport
+ cacheKey string // its connectMethod.String()
+ conn net.Conn
+ cc *ClientConn
+ br *bufio.Reader
+ reqch chan requestAndChan // written by roundTrip(); read by readLoop()
+ isProxy bool
+
+ // mutateHeaderFunc is an optional func to modify extra
+ // headers on each outbound request before it's written. (the
+ // original Request given to RoundTrip is not modified)
+ mutateHeaderFunc func(Header)
lk sync.Mutex // guards numExpectedResponses and broken
numExpectedResponses int
@@ -487,12 +493,24 @@ func (pc *persistConn) expectingResponse() bool {
return pc.numExpectedResponses > 0
}
+var remoteSideClosedFunc func(os.Error) bool // or nil to use default
+
+func remoteSideClosed(err os.Error) bool {
+ if err == os.EOF || err == os.EINVAL {
+ return true
+ }
+ if remoteSideClosedFunc != nil {
+ return remoteSideClosedFunc(err)
+ }
+ return false
+}
+
func (pc *persistConn) readLoop() {
alive := true
for alive {
pb, err := pc.br.Peek(1)
if err != nil {
- if (err == os.EOF || err == os.EINVAL) && !pc.expectingResponse() {
+ if remoteSideClosed(err) && !pc.expectingResponse() {
// Remote side closed on us. (We probably hit their
// max idle timeout)
pc.close()
@@ -512,9 +530,6 @@ func (pc *persistConn) readLoop() {
if err != nil || resp.ContentLength == 0 {
return resp, err
}
- if rc.addedGzip {
- forReq.Header.Del("Accept-Encoding")
- }
if rc.addedGzip && resp.Header.Get("Content-Encoding") == "gzip" {
resp.Header.Del("Content-Encoding")
resp.Header.Del("Content-Length")
@@ -590,9 +605,9 @@ type requestAndChan struct {
addedGzip bool
}
-func (pc *persistConn) roundTrip(req *Request) (resp *Response, err os.Error) {
- if pc.mutateRequestFunc != nil {
- pc.mutateRequestFunc(req)
+func (pc *persistConn) roundTrip(req *transportRequest) (resp *Response, err os.Error) {
+ if pc.mutateHeaderFunc != nil {
+ pc.mutateHeaderFunc(req.extraHeaders())
}
// Ask for a compressed version if the caller didn't set their
@@ -602,24 +617,28 @@ func (pc *persistConn) roundTrip(req *Request) (resp *Response, err os.Error) {
requestedGzip := false
if !pc.t.DisableCompression && req.Header.Get("Accept-Encoding") == "" {
// Request gzip only, not deflate. Deflate is ambiguous and
- // as universally supported anyway.
+ // not as universally supported anyway.
// See: http://www.gzip.org/zlib/zlib_faq.html#faq38
requestedGzip = true
- req.Header.Set("Accept-Encoding", "gzip")
+ req.extraHeaders().Set("Accept-Encoding", "gzip")
}
pc.lk.Lock()
pc.numExpectedResponses++
pc.lk.Unlock()
- err = pc.cc.Write(req)
+ pc.cc.writeReq = func(r *Request, w io.Writer) os.Error {
+ return r.write(w, pc.isProxy, req.extra)
+ }
+
+ err = pc.cc.Write(req.Request)
if err != nil {
pc.close()
return
}
ch := make(chan responseAndError, 1)
- pc.reqch <- requestAndChan{req, ch, requestedGzip}
+ pc.reqch <- requestAndChan{req.Request, ch, requestedGzip}
re := <-ch
pc.lk.Lock()
pc.numExpectedResponses--
@@ -634,7 +653,7 @@ func (pc *persistConn) close() {
pc.broken = true
pc.cc.Close()
pc.conn.Close()
- pc.mutateRequestFunc = nil
+ pc.mutateHeaderFunc = nil
}
var portMap = map[string]string{
diff --git a/libgo/go/http/transport_test.go b/libgo/go/http/transport_test.go
index eafde7f8995..f3162b9ede4 100644
--- a/libgo/go/http/transport_test.go
+++ b/libgo/go/http/transport_test.go
@@ -78,7 +78,7 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
fetch := func(n int) string {
req := new(Request)
var err os.Error
- req.URL, err = url.Parse(ts.URL + fmt.Sprintf("?close=%v", connectionClose))
+ req.URL, err = url.Parse(ts.URL + fmt.Sprintf("/?close=%v", connectionClose))
if err != nil {
t.Fatalf("URL parse error: %v", err)
}
@@ -362,32 +362,6 @@ func TestTransportHeadChunkedResponse(t *testing.T) {
}
}
-func TestTransportNilURL(t *testing.T) {
- ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
- fmt.Fprintf(w, "Hi")
- }))
- defer ts.Close()
-
- req := new(Request)
- req.URL = nil // what we're actually testing
- req.Method = "GET"
- req.RawURL = ts.URL
- req.Proto = "HTTP/1.1"
- req.ProtoMajor = 1
- req.ProtoMinor = 1
- req.Header = make(Header)
-
- tr := &Transport{}
- res, err := tr.RoundTrip(req)
- if err != nil {
- t.Fatalf("unexpected RoundTrip error: %v", err)
- }
- body, err := ioutil.ReadAll(res.Body)
- if g, e := string(body), "Hi"; g != e {
- t.Fatalf("Expected response body of %q; got %q", e, g)
- }
-}
-
var roundTripTests = []struct {
accept string
expectAccept string
@@ -398,7 +372,8 @@ var roundTripTests = []struct {
// Requests with other accept-encoding should pass through unmodified
{"foo", "foo", false},
// Requests with accept-encoding == gzip should be passed through
- {"gzip", "gzip", true}}
+ {"gzip", "gzip", true},
+}
// Test that the modification made to the Request by the RoundTripper is cleaned up
func TestRoundTripGzip(t *testing.T) {
@@ -406,7 +381,8 @@ func TestRoundTripGzip(t *testing.T) {
ts := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) {
accept := req.Header.Get("Accept-Encoding")
if expect := req.FormValue("expect_accept"); accept != expect {
- t.Errorf("Accept-Encoding = %q, want %q", accept, expect)
+ t.Errorf("in handler, test %v: Accept-Encoding = %q, want %q",
+ req.FormValue("testnum"), accept, expect)
}
if accept == "gzip" {
rw.Header().Set("Content-Encoding", "gzip")
@@ -422,8 +398,10 @@ func TestRoundTripGzip(t *testing.T) {
for i, test := range roundTripTests {
// Test basic request (no accept-encoding)
- req, _ := NewRequest("GET", ts.URL+"?expect_accept="+test.expectAccept, nil)
- req.Header.Set("Accept-Encoding", test.accept)
+ req, _ := NewRequest("GET", fmt.Sprintf("%s/?testnum=%d&expect_accept=%s", ts.URL, i, test.expectAccept), nil)
+ if test.accept != "" {
+ req.Header.Set("Accept-Encoding", test.accept)
+ }
res, err := DefaultTransport.RoundTrip(req)
var body []byte
if test.compressed {
@@ -435,16 +413,16 @@ func TestRoundTripGzip(t *testing.T) {
}
if err != nil {
t.Errorf("%d. Error: %q", i, err)
- } else {
- if g, e := string(body), responseBody; g != e {
- t.Errorf("%d. body = %q; want %q", i, g, e)
- }
- if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e {
- t.Errorf("%d. Accept-Encoding = %q; want %q", i, g, e)
- }
- if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e {
- t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e)
- }
+ continue
+ }
+ if g, e := string(body), responseBody; g != e {
+ t.Errorf("%d. body = %q; want %q", i, g, e)
+ }
+ if g, e := req.Header.Get("Accept-Encoding"), test.accept; g != e {
+ t.Errorf("%d. Accept-Encoding = %q; want %q (it was mutated, in violation of RoundTrip contract)", i, g, e)
+ }
+ if g, e := res.Header.Get("Content-Encoding"), test.accept; g != e {
+ t.Errorf("%d. Content-Encoding = %q; want %q", i, g, e)
}
}
@@ -474,7 +452,7 @@ func TestTransportGzip(t *testing.T) {
gz, _ := gzip.NewWriter(w)
gz.Write([]byte(testString))
if req.FormValue("body") == "large" {
- io.Copyn(gz, rand.Reader, nRandBytes)
+ io.CopyN(gz, rand.Reader, nRandBytes)
}
gz.Close()
}))
@@ -484,7 +462,7 @@ func TestTransportGzip(t *testing.T) {
c := &Client{Transport: &Transport{}}
// First fetch something large, but only read some of it.
- res, err := c.Get(ts.URL + "?body=large&chunked=" + chunked)
+ res, err := c.Get(ts.URL + "/?body=large&chunked=" + chunked)
if err != nil {
t.Fatalf("large get: %v", err)
}
@@ -504,7 +482,7 @@ func TestTransportGzip(t *testing.T) {
}
// Then something small.
- res, err = c.Get(ts.URL + "?chunked=" + chunked)
+ res, err = c.Get(ts.URL + "/?chunked=" + chunked)
if err != nil {
t.Fatal(err)
}
diff --git a/libgo/go/http/transport_windows.go b/libgo/go/http/transport_windows.go
new file mode 100644
index 00000000000..1ae7d835015
--- /dev/null
+++ b/libgo/go/http/transport_windows.go
@@ -0,0 +1,21 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http
+
+import (
+ "os"
+ "net"
+)
+
+func init() {
+ remoteSideClosedFunc = func(err os.Error) (out bool) {
+ op, ok := err.(*net.OpError)
+ if ok && op.Op == "WSARecv" && op.Net == "tcp" && op.Error == os.Errno(10058) {
+ // TODO(bradfitz): find the symbol for 10058
+ return true
+ }
+ return false
+ }
+}
diff --git a/libgo/go/image/bmp/reader.go b/libgo/go/image/bmp/reader.go
index 357da1dacdc..134de5be991 100644
--- a/libgo/go/image/bmp/reader.go
+++ b/libgo/go/image/bmp/reader.go
@@ -8,6 +8,7 @@
package bmp
import (
+ "image/color"
"image"
"io"
"os"
@@ -28,7 +29,7 @@ func readUint32(b []byte) uint32 {
// decodePaletted reads an 8 bit-per-pixel BMP image from r.
func decodePaletted(r io.Reader, c image.Config) (image.Image, os.Error) {
var tmp [4]byte
- paletted := image.NewPaletted(c.Width, c.Height, c.ColorModel.(image.PalettedColorModel))
+ paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette))
// BMP images are stored bottom-up rather than top-down.
for y := c.Height - 1; y >= 0; y-- {
p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width]
@@ -49,7 +50,7 @@ func decodePaletted(r io.Reader, c image.Config) (image.Image, os.Error) {
// decodeRGBA reads a 24 bit-per-pixel BMP image from r.
func decodeRGBA(r io.Reader, c image.Config) (image.Image, os.Error) {
- rgba := image.NewRGBA(c.Width, c.Height)
+ rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height))
// There are 3 bytes per pixel, and each row is 4-byte aligned.
b := make([]byte, (3*c.Width+3)&^3)
// BMP images are stored bottom-up rather than top-down.
@@ -77,7 +78,7 @@ func Decode(r io.Reader) (image.Image, os.Error) {
if err != nil {
return nil, err
}
- if c.ColorModel == image.RGBAColorModel {
+ if c.ColorModel == color.RGBAModel {
return decodeRGBA(r, c)
}
return decodePaletted(r, c)
@@ -128,11 +129,11 @@ func DecodeConfig(r io.Reader) (config image.Config, err os.Error) {
if err != nil {
return
}
- pcm := make(image.PalettedColorModel, 256)
+ pcm := make(color.Palette, 256)
for i := range pcm {
// BMP images are stored in BGR order rather than RGB order.
// Every 4th byte is padding.
- pcm[i] = image.RGBAColor{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
+ pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF}
}
return image.Config{pcm, width, height}, nil
case 24:
@@ -140,7 +141,7 @@ func DecodeConfig(r io.Reader) (config image.Config, err os.Error) {
err = ErrUnsupported
return
}
- return image.Config{image.RGBAColorModel, width, height}, nil
+ return image.Config{color.RGBAModel, width, height}, nil
}
err = ErrUnsupported
return
diff --git a/libgo/go/image/color.go b/libgo/go/image/color.go
deleted file mode 100644
index 501a882f02e..00000000000
--- a/libgo/go/image/color.go
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package image
-
-// Color can convert itself to alpha-premultiplied RGBA, with a possible loss
-// of precision. Each value ranges within [0, 0xFFFF], but is represented by a
-// uint32 so that multiplying by a blend factor up to 0xFFFF will not overflow.
-type Color interface {
- RGBA() (r, g, b, a uint32)
-}
-
-// RGBAColor represents a traditional 32-bit alpha-premultiplied color,
-// having 8 bits for each of red, green, blue and alpha.
-type RGBAColor struct {
- R, G, B, A uint8
-}
-
-func (c RGBAColor) RGBA() (r, g, b, a uint32) {
- r = uint32(c.R)
- r |= r << 8
- g = uint32(c.G)
- g |= g << 8
- b = uint32(c.B)
- b |= b << 8
- a = uint32(c.A)
- a |= a << 8
- return
-}
-
-// RGBA64Color represents a 64-bit alpha-premultiplied color,
-// having 16 bits for each of red, green, blue and alpha.
-type RGBA64Color struct {
- R, G, B, A uint16
-}
-
-func (c RGBA64Color) RGBA() (r, g, b, a uint32) {
- return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
-}
-
-// NRGBAColor represents a non-alpha-premultiplied 32-bit color.
-type NRGBAColor struct {
- R, G, B, A uint8
-}
-
-func (c NRGBAColor) RGBA() (r, g, b, a uint32) {
- r = uint32(c.R)
- r |= r << 8
- r *= uint32(c.A)
- r /= 0xff
- g = uint32(c.G)
- g |= g << 8
- g *= uint32(c.A)
- g /= 0xff
- b = uint32(c.B)
- b |= b << 8
- b *= uint32(c.A)
- b /= 0xff
- a = uint32(c.A)
- a |= a << 8
- return
-}
-
-// NRGBA64Color represents a non-alpha-premultiplied 64-bit color,
-// having 16 bits for each of red, green, blue and alpha.
-type NRGBA64Color struct {
- R, G, B, A uint16
-}
-
-func (c NRGBA64Color) RGBA() (r, g, b, a uint32) {
- r = uint32(c.R)
- r *= uint32(c.A)
- r /= 0xffff
- g = uint32(c.G)
- g *= uint32(c.A)
- g /= 0xffff
- b = uint32(c.B)
- b *= uint32(c.A)
- b /= 0xffff
- a = uint32(c.A)
- return
-}
-
-// AlphaColor represents an 8-bit alpha.
-type AlphaColor struct {
- A uint8
-}
-
-func (c AlphaColor) RGBA() (r, g, b, a uint32) {
- a = uint32(c.A)
- a |= a << 8
- return a, a, a, a
-}
-
-// Alpha16Color represents a 16-bit alpha.
-type Alpha16Color struct {
- A uint16
-}
-
-func (c Alpha16Color) RGBA() (r, g, b, a uint32) {
- a = uint32(c.A)
- return a, a, a, a
-}
-
-// GrayColor represents an 8-bit grayscale color.
-type GrayColor struct {
- Y uint8
-}
-
-func (c GrayColor) RGBA() (r, g, b, a uint32) {
- y := uint32(c.Y)
- y |= y << 8
- return y, y, y, 0xffff
-}
-
-// Gray16Color represents a 16-bit grayscale color.
-type Gray16Color struct {
- Y uint16
-}
-
-func (c Gray16Color) RGBA() (r, g, b, a uint32) {
- y := uint32(c.Y)
- return y, y, y, 0xffff
-}
-
-// ColorModel can convert foreign Colors, with a possible loss of precision,
-// to a Color from its own color model.
-type ColorModel interface {
- Convert(c Color) Color
-}
-
-// The ColorModelFunc type is an adapter to allow the use of an ordinary
-// color conversion function as a ColorModel. If f is such a function,
-// ColorModelFunc(f) is a ColorModel object that invokes f to implement
-// the conversion.
-type ColorModelFunc func(Color) Color
-
-func (f ColorModelFunc) Convert(c Color) Color {
- return f(c)
-}
-
-func toRGBAColor(c Color) Color {
- if _, ok := c.(RGBAColor); ok {
- return c
- }
- r, g, b, a := c.RGBA()
- return RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
-}
-
-func toRGBA64Color(c Color) Color {
- if _, ok := c.(RGBA64Color); ok {
- return c
- }
- r, g, b, a := c.RGBA()
- return RGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
-}
-
-func toNRGBAColor(c Color) Color {
- if _, ok := c.(NRGBAColor); ok {
- return c
- }
- r, g, b, a := c.RGBA()
- if a == 0xffff {
- return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
- }
- if a == 0 {
- return NRGBAColor{0, 0, 0, 0}
- }
- // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
- r = (r * 0xffff) / a
- g = (g * 0xffff) / a
- b = (b * 0xffff) / a
- return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
-}
-
-func toNRGBA64Color(c Color) Color {
- if _, ok := c.(NRGBA64Color); ok {
- return c
- }
- r, g, b, a := c.RGBA()
- if a == 0xffff {
- return NRGBA64Color{uint16(r), uint16(g), uint16(b), 0xffff}
- }
- if a == 0 {
- return NRGBA64Color{0, 0, 0, 0}
- }
- // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
- r = (r * 0xffff) / a
- g = (g * 0xffff) / a
- b = (b * 0xffff) / a
- return NRGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
-}
-
-func toAlphaColor(c Color) Color {
- if _, ok := c.(AlphaColor); ok {
- return c
- }
- _, _, _, a := c.RGBA()
- return AlphaColor{uint8(a >> 8)}
-}
-
-func toAlpha16Color(c Color) Color {
- if _, ok := c.(Alpha16Color); ok {
- return c
- }
- _, _, _, a := c.RGBA()
- return Alpha16Color{uint16(a)}
-}
-
-func toGrayColor(c Color) Color {
- if _, ok := c.(GrayColor); ok {
- return c
- }
- r, g, b, _ := c.RGBA()
- y := (299*r + 587*g + 114*b + 500) / 1000
- return GrayColor{uint8(y >> 8)}
-}
-
-func toGray16Color(c Color) Color {
- if _, ok := c.(Gray16Color); ok {
- return c
- }
- r, g, b, _ := c.RGBA()
- y := (299*r + 587*g + 114*b + 500) / 1000
- return Gray16Color{uint16(y)}
-}
-
-// The ColorModel associated with RGBAColor.
-var RGBAColorModel ColorModel = ColorModelFunc(toRGBAColor)
-
-// The ColorModel associated with RGBA64Color.
-var RGBA64ColorModel ColorModel = ColorModelFunc(toRGBA64Color)
-
-// The ColorModel associated with NRGBAColor.
-var NRGBAColorModel ColorModel = ColorModelFunc(toNRGBAColor)
-
-// The ColorModel associated with NRGBA64Color.
-var NRGBA64ColorModel ColorModel = ColorModelFunc(toNRGBA64Color)
-
-// The ColorModel associated with AlphaColor.
-var AlphaColorModel ColorModel = ColorModelFunc(toAlphaColor)
-
-// The ColorModel associated with Alpha16Color.
-var Alpha16ColorModel ColorModel = ColorModelFunc(toAlpha16Color)
-
-// The ColorModel associated with GrayColor.
-var GrayColorModel ColorModel = ColorModelFunc(toGrayColor)
-
-// The ColorModel associated with Gray16Color.
-var Gray16ColorModel ColorModel = ColorModelFunc(toGray16Color)
diff --git a/libgo/go/image/color/color.go b/libgo/go/image/color/color.go
new file mode 100644
index 00000000000..4a0fae5a789
--- /dev/null
+++ b/libgo/go/image/color/color.go
@@ -0,0 +1,293 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package color implements a basic color library.
+package color
+
+// Color can convert itself to alpha-premultiplied 16-bits per channel RGBA.
+// The conversion may be lossy.
+type Color interface {
+ // RGBA returns the alpha-premultiplied red, green, blue and alpha values
+ // for the color. Each value ranges within [0, 0xFFFF], but is represented
+ // by a uint32 so that multiplying by a blend factor up to 0xFFFF will not
+ // overflow.
+ RGBA() (r, g, b, a uint32)
+}
+
+// RGBA represents a traditional 32-bit alpha-premultiplied color,
+// having 8 bits for each of red, green, blue and alpha.
+type RGBA struct {
+ R, G, B, A uint8
+}
+
+func (c RGBA) RGBA() (r, g, b, a uint32) {
+ r = uint32(c.R)
+ r |= r << 8
+ g = uint32(c.G)
+ g |= g << 8
+ b = uint32(c.B)
+ b |= b << 8
+ a = uint32(c.A)
+ a |= a << 8
+ return
+}
+
+// RGBA64 represents a 64-bit alpha-premultiplied color,
+// having 16 bits for each of red, green, blue and alpha.
+type RGBA64 struct {
+ R, G, B, A uint16
+}
+
+func (c RGBA64) RGBA() (r, g, b, a uint32) {
+ return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
+}
+
+// NRGBA represents a non-alpha-premultiplied 32-bit color.
+type NRGBA struct {
+ R, G, B, A uint8
+}
+
+func (c NRGBA) RGBA() (r, g, b, a uint32) {
+ r = uint32(c.R)
+ r |= r << 8
+ r *= uint32(c.A)
+ r /= 0xff
+ g = uint32(c.G)
+ g |= g << 8
+ g *= uint32(c.A)
+ g /= 0xff
+ b = uint32(c.B)
+ b |= b << 8
+ b *= uint32(c.A)
+ b /= 0xff
+ a = uint32(c.A)
+ a |= a << 8
+ return
+}
+
+// NRGBA64 represents a non-alpha-premultiplied 64-bit color,
+// having 16 bits for each of red, green, blue and alpha.
+type NRGBA64 struct {
+ R, G, B, A uint16
+}
+
+func (c NRGBA64) RGBA() (r, g, b, a uint32) {
+ r = uint32(c.R)
+ r *= uint32(c.A)
+ r /= 0xffff
+ g = uint32(c.G)
+ g *= uint32(c.A)
+ g /= 0xffff
+ b = uint32(c.B)
+ b *= uint32(c.A)
+ b /= 0xffff
+ a = uint32(c.A)
+ return
+}
+
+// Alpha represents an 8-bit alpha color.
+type Alpha struct {
+ A uint8
+}
+
+func (c Alpha) RGBA() (r, g, b, a uint32) {
+ a = uint32(c.A)
+ a |= a << 8
+ return a, a, a, a
+}
+
+// Alpha16 represents a 16-bit alpha color.
+type Alpha16 struct {
+ A uint16
+}
+
+func (c Alpha16) RGBA() (r, g, b, a uint32) {
+ a = uint32(c.A)
+ return a, a, a, a
+}
+
+// Gray represents an 8-bit grayscale color.
+type Gray struct {
+ Y uint8
+}
+
+func (c Gray) RGBA() (r, g, b, a uint32) {
+ y := uint32(c.Y)
+ y |= y << 8
+ return y, y, y, 0xffff
+}
+
+// Gray16 represents a 16-bit grayscale color.
+type Gray16 struct {
+ Y uint16
+}
+
+func (c Gray16) RGBA() (r, g, b, a uint32) {
+ y := uint32(c.Y)
+ return y, y, y, 0xffff
+}
+
+// Model can convert any Color to one from its own color model. The conversion
+// may be lossy.
+type Model interface {
+ Convert(c Color) Color
+}
+
+// ModelFunc is an adapter type to allow the use of a color conversion
+// function as a Model. If f is such a function, ModelFunc(f) is a Model that
+// invokes f to implement the conversion.
+type ModelFunc func(Color) Color
+
+func (f ModelFunc) Convert(c Color) Color {
+ return f(c)
+}
+
+// RGBAModel is the Model for RGBA colors.
+var RGBAModel Model = ModelFunc(func(c Color) Color {
+ if _, ok := c.(RGBA); ok {
+ return c
+ }
+ r, g, b, a := c.RGBA()
+ return RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
+})
+
+// RGBAModel is the Model for RGBA64 colors.
+var RGBA64Model Model = ModelFunc(func(c Color) Color {
+ if _, ok := c.(RGBA64); ok {
+ return c
+ }
+ r, g, b, a := c.RGBA()
+ return RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+})
+
+// NRGBAModel is the Model for NRGBA colors.
+var NRGBAModel Model = ModelFunc(func(c Color) Color {
+ if _, ok := c.(NRGBA); ok {
+ return c
+ }
+ r, g, b, a := c.RGBA()
+ if a == 0xffff {
+ return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
+ }
+ if a == 0 {
+ return NRGBA{0, 0, 0, 0}
+ }
+ // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
+ r = (r * 0xffff) / a
+ g = (g * 0xffff) / a
+ b = (b * 0xffff) / a
+ return NRGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
+})
+
+// NRGBAModel is the Model for NRGBA64 colors.
+var NRGBA64Model Model = ModelFunc(func(c Color) Color {
+ if _, ok := c.(NRGBA64); ok {
+ return c
+ }
+ r, g, b, a := c.RGBA()
+ if a == 0xffff {
+ return NRGBA64{uint16(r), uint16(g), uint16(b), 0xffff}
+ }
+ if a == 0 {
+ return NRGBA64{0, 0, 0, 0}
+ }
+ // Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
+ r = (r * 0xffff) / a
+ g = (g * 0xffff) / a
+ b = (b * 0xffff) / a
+ return NRGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
+})
+
+// AlphaModel is the Model for Alpha colors.
+var AlphaModel Model = ModelFunc(func(c Color) Color {
+ if _, ok := c.(Alpha); ok {
+ return c
+ }
+ _, _, _, a := c.RGBA()
+ return Alpha{uint8(a >> 8)}
+})
+
+// Alpha16Model is the Model for Alpha16 colors.
+var Alpha16Model Model = ModelFunc(func(c Color) Color {
+ if _, ok := c.(Alpha16); ok {
+ return c
+ }
+ _, _, _, a := c.RGBA()
+ return Alpha16{uint16(a)}
+})
+
+// GrayModel is the Model for Gray colors.
+var GrayModel Model = ModelFunc(func(c Color) Color {
+ if _, ok := c.(Gray); ok {
+ return c
+ }
+ r, g, b, _ := c.RGBA()
+ y := (299*r + 587*g + 114*b + 500) / 1000
+ return Gray{uint8(y >> 8)}
+})
+
+// Gray16Model is the Model for Gray16 colors.
+var Gray16Model Model = ModelFunc(func(c Color) Color {
+ if _, ok := c.(Gray16); ok {
+ return c
+ }
+ r, g, b, _ := c.RGBA()
+ y := (299*r + 587*g + 114*b + 500) / 1000
+ return Gray16{uint16(y)}
+})
+
+// Palette is a palette of colors.
+type Palette []Color
+
+func diff(a, b uint32) uint32 {
+ if a > b {
+ return a - b
+ }
+ return b - a
+}
+
+// Convert returns the palette color closest to c in Euclidean R,G,B space.
+func (p Palette) Convert(c Color) Color {
+ if len(p) == 0 {
+ return nil
+ }
+ return p[p.Index(c)]
+}
+
+// Index returns the index of the palette color closest to c in Euclidean
+// R,G,B space.
+func (p Palette) Index(c Color) int {
+ cr, cg, cb, _ := c.RGBA()
+ // Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
+ cr >>= 1
+ cg >>= 1
+ cb >>= 1
+ ret, bestSSD := 0, uint32(1<<32-1)
+ for i, v := range p {
+ vr, vg, vb, _ := v.RGBA()
+ vr >>= 1
+ vg >>= 1
+ vb >>= 1
+ dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
+ ssd := (dr * dr) + (dg * dg) + (db * db)
+ if ssd < bestSSD {
+ if ssd == 0 {
+ return i
+ }
+ ret, bestSSD = i, ssd
+ }
+ }
+ return ret
+}
+
+var (
+ // Black is an opaque black Color.
+ Black = Gray16{0}
+ // White is an opaque white Color.
+ White = Gray16{0xffff}
+ // Transparent is a fully transparent Color.
+ Transparent = Alpha16{0}
+ // Opaque is a fully opaque Color.
+ Opaque = Alpha16{0xffff}
+)
diff --git a/libgo/go/image/decode_test.go b/libgo/go/image/decode_test.go
index 540d5eda5c2..b348c1d1114 100644
--- a/libgo/go/image/decode_test.go
+++ b/libgo/go/image/decode_test.go
@@ -7,6 +7,7 @@ package image_test
import (
"bufio"
"image"
+ "image/color"
"os"
"testing"
@@ -66,7 +67,7 @@ func delta(u0, u1 uint32) int {
return d
}
-func withinTolerance(c0, c1 image.Color, tolerance int) bool {
+func withinTolerance(c0, c1 color.Color, tolerance int) bool {
r0, g0, b0, a0 := c0.RGBA()
r1, g1, b1, a1 := c1.RGBA()
r := delta(r0, r1)
diff --git a/libgo/go/image/draw/bench_test.go b/libgo/go/image/draw/bench_test.go
index a99b408141e..2be91185af2 100644
--- a/libgo/go/image/draw/bench_test.go
+++ b/libgo/go/image/draw/bench_test.go
@@ -6,6 +6,7 @@ package draw
import (
"image"
+ "image/color"
"image/ycbcr"
"testing"
)
@@ -18,16 +19,16 @@ const (
// bench benchmarks drawing src and mask images onto a dst image with the
// given op and the color models to create those images from.
// The created images' pixels are initialized to non-zero values.
-func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
+func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) {
b.StopTimer()
var dst Image
switch dcm {
- case image.RGBAColorModel:
- dst1 := image.NewRGBA(dstw, dsth)
+ case color.RGBAModel:
+ dst1 := image.NewRGBA(image.Rect(0, 0, dstw, dsth))
for y := 0; y < dsth; y++ {
for x := 0; x < dstw; x++ {
- dst1.SetRGBA(x, y, image.RGBAColor{
+ dst1.SetRGBA(x, y, color.RGBA{
uint8(5 * x % 0x100),
uint8(7 * y % 0x100),
uint8((7*x + 5*y) % 0x100),
@@ -36,11 +37,11 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
}
}
dst = dst1
- case image.RGBA64ColorModel:
- dst1 := image.NewRGBA64(dstw, dsth)
+ case color.RGBA64Model:
+ dst1 := image.NewRGBA64(image.Rect(0, 0, dstw, dsth))
for y := 0; y < dsth; y++ {
for x := 0; x < dstw; x++ {
- dst1.SetRGBA64(x, y, image.RGBA64Color{
+ dst1.SetRGBA64(x, y, color.RGBA64{
uint16(53 * x % 0x10000),
uint16(59 * y % 0x10000),
uint16((59*x + 53*y) % 0x10000),
@@ -56,12 +57,12 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
var src image.Image
switch scm {
case nil:
- src = &image.ColorImage{image.RGBAColor{0x11, 0x22, 0x33, 0xff}}
- case image.RGBAColorModel:
- src1 := image.NewRGBA(srcw, srch)
+ src = &image.Uniform{color.RGBA{0x11, 0x22, 0x33, 0xff}}
+ case color.RGBAModel:
+ src1 := image.NewRGBA(image.Rect(0, 0, srcw, srch))
for y := 0; y < srch; y++ {
for x := 0; x < srcw; x++ {
- src1.SetRGBA(x, y, image.RGBAColor{
+ src1.SetRGBA(x, y, color.RGBA{
uint8(13 * x % 0x80),
uint8(11 * y % 0x80),
uint8((11*x + 13*y) % 0x80),
@@ -70,11 +71,11 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
}
}
src = src1
- case image.RGBA64ColorModel:
- src1 := image.NewRGBA64(srcw, srch)
+ case color.RGBA64Model:
+ src1 := image.NewRGBA64(image.Rect(0, 0, srcw, srch))
for y := 0; y < srch; y++ {
for x := 0; x < srcw; x++ {
- src1.SetRGBA64(x, y, image.RGBA64Color{
+ src1.SetRGBA64(x, y, color.RGBA64{
uint16(103 * x % 0x8000),
uint16(101 * y % 0x8000),
uint16((101*x + 103*y) % 0x8000),
@@ -83,11 +84,11 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
}
}
src = src1
- case image.NRGBAColorModel:
- src1 := image.NewNRGBA(srcw, srch)
+ case color.NRGBAModel:
+ src1 := image.NewNRGBA(image.Rect(0, 0, srcw, srch))
for y := 0; y < srch; y++ {
for x := 0; x < srcw; x++ {
- src1.SetNRGBA(x, y, image.NRGBAColor{
+ src1.SetNRGBA(x, y, color.NRGBA{
uint8(13 * x % 0x100),
uint8(11 * y % 0x100),
uint8((11*x + 13*y) % 0x100),
@@ -122,15 +123,15 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
switch mcm {
case nil:
// No-op.
- case image.AlphaColorModel:
- mask1 := image.NewAlpha(srcw, srch)
+ case color.AlphaModel:
+ mask1 := image.NewAlpha(image.Rect(0, 0, srcw, srch))
for y := 0; y < srch; y++ {
for x := 0; x < srcw; x++ {
a := uint8((23*x + 29*y) % 0x100)
// Glyph masks are typically mostly zero,
// so we only set a quarter of mask1's pixels.
if a >= 0xc0 {
- mask1.SetAlpha(x, y, image.AlphaColor{a})
+ mask1.SetAlpha(x, y, color.Alpha{a})
}
}
}
@@ -152,55 +153,55 @@ func bench(b *testing.B, dcm, scm, mcm image.ColorModel, op Op) {
// The BenchmarkFoo functions exercise a drawFoo fast-path function in draw.go.
func BenchmarkFillOver(b *testing.B) {
- bench(b, image.RGBAColorModel, nil, nil, Over)
+ bench(b, color.RGBAModel, nil, nil, Over)
}
func BenchmarkFillSrc(b *testing.B) {
- bench(b, image.RGBAColorModel, nil, nil, Src)
+ bench(b, color.RGBAModel, nil, nil, Src)
}
func BenchmarkCopyOver(b *testing.B) {
- bench(b, image.RGBAColorModel, image.RGBAColorModel, nil, Over)
+ bench(b, color.RGBAModel, color.RGBAModel, nil, Over)
}
func BenchmarkCopySrc(b *testing.B) {
- bench(b, image.RGBAColorModel, image.RGBAColorModel, nil, Src)
+ bench(b, color.RGBAModel, color.RGBAModel, nil, Src)
}
func BenchmarkNRGBAOver(b *testing.B) {
- bench(b, image.RGBAColorModel, image.NRGBAColorModel, nil, Over)
+ bench(b, color.RGBAModel, color.NRGBAModel, nil, Over)
}
func BenchmarkNRGBASrc(b *testing.B) {
- bench(b, image.RGBAColorModel, image.NRGBAColorModel, nil, Src)
+ bench(b, color.RGBAModel, color.NRGBAModel, nil, Src)
}
func BenchmarkYCbCr(b *testing.B) {
- bench(b, image.RGBAColorModel, ycbcr.YCbCrColorModel, nil, Over)
+ bench(b, color.RGBAModel, ycbcr.YCbCrColorModel, nil, Over)
}
func BenchmarkGlyphOver(b *testing.B) {
- bench(b, image.RGBAColorModel, nil, image.AlphaColorModel, Over)
+ bench(b, color.RGBAModel, nil, color.AlphaModel, Over)
}
func BenchmarkRGBA(b *testing.B) {
- bench(b, image.RGBAColorModel, image.RGBA64ColorModel, nil, Src)
+ bench(b, color.RGBAModel, color.RGBA64Model, nil, Src)
}
// The BenchmarkGenericFoo functions exercise the generic, slow-path code.
func BenchmarkGenericOver(b *testing.B) {
- bench(b, image.RGBA64ColorModel, image.RGBA64ColorModel, nil, Over)
+ bench(b, color.RGBA64Model, color.RGBA64Model, nil, Over)
}
func BenchmarkGenericMaskOver(b *testing.B) {
- bench(b, image.RGBA64ColorModel, image.RGBA64ColorModel, image.AlphaColorModel, Over)
+ bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Over)
}
func BenchmarkGenericSrc(b *testing.B) {
- bench(b, image.RGBA64ColorModel, image.RGBA64ColorModel, nil, Src)
+ bench(b, color.RGBA64Model, color.RGBA64Model, nil, Src)
}
func BenchmarkGenericMaskSrc(b *testing.B) {
- bench(b, image.RGBA64ColorModel, image.RGBA64ColorModel, image.AlphaColorModel, Src)
+ bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Src)
}
diff --git a/libgo/go/image/draw/clip_test.go b/libgo/go/image/draw/clip_test.go
index db40d82f546..65381f72f65 100644
--- a/libgo/go/image/draw/clip_test.go
+++ b/libgo/go/image/draw/clip_test.go
@@ -143,9 +143,9 @@ var clipTests = []clipTest{
}
func TestClip(t *testing.T) {
- dst0 := image.NewRGBA(100, 100)
- src0 := image.NewRGBA(100, 100)
- mask0 := image.NewRGBA(100, 100)
+ dst0 := image.NewRGBA(image.Rect(0, 0, 100, 100))
+ src0 := image.NewRGBA(image.Rect(0, 0, 100, 100))
+ mask0 := image.NewRGBA(image.Rect(0, 0, 100, 100))
for _, c := range clipTests {
dst := dst0.SubImage(c.dr).(*image.RGBA)
src := src0.SubImage(c.sr).(*image.RGBA)
diff --git a/libgo/go/image/draw/draw.go b/libgo/go/image/draw/draw.go
index a748ff8c77a..af02639ccd5 100644
--- a/libgo/go/image/draw/draw.go
+++ b/libgo/go/image/draw/draw.go
@@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package draw provides image composition functions
-// in the style of the Plan 9 graphics library
-// (see http://plan9.bell-labs.com/magic/man2html/2/draw)
-// and the X Render extension.
+// Package draw provides image composition functions.
+//
+// See "The Go image/draw package" for an introduction to this package:
+// http://blog.golang.org/2011/09/go-imagedraw-package.html
package draw
import (
"image"
+ "image/color"
"image/ycbcr"
)
@@ -26,12 +27,10 @@ const (
Src
)
-var zeroColor image.Color = image.AlphaColor{0}
-
// A draw.Image is an image.Image with a Set method to change a single pixel.
type Image interface {
image.Image
- Set(x, y int, c image.Color)
+ Set(x, y int, c color.Color)
}
// Draw calls DrawMask with a nil mask.
@@ -73,7 +72,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
if op == Over {
if mask == nil {
switch src0 := src.(type) {
- case *image.ColorImage:
+ case *image.Uniform:
drawFillOver(dst0, r, src0)
return
case *image.RGBA:
@@ -88,7 +87,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
}
} else if mask0, ok := mask.(*image.Alpha); ok {
switch src0 := src.(type) {
- case *image.ColorImage:
+ case *image.Uniform:
drawGlyphOver(dst0, r, src0, mask0, mp)
return
}
@@ -96,7 +95,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
} else {
if mask == nil {
switch src0 := src.(type) {
- case *image.ColorImage:
+ case *image.Uniform:
drawFillSrc(dst0, r, src0)
return
case *image.RGBA:
@@ -125,7 +124,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
}
}
- var out *image.RGBA64Color
+ var out *color.RGBA64
sy := sp.Y + y0 - r.Min.Y
my := mp.Y + y0 - r.Min.Y
for y := y0; y != y1; y, sy, my = y+dy, sy+dy, my+dy {
@@ -141,14 +140,14 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
if op == Over {
// No-op.
} else {
- dst.Set(x, y, zeroColor)
+ dst.Set(x, y, color.Transparent)
}
case ma == m && op == Src:
dst.Set(x, y, src.At(sx, sy))
default:
sr, sg, sb, sa := src.At(sx, sy).RGBA()
if out == nil {
- out = new(image.RGBA64Color)
+ out = new(color.RGBA64)
}
if op == Over {
dr, dg, db, da := dst.At(x, y).RGBA()
@@ -169,7 +168,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
}
}
-func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
+func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
sr, sg, sb, sa := src.RGBA()
// The 0x101 is here for the same reason as in drawRGBA.
a := (m - sa) * 0x101
@@ -192,7 +191,7 @@ func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
}
}
-func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.ColorImage) {
+func drawFillSrc(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
sr, sg, sb, sa := src.RGBA()
// The built-in copy function is faster than a straightforward for loop to fill the destination with
// the color, but copy requires a slice source. We therefore use a for loop to fill the first row, and
@@ -406,7 +405,7 @@ func drawYCbCr(dst *image.RGBA, r image.Rectangle, src *ycbcr.YCbCr, sp image.Po
}
}
-func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.ColorImage, mask *image.Alpha, mp image.Point) {
+func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask *image.Alpha, mp image.Point) {
i0 := (r.Min.Y-dst.Rect.Min.Y)*dst.Stride + (r.Min.X-dst.Rect.Min.X)*4
i1 := i0 + r.Dx()*4
mi0 := (mp.Y-mask.Rect.Min.Y)*mask.Stride + mp.X - mask.Rect.Min.X
diff --git a/libgo/go/image/draw/draw_test.go b/libgo/go/image/draw/draw_test.go
index 55435cc2719..663ab67a190 100644
--- a/libgo/go/image/draw/draw_test.go
+++ b/libgo/go/image/draw/draw_test.go
@@ -6,49 +6,50 @@ package draw
import (
"image"
+ "image/color"
"image/ycbcr"
"testing"
)
-func eq(c0, c1 image.Color) bool {
+func eq(c0, c1 color.Color) bool {
r0, g0, b0, a0 := c0.RGBA()
r1, g1, b1, a1 := c1.RGBA()
return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
}
func fillBlue(alpha int) image.Image {
- return image.NewColorImage(image.RGBAColor{0, 0, uint8(alpha), uint8(alpha)})
+ return image.NewUniform(color.RGBA{0, 0, uint8(alpha), uint8(alpha)})
}
func fillAlpha(alpha int) image.Image {
- return image.NewColorImage(image.AlphaColor{uint8(alpha)})
+ return image.NewUniform(color.Alpha{uint8(alpha)})
}
func vgradGreen(alpha int) image.Image {
- m := image.NewRGBA(16, 16)
+ m := image.NewRGBA(image.Rect(0, 0, 16, 16))
for y := 0; y < 16; y++ {
for x := 0; x < 16; x++ {
- m.Set(x, y, image.RGBAColor{0, uint8(y * alpha / 15), 0, uint8(alpha)})
+ m.Set(x, y, color.RGBA{0, uint8(y * alpha / 15), 0, uint8(alpha)})
}
}
return m
}
func vgradAlpha(alpha int) image.Image {
- m := image.NewAlpha(16, 16)
+ m := image.NewAlpha(image.Rect(0, 0, 16, 16))
for y := 0; y < 16; y++ {
for x := 0; x < 16; x++ {
- m.Set(x, y, image.AlphaColor{uint8(y * alpha / 15)})
+ m.Set(x, y, color.Alpha{uint8(y * alpha / 15)})
}
}
return m
}
func vgradGreenNRGBA(alpha int) image.Image {
- m := image.NewNRGBA(16, 16)
+ m := image.NewNRGBA(image.Rect(0, 0, 16, 16))
for y := 0; y < 16; y++ {
for x := 0; x < 16; x++ {
- m.Set(x, y, image.RGBAColor{0, uint8(y * 0x11), 0, uint8(alpha)})
+ m.Set(x, y, color.RGBA{0, uint8(y * 0x11), 0, uint8(alpha)})
}
}
return m
@@ -73,20 +74,20 @@ func vgradCr() image.Image {
}
func hgradRed(alpha int) Image {
- m := image.NewRGBA(16, 16)
+ m := image.NewRGBA(image.Rect(0, 0, 16, 16))
for y := 0; y < 16; y++ {
for x := 0; x < 16; x++ {
- m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), 0, 0, uint8(alpha)})
+ m.Set(x, y, color.RGBA{uint8(x * alpha / 15), 0, 0, uint8(alpha)})
}
}
return m
}
func gradYellow(alpha int) Image {
- m := image.NewRGBA(16, 16)
+ m := image.NewRGBA(image.Rect(0, 0, 16, 16))
for y := 0; y < 16; y++ {
for x := 0; x < 16; x++ {
- m.Set(x, y, image.RGBAColor{uint8(x * alpha / 15), uint8(y * alpha / 15), 0, uint8(alpha)})
+ m.Set(x, y, color.RGBA{uint8(x * alpha / 15), uint8(y * alpha / 15), 0, uint8(alpha)})
}
}
return m
@@ -97,61 +98,61 @@ type drawTest struct {
src image.Image
mask image.Image
op Op
- expected image.Color
+ expected color.Color
}
var drawTests = []drawTest{
// Uniform mask (0% opaque).
- {"nop", vgradGreen(255), fillAlpha(0), Over, image.RGBAColor{136, 0, 0, 255}},
- {"clear", vgradGreen(255), fillAlpha(0), Src, image.RGBAColor{0, 0, 0, 0}},
+ {"nop", vgradGreen(255), fillAlpha(0), Over, color.RGBA{136, 0, 0, 255}},
+ {"clear", vgradGreen(255), fillAlpha(0), Src, color.RGBA{0, 0, 0, 0}},
// Uniform mask (100%, 75%, nil) and uniform source.
// At (x, y) == (8, 8):
// The destination pixel is {136, 0, 0, 255}.
// The source pixel is {0, 0, 90, 90}.
- {"fill", fillBlue(90), fillAlpha(255), Over, image.RGBAColor{88, 0, 90, 255}},
- {"fillSrc", fillBlue(90), fillAlpha(255), Src, image.RGBAColor{0, 0, 90, 90}},
- {"fillAlpha", fillBlue(90), fillAlpha(192), Over, image.RGBAColor{100, 0, 68, 255}},
- {"fillAlphaSrc", fillBlue(90), fillAlpha(192), Src, image.RGBAColor{0, 0, 68, 68}},
- {"fillNil", fillBlue(90), nil, Over, image.RGBAColor{88, 0, 90, 255}},
- {"fillNilSrc", fillBlue(90), nil, Src, image.RGBAColor{0, 0, 90, 90}},
+ {"fill", fillBlue(90), fillAlpha(255), Over, color.RGBA{88, 0, 90, 255}},
+ {"fillSrc", fillBlue(90), fillAlpha(255), Src, color.RGBA{0, 0, 90, 90}},
+ {"fillAlpha", fillBlue(90), fillAlpha(192), Over, color.RGBA{100, 0, 68, 255}},
+ {"fillAlphaSrc", fillBlue(90), fillAlpha(192), Src, color.RGBA{0, 0, 68, 68}},
+ {"fillNil", fillBlue(90), nil, Over, color.RGBA{88, 0, 90, 255}},
+ {"fillNilSrc", fillBlue(90), nil, Src, color.RGBA{0, 0, 90, 90}},
// Uniform mask (100%, 75%, nil) and variable source.
// At (x, y) == (8, 8):
// The destination pixel is {136, 0, 0, 255}.
// The source pixel is {0, 48, 0, 90}.
- {"copy", vgradGreen(90), fillAlpha(255), Over, image.RGBAColor{88, 48, 0, 255}},
- {"copySrc", vgradGreen(90), fillAlpha(255), Src, image.RGBAColor{0, 48, 0, 90}},
- {"copyAlpha", vgradGreen(90), fillAlpha(192), Over, image.RGBAColor{100, 36, 0, 255}},
- {"copyAlphaSrc", vgradGreen(90), fillAlpha(192), Src, image.RGBAColor{0, 36, 0, 68}},
- {"copyNil", vgradGreen(90), nil, Over, image.RGBAColor{88, 48, 0, 255}},
- {"copyNilSrc", vgradGreen(90), nil, Src, image.RGBAColor{0, 48, 0, 90}},
+ {"copy", vgradGreen(90), fillAlpha(255), Over, color.RGBA{88, 48, 0, 255}},
+ {"copySrc", vgradGreen(90), fillAlpha(255), Src, color.RGBA{0, 48, 0, 90}},
+ {"copyAlpha", vgradGreen(90), fillAlpha(192), Over, color.RGBA{100, 36, 0, 255}},
+ {"copyAlphaSrc", vgradGreen(90), fillAlpha(192), Src, color.RGBA{0, 36, 0, 68}},
+ {"copyNil", vgradGreen(90), nil, Over, color.RGBA{88, 48, 0, 255}},
+ {"copyNilSrc", vgradGreen(90), nil, Src, color.RGBA{0, 48, 0, 90}},
// Uniform mask (100%, 75%, nil) and variable NRGBA source.
// At (x, y) == (8, 8):
// The destination pixel is {136, 0, 0, 255}.
// The source pixel is {0, 136, 0, 90} in NRGBA-space, which is {0, 48, 0, 90} in RGBA-space.
// The result pixel is different than in the "copy*" test cases because of rounding errors.
- {"nrgba", vgradGreenNRGBA(90), fillAlpha(255), Over, image.RGBAColor{88, 46, 0, 255}},
- {"nrgbaSrc", vgradGreenNRGBA(90), fillAlpha(255), Src, image.RGBAColor{0, 46, 0, 90}},
- {"nrgbaAlpha", vgradGreenNRGBA(90), fillAlpha(192), Over, image.RGBAColor{100, 34, 0, 255}},
- {"nrgbaAlphaSrc", vgradGreenNRGBA(90), fillAlpha(192), Src, image.RGBAColor{0, 34, 0, 68}},
- {"nrgbaNil", vgradGreenNRGBA(90), nil, Over, image.RGBAColor{88, 46, 0, 255}},
- {"nrgbaNilSrc", vgradGreenNRGBA(90), nil, Src, image.RGBAColor{0, 46, 0, 90}},
+ {"nrgba", vgradGreenNRGBA(90), fillAlpha(255), Over, color.RGBA{88, 46, 0, 255}},
+ {"nrgbaSrc", vgradGreenNRGBA(90), fillAlpha(255), Src, color.RGBA{0, 46, 0, 90}},
+ {"nrgbaAlpha", vgradGreenNRGBA(90), fillAlpha(192), Over, color.RGBA{100, 34, 0, 255}},
+ {"nrgbaAlphaSrc", vgradGreenNRGBA(90), fillAlpha(192), Src, color.RGBA{0, 34, 0, 68}},
+ {"nrgbaNil", vgradGreenNRGBA(90), nil, Over, color.RGBA{88, 46, 0, 255}},
+ {"nrgbaNilSrc", vgradGreenNRGBA(90), nil, Src, color.RGBA{0, 46, 0, 90}},
// Uniform mask (100%, 75%, nil) and variable YCbCr source.
// At (x, y) == (8, 8):
// The destination pixel is {136, 0, 0, 255}.
// The source pixel is {0, 0, 136} in YCbCr-space, which is {11, 38, 0, 255} in RGB-space.
- {"ycbcr", vgradCr(), fillAlpha(255), Over, image.RGBAColor{11, 38, 0, 255}},
- {"ycbcrSrc", vgradCr(), fillAlpha(255), Src, image.RGBAColor{11, 38, 0, 255}},
- {"ycbcrAlpha", vgradCr(), fillAlpha(192), Over, image.RGBAColor{42, 28, 0, 255}},
- {"ycbcrAlphaSrc", vgradCr(), fillAlpha(192), Src, image.RGBAColor{8, 28, 0, 192}},
- {"ycbcrNil", vgradCr(), nil, Over, image.RGBAColor{11, 38, 0, 255}},
- {"ycbcrNilSrc", vgradCr(), nil, Src, image.RGBAColor{11, 38, 0, 255}},
+ {"ycbcr", vgradCr(), fillAlpha(255), Over, color.RGBA{11, 38, 0, 255}},
+ {"ycbcrSrc", vgradCr(), fillAlpha(255), Src, color.RGBA{11, 38, 0, 255}},
+ {"ycbcrAlpha", vgradCr(), fillAlpha(192), Over, color.RGBA{42, 28, 0, 255}},
+ {"ycbcrAlphaSrc", vgradCr(), fillAlpha(192), Src, color.RGBA{8, 28, 0, 192}},
+ {"ycbcrNil", vgradCr(), nil, Over, color.RGBA{11, 38, 0, 255}},
+ {"ycbcrNilSrc", vgradCr(), nil, Src, color.RGBA{11, 38, 0, 255}},
// Variable mask and variable source.
// At (x, y) == (8, 8):
// The destination pixel is {136, 0, 0, 255}.
// The source pixel is {0, 0, 255, 255}.
// The mask pixel's alpha is 102, or 40%.
- {"generic", fillBlue(255), vgradAlpha(192), Over, image.RGBAColor{81, 0, 102, 255}},
- {"genericSrc", fillBlue(255), vgradAlpha(192), Src, image.RGBAColor{0, 0, 102, 102}},
+ {"generic", fillBlue(255), vgradAlpha(192), Over, color.RGBA{81, 0, 102, 255}},
+ {"genericSrc", fillBlue(255), vgradAlpha(192), Src, color.RGBA{0, 0, 102, 102}},
}
func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Point, mask image.Image, mp image.Point, op Op) image.Image {
@@ -163,7 +164,7 @@ func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Po
if mask != nil {
mb = mask.Bounds()
}
- golden := image.NewRGBA(b.Max.X, b.Max.Y)
+ golden := image.NewRGBA(image.Rect(0, 0, b.Max.X, b.Max.Y))
for y := r.Min.Y; y < r.Max.Y; y++ {
sy := y + sp.Y - r.Min.Y
my := y + mp.Y - r.Min.Y
@@ -191,7 +192,7 @@ func makeGolden(dst image.Image, r image.Rectangle, src image.Image, sp image.Po
_, _, _, ma = mask.At(mx, my).RGBA()
}
a := M - (sa * ma / M)
- golden.Set(x, y, image.RGBA64Color{
+ golden.Set(x, y, color.RGBA64{
uint16((dr*a + sr*ma) / M),
uint16((dg*a + sg*ma) / M),
uint16((db*a + sb*ma) / M),
@@ -281,15 +282,15 @@ func TestDrawOverlap(t *testing.T) {
// TestNonZeroSrcPt checks drawing with a non-zero src point parameter.
func TestNonZeroSrcPt(t *testing.T) {
- a := image.NewRGBA(1, 1)
- b := image.NewRGBA(2, 2)
- b.Set(0, 0, image.RGBAColor{0, 0, 0, 5})
- b.Set(1, 0, image.RGBAColor{0, 0, 5, 5})
- b.Set(0, 1, image.RGBAColor{0, 5, 0, 5})
- b.Set(1, 1, image.RGBAColor{5, 0, 0, 5})
+ a := image.NewRGBA(image.Rect(0, 0, 1, 1))
+ b := image.NewRGBA(image.Rect(0, 0, 2, 2))
+ b.Set(0, 0, color.RGBA{0, 0, 0, 5})
+ b.Set(1, 0, color.RGBA{0, 0, 5, 5})
+ b.Set(0, 1, color.RGBA{0, 5, 0, 5})
+ b.Set(1, 1, color.RGBA{5, 0, 0, 5})
Draw(a, image.Rect(0, 0, 1, 1), b, image.Pt(1, 1), Over)
- if !eq(image.RGBAColor{5, 0, 0, 5}, a.At(0, 0)) {
- t.Errorf("non-zero src pt: want %v got %v", image.RGBAColor{5, 0, 0, 5}, a.At(0, 0))
+ if !eq(color.RGBA{5, 0, 0, 5}, a.At(0, 0)) {
+ t.Errorf("non-zero src pt: want %v got %v", color.RGBA{5, 0, 0, 5}, a.At(0, 0))
}
}
@@ -310,10 +311,10 @@ func TestFill(t *testing.T) {
image.Rect(20, 20, 29, 29),
}
for _, r := range rr {
- m := image.NewRGBA(40, 30).SubImage(r).(*image.RGBA)
+ m := image.NewRGBA(image.Rect(0, 0, 40, 30)).SubImage(r).(*image.RGBA)
b := m.Bounds()
- c := image.RGBAColor{11, 0, 0, 255}
- src := &image.ColorImage{c}
+ c := color.RGBA{11, 0, 0, 255}
+ src := &image.Uniform{c}
check := func(desc string) {
for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
@@ -332,22 +333,22 @@ func TestFill(t *testing.T) {
}
check("pixel")
// Draw 1 row at a time.
- c = image.RGBAColor{0, 22, 0, 255}
- src = &image.ColorImage{c}
+ c = color.RGBA{0, 22, 0, 255}
+ src = &image.Uniform{c}
for y := b.Min.Y; y < b.Max.Y; y++ {
DrawMask(m, image.Rect(b.Min.X, y, b.Max.X, y+1), src, image.ZP, nil, image.ZP, Src)
}
check("row")
// Draw 1 column at a time.
- c = image.RGBAColor{0, 0, 33, 255}
- src = &image.ColorImage{c}
+ c = color.RGBA{0, 0, 33, 255}
+ src = &image.Uniform{c}
for x := b.Min.X; x < b.Max.X; x++ {
DrawMask(m, image.Rect(x, b.Min.Y, x+1, b.Max.Y), src, image.ZP, nil, image.ZP, Src)
}
check("column")
// Draw the whole image at once.
- c = image.RGBAColor{44, 55, 66, 77}
- src = &image.ColorImage{c}
+ c = color.RGBA{44, 55, 66, 77}
+ src = &image.Uniform{c}
DrawMask(m, b, src, image.ZP, nil, image.ZP, Src)
check("whole")
}
diff --git a/libgo/go/image/gif/reader.go b/libgo/go/image/gif/reader.go
index e39b7974604..a5a4265e47f 100644
--- a/libgo/go/image/gif/reader.go
+++ b/libgo/go/image/gif/reader.go
@@ -12,6 +12,7 @@ import (
"compress/lzw"
"fmt"
"image"
+ "image/color"
"io"
"os"
)
@@ -76,7 +77,7 @@ type decoder struct {
// Computed.
pixelSize uint
- globalColorMap image.PalettedColorModel
+ globalColorMap color.Palette
// Used when decoding.
delay []int
@@ -235,7 +236,7 @@ func (d *decoder) readHeaderAndScreenDescriptor() os.Error {
return nil
}
-func (d *decoder) readColorMap() (image.PalettedColorModel, os.Error) {
+func (d *decoder) readColorMap() (color.Palette, os.Error) {
if d.pixelSize > 8 {
return nil, fmt.Errorf("gif: can't handle %d bits per pixel", d.pixelSize)
}
@@ -248,10 +249,10 @@ func (d *decoder) readColorMap() (image.PalettedColorModel, os.Error) {
if err != nil {
return nil, fmt.Errorf("gif: short read on color map: %s", err)
}
- colorMap := make(image.PalettedColorModel, numColors)
+ colorMap := make(color.Palette, numColors)
j := 0
for i := range colorMap {
- colorMap[i] = image.RGBAColor{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
+ colorMap[i] = color.RGBA{d.tmp[j+0], d.tmp[j+1], d.tmp[j+2], 0xFF}
j += 3
}
return colorMap, nil
@@ -319,9 +320,9 @@ func (d *decoder) readGraphicControl() os.Error {
return nil
}
-func (d *decoder) setTransparency(colorMap image.PalettedColorModel) {
+func (d *decoder) setTransparency(colorMap color.Palette) {
if int(d.transparentIndex) < len(colorMap) {
- colorMap[d.transparentIndex] = image.RGBAColor{}
+ colorMap[d.transparentIndex] = color.RGBA{}
}
}
@@ -334,10 +335,7 @@ func (d *decoder) newImageFromDescriptor() (*image.Paletted, os.Error) {
width := int(d.tmp[4]) + int(d.tmp[5])<<8
height := int(d.tmp[6]) + int(d.tmp[7])<<8
d.imageFields = d.tmp[8]
- m := image.NewPaletted(width, height, nil)
- // Overwrite the rectangle to take account of left and top.
- m.Rect = image.Rect(left, top, left+width, top+height)
- return m, nil
+ return image.NewPaletted(image.Rect(left, top, left+width, top+height), nil), nil
}
func (d *decoder) readBlock() (int, os.Error) {
diff --git a/libgo/go/image/image.go b/libgo/go/image/image.go
index 11def94354a..a0dd930c7c0 100644
--- a/libgo/go/image/image.go
+++ b/libgo/go/image/image.go
@@ -3,25 +3,43 @@
// license that can be found in the LICENSE file.
// Package image implements a basic 2-D image library.
+//
+// See "The Go image package" for an introduction to this package:
+// http://blog.golang.org/2011/09/go-image-package.html
package image
+import (
+ "image/color"
+)
+
// Config holds an image's color model and dimensions.
type Config struct {
- ColorModel ColorModel
+ ColorModel color.Model
Width, Height int
}
-// Image is a finite rectangular grid of Colors drawn from a ColorModel.
+// Image is a finite rectangular grid of Colors drawn from a color model.
type Image interface {
- // ColorModel returns the Image's ColorModel.
- ColorModel() ColorModel
+ // ColorModel returns the Image's color model.
+ ColorModel() color.Model
// Bounds returns the domain for which At can return non-zero color.
// The bounds do not necessarily contain the point (0, 0).
Bounds() Rectangle
// At returns the color of the pixel at (x, y).
// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
- At(x, y int) Color
+ At(x, y int) color.Color
+}
+
+// PalettedImage is an image whose colors may come from a limited palette.
+// If m is a PalettedImage and m.ColorModel() returns a PalettedColorModel p,
+// then m.At(x, y) should be equivalent to p[m.ColorIndexAt(x, y)]. If m's
+// color model is not a PalettedColorModel, then ColorIndexAt's behavior is
+// undefined.
+type PalettedImage interface {
+ // ColorIndexAt returns the palette index of the pixel at (x, y).
+ ColorIndexAt(x, y int) uint8
+ Image
}
// RGBA is an in-memory image of RGBAColor values.
@@ -35,31 +53,31 @@ type RGBA struct {
Rect Rectangle
}
-func (p *RGBA) ColorModel() ColorModel { return RGBAColorModel }
+func (p *RGBA) ColorModel() color.Model { return color.RGBAModel }
func (p *RGBA) Bounds() Rectangle { return p.Rect }
-func (p *RGBA) At(x, y int) Color {
+func (p *RGBA) At(x, y int) color.Color {
if !(Point{x, y}.In(p.Rect)) {
- return RGBAColor{}
+ return color.RGBA{}
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
- return RGBAColor{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+ return color.RGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
}
-func (p *RGBA) Set(x, y int, c Color) {
+func (p *RGBA) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
- c1 := toRGBAColor(c).(RGBAColor)
+ c1 := color.RGBAModel.Convert(c).(color.RGBA)
p.Pix[i+0] = c1.R
p.Pix[i+1] = c1.G
p.Pix[i+2] = c1.B
p.Pix[i+3] = c1.A
}
-func (p *RGBA) SetRGBA(x, y int, c RGBAColor) {
+func (p *RGBA) SetRGBA(x, y int, c color.RGBA) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -107,9 +125,10 @@ func (p *RGBA) Opaque() bool {
}
// NewRGBA returns a new RGBA with the given width and height.
-func NewRGBA(w, h int) *RGBA {
+func NewRGBA(r Rectangle) *RGBA {
+ w, h := r.Dx(), r.Dy()
buf := make([]uint8, 4*w*h)
- return &RGBA{buf, 4 * w, Rectangle{ZP, Point{w, h}}}
+ return &RGBA{buf, 4 * w, r}
}
// RGBA64 is an in-memory image of RGBA64Color values.
@@ -123,16 +142,16 @@ type RGBA64 struct {
Rect Rectangle
}
-func (p *RGBA64) ColorModel() ColorModel { return RGBA64ColorModel }
+func (p *RGBA64) ColorModel() color.Model { return color.RGBA64Model }
func (p *RGBA64) Bounds() Rectangle { return p.Rect }
-func (p *RGBA64) At(x, y int) Color {
+func (p *RGBA64) At(x, y int) color.Color {
if !(Point{x, y}.In(p.Rect)) {
- return RGBA64Color{}
+ return color.RGBA64{}
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
- return RGBA64Color{
+ return color.RGBA64{
uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
@@ -140,12 +159,12 @@ func (p *RGBA64) At(x, y int) Color {
}
}
-func (p *RGBA64) Set(x, y int, c Color) {
+func (p *RGBA64) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
- c1 := toRGBA64Color(c).(RGBA64Color)
+ c1 := color.RGBA64Model.Convert(c).(color.RGBA64)
p.Pix[i+0] = uint8(c1.R >> 8)
p.Pix[i+1] = uint8(c1.R)
p.Pix[i+2] = uint8(c1.G >> 8)
@@ -156,7 +175,7 @@ func (p *RGBA64) Set(x, y int, c Color) {
p.Pix[i+7] = uint8(c1.A)
}
-func (p *RGBA64) SetRGBA64(x, y int, c RGBA64Color) {
+func (p *RGBA64) SetRGBA64(x, y int, c color.RGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -208,9 +227,10 @@ func (p *RGBA64) Opaque() bool {
}
// NewRGBA64 returns a new RGBA64 with the given width and height.
-func NewRGBA64(w, h int) *RGBA64 {
+func NewRGBA64(r Rectangle) *RGBA64 {
+ w, h := r.Dx(), r.Dy()
pix := make([]uint8, 8*w*h)
- return &RGBA64{pix, 8 * w, Rectangle{ZP, Point{w, h}}}
+ return &RGBA64{pix, 8 * w, r}
}
// NRGBA is an in-memory image of NRGBAColor values.
@@ -224,31 +244,31 @@ type NRGBA struct {
Rect Rectangle
}
-func (p *NRGBA) ColorModel() ColorModel { return NRGBAColorModel }
+func (p *NRGBA) ColorModel() color.Model { return color.NRGBAModel }
func (p *NRGBA) Bounds() Rectangle { return p.Rect }
-func (p *NRGBA) At(x, y int) Color {
+func (p *NRGBA) At(x, y int) color.Color {
if !(Point{x, y}.In(p.Rect)) {
- return NRGBAColor{}
+ return color.NRGBA{}
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
- return NRGBAColor{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
+ return color.NRGBA{p.Pix[i+0], p.Pix[i+1], p.Pix[i+2], p.Pix[i+3]}
}
-func (p *NRGBA) Set(x, y int, c Color) {
+func (p *NRGBA) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*4
- c1 := toNRGBAColor(c).(NRGBAColor)
+ c1 := color.NRGBAModel.Convert(c).(color.NRGBA)
p.Pix[i+0] = c1.R
p.Pix[i+1] = c1.G
p.Pix[i+2] = c1.B
p.Pix[i+3] = c1.A
}
-func (p *NRGBA) SetNRGBA(x, y int, c NRGBAColor) {
+func (p *NRGBA) SetNRGBA(x, y int, c color.NRGBA) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -296,9 +316,10 @@ func (p *NRGBA) Opaque() bool {
}
// NewNRGBA returns a new NRGBA with the given width and height.
-func NewNRGBA(w, h int) *NRGBA {
+func NewNRGBA(r Rectangle) *NRGBA {
+ w, h := r.Dx(), r.Dy()
pix := make([]uint8, 4*w*h)
- return &NRGBA{pix, 4 * w, Rectangle{ZP, Point{w, h}}}
+ return &NRGBA{pix, 4 * w, r}
}
// NRGBA64 is an in-memory image of NRGBA64Color values.
@@ -312,16 +333,16 @@ type NRGBA64 struct {
Rect Rectangle
}
-func (p *NRGBA64) ColorModel() ColorModel { return NRGBA64ColorModel }
+func (p *NRGBA64) ColorModel() color.Model { return color.NRGBA64Model }
func (p *NRGBA64) Bounds() Rectangle { return p.Rect }
-func (p *NRGBA64) At(x, y int) Color {
+func (p *NRGBA64) At(x, y int) color.Color {
if !(Point{x, y}.In(p.Rect)) {
- return NRGBA64Color{}
+ return color.NRGBA64{}
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
- return NRGBA64Color{
+ return color.NRGBA64{
uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1]),
uint16(p.Pix[i+2])<<8 | uint16(p.Pix[i+3]),
uint16(p.Pix[i+4])<<8 | uint16(p.Pix[i+5]),
@@ -329,12 +350,12 @@ func (p *NRGBA64) At(x, y int) Color {
}
}
-func (p *NRGBA64) Set(x, y int, c Color) {
+func (p *NRGBA64) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*8
- c1 := toNRGBA64Color(c).(NRGBA64Color)
+ c1 := color.NRGBA64Model.Convert(c).(color.NRGBA64)
p.Pix[i+0] = uint8(c1.R >> 8)
p.Pix[i+1] = uint8(c1.R)
p.Pix[i+2] = uint8(c1.G >> 8)
@@ -345,7 +366,7 @@ func (p *NRGBA64) Set(x, y int, c Color) {
p.Pix[i+7] = uint8(c1.A)
}
-func (p *NRGBA64) SetNRGBA64(x, y int, c NRGBA64Color) {
+func (p *NRGBA64) SetNRGBA64(x, y int, c color.NRGBA64) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -397,9 +418,10 @@ func (p *NRGBA64) Opaque() bool {
}
// NewNRGBA64 returns a new NRGBA64 with the given width and height.
-func NewNRGBA64(w, h int) *NRGBA64 {
+func NewNRGBA64(r Rectangle) *NRGBA64 {
+ w, h := r.Dx(), r.Dy()
pix := make([]uint8, 8*w*h)
- return &NRGBA64{pix, 8 * w, Rectangle{ZP, Point{w, h}}}
+ return &NRGBA64{pix, 8 * w, r}
}
// Alpha is an in-memory image of AlphaColor values.
@@ -413,27 +435,27 @@ type Alpha struct {
Rect Rectangle
}
-func (p *Alpha) ColorModel() ColorModel { return AlphaColorModel }
+func (p *Alpha) ColorModel() color.Model { return color.AlphaModel }
func (p *Alpha) Bounds() Rectangle { return p.Rect }
-func (p *Alpha) At(x, y int) Color {
+func (p *Alpha) At(x, y int) color.Color {
if !(Point{x, y}.In(p.Rect)) {
- return AlphaColor{}
+ return color.Alpha{}
}
i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
- return AlphaColor{p.Pix[i]}
+ return color.Alpha{p.Pix[i]}
}
-func (p *Alpha) Set(x, y int, c Color) {
+func (p *Alpha) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
- p.Pix[i] = toAlphaColor(c).(AlphaColor).A
+ p.Pix[i] = color.AlphaModel.Convert(c).(color.Alpha).A
}
-func (p *Alpha) SetAlpha(x, y int, c AlphaColor) {
+func (p *Alpha) SetAlpha(x, y int, c color.Alpha) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -478,9 +500,10 @@ func (p *Alpha) Opaque() bool {
}
// NewAlpha returns a new Alpha with the given width and height.
-func NewAlpha(w, h int) *Alpha {
+func NewAlpha(r Rectangle) *Alpha {
+ w, h := r.Dx(), r.Dy()
pix := make([]uint8, 1*w*h)
- return &Alpha{pix, 1 * w, Rectangle{ZP, Point{w, h}}}
+ return &Alpha{pix, 1 * w, r}
}
// Alpha16 is an in-memory image of Alpha16Color values.
@@ -494,29 +517,29 @@ type Alpha16 struct {
Rect Rectangle
}
-func (p *Alpha16) ColorModel() ColorModel { return Alpha16ColorModel }
+func (p *Alpha16) ColorModel() color.Model { return color.Alpha16Model }
func (p *Alpha16) Bounds() Rectangle { return p.Rect }
-func (p *Alpha16) At(x, y int) Color {
+func (p *Alpha16) At(x, y int) color.Color {
if !(Point{x, y}.In(p.Rect)) {
- return Alpha16Color{}
+ return color.Alpha16{}
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
- return Alpha16Color{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
+ return color.Alpha16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
}
-func (p *Alpha16) Set(x, y int, c Color) {
+func (p *Alpha16) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
- c1 := toAlpha16Color(c).(Alpha16Color)
+ c1 := color.Alpha16Model.Convert(c).(color.Alpha16)
p.Pix[i+0] = uint8(c1.A >> 8)
p.Pix[i+1] = uint8(c1.A)
}
-func (p *Alpha16) SetAlpha16(x, y int, c Alpha16Color) {
+func (p *Alpha16) SetAlpha16(x, y int, c color.Alpha16) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -562,9 +585,10 @@ func (p *Alpha16) Opaque() bool {
}
// NewAlpha16 returns a new Alpha16 with the given width and height.
-func NewAlpha16(w, h int) *Alpha16 {
+func NewAlpha16(r Rectangle) *Alpha16 {
+ w, h := r.Dx(), r.Dy()
pix := make([]uint8, 2*w*h)
- return &Alpha16{pix, 2 * w, Rectangle{ZP, Point{w, h}}}
+ return &Alpha16{pix, 2 * w, r}
}
// Gray is an in-memory image of GrayColor values.
@@ -578,27 +602,27 @@ type Gray struct {
Rect Rectangle
}
-func (p *Gray) ColorModel() ColorModel { return GrayColorModel }
+func (p *Gray) ColorModel() color.Model { return color.GrayModel }
func (p *Gray) Bounds() Rectangle { return p.Rect }
-func (p *Gray) At(x, y int) Color {
+func (p *Gray) At(x, y int) color.Color {
if !(Point{x, y}.In(p.Rect)) {
- return GrayColor{}
+ return color.Gray{}
}
i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
- return GrayColor{p.Pix[i]}
+ return color.Gray{p.Pix[i]}
}
-func (p *Gray) Set(x, y int, c Color) {
+func (p *Gray) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := (y-p.Rect.Min.Y)*p.Stride + (x - p.Rect.Min.X)
- p.Pix[i] = toGrayColor(c).(GrayColor).Y
+ p.Pix[i] = color.GrayModel.Convert(c).(color.Gray).Y
}
-func (p *Gray) SetGray(x, y int, c GrayColor) {
+func (p *Gray) SetGray(x, y int, c color.Gray) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -630,9 +654,10 @@ func (p *Gray) Opaque() bool {
}
// NewGray returns a new Gray with the given width and height.
-func NewGray(w, h int) *Gray {
+func NewGray(r Rectangle) *Gray {
+ w, h := r.Dx(), r.Dy()
pix := make([]uint8, 1*w*h)
- return &Gray{pix, 1 * w, Rectangle{ZP, Point{w, h}}}
+ return &Gray{pix, 1 * w, r}
}
// Gray16 is an in-memory image of Gray16Color values.
@@ -646,29 +671,29 @@ type Gray16 struct {
Rect Rectangle
}
-func (p *Gray16) ColorModel() ColorModel { return Gray16ColorModel }
+func (p *Gray16) ColorModel() color.Model { return color.Gray16Model }
func (p *Gray16) Bounds() Rectangle { return p.Rect }
-func (p *Gray16) At(x, y int) Color {
+func (p *Gray16) At(x, y int) color.Color {
if !(Point{x, y}.In(p.Rect)) {
- return Gray16Color{}
+ return color.Gray16{}
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
- return Gray16Color{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
+ return color.Gray16{uint16(p.Pix[i+0])<<8 | uint16(p.Pix[i+1])}
}
-func (p *Gray16) Set(x, y int, c Color) {
+func (p *Gray16) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
i := (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*2
- c1 := toGray16Color(c).(Gray16Color)
+ c1 := color.Gray16Model.Convert(c).(color.Gray16)
p.Pix[i+0] = uint8(c1.Y >> 8)
p.Pix[i+1] = uint8(c1.Y)
}
-func (p *Gray16) SetGray16(x, y int, c Gray16Color) {
+func (p *Gray16) SetGray16(x, y int, c color.Gray16) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -701,50 +726,10 @@ func (p *Gray16) Opaque() bool {
}
// NewGray16 returns a new Gray16 with the given width and height.
-func NewGray16(w, h int) *Gray16 {
+func NewGray16(r Rectangle) *Gray16 {
+ w, h := r.Dx(), r.Dy()
pix := make([]uint8, 2*w*h)
- return &Gray16{pix, 2 * w, Rectangle{ZP, Point{w, h}}}
-}
-
-// A PalettedColorModel represents a fixed palette of at most 256 colors.
-type PalettedColorModel []Color
-
-func diff(a, b uint32) uint32 {
- if a > b {
- return a - b
- }
- return b - a
-}
-
-// Convert returns the palette color closest to c in Euclidean R,G,B space.
-func (p PalettedColorModel) Convert(c Color) Color {
- if len(p) == 0 {
- return nil
- }
- return p[p.Index(c)]
-}
-
-// Index returns the index of the palette color closest to c in Euclidean
-// R,G,B space.
-func (p PalettedColorModel) Index(c Color) int {
- cr, cg, cb, _ := c.RGBA()
- // Shift by 1 bit to avoid potential uint32 overflow in sum-squared-difference.
- cr >>= 1
- cg >>= 1
- cb >>= 1
- ret, bestSSD := 0, uint32(1<<32-1)
- for i, v := range p {
- vr, vg, vb, _ := v.RGBA()
- vr >>= 1
- vg >>= 1
- vb >>= 1
- dr, dg, db := diff(cr, vr), diff(cg, vg), diff(cb, vb)
- ssd := (dr * dr) + (dg * dg) + (db * db)
- if ssd < bestSSD {
- ret, bestSSD = i, ssd
- }
- }
- return ret
+ return &Gray16{pix, 2 * w, r}
}
// Paletted is an in-memory image of uint8 indices into a given palette.
@@ -757,14 +742,14 @@ type Paletted struct {
// Rect is the image's bounds.
Rect Rectangle
// Palette is the image's palette.
- Palette PalettedColorModel
+ Palette color.Palette
}
-func (p *Paletted) ColorModel() ColorModel { return p.Palette }
+func (p *Paletted) ColorModel() color.Model { return p.Palette }
func (p *Paletted) Bounds() Rectangle { return p.Rect }
-func (p *Paletted) At(x, y int) Color {
+func (p *Paletted) At(x, y int) color.Color {
if len(p.Palette) == 0 {
return nil
}
@@ -775,7 +760,7 @@ func (p *Paletted) At(x, y int) Color {
return p.Palette[p.Pix[i]]
}
-func (p *Paletted) Set(x, y int, c Color) {
+func (p *Paletted) Set(x, y int, c color.Color) {
if !(Point{x, y}.In(p.Rect)) {
return
}
@@ -844,7 +829,8 @@ func (p *Paletted) Opaque() bool {
}
// NewPaletted returns a new Paletted with the given width, height and palette.
-func NewPaletted(w, h int, m PalettedColorModel) *Paletted {
+func NewPaletted(r Rectangle, p color.Palette) *Paletted {
+ w, h := r.Dx(), r.Dy()
pix := make([]uint8, 1*w*h)
- return &Paletted{pix, 1 * w, Rectangle{ZP, Point{w, h}}, m}
+ return &Paletted{pix, 1 * w, r, p}
}
diff --git a/libgo/go/image/image_test.go b/libgo/go/image/image_test.go
index 9519acf7906..2b3f1493fb8 100644
--- a/libgo/go/image/image_test.go
+++ b/libgo/go/image/image_test.go
@@ -6,17 +6,18 @@ package image_test
import (
. "image"
+ "image/color"
"testing"
)
type image interface {
Image
Opaque() bool
- Set(int, int, Color)
+ Set(int, int, color.Color)
SubImage(Rectangle) Image
}
-func cmp(t *testing.T, cm ColorModel, c0, c1 Color) bool {
+func cmp(t *testing.T, cm color.Model, c0, c1 color.Color) bool {
r0, g0, b0, a0 := cm.Convert(c0).RGBA()
r1, g1, b1, a1 := cm.Convert(c1).RGBA()
return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
@@ -24,15 +25,15 @@ func cmp(t *testing.T, cm ColorModel, c0, c1 Color) bool {
func TestImage(t *testing.T) {
testImage := []image{
- NewRGBA(10, 10),
- NewRGBA64(10, 10),
- NewNRGBA(10, 10),
- NewNRGBA64(10, 10),
- NewAlpha(10, 10),
- NewAlpha16(10, 10),
- NewGray(10, 10),
- NewGray16(10, 10),
- NewPaletted(10, 10, PalettedColorModel{
+ NewRGBA(Rect(0, 0, 10, 10)),
+ NewRGBA64(Rect(0, 0, 10, 10)),
+ NewNRGBA(Rect(0, 0, 10, 10)),
+ NewNRGBA64(Rect(0, 0, 10, 10)),
+ NewAlpha(Rect(0, 0, 10, 10)),
+ NewAlpha16(Rect(0, 0, 10, 10)),
+ NewGray(Rect(0, 0, 10, 10)),
+ NewGray16(Rect(0, 0, 10, 10)),
+ NewPaletted(Rect(0, 0, 10, 10), color.Palette{
Transparent,
Opaque,
}),
@@ -82,14 +83,14 @@ func TestImage(t *testing.T) {
}
func Test16BitsPerColorChannel(t *testing.T) {
- testColorModel := []ColorModel{
- RGBA64ColorModel,
- NRGBA64ColorModel,
- Alpha16ColorModel,
- Gray16ColorModel,
+ testColorModel := []color.Model{
+ color.RGBA64Model,
+ color.NRGBA64Model,
+ color.Alpha16Model,
+ color.Gray16Model,
}
for _, cm := range testColorModel {
- c := cm.Convert(RGBA64Color{0x1234, 0x1234, 0x1234, 0x1234}) // Premultiplied alpha.
+ c := cm.Convert(color.RGBA64{0x1234, 0x1234, 0x1234, 0x1234}) // Premultiplied alpha.
r, _, _, _ := c.RGBA()
if r != 0x1234 {
t.Errorf("%T: want red value 0x%04x got 0x%04x", c, 0x1234, r)
@@ -97,13 +98,13 @@ func Test16BitsPerColorChannel(t *testing.T) {
}
}
testImage := []image{
- NewRGBA64(10, 10),
- NewNRGBA64(10, 10),
- NewAlpha16(10, 10),
- NewGray16(10, 10),
+ NewRGBA64(Rect(0, 0, 10, 10)),
+ NewNRGBA64(Rect(0, 0, 10, 10)),
+ NewAlpha16(Rect(0, 0, 10, 10)),
+ NewGray16(Rect(0, 0, 10, 10)),
}
for _, m := range testImage {
- m.Set(1, 2, NRGBA64Color{0xffff, 0xffff, 0xffff, 0x1357}) // Non-premultiplied alpha.
+ m.Set(1, 2, color.NRGBA64{0xffff, 0xffff, 0xffff, 0x1357}) // Non-premultiplied alpha.
r, _, _, _ := m.At(1, 2).RGBA()
if r != 0x1357 {
t.Errorf("%T: want red value 0x%04x got 0x%04x", m, 0x1357, r)
diff --git a/libgo/go/image/jpeg/reader.go b/libgo/go/image/jpeg/reader.go
index 3f22c5271f3..450355efae5 100644
--- a/libgo/go/image/jpeg/reader.go
+++ b/libgo/go/image/jpeg/reader.go
@@ -10,6 +10,7 @@ package jpeg
import (
"bufio"
"image"
+ "image/color"
"image/ycbcr"
"io"
"os"
@@ -199,7 +200,7 @@ func (d *decoder) processDQT(n int) os.Error {
// makeImg allocates and initializes the destination image.
func (d *decoder) makeImg(h0, v0, mxx, myy int) {
if d.nComp == nGrayComponent {
- m := image.NewGray(8*mxx, 8*myy)
+ m := image.NewGray(image.Rect(0, 0, 8*mxx, 8*myy))
d.img1 = m.SubImage(image.Rect(0, 0, d.width, d.height)).(*image.Gray)
return
}
@@ -464,7 +465,7 @@ func DecodeConfig(r io.Reader) (image.Config, os.Error) {
}
switch d.nComp {
case nGrayComponent:
- return image.Config{image.GrayColorModel, d.width, d.height}, nil
+ return image.Config{color.GrayModel, d.width, d.height}, nil
case nColorComponent:
return image.Config{ycbcr.YCbCrColorModel, d.width, d.height}, nil
}
diff --git a/libgo/go/image/jpeg/writer_test.go b/libgo/go/image/jpeg/writer_test.go
index 7aec70f016e..0378252d2fb 100644
--- a/libgo/go/image/jpeg/writer_test.go
+++ b/libgo/go/image/jpeg/writer_test.go
@@ -7,6 +7,7 @@ package jpeg
import (
"bytes"
"image"
+ "image/color"
"image/png"
"io/ioutil"
"rand"
@@ -90,13 +91,13 @@ func TestWriter(t *testing.T) {
func BenchmarkEncodeRGBOpaque(b *testing.B) {
b.StopTimer()
- img := image.NewRGBA(640, 480)
+ img := image.NewRGBA(image.Rect(0, 0, 640, 480))
// Set all pixels to 0xFF alpha to force opaque mode.
bo := img.Bounds()
rnd := rand.New(rand.NewSource(123))
for y := bo.Min.Y; y < bo.Max.Y; y++ {
for x := bo.Min.X; x < bo.Max.X; x++ {
- img.Set(x, y, image.RGBAColor{
+ img.Set(x, y, color.RGBA{
uint8(rnd.Intn(256)),
uint8(rnd.Intn(256)),
uint8(rnd.Intn(256)),
diff --git a/libgo/go/image/names.go b/libgo/go/image/names.go
index c309684cea1..a7ad51d5371 100644
--- a/libgo/go/image/names.go
+++ b/libgo/go/image/names.go
@@ -4,43 +4,47 @@
package image
+import (
+ "image/color"
+)
+
var (
- // Black is an opaque black ColorImage.
- Black = NewColorImage(Gray16Color{0})
- // White is an opaque white ColorImage.
- White = NewColorImage(Gray16Color{0xffff})
- // Transparent is a fully transparent ColorImage.
- Transparent = NewColorImage(Alpha16Color{0})
- // Opaque is a fully opaque ColorImage.
- Opaque = NewColorImage(Alpha16Color{0xffff})
+ // Black is an opaque black uniform image.
+ Black = NewUniform(color.Black)
+ // White is an opaque white uniform image.
+ White = NewUniform(color.White)
+ // Transparent is a fully transparent uniform image.
+ Transparent = NewUniform(color.Transparent)
+ // Opaque is a fully opaque uniform image.
+ Opaque = NewUniform(color.Opaque)
)
-// A ColorImage is an infinite-sized Image of uniform Color.
-// It implements both the Color and Image interfaces.
-type ColorImage struct {
- C Color
+// Uniform is an infinite-sized Image of uniform color.
+// It implements both the color.Color and Image interfaces.
+type Uniform struct {
+ C color.Color
}
-func (c *ColorImage) RGBA() (r, g, b, a uint32) {
+func (c *Uniform) RGBA() (r, g, b, a uint32) {
return c.C.RGBA()
}
-func (c *ColorImage) ColorModel() ColorModel {
- return ColorModelFunc(func(Color) Color { return c.C })
+func (c *Uniform) ColorModel() color.Model {
+ return color.ModelFunc(func(color.Color) color.Color { return c.C })
}
-func (c *ColorImage) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
+func (c *Uniform) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
-func (c *ColorImage) At(x, y int) Color { return c.C }
+func (c *Uniform) At(x, y int) color.Color { return c.C }
// Opaque scans the entire image and returns whether or not it is fully opaque.
-func (c *ColorImage) Opaque() bool {
+func (c *Uniform) Opaque() bool {
_, _, _, a := c.C.RGBA()
return a == 0xffff
}
-func NewColorImage(c Color) *ColorImage {
- return &ColorImage{c}
+func NewUniform(c color.Color) *Uniform {
+ return &Uniform{c}
}
// A Tiled is an infinite-sized Image that repeats another Image in both
@@ -51,13 +55,13 @@ type Tiled struct {
Offset Point
}
-func (t *Tiled) ColorModel() ColorModel {
+func (t *Tiled) ColorModel() color.Model {
return t.I.ColorModel()
}
func (t *Tiled) Bounds() Rectangle { return Rectangle{Point{-1e9, -1e9}, Point{1e9, 1e9}} }
-func (t *Tiled) At(x, y int) Color {
+func (t *Tiled) At(x, y int) color.Color {
p := Point{x, y}.Add(t.Offset).Mod(t.I.Bounds())
return t.I.At(p.X, p.Y)
}
diff --git a/libgo/go/image/png/reader.go b/libgo/go/image/png/reader.go
index 8c76afa72c6..66f1916a6f3 100644
--- a/libgo/go/image/png/reader.go
+++ b/libgo/go/image/png/reader.go
@@ -4,15 +4,17 @@
// Package png implements a PNG image decoder and encoder.
//
-// The PNG specification is at http://www.libpng.org/pub/png/spec/1.2/PNG-Contents.html
+// The PNG specification is at http://www.w3.org/TR/PNG/.
package png
import (
"compress/zlib"
+ "encoding/binary"
"fmt"
"hash"
"hash/crc32"
"image"
+ "image/color"
"io"
"os"
)
@@ -61,6 +63,7 @@ const (
// chunks must appear in that order. There may be multiple IDAT chunks, and
// IDAT chunks must be sequential (i.e. they may not have any other chunks
// between them).
+// http://www.w3.org/TR/PNG/#5ChunkOrdering
const (
dsStart = iota
dsSeenIHDR
@@ -71,19 +74,16 @@ const (
const pngHeader = "\x89PNG\r\n\x1a\n"
-type imgOrErr struct {
- img image.Image
- err os.Error
-}
-
type decoder struct {
+ r io.Reader
+ img image.Image
+ crc hash.Hash32
width, height int
depth int
- palette image.PalettedColorModel
+ palette color.Palette
cb int
stage int
- idatWriter io.WriteCloser
- idatDone chan imgOrErr
+ idatLength uint32
tmp [3 * 256]byte
}
@@ -94,23 +94,11 @@ func (e FormatError) String() string { return "png: invalid format: " + string(e
var chunkOrderError = FormatError("chunk out of order")
-// An IDATDecodingError wraps an inner error (such as a ZLIB decoding error) encountered while processing an IDAT chunk.
-type IDATDecodingError struct {
- Err os.Error
-}
-
-func (e IDATDecodingError) String() string { return "png: IDAT decoding error: " + e.Err.String() }
-
// An UnsupportedError reports that the input uses a valid but unimplemented PNG feature.
type UnsupportedError string
func (e UnsupportedError) String() string { return "png: unsupported feature: " + string(e) }
-// Big-endian.
-func parseUint32(b []uint8) uint32 {
- return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3])
-}
-
func abs(x int) int {
if x < 0 {
return -x
@@ -125,20 +113,19 @@ func min(a, b int) int {
return b
}
-func (d *decoder) parseIHDR(r io.Reader, crc hash.Hash32, length uint32) os.Error {
+func (d *decoder) parseIHDR(length uint32) os.Error {
if length != 13 {
return FormatError("bad IHDR length")
}
- _, err := io.ReadFull(r, d.tmp[0:13])
- if err != nil {
+ if _, err := io.ReadFull(d.r, d.tmp[:13]); err != nil {
return err
}
- crc.Write(d.tmp[0:13])
+ d.crc.Write(d.tmp[:13])
if d.tmp[10] != 0 || d.tmp[11] != 0 || d.tmp[12] != 0 {
return UnsupportedError("compression, filter or interlace method")
}
- w := int32(parseUint32(d.tmp[0:4]))
- h := int32(parseUint32(d.tmp[4:8]))
+ w := int32(binary.BigEndian.Uint32(d.tmp[0:4]))
+ h := int32(binary.BigEndian.Uint32(d.tmp[4:8]))
if w < 0 || h < 0 {
return FormatError("negative dimension")
}
@@ -199,24 +186,24 @@ func (d *decoder) parseIHDR(r io.Reader, crc hash.Hash32, length uint32) os.Erro
return UnsupportedError(fmt.Sprintf("bit depth %d, color type %d", d.tmp[8], d.tmp[9]))
}
d.width, d.height = int(w), int(h)
- return nil
+ return d.verifyChecksum()
}
-func (d *decoder) parsePLTE(r io.Reader, crc hash.Hash32, length uint32) os.Error {
+func (d *decoder) parsePLTE(length uint32) os.Error {
np := int(length / 3) // The number of palette entries.
if length%3 != 0 || np <= 0 || np > 256 || np > 1<<uint(d.depth) {
return FormatError("bad PLTE length")
}
- n, err := io.ReadFull(r, d.tmp[0:3*np])
+ n, err := io.ReadFull(d.r, d.tmp[:3*np])
if err != nil {
return err
}
- crc.Write(d.tmp[0:n])
+ d.crc.Write(d.tmp[:n])
switch d.cb {
case cbP1, cbP2, cbP4, cbP8:
- d.palette = image.PalettedColorModel(make([]image.Color, np))
+ d.palette = color.Palette(make([]color.Color, np))
for i := 0; i < np; i++ {
- d.palette[i] = image.RGBAColor{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
+ d.palette[i] = color.RGBA{d.tmp[3*i+0], d.tmp[3*i+1], d.tmp[3*i+2], 0xff}
}
case cbTC8, cbTCA8, cbTC16, cbTCA16:
// As per the PNG spec, a PLTE chunk is optional (and for practical purposes,
@@ -224,18 +211,18 @@ func (d *decoder) parsePLTE(r io.Reader, crc hash.Hash32, length uint32) os.Erro
default:
return FormatError("PLTE, color type mismatch")
}
- return nil
+ return d.verifyChecksum()
}
-func (d *decoder) parsetRNS(r io.Reader, crc hash.Hash32, length uint32) os.Error {
+func (d *decoder) parsetRNS(length uint32) os.Error {
if length > 256 {
return FormatError("bad tRNS length")
}
- n, err := io.ReadFull(r, d.tmp[0:length])
+ n, err := io.ReadFull(d.r, d.tmp[:length])
if err != nil {
return err
}
- crc.Write(d.tmp[0:n])
+ d.crc.Write(d.tmp[:n])
switch d.cb {
case cbG8, cbG16:
return UnsupportedError("grayscale transparency")
@@ -246,13 +233,13 @@ func (d *decoder) parsetRNS(r io.Reader, crc hash.Hash32, length uint32) os.Erro
return FormatError("bad tRNS length")
}
for i := 0; i < n; i++ {
- rgba := d.palette[i].(image.RGBAColor)
- d.palette[i] = image.RGBAColor{rgba.R, rgba.G, rgba.B, d.tmp[i]}
+ rgba := d.palette[i].(color.RGBA)
+ d.palette[i] = color.RGBA{rgba.R, rgba.G, rgba.B, d.tmp[i]}
}
case cbGA8, cbGA16, cbTCA8, cbTCA16:
return FormatError("tRNS, color type mismatch")
}
- return nil
+ return d.verifyChecksum()
}
// The Paeth filter function, as per the PNG specification.
@@ -269,8 +256,46 @@ func paeth(a, b, c uint8) uint8 {
return c
}
-func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
- r, err := zlib.NewReader(idat)
+// Read presents one or more IDAT chunks as one continuous stream (minus the
+// intermediate chunk headers and footers). If the PNG data looked like:
+// ... len0 IDAT xxx crc0 len1 IDAT yy crc1 len2 IEND crc2
+// then this reader presents xxxyy. For well-formed PNG data, the decoder state
+// immediately before the first Read call is that d.r is positioned between the
+// first IDAT and xxx, and the decoder state immediately after the last Read
+// call is that d.r is positioned between yy and crc1.
+func (d *decoder) Read(p []byte) (int, os.Error) {
+ if len(p) == 0 {
+ return 0, nil
+ }
+ for d.idatLength == 0 {
+ // We have exhausted an IDAT chunk. Verify the checksum of that chunk.
+ if err := d.verifyChecksum(); err != nil {
+ return 0, err
+ }
+ // Read the length and chunk type of the next chunk, and check that
+ // it is an IDAT chunk.
+ if _, err := io.ReadFull(d.r, d.tmp[:8]); err != nil {
+ return 0, err
+ }
+ d.idatLength = binary.BigEndian.Uint32(d.tmp[:4])
+ if string(d.tmp[4:8]) != "IDAT" {
+ return 0, FormatError("not enough pixel data")
+ }
+ d.crc.Reset()
+ d.crc.Write(d.tmp[4:8])
+ }
+ if int(d.idatLength) < 0 {
+ return 0, UnsupportedError("IDAT chunk length overflow")
+ }
+ n, err := d.r.Read(p[:min(len(p), int(d.idatLength))])
+ d.crc.Write(p[:n])
+ d.idatLength -= uint32(n)
+ return n, err
+}
+
+// decode decodes the IDAT data into an image.
+func (d *decoder) decode() (image.Image, os.Error) {
+ r, err := zlib.NewReader(d)
if err != nil {
return nil, err
}
@@ -290,40 +315,40 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
switch d.cb {
case cbG1, cbG2, cbG4, cbG8:
bitsPerPixel = d.depth
- gray = image.NewGray(d.width, d.height)
+ gray = image.NewGray(image.Rect(0, 0, d.width, d.height))
img = gray
case cbGA8:
bitsPerPixel = 16
- nrgba = image.NewNRGBA(d.width, d.height)
+ nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
img = nrgba
case cbTC8:
bitsPerPixel = 24
- rgba = image.NewRGBA(d.width, d.height)
+ rgba = image.NewRGBA(image.Rect(0, 0, d.width, d.height))
img = rgba
case cbP1, cbP2, cbP4, cbP8:
bitsPerPixel = d.depth
- paletted = image.NewPaletted(d.width, d.height, d.palette)
+ paletted = image.NewPaletted(image.Rect(0, 0, d.width, d.height), d.palette)
img = paletted
maxPalette = uint8(len(d.palette) - 1)
case cbTCA8:
bitsPerPixel = 32
- nrgba = image.NewNRGBA(d.width, d.height)
+ nrgba = image.NewNRGBA(image.Rect(0, 0, d.width, d.height))
img = nrgba
case cbG16:
bitsPerPixel = 16
- gray16 = image.NewGray16(d.width, d.height)
+ gray16 = image.NewGray16(image.Rect(0, 0, d.width, d.height))
img = gray16
case cbGA16:
bitsPerPixel = 32
- nrgba64 = image.NewNRGBA64(d.width, d.height)
+ nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
img = nrgba64
case cbTC16:
bitsPerPixel = 48
- rgba64 = image.NewRGBA64(d.width, d.height)
+ rgba64 = image.NewRGBA64(image.Rect(0, 0, d.width, d.height))
img = rgba64
case cbTCA16:
bitsPerPixel = 64
- nrgba64 = image.NewNRGBA64(d.width, d.height)
+ nrgba64 = image.NewNRGBA64(image.Rect(0, 0, d.width, d.height))
img = nrgba64
}
bytesPerPixel := (bitsPerPixel + 7) / 8
@@ -378,7 +403,7 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
for x := 0; x < d.width; x += 8 {
b := cdat[x/8]
for x2 := 0; x2 < 8 && x+x2 < d.width; x2++ {
- gray.SetGray(x+x2, y, image.GrayColor{(b >> 7) * 0xff})
+ gray.SetGray(x+x2, y, color.Gray{(b >> 7) * 0xff})
b <<= 1
}
}
@@ -386,7 +411,7 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
for x := 0; x < d.width; x += 4 {
b := cdat[x/4]
for x2 := 0; x2 < 4 && x+x2 < d.width; x2++ {
- gray.SetGray(x+x2, y, image.GrayColor{(b >> 6) * 0x55})
+ gray.SetGray(x+x2, y, color.Gray{(b >> 6) * 0x55})
b <<= 2
}
}
@@ -394,22 +419,22 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
for x := 0; x < d.width; x += 2 {
b := cdat[x/2]
for x2 := 0; x2 < 2 && x+x2 < d.width; x2++ {
- gray.SetGray(x+x2, y, image.GrayColor{(b >> 4) * 0x11})
+ gray.SetGray(x+x2, y, color.Gray{(b >> 4) * 0x11})
b <<= 4
}
}
case cbG8:
for x := 0; x < d.width; x++ {
- gray.SetGray(x, y, image.GrayColor{cdat[x]})
+ gray.SetGray(x, y, color.Gray{cdat[x]})
}
case cbGA8:
for x := 0; x < d.width; x++ {
ycol := cdat[2*x+0]
- nrgba.SetNRGBA(x, y, image.NRGBAColor{ycol, ycol, ycol, cdat[2*x+1]})
+ nrgba.SetNRGBA(x, y, color.NRGBA{ycol, ycol, ycol, cdat[2*x+1]})
}
case cbTC8:
for x := 0; x < d.width; x++ {
- rgba.SetRGBA(x, y, image.RGBAColor{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
+ rgba.SetRGBA(x, y, color.RGBA{cdat[3*x+0], cdat[3*x+1], cdat[3*x+2], 0xff})
}
case cbP1:
for x := 0; x < d.width; x += 8 {
@@ -456,25 +481,25 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
}
case cbTCA8:
for x := 0; x < d.width; x++ {
- nrgba.SetNRGBA(x, y, image.NRGBAColor{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
+ nrgba.SetNRGBA(x, y, color.NRGBA{cdat[4*x+0], cdat[4*x+1], cdat[4*x+2], cdat[4*x+3]})
}
case cbG16:
for x := 0; x < d.width; x++ {
ycol := uint16(cdat[2*x+0])<<8 | uint16(cdat[2*x+1])
- gray16.SetGray16(x, y, image.Gray16Color{ycol})
+ gray16.SetGray16(x, y, color.Gray16{ycol})
}
case cbGA16:
for x := 0; x < d.width; x++ {
ycol := uint16(cdat[4*x+0])<<8 | uint16(cdat[4*x+1])
acol := uint16(cdat[4*x+2])<<8 | uint16(cdat[4*x+3])
- nrgba64.SetNRGBA64(x, y, image.NRGBA64Color{ycol, ycol, ycol, acol})
+ nrgba64.SetNRGBA64(x, y, color.NRGBA64{ycol, ycol, ycol, acol})
}
case cbTC16:
for x := 0; x < d.width; x++ {
rcol := uint16(cdat[6*x+0])<<8 | uint16(cdat[6*x+1])
gcol := uint16(cdat[6*x+2])<<8 | uint16(cdat[6*x+3])
bcol := uint16(cdat[6*x+4])<<8 | uint16(cdat[6*x+5])
- rgba64.SetRGBA64(x, y, image.RGBA64Color{rcol, gcol, bcol, 0xffff})
+ rgba64.SetRGBA64(x, y, color.RGBA64{rcol, gcol, bcol, 0xffff})
}
case cbTCA16:
for x := 0; x < d.width; x++ {
@@ -482,150 +507,113 @@ func (d *decoder) idatReader(idat io.Reader) (image.Image, os.Error) {
gcol := uint16(cdat[8*x+2])<<8 | uint16(cdat[8*x+3])
bcol := uint16(cdat[8*x+4])<<8 | uint16(cdat[8*x+5])
acol := uint16(cdat[8*x+6])<<8 | uint16(cdat[8*x+7])
- nrgba64.SetNRGBA64(x, y, image.NRGBA64Color{rcol, gcol, bcol, acol})
+ nrgba64.SetNRGBA64(x, y, color.NRGBA64{rcol, gcol, bcol, acol})
}
}
// The current row for y is the previous row for y+1.
pr, cr = cr, pr
}
- return img, nil
-}
-func (d *decoder) parseIDAT(r io.Reader, crc hash.Hash32, length uint32) os.Error {
- // There may be more than one IDAT chunk, but their contents must be
- // treated as if it was one continuous stream (to the zlib decoder).
- // We bring up an io.Pipe and write the IDAT chunks into the pipe as
- // we see them, and decode the stream in a separate go-routine, which
- // signals its completion (successful or not) via a channel.
- if d.idatWriter == nil {
- pr, pw := io.Pipe()
- d.idatWriter = pw
- d.idatDone = make(chan imgOrErr)
- go func() {
- img, err := d.idatReader(pr)
- if err == os.EOF {
- err = FormatError("too little IDAT")
- }
- pr.CloseWithError(FormatError("too much IDAT"))
- d.idatDone <- imgOrErr{img, err}
- }()
+ // Check for EOF, to verify the zlib checksum.
+ n, err := r.Read(pr[:1])
+ if err != os.EOF {
+ return nil, FormatError(err.String())
}
- var buf [4096]byte
- for length > 0 {
- n, err1 := r.Read(buf[0:min(len(buf), int(length))])
- // We delay checking err1. It is possible to get n bytes and an error,
- // but if the n bytes themselves contain a FormatError, for example, we
- // want to report that error, and not the one that made the Read stop.
- n, err2 := d.idatWriter.Write(buf[0:n])
- if err2 != nil {
- return err2
- }
- if err1 != nil {
- return err1
- }
- crc.Write(buf[0:n])
- length -= uint32(n)
+ if n != 0 || d.idatLength != 0 {
+ return nil, FormatError("too much pixel data")
}
- return nil
-}
-func (d *decoder) parseIEND(r io.Reader, crc hash.Hash32, length uint32) os.Error {
- if length != 0 {
- return FormatError("bad IEND length")
- }
- return nil
+ return img, nil
}
-func (d *decoder) parseChunk(r io.Reader) os.Error {
- // Read the length.
- n, err := io.ReadFull(r, d.tmp[0:4])
- if err == os.EOF {
- return io.ErrUnexpectedEOF
- }
+func (d *decoder) parseIDAT(length uint32) (err os.Error) {
+ d.idatLength = length
+ d.img, err = d.decode()
if err != nil {
return err
}
- length := parseUint32(d.tmp[0:4])
+ return d.verifyChecksum()
+}
- // Read the chunk type.
- n, err = io.ReadFull(r, d.tmp[0:4])
- if err == os.EOF {
- return io.ErrUnexpectedEOF
+func (d *decoder) parseIEND(length uint32) os.Error {
+ if length != 0 {
+ return FormatError("bad IEND length")
}
+ return d.verifyChecksum()
+}
+
+func (d *decoder) parseChunk() os.Error {
+ // Read the length and chunk type.
+ n, err := io.ReadFull(d.r, d.tmp[:8])
if err != nil {
return err
}
- crc := crc32.NewIEEE()
- crc.Write(d.tmp[0:4])
+ length := binary.BigEndian.Uint32(d.tmp[:4])
+ d.crc.Reset()
+ d.crc.Write(d.tmp[4:8])
// Read the chunk data.
- switch string(d.tmp[0:4]) {
+ switch string(d.tmp[4:8]) {
case "IHDR":
if d.stage != dsStart {
return chunkOrderError
}
d.stage = dsSeenIHDR
- err = d.parseIHDR(r, crc, length)
+ return d.parseIHDR(length)
case "PLTE":
if d.stage != dsSeenIHDR {
return chunkOrderError
}
d.stage = dsSeenPLTE
- err = d.parsePLTE(r, crc, length)
+ return d.parsePLTE(length)
case "tRNS":
if d.stage != dsSeenPLTE {
return chunkOrderError
}
- err = d.parsetRNS(r, crc, length)
+ return d.parsetRNS(length)
case "IDAT":
if d.stage < dsSeenIHDR || d.stage > dsSeenIDAT || (d.cb == cbP8 && d.stage == dsSeenIHDR) {
return chunkOrderError
}
d.stage = dsSeenIDAT
- err = d.parseIDAT(r, crc, length)
+ return d.parseIDAT(length)
case "IEND":
if d.stage != dsSeenIDAT {
return chunkOrderError
}
d.stage = dsSeenIEND
- err = d.parseIEND(r, crc, length)
- default:
- // Ignore this chunk (of a known length).
- var ignored [4096]byte
- for length > 0 {
- n, err = io.ReadFull(r, ignored[0:min(len(ignored), int(length))])
- if err != nil {
- return err
- }
- crc.Write(ignored[0:n])
- length -= uint32(n)
- }
+ return d.parseIEND(length)
}
- if err != nil {
- return err
+ // Ignore this chunk (of a known length).
+ var ignored [4096]byte
+ for length > 0 {
+ n, err = io.ReadFull(d.r, ignored[:min(len(ignored), int(length))])
+ if err != nil {
+ return err
+ }
+ d.crc.Write(ignored[:n])
+ length -= uint32(n)
}
+ return d.verifyChecksum()
+}
- // Read the checksum.
- n, err = io.ReadFull(r, d.tmp[0:4])
- if err == os.EOF {
- return io.ErrUnexpectedEOF
- }
- if err != nil {
+func (d *decoder) verifyChecksum() os.Error {
+ if _, err := io.ReadFull(d.r, d.tmp[:4]); err != nil {
return err
}
- if parseUint32(d.tmp[0:4]) != crc.Sum32() {
+ if binary.BigEndian.Uint32(d.tmp[:4]) != d.crc.Sum32() {
return FormatError("invalid checksum")
}
return nil
}
-func (d *decoder) checkHeader(r io.Reader) os.Error {
- _, err := io.ReadFull(r, d.tmp[0:8])
+func (d *decoder) checkHeader() os.Error {
+ _, err := io.ReadFull(d.r, d.tmp[:len(pngHeader)])
if err != nil {
return err
}
- if string(d.tmp[0:8]) != pngHeader {
+ if string(d.tmp[:len(pngHeader)]) != pngHeader {
return FormatError("not a PNG file")
}
return nil
@@ -634,42 +622,45 @@ func (d *decoder) checkHeader(r io.Reader) os.Error {
// Decode reads a PNG image from r and returns it as an image.Image.
// The type of Image returned depends on the PNG contents.
func Decode(r io.Reader) (image.Image, os.Error) {
- var d decoder
- err := d.checkHeader(r)
- if err != nil {
- return nil, err
+ d := &decoder{
+ r: r,
+ crc: crc32.NewIEEE(),
}
- for d.stage != dsSeenIEND {
- err = d.parseChunk(r)
- if err != nil {
- break
+ if err := d.checkHeader(); err != nil {
+ if err == os.EOF {
+ err = io.ErrUnexpectedEOF
}
+ return nil, err
}
- var img image.Image
- if d.idatWriter != nil {
- d.idatWriter.Close()
- ie := <-d.idatDone
- if err == nil {
- img, err = ie.img, ie.err
+ for d.stage != dsSeenIEND {
+ if err := d.parseChunk(); err != nil {
+ if err == os.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return nil, err
}
}
- if err != nil {
- return nil, err
- }
- return img, nil
+ return d.img, nil
}
// DecodeConfig returns the color model and dimensions of a PNG image without
// decoding the entire image.
func DecodeConfig(r io.Reader) (image.Config, os.Error) {
- var d decoder
- err := d.checkHeader(r)
- if err != nil {
+ d := &decoder{
+ r: r,
+ crc: crc32.NewIEEE(),
+ }
+ if err := d.checkHeader(); err != nil {
+ if err == os.EOF {
+ err = io.ErrUnexpectedEOF
+ }
return image.Config{}, err
}
for {
- err = d.parseChunk(r)
- if err != nil {
+ if err := d.parseChunk(); err != nil {
+ if err == os.EOF {
+ err = io.ErrUnexpectedEOF
+ }
return image.Config{}, err
}
if d.stage == dsSeenIHDR && d.cb != cbP8 {
@@ -679,26 +670,26 @@ func DecodeConfig(r io.Reader) (image.Config, os.Error) {
break
}
}
- var cm image.ColorModel
+ var cm color.Model
switch d.cb {
case cbG1, cbG2, cbG4, cbG8:
- cm = image.GrayColorModel
+ cm = color.GrayModel
case cbGA8:
- cm = image.NRGBAColorModel
+ cm = color.NRGBAModel
case cbTC8:
- cm = image.RGBAColorModel
+ cm = color.RGBAModel
case cbP1, cbP2, cbP4, cbP8:
cm = d.palette
case cbTCA8:
- cm = image.NRGBAColorModel
+ cm = color.NRGBAModel
case cbG16:
- cm = image.Gray16ColorModel
+ cm = color.Gray16Model
case cbGA16:
- cm = image.NRGBA64ColorModel
+ cm = color.NRGBA64Model
case cbTC16:
- cm = image.RGBA64ColorModel
+ cm = color.RGBA64Model
case cbTCA16:
- cm = image.NRGBA64ColorModel
+ cm = color.NRGBA64Model
}
return image.Config{cm, d.width, d.height}, nil
}
diff --git a/libgo/go/image/png/reader_test.go b/libgo/go/image/png/reader_test.go
index bcc1a3db475..48d06130e37 100644
--- a/libgo/go/image/png/reader_test.go
+++ b/libgo/go/image/png/reader_test.go
@@ -8,8 +8,10 @@ import (
"bufio"
"fmt"
"image"
+ "image/color"
"io"
"os"
+ "strings"
"testing"
)
@@ -41,7 +43,7 @@ var filenamesShort = []string{
"basn6a16",
}
-func readPng(filename string) (image.Image, os.Error) {
+func readPNG(filename string) (image.Image, os.Error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
@@ -57,12 +59,12 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
cm := png.ColorModel()
var bitdepth int
switch cm {
- case image.RGBAColorModel, image.NRGBAColorModel, image.AlphaColorModel, image.GrayColorModel:
+ case color.RGBAModel, color.NRGBAModel, color.AlphaModel, color.GrayModel:
bitdepth = 8
default:
bitdepth = 16
}
- cpm, _ := cm.(image.PalettedColorModel)
+ cpm, _ := cm.(color.Palette)
var paletted *image.Paletted
if cpm != nil {
switch {
@@ -82,11 +84,11 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
io.WriteString(w, "#SNG: from "+filename+".png\nIHDR {\n")
fmt.Fprintf(w, " width: %d; height: %d; bitdepth: %d;\n", bounds.Dx(), bounds.Dy(), bitdepth)
switch {
- case cm == image.RGBAColorModel, cm == image.RGBA64ColorModel:
+ case cm == color.RGBAModel, cm == color.RGBA64Model:
io.WriteString(w, " using color;\n")
- case cm == image.NRGBAColorModel, cm == image.NRGBA64ColorModel:
+ case cm == color.NRGBAModel, cm == color.NRGBA64Model:
io.WriteString(w, " using color alpha;\n")
- case cm == image.GrayColorModel, cm == image.Gray16ColorModel:
+ case cm == color.GrayModel, cm == color.Gray16Model:
io.WriteString(w, " using grayscale;\n")
case cpm != nil:
io.WriteString(w, " using color palette;\n")
@@ -129,34 +131,34 @@ func sng(w io.WriteCloser, filename string, png image.Image) {
io.WriteString(w, "IMAGE {\n pixels hex\n")
for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
switch {
- case cm == image.GrayColorModel:
+ case cm == color.GrayModel:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
- gray := png.At(x, y).(image.GrayColor)
+ gray := png.At(x, y).(color.Gray)
fmt.Fprintf(w, "%02x", gray.Y)
}
- case cm == image.Gray16ColorModel:
+ case cm == color.Gray16Model:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
- gray16 := png.At(x, y).(image.Gray16Color)
+ gray16 := png.At(x, y).(color.Gray16)
fmt.Fprintf(w, "%04x ", gray16.Y)
}
- case cm == image.RGBAColorModel:
+ case cm == color.RGBAModel:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
- rgba := png.At(x, y).(image.RGBAColor)
+ rgba := png.At(x, y).(color.RGBA)
fmt.Fprintf(w, "%02x%02x%02x ", rgba.R, rgba.G, rgba.B)
}
- case cm == image.RGBA64ColorModel:
+ case cm == color.RGBA64Model:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
- rgba64 := png.At(x, y).(image.RGBA64Color)
+ rgba64 := png.At(x, y).(color.RGBA64)
fmt.Fprintf(w, "%04x%04x%04x ", rgba64.R, rgba64.G, rgba64.B)
}
- case cm == image.NRGBAColorModel:
+ case cm == color.NRGBAModel:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
- nrgba := png.At(x, y).(image.NRGBAColor)
+ nrgba := png.At(x, y).(color.NRGBA)
fmt.Fprintf(w, "%02x%02x%02x%02x ", nrgba.R, nrgba.G, nrgba.B, nrgba.A)
}
- case cm == image.NRGBA64ColorModel:
+ case cm == color.NRGBA64Model:
for x := bounds.Min.X; x < bounds.Max.X; x++ {
- nrgba64 := png.At(x, y).(image.NRGBA64Color)
+ nrgba64 := png.At(x, y).(color.NRGBA64)
fmt.Fprintf(w, "%04x%04x%04x%04x ", nrgba64.R, nrgba64.G, nrgba64.B, nrgba64.A)
}
case cpm != nil:
@@ -183,7 +185,7 @@ func TestReader(t *testing.T) {
}
for _, fn := range names {
// Read the .png file.
- img, err := readPng("testdata/pngsuite/" + fn + ".png")
+ img, err := readPNG("testdata/pngsuite/" + fn + ".png")
if err != nil {
t.Error(fn, err)
continue
@@ -192,7 +194,7 @@ func TestReader(t *testing.T) {
if fn == "basn4a16" {
// basn4a16.sng is gray + alpha but sng() will produce true color + alpha
// so we just check a single random pixel.
- c := img.At(2, 1).(image.NRGBA64Color)
+ c := img.At(2, 1).(color.NRGBA64)
if c.R != 0x11a7 || c.G != 0x11a7 || c.B != 0x11a7 || c.A != 0x1085 {
t.Error(fn, fmt.Errorf("wrong pixel value at (2, 1): %x", c))
}
@@ -239,3 +241,29 @@ func TestReader(t *testing.T) {
}
}
}
+
+var readerErrors = []struct {
+ file string
+ err string
+}{
+ {"invalid-zlib.png", "zlib checksum error"},
+ {"invalid-crc32.png", "invalid checksum"},
+ {"invalid-noend.png", "unexpected EOF"},
+ {"invalid-trunc.png", "unexpected EOF"},
+}
+
+func TestReaderError(t *testing.T) {
+ for _, tt := range readerErrors {
+ img, err := readPNG("testdata/" + tt.file)
+ if err == nil {
+ t.Errorf("decoding %s: missing error", tt.file)
+ continue
+ }
+ if !strings.Contains(err.String(), tt.err) {
+ t.Errorf("decoding %s: %s, want %s", tt.file, err, tt.err)
+ }
+ if img != nil {
+ t.Errorf("decoding %s: have image + error", tt.file)
+ }
+ }
+}
diff --git a/libgo/go/image/png/testdata/invalid-crc32.png b/libgo/go/image/png/testdata/invalid-crc32.png
new file mode 100644
index 00000000000..e5be4086cb2
--- /dev/null
+++ b/libgo/go/image/png/testdata/invalid-crc32.png
Binary files differ
diff --git a/libgo/go/image/png/testdata/invalid-noend.png b/libgo/go/image/png/testdata/invalid-noend.png
new file mode 100644
index 00000000000..9137270d9c3
--- /dev/null
+++ b/libgo/go/image/png/testdata/invalid-noend.png
Binary files differ
diff --git a/libgo/go/image/png/testdata/invalid-trunc.png b/libgo/go/image/png/testdata/invalid-trunc.png
new file mode 100644
index 00000000000..d0748cf6541
--- /dev/null
+++ b/libgo/go/image/png/testdata/invalid-trunc.png
Binary files differ
diff --git a/libgo/go/image/png/testdata/invalid-zlib.png b/libgo/go/image/png/testdata/invalid-zlib.png
new file mode 100644
index 00000000000..c6d051caee0
--- /dev/null
+++ b/libgo/go/image/png/testdata/invalid-zlib.png
Binary files differ
diff --git a/libgo/go/image/png/writer.go b/libgo/go/image/png/writer.go
index 55ca97e0628..b6103c6d0e5 100644
--- a/libgo/go/image/png/writer.go
+++ b/libgo/go/image/png/writer.go
@@ -9,6 +9,7 @@ import (
"compress/zlib"
"hash/crc32"
"image"
+ "image/color"
"io"
"os"
"strconv"
@@ -125,7 +126,7 @@ func (e *encoder) writeIHDR() {
e.writeChunk(e.tmp[0:13], "IHDR")
}
-func (e *encoder) writePLTE(p image.PalettedColorModel) {
+func (e *encoder) writePLTE(p color.Palette) {
if len(p) < 1 || len(p) > 256 {
e.err = FormatError("bad palette length: " + strconv.Itoa(len(p)))
return
@@ -139,7 +140,7 @@ func (e *encoder) writePLTE(p image.PalettedColorModel) {
e.writeChunk(e.tmp[0:3*len(p)], "PLTE")
}
-func (e *encoder) maybeWritetRNS(p image.PalettedColorModel) {
+func (e *encoder) maybeWritetRNS(p color.Palette) {
last := -1
for i, c := range p {
_, _, _, a := c.RGBA()
@@ -160,10 +161,6 @@ func (e *encoder) maybeWritetRNS(p image.PalettedColorModel) {
//
// This method should only be called from writeIDATs (via writeImage).
// No other code should treat an encoder as an io.Writer.
-//
-// Note that, because the zlib Reader may involve an io.Pipe, e.Write calls may
-// occur on a separate go-routine than the e.writeIDATs call, and care should be
-// taken that e's state (such as its tmp buffer) is not modified concurrently.
func (e *encoder) Write(b []byte) (int, os.Error) {
e.writeChunk(b, "IDAT")
if e.err != nil {
@@ -310,7 +307,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
switch cb {
case cbG8:
for x := b.Min.X; x < b.Max.X; x++ {
- c := image.GrayColorModel.Convert(m.At(x, y)).(image.GrayColor)
+ c := color.GrayModel.Convert(m.At(x, y)).(color.Gray)
cr[0][i] = c.Y
i++
}
@@ -336,13 +333,20 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
}
}
case cbP8:
- paletted := m.(*image.Paletted)
- offset := (y - b.Min.Y) * paletted.Stride
- copy(cr[0][1:], paletted.Pix[offset:offset+b.Dx()])
+ if p, _ := m.(*image.Paletted); p != nil {
+ offset := (y - b.Min.Y) * p.Stride
+ copy(cr[0][1:], p.Pix[offset:offset+b.Dx()])
+ } else {
+ pi := m.(image.PalettedImage)
+ for x := b.Min.X; x < b.Max.X; x++ {
+ cr[0][i] = pi.ColorIndexAt(x, y)
+ i += 1
+ }
+ }
case cbTCA8:
// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
for x := b.Min.X; x < b.Max.X; x++ {
- c := image.NRGBAColorModel.Convert(m.At(x, y)).(image.NRGBAColor)
+ c := color.NRGBAModel.Convert(m.At(x, y)).(color.NRGBA)
cr[0][i+0] = c.R
cr[0][i+1] = c.G
cr[0][i+2] = c.B
@@ -351,7 +355,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
}
case cbG16:
for x := b.Min.X; x < b.Max.X; x++ {
- c := image.Gray16ColorModel.Convert(m.At(x, y)).(image.Gray16Color)
+ c := color.Gray16Model.Convert(m.At(x, y)).(color.Gray16)
cr[0][i+0] = uint8(c.Y >> 8)
cr[0][i+1] = uint8(c.Y)
i += 2
@@ -371,7 +375,7 @@ func writeImage(w io.Writer, m image.Image, cb int) os.Error {
case cbTCA16:
// Convert from image.Image (which is alpha-premultiplied) to PNG's non-alpha-premultiplied.
for x := b.Min.X; x < b.Max.X; x++ {
- c := image.NRGBA64ColorModel.Convert(m.At(x, y)).(image.NRGBA64Color)
+ c := color.NRGBA64Model.Convert(m.At(x, y)).(color.NRGBA64)
cr[0][i+0] = uint8(c.R >> 8)
cr[0][i+1] = uint8(c.R)
cr[0][i+2] = uint8(c.G >> 8)
@@ -432,16 +436,21 @@ func Encode(w io.Writer, m image.Image) os.Error {
var e encoder
e.w = w
e.m = m
- pal, _ := m.(*image.Paletted)
+
+ var pal color.Palette
+ // cbP8 encoding needs PalettedImage's ColorIndexAt method.
+ if _, ok := m.(image.PalettedImage); ok {
+ pal, _ = m.ColorModel().(color.Palette)
+ }
if pal != nil {
e.cb = cbP8
} else {
switch m.ColorModel() {
- case image.GrayColorModel:
+ case color.GrayModel:
e.cb = cbG8
- case image.Gray16ColorModel:
+ case color.Gray16Model:
e.cb = cbG16
- case image.RGBAColorModel, image.NRGBAColorModel, image.AlphaColorModel:
+ case color.RGBAModel, color.NRGBAModel, color.AlphaModel:
if opaque(m) {
e.cb = cbTC8
} else {
@@ -459,8 +468,8 @@ func Encode(w io.Writer, m image.Image) os.Error {
_, e.err = io.WriteString(w, pngHeader)
e.writeIHDR()
if pal != nil {
- e.writePLTE(pal.Palette)
- e.maybeWritetRNS(pal.Palette)
+ e.writePLTE(pal)
+ e.maybeWritetRNS(pal)
}
e.writeIDATs()
e.writeIEND()
diff --git a/libgo/go/image/png/writer_test.go b/libgo/go/image/png/writer_test.go
index 1599791b3a3..e517173c3e1 100644
--- a/libgo/go/image/png/writer_test.go
+++ b/libgo/go/image/png/writer_test.go
@@ -8,6 +8,7 @@ import (
"bytes"
"fmt"
"image"
+ "image/color"
"io/ioutil"
"os"
"testing"
@@ -56,13 +57,13 @@ func TestWriter(t *testing.T) {
for _, fn := range names {
qfn := "testdata/pngsuite/" + fn + ".png"
// Read the image.
- m0, err := readPng(qfn)
+ m0, err := readPNG(qfn)
if err != nil {
t.Error(fn, err)
continue
}
// Read the image again, encode it, and decode it.
- m1, err := readPng(qfn)
+ m1, err := readPNG(qfn)
if err != nil {
t.Error(fn, err)
return
@@ -82,10 +83,10 @@ func TestWriter(t *testing.T) {
}
func TestSubImage(t *testing.T) {
- m0 := image.NewRGBA(256, 256)
+ m0 := image.NewRGBA(image.Rect(0, 0, 256, 256))
for y := 0; y < 256; y++ {
for x := 0; x < 256; x++ {
- m0.Set(x, y, image.RGBAColor{uint8(x), uint8(y), 0, 255})
+ m0.Set(x, y, color.RGBA{uint8(x), uint8(y), 0, 255})
}
}
m0 = m0.SubImage(image.Rect(50, 30, 250, 130)).(*image.RGBA)
@@ -103,11 +104,10 @@ func TestSubImage(t *testing.T) {
func BenchmarkEncodePaletted(b *testing.B) {
b.StopTimer()
- img := image.NewPaletted(640, 480,
- []image.Color{
- image.RGBAColor{0, 0, 0, 255},
- image.RGBAColor{255, 255, 255, 255},
- })
+ img := image.NewPaletted(image.Rect(0, 0, 640, 480), color.Palette{
+ color.RGBA{0, 0, 0, 255},
+ color.RGBA{255, 255, 255, 255},
+ })
b.SetBytes(640 * 480 * 1)
b.StartTimer()
for i := 0; i < b.N; i++ {
@@ -117,12 +117,12 @@ func BenchmarkEncodePaletted(b *testing.B) {
func BenchmarkEncodeRGBOpaque(b *testing.B) {
b.StopTimer()
- img := image.NewRGBA(640, 480)
+ img := image.NewRGBA(image.Rect(0, 0, 640, 480))
// Set all pixels to 0xFF alpha to force opaque mode.
bo := img.Bounds()
for y := bo.Min.Y; y < bo.Max.Y; y++ {
for x := bo.Min.X; x < bo.Max.X; x++ {
- img.Set(x, y, image.RGBAColor{0, 0, 0, 255})
+ img.Set(x, y, color.RGBA{0, 0, 0, 255})
}
}
if !img.Opaque() {
@@ -137,7 +137,7 @@ func BenchmarkEncodeRGBOpaque(b *testing.B) {
func BenchmarkEncodeRGBA(b *testing.B) {
b.StopTimer()
- img := image.NewRGBA(640, 480)
+ img := image.NewRGBA(image.Rect(0, 0, 640, 480))
if img.Opaque() {
panic("expected image to not be opaque")
}
diff --git a/libgo/go/image/tiff/compress.go b/libgo/go/image/tiff/compress.go
new file mode 100644
index 00000000000..e89aa6d7ac3
--- /dev/null
+++ b/libgo/go/image/tiff/compress.go
@@ -0,0 +1,60 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package tiff
+
+import (
+ "bufio"
+ "io"
+ "os"
+)
+
+type byteReader interface {
+ io.Reader
+ io.ByteReader
+}
+
+// unpackBits decodes the PackBits-compressed data in src and returns the
+// uncompressed data.
+//
+// The PackBits compression format is described in section 9 (p. 42)
+// of the TIFF spec.
+func unpackBits(r io.Reader) ([]byte, os.Error) {
+ buf := make([]byte, 128)
+ dst := make([]byte, 0, 1024)
+ br, ok := r.(byteReader)
+ if !ok {
+ br = bufio.NewReader(r)
+ }
+
+ for {
+ b, err := br.ReadByte()
+ if err != nil {
+ if err == os.EOF {
+ return dst, nil
+ }
+ return nil, err
+ }
+ code := int(int8(b))
+ switch {
+ case code >= 0:
+ n, err := io.ReadFull(br, buf[:code+1])
+ if err != nil {
+ return nil, err
+ }
+ dst = append(dst, buf[:n]...)
+ case code == -128:
+ // No-op.
+ default:
+ if b, err = br.ReadByte(); err != nil {
+ return nil, err
+ }
+ for j := 0; j < 1-code; j++ {
+ buf[j] = b
+ }
+ dst = append(dst, buf[:1-code]...)
+ }
+ }
+ panic("unreachable")
+}
diff --git a/libgo/go/image/tiff/reader.go b/libgo/go/image/tiff/reader.go
index f5652667aa3..c452f5d54cc 100644
--- a/libgo/go/image/tiff/reader.go
+++ b/libgo/go/image/tiff/reader.go
@@ -12,6 +12,7 @@ import (
"compress/zlib"
"encoding/binary"
"image"
+ "image/color"
"io"
"io/ioutil"
"os"
@@ -45,7 +46,7 @@ type decoder struct {
config image.Config
mode imageMode
features map[int][]uint
- palette []image.Color
+ palette []color.Color
buf []byte
off int // Current offset in buf.
@@ -129,9 +130,9 @@ func (d *decoder) parseIFD(p []byte) os.Error {
if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 {
return FormatError("bad ColorMap length")
}
- d.palette = make([]image.Color, numcolors)
+ d.palette = make([]color.Color, numcolors)
for i := 0; i < numcolors; i++ {
- d.palette[i] = image.RGBA64Color{
+ d.palette[i] = color.RGBA64{
uint16(val[i]),
uint16(val[i+numcolors]),
uint16(val[i+2*numcolors]),
@@ -180,22 +181,21 @@ func (d *decoder) flushBits() {
// decode decodes the raw data of an image.
// It reads from d.buf and writes the strip with ymin <= y < ymax into dst.
func (d *decoder) decode(dst image.Image, ymin, ymax int) os.Error {
- spp := len(d.features[tBitsPerSample]) // samples per pixel
d.off = 0
- width := dst.Bounds().Dx()
// Apply horizontal predictor if necessary.
// In this case, p contains the color difference to the preceding pixel.
// See page 64-65 of the spec.
if d.firstVal(tPredictor) == prHorizontal && d.firstVal(tBitsPerSample) == 8 {
+ var off int
+ spp := len(d.features[tBitsPerSample]) // samples per pixel
for y := ymin; y < ymax; y++ {
- d.off += spp
- for x := 0; x < (width-1)*spp; x++ {
- d.buf[d.off] += d.buf[d.off-spp]
- d.off++
+ off += spp
+ for x := 0; x < (dst.Bounds().Dx()-1)*spp; x++ {
+ d.buf[off] += d.buf[off-spp]
+ off++
}
}
- d.off = 0
}
switch d.mode {
@@ -209,7 +209,7 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) os.Error {
if d.mode == mGrayInvert {
v = 0xff - v
}
- img.SetGray(x, y, image.GrayColor{v})
+ img.SetGray(x, y, color.Gray{v})
}
d.flushBits()
}
@@ -224,28 +224,32 @@ func (d *decoder) decode(dst image.Image, ymin, ymax int) os.Error {
}
case mRGB:
img := dst.(*image.RGBA)
- for y := ymin; y < ymax; y++ {
- for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
- img.SetRGBA(x, y, image.RGBAColor{d.buf[d.off], d.buf[d.off+1], d.buf[d.off+2], 0xff})
- d.off += spp
- }
+ min := (ymin-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+ max := (ymax-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+ var off int
+ for i := min; i < max; i += 4 {
+ img.Pix[i+0] = d.buf[off+0]
+ img.Pix[i+1] = d.buf[off+1]
+ img.Pix[i+2] = d.buf[off+2]
+ img.Pix[i+3] = 0xff
+ off += 3
}
case mNRGBA:
img := dst.(*image.NRGBA)
- for y := ymin; y < ymax; y++ {
- for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
- img.SetNRGBA(x, y, image.NRGBAColor{d.buf[d.off], d.buf[d.off+1], d.buf[d.off+2], d.buf[d.off+3]})
- d.off += spp
- }
+ min := (ymin-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+ max := (ymax-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+ if len(d.buf) != max-min {
+ return FormatError("short data strip")
}
+ copy(img.Pix[min:max], d.buf)
case mRGBA:
img := dst.(*image.RGBA)
- for y := ymin; y < ymax; y++ {
- for x := img.Rect.Min.X; x < img.Rect.Max.X; x++ {
- img.SetRGBA(x, y, image.RGBAColor{d.buf[d.off], d.buf[d.off+1], d.buf[d.off+2], d.buf[d.off+3]})
- d.off += spp
- }
+ min := (ymin-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+ max := (ymax-img.Rect.Min.Y)*img.Stride - img.Rect.Min.X*4
+ if len(d.buf) != max-min {
+ return FormatError("short data strip")
}
+ copy(img.Pix[min:max], d.buf)
}
return nil
@@ -305,10 +309,13 @@ func newDecoder(r io.Reader) (*decoder, os.Error) {
return nil, UnsupportedError("non-8-bit RGB image")
}
}
- d.config.ColorModel = image.RGBAColorModel
+ d.config.ColorModel = color.RGBAModel
// RGB images normally have 3 samples per pixel.
// If there are more, ExtraSamples (p. 31-32 of the spec)
// gives their meaning (usually an alpha channel).
+ //
+ // This implementation does not support extra samples
+ // of an unspecified type.
switch len(d.features[tBitsPerSample]) {
case 3:
d.mode = mRGB
@@ -318,23 +325,22 @@ func newDecoder(r io.Reader) (*decoder, os.Error) {
d.mode = mRGBA
case 2:
d.mode = mNRGBA
- d.config.ColorModel = image.NRGBAColorModel
+ d.config.ColorModel = color.NRGBAModel
default:
- // The extra sample is discarded.
- d.mode = mRGB
+ return nil, FormatError("wrong number of samples for RGB")
}
default:
return nil, FormatError("wrong number of samples for RGB")
}
case pPaletted:
d.mode = mPaletted
- d.config.ColorModel = image.PalettedColorModel(d.palette)
+ d.config.ColorModel = color.Palette(d.palette)
case pWhiteIsZero:
d.mode = mGrayInvert
- d.config.ColorModel = image.GrayColorModel
+ d.config.ColorModel = color.GrayModel
case pBlackIsZero:
d.mode = mGray
- d.config.ColorModel = image.GrayColorModel
+ d.config.ColorModel = color.GrayModel
default:
return nil, UnsupportedError("color model")
}
@@ -373,13 +379,13 @@ func Decode(r io.Reader) (img image.Image, err os.Error) {
switch d.mode {
case mGray, mGrayInvert:
- img = image.NewGray(d.config.Width, d.config.Height)
+ img = image.NewGray(image.Rect(0, 0, d.config.Width, d.config.Height))
case mPaletted:
- img = image.NewPaletted(d.config.Width, d.config.Height, d.palette)
+ img = image.NewPaletted(image.Rect(0, 0, d.config.Width, d.config.Height), d.palette)
case mNRGBA:
- img = image.NewNRGBA(d.config.Width, d.config.Height)
+ img = image.NewNRGBA(image.Rect(0, 0, d.config.Width, d.config.Height))
case mRGB, mRGBA:
- img = image.NewRGBA(d.config.Width, d.config.Height)
+ img = image.NewRGBA(image.Rect(0, 0, d.config.Width, d.config.Height))
}
for i := 0; i < numStrips; i++ {
@@ -406,6 +412,8 @@ func Decode(r io.Reader) (img image.Image, err os.Error) {
}
d.buf, err = ioutil.ReadAll(r)
r.Close()
+ case cPackBits:
+ d.buf, err = unpackBits(io.NewSectionReader(d.r, offset, n))
default:
err = UnsupportedError("compression")
}
diff --git a/libgo/go/image/tiff/reader_test.go b/libgo/go/image/tiff/reader_test.go
index f2122c44038..86b7dc37619 100644
--- a/libgo/go/image/tiff/reader_test.go
+++ b/libgo/go/image/tiff/reader_test.go
@@ -5,10 +5,18 @@
package tiff
import (
+ "image"
+ "io/ioutil"
"os"
+ "strings"
"testing"
)
+// Read makes *buffer implements io.Reader, so that we can pass one to Decode.
+func (*buffer) Read([]byte) (int, os.Error) {
+ panic("unimplemented")
+}
+
// TestNoRPS tries to decode an image that has no RowsPerStrip tag.
// The tag is mandatory according to the spec but some software omits
// it in the case of a single strip.
@@ -23,3 +31,89 @@ func TestNoRPS(t *testing.T) {
t.Fatal(err)
}
}
+
+// TestUnpackBits tests the decoding of PackBits-encoded data.
+func TestUnpackBits(t *testing.T) {
+ var unpackBitsTests = []struct {
+ compressed string
+ uncompressed string
+ }{{
+ // Example data from Wikipedia.
+ "\xfe\xaa\x02\x80\x00\x2a\xfd\xaa\x03\x80\x00\x2a\x22\xf7\xaa",
+ "\xaa\xaa\xaa\x80\x00\x2a\xaa\xaa\xaa\xaa\x80\x00\x2a\x22\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
+ }}
+ for _, u := range unpackBitsTests {
+ buf, err := unpackBits(strings.NewReader(u.compressed))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if string(buf) != u.uncompressed {
+ t.Fatalf("unpackBits: want %x, got %x", u.uncompressed, buf)
+ }
+ }
+}
+
+// TestDecompress tests that decoding some TIFF images that use different
+// compression formats result in the same pixel data.
+func TestDecompress(t *testing.T) {
+ var decompressTests = []string{
+ "bw-uncompressed.tiff",
+ "bw-deflate.tiff",
+ "bw-packbits.tiff",
+ }
+ var img0 image.Image
+ for _, name := range decompressTests {
+ f, err := os.Open("testdata/" + name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ if img0 == nil {
+ img0, err = Decode(f)
+ if err != nil {
+ t.Fatalf("decoding %s: %v", name, err)
+ }
+ continue
+ }
+
+ img1, err := Decode(f)
+ if err != nil {
+ t.Fatalf("decoding %s: %v", name, err)
+ }
+ b := img1.Bounds()
+ // Compare images.
+ if !b.Eq(img0.Bounds()) {
+ t.Fatalf("wrong image size: want %s, got %s", img0.Bounds(), b)
+ }
+ for y := b.Min.Y; y < b.Max.Y; y++ {
+ for x := b.Min.X; x < b.Max.X; x++ {
+ c0 := img0.At(x, y)
+ c1 := img1.At(x, y)
+ r0, g0, b0, a0 := c0.RGBA()
+ r1, g1, b1, a1 := c1.RGBA()
+ if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 {
+ t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1)
+ }
+ }
+ }
+ }
+}
+
+const filename = "testdata/video-001-uncompressed.tiff"
+
+// BenchmarkDecode benchmarks the decoding of an image.
+func BenchmarkDecode(b *testing.B) {
+ b.StopTimer()
+ contents, err := ioutil.ReadFile(filename)
+ if err != nil {
+ panic(err)
+ }
+ r := &buffer{buf: contents}
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ _, err := Decode(r)
+ if err != nil {
+ panic(err)
+ }
+ }
+}
diff --git a/libgo/go/image/tiff/testdata/bw-deflate.tiff b/libgo/go/image/tiff/testdata/bw-deflate.tiff
new file mode 100644
index 00000000000..137a0c3ef1f
--- /dev/null
+++ b/libgo/go/image/tiff/testdata/bw-deflate.tiff
Binary files differ
diff --git a/libgo/go/image/tiff/testdata/bw-packbits.tiff b/libgo/go/image/tiff/testdata/bw-packbits.tiff
new file mode 100644
index 00000000000..d59fa4aeed3
--- /dev/null
+++ b/libgo/go/image/tiff/testdata/bw-packbits.tiff
Binary files differ
diff --git a/libgo/go/image/tiff/testdata/bw-uncompressed.tiff b/libgo/go/image/tiff/testdata/bw-uncompressed.tiff
new file mode 100644
index 00000000000..8390f11357f
--- /dev/null
+++ b/libgo/go/image/tiff/testdata/bw-uncompressed.tiff
Binary files differ
diff --git a/libgo/go/image/tiff/testdata/video-001-uncompressed.tiff b/libgo/go/image/tiff/testdata/video-001-uncompressed.tiff
new file mode 100644
index 00000000000..fad147107b2
--- /dev/null
+++ b/libgo/go/image/tiff/testdata/video-001-uncompressed.tiff
Binary files differ
diff --git a/libgo/go/image/ycbcr/ycbcr.go b/libgo/go/image/ycbcr/ycbcr.go
index f2de3d6fbc5..84a35a3fb5e 100644
--- a/libgo/go/image/ycbcr/ycbcr.go
+++ b/libgo/go/image/ycbcr/ycbcr.go
@@ -15,6 +15,7 @@ package ycbcr
import (
"image"
+ "image/color"
)
// RGBToYCbCr converts an RGB triple to a YCbCr triple. All components lie
@@ -92,7 +93,7 @@ func (c YCbCrColor) RGBA() (uint32, uint32, uint32, uint32) {
return uint32(r) * 0x101, uint32(g) * 0x101, uint32(b) * 0x101, 0xffff
}
-func toYCbCrColor(c image.Color) image.Color {
+func toYCbCrColor(c color.Color) color.Color {
if _, ok := c.(YCbCrColor); ok {
return c
}
@@ -102,7 +103,7 @@ func toYCbCrColor(c image.Color) image.Color {
}
// YCbCrColorModel is the color model for YCbCrColor.
-var YCbCrColorModel image.ColorModel = image.ColorModelFunc(toYCbCrColor)
+var YCbCrColorModel color.Model = color.ModelFunc(toYCbCrColor)
// SubsampleRatio is the chroma subsample ratio used in a YCbCr image.
type SubsampleRatio int
@@ -133,7 +134,7 @@ type YCbCr struct {
Rect image.Rectangle
}
-func (p *YCbCr) ColorModel() image.ColorModel {
+func (p *YCbCr) ColorModel() color.Model {
return YCbCrColorModel
}
@@ -141,7 +142,7 @@ func (p *YCbCr) Bounds() image.Rectangle {
return p.Rect
}
-func (p *YCbCr) At(x, y int) image.Color {
+func (p *YCbCr) At(x, y int) color.Color {
if !(image.Point{x, y}.In(p.Rect)) {
return YCbCrColor{}
}
diff --git a/libgo/go/index/suffixarray/qsufsort.go b/libgo/go/index/suffixarray/qsufsort.go
index 30c1104428c..c69be43c2ac 100644
--- a/libgo/go/index/suffixarray/qsufsort.go
+++ b/libgo/go/index/suffixarray/qsufsort.go
@@ -37,7 +37,7 @@ func qsufsort(data []byte) []int {
inv := initGroups(sa, data)
// the index starts 1-ordered
- sufSortable := &suffixSortable{sa, inv, 1}
+ sufSortable := &suffixSortable{sa: sa, inv: inv, h: 1}
for sa[0] > -len(sa) { // until all suffixes are one big sorted group
// The suffixes are h-ordered, make them 2*h-ordered
@@ -135,6 +135,7 @@ type suffixSortable struct {
sa []int
inv []int
h int
+ buf []int // common scratch space
}
func (x *suffixSortable) Len() int { return len(x.sa) }
@@ -142,7 +143,7 @@ func (x *suffixSortable) Less(i, j int) bool { return x.inv[x.sa[i]+x.h] < x.inv
func (x *suffixSortable) Swap(i, j int) { x.sa[i], x.sa[j] = x.sa[j], x.sa[i] }
func (x *suffixSortable) updateGroups(offset int) {
- bounds := make([]int, 0, 4)
+ bounds := x.buf[0:0]
group := x.inv[x.sa[0]+x.h]
for i := 1; i < len(x.sa); i++ {
if g := x.inv[x.sa[i]+x.h]; g > group {
@@ -151,6 +152,7 @@ func (x *suffixSortable) updateGroups(offset int) {
}
}
bounds = append(bounds, len(x.sa))
+ x.buf = bounds
// update the group numberings after all new groups are determined
prev := 0
diff --git a/libgo/go/index/suffixarray/suffixarray.go b/libgo/go/index/suffixarray/suffixarray.go
index 82e98d2ef54..174460cab86 100644
--- a/libgo/go/index/suffixarray/suffixarray.go
+++ b/libgo/go/index/suffixarray/suffixarray.go
@@ -18,6 +18,9 @@ package suffixarray
import (
"bytes"
+ "encoding/binary"
+ "io"
+ "os"
"regexp"
"sort"
)
@@ -25,7 +28,7 @@ import (
// Index implements a suffix array for fast substring search.
type Index struct {
data []byte
- sa []int // suffix array for data
+ sa []int // suffix array for data; len(sa) == len(data)
}
// New creates a new Index for data.
@@ -34,6 +37,129 @@ func New(data []byte) *Index {
return &Index{data, qsufsort(data)}
}
+// writeInt writes an int x to w using buf to buffer the write.
+func writeInt(w io.Writer, buf []byte, x int) os.Error {
+ binary.PutVarint(buf, int64(x))
+ _, err := w.Write(buf[0:binary.MaxVarintLen64])
+ return err
+}
+
+// readInt reads an int x from r using buf to buffer the read and returns x.
+func readInt(r io.Reader, buf []byte) (int, os.Error) {
+ _, err := io.ReadFull(r, buf[0:binary.MaxVarintLen64]) // ok to continue with error
+ x, _ := binary.Varint(buf)
+ return int(x), err
+}
+
+// writeSlice writes data[:n] to w and returns n.
+// It uses buf to buffer the write.
+func writeSlice(w io.Writer, buf []byte, data []int) (n int, err os.Error) {
+ // encode as many elements as fit into buf
+ p := binary.MaxVarintLen64
+ for ; n < len(data) && p+binary.MaxVarintLen64 <= len(buf); n++ {
+ p += binary.PutUvarint(buf[p:], uint64(data[n]))
+ }
+
+ // update buffer size
+ binary.PutVarint(buf, int64(p))
+
+ // write buffer
+ _, err = w.Write(buf[0:p])
+ return
+}
+
+// readSlice reads data[:n] from r and returns n.
+// It uses buf to buffer the read.
+func readSlice(r io.Reader, buf []byte, data []int) (n int, err os.Error) {
+ // read buffer size
+ var size int
+ size, err = readInt(r, buf)
+ if err != nil {
+ return
+ }
+
+ // read buffer w/o the size
+ if _, err = io.ReadFull(r, buf[binary.MaxVarintLen64:size]); err != nil {
+ return
+ }
+
+ // decode as many elements as present in buf
+ for p := binary.MaxVarintLen64; p < size; n++ {
+ x, w := binary.Uvarint(buf[p:])
+ data[n] = int(x)
+ p += w
+ }
+
+ return
+}
+
+const bufSize = 16 << 10 // reasonable for BenchmarkSaveRestore
+
+// Read reads the index from r into x; x must not be nil.
+func (x *Index) Read(r io.Reader) os.Error {
+ // buffer for all reads
+ buf := make([]byte, bufSize)
+
+ // read length
+ n, err := readInt(r, buf)
+ if err != nil {
+ return err
+ }
+
+ // allocate space
+ if 2*n < cap(x.data) || cap(x.data) < n {
+ // new data is significantly smaller or larger then
+ // existing buffers - allocate new ones
+ x.data = make([]byte, n)
+ x.sa = make([]int, n)
+ } else {
+ // re-use existing buffers
+ x.data = x.data[0:n]
+ x.sa = x.sa[0:n]
+ }
+
+ // read data
+ if _, err := io.ReadFull(r, x.data); err != nil {
+ return err
+ }
+
+ // read index
+ for sa := x.sa; len(sa) > 0; {
+ n, err := readSlice(r, buf, sa)
+ if err != nil {
+ return err
+ }
+ sa = sa[n:]
+ }
+ return nil
+}
+
+// Write writes the index x to w.
+func (x *Index) Write(w io.Writer) os.Error {
+ // buffer for all writes
+ buf := make([]byte, bufSize)
+
+ // write length
+ if err := writeInt(w, buf, len(x.data)); err != nil {
+ return err
+ }
+
+ // write data
+ if _, err := w.Write(x.data); err != nil {
+ return err
+ }
+
+ // write index
+ for sa := x.sa; len(sa) > 0; {
+ n, err := writeSlice(w, buf, sa)
+ if err != nil {
+ return err
+ }
+ sa = sa[n:]
+ }
+ return nil
+}
+
// Bytes returns the data over which the index was created.
// It must not be modified.
//
@@ -65,9 +191,10 @@ func (x *Index) lookupAll(s []byte) []int {
func (x *Index) Lookup(s []byte, n int) (result []int) {
if len(s) > 0 && n != 0 {
matches := x.lookupAll(s)
- if len(matches) < n || n < 0 {
+ if n < 0 || len(matches) < n {
n = len(matches)
}
+ // 0 <= n <= len(matches)
if n > 0 {
result = make([]int, n)
copy(result, matches)
diff --git a/libgo/go/index/suffixarray/suffixarray_test.go b/libgo/go/index/suffixarray/suffixarray_test.go
index 02374850056..f6b2f00fb7d 100644
--- a/libgo/go/index/suffixarray/suffixarray_test.go
+++ b/libgo/go/index/suffixarray/suffixarray_test.go
@@ -6,6 +6,7 @@ package suffixarray
import (
"bytes"
+ "rand"
"regexp"
"sort"
"strings"
@@ -213,14 +214,44 @@ func (a *index) at(i int) []byte { return a.data[a.sa[i]:] }
func testConstruction(t *testing.T, tc *testCase, x *Index) {
if !sort.IsSorted((*index)(x)) {
- t.Errorf("testConstruction failed %s", tc.name)
+ t.Errorf("failed testConstruction %s", tc.name)
}
}
+func equal(x, y *Index) bool {
+ if !bytes.Equal(x.data, y.data) {
+ return false
+ }
+ for i, j := range x.sa {
+ if j != y.sa[i] {
+ return false
+ }
+ }
+ return true
+}
+
+// returns the serialized index size
+func testSaveRestore(t *testing.T, tc *testCase, x *Index) int {
+ var buf bytes.Buffer
+ if err := x.Write(&buf); err != nil {
+ t.Errorf("failed writing index %s (%s)", tc.name, err)
+ }
+ size := buf.Len()
+ var y Index
+ if err := y.Read(&buf); err != nil {
+ t.Errorf("failed reading index %s (%s)", tc.name, err)
+ }
+ if !equal(x, &y) {
+ t.Errorf("restored index doesn't match saved index %s", tc.name)
+ }
+ return size
+}
+
func TestIndex(t *testing.T) {
for _, tc := range testCases {
x := New([]byte(tc.source))
testConstruction(t, &tc, x)
+ testSaveRestore(t, &tc, x)
testLookups(t, &tc, x, 0)
testLookups(t, &tc, x, 1)
testLookups(t, &tc, x, 10)
@@ -228,3 +259,46 @@ func TestIndex(t *testing.T) {
testLookups(t, &tc, x, -1)
}
}
+
+// Of all possible inputs, the random bytes have the least amount of substring
+// repetition, and the repeated bytes have the most. For most algorithms,
+// the running time of every input will be between these two.
+func benchmarkNew(b *testing.B, random bool) {
+ b.StopTimer()
+ data := make([]byte, 1e6)
+ if random {
+ for i := range data {
+ data[i] = byte(rand.Intn(256))
+ }
+ }
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ New(data)
+ }
+}
+
+func BenchmarkNewIndexRandom(b *testing.B) {
+ benchmarkNew(b, true)
+}
+func BenchmarkNewIndexRepeat(b *testing.B) {
+ benchmarkNew(b, false)
+}
+
+func BenchmarkSaveRestore(b *testing.B) {
+ b.StopTimer()
+ r := rand.New(rand.NewSource(0x5a77a1)) // guarantee always same sequence
+ data := make([]byte, 10<<20) // 10MB of data to index
+ for i := range data {
+ data[i] = byte(r.Intn(256))
+ }
+ x := New(data)
+ size := testSaveRestore(nil, nil, x) // verify correctness
+ buf := bytes.NewBuffer(make([]byte, size)) // avoid growing
+ b.SetBytes(int64(size))
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ x.Write(buf)
+ var y Index
+ y.Read(buf)
+ }
+}
diff --git a/libgo/go/io/io.go b/libgo/go/io/io.go
index b879fe5b721..55206348e42 100644
--- a/libgo/go/io/io.go
+++ b/libgo/go/io/io.go
@@ -256,15 +256,15 @@ func ReadFull(r Reader, buf []byte) (n int, err os.Error) {
return ReadAtLeast(r, buf, len(buf))
}
-// Copyn copies n bytes (or until an error) from src to dst.
+// CopyN copies n bytes (or until an error) from src to dst.
// It returns the number of bytes copied and the earliest
// error encountered while copying. Because Read can
// return the full amount requested as well as an error
-// (including os.EOF), so can Copyn.
+// (including os.EOF), so can CopyN.
//
// If dst implements the ReaderFrom interface,
// the copy is implemented by calling dst.ReadFrom(src).
-func Copyn(dst Writer, src Reader, n int64) (written int64, err os.Error) {
+func CopyN(dst Writer, src Reader, n int64) (written int64, err os.Error) {
// If the writer has a ReadFrom method, use it to do the copy.
// Avoids a buffer allocation and a copy.
if rt, ok := dst.(ReaderFrom); ok {
@@ -437,3 +437,27 @@ func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err os.Error) {
// Size returns the size of the section in bytes.
func (s *SectionReader) Size() int64 { return s.limit - s.base }
+
+// TeeReader returns a Reader that writes to w what it reads from r.
+// All reads from r performed through it are matched with
+// corresponding writes to w. There is no internal buffering -
+// the write must complete before the read completes.
+// Any error encountered while writing is reported as a read error.
+func TeeReader(r Reader, w Writer) Reader {
+ return &teeReader{r, w}
+}
+
+type teeReader struct {
+ r Reader
+ w Writer
+}
+
+func (t *teeReader) Read(p []byte) (n int, err os.Error) {
+ n, err = t.r.Read(p)
+ if n > 0 {
+ if n, err := t.w.Write(p[:n]); err != nil {
+ return n, err
+ }
+ }
+ return
+}
diff --git a/libgo/go/io/io_test.go b/libgo/go/io/io_test.go
index bc4f354af40..f1b23e9461b 100644
--- a/libgo/go/io/io_test.go
+++ b/libgo/go/io/io_test.go
@@ -19,7 +19,7 @@ type Buffer struct {
WriterTo // conflicts with and hides bytes.Buffer's WriterTo.
}
-// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and Copyn.
+// Simple tests, primarily to verify the ReadFrom and WriteTo callouts inside Copy and CopyN.
func TestCopy(t *testing.T) {
rb := new(Buffer)
@@ -51,33 +51,33 @@ func TestCopyWriteTo(t *testing.T) {
}
}
-func TestCopyn(t *testing.T) {
+func TestCopyN(t *testing.T) {
rb := new(Buffer)
wb := new(Buffer)
rb.WriteString("hello, world.")
- Copyn(wb, rb, 5)
+ CopyN(wb, rb, 5)
if wb.String() != "hello" {
- t.Errorf("Copyn did not work properly")
+ t.Errorf("CopyN did not work properly")
}
}
-func TestCopynReadFrom(t *testing.T) {
+func TestCopyNReadFrom(t *testing.T) {
rb := new(Buffer)
wb := new(bytes.Buffer) // implements ReadFrom.
rb.WriteString("hello")
- Copyn(wb, rb, 5)
+ CopyN(wb, rb, 5)
if wb.String() != "hello" {
- t.Errorf("Copyn did not work properly")
+ t.Errorf("CopyN did not work properly")
}
}
-func TestCopynWriteTo(t *testing.T) {
+func TestCopyNWriteTo(t *testing.T) {
rb := new(bytes.Buffer) // implements WriteTo.
wb := new(Buffer)
rb.WriteString("hello, world.")
- Copyn(wb, rb, 5)
+ CopyN(wb, rb, 5)
if wb.String() != "hello" {
- t.Errorf("Copyn did not work properly")
+ t.Errorf("CopyN did not work properly")
}
}
@@ -89,30 +89,30 @@ func (w *noReadFrom) Write(p []byte) (n int, err os.Error) {
return w.w.Write(p)
}
-func TestCopynEOF(t *testing.T) {
+func TestCopyNEOF(t *testing.T) {
// Test that EOF behavior is the same regardless of whether
- // argument to Copyn has ReadFrom.
+ // argument to CopyN has ReadFrom.
b := new(bytes.Buffer)
- n, err := Copyn(&noReadFrom{b}, strings.NewReader("foo"), 3)
+ n, err := CopyN(&noReadFrom{b}, strings.NewReader("foo"), 3)
if n != 3 || err != nil {
- t.Errorf("Copyn(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err)
+ t.Errorf("CopyN(noReadFrom, foo, 3) = %d, %v; want 3, nil", n, err)
}
- n, err = Copyn(&noReadFrom{b}, strings.NewReader("foo"), 4)
+ n, err = CopyN(&noReadFrom{b}, strings.NewReader("foo"), 4)
if n != 3 || err != os.EOF {
- t.Errorf("Copyn(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
+ t.Errorf("CopyN(noReadFrom, foo, 4) = %d, %v; want 3, EOF", n, err)
}
- n, err = Copyn(b, strings.NewReader("foo"), 3) // b has read from
+ n, err = CopyN(b, strings.NewReader("foo"), 3) // b has read from
if n != 3 || err != nil {
- t.Errorf("Copyn(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err)
+ t.Errorf("CopyN(bytes.Buffer, foo, 3) = %d, %v; want 3, nil", n, err)
}
- n, err = Copyn(b, strings.NewReader("foo"), 4) // b has read from
+ n, err = CopyN(b, strings.NewReader("foo"), 4) // b has read from
if n != 3 || err != os.EOF {
- t.Errorf("Copyn(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
+ t.Errorf("CopyN(bytes.Buffer, foo, 4) = %d, %v; want 3, EOF", n, err)
}
}
@@ -177,3 +177,30 @@ func testReadAtLeast(t *testing.T, rb ReadWriter) {
t.Errorf("expected to have read 1 bytes, got %v", n)
}
}
+
+func TestTeeReader(t *testing.T) {
+ src := []byte("hello, world")
+ dst := make([]byte, len(src))
+ rb := bytes.NewBuffer(src)
+ wb := new(bytes.Buffer)
+ r := TeeReader(rb, wb)
+ if n, err := ReadFull(r, dst); err != nil || n != len(src) {
+ t.Fatalf("ReadFull(r, dst) = %d, %v; want %d, nil", n, err, len(src))
+ }
+ if !bytes.Equal(dst, src) {
+ t.Errorf("bytes read = %q want %q", dst, src)
+ }
+ if !bytes.Equal(wb.Bytes(), src) {
+ t.Errorf("bytes written = %q want %q", wb.Bytes(), src)
+ }
+ if n, err := r.Read(dst); n != 0 || err != os.EOF {
+ t.Errorf("r.Read at EOF = %d, %v want 0, EOF", n, err)
+ }
+ rb = bytes.NewBuffer(src)
+ pr, pw := Pipe()
+ pr.Close()
+ r = TeeReader(rb, pw)
+ if n, err := ReadFull(r, dst); n != 0 || err != os.EPIPE {
+ t.Errorf("closed tee: ReadFull(r, dst) = %d, %v; want 0, EPIPE", n, err)
+ }
+}
diff --git a/libgo/go/io/ioutil/ioutil.go b/libgo/go/io/ioutil/ioutil.go
index fffa1320f59..dd50d96869e 100644
--- a/libgo/go/io/ioutil/ioutil.go
+++ b/libgo/go/io/ioutil/ioutil.go
@@ -104,6 +104,10 @@ func NopCloser(r io.Reader) io.ReadCloser {
type devNull int
+// devNull implements ReaderFrom as an optimization so io.Copy to
+// ioutil.Discard can avoid doing unnecessary work.
+var _ io.ReaderFrom = devNull(0)
+
func (devNull) Write(p []byte) (int, os.Error) {
return len(p), nil
}
diff --git a/libgo/go/json/decode.go b/libgo/go/json/decode.go
index b7129f9846a..31b15a400df 100644
--- a/libgo/go/json/decode.go
+++ b/libgo/go/json/decode.go
@@ -22,17 +22,20 @@ import (
// Unmarshal parses the JSON-encoded data and stores the result
// in the value pointed to by v.
//
-// Unmarshal traverses the value v recursively.
-// If an encountered value implements the Unmarshaler interface,
-// Unmarshal calls its UnmarshalJSON method with a well-formed
-// JSON encoding.
-//
-// Otherwise, Unmarshal uses the inverse of the encodings that
+// Unmarshal uses the inverse of the encodings that
// Marshal uses, allocating maps, slices, and pointers as necessary,
// with the following additional rules:
//
-// To unmarshal a JSON value into a nil interface value, the
-// type stored in the interface value is one of:
+// To unmarshal JSON into a pointer, Unmarshal first handles the case of
+// the JSON being the JSON literal null. In that case, Unmarshal sets
+// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
+// the value pointed at by the pointer. If the pointer is nil, Unmarshal
+// allocates a new value for it to point to.
+//
+// To unmarshal JSON into an interface value, Unmarshal unmarshals
+// the JSON into the concrete value contained in the interface value.
+// If the interface value is nil, that is, has no concrete value stored in it,
+// Unmarshal stores one of these in the interface value:
//
// bool, for JSON booleans
// float64, for JSON numbers
@@ -250,8 +253,8 @@ func (d *decodeState) value(v reflect.Value) {
// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
// if it encounters an Unmarshaler, indirect stops and returns that.
-// if wantptr is true, indirect stops at the last pointer.
-func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, reflect.Value) {
+// if decodingNull is true, indirect stops at the last pointer so it can be set to nil.
+func (d *decodeState) indirect(v reflect.Value, decodingNull bool) (Unmarshaler, reflect.Value) {
// If v is a named type and is addressable,
// start with its address, so that if the type has pointer methods,
// we find them.
@@ -277,7 +280,7 @@ func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, refl
break
}
- if pv.Elem().Kind() != reflect.Ptr && wantptr && pv.CanSet() && !isUnmarshaler {
+ if pv.Elem().Kind() != reflect.Ptr && decodingNull && pv.CanSet() {
return nil, pv
}
if pv.IsNil() {
@@ -391,11 +394,6 @@ func (d *decodeState) array(v reflect.Value) {
}
}
-// matchName returns true if key should be written to a field named name.
-func matchName(key, name string) bool {
- return strings.ToLower(key) == strings.ToLower(name)
-}
-
// object consumes an object from d.data[d.off-1:], decoding into the value v.
// the first byte of the object ('{') has been read already.
func (d *decodeState) object(v reflect.Value) {
@@ -485,24 +483,31 @@ func (d *decodeState) object(v reflect.Value) {
var f reflect.StructField
var ok bool
st := sv.Type()
- // First try for field with that tag.
- if isValidTag(key) {
- for i := 0; i < sv.NumField(); i++ {
- f = st.Field(i)
- tagName, _ := parseTag(f.Tag.Get("json"))
- if tagName == key {
- ok = true
- break
- }
+ for i := 0; i < sv.NumField(); i++ {
+ sf := st.Field(i)
+ tag := sf.Tag.Get("json")
+ if tag == "-" {
+ // Pretend this field doesn't exist.
+ continue
+ }
+ // First, tag match
+ tagName, _ := parseTag(tag)
+ if tagName == key {
+ f = sf
+ ok = true
+ break // no better match possible
+ }
+ // Second, exact field name match
+ if sf.Name == key {
+ f = sf
+ ok = true
+ }
+ // Third, case-insensitive field name match,
+ // but only if a better match hasn't already been seen
+ if !ok && strings.EqualFold(sf.Name, key) {
+ f = sf
+ ok = true
}
- }
- if !ok {
- // Second, exact match.
- f, ok = st.FieldByName(key)
- }
- if !ok {
- // Third, case-insensitive match.
- f, ok = st.FieldByNameFunc(func(s string) bool { return matchName(key, s) })
}
// Extract value; name must be exported.
diff --git a/libgo/go/json/decode_test.go b/libgo/go/json/decode_test.go
index 5f6c3f5b8d0..2c7cbc4a290 100644
--- a/libgo/go/json/decode_test.go
+++ b/libgo/go/json/decode_test.go
@@ -15,6 +15,7 @@ import (
type T struct {
X string
Y int
+ Z int `json:"-"`
}
type tx struct {
@@ -42,7 +43,7 @@ var (
um0, um1 unmarshaler // target2 of unmarshaling
ump = &um1
umtrue = unmarshaler{true}
- umslice = []unmarshaler{unmarshaler{true}}
+ umslice = []unmarshaler{{true}}
umslicep = new([]unmarshaler)
umstruct = ustruct{unmarshaler{true}}
)
@@ -68,6 +69,9 @@ var unmarshalTests = []unmarshalTest{
{`{"X": [1,2,3], "Y": 4}`, new(T), T{Y: 4}, &UnmarshalTypeError{"array", reflect.TypeOf("")}},
{`{"x": 1}`, new(tx), tx{}, &UnmarshalFieldError{"x", txType, txType.Field(0)}},
+ // Z has a "-" tag.
+ {`{"Y": 1, "Z": 2}`, new(T), T{Y: 1}, nil},
+
// syntax errors
{`{"X": "foo", "Y"}`, nil, nil, &SyntaxError{"invalid character '}' after object key", 17}},
diff --git a/libgo/go/json/encode.go b/libgo/go/json/encode.go
index 16be5e2af16..46abe4360ed 100644
--- a/libgo/go/json/encode.go
+++ b/libgo/go/json/encode.go
@@ -24,8 +24,11 @@ import (
// Marshal returns the JSON encoding of v.
//
// Marshal traverses the value v recursively.
-// If an encountered value implements the Marshaler interface,
-// Marshal calls its MarshalJSON method to produce JSON.
+// If an encountered value implements the Marshaler interface
+// and is not a nil pointer, Marshal calls its MarshalJSON method
+// to produce JSON. The nil pointer exception is not strictly necessary
+// but mimics a similar, necessary exception in the behavior of
+// UnmarshalJSON.
//
// Otherwise, Marshal uses the following type-dependent default encodings:
//
@@ -40,18 +43,23 @@ import (
// []byte encodes as a base64-encoded string.
//
// Struct values encode as JSON objects. Each exported struct field
-// becomes a member of the object unless the field is empty and its tag
-// specifies the "omitempty" option. The empty values are false, 0, any
+// becomes a member of the object unless
+// - the field's tag is "-", or
+// - the field is empty and its tag specifies the "omitempty" option.
+// The empty values are false, 0, any
// nil pointer or interface value, and any array, slice, map, or string of
// length zero. The object's default key string is the struct field name
// but can be specified in the struct field's tag value. The "json" key in
// struct field's tag value is the key name, followed by an optional comma
// and options. Examples:
//
-// // Specifies that Field appears in JSON as key "myName"
+// // Field is ignored by this package.
+// Field int `json:"-"`
+//
+// // Field appears in JSON as key "myName".
// Field int `json:"myName"`
//
-// // Specifies that Field appears in JSON as key "myName" and
+// // Field appears in JSON as key "myName" and
// // the field is omitted from the object if its value is empty,
// // as defined above.
// Field int `json:"myName,omitempty"`
@@ -240,7 +248,7 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
return
}
- if j, ok := v.Interface().(Marshaler); ok {
+ if j, ok := v.Interface().(Marshaler); ok && (v.Kind() != reflect.Ptr || !v.IsNil()) {
b, err := j.MarshalJSON()
if err == nil {
// copy JSON into buffer, checking validity.
@@ -298,6 +306,9 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
}
tag, omitEmpty, quoted := f.Name, false, false
if tv := f.Tag.Get("json"); tv != "" {
+ if tv == "-" {
+ continue
+ }
name, opts := parseTag(tv)
if isValidTag(name) {
tag = name
diff --git a/libgo/go/json/encode_test.go b/libgo/go/json/encode_test.go
index 012e9f143b4..f85bb6216a2 100644
--- a/libgo/go/json/encode_test.go
+++ b/libgo/go/json/encode_test.go
@@ -13,6 +13,7 @@ import (
type Optionals struct {
Sr string `json:"sr"`
So string `json:"so,omitempty"`
+ Sw string `json:"-"`
Ir int `json:"omitempty"` // actually named omitempty, not an option
Io int `json:"io,omitempty"`
@@ -33,6 +34,7 @@ var optionalsExpected = `{
func TestOmitEmpty(t *testing.T) {
var o Optionals
+ o.Sw = "something"
o.Mr = map[string]interface{}{}
o.Mo = map[string]interface{}{}
diff --git a/libgo/go/json/indent.go b/libgo/go/json/indent.go
index 000da42f6fb..2a753037308 100644
--- a/libgo/go/json/indent.go
+++ b/libgo/go/json/indent.go
@@ -59,6 +59,7 @@ func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) os.Error {
needIndent := false
depth := 0
for _, c := range src {
+ scan.bytes++
v := scan.step(&scan, int(c))
if v == scanSkipSpace {
continue
diff --git a/libgo/go/json/scanner_test.go b/libgo/go/json/scanner_test.go
index 023e7c81ee4..4d73eac8aaa 100644
--- a/libgo/go/json/scanner_test.go
+++ b/libgo/go/json/scanner_test.go
@@ -7,7 +7,9 @@ package json
import (
"bytes"
"math"
+ "os"
"rand"
+ "reflect"
"testing"
)
@@ -136,6 +138,29 @@ func TestIndentBig(t *testing.T) {
}
}
+type indentErrorTest struct {
+ in string
+ err os.Error
+}
+
+var indentErrorTests = []indentErrorTest{
+ {`{"X": "foo", "Y"}`, &SyntaxError{"invalid character '}' after object key", 17}},
+ {`{"X": "foo" "Y": "bar"}`, &SyntaxError{"invalid character '\"' after object key:value pair", 13}},
+}
+
+func TestIdentErrors(t *testing.T) {
+ for i, tt := range indentErrorTests {
+ slice := make([]uint8, 0)
+ buf := bytes.NewBuffer(slice)
+ if err := Indent(buf, []uint8(tt.in), "", ""); err != nil {
+ if !reflect.DeepEqual(err, tt.err) {
+ t.Errorf("#%d: Indent: %#v", i, err)
+ continue
+ }
+ }
+ }
+}
+
func TestNextValueBig(t *testing.T) {
initBig()
var scan scanner
@@ -150,7 +175,7 @@ func TestNextValueBig(t *testing.T) {
t.Errorf("invalid rest: %d", len(rest))
}
- item, rest, err = nextValue(append(jsonBig, []byte("HELLO WORLD")...), &scan)
+ item, rest, err = nextValue(append(jsonBig, "HELLO WORLD"...), &scan)
if err != nil {
t.Fatalf("nextValue extra: %s", err)
}
@@ -235,10 +260,10 @@ func genValue(n int) interface{} {
}
func genString(stddev float64) string {
- n := int(math.Fabs(rand.NormFloat64()*stddev + stddev/2))
+ n := int(math.Abs(rand.NormFloat64()*stddev + stddev/2))
c := make([]int, n)
for i := range c {
- f := math.Fabs(rand.NormFloat64()*64 + 32)
+ f := math.Abs(rand.NormFloat64()*64 + 32)
if f > 0x10ffff {
f = 0x10ffff
}
@@ -248,7 +273,7 @@ func genString(stddev float64) string {
}
func genArray(n int) []interface{} {
- f := int(math.Fabs(rand.NormFloat64()) * math.Fmin(10, float64(n/2)))
+ f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
if f > n {
f = n
}
@@ -263,7 +288,7 @@ func genArray(n int) []interface{} {
}
func genMap(n int) map[string]interface{} {
- f := int(math.Fabs(rand.NormFloat64()) * math.Fmin(10, float64(n/2)))
+ f := int(math.Abs(rand.NormFloat64()) * math.Min(10, float64(n/2)))
if f > n {
f = n
}
diff --git a/libgo/go/json/stream_test.go b/libgo/go/json/stream_test.go
index 6ddaed9fe8f..ce5a7e6d656 100644
--- a/libgo/go/json/stream_test.go
+++ b/libgo/go/json/stream_test.go
@@ -120,3 +120,28 @@ func TestRawMessage(t *testing.T) {
t.Fatalf("Marshal: have %#q want %#q", b, msg)
}
}
+
+func TestNullRawMessage(t *testing.T) {
+ // TODO(rsc): Should not need the * in *RawMessage
+ var data struct {
+ X float64
+ Id *RawMessage
+ Y float32
+ }
+ data.Id = new(RawMessage)
+ const msg = `{"X":0.1,"Id":null,"Y":0.2}`
+ err := Unmarshal([]byte(msg), &data)
+ if err != nil {
+ t.Fatalf("Unmarshal: %v", err)
+ }
+ if data.Id != nil {
+ t.Fatalf("Raw mismatch: have non-nil, want nil")
+ }
+ b, err := Marshal(&data)
+ if err != nil {
+ t.Fatalf("Marshal: %v", err)
+ }
+ if string(b) != msg {
+ t.Fatalf("Marshal: have %#q want %#q", b, msg)
+ }
+}
diff --git a/libgo/go/mail/message_test.go b/libgo/go/mail/message_test.go
index e1bcc89ee5f..5653647b8cc 100644
--- a/libgo/go/mail/message_test.go
+++ b/libgo/go/mail/message_test.go
@@ -94,7 +94,6 @@ func TestDateParsing(t *testing.T) {
Hour: 9,
Minute: 55,
Second: 6,
- Weekday: 5, // Fri
ZoneOffset: -6 * 60 * 60,
},
},
diff --git a/libgo/go/math/abs.go b/libgo/go/math/abs.go
new file mode 100644
index 00000000000..eb3e4c72b32
--- /dev/null
+++ b/libgo/go/math/abs.go
@@ -0,0 +1,21 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+// Abs returns the absolute value of x.
+//
+// Special cases are:
+// Abs(+Inf) = +Inf
+// Abs(-Inf) = +Inf
+// Abs(NaN) = NaN
+func Abs(x float64) float64 {
+ switch {
+ case x < 0:
+ return -x
+ case x == 0:
+ return 0 // return correctly abs(-0)
+ }
+ return x
+}
diff --git a/libgo/go/math/abs_decl.go b/libgo/go/math/abs_decl.go
new file mode 100644
index 00000000000..6be9305ac50
--- /dev/null
+++ b/libgo/go/math/abs_decl.go
@@ -0,0 +1,7 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+func Abs(x float64) float64
diff --git a/libgo/go/math/all_test.go b/libgo/go/math/all_test.go
index d2a7d411ec0..94ddea2bfcb 100644
--- a/libgo/go/math/all_test.go
+++ b/libgo/go/math/all_test.go
@@ -1359,6 +1359,20 @@ var powSC = []float64{
NaN(), // pow(NaN, NaN)
}
+var vfpow10SC = []int{
+ MinInt32,
+ MaxInt32,
+ -325,
+ 309,
+}
+
+var pow10SC = []float64{
+ 0, // pow10(MinInt32)
+ Inf(1), // pow10(MaxInt32)
+ 0, // pow10(-325)
+ Inf(1), // pow10(309)
+}
+
var vfsignbitSC = []float64{
Inf(-1),
Copysign(0, -1),
@@ -1570,7 +1584,7 @@ func TestAcos(t *testing.T) {
func TestAcosh(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := 1 + Fabs(vf[i])
+ a := 1 + Abs(vf[i])
if f := Acosh(a); !veryclose(acosh[i], f) {
t.Errorf("Acosh(%g) = %g, want %g", a, f, acosh[i])
}
@@ -1804,23 +1818,23 @@ func testExp2(t *testing.T, Exp2 func(float64) float64, name string) {
}
}
-func TestFabs(t *testing.T) {
+func TestAbs(t *testing.T) {
for i := 0; i < len(vf); i++ {
- if f := Fabs(vf[i]); fabs[i] != f {
- t.Errorf("Fabs(%g) = %g, want %g", vf[i], f, fabs[i])
+ if f := Abs(vf[i]); fabs[i] != f {
+ t.Errorf("Abs(%g) = %g, want %g", vf[i], f, fabs[i])
}
}
for i := 0; i < len(vffabsSC); i++ {
- if f := Fabs(vffabsSC[i]); !alike(fabsSC[i], f) {
- t.Errorf("Fabs(%g) = %g, want %g", vffabsSC[i], f, fabsSC[i])
+ if f := Abs(vffabsSC[i]); !alike(fabsSC[i], f) {
+ t.Errorf("Abs(%g) = %g, want %g", vffabsSC[i], f, fabsSC[i])
}
}
}
-func TestFdim(t *testing.T) {
+func TestDim(t *testing.T) {
for i := 0; i < len(vf); i++ {
- if f := Fdim(vf[i], 0); fdim[i] != f {
- t.Errorf("Fdim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i])
+ if f := Dim(vf[i], 0); fdim[i] != f {
+ t.Errorf("Dim(%g, %g) = %g, want %g", vf[i], 0.0, f, fdim[i])
}
}
}
@@ -1838,31 +1852,31 @@ func TestFloor(t *testing.T) {
}
}
-func TestFmax(t *testing.T) {
+func TestMax(t *testing.T) {
for i := 0; i < len(vf); i++ {
- if f := Fmax(vf[i], ceil[i]); ceil[i] != f {
- t.Errorf("Fmax(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i])
+ if f := Max(vf[i], ceil[i]); ceil[i] != f {
+ t.Errorf("Max(%g, %g) = %g, want %g", vf[i], ceil[i], f, ceil[i])
}
}
}
-func TestFmin(t *testing.T) {
+func TestMin(t *testing.T) {
for i := 0; i < len(vf); i++ {
- if f := Fmin(vf[i], floor[i]); floor[i] != f {
- t.Errorf("Fmin(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i])
+ if f := Min(vf[i], floor[i]); floor[i] != f {
+ t.Errorf("Min(%g, %g) = %g, want %g", vf[i], floor[i], f, floor[i])
}
}
}
-func TestFmod(t *testing.T) {
+func TestMod(t *testing.T) {
for i := 0; i < len(vf); i++ {
- if f := Fmod(10, vf[i]); fmod[i] != f {
- t.Errorf("Fmod(10, %g) = %g, want %g", vf[i], f, fmod[i])
+ if f := Mod(10, vf[i]); fmod[i] != f {
+ t.Errorf("Mod(10, %g) = %g, want %g", vf[i], f, fmod[i])
}
}
for i := 0; i < len(vffmodSC); i++ {
- if f := Fmod(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) {
- t.Errorf("Fmod(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i])
+ if f := Mod(vffmodSC[i][0], vffmodSC[i][1]); !alike(fmodSC[i], f) {
+ t.Errorf("Mod(%g, %g) = %g, want %g", vffmodSC[i][0], vffmodSC[i][1], f, fmodSC[i])
}
}
}
@@ -1900,7 +1914,7 @@ func TestGamma(t *testing.T) {
func TestHypot(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := Fabs(1e200 * tanh[i] * Sqrt(2))
+ a := Abs(1e200 * tanh[i] * Sqrt(2))
if f := Hypot(1e200*tanh[i], 1e200*tanh[i]); !veryclose(a, f) {
t.Errorf("Hypot(%g, %g) = %g, want %g", 1e200*tanh[i], 1e200*tanh[i], f, a)
}
@@ -2019,7 +2033,7 @@ func TestLgamma(t *testing.T) {
func TestLog(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := Fabs(vf[i])
+ a := Abs(vf[i])
if f := Log(a); log[i] != f {
t.Errorf("Log(%g) = %g, want %g", a, f, log[i])
}
@@ -2054,7 +2068,7 @@ func TestLogb(t *testing.T) {
func TestLog10(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := Fabs(vf[i])
+ a := Abs(vf[i])
if f := Log10(a); !veryclose(log10[i], f) {
t.Errorf("Log10(%g) = %g, want %g", a, f, log10[i])
}
@@ -2089,7 +2103,7 @@ func TestLog1p(t *testing.T) {
func TestLog2(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := Fabs(vf[i])
+ a := Abs(vf[i])
if f := Log2(a); !veryclose(log2[i], f) {
t.Errorf("Log2(%g) = %g, want %g", a, f, log2[i])
}
@@ -2143,6 +2157,14 @@ func TestPow(t *testing.T) {
}
}
+func TestPow10(t *testing.T) {
+ for i := 0; i < len(vfpow10SC); i++ {
+ if f := Pow10(vfpow10SC[i]); !alike(pow10SC[i], f) {
+ t.Errorf("Pow10(%d) = %g, want %g", vfpow10SC[i], f, pow10SC[i])
+ }
+ }
+}
+
func TestRemainder(t *testing.T) {
for i := 0; i < len(vf); i++ {
if f := Remainder(10, vf[i]); remainder[i] != f {
@@ -2204,11 +2226,11 @@ func TestSinh(t *testing.T) {
func TestSqrt(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := Fabs(vf[i])
+ a := Abs(vf[i])
if f := SqrtGo(a); sqrt[i] != f {
t.Errorf("SqrtGo(%g) = %g, want %g", a, f, sqrt[i])
}
- a = Fabs(vf[i])
+ a = Abs(vf[i])
if f := Sqrt(a); sqrt[i] != f {
t.Errorf("Sqrt(%g) = %g, want %g", a, f, sqrt[i])
}
@@ -2275,7 +2297,7 @@ func TestTrunc(t *testing.T) {
func TestY0(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := Fabs(vf[i])
+ a := Abs(vf[i])
if f := Y0(a); !close(y0[i], f) {
t.Errorf("Y0(%g) = %g, want %g", a, f, y0[i])
}
@@ -2289,7 +2311,7 @@ func TestY0(t *testing.T) {
func TestY1(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := Fabs(vf[i])
+ a := Abs(vf[i])
if f := Y1(a); !soclose(y1[i], f, 2e-14) {
t.Errorf("Y1(%g) = %g, want %g", a, f, y1[i])
}
@@ -2303,7 +2325,7 @@ func TestY1(t *testing.T) {
func TestYn(t *testing.T) {
for i := 0; i < len(vf); i++ {
- a := Fabs(vf[i])
+ a := Abs(vf[i])
if f := Yn(2, a); !close(y2[i], f) {
t.Errorf("Yn(2, %g) = %g, want %g", a, f, y2[i])
}
@@ -2509,15 +2531,15 @@ func BenchmarkExp2Go(b *testing.B) {
}
}
-func BenchmarkFabs(b *testing.B) {
+func BenchmarkAbs(b *testing.B) {
for i := 0; i < b.N; i++ {
- Fabs(.5)
+ Abs(.5)
}
}
-func BenchmarkFdim(b *testing.B) {
+func BenchmarkDim(b *testing.B) {
for i := 0; i < b.N; i++ {
- Fdim(10, 3)
+ Dim(10, 3)
}
}
@@ -2527,21 +2549,21 @@ func BenchmarkFloor(b *testing.B) {
}
}
-func BenchmarkFmax(b *testing.B) {
+func BenchmarkMax(b *testing.B) {
for i := 0; i < b.N; i++ {
- Fmax(10, 3)
+ Max(10, 3)
}
}
-func BenchmarkFmin(b *testing.B) {
+func BenchmarkMin(b *testing.B) {
for i := 0; i < b.N; i++ {
- Fmin(10, 3)
+ Min(10, 3)
}
}
-func BenchmarkFmod(b *testing.B) {
+func BenchmarkMod(b *testing.B) {
for i := 0; i < b.N; i++ {
- Fmod(10, 3)
+ Mod(10, 3)
}
}
@@ -2659,6 +2681,18 @@ func BenchmarkPowFrac(b *testing.B) {
}
}
+func BenchmarkPow10Pos(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Pow10(300)
+ }
+}
+
+func BenchmarkPow10Neg(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Pow10(-300)
+ }
+}
+
func BenchmarkRemainder(b *testing.B) {
for i := 0; i < b.N; i++ {
Remainder(10, 3)
diff --git a/libgo/go/math/bits.go b/libgo/go/math/bits.go
index a1dca3ed695..1cf60ce7df2 100644
--- a/libgo/go/math/bits.go
+++ b/libgo/go/math/bits.go
@@ -52,7 +52,7 @@ func IsInf(f float64, sign int) bool {
// satisfying x == y × 2**exp. It assumes x is finite and non-zero.
func normalize(x float64) (y float64, exp int) {
const SmallestNormal = 2.2250738585072014e-308 // 2**-1022
- if Fabs(x) < SmallestNormal {
+ if Abs(x) < SmallestNormal {
return x * (1 << 52), -52
}
return x, 0
diff --git a/libgo/go/math/dim.go b/libgo/go/math/dim.go
new file mode 100644
index 00000000000..d2eb52f3bf1
--- /dev/null
+++ b/libgo/go/math/dim.go
@@ -0,0 +1,29 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+// Dim returns the maximum of x-y or 0.
+func Dim(x, y float64) float64 {
+ if x > y {
+ return x - y
+ }
+ return 0
+}
+
+// Max returns the larger of x or y.
+func Max(x, y float64) float64 {
+ if x > y {
+ return x
+ }
+ return y
+}
+
+// Min returns the smaller of x or y.
+func Min(x, y float64) float64 {
+ if x < y {
+ return x
+ }
+ return y
+}
diff --git a/libgo/go/math/dim_decl.go b/libgo/go/math/dim_decl.go
new file mode 100644
index 00000000000..196f84fd793
--- /dev/null
+++ b/libgo/go/math/dim_decl.go
@@ -0,0 +1,9 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+func Dim(x, y float64) float64
+func Max(x, y float64) float64
+func Min(x, y float64) float64
diff --git a/libgo/go/math/fabs.go b/libgo/go/math/fabs.go
deleted file mode 100644
index 343123126db..00000000000
--- a/libgo/go/math/fabs.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-// Fabs returns the absolute value of x.
-//
-// Special cases are:
-// Fabs(+Inf) = +Inf
-// Fabs(-Inf) = +Inf
-// Fabs(NaN) = NaN
-func Fabs(x float64) float64 {
- switch {
- case x < 0:
- return -x
- case x == 0:
- return 0 // return correctly fabs(-0)
- }
- return x
-}
diff --git a/libgo/go/math/fdim.go b/libgo/go/math/fdim.go
deleted file mode 100644
index 18993137a20..00000000000
--- a/libgo/go/math/fdim.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-// Fdim returns the maximum of x-y or 0.
-func Fdim(x, y float64) float64 {
- if x > y {
- return x - y
- }
- return 0
-}
-
-// Fmax returns the larger of x or y.
-func Fmax(x, y float64) float64 {
- if x > y {
- return x
- }
- return y
-}
-
-// Fmin returns the smaller of x or y.
-func Fmin(x, y float64) float64 {
- if x < y {
- return x
- }
- return y
-}
diff --git a/libgo/go/math/fmod.go b/libgo/go/math/fmod.go
deleted file mode 100644
index 75c614629d4..00000000000
--- a/libgo/go/math/fmod.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2009-2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package math
-
-/*
- Floating-point mod function.
-*/
-
-// Fmod returns the floating-point remainder of x/y.
-// The magnitude of the result is less than y and its
-// sign agrees with that of x.
-//
-// Special cases are:
-// if x is not finite, Fmod returns NaN
-// if y is 0 or NaN, Fmod returns NaN
-func Fmod(x, y float64) float64 {
- // TODO(rsc): Remove manual inlining of IsNaN, IsInf
- // when compiler does it for us.
- if y == 0 || x > MaxFloat64 || x < -MaxFloat64 || x != x || y != y { // y == 0 || IsInf(x, 0) || IsNaN(x) || IsNan(y)
- return NaN()
- }
- if y < 0 {
- y = -y
- }
-
- yfr, yexp := Frexp(y)
- sign := false
- r := x
- if x < 0 {
- r = -x
- sign = true
- }
-
- for r >= y {
- rfr, rexp := Frexp(r)
- if rfr < yfr {
- rexp = rexp - 1
- }
- r = r - Ldexp(y, rexp-yexp)
- }
- if sign {
- r = -r
- }
- return r
-}
diff --git a/libgo/go/math/gamma.go b/libgo/go/math/gamma.go
index 73ca0e53add..01365070ebe 100644
--- a/libgo/go/math/gamma.go
+++ b/libgo/go/math/gamma.go
@@ -127,7 +127,7 @@ func Gamma(x float64) float64 {
case x < -170.5674972726612 || x > 171.61447887182298:
return Inf(1)
}
- q := Fabs(x)
+ q := Abs(x)
p := Floor(q)
if q > 33 {
if x >= 0 {
@@ -146,7 +146,7 @@ func Gamma(x float64) float64 {
if z == 0 {
return Inf(signgam)
}
- z = Pi / (Fabs(z) * stirling(q))
+ z = Pi / (Abs(z) * stirling(q))
return float64(signgam) * z
}
diff --git a/libgo/go/math/jn.go b/libgo/go/math/jn.go
index 9024af3c223..1878df5b5a2 100644
--- a/libgo/go/math/jn.go
+++ b/libgo/go/math/jn.go
@@ -197,7 +197,7 @@ func Jn(n int, x float64) float64 {
tmp := float64(n)
v := 2 / x
- tmp = tmp * Log(Fabs(v*tmp))
+ tmp = tmp * Log(Abs(v*tmp))
if tmp < 7.09782712893383973096e+02 {
for i := n - 1; i > 0; i-- {
di := float64(i + i)
diff --git a/libgo/go/math/lgamma.go b/libgo/go/math/lgamma.go
index dc30f468f4b..8f6d7b99fc5 100644
--- a/libgo/go/math/lgamma.go
+++ b/libgo/go/math/lgamma.go
@@ -206,7 +206,7 @@ func Lgamma(x float64) (lgamma float64, sign int) {
lgamma = Inf(1) // -integer
return
}
- nadj = Log(Pi / Fabs(t*x))
+ nadj = Log(Pi / Abs(t*x))
if t < 0 {
sign = -1
}
@@ -319,7 +319,7 @@ func sinPi(x float64) float64 {
z := Floor(x)
var n int
if z != x { // inexact
- x = Fmod(x, 2)
+ x = Mod(x, 2)
n = int(x * 4)
} else {
if x >= Two53 { // x must be even
diff --git a/libgo/go/math/mod.go b/libgo/go/math/mod.go
new file mode 100644
index 00000000000..6b16abe5d13
--- /dev/null
+++ b/libgo/go/math/mod.go
@@ -0,0 +1,47 @@
+// Copyright 2009-2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+/*
+ Floating-point mod function.
+*/
+
+// Mod returns the floating-point remainder of x/y.
+// The magnitude of the result is less than y and its
+// sign agrees with that of x.
+//
+// Special cases are:
+// if x is not finite, Mod returns NaN
+// if y is 0 or NaN, Mod returns NaN
+func Mod(x, y float64) float64 {
+ // TODO(rsc): Remove manual inlining of IsNaN, IsInf
+ // when compiler does it for us.
+ if y == 0 || x > MaxFloat64 || x < -MaxFloat64 || x != x || y != y { // y == 0 || IsInf(x, 0) || IsNaN(x) || IsNan(y)
+ return NaN()
+ }
+ if y < 0 {
+ y = -y
+ }
+
+ yfr, yexp := Frexp(y)
+ sign := false
+ r := x
+ if x < 0 {
+ r = -x
+ sign = true
+ }
+
+ for r >= y {
+ rfr, rexp := Frexp(r)
+ if rfr < yfr {
+ rexp = rexp - 1
+ }
+ r = r - Ldexp(y, rexp-yexp)
+ }
+ if sign {
+ r = -r
+ }
+ return r
+}
diff --git a/libgo/go/math/mod_decl.go b/libgo/go/math/mod_decl.go
new file mode 100644
index 00000000000..d5047a754a8
--- /dev/null
+++ b/libgo/go/math/mod_decl.go
@@ -0,0 +1,7 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package math
+
+func Mod(x, y float64) float64
diff --git a/libgo/go/math/pow.go b/libgo/go/math/pow.go
index 06b107401b9..f0f52c5cd4b 100644
--- a/libgo/go/math/pow.go
+++ b/libgo/go/math/pow.go
@@ -66,7 +66,7 @@ func Pow(x, y float64) float64 {
switch {
case x == -1:
return 1
- case (Fabs(x) < 1) == IsInf(y, 1):
+ case (Abs(x) < 1) == IsInf(y, 1):
return 0
default:
return Inf(1)
diff --git a/libgo/go/math/pow10.go b/libgo/go/math/pow10.go
index bda2e824ef1..20f91bcb70c 100644
--- a/libgo/go/math/pow10.go
+++ b/libgo/go/math/pow10.go
@@ -10,6 +10,12 @@ var pow10tab [70]float64
// Pow10 returns 10**e, the base-10 exponential of e.
func Pow10(e int) float64 {
+ if e <= -325 {
+ return 0
+ } else if e > 309 {
+ return Inf(1)
+ }
+
if e < 0 {
return 1 / Pow10(-e)
}
diff --git a/libgo/go/math/remainder.go b/libgo/go/math/remainder.go
index be8724c7f3a..7fb8a12f9e6 100644
--- a/libgo/go/math/remainder.go
+++ b/libgo/go/math/remainder.go
@@ -24,7 +24,7 @@ package math
// precision arithmetic, where [x/y] is the (infinite bit)
// integer nearest x/y (in half way cases, choose the even one).
// Method :
-// Based on fmod() returning x - [x/y]chopped * y exactly.
+// Based on Mod() returning x - [x/y]chopped * y exactly.
// Remainder returns the IEEE 754 floating-point remainder of x/y.
//
@@ -60,7 +60,7 @@ func Remainder(x, y float64) float64 {
return 0
}
if y <= HalfMax {
- x = Fmod(x, y+y) // now x < 2y
+ x = Mod(x, y+y) // now x < 2y
}
if y < Tiny {
if x+x > y {
diff --git a/libgo/go/mime/grammar.go b/libgo/go/mime/grammar.go
index 6e319ff8be8..70a94cd807f 100644
--- a/libgo/go/mime/grammar.go
+++ b/libgo/go/mime/grammar.go
@@ -22,6 +22,15 @@ func IsTokenChar(rune int) bool {
return rune > 0x20 && rune < 0x7f && !isTSpecial(rune)
}
+// IsToken returns true if s is a 'token' as as defined by RFC 1521
+// and RFC 2045.
+func IsToken(s string) bool {
+ if s == "" {
+ return false
+ }
+ return strings.IndexFunc(s, isNotTokenChar) < 0
+}
+
// IsQText returns true if rune is in 'qtext' as defined by RFC 822.
func IsQText(rune int) bool {
// CHAR = <any ASCII character> ; ( 0-177, 0.-127.)
diff --git a/libgo/go/mime/mediatype.go b/libgo/go/mime/mediatype.go
index 40c735c5baa..b0d39338170 100644
--- a/libgo/go/mime/mediatype.go
+++ b/libgo/go/mime/mediatype.go
@@ -12,40 +12,89 @@ import (
"unicode"
)
-func validMediaTypeOrDisposition(s string) bool {
+// FormatMediaType serializes type t, subtype sub and the paramaters
+// param as a media type conform RFC 2045 and RFC 2616.
+// The type, subtype, and parameter names are written in lower-case.
+// When any of the arguments result in a standard violation then
+// FormatMediaType returns the empty string.
+func FormatMediaType(t, sub string, param map[string]string) string {
+ if !(IsToken(t) && IsToken(sub)) {
+ return ""
+ }
+ var b bytes.Buffer
+ b.WriteString(strings.ToLower(t))
+ b.WriteByte('/')
+ b.WriteString(strings.ToLower(sub))
+
+ for attribute, value := range param {
+ b.WriteByte(';')
+ b.WriteByte(' ')
+ if !IsToken(attribute) {
+ return ""
+ }
+ b.WriteString(strings.ToLower(attribute))
+ b.WriteByte('=')
+ if IsToken(value) {
+ b.WriteString(value)
+ continue
+ }
+
+ b.WriteByte('"')
+ offset := 0
+ for index, character := range value {
+ if character == '"' || character == '\r' {
+ b.WriteString(value[offset:index])
+ offset = index
+ b.WriteByte('\\')
+ }
+ if character&0x80 != 0 {
+ return ""
+ }
+ }
+ b.WriteString(value[offset:])
+ b.WriteByte('"')
+ }
+ return b.String()
+}
+
+func checkMediaTypeDisposition(s string) os.Error {
typ, rest := consumeToken(s)
if typ == "" {
- return false
+ return os.NewError("mime: no media type")
}
if rest == "" {
- return true
+ return nil
}
if !strings.HasPrefix(rest, "/") {
- return false
+ return os.NewError("mime: expected slash after first token")
}
subtype, rest := consumeToken(rest[1:])
if subtype == "" {
- return false
+ return os.NewError("mime: expected token after slash")
}
- return rest == ""
+ if rest != "" {
+ return os.NewError("mime: unexpected content after media subtype")
+ }
+ return nil
}
// ParseMediaType parses a media type value and any optional
// parameters, per RFC 1521. Media types are the values in
// Content-Type and Content-Disposition headers (RFC 2183).
// On success, ParseMediaType returns the media type converted
-// to lowercase and trimmed of white space. The returned params
-// is always a non-nil map. Params maps from the lowercase
+// to lowercase and trimmed of white space and a non-nil map.
+// The returned map, params, maps from the lowercase
// attribute to the attribute value with its case preserved.
-// On error, it returns an empty string and a nil params.
-func ParseMediaType(v string) (mediatype string, params map[string]string) {
+func ParseMediaType(v string) (mediatype string, params map[string]string, err os.Error) {
i := strings.Index(v, ";")
if i == -1 {
i = len(v)
}
mediatype = strings.TrimSpace(strings.ToLower(v[0:i]))
- if !validMediaTypeOrDisposition(mediatype) {
- return "", nil
+
+ err = checkMediaTypeDisposition(mediatype)
+ if err != nil {
+ return
}
params = make(map[string]string)
@@ -69,7 +118,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string) {
return
}
// Parse error.
- return "", nil
+ return "", nil, os.NewError("mime: invalid media parameter")
}
pmap := params
@@ -86,7 +135,7 @@ func ParseMediaType(v string) (mediatype string, params map[string]string) {
}
if _, exists := pmap[key]; exists {
// Duplicate parameter name is bogus.
- return "", nil
+ return "", nil, os.NewError("mime: duplicate parameter name")
}
pmap[key] = value
v = rest
diff --git a/libgo/go/mime/mediatype_test.go b/libgo/go/mime/mediatype_test.go
index 93264bd09a1..884573e0bbb 100644
--- a/libgo/go/mime/mediatype_test.go
+++ b/libgo/go/mime/mediatype_test.go
@@ -219,7 +219,14 @@ func TestParseMediaType(t *testing.T) {
m("firstname", "БрÑд", "lastname", "Фицпатрик")},
}
for _, test := range tests {
- mt, params := ParseMediaType(test.in)
+ mt, params, err := ParseMediaType(test.in)
+ if err != nil {
+ if test.t != "" {
+ t.Errorf("for input %q, unexpected error: %v", test.in, err)
+ continue
+ }
+ continue
+ }
if g, e := mt, test.t; g != e {
t.Errorf("for input %q, expected type %q, got %q",
test.in, e, g)
@@ -238,11 +245,11 @@ func TestParseMediaType(t *testing.T) {
}
func TestParseMediaTypeBogus(t *testing.T) {
- mt, params := ParseMediaType("bogus ;=========")
- if mt != "" {
- t.Error("expected empty type")
+ mt, params, err := ParseMediaType("bogus ;=========")
+ if err == nil {
+ t.Fatalf("expected an error parsing invalid media type; got type %q, params %#v", mt, params)
}
- if params != nil {
- t.Error("expected nil params")
+ if err.String() != "mime: invalid media parameter" {
+ t.Errorf("expected invalid media parameter; got error %q", err)
}
}
diff --git a/libgo/go/mime/mime_test.go b/libgo/go/mime/mime_test.go
deleted file mode 100644
index 17e610443e7..00000000000
--- a/libgo/go/mime/mime_test.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Tests for type.go
-
-package mime
-
-import "testing"
-
-var typeTests = map[string]string{
- ".t1": "application/test",
- ".t2": "text/test; charset=utf-8",
- ".png": "image/png",
-}
-
-func TestType(t *testing.T) {
- typeFiles = []string{"test.types"}
-
- for ext, want := range typeTests {
- val := TypeByExtension(ext)
- if val != want {
- t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
- }
-
- }
-}
diff --git a/libgo/go/mime/multipart/formdata.go b/libgo/go/mime/multipart/formdata.go
index 91404d6f41c..d114bfa9b43 100644
--- a/libgo/go/mime/multipart/formdata.go
+++ b/libgo/go/mime/multipart/formdata.go
@@ -47,7 +47,7 @@ func (r *Reader) ReadForm(maxMemory int64) (f *Form, err os.Error) {
if filename == "" {
// value, store as string in memory
- n, err := io.Copyn(&b, p, maxValueBytes)
+ n, err := io.CopyN(&b, p, maxValueBytes)
if err != nil && err != os.EOF {
return nil, err
}
@@ -64,7 +64,7 @@ func (r *Reader) ReadForm(maxMemory int64) (f *Form, err os.Error) {
Filename: filename,
Header: p.Header,
}
- n, err := io.Copyn(&b, p, maxMemory+1)
+ n, err := io.CopyN(&b, p, maxMemory+1)
if err != nil && err != os.EOF {
return nil, err
}
diff --git a/libgo/go/mime/multipart/multipart.go b/libgo/go/mime/multipart/multipart.go
index 2533bd337dc..d36e9e91b8f 100644
--- a/libgo/go/mime/multipart/multipart.go
+++ b/libgo/go/mime/multipart/multipart.go
@@ -69,8 +69,9 @@ func (p *Part) FileName() string {
func (p *Part) parseContentDisposition() {
v := p.Header.Get("Content-Disposition")
- p.disposition, p.dispositionParams = mime.ParseMediaType(v)
- if p.dispositionParams == nil {
+ var err os.Error
+ p.disposition, p.dispositionParams, err = mime.ParseMediaType(v)
+ if err != nil {
p.dispositionParams = emptyParams
}
}
@@ -145,7 +146,7 @@ func (bp *Part) Read(p []byte) (n int, err os.Error) {
return 0, io.ErrUnexpectedEOF
}
if nCopy > 0 {
- if _, err := io.Copyn(bp.buffer, bp.mr.bufReader, int64(nCopy)); err != nil {
+ if _, err := io.CopyN(bp.buffer, bp.mr.bufReader, int64(nCopy)); err != nil {
return 0, err
}
}
diff --git a/libgo/go/mime/multipart/writer.go b/libgo/go/mime/multipart/writer.go
index 97a8897b299..1bff02fa2a0 100644
--- a/libgo/go/mime/multipart/writer.go
+++ b/libgo/go/mime/multipart/writer.go
@@ -85,10 +85,10 @@ func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, os.Error) {
return p, nil
}
+var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
+
func escapeQuotes(s string) string {
- s = strings.Replace(s, "\\", "\\\\", -1)
- s = strings.Replace(s, "\"", "\\\"", -1)
- return s
+ return quoteEscaper.Replace(s)
}
// CreateFormFile is a convenience wrapper around CreatePart. It creates
diff --git a/libgo/go/mime/type.go b/libgo/go/mime/type.go
index 8ecfe9a37b1..39bf40ee89a 100644
--- a/libgo/go/mime/type.go
+++ b/libgo/go/mime/type.go
@@ -7,6 +7,7 @@ package mime
import (
"bufio"
+ "fmt"
"os"
"strings"
"sync"
@@ -49,15 +50,12 @@ func loadMimeFile(filename string) {
if len(fields) <= 1 || fields[0][0] == '#' {
continue
}
- typename := fields[0]
- if strings.HasPrefix(typename, "text/") {
- typename += "; charset=utf-8"
- }
+ mimeType := fields[0]
for _, ext := range fields[1:] {
if ext[0] == '#' {
break
}
- mimeTypes["."+ext] = typename
+ setExtensionType("."+ext, mimeType)
}
}
}
@@ -81,6 +79,8 @@ var once sync.Once
// /etc/mime.types
// /etc/apache2/mime.types
// /etc/apache/mime.types
+//
+// Text types have the charset parameter set to "utf-8" by default.
func TypeByExtension(ext string) string {
once.Do(initMime)
mimeLock.RLock()
@@ -93,12 +93,31 @@ func TypeByExtension(ext string) string {
// the extension ext to typ. The extension should begin with
// a leading dot, as in ".html".
func AddExtensionType(ext, typ string) os.Error {
+ if ext == "" || ext[0] != '.' {
+ return fmt.Errorf(`mime: extension "%s" misses dot`, ext)
+ }
once.Do(initMime)
- if len(ext) < 1 || ext[0] != '.' {
- return os.EINVAL
+ return setExtensionType(ext, typ)
+}
+
+func setExtensionType(extension, mimeType string) os.Error {
+ full, param, err := ParseMediaType(mimeType)
+ if err != nil {
+ return err
+ }
+ if split := strings.Index(full, "/"); split < 0 {
+ return fmt.Errorf(`mime: malformed MIME type "%s"`, mimeType)
+ } else {
+ main := full[:split]
+ sub := full[split+1:]
+ if main == "text" && param["charset"] == "" {
+ param["charset"] = "utf-8"
+ }
+ mimeType = FormatMediaType(main, sub, param)
}
+
mimeLock.Lock()
- mimeTypes[ext] = typ
+ mimeTypes[extension] = mimeType
mimeLock.Unlock()
return nil
}
diff --git a/libgo/go/mime/type_test.go b/libgo/go/mime/type_test.go
new file mode 100644
index 00000000000..976f8534309
--- /dev/null
+++ b/libgo/go/mime/type_test.go
@@ -0,0 +1,35 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mime
+
+import "testing"
+
+var typeTests = map[string]string{
+ ".t1": "application/test",
+ ".t2": "text/test; charset=utf-8",
+ ".png": "image/png",
+}
+
+func TestTypeByExtension(t *testing.T) {
+ typeFiles = []string{"test.types"}
+
+ for ext, want := range typeTests {
+ val := TypeByExtension(ext)
+ if val != want {
+ t.Errorf("TypeByExtension(%q) = %q, want %q", ext, val, want)
+ }
+
+ }
+}
+
+func TestCustomExtension(t *testing.T) {
+ custom := "text/xml; charset=iso-8859-1"
+ if error := AddExtensionType(".xml", custom); error != nil {
+ t.Fatalf("error %s for AddExtension(%s)", error, custom)
+ }
+ if registered := TypeByExtension(".xml"); registered != custom {
+ t.Fatalf("registered %s instead of %s", registered, custom)
+ }
+}
diff --git a/libgo/go/net/cgo_bsd.go b/libgo/go/net/cgo_bsd.go
index 3951d847416..b8c6ef974e4 100644
--- a/libgo/go/net/cgo_bsd.go
+++ b/libgo/go/net/cgo_bsd.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd
+
package net
/*
diff --git a/libgo/go/net/cgo_stub.go b/libgo/go/net/cgo_stub.go
index c6277cb657c..565cbe7fece 100644
--- a/libgo/go/net/cgo_stub.go
+++ b/libgo/go/net/cgo_stub.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build openbsd
+
// Stub cgo routines for systems that do not use cgo to do network lookups.
package net
diff --git a/libgo/go/net/cgo_unix.go b/libgo/go/net/cgo_unix.go
index b8090181293..bfb3dfddff9 100644
--- a/libgo/go/net/cgo_unix.go
+++ b/libgo/go/net/cgo_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux
+
package net
/*
@@ -24,6 +26,17 @@ func libc_getaddrinfo(node *byte, service *byte, hints *syscall.Addrinfo, res **
func libc_freeaddrinfo(res *syscall.Addrinfo) __asm__ ("freeaddrinfo")
func libc_gai_strerror(errcode int) *byte __asm__ ("gai_strerror")
+// bytePtrToString takes a NUL-terminated array of bytes and convert
+// it to a Go string.
+func bytePtrToString(p *byte) string {
+ a := (*[10000]byte)(unsafe.Pointer(p))
+ i := 0
+ for a[i] != 0 {
+ i++
+ }
+ return string(a[:i])
+}
+
func cgoLookupHost(name string) (addrs []string, err os.Error, completed bool) {
ip, err, completed := cgoLookupIP(name)
for _, p := range ip {
@@ -99,13 +112,13 @@ func cgoLookupIPCNAME(name string) (addrs []IP, cname string, err os.Error, comp
} else if gerrno == syscall.EAI_SYSTEM {
str = syscall.Errstr(syscall.GetErrno())
} else {
- str = syscall.BytePtrToString(libc_gai_strerror(gerrno))
+ str = bytePtrToString(libc_gai_strerror(gerrno))
}
return nil, "", &DNSError{Error: str, Name: name}, true
}
defer libc_freeaddrinfo(res)
if res != nil {
- cname = syscall.BytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
+ cname = bytePtrToString((*byte)(unsafe.Pointer(res.Ai_canonname)))
if cname == "" {
cname = name
}
diff --git a/libgo/go/net/dial.go b/libgo/go/net/dial.go
index 10c67dcc40a..85d54b3703c 100644
--- a/libgo/go/net/dial.go
+++ b/libgo/go/net/dial.go
@@ -59,10 +59,10 @@ func Dial(net, addr string) (c Conn, err os.Error) {
case *IPAddr:
c, err = DialIP(net, nil, ra)
default:
- err = UnknownNetworkError(net)
+ err = &OpError{"dial", net + " " + addr, nil, UnknownNetworkError(net)}
}
if err != nil {
- return nil, &OpError{"dial", net + " " + addr, nil, err}
+ return nil, err
}
return
}
diff --git a/libgo/go/net/dnsclient_unix.go b/libgo/go/net/dnsclient_unix.go
index f407b177830..eb7db5e2707 100644
--- a/libgo/go/net/dnsclient_unix.go
+++ b/libgo/go/net/dnsclient_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
// DNS client: see RFC 1035.
// Has to be linked into package net for Dial.
@@ -113,7 +115,7 @@ func convertRR_A(records []dnsRR) []IP {
func convertRR_AAAA(records []dnsRR) []IP {
addrs := make([]IP, len(records))
for i, rr := range records {
- a := make(IP, 16)
+ a := make(IP, IPv6len)
copy(a, rr.(*dnsRR_AAAA).AAAA[:])
addrs[i] = a
}
@@ -213,6 +215,18 @@ func goLookupHost(name string) (addrs []string, err os.Error) {
// depending on our lookup code, so that Go and C get the same
// answers.
func goLookupIP(name string) (addrs []IP, err os.Error) {
+ // Use entries from /etc/hosts if possible.
+ haddrs := lookupStaticHost(name)
+ if len(haddrs) > 0 {
+ for _, haddr := range haddrs {
+ if ip := ParseIP(haddr); ip != nil {
+ addrs = append(addrs, ip)
+ }
+ }
+ if len(addrs) > 0 {
+ return
+ }
+ }
onceLoadConfig.Do(loadConfig)
if dnserr != nil || cfg == nil {
err = dnserr
diff --git a/libgo/go/net/dnsconfig.go b/libgo/go/net/dnsconfig.go
index 54e334342ad..afc05991773 100644
--- a/libgo/go/net/dnsconfig.go
+++ b/libgo/go/net/dnsconfig.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
// Read system DNS config from /etc/resolv.conf
package net
diff --git a/libgo/go/net/fd.go b/libgo/go/net/fd.go
index 707dccaa421..80d40af7662 100644
--- a/libgo/go/net/fd.go
+++ b/libgo/go/net/fd.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package net
import (
@@ -150,7 +152,7 @@ func (s *pollServer) LookupFD(fd int, mode int) *netFD {
if !ok {
return nil
}
- s.pending[key] = nil, false
+ delete(s.pending, key)
return netfd
}
@@ -193,7 +195,7 @@ func (s *pollServer) CheckDeadlines() {
}
if t > 0 {
if t <= now {
- s.pending[key] = nil, false
+ delete(s.pending, key)
if mode == 'r' {
s.poll.DelFD(fd.sysfd, mode)
fd.rdeadline = -1
@@ -356,6 +358,25 @@ func (fd *netFD) Close() os.Error {
return nil
}
+func (fd *netFD) shutdown(how int) os.Error {
+ if fd == nil || fd.sysfile == nil {
+ return os.EINVAL
+ }
+ errno := syscall.Shutdown(fd.sysfd, how)
+ if errno != 0 {
+ return &OpError{"shutdown", fd.net, fd.laddr, os.Errno(errno)}
+ }
+ return nil
+}
+
+func (fd *netFD) CloseRead() os.Error {
+ return fd.shutdown(syscall.SHUT_RD)
+}
+
+func (fd *netFD) CloseWrite() os.Error {
+ return fd.shutdown(syscall.SHUT_WR)
+}
+
func (fd *netFD) Read(p []byte) (n int, err os.Error) {
if fd == nil {
return 0, os.EINVAL
diff --git a/libgo/go/net/fd_linux.go b/libgo/go/net/fd_linux.go
index 70fc344b2a0..c860c842af7 100644
--- a/libgo/go/net/fd_linux.go
+++ b/libgo/go/net/fd_linux.go
@@ -105,7 +105,7 @@ func (p *pollster) StopWaiting(fd int, bits uint) {
if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n")
}
- p.events[fd] = 0, false
+ delete(p.events, fd)
}
}
diff --git a/libgo/go/net/fd_select.go b/libgo/go/net/fd_select.go
index e9c68ab2ccc..21fd8010fa6 100644
--- a/libgo/go/net/fd_select.go
+++ b/libgo/go/net/fd_select.go
@@ -12,20 +12,20 @@ import (
)
type pollster struct {
- readFds, writeFds, repeatFds *syscall.FdSet_t
+ readFds, writeFds, repeatFds *syscall.FdSet
maxFd int
- readyReadFds, readyWriteFds *syscall.FdSet_t
+ readyReadFds, readyWriteFds *syscall.FdSet
nReady int
lastFd int
}
func newpollster() (p *pollster, err os.Error) {
p = new(pollster)
- p.readFds = new(syscall.FdSet_t)
- p.writeFds = new(syscall.FdSet_t)
- p.repeatFds = new(syscall.FdSet_t)
- p.readyReadFds = new(syscall.FdSet_t)
- p.readyWriteFds = new(syscall.FdSet_t)
+ p.readFds = new(syscall.FdSet)
+ p.writeFds = new(syscall.FdSet)
+ p.repeatFds = new(syscall.FdSet)
+ p.readyReadFds = new(syscall.FdSet)
+ p.readyWriteFds = new(syscall.FdSet)
p.maxFd = -1
p.nReady = 0
p.lastFd = 0
@@ -86,9 +86,9 @@ func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err os.E
}
var n, e int
- var tmpReadFds, tmpWriteFds syscall.FdSet_t
+ var tmpReadFds, tmpWriteFds syscall.FdSet
for {
- // Temporary syscall.FdSet_ts into which the values are copied
+ // Temporary syscall.FdSet's into which the values are copied
// because select mutates the values.
tmpReadFds = *p.readFds
tmpWriteFds = *p.writeFds
diff --git a/libgo/go/net/fd_windows.go b/libgo/go/net/fd_windows.go
index 3757e143dca..8e8b3b746d4 100644
--- a/libgo/go/net/fd_windows.go
+++ b/libgo/go/net/fd_windows.go
@@ -23,7 +23,7 @@ var initErr os.Error
func init() {
var d syscall.WSAData
- e := syscall.WSAStartup(uint32(0x101), &d)
+ e := syscall.WSAStartup(uint32(0x202), &d)
if e != 0 {
initErr = os.NewSyscallError("WSAStartup", e)
}
@@ -52,15 +52,27 @@ type anOp struct {
// of the struct, as our code rely on it.
o syscall.Overlapped
- resultc chan ioResult // io completion results
- errnoc chan int // io submit / cancel operation errors
+ resultc chan ioResult
+ errnoc chan int
fd *netFD
}
-func (o *anOp) Init(fd *netFD) {
+func (o *anOp) Init(fd *netFD, mode int) {
o.fd = fd
- o.resultc = make(chan ioResult, 1)
- o.errnoc = make(chan int)
+ var i int
+ if mode == 'r' {
+ i = 0
+ } else {
+ i = 1
+ }
+ if fd.resultc[i] == nil {
+ fd.resultc[i] = make(chan ioResult, 1)
+ }
+ o.resultc = fd.resultc[i]
+ if fd.errnoc[i] == nil {
+ fd.errnoc[i] = make(chan int)
+ }
+ o.errnoc = fd.errnoc[i]
}
func (o *anOp) Op() *anOp {
@@ -74,8 +86,8 @@ type bufOp struct {
buf syscall.WSABuf
}
-func (o *bufOp) Init(fd *netFD, buf []byte) {
- o.anOp.Init(fd)
+func (o *bufOp) Init(fd *netFD, buf []byte, mode int) {
+ o.anOp.Init(fd, mode)
o.buf.Len = uint32(len(buf))
if len(buf) == 0 {
o.buf.Buf = nil
@@ -208,12 +220,14 @@ type netFD struct {
closing bool
// immutable until Close
- sysfd syscall.Handle
- family int
- proto int
- net string
- laddr Addr
- raddr Addr
+ sysfd syscall.Handle
+ family int
+ proto int
+ net string
+ laddr Addr
+ raddr Addr
+ resultc [2]chan ioResult // read/write completion results
+ errnoc [2]chan int // read/write submit or cancel operation errors
// owned by client
rdeadline_delta int64
@@ -298,6 +312,25 @@ func (fd *netFD) Close() os.Error {
return nil
}
+func (fd *netFD) shutdown(how int) os.Error {
+ if fd == nil || fd.sysfd == syscall.InvalidHandle {
+ return os.EINVAL
+ }
+ errno := syscall.Shutdown(fd.sysfd, how)
+ if errno != 0 {
+ return &OpError{"shutdown", fd.net, fd.laddr, os.Errno(errno)}
+ }
+ return nil
+}
+
+func (fd *netFD) CloseRead() os.Error {
+ return fd.shutdown(syscall.SHUT_RD)
+}
+
+func (fd *netFD) CloseWrite() os.Error {
+ return fd.shutdown(syscall.SHUT_WR)
+}
+
// Read from network.
type readOp struct {
@@ -325,7 +358,7 @@ func (fd *netFD) Read(buf []byte) (n int, err os.Error) {
return 0, os.EINVAL
}
var o readOp
- o.Init(fd, buf)
+ o.Init(fd, buf, 'r')
n, err = iosrv.ExecIO(&o, fd.rdeadline_delta)
if err == nil && n == 0 {
err = os.EOF
@@ -365,7 +398,7 @@ func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err os.Error)
return 0, nil, os.EINVAL
}
var o readFromOp
- o.Init(fd, buf)
+ o.Init(fd, buf, 'r')
o.rsan = int32(unsafe.Sizeof(o.rsa))
n, err = iosrv.ExecIO(&o, fd.rdeadline_delta)
if err != nil {
@@ -402,7 +435,7 @@ func (fd *netFD) Write(buf []byte) (n int, err os.Error) {
return 0, os.EINVAL
}
var o writeOp
- o.Init(fd, buf)
+ o.Init(fd, buf, 'w')
return iosrv.ExecIO(&o, fd.wdeadline_delta)
}
@@ -437,7 +470,7 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err os.Error)
return 0, os.EINVAL
}
var o writeToOp
- o.Init(fd, buf)
+ o.Init(fd, buf, 'w')
o.sa = sa
return iosrv.ExecIO(&o, fd.wdeadline_delta)
}
@@ -487,7 +520,7 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.
// Submit accept request.
var o acceptOp
- o.Init(fd)
+ o.Init(fd, 'r')
o.newsock = s
_, err = iosrv.ExecIO(&o, 0)
if err != nil {
diff --git a/libgo/go/net/file.go b/libgo/go/net/file.go
index 0e411a192f2..ed2559d8c30 100644
--- a/libgo/go/net/file.go
+++ b/libgo/go/net/file.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package net
import (
@@ -20,6 +22,7 @@ func newFileFD(f *os.File) (nfd *netFD, err os.Error) {
return nil, os.NewSyscallError("getsockopt", errno)
}
+ family := syscall.AF_UNSPEC
toAddr := sockaddrToTCP
sa, _ := syscall.Getsockname(fd)
switch sa.(type) {
@@ -27,18 +30,21 @@ func newFileFD(f *os.File) (nfd *netFD, err os.Error) {
closesocket(fd)
return nil, os.EINVAL
case *syscall.SockaddrInet4:
+ family = syscall.AF_INET
if proto == syscall.SOCK_DGRAM {
toAddr = sockaddrToUDP
} else if proto == syscall.SOCK_RAW {
toAddr = sockaddrToIP
}
case *syscall.SockaddrInet6:
+ family = syscall.AF_INET6
if proto == syscall.SOCK_DGRAM {
toAddr = sockaddrToUDP
} else if proto == syscall.SOCK_RAW {
toAddr = sockaddrToIP
}
case *syscall.SockaddrUnix:
+ family = syscall.AF_UNIX
toAddr = sockaddrToUnix
if proto == syscall.SOCK_DGRAM {
toAddr = sockaddrToUnixgram
@@ -50,7 +56,7 @@ func newFileFD(f *os.File) (nfd *netFD, err os.Error) {
sa, _ = syscall.Getpeername(fd)
raddr := toAddr(sa)
- if nfd, err = newFD(fd, 0, proto, laddr.Network()); err != nil {
+ if nfd, err = newFD(fd, family, proto, laddr.Network()); err != nil {
return nil, err
}
nfd.setAddr(laddr, raddr)
diff --git a/libgo/go/net/file_test.go b/libgo/go/net/file_test.go
index 9a8c2dcbc4c..0fa6740769b 100644
--- a/libgo/go/net/file_test.go
+++ b/libgo/go/net/file_test.go
@@ -73,7 +73,7 @@ func TestFileListener(t *testing.T) {
}
}
-func testFilePacketConn(t *testing.T, pcf packetConnFile) {
+func testFilePacketConn(t *testing.T, pcf packetConnFile, listen bool) {
f, err := pcf.File()
if err != nil {
t.Fatalf("File failed: %v", err)
@@ -85,6 +85,11 @@ func testFilePacketConn(t *testing.T, pcf packetConnFile) {
if !reflect.DeepEqual(pcf.LocalAddr(), c.LocalAddr()) {
t.Fatalf("LocalAddrs not equal: %#v != %#v", pcf.LocalAddr(), c.LocalAddr())
}
+ if listen {
+ if _, err := c.WriteTo([]byte{}, c.LocalAddr()); err != nil {
+ t.Fatalf("WriteTo failed: %v", err)
+ }
+ }
if err := c.Close(); err != nil {
t.Fatalf("Close failed: %v", err)
}
@@ -98,7 +103,7 @@ func testFilePacketConnListen(t *testing.T, net, laddr string) {
if err != nil {
t.Fatalf("Listen failed: %v", err)
}
- testFilePacketConn(t, l.(packetConnFile))
+ testFilePacketConn(t, l.(packetConnFile), true)
if err := l.Close(); err != nil {
t.Fatalf("Close failed: %v", err)
}
@@ -109,7 +114,7 @@ func testFilePacketConnDial(t *testing.T, net, raddr string) {
if err != nil {
t.Fatalf("Dial failed: %v", err)
}
- testFilePacketConn(t, c.(packetConnFile))
+ testFilePacketConn(t, c.(packetConnFile), false)
if err := c.Close(); err != nil {
t.Fatalf("Close failed: %v", err)
}
diff --git a/libgo/go/net/interface.go b/libgo/go/net/interface.go
index 8a14cb23202..2696b7f4c58 100644
--- a/libgo/go/net/interface.go
+++ b/libgo/go/net/interface.go
@@ -26,6 +26,63 @@ func (a HardwareAddr) String() string {
return buf.String()
}
+// ParseMAC parses s as an IEEE 802 MAC-48, EUI-48, or EUI-64 using one of the
+// following formats:
+// 01:23:45:67:89:ab
+// 01:23:45:67:89:ab:cd:ef
+// 01-23-45-67-89-ab
+// 01-23-45-67-89-ab-cd-ef
+// 0123.4567.89ab
+// 0123.4567.89ab.cdef
+func ParseMAC(s string) (hw HardwareAddr, err os.Error) {
+ if len(s) < 14 {
+ goto error
+ }
+
+ if s[2] == ':' || s[2] == '-' {
+ if (len(s)+1)%3 != 0 {
+ goto error
+ }
+ n := (len(s) + 1) / 3
+ if n != 6 && n != 8 {
+ goto error
+ }
+ hw = make(HardwareAddr, n)
+ for x, i := 0, 0; i < n; i++ {
+ var ok bool
+ if hw[i], ok = xtoi2(s[x:], s[2]); !ok {
+ goto error
+ }
+ x += 3
+ }
+ } else if s[4] == '.' {
+ if (len(s)+1)%5 != 0 {
+ goto error
+ }
+ n := 2 * (len(s) + 1) / 5
+ if n != 6 && n != 8 {
+ goto error
+ }
+ hw = make(HardwareAddr, n)
+ for x, i := 0, 0; i < n; i += 2 {
+ var ok bool
+ if hw[i], ok = xtoi2(s[x:x+2], 0); !ok {
+ goto error
+ }
+ if hw[i+1], ok = xtoi2(s[x+2:], s[4]); !ok {
+ goto error
+ }
+ x += 5
+ }
+ } else {
+ goto error
+ }
+ return hw, nil
+
+error:
+ return nil, os.NewError("invalid MAC address: " + s)
+}
+
// Interface represents a mapping between network interface name
// and index. It also represents network interface facility
// information.
diff --git a/libgo/go/net/interface_bsd.go b/libgo/go/net/interface_bsd.go
index 2675f94b973..54fa5ddeb69 100644
--- a/libgo/go/net/interface_bsd.go
+++ b/libgo/go/net/interface_bsd.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd openbsd
+
// Network interface identification for BSD variants
package net
@@ -148,7 +150,6 @@ func newAddr(m *syscall.InterfaceAddrMessage) ([]Addr, os.Error) {
}
for _, s := range sas {
-
switch v := s.(type) {
case *syscall.SockaddrInet4:
ifa := &IPAddr{IP: IPv4(v.Addr[0], v.Addr[1], v.Addr[2], v.Addr[3])}
diff --git a/libgo/go/net/interface_linux.go b/libgo/go/net/interface_linux.go
index 3d2a0bb9f8a..36ae04ffa71 100644
--- a/libgo/go/net/interface_linux.go
+++ b/libgo/go/net/interface_linux.go
@@ -103,42 +103,29 @@ func linkFlags(rawFlags uint32) Flags {
// for a specific interface.
func interfaceAddrTable(ifindex int) ([]Addr, os.Error) {
var (
- tab []byte
- e int
- err os.Error
- ifat4 []Addr
- ifat6 []Addr
- msgs4 []syscall.NetlinkMessage
- msgs6 []syscall.NetlinkMessage
+ tab []byte
+ e int
+ err os.Error
+ ifat []Addr
+ msgs []syscall.NetlinkMessage
)
- tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET)
+ tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_UNSPEC)
if e != 0 {
return nil, os.NewSyscallError("netlink rib", e)
}
- msgs4, e = syscall.ParseNetlinkMessage(tab)
- if e != 0 {
- return nil, os.NewSyscallError("netlink message", e)
- }
- ifat4, err = addrTable(msgs4, ifindex)
- if err != nil {
- return nil, err
- }
- tab, e = syscall.NetlinkRIB(syscall.RTM_GETADDR, syscall.AF_INET6)
- if e != 0 {
- return nil, os.NewSyscallError("netlink rib", e)
- }
- msgs6, e = syscall.ParseNetlinkMessage(tab)
+ msgs, e = syscall.ParseNetlinkMessage(tab)
if e != 0 {
return nil, os.NewSyscallError("netlink message", e)
}
- ifat6, err = addrTable(msgs6, ifindex)
+
+ ifat, err = addrTable(msgs, ifindex)
if err != nil {
return nil, err
}
- return append(ifat4, ifat6...), nil
+ return ifat, nil
}
func addrTable(msgs []syscall.NetlinkMessage, ifindex int) ([]Addr, os.Error) {
diff --git a/libgo/go/net/interface_stub.go b/libgo/go/net/interface_stub.go
index 950de6c5926..282b38b5e49 100644
--- a/libgo/go/net/interface_stub.go
+++ b/libgo/go/net/interface_stub.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build plan9
+
// Network interface identification
package net
diff --git a/libgo/go/net/interface_test.go b/libgo/go/net/interface_test.go
index 0e4089abf8a..c918f247f96 100644
--- a/libgo/go/net/interface_test.go
+++ b/libgo/go/net/interface_test.go
@@ -6,6 +6,9 @@ package net
import (
"bytes"
+ "os"
+ "reflect"
+ "strings"
"testing"
)
@@ -71,3 +74,46 @@ func TestInterfaceAddrs(t *testing.T) {
t.Logf("interface address %q\n", ifa.String())
}
}
+
+var mactests = []struct {
+ in string
+ out HardwareAddr
+ err string
+}{
+ {"01:23:45:67:89:AB", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab}, ""},
+ {"01-23-45-67-89-AB", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab}, ""},
+ {"0123.4567.89AB", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab}, ""},
+ {"ab:cd:ef:AB:CD:EF", HardwareAddr{0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef}, ""},
+ {"01.02.03.04.05.06", nil, "invalid MAC address"},
+ {"01:02:03:04:05:06:", nil, "invalid MAC address"},
+ {"x1:02:03:04:05:06", nil, "invalid MAC address"},
+ {"01002:03:04:05:06", nil, "invalid MAC address"},
+ {"01:02003:04:05:06", nil, "invalid MAC address"},
+ {"01:02:03004:05:06", nil, "invalid MAC address"},
+ {"01:02:03:04005:06", nil, "invalid MAC address"},
+ {"01:02:03:04:05006", nil, "invalid MAC address"},
+ {"01-02:03:04:05:06", nil, "invalid MAC address"},
+ {"01:02-03-04-05-06", nil, "invalid MAC address"},
+ {"0123:4567:89AF", nil, "invalid MAC address"},
+ {"0123-4567-89AF", nil, "invalid MAC address"},
+ {"01:23:45:67:89:AB:CD:EF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
+ {"01-23-45-67-89-AB-CD-EF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
+ {"0123.4567.89AB.CDEF", HardwareAddr{1, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef}, ""},
+}
+
+func match(err os.Error, s string) bool {
+ if s == "" {
+ return err == nil
+ }
+ return err != nil && strings.Contains(err.String(), s)
+}
+
+func TestParseMAC(t *testing.T) {
+ for _, tt := range mactests {
+ out, err := ParseMAC(tt.in)
+ if !reflect.DeepEqual(out, tt.out) || !match(err, tt.err) {
+ t.Errorf("ParseMAC(%q) = %v, %v, want %v, %v", tt.in, out, err, tt.out,
+ tt.err)
+ }
+ }
+}
diff --git a/libgo/go/net/ip.go b/libgo/go/net/ip.go
index b0e2c42053f..61dc3be909c 100644
--- a/libgo/go/net/ip.go
+++ b/libgo/go/net/ip.go
@@ -21,11 +21,8 @@ const (
)
// An IP is a single IP address, an array of bytes.
-// Functions in this package accept either 4-byte (IP v4)
-// or 16-byte (IP v6) arrays as input. Unless otherwise
-// specified, functions in this package always return
-// IP addresses in 16-byte form using the canonical
-// embedding.
+// Functions in this package accept either 4-byte (IPv4)
+// or 16-byte (IPv6) arrays as input.
//
// Note that in this documentation, referring to an
// IP address as an IPv4 address or an IPv6 address
@@ -37,6 +34,12 @@ type IP []byte
// An IP mask is an IP address.
type IPMask []byte
+// An IPNet represents an IP network.
+type IPNet struct {
+ IP IP // network number
+ Mask IPMask // network mask
+}
+
// IPv4 returns the IP address (in 16-byte form) of the
// IPv4 address a.b.c.d.
func IPv4(a, b, c, d byte) IP {
@@ -51,20 +54,42 @@ func IPv4(a, b, c, d byte) IP {
var v4InV6Prefix = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}
-// IPv4Mask returns the IP mask (in 16-byte form) of the
+// IPv4Mask returns the IP mask (in 4-byte form) of the
// IPv4 mask a.b.c.d.
func IPv4Mask(a, b, c, d byte) IPMask {
- p := make(IPMask, IPv6len)
- for i := 0; i < 12; i++ {
- p[i] = 0xff
- }
- p[12] = a
- p[13] = b
- p[14] = c
- p[15] = d
+ p := make(IPMask, IPv4len)
+ p[0] = a
+ p[1] = b
+ p[2] = c
+ p[3] = d
return p
}
+// CIDRMask returns an IPMask consisting of `ones' 1 bits
+// followed by 0s up to a total length of `bits' bits.
+// For a mask of this form, CIDRMask is the inverse of IPMask.Size.
+func CIDRMask(ones, bits int) IPMask {
+ if bits != 8*IPv4len && bits != 8*IPv6len {
+ return nil
+ }
+ if ones < 0 || ones > bits {
+ return nil
+ }
+ l := bits / 8
+ m := make(IPMask, l)
+ n := uint(ones)
+ for i := 0; i < l; i++ {
+ if n >= 8 {
+ m[i] = 0xff
+ n -= 8
+ continue
+ }
+ m[i] = ^byte(0xff >> n)
+ n = 0
+ }
+ return m
+}
+
// Well-known IPv4 addresses
var (
IPv4bcast = IPv4(255, 255, 255, 255) // broadcast
@@ -213,13 +238,13 @@ func allFF(b []byte) bool {
// Mask returns the result of masking the IP address ip with mask.
func (ip IP) Mask(mask IPMask) IP {
- n := len(ip)
- if len(mask) == 16 && len(ip) == 4 && allFF(mask[:12]) {
+ if len(mask) == IPv6len && len(ip) == IPv4len && allFF(mask[:12]) {
mask = mask[12:]
}
- if len(mask) == 4 && len(ip) == 16 && bytesEqual(ip[:12], v4InV6Prefix) {
+ if len(mask) == IPv4len && len(ip) == IPv6len && bytesEqual(ip[:12], v4InV6Prefix) {
ip = ip[12:]
}
+ n := len(ip)
if n != len(mask) {
return nil
}
@@ -230,40 +255,6 @@ func (ip IP) Mask(mask IPMask) IP {
return out
}
-// Convert i to decimal string.
-func itod(i uint) string {
- if i == 0 {
- return "0"
- }
-
- // Assemble decimal in reverse order.
- var b [32]byte
- bp := len(b)
- for ; i > 0; i /= 10 {
- bp--
- b[bp] = byte(i%10) + '0'
- }
-
- return string(b[bp:])
-}
-
-// Convert i to hexadecimal string.
-func itox(i uint) string {
- if i == 0 {
- return "0"
- }
-
- // Assemble hexadecimal in reverse order.
- var b [32]byte
- bp := len(b)
- for ; i > 0; i /= 16 {
- bp--
- b[bp] = "0123456789abcdef"[byte(i%16)]
- }
-
- return string(b[bp:])
-}
-
// String returns the string form of the IP address ip.
// If the address is an IPv4 address, the string representation
// is dotted decimal ("74.125.19.99"). Otherwise the representation
@@ -272,11 +263,11 @@ func (ip IP) String() string {
p := ip
if len(ip) == 0 {
- return ""
+ return "<nil>"
}
// If IPv4, use dotted notation.
- if p4 := p.To4(); len(p4) == 4 {
+ if p4 := p.To4(); len(p4) == IPv4len {
return itod(uint(p4[0])) + "." +
itod(uint(p4[1])) + "." +
itod(uint(p4[2])) + "." +
@@ -289,9 +280,9 @@ func (ip IP) String() string {
// Find longest run of zeros.
e0 := -1
e1 := -1
- for i := 0; i < 16; i += 2 {
+ for i := 0; i < IPv6len; i += 2 {
j := i
- for j < 16 && p[j] == 0 && p[j+1] == 0 {
+ for j < IPv6len && p[j] == 0 && p[j+1] == 0 {
j += 2
}
if j > i && j-i > e1-e0 {
@@ -307,17 +298,17 @@ func (ip IP) String() string {
// Print with possible :: in place of run of zeros
var s string
- for i := 0; i < 16; i += 2 {
+ for i := 0; i < IPv6len; i += 2 {
if i == e0 {
s += "::"
i = e1
- if i >= 16 {
+ if i >= IPv6len {
break
}
} else if i > 0 {
s += ":"
}
- s += itox((uint(p[i]) << 8) | uint(p[i+1]))
+ s += itox((uint(p[i])<<8)|uint(p[i+1]), 1)
}
return s
}
@@ -329,10 +320,10 @@ func (ip IP) Equal(x IP) bool {
if len(ip) == len(x) {
return bytesEqual(ip, x)
}
- if len(ip) == 4 && len(x) == 16 {
+ if len(ip) == IPv4len && len(x) == IPv6len {
return bytesEqual(x[0:12], v4InV6Prefix) && bytesEqual(ip, x[12:])
}
- if len(ip) == 16 && len(x) == 4 {
+ if len(ip) == IPv6len && len(x) == IPv4len {
return bytesEqual(ip[0:12], v4InV6Prefix) && bytesEqual(ip[12:], x)
}
return false
@@ -379,25 +370,86 @@ func simpleMaskLength(mask IPMask) int {
return n
}
-// String returns the string representation of mask.
-// If the mask is in the canonical form--ones followed by zeros--the
-// string representation is just the decimal number of ones.
-// If the mask is in a non-canonical form, it is formatted
-// as an IP address.
-func (mask IPMask) String() string {
- switch len(mask) {
- case 4:
- n := simpleMaskLength(mask)
- if n >= 0 {
- return itod(uint(n + (IPv6len-IPv4len)*8))
+// Size returns the number of leading ones and total bits in the mask.
+// If the mask is not in the canonical form--ones followed by zeros--then
+// Size returns 0, 0.
+func (m IPMask) Size() (ones, bits int) {
+ ones, bits = simpleMaskLength(m), len(m)*8
+ if ones == -1 {
+ return 0, 0
+ }
+ return
+}
+
+// String returns the hexadecimal form of m, with no punctuation.
+func (m IPMask) String() string {
+ s := ""
+ for _, b := range m {
+ s += itox(uint(b), 2)
+ }
+ if len(s) == 0 {
+ return "<nil>"
+ }
+ return s
+}
+
+func networkNumberAndMask(n *IPNet) (ip IP, m IPMask) {
+ if ip = n.IP.To4(); ip == nil {
+ ip = n.IP
+ if len(ip) != IPv6len {
+ return nil, nil
}
- case 16:
- n := simpleMaskLength(mask)
- if n >= 12*8 {
- return itod(uint(n - 12*8))
+ }
+ m = n.Mask
+ switch len(m) {
+ case IPv4len:
+ if len(ip) != IPv4len {
+ return nil, nil
+ }
+ case IPv6len:
+ if len(ip) == IPv4len {
+ m = m[12:]
+ }
+ default:
+ return nil, nil
+ }
+ return
+}
+
+// Contains reports whether the network includes ip.
+func (n *IPNet) Contains(ip IP) bool {
+ nn, m := networkNumberAndMask(n)
+ if x := ip.To4(); x != nil {
+ ip = x
+ }
+ l := len(ip)
+ if l != len(nn) {
+ return false
+ }
+ for i := 0; i < l; i++ {
+ if nn[i]&m[i] != ip[i]&m[i] {
+ return false
}
}
- return IP(mask).String()
+ return true
+}
+
+// String returns the CIDR notation of n like "192.168.100.1/24"
+// or "2001:DB8::/48" as defined in RFC 4632 and RFC 4291.
+// If the mask is not in the canonical form, it returns the
+// string which consists of an IP address, followed by a slash
+// character and a mask expressed as hexadecimal form with no
+// punctuation like "192.168.100.1/c000ff00".
+func (n *IPNet) String() string {
+ nn, m := networkNumberAndMask(n)
+ if nn == nil || m == nil {
+ return "<nil>"
+ }
+ l := simpleMaskLength(m)
+ if l == -1 {
+ return nn.String() + "/" + m.String()
+ }
+ return nn.String() + "/" + itod(uint(l))
}
// Parse IPv4 address (d.d.d.d).
@@ -440,7 +492,7 @@ func parseIPv4(s string) IP {
// * The last 32 bits can be in IPv4 form.
// Thus, ::ffff:1.2.3.4 is the IPv4 address 1.2.3.4.
func parseIPv6(s string) IP {
- p := make(IP, 16)
+ p := make(IP, IPv6len)
ellipsis := -1 // position of ellipsis in p
i := 0 // index in string s
@@ -482,7 +534,7 @@ func parseIPv6(s string) IP {
p[j+2] = p4[14]
p[j+3] = p4[15]
i = len(s)
- j += 4
+ j += IPv4len
break
}
@@ -569,46 +621,28 @@ func ParseIP(s string) IP {
}
// ParseCIDR parses s as a CIDR notation IP address and mask,
-// like "192.168.100.1/24", "2001:DB8::/48", as defined in
+// like "192.168.100.1/24" or "2001:DB8::/48", as defined in
// RFC 4632 and RFC 4291.
-func ParseCIDR(s string) (ip IP, mask IPMask, err os.Error) {
+//
+// It returns the IP address and the network implied by the IP
+// and mask. For example, ParseCIDR("192.168.100.1/16") returns
+// the IP address 192.168.100.1 and the network 192.168.0.0/16.
+func ParseCIDR(s string) (IP, *IPNet, os.Error) {
i := byteIndex(s, '/')
if i < 0 {
return nil, nil, &ParseError{"CIDR address", s}
}
ipstr, maskstr := s[:i], s[i+1:]
- iplen := 4
- ip = parseIPv4(ipstr)
+ iplen := IPv4len
+ ip := parseIPv4(ipstr)
if ip == nil {
- iplen = 16
+ iplen = IPv6len
ip = parseIPv6(ipstr)
}
- nn, i, ok := dtoi(maskstr, 0)
- if ip == nil || !ok || i != len(maskstr) || nn < 0 || nn > 8*iplen {
+ n, i, ok := dtoi(maskstr, 0)
+ if ip == nil || !ok || i != len(maskstr) || n < 0 || n > 8*iplen {
return nil, nil, &ParseError{"CIDR address", s}
}
- n := uint(nn)
- if iplen == 4 {
- v4mask := ^uint32(0xffffffff >> n)
- mask = IPv4Mask(byte(v4mask>>24), byte(v4mask>>16), byte(v4mask>>8), byte(v4mask))
- } else {
- mask = make(IPMask, 16)
- for i := 0; i < 16; i++ {
- if n >= 8 {
- mask[i] = 0xff
- n -= 8
- continue
- }
- mask[i] = ^byte(0xff >> n)
- n = 0
-
- }
- }
- // address must not have any bits not in mask
- for i := range ip {
- if ip[i]&^mask[i] != 0 {
- return nil, nil, &ParseError{"CIDR address", s}
- }
- }
- return ip, mask, nil
+ m := CIDRMask(n, 8*iplen)
+ return ip, &IPNet{ip.Mask(m), m}, nil
}
diff --git a/libgo/go/net/ip_test.go b/libgo/go/net/ip_test.go
index b189b10c4fd..07e627aef4f 100644
--- a/libgo/go/net/ip_test.go
+++ b/libgo/go/net/ip_test.go
@@ -34,12 +34,13 @@ var parseiptests = []struct {
{"::ffff:127.0.0.1", IPv4(127, 0, 0, 1)},
{"2001:4860:0:2001::68", IP{0x20, 0x01, 0x48, 0x60, 0, 0, 0x20, 0x01, 0, 0, 0, 0, 0, 0, 0x00, 0x68}},
{"::ffff:4a7d:1363", IPv4(74, 125, 19, 99)},
+ {"", nil},
}
func TestParseIP(t *testing.T) {
for _, tt := range parseiptests {
if out := ParseIP(tt.in); !isEqual(out, tt.out) {
- t.Errorf("ParseIP(%#q) = %v, want %v", tt.in, out, tt.out)
+ t.Errorf("ParseIP(%q) = %v, want %v", tt.in, out, tt.out)
}
}
}
@@ -49,60 +50,213 @@ var ipstringtests = []struct {
out string
}{
// cf. RFC 5952 (A Recommendation for IPv6 Address Text Representation)
- {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1},
- "2001:db8::123:12:1"},
- {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1},
- "2001:db8::1"},
- {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1},
- "2001:db8:0:1:0:1:0:1"},
- {IP{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0},
- "2001:db8:1:0:1:0:1:0"},
- {IP{0x20, 0x1, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1},
- "2001::1:0:0:1"},
- {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0},
- "2001:db8:0:0:1::"},
- {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1},
- "2001:db8::1:0:0:1"},
- {IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, 0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD},
- "2001:db8::a:b:c:d"},
+ {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}, "2001:db8::123:12:1"},
+ {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1"},
+ {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1}, "2001:db8:0:1:0:1:0:1"},
+ {IP{0x20, 0x1, 0xd, 0xb8, 0, 0x1, 0, 0, 0, 0x1, 0, 0, 0, 0x1, 0, 0}, "2001:db8:1:0:1:0:1:0"},
+ {IP{0x20, 0x1, 0, 0, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1}, "2001::1:0:0:1"},
+ {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0}, "2001:db8:0:0:1::"},
+ {IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0x1, 0, 0, 0, 0, 0, 0x1}, "2001:db8::1:0:0:1"},
+ {IP{0x20, 0x1, 0xD, 0xB8, 0, 0, 0, 0, 0, 0xA, 0, 0xB, 0, 0xC, 0, 0xD}, "2001:db8::a:b:c:d"},
+ {nil, "<nil>"},
}
func TestIPString(t *testing.T) {
for _, tt := range ipstringtests {
if out := tt.in.String(); out != tt.out {
- t.Errorf("IP.String(%v) = %#q, want %#q", tt.in, out, tt.out)
+ t.Errorf("IP.String(%v) = %q, want %q", tt.in, out, tt.out)
}
}
}
-var parsecidrtests = []struct {
- in string
- ip IP
+var ipmasktests = []struct {
+ in IP
mask IPMask
- err os.Error
+ out IP
+}{
+ {IPv4(192, 168, 1, 127), IPv4Mask(255, 255, 255, 128), IPv4(192, 168, 1, 0)},
+ {IPv4(192, 168, 1, 127), IPMask(ParseIP("255.255.255.192")), IPv4(192, 168, 1, 64)},
+ {IPv4(192, 168, 1, 127), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0")), IPv4(192, 168, 1, 96)},
+ {IPv4(192, 168, 1, 127), IPv4Mask(255, 0, 255, 0), IPv4(192, 0, 1, 0)},
+ {ParseIP("2001:db8::1"), IPMask(ParseIP("ffff:ff80::")), ParseIP("2001:d80::")},
+ {ParseIP("2001:db8::1"), IPMask(ParseIP("f0f0:0f0f::")), ParseIP("2000:d08::")},
+}
+
+func TestIPMask(t *testing.T) {
+ for _, tt := range ipmasktests {
+ if out := tt.in.Mask(tt.mask); out == nil || !tt.out.Equal(out) {
+ t.Errorf("IP(%v).Mask(%v) = %v, want %v", tt.in, tt.mask, out, tt.out)
+ }
+ }
+}
+
+var ipmaskstringtests = []struct {
+ in IPMask
+ out string
+}{
+ {IPv4Mask(255, 255, 255, 240), "fffffff0"},
+ {IPv4Mask(255, 0, 128, 0), "ff008000"},
+ {IPMask(ParseIP("ffff:ff80::")), "ffffff80000000000000000000000000"},
+ {IPMask(ParseIP("ef00:ff80::cafe:0")), "ef00ff800000000000000000cafe0000"},
+ {nil, "<nil>"},
+}
+
+func TestIPMaskString(t *testing.T) {
+ for _, tt := range ipmaskstringtests {
+ if out := tt.in.String(); out != tt.out {
+ t.Errorf("IPMask.String(%v) = %q, want %q", tt.in, out, tt.out)
+ }
+ }
+}
+
+var parsecidrtests = []struct {
+ in string
+ ip IP
+ net *IPNet
+ err os.Error
}{
- {"135.104.0.0/32", IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 255), nil},
- {"0.0.0.0/24", IPv4(0, 0, 0, 0), IPv4Mask(255, 255, 255, 0), nil},
- {"135.104.0.0/24", IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 0), nil},
- {"135.104.0.1/32", IPv4(135, 104, 0, 1), IPv4Mask(255, 255, 255, 255), nil},
- {"135.104.0.1/24", nil, nil, &ParseError{"CIDR address", "135.104.0.1/24"}},
- {"::1/128", ParseIP("::1"), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")), nil},
- {"abcd:2345::/127", ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe")), nil},
- {"abcd:2345::/65", ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::")), nil},
- {"abcd:2345::/64", ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff::")), nil},
- {"abcd:2345::/63", ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:fffe::")), nil},
- {"abcd:2345::/33", ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:8000::")), nil},
- {"abcd:2345::/32", ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff::")), nil},
- {"abcd:2344::/31", ParseIP("abcd:2344::"), IPMask(ParseIP("ffff:fffe::")), nil},
- {"abcd:2300::/24", ParseIP("abcd:2300::"), IPMask(ParseIP("ffff:ff00::")), nil},
- {"abcd:2345::/24", nil, nil, &ParseError{"CIDR address", "abcd:2345::/24"}},
- {"2001:DB8::/48", ParseIP("2001:DB8::"), IPMask(ParseIP("ffff:ffff:ffff::")), nil},
+ {"135.104.0.0/32", IPv4(135, 104, 0, 0), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 255)}, nil},
+ {"0.0.0.0/24", IPv4(0, 0, 0, 0), &IPNet{IPv4(0, 0, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
+ {"135.104.0.0/24", IPv4(135, 104, 0, 0), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
+ {"135.104.0.1/32", IPv4(135, 104, 0, 1), &IPNet{IPv4(135, 104, 0, 1), IPv4Mask(255, 255, 255, 255)}, nil},
+ {"135.104.0.1/24", IPv4(135, 104, 0, 1), &IPNet{IPv4(135, 104, 0, 0), IPv4Mask(255, 255, 255, 0)}, nil},
+ {"::1/128", ParseIP("::1"), &IPNet{ParseIP("::1"), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))}, nil},
+ {"abcd:2345::/127", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe"))}, nil},
+ {"abcd:2345::/65", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff:8000::"))}, nil},
+ {"abcd:2345::/64", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:ffff::"))}, nil},
+ {"abcd:2345::/63", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:ffff:fffe::"))}, nil},
+ {"abcd:2345::/33", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff:8000::"))}, nil},
+ {"abcd:2345::/32", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2345::"), IPMask(ParseIP("ffff:ffff::"))}, nil},
+ {"abcd:2344::/31", ParseIP("abcd:2344::"), &IPNet{ParseIP("abcd:2344::"), IPMask(ParseIP("ffff:fffe::"))}, nil},
+ {"abcd:2300::/24", ParseIP("abcd:2300::"), &IPNet{ParseIP("abcd:2300::"), IPMask(ParseIP("ffff:ff00::"))}, nil},
+ {"abcd:2345::/24", ParseIP("abcd:2345::"), &IPNet{ParseIP("abcd:2300::"), IPMask(ParseIP("ffff:ff00::"))}, nil},
+ {"2001:DB8::/48", ParseIP("2001:DB8::"), &IPNet{ParseIP("2001:DB8::"), IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
+ {"2001:DB8::1/48", ParseIP("2001:DB8::1"), &IPNet{ParseIP("2001:DB8::"), IPMask(ParseIP("ffff:ffff:ffff::"))}, nil},
+ {"192.168.1.1/255.255.255.0", nil, nil, &ParseError{"CIDR address", "192.168.1.1/255.255.255.0"}},
+ {"192.168.1.1/35", nil, nil, &ParseError{"CIDR address", "192.168.1.1/35"}},
+ {"2001:db8::1/-1", nil, nil, &ParseError{"CIDR address", "2001:db8::1/-1"}},
+ {"", nil, nil, &ParseError{"CIDR address", ""}},
}
func TestParseCIDR(t *testing.T) {
for _, tt := range parsecidrtests {
- if ip, mask, err := ParseCIDR(tt.in); !isEqual(ip, tt.ip) || !isEqual(mask, tt.mask) || !reflect.DeepEqual(err, tt.err) {
- t.Errorf("ParseCIDR(%q) = %v, %v, %v; want %v, %v, %v", tt.in, ip, mask, err, tt.ip, tt.mask, tt.err)
+ ip, net, err := ParseCIDR(tt.in)
+ if !reflect.DeepEqual(err, tt.err) {
+ t.Errorf("ParseCIDR(%q) = %v, %v; want %v, %v", tt.in, ip, net, tt.ip, tt.net)
+ }
+ if err == nil && (!tt.ip.Equal(ip) || !tt.net.IP.Equal(net.IP) || !isEqual(net.Mask, tt.net.Mask)) {
+ t.Errorf("ParseCIDR(%q) = %v, {%v, %v}; want %v {%v, %v}", tt.in, ip, net.IP, net.Mask, tt.ip, tt.net.IP, tt.net.Mask)
+ }
+ }
+}
+
+var ipnetcontainstests = []struct {
+ ip IP
+ net *IPNet
+ ok bool
+}{
+ {IPv4(172, 16, 1, 1), &IPNet{IPv4(172, 16, 0, 0), CIDRMask(12, 32)}, true},
+ {IPv4(172, 24, 0, 1), &IPNet{IPv4(172, 16, 0, 0), CIDRMask(13, 32)}, false},
+ {IPv4(192, 168, 0, 3), &IPNet{IPv4(192, 168, 0, 0), IPv4Mask(0, 0, 255, 252)}, true},
+ {IPv4(192, 168, 0, 4), &IPNet{IPv4(192, 168, 0, 0), IPv4Mask(0, 255, 0, 252)}, false},
+ {ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), CIDRMask(47, 128)}, true},
+ {ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:2::"), CIDRMask(47, 128)}, false},
+ {ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), IPMask(ParseIP("ffff:0:ffff::"))}, true},
+ {ParseIP("2001:db8:1:2::1"), &IPNet{ParseIP("2001:db8:1::"), IPMask(ParseIP("0:0:0:ffff::"))}, false},
+}
+
+func TestIPNetContains(t *testing.T) {
+ for _, tt := range ipnetcontainstests {
+ if ok := tt.net.Contains(tt.ip); ok != tt.ok {
+ t.Errorf("IPNet(%v).Contains(%v) = %v, want %v", tt.net, tt.ip, ok, tt.ok)
+ }
+ }
+}
+
+var ipnetstringtests = []struct {
+ in *IPNet
+ out string
+}{
+ {&IPNet{IPv4(192, 168, 1, 0), CIDRMask(26, 32)}, "192.168.1.0/26"},
+ {&IPNet{IPv4(192, 168, 1, 0), IPv4Mask(255, 0, 255, 0)}, "192.168.1.0/ff00ff00"},
+ {&IPNet{ParseIP("2001:db8::"), CIDRMask(55, 128)}, "2001:db8::/55"},
+ {&IPNet{ParseIP("2001:db8::"), IPMask(ParseIP("8000:f123:0:cafe::"))}, "2001:db8::/8000f1230000cafe0000000000000000"},
+}
+
+func TestIPNetString(t *testing.T) {
+ for _, tt := range ipnetstringtests {
+ if out := tt.in.String(); out != tt.out {
+ t.Errorf("IPNet.String(%v) = %q, want %q", tt.in, out, tt.out)
+ }
+ }
+}
+
+var cidrmasktests = []struct {
+ ones int
+ bits int
+ out IPMask
+}{
+ {0, 32, IPv4Mask(0, 0, 0, 0)},
+ {12, 32, IPv4Mask(255, 240, 0, 0)},
+ {24, 32, IPv4Mask(255, 255, 255, 0)},
+ {32, 32, IPv4Mask(255, 255, 255, 255)},
+ {0, 128, IPMask{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+ {4, 128, IPMask{0xf0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+ {48, 128, IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+ {128, 128, IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
+ {33, 32, nil},
+ {32, 33, nil},
+ {-1, 128, nil},
+ {128, -1, nil},
+}
+
+func TestCIDRMask(t *testing.T) {
+ for _, tt := range cidrmasktests {
+ if out := CIDRMask(tt.ones, tt.bits); !isEqual(out, tt.out) {
+ t.Errorf("CIDRMask(%v, %v) = %v, want %v", tt.ones, tt.bits, out, tt.out)
+ }
+ }
+}
+
+var (
+ v4addr = IP{192, 168, 0, 1}
+ v4mappedv6addr = IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 0, 1}
+ v6addr = IP{0x20, 0x1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0x1, 0x23, 0, 0x12, 0, 0x1}
+ v4mask = IPMask{255, 255, 255, 0}
+ v4mappedv6mask = IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 255, 255, 255, 0}
+ v6mask = IPMask{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0}
+ badaddr = IP{192, 168, 0}
+ badmask = IPMask{255, 255, 0}
+ v4maskzero = IPMask{0, 0, 0, 0}
+)
+
+var networknumberandmasktests = []struct {
+ in IPNet
+ out IPNet
+}{
+ {IPNet{v4addr, v4mask}, IPNet{v4addr, v4mask}},
+ {IPNet{v4addr, v4mappedv6mask}, IPNet{v4addr, v4mask}},
+ {IPNet{v4mappedv6addr, v4mappedv6mask}, IPNet{v4addr, v4mask}},
+ {IPNet{v4mappedv6addr, v6mask}, IPNet{v4addr, v4maskzero}},
+ {IPNet{v4addr, v6mask}, IPNet{v4addr, v4maskzero}},
+ {IPNet{v6addr, v6mask}, IPNet{v6addr, v6mask}},
+ {IPNet{v6addr, v4mappedv6mask}, IPNet{v6addr, v4mappedv6mask}},
+ {in: IPNet{v6addr, v4mask}},
+ {in: IPNet{v4addr, badmask}},
+ {in: IPNet{v4mappedv6addr, badmask}},
+ {in: IPNet{v6addr, badmask}},
+ {in: IPNet{badaddr, v4mask}},
+ {in: IPNet{badaddr, v4mappedv6mask}},
+ {in: IPNet{badaddr, v6mask}},
+ {in: IPNet{badaddr, badmask}},
+}
+
+func TestNetworkNumberAndMask(t *testing.T) {
+ for _, tt := range networknumberandmasktests {
+ ip, m := networkNumberAndMask(&tt.in)
+ out := &IPNet{ip, m}
+ if !reflect.DeepEqual(&tt.out, out) {
+ t.Errorf("networkNumberAndMask(%v) = %v; want %v", tt.in, out, &tt.out)
}
}
}
@@ -158,10 +312,10 @@ var ipaftests = []struct {
func TestIPAddrFamily(t *testing.T) {
for _, tt := range ipaftests {
if af := tt.in.To4() != nil; af != tt.af4 {
- t.Errorf("verifying IPv4 address family for %#q = %v, want %v", tt.in, af, tt.af4)
+ t.Errorf("verifying IPv4 address family for %q = %v, want %v", tt.in, af, tt.af4)
}
if af := len(tt.in) == IPv6len && tt.in.To4() == nil; af != tt.af6 {
- t.Errorf("verifying IPv6 address family for %#q = %v, want %v", tt.in, af, tt.af6)
+ t.Errorf("verifying IPv6 address family for %q = %v, want %v", tt.in, af, tt.af6)
}
}
}
@@ -209,7 +363,7 @@ func name(f interface{}) string {
func TestIPAddrScope(t *testing.T) {
for _, tt := range ipscopetests {
if ok := tt.scope(tt.in); ok != tt.ok {
- t.Errorf("%s(%#q) = %v, want %v", name(tt.scope), tt.in, ok, tt.ok)
+ t.Errorf("%s(%q) = %v, want %v", name(tt.scope), tt.in, ok, tt.ok)
}
}
}
diff --git a/libgo/go/net/iprawsock_posix.go b/libgo/go/net/iprawsock_posix.go
index 4e115180061..dafbdab7804 100644
--- a/libgo/go/net/iprawsock_posix.go
+++ b/libgo/go/net/iprawsock_posix.go
@@ -2,18 +2,17 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
// (Raw) IP sockets
package net
import (
"os"
- "sync"
"syscall"
)
-var onceReadProtocols sync.Once
-
func sockaddrToIP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
@@ -25,7 +24,7 @@ func sockaddrToIP(sa syscall.Sockaddr) Addr {
}
func (a *IPAddr) family() int {
- if a == nil || len(a.IP) <= 4 {
+ if a == nil || len(a.IP) <= IPv4len {
return syscall.AF_INET
}
if a.IP.To4() != nil {
@@ -158,7 +157,7 @@ func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err os.Error) {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
addr = &IPAddr{sa.Addr[0:]}
- if len(b) >= 4 { // discard ipv4 header
+ if len(b) >= IPv4len { // discard ipv4 header
hsize := (int(b[0]) & 0xf) * 4
copy(b, b[hsize:])
n -= hsize
@@ -207,33 +206,7 @@ func (c *IPConn) WriteTo(b []byte, addr Addr) (n int, err os.Error) {
return c.WriteToIP(b, a)
}
-var protocols map[string]int
-
-func readProtocols() {
- protocols = make(map[string]int)
- if file, err := open("/etc/protocols"); err == nil {
- for line, ok := file.readLine(); ok; line, ok = file.readLine() {
- // tcp 6 TCP # transmission control protocol
- if i := byteIndex(line, '#'); i >= 0 {
- line = line[0:i]
- }
- f := getFields(line)
- if len(f) < 2 {
- continue
- }
- if proto, _, ok := dtoi(f[1], 0); ok {
- protocols[f[0]] = proto
- for _, alias := range f[2:] {
- protocols[alias] = proto
- }
- }
- }
- file.close()
- }
-}
-
func splitNetProto(netProto string) (net string, proto int, err os.Error) {
- onceReadProtocols.Do(readProtocols)
i := last(netProto, ':')
if i < 0 { // no colon
return "", 0, os.NewError("no IP protocol specified")
@@ -242,13 +215,12 @@ func splitNetProto(netProto string) (net string, proto int, err os.Error) {
protostr := netProto[i+1:]
proto, i, ok := dtoi(protostr, 0)
if !ok || i != len(protostr) {
- // lookup by name
- proto, ok = protocols[protostr]
- if ok {
- return
+ proto, err = lookupProtocol(protostr)
+ if err != nil {
+ return "", 0, err
}
}
- return
+ return net, proto, nil
}
// DialIP connects to the remote address raddr on the network net,
@@ -303,3 +275,8 @@ func (c *IPConn) BindToDevice(device string) os.Error {
defer c.fd.decref()
return os.NewSyscallError("setsockopt", syscall.BindToDevice(c.fd.sysfd, device))
}
+
+// File returns a copy of the underlying os.File, set to blocking mode.
+// It is the caller's responsibility to close f when finished.
+// Closing c does not affect f, and closing f does not affect c.
+func (c *IPConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
diff --git a/libgo/go/net/ipsock_posix.go b/libgo/go/net/ipsock_posix.go
index 0c522fb7fbe..049df9ea4cb 100644
--- a/libgo/go/net/ipsock_posix.go
+++ b/libgo/go/net/ipsock_posix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
package net
import (
diff --git a/libgo/go/net/lookup_plan9.go b/libgo/go/net/lookup_plan9.go
index 37d6b8e315a..d779f4a5d71 100644
--- a/libgo/go/net/lookup_plan9.go
+++ b/libgo/go/net/lookup_plan9.go
@@ -157,12 +157,21 @@ func LookupCNAME(name string) (cname string, err os.Error) {
}
// LookupSRV tries to resolve an SRV query of the given service,
-// protocol, and domain name, as specified in RFC 2782. In most cases
-// the proto argument can be the same as the corresponding
-// Addr.Network(). The returned records are sorted by priority
-// and randomized by weight within a priority.
+// protocol, and domain name. The proto is "tcp" or "udp".
+// The returned records are sorted by priority and randomized
+// by weight within a priority.
+//
+// LookupSRV constructs the DNS name to look up following RFC 2782.
+// That is, it looks up _service._proto.name. To accommodate services
+// publishing SRV records under non-standard names, if both service
+// and proto are empty strings, LookupSRV looks up name directly.
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
- target := "_" + service + "._" + proto + "." + name
+ var target string
+ if service == "" && proto == "" {
+ target = name
+ } else {
+ target = "_" + service + "._" + proto + "." + name
+ }
lines, err := queryDNS(target, "srv")
if err != nil {
return
@@ -204,6 +213,11 @@ func LookupMX(name string) (mx []*MX, err os.Error) {
return
}
+// LookupTXT returns the DNS TXT records for the given domain name.
+func LookupTXT(name string) (txt []string, err os.Error) {
+ return nil, os.NewError("net.LookupTXT is not implemented on Plan 9")
+}
+
// LookupAddr performs a reverse lookup for the given address, returning a list
// of names mapping to that address.
func LookupAddr(addr string) (name []string, err os.Error) {
diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go
index 995ab03d090..c0fcd260472 100644
--- a/libgo/go/net/lookup_test.go
+++ b/libgo/go/net/lookup_test.go
@@ -26,6 +26,15 @@ func TestGoogleSRV(t *testing.T) {
if len(addrs) == 0 {
t.Errorf("no results")
}
+
+ // Non-standard back door.
+ _, addrs, err = LookupSRV("", "", "_xmpp-server._tcp.google.com")
+ if err != nil {
+ t.Errorf("back door failed: %s", err)
+ }
+ if len(addrs) == 0 {
+ t.Errorf("back door no results")
+ }
}
func TestGmailMX(t *testing.T) {
@@ -42,6 +51,24 @@ func TestGmailMX(t *testing.T) {
}
}
+func TestGmailTXT(t *testing.T) {
+ if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
+ t.Logf("LookupTXT is not implemented on Windows or Plan 9")
+ return
+ }
+ if testing.Short() || avoidMacFirewall {
+ t.Logf("skipping test to avoid external network")
+ return
+ }
+ txt, err := LookupTXT("gmail.com")
+ if err != nil {
+ t.Errorf("failed: %s", err)
+ }
+ if len(txt) == 0 || len(txt[0]) == 0 {
+ t.Errorf("no results")
+ }
+}
+
func TestGoogleDNSAddr(t *testing.T) {
if testing.Short() || avoidMacFirewall {
t.Logf("skipping test to avoid external network")
diff --git a/libgo/go/net/lookup_unix.go b/libgo/go/net/lookup_unix.go
index 8f5e66212b3..6e79295a948 100644
--- a/libgo/go/net/lookup_unix.go
+++ b/libgo/go/net/lookup_unix.go
@@ -2,12 +2,56 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package net
import (
"os"
+ "sync"
+)
+
+var (
+ protocols map[string]int
+ onceReadProtocols sync.Once
)
+// readProtocols loads contents of /etc/protocols into protocols map
+// for quick access.
+func readProtocols() {
+ protocols = make(map[string]int)
+ if file, err := open("/etc/protocols"); err == nil {
+ for line, ok := file.readLine(); ok; line, ok = file.readLine() {
+ // tcp 6 TCP # transmission control protocol
+ if i := byteIndex(line, '#'); i >= 0 {
+ line = line[0:i]
+ }
+ f := getFields(line)
+ if len(f) < 2 {
+ continue
+ }
+ if proto, _, ok := dtoi(f[1], 0); ok {
+ protocols[f[0]] = proto
+ for _, alias := range f[2:] {
+ protocols[alias] = proto
+ }
+ }
+ }
+ file.close()
+ }
+}
+
+// lookupProtocol looks up IP protocol name in /etc/protocols and
+// returns correspondent protocol number.
+func lookupProtocol(name string) (proto int, err os.Error) {
+ onceReadProtocols.Do(readProtocols)
+ proto, found := protocols[name]
+ if !found {
+ return 0, os.NewError("unknown IP protocol specified: " + name)
+ }
+ return
+}
+
// LookupHost looks up the given host using the local resolver.
// It returns an array of that host's addresses.
func LookupHost(host string) (addrs []string, err os.Error) {
@@ -50,12 +94,21 @@ func LookupCNAME(name string) (cname string, err os.Error) {
}
// LookupSRV tries to resolve an SRV query of the given service,
-// protocol, and domain name, as specified in RFC 2782. In most cases
-// the proto argument can be the same as the corresponding
-// Addr.Network(). The returned records are sorted by priority
-// and randomized by weight within a priority.
+// protocol, and domain name. The proto is "tcp" or "udp".
+// The returned records are sorted by priority and randomized
+// by weight within a priority.
+//
+// LookupSRV constructs the DNS name to look up following RFC 2782.
+// That is, it looks up _service._proto.name. To accommodate services
+// publishing SRV records under non-standard names, if both service
+// and proto are empty strings, LookupSRV looks up name directly.
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
- target := "_" + service + "._" + proto + "." + name
+ var target string
+ if service == "" && proto == "" {
+ target = name
+ } else {
+ target = "_" + service + "._" + proto + "." + name
+ }
var records []dnsRR
cname, records, err = lookup(target, dnsTypeSRV)
if err != nil {
@@ -72,19 +125,32 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
func LookupMX(name string) (mx []*MX, err os.Error) {
- _, rr, err := lookup(name, dnsTypeMX)
+ _, records, err := lookup(name, dnsTypeMX)
if err != nil {
return
}
- mx = make([]*MX, len(rr))
- for i := range rr {
- r := rr[i].(*dnsRR_MX)
+ mx = make([]*MX, len(records))
+ for i, rr := range records {
+ r := rr.(*dnsRR_MX)
mx[i] = &MX{r.Mx, r.Pref}
}
byPref(mx).sort()
return
}
+// LookupTXT returns the DNS TXT records for the given domain name.
+func LookupTXT(name string) (txt []string, err os.Error) {
+ _, records, err := lookup(name, dnsTypeTXT)
+ if err != nil {
+ return
+ }
+ txt = make([]string, len(records))
+ for i, r := range records {
+ txt[i] = r.(*dnsRR_TXT).Txt
+ }
+ return
+}
+
// LookupAddr performs a reverse lookup for the given address, returning a list
// of names mapping to that address.
func LookupAddr(addr string) (name []string, err os.Error) {
diff --git a/libgo/go/net/lookup_windows.go b/libgo/go/net/lookup_windows.go
index fa3ad7c7f42..ea939f85986 100644
--- a/libgo/go/net/lookup_windows.go
+++ b/libgo/go/net/lookup_windows.go
@@ -11,8 +11,22 @@ import (
"sync"
)
-var hostentLock sync.Mutex
-var serventLock sync.Mutex
+var (
+ protoentLock sync.Mutex
+ hostentLock sync.Mutex
+ serventLock sync.Mutex
+)
+
+// lookupProtocol looks up IP protocol name and returns correspondent protocol number.
+func lookupProtocol(name string) (proto int, err os.Error) {
+ protoentLock.Lock()
+ defer protoentLock.Unlock()
+ p, e := syscall.GetProtoByName(name)
+ if e != 0 {
+ return 0, os.NewSyscallError("GetProtoByName", e)
+ }
+ return int(p.Proto), nil
+}
func LookupHost(name string) (addrs []string, err os.Error) {
ips, err := LookupIP(name)
@@ -77,9 +91,23 @@ func LookupCNAME(name string) (cname string, err os.Error) {
return
}
+// LookupSRV tries to resolve an SRV query of the given service,
+// protocol, and domain name. The proto is "tcp" or "udp".
+// The returned records are sorted by priority and randomized
+// by weight within a priority.
+//
+// LookupSRV constructs the DNS name to look up following RFC 2782.
+// That is, it looks up _service._proto.name. To accommodate services
+// publishing SRV records under non-standard names, if both service
+// and proto are empty strings, LookupSRV looks up name directly.
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
+ var target string
+ if service == "" && proto == "" {
+ target = name
+ } else {
+ target = "_" + service + "._" + proto + "." + name
+ }
var r *syscall.DNSRecord
- target := "_" + service + "._" + proto + "." + name
e := syscall.DnsQuery(target, syscall.DNS_TYPE_SRV, 0, nil, &r, nil)
if int(e) != 0 {
return "", nil, os.NewSyscallError("LookupSRV", int(e))
@@ -110,6 +138,10 @@ func LookupMX(name string) (mx []*MX, err os.Error) {
return mx, nil
}
+func LookupTXT(name string) (txt []string, err os.Error) {
+ return nil, os.NewError("net.LookupTXT is not implemented on Windows")
+}
+
func LookupAddr(addr string) (name []string, err os.Error) {
arpa, err := reverseaddr(addr)
if err != nil {
diff --git a/libgo/go/net/multicast_test.go b/libgo/go/net/multicast_test.go
index be6dbf2dc19..a66250c844b 100644
--- a/libgo/go/net/multicast_test.go
+++ b/libgo/go/net/multicast_test.go
@@ -6,13 +6,33 @@ package net
import (
"flag"
+ "os"
"runtime"
"testing"
)
var multicast = flag.Bool("multicast", false, "enable multicast tests")
-func TestMulticastJoinAndLeave(t *testing.T) {
+var joinAndLeaveGroupUDPTests = []struct {
+ net string
+ laddr IP
+ gaddr IP
+ flags Flags
+ ipv6 bool
+}{
+ // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
+ {"udp", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false},
+ {"udp4", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false},
+ {"udp", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff01::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff02::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff04::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff05::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff08::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true},
+}
+
+func TestJoinAndLeaveGroupUDP(t *testing.T) {
if runtime.GOOS == "windows" {
return
}
@@ -21,53 +41,51 @@ func TestMulticastJoinAndLeave(t *testing.T) {
return
}
- addr := &UDPAddr{
- IP: IPv4zero,
- Port: 0,
- }
- // open a UDPConn
- conn, err := ListenUDP("udp4", addr)
- if err != nil {
- t.Fatal(err)
- }
- defer conn.Close()
-
- // try to join group
- mcast := IPv4(224, 0, 0, 254)
- err = conn.JoinGroup(mcast)
- if err != nil {
- t.Fatal(err)
- }
-
- // try to leave group
- err = conn.LeaveGroup(mcast)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestJoinFailureWithIPv6Address(t *testing.T) {
- if !*multicast {
- t.Logf("test disabled; use --multicast to enable")
- return
- }
- addr := &UDPAddr{
- IP: IPv4zero,
- Port: 0,
- }
-
- // open a UDPConn
- conn, err := ListenUDP("udp4", addr)
- if err != nil {
- t.Fatal(err)
- }
- defer conn.Close()
-
- // try to join group
- mcast := ParseIP("ff02::1")
- err = conn.JoinGroup(mcast)
- if err == nil {
- t.Fatal("JoinGroup succeeded, should fail")
+ for _, tt := range joinAndLeaveGroupUDPTests {
+ var (
+ ifi *Interface
+ found bool
+ )
+ if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) {
+ continue
+ }
+ ift, err := Interfaces()
+ if err != nil {
+ t.Fatalf("Interfaces() failed: %v", err)
+ }
+ for _, x := range ift {
+ if x.Flags&tt.flags == tt.flags {
+ ifi = &x
+ break
+ }
+ }
+ if ifi == nil {
+ t.Logf("an appropriate multicast interface not found")
+ return
+ }
+ c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ if err := c.JoinGroup(ifi, tt.gaddr); err != nil {
+ t.Fatal(err)
+ }
+ ifmat, err := ifi.MulticastAddrs()
+ if err != nil {
+ t.Fatalf("MulticastAddrs() failed: %v", err)
+ }
+ for _, ifma := range ifmat {
+ if ifma.(*IPAddr).IP.Equal(tt.gaddr) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Fatalf("%q not found in RIB", tt.gaddr.String())
+ }
+ if err := c.LeaveGroup(ifi, tt.gaddr); err != nil {
+ t.Fatal(err)
+ }
}
- t.Logf("%s", err)
}
diff --git a/libgo/go/net/net_test.go b/libgo/go/net/net_test.go
index dc0d49d23ac..b4a6e1f5d69 100644
--- a/libgo/go/net/net_test.go
+++ b/libgo/go/net/net_test.go
@@ -6,6 +6,7 @@ package net
import (
"flag"
+ "os"
"regexp"
"testing"
)
@@ -61,6 +62,8 @@ var dialErrorTests = []DialErrorTest{
},
}
+var duplicateErrorPattern = `dial (.*) dial (.*)`
+
func TestDialError(t *testing.T) {
if !*runErrorTest {
t.Logf("test disabled; use --run_error_test to enable")
@@ -80,6 +83,10 @@ func TestDialError(t *testing.T) {
if !match {
t.Errorf("#%d: %q, want match for %#q", i, s, tt.Pattern)
}
+ match, _ = regexp.MatchString(duplicateErrorPattern, s)
+ if match {
+ t.Errorf("#%d: %q, duplicate error return from Dial", i, s)
+ }
}
}
@@ -119,3 +126,46 @@ func TestReverseAddress(t *testing.T) {
}
}
}
+
+func TestShutdown(t *testing.T) {
+ l, err := Listen("tcp", "127.0.0.1:0")
+ if err != nil {
+ if l, err = Listen("tcp6", "[::1]:0"); err != nil {
+ t.Fatalf("ListenTCP on :0: %v", err)
+ }
+ }
+
+ go func() {
+ c, err := l.Accept()
+ if err != nil {
+ t.Fatalf("Accept: %v", err)
+ }
+ var buf [10]byte
+ n, err := c.Read(buf[:])
+ if n != 0 || err != os.EOF {
+ t.Fatalf("server Read = %d, %v; want 0, os.EOF", n, err)
+ }
+ c.Write([]byte("response"))
+ c.Close()
+ }()
+
+ c, err := Dial("tcp", l.Addr().String())
+ if err != nil {
+ t.Fatalf("Dial: %v", err)
+ }
+ defer c.Close()
+
+ err = c.(*TCPConn).CloseWrite()
+ if err != nil {
+ t.Fatalf("CloseWrite: %v", err)
+ }
+ var buf [10]byte
+ n, err := c.Read(buf[:])
+ if err != nil {
+ t.Fatalf("client Read: %d, %v", n, err)
+ }
+ got := string(buf[:n])
+ if got != "response" {
+ t.Errorf("read = %q, want \"response\"", got)
+ }
+}
diff --git a/libgo/go/net/newpollserver.go b/libgo/go/net/newpollserver.go
index 427208701b3..3c9a6da5373 100644
--- a/libgo/go/net/newpollserver.go
+++ b/libgo/go/net/newpollserver.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package net
import (
diff --git a/libgo/go/net/parse.go b/libgo/go/net/parse.go
index de46830d292..0d30a7ac609 100644
--- a/libgo/go/net/parse.go
+++ b/libgo/go/net/parse.go
@@ -159,6 +159,18 @@ func xtoi(s string, i0 int) (n int, i int, ok bool) {
return n, i, true
}
+// xtoi2 converts the next two hex digits of s into a byte.
+// If s is longer than 2 bytes then the third byte must be e.
+// If the first two bytes of s are not hex digits or the third byte
+// does not match e, false is returned.
+func xtoi2(s string, e byte) (byte, bool) {
+ if len(s) > 2 && s[2] != e {
+ return 0, false
+ }
+ n, ei, ok := xtoi(s[:2], 0)
+ return byte(n), ok && ei == 2
+}
+
// Integer to decimal.
func itoa(i int) string {
var buf [30]byte
@@ -181,6 +193,37 @@ func itoa(i int) string {
return string(buf[n:])
}
+// Convert i to decimal string.
+func itod(i uint) string {
+ if i == 0 {
+ return "0"
+ }
+
+ // Assemble decimal in reverse order.
+ var b [32]byte
+ bp := len(b)
+ for ; i > 0; i /= 10 {
+ bp--
+ b[bp] = byte(i%10) + '0'
+ }
+
+ return string(b[bp:])
+}
+
+// Convert i to hexadecimal string.
+func itox(i uint, min int) string {
+ // Assemble hexadecimal in reverse order.
+ var b [32]byte
+ bp := len(b)
+ for ; i > 0 || min > 0; i /= 16 {
+ bp--
+ b[bp] = "0123456789abcdef"[byte(i%16)]
+ min--
+ }
+
+ return string(b[bp:])
+}
+
// Number of occurrences of b in s.
func count(s string, b byte) int {
n := 0
diff --git a/libgo/go/net/port.go b/libgo/go/net/port.go
index 8f8327a3733..a8ca60c60aa 100644
--- a/libgo/go/net/port.go
+++ b/libgo/go/net/port.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
// Read system port mappings from /etc/services
package net
diff --git a/libgo/go/net/sendfile_stub.go b/libgo/go/net/sendfile_stub.go
index 43e8104e94c..c55be6c0801 100644
--- a/libgo/go/net/sendfile_stub.go
+++ b/libgo/go/net/sendfile_stub.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd openbsd
+
package net
import (
diff --git a/libgo/go/net/sendfile_windows.go b/libgo/go/net/sendfile_windows.go
index 3772eee2490..d9c2f537a3d 100644
--- a/libgo/go/net/sendfile_windows.go
+++ b/libgo/go/net/sendfile_windows.go
@@ -54,7 +54,7 @@ func sendFile(c *netFD, r io.Reader) (written int64, err os.Error, handled bool)
defer c.decref()
var o sendfileOp
- o.Init(c)
+ o.Init(c, 'w')
o.n = uint32(n)
o.src = f.Fd()
done, err := iosrv.ExecIO(&o, 0)
diff --git a/libgo/go/net/server_test.go b/libgo/go/net/server_test.go
index 7d7f7fc01c4..a2ff218e708 100644
--- a/libgo/go/net/server_test.go
+++ b/libgo/go/net/server_test.go
@@ -115,7 +115,9 @@ func doTest(t *testing.T, network, listenaddr, dialaddr string) {
}
func TestTCPServer(t *testing.T) {
- doTest(t, "tcp", "", "127.0.0.1")
+ if syscall.OS != "openbsd" {
+ doTest(t, "tcp", "", "127.0.0.1")
+ }
doTest(t, "tcp", "0.0.0.0", "127.0.0.1")
doTest(t, "tcp", "127.0.0.1", "127.0.0.1")
doTest(t, "tcp4", "", "127.0.0.1")
diff --git a/libgo/go/net/sock.go b/libgo/go/net/sock.go
index 821716e43bd..2359014ad63 100644
--- a/libgo/go/net/sock.go
+++ b/libgo/go/net/sock.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
// Sockets
package net
@@ -50,6 +52,7 @@ func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscal
if ra != nil {
if err = fd.connect(ra); err != nil {
+ closesocket(s)
fd.Close()
return nil, err
}
diff --git a/libgo/go/net/sock_bsd.go b/libgo/go/net/sock_bsd.go
index 5fd52074ad3..c59802fecb3 100644
--- a/libgo/go/net/sock_bsd.go
+++ b/libgo/go/net/sock_bsd.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd
+
// Sockets for BSD variants
package net
diff --git a/libgo/go/net/tcpsock_posix.go b/libgo/go/net/tcpsock_posix.go
index 5560301b40f..740a63d3038 100644
--- a/libgo/go/net/tcpsock_posix.go
+++ b/libgo/go/net/tcpsock_posix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
// TCP sockets
package net
@@ -12,6 +14,11 @@ import (
"syscall"
)
+// BUG(rsc): On OpenBSD, listening on the "tcp" network does not listen for
+// both IPv4 and IPv6 connections. This is due to the fact that IPv4 traffic
+// will not be routed to an IPv6 socket - two separate sockets are required
+// if both AFs are to be supported. See inet6(4) on OpenBSD for details.
+
func sockaddrToTCP(sa syscall.Sockaddr) Addr {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
@@ -23,7 +30,7 @@ func sockaddrToTCP(sa syscall.Sockaddr) Addr {
}
func (a *TCPAddr) family() int {
- if a == nil || len(a.IP) <= 4 {
+ if a == nil || len(a.IP) <= IPv4len {
return syscall.AF_INET
}
if a.IP.To4() != nil {
@@ -93,6 +100,24 @@ func (c *TCPConn) Close() os.Error {
return err
}
+// CloseRead shuts down the reading side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseRead() os.Error {
+ if !c.ok() {
+ return os.EINVAL
+ }
+ return c.fd.CloseRead()
+}
+
+// CloseWrite shuts down the writing side of the TCP connection.
+// Most callers should just use Close.
+func (c *TCPConn) CloseWrite() os.Error {
+ if !c.ok() {
+ return os.EINVAL
+ }
+ return c.fd.CloseWrite()
+}
+
// LocalAddr returns the local network address, a *TCPAddr.
func (c *TCPConn) LocalAddr() Addr {
if !c.ok() {
diff --git a/libgo/go/net/textproto/header.go b/libgo/go/net/textproto/header.go
index 288deb2ceb4..7fb32f8045e 100644
--- a/libgo/go/net/textproto/header.go
+++ b/libgo/go/net/textproto/header.go
@@ -39,5 +39,5 @@ func (h MIMEHeader) Get(key string) string {
// Del deletes the values associated with key.
func (h MIMEHeader) Del(key string) {
- h[CanonicalMIMEHeaderKey(key)] = nil, false
+ delete(h, CanonicalMIMEHeaderKey(key))
}
diff --git a/libgo/go/net/textproto/pipeline.go b/libgo/go/net/textproto/pipeline.go
index 8c25884b3bf..ca50eddac38 100644
--- a/libgo/go/net/textproto/pipeline.go
+++ b/libgo/go/net/textproto/pipeline.go
@@ -108,7 +108,7 @@ func (s *sequencer) End(id uint) {
}
c, ok := s.wait[id]
if ok {
- s.wait[id] = nil, false
+ delete(s.wait, id)
}
s.mu.Unlock()
if ok {
diff --git a/libgo/go/net/textproto/reader.go b/libgo/go/net/textproto/reader.go
index ce0ddc73f84..ece9a99ffbb 100644
--- a/libgo/go/net/textproto/reader.go
+++ b/libgo/go/net/textproto/reader.go
@@ -11,6 +11,7 @@ import (
"io/ioutil"
"os"
"strconv"
+ "strings"
)
// BUG(rsc): To let callers manage exposure to denial of service
@@ -182,6 +183,10 @@ func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message
if err != nil {
return
}
+ return parseCodeLine(line, expectCode)
+}
+
+func parseCodeLine(line string, expectCode int) (code int, continued bool, message string, err os.Error) {
if len(line) < 4 || line[3] != ' ' && line[3] != '-' {
err = ProtocolError("short response: " + line)
return
@@ -224,15 +229,20 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err os.
return
}
-// ReadResponse reads a multi-line response of the form
+// ReadResponse reads a multi-line response of the form:
+//
// code-message line 1
// code-message line 2
// ...
// code message line n
-// where code is a 3-digit status code. Each line should have the same code.
-// The response is terminated by a line that uses a space between the code and
-// the message line rather than a dash. Each line in message is separated by
-// a newline (\n).
+//
+// where code is a 3-digit status code. The first line starts with the
+// code and a hyphen. The response is terminated by a line that starts
+// with the same code followed by a space. Each line in message is
+// separated by a newline (\n).
+//
+// See page 36 of RFC 959 (http://www.ietf.org/rfc/rfc959.txt) for
+// details.
//
// If the prefix of the status does not match the digits in expectCode,
// ReadResponse returns with err set to &Error{code, message}.
@@ -244,11 +254,18 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err os.
func (r *Reader) ReadResponse(expectCode int) (code int, message string, err os.Error) {
code, continued, message, err := r.readCodeLine(expectCode)
for err == nil && continued {
+ line, err := r.ReadLine()
+ if err != nil {
+ return 0, "", err
+ }
+
var code2 int
var moreMessage string
- code2, continued, moreMessage, err = r.readCodeLine(expectCode)
- if code != code2 {
- err = ProtocolError("status code mismatch: " + strconv.Itoa(code) + ", " + strconv.Itoa(code2))
+ code2, continued, moreMessage, err = parseCodeLine(line, expectCode)
+ if err != nil || code2 != code {
+ message += "\n" + strings.TrimRight(line, "\r\n")
+ continued = true
+ continue
}
message += "\n" + moreMessage
}
diff --git a/libgo/go/net/textproto/reader_test.go b/libgo/go/net/textproto/reader_test.go
index 0658e58b82d..23ebc3f61e8 100644
--- a/libgo/go/net/textproto/reader_test.go
+++ b/libgo/go/net/textproto/reader_test.go
@@ -138,3 +138,56 @@ func TestReadMIMEHeader(t *testing.T) {
t.Fatalf("ReadMIMEHeader: %v, %v; want %v", m, err, want)
}
}
+
+type readResponseTest struct {
+ in string
+ inCode int
+ wantCode int
+ wantMsg string
+}
+
+var readResponseTests = []readResponseTest{
+ {"230-Anonymous access granted, restrictions apply\n" +
+ "Read the file README.txt,\n" +
+ "230 please",
+ 23,
+ 230,
+ "Anonymous access granted, restrictions apply\nRead the file README.txt,\n please",
+ },
+
+ {"230 Anonymous access granted, restrictions apply\n",
+ 23,
+ 230,
+ "Anonymous access granted, restrictions apply",
+ },
+
+ {"400-A\n400-B\n400 C",
+ 4,
+ 400,
+ "A\nB\nC",
+ },
+
+ {"400-A\r\n400-B\r\n400 C\r\n",
+ 4,
+ 400,
+ "A\nB\nC",
+ },
+}
+
+// See http://www.ietf.org/rfc/rfc959.txt page 36.
+func TestRFC959Lines(t *testing.T) {
+ for i, tt := range readResponseTests {
+ r := reader(tt.in + "\nFOLLOWING DATA")
+ code, msg, err := r.ReadResponse(tt.inCode)
+ if err != nil {
+ t.Errorf("#%d: ReadResponse: %v", i, err)
+ continue
+ }
+ if code != tt.wantCode {
+ t.Errorf("#%d: code=%d, want %d", i, code, tt.wantCode)
+ }
+ if msg != tt.wantMsg {
+ t.Errorf("%#d: msg=%q, want %q", i, msg, tt.wantMsg)
+ }
+ }
+}
diff --git a/libgo/go/net/udpsock_plan9.go b/libgo/go/net/udpsock_plan9.go
index bb7196041a4..d5c6ccb9046 100644
--- a/libgo/go/net/udpsock_plan9.go
+++ b/libgo/go/net/udpsock_plan9.go
@@ -169,17 +169,18 @@ func ListenUDP(net string, laddr *UDPAddr) (c *UDPConn, err os.Error) {
return &UDPConn{*l.plan9Conn()}, nil
}
-// JoinGroup joins the IPv4 multicast group named by addr.
-// The UDPConn must use the "udp4" network.
-func (c *UDPConn) JoinGroup(addr IP) os.Error {
+// JoinGroup joins the IP multicast group named by addr on ifi,
+// which specifies the interface to join. JoinGroup uses the
+// default multicast interface if ifi is nil.
+func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) os.Error {
if !c.ok() {
return os.EINVAL
}
return os.EPLAN9
}
-// LeaveGroup exits the IPv4 multicast group named by addr.
-func (c *UDPConn) LeaveGroup(addr IP) os.Error {
+// LeaveGroup exits the IP multicast group named by addr on ifi.
+func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) os.Error {
if !c.ok() {
return os.EINVAL
}
diff --git a/libgo/go/net/udpsock_posix.go b/libgo/go/net/udpsock_posix.go
index d4ea056f3c7..06298ee40c8 100644
--- a/libgo/go/net/udpsock_posix.go
+++ b/libgo/go/net/udpsock_posix.go
@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
// UDP sockets
package net
import (
+ "bytes"
"os"
"syscall"
)
@@ -22,7 +25,7 @@ func sockaddrToUDP(sa syscall.Sockaddr) Addr {
}
func (a *UDPAddr) family() int {
- if a == nil || len(a.IP) <= 4 {
+ if a == nil || len(a.IP) <= IPv4len {
return syscall.AF_INET
}
if a.IP.To4() != nil {
@@ -252,43 +255,94 @@ func (c *UDPConn) BindToDevice(device string) os.Error {
// Closing c does not affect f, and closing f does not affect c.
func (c *UDPConn) File() (f *os.File, err os.Error) { return c.fd.dup() }
-var errInvalidMulticast = os.NewError("invalid IPv4 multicast address")
+// JoinGroup joins the IP multicast group named by addr on ifi,
+// which specifies the interface to join. JoinGroup uses the
+// default multicast interface if ifi is nil.
+func (c *UDPConn) JoinGroup(ifi *Interface, addr IP) os.Error {
+ if !c.ok() {
+ return os.EINVAL
+ }
+ ip := addr.To4()
+ if ip != nil {
+ return joinIPv4GroupUDP(c, ifi, ip)
+ }
+ return joinIPv6GroupUDP(c, ifi, addr)
+}
-// JoinGroup joins the IPv4 multicast group named by addr.
-// The UDPConn must use the "udp4" network.
-func (c *UDPConn) JoinGroup(addr IP) os.Error {
+// LeaveGroup exits the IP multicast group named by addr on ifi.
+func (c *UDPConn) LeaveGroup(ifi *Interface, addr IP) os.Error {
if !c.ok() {
return os.EINVAL
}
ip := addr.To4()
- if ip == nil {
- return &OpError{"joingroup", "udp", &IPAddr{ip}, errInvalidMulticast}
+ if ip != nil {
+ return leaveIPv4GroupUDP(c, ifi, ip)
}
- mreq := &syscall.IPMreq{
- Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
+ return leaveIPv6GroupUDP(c, ifi, addr)
+}
+
+func joinIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) os.Error {
+ mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+ if err := setIPv4InterfaceToJoin(mreq, ifi); err != nil {
+ return &OpError{"joinipv4group", "udp", &IPAddr{ip}, err}
}
- err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq))
- if err != nil {
- return &OpError{"joingroup", "udp", &IPAddr{ip}, err}
+ if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_ADD_MEMBERSHIP, mreq)); err != nil {
+ return &OpError{"joinipv4group", "udp", &IPAddr{ip}, err}
}
return nil
}
-// LeaveGroup exits the IPv4 multicast group named by addr.
-func (c *UDPConn) LeaveGroup(addr IP) os.Error {
- if !c.ok() {
- return os.EINVAL
+func leaveIPv4GroupUDP(c *UDPConn, ifi *Interface, ip IP) os.Error {
+ mreq := &syscall.IPMreq{Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]}}
+ if err := setIPv4InterfaceToJoin(mreq, ifi); err != nil {
+ return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
}
- ip := addr.To4()
- if ip == nil {
- return &OpError{"leavegroup", "udp", &IPAddr{ip}, errInvalidMulticast}
+ if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq)); err != nil {
+ return &OpError{"leaveipv4group", "udp", &IPAddr{ip}, err}
}
- mreq := &syscall.IPMreq{
- Multiaddr: [4]byte{ip[0], ip[1], ip[2], ip[3]},
+ return nil
+}
+
+func setIPv4InterfaceToJoin(mreq *syscall.IPMreq, ifi *Interface) os.Error {
+ if ifi == nil {
+ return nil
}
- err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPMreq(c.fd.sysfd, syscall.IPPROTO_IP, syscall.IP_DROP_MEMBERSHIP, mreq))
+ ifat, err := ifi.Addrs()
if err != nil {
- return &OpError{"leavegroup", "udp", &IPAddr{ip}, err}
+ return err
+ }
+ for _, ifa := range ifat {
+ if x := ifa.(*IPAddr).IP.To4(); x != nil {
+ copy(mreq.Interface[:], x)
+ break
+ }
+ }
+ if bytes.Equal(mreq.Multiaddr[:], IPv4zero) {
+ return os.EINVAL
+ }
+ return nil
+}
+
+func joinIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) os.Error {
+ mreq := &syscall.IPv6Mreq{}
+ copy(mreq.Multiaddr[:], ip)
+ if ifi != nil {
+ mreq.Interface = uint32(ifi.Index)
+ }
+ if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(c.fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_JOIN_GROUP, mreq)); err != nil {
+ return &OpError{"joinipv6group", "udp", &IPAddr{ip}, err}
+ }
+ return nil
+}
+
+func leaveIPv6GroupUDP(c *UDPConn, ifi *Interface, ip IP) os.Error {
+ mreq := &syscall.IPv6Mreq{}
+ copy(mreq.Multiaddr[:], ip)
+ if ifi != nil {
+ mreq.Interface = uint32(ifi.Index)
+ }
+ if err := os.NewSyscallError("setsockopt", syscall.SetsockoptIPv6Mreq(c.fd.sysfd, syscall.IPPROTO_IPV6, syscall.IPV6_LEAVE_GROUP, mreq)); err != nil {
+ return &OpError{"leaveipv6group", "udp", &IPAddr{ip}, err}
}
return nil
}
diff --git a/libgo/go/net/unixsock_posix.go b/libgo/go/net/unixsock_posix.go
index 38c6fe9eb1e..fccf0189c05 100644
--- a/libgo/go/net/unixsock_posix.go
+++ b/libgo/go/net/unixsock_posix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
// Unix domain sockets
package net
diff --git a/libgo/go/netchan/export.go b/libgo/go/netchan/export.go
deleted file mode 100644
index 7df73651536..00000000000
--- a/libgo/go/netchan/export.go
+++ /dev/null
@@ -1,400 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
- Package netchan implements type-safe networked channels:
- it allows the two ends of a channel to appear on different
- computers connected by a network. It does this by transporting
- data sent to a channel on one machine so it can be recovered
- by a receive of a channel of the same type on the other.
-
- An exporter publishes a set of channels by name. An importer
- connects to the exporting machine and imports the channels
- by name. After importing the channels, the two machines can
- use the channels in the usual way.
-
- Networked channels are not synchronized; they always behave
- as if they are buffered channels of at least one element.
-*/
-package netchan
-
-// BUG: can't use range clause to receive when using ImportNValues to limit the count.
-
-import (
- "log"
- "io"
- "net"
- "os"
- "reflect"
- "strconv"
- "sync"
-)
-
-// Export
-
-// expLog is a logging convenience function. The first argument must be a string.
-func expLog(args ...interface{}) {
- args[0] = "netchan export: " + args[0].(string)
- log.Print(args...)
-}
-
-// An Exporter allows a set of channels to be published on a single
-// network port. A single machine may have multiple Exporters
-// but they must use different ports.
-type Exporter struct {
- *clientSet
-}
-
-type expClient struct {
- *encDec
- exp *Exporter
- chans map[int]*netChan // channels in use by client
- mu sync.Mutex // protects remaining fields
- errored bool // client has been sent an error
- seqNum int64 // sequences messages sent to client; has value of highest sent
- ackNum int64 // highest sequence number acknowledged
- seqLock sync.Mutex // guarantees messages are in sequence, only locked under mu
-}
-
-func newClient(exp *Exporter, conn io.ReadWriter) *expClient {
- client := new(expClient)
- client.exp = exp
- client.encDec = newEncDec(conn)
- client.seqNum = 0
- client.ackNum = 0
- client.chans = make(map[int]*netChan)
- return client
-}
-
-func (client *expClient) sendError(hdr *header, err string) {
- error := &error{err}
- expLog("sending error to client:", error.Error)
- client.encode(hdr, payError, error) // ignore any encode error, hope client gets it
- client.mu.Lock()
- client.errored = true
- client.mu.Unlock()
-}
-
-func (client *expClient) newChan(hdr *header, dir Dir, name string, size int, count int64) *netChan {
- exp := client.exp
- exp.mu.Lock()
- ech, ok := exp.names[name]
- exp.mu.Unlock()
- if !ok {
- client.sendError(hdr, "no such channel: "+name)
- return nil
- }
- if ech.dir != dir {
- client.sendError(hdr, "wrong direction for channel: "+name)
- return nil
- }
- nch := newNetChan(name, hdr.Id, ech, client.encDec, size, count)
- client.chans[hdr.Id] = nch
- return nch
-}
-
-func (client *expClient) getChan(hdr *header, dir Dir) *netChan {
- nch := client.chans[hdr.Id]
- if nch == nil {
- return nil
- }
- if nch.dir != dir {
- client.sendError(hdr, "wrong direction for channel: "+nch.name)
- }
- return nch
-}
-
-// The function run manages sends and receives for a single client. For each
-// (client Recv) request, this will launch a serveRecv goroutine to deliver
-// the data for that channel, while (client Send) requests are handled as
-// data arrives from the client.
-func (client *expClient) run() {
- hdr := new(header)
- hdrValue := reflect.ValueOf(hdr)
- req := new(request)
- reqValue := reflect.ValueOf(req)
- error := new(error)
- for {
- *hdr = header{}
- if err := client.decode(hdrValue); err != nil {
- if err != os.EOF {
- expLog("error decoding client header:", err)
- }
- break
- }
- switch hdr.PayloadType {
- case payRequest:
- *req = request{}
- if err := client.decode(reqValue); err != nil {
- expLog("error decoding client request:", err)
- break
- }
- if req.Size < 1 {
- panic("netchan: remote requested " + strconv.Itoa(req.Size) + " values")
- }
- switch req.Dir {
- case Recv:
- // look up channel before calling serveRecv to
- // avoid a lock around client.chans.
- if nch := client.newChan(hdr, Send, req.Name, req.Size, req.Count); nch != nil {
- go client.serveRecv(nch, *hdr, req.Count)
- }
- case Send:
- client.newChan(hdr, Recv, req.Name, req.Size, req.Count)
- // The actual sends will have payload type payData.
- // TODO: manage the count?
- default:
- error.Error = "request: can't handle channel direction"
- expLog(error.Error, req.Dir)
- client.encode(hdr, payError, error)
- }
- case payData:
- client.serveSend(*hdr)
- case payClosed:
- client.serveClosed(*hdr)
- case payAck:
- client.mu.Lock()
- if client.ackNum != hdr.SeqNum-1 {
- // Since the sequence number is incremented and the message is sent
- // in a single instance of locking client.mu, the messages are guaranteed
- // to be sent in order. Therefore receipt of acknowledgement N means
- // all messages <=N have been seen by the recipient. We check anyway.
- expLog("sequence out of order:", client.ackNum, hdr.SeqNum)
- }
- if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count.
- client.ackNum = hdr.SeqNum
- }
- client.mu.Unlock()
- case payAckSend:
- if nch := client.getChan(hdr, Send); nch != nil {
- nch.acked()
- }
- default:
- log.Fatal("netchan export: unknown payload type", hdr.PayloadType)
- }
- }
- client.exp.delClient(client)
-}
-
-// Send all the data on a single channel to a client asking for a Recv.
-// The header is passed by value to avoid issues of overwriting.
-func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) {
- for {
- val, ok := nch.recv()
- if !ok {
- if err := client.encode(&hdr, payClosed, nil); err != nil {
- expLog("error encoding server closed message:", err)
- }
- break
- }
- // We hold the lock during transmission to guarantee messages are
- // sent in sequence number order. Also, we increment first so the
- // value of client.SeqNum is the value of the highest used sequence
- // number, not one beyond.
- client.mu.Lock()
- client.seqNum++
- hdr.SeqNum = client.seqNum
- client.seqLock.Lock() // guarantee ordering of messages
- client.mu.Unlock()
- err := client.encode(&hdr, payData, val.Interface())
- client.seqLock.Unlock()
- if err != nil {
- expLog("error encoding client response:", err)
- client.sendError(&hdr, err.String())
- break
- }
- // Negative count means run forever.
- if count >= 0 {
- if count--; count <= 0 {
- break
- }
- }
- }
-}
-
-// Receive and deliver locally one item from a client asking for a Send
-// The header is passed by value to avoid issues of overwriting.
-func (client *expClient) serveSend(hdr header) {
- nch := client.getChan(&hdr, Recv)
- if nch == nil {
- return
- }
- // Create a new value for each received item.
- val := reflect.New(nch.ch.Type().Elem()).Elem()
- if err := client.decode(val); err != nil {
- expLog("value decode:", err, "; type ", nch.ch.Type())
- return
- }
- nch.send(val)
-}
-
-// Report that client has closed the channel that is sending to us.
-// The header is passed by value to avoid issues of overwriting.
-func (client *expClient) serveClosed(hdr header) {
- nch := client.getChan(&hdr, Recv)
- if nch == nil {
- return
- }
- nch.close()
-}
-
-func (client *expClient) unackedCount() int64 {
- client.mu.Lock()
- n := client.seqNum - client.ackNum
- client.mu.Unlock()
- return n
-}
-
-func (client *expClient) seq() int64 {
- client.mu.Lock()
- n := client.seqNum
- client.mu.Unlock()
- return n
-}
-
-func (client *expClient) ack() int64 {
- client.mu.Lock()
- n := client.seqNum
- client.mu.Unlock()
- return n
-}
-
-// Serve waits for incoming connections on the listener
-// and serves the Exporter's channels on each.
-// It blocks until the listener is closed.
-func (exp *Exporter) Serve(listener net.Listener) {
- for {
- conn, err := listener.Accept()
- if err != nil {
- expLog("listen:", err)
- break
- }
- go exp.ServeConn(conn)
- }
-}
-
-// ServeConn exports the Exporter's channels on conn.
-// It blocks until the connection is terminated.
-func (exp *Exporter) ServeConn(conn io.ReadWriter) {
- exp.addClient(conn).run()
-}
-
-// NewExporter creates a new Exporter that exports a set of channels.
-func NewExporter() *Exporter {
- e := &Exporter{
- clientSet: &clientSet{
- names: make(map[string]*chanDir),
- clients: make(map[unackedCounter]bool),
- },
- }
- return e
-}
-
-// ListenAndServe exports the exporter's channels through the
-// given network and local address defined as in net.Listen.
-func (exp *Exporter) ListenAndServe(network, localaddr string) os.Error {
- listener, err := net.Listen(network, localaddr)
- if err != nil {
- return err
- }
- go exp.Serve(listener)
- return nil
-}
-
-// addClient creates a new expClient and records its existence
-func (exp *Exporter) addClient(conn io.ReadWriter) *expClient {
- client := newClient(exp, conn)
- exp.mu.Lock()
- exp.clients[client] = true
- exp.mu.Unlock()
- return client
-}
-
-// delClient forgets the client existed
-func (exp *Exporter) delClient(client *expClient) {
- exp.mu.Lock()
- exp.clients[client] = false, false
- exp.mu.Unlock()
-}
-
-// Drain waits until all messages sent from this exporter/importer, including
-// those not yet sent to any client and possibly including those sent while
-// Drain was executing, have been received by the importer. In short, it
-// waits until all the exporter's messages have been received by a client.
-// If the timeout (measured in nanoseconds) is positive and Drain takes
-// longer than that to complete, an error is returned.
-func (exp *Exporter) Drain(timeout int64) os.Error {
- // This wrapper function is here so the method's comment will appear in godoc.
- return exp.clientSet.drain(timeout)
-}
-
-// Sync waits until all clients of the exporter have received the messages
-// that were sent at the time Sync was invoked. Unlike Drain, it does not
-// wait for messages sent while it is running or messages that have not been
-// dispatched to any client. If the timeout (measured in nanoseconds) is
-// positive and Sync takes longer than that to complete, an error is
-// returned.
-func (exp *Exporter) Sync(timeout int64) os.Error {
- // This wrapper function is here so the method's comment will appear in godoc.
- return exp.clientSet.sync(timeout)
-}
-
-func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
- chanType := reflect.TypeOf(chT)
- if chanType.Kind() != reflect.Chan {
- return reflect.Value{}, os.NewError("not a channel")
- }
- if dir != Send && dir != Recv {
- return reflect.Value{}, os.NewError("unknown channel direction")
- }
- switch chanType.ChanDir() {
- case reflect.BothDir:
- case reflect.SendDir:
- if dir != Recv {
- return reflect.Value{}, os.NewError("to import/export with Send, must provide <-chan")
- }
- case reflect.RecvDir:
- if dir != Send {
- return reflect.Value{}, os.NewError("to import/export with Recv, must provide chan<-")
- }
- }
- return reflect.ValueOf(chT), nil
-}
-
-// Export exports a channel of a given type and specified direction. The
-// channel to be exported is provided in the call and may be of arbitrary
-// channel type.
-// Despite the literal signature, the effective signature is
-// Export(name string, chT chan T, dir Dir)
-func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error {
- ch, err := checkChan(chT, dir)
- if err != nil {
- return err
- }
- exp.mu.Lock()
- defer exp.mu.Unlock()
- _, present := exp.names[name]
- if present {
- return os.NewError("channel name already being exported:" + name)
- }
- exp.names[name] = &chanDir{ch, dir}
- return nil
-}
-
-// Hangup disassociates the named channel from the Exporter and closes
-// the channel. Messages in flight for the channel may be dropped.
-func (exp *Exporter) Hangup(name string) os.Error {
- exp.mu.Lock()
- chDir, ok := exp.names[name]
- if ok {
- exp.names[name] = nil, false
- }
- // TODO drop all instances of channel from client sets
- exp.mu.Unlock()
- if !ok {
- return os.NewError("netchan export: hangup: no such channel: " + name)
- }
- chDir.ch.Close()
- return nil
-}
diff --git a/libgo/go/netchan/import.go b/libgo/go/netchan/import.go
deleted file mode 100644
index ec17d97774b..00000000000
--- a/libgo/go/netchan/import.go
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package netchan
-
-import (
- "io"
- "log"
- "net"
- "os"
- "reflect"
- "sync"
- "time"
-)
-
-// Import
-
-// impLog is a logging convenience function. The first argument must be a string.
-func impLog(args ...interface{}) {
- args[0] = "netchan import: " + args[0].(string)
- log.Print(args...)
-}
-
-// An Importer allows a set of channels to be imported from a single
-// remote machine/network port. A machine may have multiple
-// importers, even from the same machine/network port.
-type Importer struct {
- *encDec
- chanLock sync.Mutex // protects access to channel map
- names map[string]*netChan
- chans map[int]*netChan
- errors chan os.Error
- maxId int
- mu sync.Mutex // protects remaining fields
- unacked int64 // number of unacknowledged sends.
- seqLock sync.Mutex // guarantees messages are in sequence, only locked under mu
-}
-
-// NewImporter creates a new Importer object to import a set of channels
-// from the given connection. The Exporter must be available and serving when
-// the Importer is created.
-func NewImporter(conn io.ReadWriter) *Importer {
- imp := new(Importer)
- imp.encDec = newEncDec(conn)
- imp.chans = make(map[int]*netChan)
- imp.names = make(map[string]*netChan)
- imp.errors = make(chan os.Error, 10)
- imp.unacked = 0
- go imp.run()
- return imp
-}
-
-// Import imports a set of channels from the given network and address.
-func Import(network, remoteaddr string) (*Importer, os.Error) {
- conn, err := net.Dial(network, remoteaddr)
- if err != nil {
- return nil, err
- }
- return NewImporter(conn), nil
-}
-
-// shutdown closes all channels for which we are receiving data from the remote side.
-func (imp *Importer) shutdown() {
- imp.chanLock.Lock()
- for _, ich := range imp.chans {
- if ich.dir == Recv {
- ich.close()
- }
- }
- imp.chanLock.Unlock()
-}
-
-// Handle the data from a single imported data stream, which will
-// have the form
-// (response, data)*
-// The response identifies by name which channel is transmitting data.
-func (imp *Importer) run() {
- // Loop on responses; requests are sent by ImportNValues()
- hdr := new(header)
- hdrValue := reflect.ValueOf(hdr)
- ackHdr := new(header)
- err := new(error)
- errValue := reflect.ValueOf(err)
- for {
- *hdr = header{}
- if e := imp.decode(hdrValue); e != nil {
- if e != os.EOF {
- impLog("header:", e)
- imp.shutdown()
- }
- return
- }
- switch hdr.PayloadType {
- case payData:
- // done lower in loop
- case payError:
- if e := imp.decode(errValue); e != nil {
- impLog("error:", e)
- return
- }
- if err.Error != "" {
- impLog("response error:", err.Error)
- select {
- case imp.errors <- os.NewError(err.Error):
- continue // errors are not acknowledged
- default:
- imp.shutdown()
- return
- }
- }
- case payClosed:
- nch := imp.getChan(hdr.Id, false)
- if nch != nil {
- nch.close()
- }
- continue // closes are not acknowledged.
- case payAckSend:
- // we can receive spurious acks if the channel is
- // hung up, so we ask getChan to ignore any errors.
- nch := imp.getChan(hdr.Id, true)
- if nch != nil {
- nch.acked()
- imp.mu.Lock()
- imp.unacked--
- imp.mu.Unlock()
- }
- continue
- default:
- impLog("unexpected payload type:", hdr.PayloadType)
- return
- }
- nch := imp.getChan(hdr.Id, false)
- if nch == nil {
- continue
- }
- if nch.dir != Recv {
- impLog("cannot happen: receive from non-Recv channel")
- return
- }
- // Acknowledge receipt
- ackHdr.Id = hdr.Id
- ackHdr.SeqNum = hdr.SeqNum
- imp.encode(ackHdr, payAck, nil)
- // Create a new value for each received item.
- value := reflect.New(nch.ch.Type().Elem()).Elem()
- if e := imp.decode(value); e != nil {
- impLog("importer value decode:", e)
- return
- }
- nch.send(value)
- }
-}
-
-func (imp *Importer) getChan(id int, errOk bool) *netChan {
- imp.chanLock.Lock()
- ich := imp.chans[id]
- imp.chanLock.Unlock()
- if ich == nil {
- if !errOk {
- impLog("unknown id in netchan request: ", id)
- }
- return nil
- }
- return ich
-}
-
-// Errors returns a channel from which transmission and protocol errors
-// can be read. Clients of the importer are not required to read the error
-// channel for correct execution. However, if too many errors occur
-// without being read from the error channel, the importer will shut down.
-func (imp *Importer) Errors() chan os.Error {
- return imp.errors
-}
-
-// Import imports a channel of the given type, size and specified direction.
-// It is equivalent to ImportNValues with a count of -1, meaning unbounded.
-func (imp *Importer) Import(name string, chT interface{}, dir Dir, size int) os.Error {
- return imp.ImportNValues(name, chT, dir, size, -1)
-}
-
-// ImportNValues imports a channel of the given type and specified
-// direction and then receives or transmits up to n values on that
-// channel. A value of n==-1 implies an unbounded number of values. The
-// channel will have buffer space for size values, or 1 value if size < 1.
-// The channel to be bound to the remote site's channel is provided
-// in the call and may be of arbitrary channel type.
-// Despite the literal signature, the effective signature is
-// ImportNValues(name string, chT chan T, dir Dir, size, n int) os.Error
-// Example usage:
-// imp, err := NewImporter("tcp", "netchanserver.mydomain.com:1234")
-// if err != nil { log.Fatal(err) }
-// ch := make(chan myType)
-// err = imp.ImportNValues("name", ch, Recv, 1, 1)
-// if err != nil { log.Fatal(err) }
-// fmt.Printf("%+v\n", <-ch)
-func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, size, n int) os.Error {
- ch, err := checkChan(chT, dir)
- if err != nil {
- return err
- }
- imp.chanLock.Lock()
- defer imp.chanLock.Unlock()
- _, present := imp.names[name]
- if present {
- return os.NewError("channel name already being imported:" + name)
- }
- if size < 1 {
- size = 1
- }
- id := imp.maxId
- imp.maxId++
- nch := newNetChan(name, id, &chanDir{ch, dir}, imp.encDec, size, int64(n))
- imp.names[name] = nch
- imp.chans[id] = nch
- // Tell the other side about this channel.
- hdr := &header{Id: id}
- req := &request{Name: name, Count: int64(n), Dir: dir, Size: size}
- if err = imp.encode(hdr, payRequest, req); err != nil {
- impLog("request encode:", err)
- return err
- }
- if dir == Send {
- go func() {
- for i := 0; n == -1 || i < n; i++ {
- val, ok := nch.recv()
- if !ok {
- if err = imp.encode(hdr, payClosed, nil); err != nil {
- impLog("error encoding client closed message:", err)
- }
- return
- }
- // We hold the lock during transmission to guarantee messages are
- // sent in order.
- imp.mu.Lock()
- imp.unacked++
- imp.seqLock.Lock()
- imp.mu.Unlock()
- if err = imp.encode(hdr, payData, val.Interface()); err != nil {
- impLog("error encoding client send:", err)
- return
- }
- imp.seqLock.Unlock()
- }
- }()
- }
- return nil
-}
-
-// Hangup disassociates the named channel from the Importer and closes
-// the channel. Messages in flight for the channel may be dropped.
-func (imp *Importer) Hangup(name string) os.Error {
- imp.chanLock.Lock()
- defer imp.chanLock.Unlock()
- nc := imp.names[name]
- if nc == nil {
- return os.NewError("netchan import: hangup: no such channel: " + name)
- }
- imp.names[name] = nil, false
- imp.chans[nc.id] = nil, false
- nc.close()
- return nil
-}
-
-func (imp *Importer) unackedCount() int64 {
- imp.mu.Lock()
- n := imp.unacked
- imp.mu.Unlock()
- return n
-}
-
-// Drain waits until all messages sent from this exporter/importer, including
-// those not yet sent to any server and possibly including those sent while
-// Drain was executing, have been received by the exporter. In short, it
-// waits until all the importer's messages have been received.
-// If the timeout (measured in nanoseconds) is positive and Drain takes
-// longer than that to complete, an error is returned.
-func (imp *Importer) Drain(timeout int64) os.Error {
- startTime := time.Nanoseconds()
- for imp.unackedCount() > 0 {
- if timeout > 0 && time.Nanoseconds()-startTime >= timeout {
- return os.NewError("timeout")
- }
- time.Sleep(100 * 1e6)
- }
- return nil
-}
diff --git a/libgo/go/netchan/common.go b/libgo/go/old/netchan/common.go
index ac1ca12f5ff..ac1ca12f5ff 100644
--- a/libgo/go/netchan/common.go
+++ b/libgo/go/old/netchan/common.go
diff --git a/libgo/go/old/netchan/export.go b/libgo/go/old/netchan/export.go
new file mode 100644
index 00000000000..99d5d7e05d1
--- /dev/null
+++ b/libgo/go/old/netchan/export.go
@@ -0,0 +1,400 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+ Package netchan implements type-safe networked channels:
+ it allows the two ends of a channel to appear on different
+ computers connected by a network. It does this by transporting
+ data sent to a channel on one machine so it can be recovered
+ by a receive of a channel of the same type on the other.
+
+ An exporter publishes a set of channels by name. An importer
+ connects to the exporting machine and imports the channels
+ by name. After importing the channels, the two machines can
+ use the channels in the usual way.
+
+ Networked channels are not synchronized; they always behave
+ as if they are buffered channels of at least one element.
+*/
+package netchan
+
+// BUG: can't use range clause to receive when using ImportNValues to limit the count.
+
+import (
+ "log"
+ "io"
+ "net"
+ "os"
+ "reflect"
+ "strconv"
+ "sync"
+)
+
+// Export
+
+// expLog is a logging convenience function. The first argument must be a string.
+func expLog(args ...interface{}) {
+ args[0] = "netchan export: " + args[0].(string)
+ log.Print(args...)
+}
+
+// An Exporter allows a set of channels to be published on a single
+// network port. A single machine may have multiple Exporters
+// but they must use different ports.
+type Exporter struct {
+ *clientSet
+}
+
+type expClient struct {
+ *encDec
+ exp *Exporter
+ chans map[int]*netChan // channels in use by client
+ mu sync.Mutex // protects remaining fields
+ errored bool // client has been sent an error
+ seqNum int64 // sequences messages sent to client; has value of highest sent
+ ackNum int64 // highest sequence number acknowledged
+ seqLock sync.Mutex // guarantees messages are in sequence, only locked under mu
+}
+
+func newClient(exp *Exporter, conn io.ReadWriter) *expClient {
+ client := new(expClient)
+ client.exp = exp
+ client.encDec = newEncDec(conn)
+ client.seqNum = 0
+ client.ackNum = 0
+ client.chans = make(map[int]*netChan)
+ return client
+}
+
+func (client *expClient) sendError(hdr *header, err string) {
+ error := &error{err}
+ expLog("sending error to client:", error.Error)
+ client.encode(hdr, payError, error) // ignore any encode error, hope client gets it
+ client.mu.Lock()
+ client.errored = true
+ client.mu.Unlock()
+}
+
+func (client *expClient) newChan(hdr *header, dir Dir, name string, size int, count int64) *netChan {
+ exp := client.exp
+ exp.mu.Lock()
+ ech, ok := exp.names[name]
+ exp.mu.Unlock()
+ if !ok {
+ client.sendError(hdr, "no such channel: "+name)
+ return nil
+ }
+ if ech.dir != dir {
+ client.sendError(hdr, "wrong direction for channel: "+name)
+ return nil
+ }
+ nch := newNetChan(name, hdr.Id, ech, client.encDec, size, count)
+ client.chans[hdr.Id] = nch
+ return nch
+}
+
+func (client *expClient) getChan(hdr *header, dir Dir) *netChan {
+ nch := client.chans[hdr.Id]
+ if nch == nil {
+ return nil
+ }
+ if nch.dir != dir {
+ client.sendError(hdr, "wrong direction for channel: "+nch.name)
+ }
+ return nch
+}
+
+// The function run manages sends and receives for a single client. For each
+// (client Recv) request, this will launch a serveRecv goroutine to deliver
+// the data for that channel, while (client Send) requests are handled as
+// data arrives from the client.
+func (client *expClient) run() {
+ hdr := new(header)
+ hdrValue := reflect.ValueOf(hdr)
+ req := new(request)
+ reqValue := reflect.ValueOf(req)
+ error := new(error)
+ for {
+ *hdr = header{}
+ if err := client.decode(hdrValue); err != nil {
+ if err != os.EOF {
+ expLog("error decoding client header:", err)
+ }
+ break
+ }
+ switch hdr.PayloadType {
+ case payRequest:
+ *req = request{}
+ if err := client.decode(reqValue); err != nil {
+ expLog("error decoding client request:", err)
+ break
+ }
+ if req.Size < 1 {
+ panic("netchan: remote requested " + strconv.Itoa(req.Size) + " values")
+ }
+ switch req.Dir {
+ case Recv:
+ // look up channel before calling serveRecv to
+ // avoid a lock around client.chans.
+ if nch := client.newChan(hdr, Send, req.Name, req.Size, req.Count); nch != nil {
+ go client.serveRecv(nch, *hdr, req.Count)
+ }
+ case Send:
+ client.newChan(hdr, Recv, req.Name, req.Size, req.Count)
+ // The actual sends will have payload type payData.
+ // TODO: manage the count?
+ default:
+ error.Error = "request: can't handle channel direction"
+ expLog(error.Error, req.Dir)
+ client.encode(hdr, payError, error)
+ }
+ case payData:
+ client.serveSend(*hdr)
+ case payClosed:
+ client.serveClosed(*hdr)
+ case payAck:
+ client.mu.Lock()
+ if client.ackNum != hdr.SeqNum-1 {
+ // Since the sequence number is incremented and the message is sent
+ // in a single instance of locking client.mu, the messages are guaranteed
+ // to be sent in order. Therefore receipt of acknowledgement N means
+ // all messages <=N have been seen by the recipient. We check anyway.
+ expLog("sequence out of order:", client.ackNum, hdr.SeqNum)
+ }
+ if client.ackNum < hdr.SeqNum { // If there has been an error, don't back up the count.
+ client.ackNum = hdr.SeqNum
+ }
+ client.mu.Unlock()
+ case payAckSend:
+ if nch := client.getChan(hdr, Send); nch != nil {
+ nch.acked()
+ }
+ default:
+ log.Fatal("netchan export: unknown payload type", hdr.PayloadType)
+ }
+ }
+ client.exp.delClient(client)
+}
+
+// Send all the data on a single channel to a client asking for a Recv.
+// The header is passed by value to avoid issues of overwriting.
+func (client *expClient) serveRecv(nch *netChan, hdr header, count int64) {
+ for {
+ val, ok := nch.recv()
+ if !ok {
+ if err := client.encode(&hdr, payClosed, nil); err != nil {
+ expLog("error encoding server closed message:", err)
+ }
+ break
+ }
+ // We hold the lock during transmission to guarantee messages are
+ // sent in sequence number order. Also, we increment first so the
+ // value of client.SeqNum is the value of the highest used sequence
+ // number, not one beyond.
+ client.mu.Lock()
+ client.seqNum++
+ hdr.SeqNum = client.seqNum
+ client.seqLock.Lock() // guarantee ordering of messages
+ client.mu.Unlock()
+ err := client.encode(&hdr, payData, val.Interface())
+ client.seqLock.Unlock()
+ if err != nil {
+ expLog("error encoding client response:", err)
+ client.sendError(&hdr, err.String())
+ break
+ }
+ // Negative count means run forever.
+ if count >= 0 {
+ if count--; count <= 0 {
+ break
+ }
+ }
+ }
+}
+
+// Receive and deliver locally one item from a client asking for a Send
+// The header is passed by value to avoid issues of overwriting.
+func (client *expClient) serveSend(hdr header) {
+ nch := client.getChan(&hdr, Recv)
+ if nch == nil {
+ return
+ }
+ // Create a new value for each received item.
+ val := reflect.New(nch.ch.Type().Elem()).Elem()
+ if err := client.decode(val); err != nil {
+ expLog("value decode:", err, "; type ", nch.ch.Type())
+ return
+ }
+ nch.send(val)
+}
+
+// Report that client has closed the channel that is sending to us.
+// The header is passed by value to avoid issues of overwriting.
+func (client *expClient) serveClosed(hdr header) {
+ nch := client.getChan(&hdr, Recv)
+ if nch == nil {
+ return
+ }
+ nch.close()
+}
+
+func (client *expClient) unackedCount() int64 {
+ client.mu.Lock()
+ n := client.seqNum - client.ackNum
+ client.mu.Unlock()
+ return n
+}
+
+func (client *expClient) seq() int64 {
+ client.mu.Lock()
+ n := client.seqNum
+ client.mu.Unlock()
+ return n
+}
+
+func (client *expClient) ack() int64 {
+ client.mu.Lock()
+ n := client.seqNum
+ client.mu.Unlock()
+ return n
+}
+
+// Serve waits for incoming connections on the listener
+// and serves the Exporter's channels on each.
+// It blocks until the listener is closed.
+func (exp *Exporter) Serve(listener net.Listener) {
+ for {
+ conn, err := listener.Accept()
+ if err != nil {
+ expLog("listen:", err)
+ break
+ }
+ go exp.ServeConn(conn)
+ }
+}
+
+// ServeConn exports the Exporter's channels on conn.
+// It blocks until the connection is terminated.
+func (exp *Exporter) ServeConn(conn io.ReadWriter) {
+ exp.addClient(conn).run()
+}
+
+// NewExporter creates a new Exporter that exports a set of channels.
+func NewExporter() *Exporter {
+ e := &Exporter{
+ clientSet: &clientSet{
+ names: make(map[string]*chanDir),
+ clients: make(map[unackedCounter]bool),
+ },
+ }
+ return e
+}
+
+// ListenAndServe exports the exporter's channels through the
+// given network and local address defined as in net.Listen.
+func (exp *Exporter) ListenAndServe(network, localaddr string) os.Error {
+ listener, err := net.Listen(network, localaddr)
+ if err != nil {
+ return err
+ }
+ go exp.Serve(listener)
+ return nil
+}
+
+// addClient creates a new expClient and records its existence
+func (exp *Exporter) addClient(conn io.ReadWriter) *expClient {
+ client := newClient(exp, conn)
+ exp.mu.Lock()
+ exp.clients[client] = true
+ exp.mu.Unlock()
+ return client
+}
+
+// delClient forgets the client existed
+func (exp *Exporter) delClient(client *expClient) {
+ exp.mu.Lock()
+ delete(exp.clients, client)
+ exp.mu.Unlock()
+}
+
+// Drain waits until all messages sent from this exporter/importer, including
+// those not yet sent to any client and possibly including those sent while
+// Drain was executing, have been received by the importer. In short, it
+// waits until all the exporter's messages have been received by a client.
+// If the timeout (measured in nanoseconds) is positive and Drain takes
+// longer than that to complete, an error is returned.
+func (exp *Exporter) Drain(timeout int64) os.Error {
+ // This wrapper function is here so the method's comment will appear in godoc.
+ return exp.clientSet.drain(timeout)
+}
+
+// Sync waits until all clients of the exporter have received the messages
+// that were sent at the time Sync was invoked. Unlike Drain, it does not
+// wait for messages sent while it is running or messages that have not been
+// dispatched to any client. If the timeout (measured in nanoseconds) is
+// positive and Sync takes longer than that to complete, an error is
+// returned.
+func (exp *Exporter) Sync(timeout int64) os.Error {
+ // This wrapper function is here so the method's comment will appear in godoc.
+ return exp.clientSet.sync(timeout)
+}
+
+func checkChan(chT interface{}, dir Dir) (reflect.Value, os.Error) {
+ chanType := reflect.TypeOf(chT)
+ if chanType.Kind() != reflect.Chan {
+ return reflect.Value{}, os.NewError("not a channel")
+ }
+ if dir != Send && dir != Recv {
+ return reflect.Value{}, os.NewError("unknown channel direction")
+ }
+ switch chanType.ChanDir() {
+ case reflect.BothDir:
+ case reflect.SendDir:
+ if dir != Recv {
+ return reflect.Value{}, os.NewError("to import/export with Send, must provide <-chan")
+ }
+ case reflect.RecvDir:
+ if dir != Send {
+ return reflect.Value{}, os.NewError("to import/export with Recv, must provide chan<-")
+ }
+ }
+ return reflect.ValueOf(chT), nil
+}
+
+// Export exports a channel of a given type and specified direction. The
+// channel to be exported is provided in the call and may be of arbitrary
+// channel type.
+// Despite the literal signature, the effective signature is
+// Export(name string, chT chan T, dir Dir)
+func (exp *Exporter) Export(name string, chT interface{}, dir Dir) os.Error {
+ ch, err := checkChan(chT, dir)
+ if err != nil {
+ return err
+ }
+ exp.mu.Lock()
+ defer exp.mu.Unlock()
+ _, present := exp.names[name]
+ if present {
+ return os.NewError("channel name already being exported:" + name)
+ }
+ exp.names[name] = &chanDir{ch, dir}
+ return nil
+}
+
+// Hangup disassociates the named channel from the Exporter and closes
+// the channel. Messages in flight for the channel may be dropped.
+func (exp *Exporter) Hangup(name string) os.Error {
+ exp.mu.Lock()
+ chDir, ok := exp.names[name]
+ if ok {
+ delete(exp.names, name)
+ }
+ // TODO drop all instances of channel from client sets
+ exp.mu.Unlock()
+ if !ok {
+ return os.NewError("netchan export: hangup: no such channel: " + name)
+ }
+ chDir.ch.Close()
+ return nil
+}
diff --git a/libgo/go/old/netchan/import.go b/libgo/go/old/netchan/import.go
new file mode 100644
index 00000000000..5a459e0d5ac
--- /dev/null
+++ b/libgo/go/old/netchan/import.go
@@ -0,0 +1,287 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package netchan
+
+import (
+ "io"
+ "log"
+ "net"
+ "os"
+ "reflect"
+ "sync"
+ "time"
+)
+
+// Import
+
+// impLog is a logging convenience function. The first argument must be a string.
+func impLog(args ...interface{}) {
+ args[0] = "netchan import: " + args[0].(string)
+ log.Print(args...)
+}
+
+// An Importer allows a set of channels to be imported from a single
+// remote machine/network port. A machine may have multiple
+// importers, even from the same machine/network port.
+type Importer struct {
+ *encDec
+ chanLock sync.Mutex // protects access to channel map
+ names map[string]*netChan
+ chans map[int]*netChan
+ errors chan os.Error
+ maxId int
+ mu sync.Mutex // protects remaining fields
+ unacked int64 // number of unacknowledged sends.
+ seqLock sync.Mutex // guarantees messages are in sequence, only locked under mu
+}
+
+// NewImporter creates a new Importer object to import a set of channels
+// from the given connection. The Exporter must be available and serving when
+// the Importer is created.
+func NewImporter(conn io.ReadWriter) *Importer {
+ imp := new(Importer)
+ imp.encDec = newEncDec(conn)
+ imp.chans = make(map[int]*netChan)
+ imp.names = make(map[string]*netChan)
+ imp.errors = make(chan os.Error, 10)
+ imp.unacked = 0
+ go imp.run()
+ return imp
+}
+
+// Import imports a set of channels from the given network and address.
+func Import(network, remoteaddr string) (*Importer, os.Error) {
+ conn, err := net.Dial(network, remoteaddr)
+ if err != nil {
+ return nil, err
+ }
+ return NewImporter(conn), nil
+}
+
+// shutdown closes all channels for which we are receiving data from the remote side.
+func (imp *Importer) shutdown() {
+ imp.chanLock.Lock()
+ for _, ich := range imp.chans {
+ if ich.dir == Recv {
+ ich.close()
+ }
+ }
+ imp.chanLock.Unlock()
+}
+
+// Handle the data from a single imported data stream, which will
+// have the form
+// (response, data)*
+// The response identifies by name which channel is transmitting data.
+func (imp *Importer) run() {
+ // Loop on responses; requests are sent by ImportNValues()
+ hdr := new(header)
+ hdrValue := reflect.ValueOf(hdr)
+ ackHdr := new(header)
+ err := new(error)
+ errValue := reflect.ValueOf(err)
+ for {
+ *hdr = header{}
+ if e := imp.decode(hdrValue); e != nil {
+ if e != os.EOF {
+ impLog("header:", e)
+ imp.shutdown()
+ }
+ return
+ }
+ switch hdr.PayloadType {
+ case payData:
+ // done lower in loop
+ case payError:
+ if e := imp.decode(errValue); e != nil {
+ impLog("error:", e)
+ return
+ }
+ if err.Error != "" {
+ impLog("response error:", err.Error)
+ select {
+ case imp.errors <- os.NewError(err.Error):
+ continue // errors are not acknowledged
+ default:
+ imp.shutdown()
+ return
+ }
+ }
+ case payClosed:
+ nch := imp.getChan(hdr.Id, false)
+ if nch != nil {
+ nch.close()
+ }
+ continue // closes are not acknowledged.
+ case payAckSend:
+ // we can receive spurious acks if the channel is
+ // hung up, so we ask getChan to ignore any errors.
+ nch := imp.getChan(hdr.Id, true)
+ if nch != nil {
+ nch.acked()
+ imp.mu.Lock()
+ imp.unacked--
+ imp.mu.Unlock()
+ }
+ continue
+ default:
+ impLog("unexpected payload type:", hdr.PayloadType)
+ return
+ }
+ nch := imp.getChan(hdr.Id, false)
+ if nch == nil {
+ continue
+ }
+ if nch.dir != Recv {
+ impLog("cannot happen: receive from non-Recv channel")
+ return
+ }
+ // Acknowledge receipt
+ ackHdr.Id = hdr.Id
+ ackHdr.SeqNum = hdr.SeqNum
+ imp.encode(ackHdr, payAck, nil)
+ // Create a new value for each received item.
+ value := reflect.New(nch.ch.Type().Elem()).Elem()
+ if e := imp.decode(value); e != nil {
+ impLog("importer value decode:", e)
+ return
+ }
+ nch.send(value)
+ }
+}
+
+func (imp *Importer) getChan(id int, errOk bool) *netChan {
+ imp.chanLock.Lock()
+ ich := imp.chans[id]
+ imp.chanLock.Unlock()
+ if ich == nil {
+ if !errOk {
+ impLog("unknown id in netchan request: ", id)
+ }
+ return nil
+ }
+ return ich
+}
+
+// Errors returns a channel from which transmission and protocol errors
+// can be read. Clients of the importer are not required to read the error
+// channel for correct execution. However, if too many errors occur
+// without being read from the error channel, the importer will shut down.
+func (imp *Importer) Errors() chan os.Error {
+ return imp.errors
+}
+
+// Import imports a channel of the given type, size and specified direction.
+// It is equivalent to ImportNValues with a count of -1, meaning unbounded.
+func (imp *Importer) Import(name string, chT interface{}, dir Dir, size int) os.Error {
+ return imp.ImportNValues(name, chT, dir, size, -1)
+}
+
+// ImportNValues imports a channel of the given type and specified
+// direction and then receives or transmits up to n values on that
+// channel. A value of n==-1 implies an unbounded number of values. The
+// channel will have buffer space for size values, or 1 value if size < 1.
+// The channel to be bound to the remote site's channel is provided
+// in the call and may be of arbitrary channel type.
+// Despite the literal signature, the effective signature is
+// ImportNValues(name string, chT chan T, dir Dir, size, n int) os.Error
+// Example usage:
+// imp, err := NewImporter("tcp", "netchanserver.mydomain.com:1234")
+// if err != nil { log.Fatal(err) }
+// ch := make(chan myType)
+// err = imp.ImportNValues("name", ch, Recv, 1, 1)
+// if err != nil { log.Fatal(err) }
+// fmt.Printf("%+v\n", <-ch)
+func (imp *Importer) ImportNValues(name string, chT interface{}, dir Dir, size, n int) os.Error {
+ ch, err := checkChan(chT, dir)
+ if err != nil {
+ return err
+ }
+ imp.chanLock.Lock()
+ defer imp.chanLock.Unlock()
+ _, present := imp.names[name]
+ if present {
+ return os.NewError("channel name already being imported:" + name)
+ }
+ if size < 1 {
+ size = 1
+ }
+ id := imp.maxId
+ imp.maxId++
+ nch := newNetChan(name, id, &chanDir{ch, dir}, imp.encDec, size, int64(n))
+ imp.names[name] = nch
+ imp.chans[id] = nch
+ // Tell the other side about this channel.
+ hdr := &header{Id: id}
+ req := &request{Name: name, Count: int64(n), Dir: dir, Size: size}
+ if err = imp.encode(hdr, payRequest, req); err != nil {
+ impLog("request encode:", err)
+ return err
+ }
+ if dir == Send {
+ go func() {
+ for i := 0; n == -1 || i < n; i++ {
+ val, ok := nch.recv()
+ if !ok {
+ if err = imp.encode(hdr, payClosed, nil); err != nil {
+ impLog("error encoding client closed message:", err)
+ }
+ return
+ }
+ // We hold the lock during transmission to guarantee messages are
+ // sent in order.
+ imp.mu.Lock()
+ imp.unacked++
+ imp.seqLock.Lock()
+ imp.mu.Unlock()
+ if err = imp.encode(hdr, payData, val.Interface()); err != nil {
+ impLog("error encoding client send:", err)
+ return
+ }
+ imp.seqLock.Unlock()
+ }
+ }()
+ }
+ return nil
+}
+
+// Hangup disassociates the named channel from the Importer and closes
+// the channel. Messages in flight for the channel may be dropped.
+func (imp *Importer) Hangup(name string) os.Error {
+ imp.chanLock.Lock()
+ defer imp.chanLock.Unlock()
+ nc := imp.names[name]
+ if nc == nil {
+ return os.NewError("netchan import: hangup: no such channel: " + name)
+ }
+ delete(imp.names, name)
+ delete(imp.chans, nc.id)
+ nc.close()
+ return nil
+}
+
+func (imp *Importer) unackedCount() int64 {
+ imp.mu.Lock()
+ n := imp.unacked
+ imp.mu.Unlock()
+ return n
+}
+
+// Drain waits until all messages sent from this exporter/importer, including
+// those not yet sent to any server and possibly including those sent while
+// Drain was executing, have been received by the exporter. In short, it
+// waits until all the importer's messages have been received.
+// If the timeout (measured in nanoseconds) is positive and Drain takes
+// longer than that to complete, an error is returned.
+func (imp *Importer) Drain(timeout int64) os.Error {
+ startTime := time.Nanoseconds()
+ for imp.unackedCount() > 0 {
+ if timeout > 0 && time.Nanoseconds()-startTime >= timeout {
+ return os.NewError("timeout")
+ }
+ time.Sleep(100 * 1e6)
+ }
+ return nil
+}
diff --git a/libgo/go/netchan/netchan_test.go b/libgo/go/old/netchan/netchan_test.go
index 8c0f9a6e4b7..8c0f9a6e4b7 100644
--- a/libgo/go/netchan/netchan_test.go
+++ b/libgo/go/old/netchan/netchan_test.go
diff --git a/libgo/go/old/regexp/all_test.go b/libgo/go/old/regexp/all_test.go
new file mode 100644
index 00000000000..71edc4d18d3
--- /dev/null
+++ b/libgo/go/old/regexp/all_test.go
@@ -0,0 +1,426 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package regexp
+
+import (
+ "os"
+ "strings"
+ "testing"
+)
+
+var good_re = []string{
+ ``,
+ `.`,
+ `^.$`,
+ `a`,
+ `a*`,
+ `a+`,
+ `a?`,
+ `a|b`,
+ `a*|b*`,
+ `(a*|b)(c*|d)`,
+ `[a-z]`,
+ `[a-abc-c\-\]\[]`,
+ `[a-z]+`,
+ `[]`,
+ `[abc]`,
+ `[^1234]`,
+ `[^\n]`,
+ `\!\\`,
+}
+
+type stringError struct {
+ re string
+ err os.Error
+}
+
+var bad_re = []stringError{
+ {`*`, ErrBareClosure},
+ {`+`, ErrBareClosure},
+ {`?`, ErrBareClosure},
+ {`(abc`, ErrUnmatchedLpar},
+ {`abc)`, ErrUnmatchedRpar},
+ {`x[a-z`, ErrUnmatchedLbkt},
+ {`abc]`, ErrUnmatchedRbkt},
+ {`[z-a]`, ErrBadRange},
+ {`abc\`, ErrExtraneousBackslash},
+ {`a**`, ErrBadClosure},
+ {`a*+`, ErrBadClosure},
+ {`a??`, ErrBadClosure},
+ {`\x`, ErrBadBackslash},
+}
+
+func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
+ re, err := Compile(expr)
+ if err != error {
+ t.Error("compiling `", expr, "`; unexpected error: ", err.String())
+ }
+ return re
+}
+
+func TestGoodCompile(t *testing.T) {
+ for i := 0; i < len(good_re); i++ {
+ compileTest(t, good_re[i], nil)
+ }
+}
+
+func TestBadCompile(t *testing.T) {
+ for i := 0; i < len(bad_re); i++ {
+ compileTest(t, bad_re[i].re, bad_re[i].err)
+ }
+}
+
+func matchTest(t *testing.T, test *FindTest) {
+ re := compileTest(t, test.pat, nil)
+ if re == nil {
+ return
+ }
+ m := re.MatchString(test.text)
+ if m != (len(test.matches) > 0) {
+ t.Errorf("MatchString failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+ }
+ // now try bytes
+ m = re.Match([]byte(test.text))
+ if m != (len(test.matches) > 0) {
+ t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+ }
+}
+
+func TestMatch(t *testing.T) {
+ for _, test := range findTests {
+ matchTest(t, &test)
+ }
+}
+
+func matchFunctionTest(t *testing.T, test *FindTest) {
+ m, err := MatchString(test.pat, test.text)
+ if err == nil {
+ return
+ }
+ if m != (len(test.matches) > 0) {
+ t.Errorf("Match failure on %s: %t should be %t", test, m, len(test.matches) > 0)
+ }
+}
+
+func TestMatchFunction(t *testing.T) {
+ for _, test := range findTests {
+ matchFunctionTest(t, &test)
+ }
+}
+
+type ReplaceTest struct {
+ pattern, replacement, input, output string
+}
+
+var replaceTests = []ReplaceTest{
+ // Test empty input and/or replacement, with pattern that matches the empty string.
+ {"", "", "", ""},
+ {"", "x", "", "x"},
+ {"", "", "abc", "abc"},
+ {"", "x", "abc", "xaxbxcx"},
+
+ // Test empty input and/or replacement, with pattern that does not match the empty string.
+ {"b", "", "", ""},
+ {"b", "x", "", ""},
+ {"b", "", "abc", "ac"},
+ {"b", "x", "abc", "axc"},
+ {"y", "", "", ""},
+ {"y", "x", "", ""},
+ {"y", "", "abc", "abc"},
+ {"y", "x", "abc", "abc"},
+
+ // Multibyte characters -- verify that we don't try to match in the middle
+ // of a character.
+ {"[a-c]*", "x", "\u65e5", "x\u65e5x"},
+ {"[^\u65e5]", "x", "abc\u65e5def", "xxx\u65e5xxx"},
+
+ // Start and end of a string.
+ {"^[a-c]*", "x", "abcdabc", "xdabc"},
+ {"[a-c]*$", "x", "abcdabc", "abcdx"},
+ {"^[a-c]*$", "x", "abcdabc", "abcdabc"},
+ {"^[a-c]*", "x", "abc", "x"},
+ {"[a-c]*$", "x", "abc", "x"},
+ {"^[a-c]*$", "x", "abc", "x"},
+ {"^[a-c]*", "x", "dabce", "xdabce"},
+ {"[a-c]*$", "x", "dabce", "dabcex"},
+ {"^[a-c]*$", "x", "dabce", "dabce"},
+ {"^[a-c]*", "x", "", "x"},
+ {"[a-c]*$", "x", "", "x"},
+ {"^[a-c]*$", "x", "", "x"},
+
+ {"^[a-c]+", "x", "abcdabc", "xdabc"},
+ {"[a-c]+$", "x", "abcdabc", "abcdx"},
+ {"^[a-c]+$", "x", "abcdabc", "abcdabc"},
+ {"^[a-c]+", "x", "abc", "x"},
+ {"[a-c]+$", "x", "abc", "x"},
+ {"^[a-c]+$", "x", "abc", "x"},
+ {"^[a-c]+", "x", "dabce", "dabce"},
+ {"[a-c]+$", "x", "dabce", "dabce"},
+ {"^[a-c]+$", "x", "dabce", "dabce"},
+ {"^[a-c]+", "x", "", ""},
+ {"[a-c]+$", "x", "", ""},
+ {"^[a-c]+$", "x", "", ""},
+
+ // Other cases.
+ {"abc", "def", "abcdefg", "defdefg"},
+ {"bc", "BC", "abcbcdcdedef", "aBCBCdcdedef"},
+ {"abc", "", "abcdabc", "d"},
+ {"x", "xXx", "xxxXxxx", "xXxxXxxXxXxXxxXxxXx"},
+ {"abc", "d", "", ""},
+ {"abc", "d", "abc", "d"},
+ {".+", "x", "abc", "x"},
+ {"[a-c]*", "x", "def", "xdxexfx"},
+ {"[a-c]+", "x", "abcbcdcdedef", "xdxdedef"},
+ {"[a-c]*", "x", "abcbcdcdedef", "xdxdxexdxexfx"},
+}
+
+type ReplaceFuncTest struct {
+ pattern string
+ replacement func(string) string
+ input, output string
+}
+
+var replaceFuncTests = []ReplaceFuncTest{
+ {"[a-c]", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxayxbyxcydef"},
+ {"[a-c]+", func(s string) string { return "x" + s + "y" }, "defabcdef", "defxabcydef"},
+ {"[a-c]*", func(s string) string { return "x" + s + "y" }, "defabcdef", "xydxyexyfxabcydxyexyfxy"},
+}
+
+func TestReplaceAll(t *testing.T) {
+ for _, tc := range replaceTests {
+ re, err := Compile(tc.pattern)
+ if err != nil {
+ t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+ continue
+ }
+ actual := re.ReplaceAllString(tc.input, tc.replacement)
+ if actual != tc.output {
+ t.Errorf("%q.Replace(%q,%q) = %q; want %q",
+ tc.pattern, tc.input, tc.replacement, actual, tc.output)
+ }
+ // now try bytes
+ actual = string(re.ReplaceAll([]byte(tc.input), []byte(tc.replacement)))
+ if actual != tc.output {
+ t.Errorf("%q.Replace(%q,%q) = %q; want %q",
+ tc.pattern, tc.input, tc.replacement, actual, tc.output)
+ }
+ }
+}
+
+func TestReplaceAllFunc(t *testing.T) {
+ for _, tc := range replaceFuncTests {
+ re, err := Compile(tc.pattern)
+ if err != nil {
+ t.Errorf("Unexpected error compiling %q: %v", tc.pattern, err)
+ continue
+ }
+ actual := re.ReplaceAllStringFunc(tc.input, tc.replacement)
+ if actual != tc.output {
+ t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
+ tc.pattern, tc.input, tc.replacement, actual, tc.output)
+ }
+ // now try bytes
+ actual = string(re.ReplaceAllFunc([]byte(tc.input), func(s []byte) []byte { return []byte(tc.replacement(string(s))) }))
+ if actual != tc.output {
+ t.Errorf("%q.ReplaceFunc(%q,%q) = %q; want %q",
+ tc.pattern, tc.input, tc.replacement, actual, tc.output)
+ }
+ }
+}
+
+type MetaTest struct {
+ pattern, output, literal string
+ isLiteral bool
+}
+
+var metaTests = []MetaTest{
+ {``, ``, ``, true},
+ {`foo`, `foo`, `foo`, true},
+ {`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
+ {`foo.\$`, `foo\.\\\$`, `foo`, false}, // has escaped operators and real operators
+ {`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`, `!@#`, false},
+}
+
+func TestQuoteMeta(t *testing.T) {
+ for _, tc := range metaTests {
+ // Verify that QuoteMeta returns the expected string.
+ quoted := QuoteMeta(tc.pattern)
+ if quoted != tc.output {
+ t.Errorf("QuoteMeta(`%s`) = `%s`; want `%s`",
+ tc.pattern, quoted, tc.output)
+ continue
+ }
+
+ // Verify that the quoted string is in fact treated as expected
+ // by Compile -- i.e. that it matches the original, unquoted string.
+ if tc.pattern != "" {
+ re, err := Compile(quoted)
+ if err != nil {
+ t.Errorf("Unexpected error compiling QuoteMeta(`%s`): %v", tc.pattern, err)
+ continue
+ }
+ src := "abc" + tc.pattern + "def"
+ repl := "xyz"
+ replaced := re.ReplaceAllString(src, repl)
+ expected := "abcxyzdef"
+ if replaced != expected {
+ t.Errorf("QuoteMeta(`%s`).Replace(`%s`,`%s`) = `%s`; want `%s`",
+ tc.pattern, src, repl, replaced, expected)
+ }
+ }
+ }
+}
+
+func TestLiteralPrefix(t *testing.T) {
+ for _, tc := range metaTests {
+ // Literal method needs to scan the pattern.
+ re := MustCompile(tc.pattern)
+ str, complete := re.LiteralPrefix()
+ if complete != tc.isLiteral {
+ t.Errorf("LiteralPrefix(`%s`) = %t; want %t", tc.pattern, complete, tc.isLiteral)
+ }
+ if str != tc.literal {
+ t.Errorf("LiteralPrefix(`%s`) = `%s`; want `%s`", tc.pattern, str, tc.literal)
+ }
+ }
+}
+
+type numSubexpCase struct {
+ input string
+ expected int
+}
+
+var numSubexpCases = []numSubexpCase{
+ {``, 0},
+ {`.*`, 0},
+ {`abba`, 0},
+ {`ab(b)a`, 1},
+ {`ab(.*)a`, 1},
+ {`(.*)ab(.*)a`, 2},
+ {`(.*)(ab)(.*)a`, 3},
+ {`(.*)((a)b)(.*)a`, 4},
+ {`(.*)(\(ab)(.*)a`, 3},
+ {`(.*)(\(a\)b)(.*)a`, 3},
+}
+
+func TestNumSubexp(t *testing.T) {
+ for _, c := range numSubexpCases {
+ re := MustCompile(c.input)
+ n := re.NumSubexp()
+ if n != c.expected {
+ t.Errorf("NumSubexp for %q returned %d, expected %d", c.input, n, c.expected)
+ }
+ }
+}
+
+func BenchmarkLiteral(b *testing.B) {
+ x := strings.Repeat("x", 50) + "y"
+ b.StopTimer()
+ re := MustCompile("y")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if !re.MatchString(x) {
+ println("no match!")
+ break
+ }
+ }
+}
+
+func BenchmarkNotLiteral(b *testing.B) {
+ x := strings.Repeat("x", 50) + "y"
+ b.StopTimer()
+ re := MustCompile(".y")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if !re.MatchString(x) {
+ println("no match!")
+ break
+ }
+ }
+}
+
+func BenchmarkMatchClass(b *testing.B) {
+ b.StopTimer()
+ x := strings.Repeat("xxxx", 20) + "w"
+ re := MustCompile("[abcdw]")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if !re.MatchString(x) {
+ println("no match!")
+ break
+ }
+ }
+}
+
+func BenchmarkMatchClass_InRange(b *testing.B) {
+ b.StopTimer()
+ // 'b' is between 'a' and 'c', so the charclass
+ // range checking is no help here.
+ x := strings.Repeat("bbbb", 20) + "c"
+ re := MustCompile("[ac]")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if !re.MatchString(x) {
+ println("no match!")
+ break
+ }
+ }
+}
+
+func BenchmarkReplaceAll(b *testing.B) {
+ x := "abcdefghijklmnopqrstuvwxyz"
+ b.StopTimer()
+ re := MustCompile("[cjrw]")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.ReplaceAllString(x, "")
+ }
+}
+
+func BenchmarkAnchoredLiteralShortNonMatch(b *testing.B) {
+ b.StopTimer()
+ x := []byte("abcdefghijklmnopqrstuvwxyz")
+ re := MustCompile("^zbc(d|e)")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.Match(x)
+ }
+}
+
+func BenchmarkAnchoredLiteralLongNonMatch(b *testing.B) {
+ b.StopTimer()
+ x := []byte("abcdefghijklmnopqrstuvwxyz")
+ for i := 0; i < 15; i++ {
+ x = append(x, x...)
+ }
+ re := MustCompile("^zbc(d|e)")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.Match(x)
+ }
+}
+
+func BenchmarkAnchoredShortMatch(b *testing.B) {
+ b.StopTimer()
+ x := []byte("abcdefghijklmnopqrstuvwxyz")
+ re := MustCompile("^.bc(d|e)")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.Match(x)
+ }
+}
+
+func BenchmarkAnchoredLongMatch(b *testing.B) {
+ b.StopTimer()
+ x := []byte("abcdefghijklmnopqrstuvwxyz")
+ for i := 0; i < 15; i++ {
+ x = append(x, x...)
+ }
+ re := MustCompile("^.bc(d|e)")
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ re.Match(x)
+ }
+}
diff --git a/libgo/go/old/regexp/find_test.go b/libgo/go/old/regexp/find_test.go
new file mode 100644
index 00000000000..83b249e3cef
--- /dev/null
+++ b/libgo/go/old/regexp/find_test.go
@@ -0,0 +1,472 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package regexp
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+// For each pattern/text pair, what is the expected output of each function?
+// We can derive the textual results from the indexed results, the non-submatch
+// results from the submatched results, the single results from the 'all' results,
+// and the byte results from the string results. Therefore the table includes
+// only the FindAllStringSubmatchIndex result.
+type FindTest struct {
+ pat string
+ text string
+ matches [][]int
+}
+
+func (t FindTest) String() string {
+ return fmt.Sprintf("pat: %#q text: %#q", t.pat, t.text)
+}
+
+var findTests = []FindTest{
+ {``, ``, build(1, 0, 0)},
+ {`^abcdefg`, "abcdefg", build(1, 0, 7)},
+ {`a+`, "baaab", build(1, 1, 4)},
+ {"abcd..", "abcdef", build(1, 0, 6)},
+ {`a`, "a", build(1, 0, 1)},
+ {`x`, "y", nil},
+ {`b`, "abc", build(1, 1, 2)},
+ {`.`, "a", build(1, 0, 1)},
+ {`.*`, "abcdef", build(1, 0, 6)},
+ {`^`, "abcde", build(1, 0, 0)},
+ {`$`, "abcde", build(1, 5, 5)},
+ {`^abcd$`, "abcd", build(1, 0, 4)},
+ {`^bcd'`, "abcdef", nil},
+ {`^abcd$`, "abcde", nil},
+ {`a+`, "baaab", build(1, 1, 4)},
+ {`a*`, "baaab", build(3, 0, 0, 1, 4, 5, 5)},
+ {`[a-z]+`, "abcd", build(1, 0, 4)},
+ {`[^a-z]+`, "ab1234cd", build(1, 2, 6)},
+ {`[a\-\]z]+`, "az]-bcz", build(2, 0, 4, 6, 7)},
+ {`[^\n]+`, "abcd\n", build(1, 0, 4)},
+ {`[日本語]+`, "日本語日本語", build(1, 0, 18)},
+ {`日本語+`, "日本語", build(1, 0, 9)},
+ {`日本語+`, "日本語語語語", build(1, 0, 18)},
+ {`()`, "", build(1, 0, 0, 0, 0)},
+ {`(a)`, "a", build(1, 0, 1, 0, 1)},
+ {`(.)(.)`, "æ—¥a", build(1, 0, 4, 0, 3, 3, 4)},
+ {`(.*)`, "", build(1, 0, 0, 0, 0)},
+ {`(.*)`, "abcd", build(1, 0, 4, 0, 4)},
+ {`(..)(..)`, "abcd", build(1, 0, 4, 0, 2, 2, 4)},
+ {`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)},
+ {`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)},
+ {`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
+ {`\a\b\f\n\r\t\v`, "\a\b\f\n\r\t\v", build(1, 0, 7)},
+ {`[\a\b\f\n\r\t\v]+`, "\a\b\f\n\r\t\v", build(1, 0, 7)},
+
+ {`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)},
+ {`(.*).*`, "ab", build(1, 0, 2, 0, 2)},
+ {`[.]`, ".", build(1, 0, 1)},
+ {`/$`, "/abc/", build(1, 4, 5)},
+ {`/$`, "/abc", nil},
+
+ // multiple matches
+ {`.`, "abc", build(3, 0, 1, 1, 2, 2, 3)},
+ {`(.)`, "abc", build(3, 0, 1, 0, 1, 1, 2, 1, 2, 2, 3, 2, 3)},
+ {`.(.)`, "abcd", build(2, 0, 2, 1, 2, 2, 4, 3, 4)},
+ {`ab*`, "abbaab", build(3, 0, 3, 3, 4, 4, 6)},
+ {`a(b*)`, "abbaab", build(3, 0, 3, 1, 3, 3, 4, 4, 4, 4, 6, 5, 6)},
+
+ // fixed bugs
+ {`ab$`, "cab", build(1, 1, 3)},
+ {`axxb$`, "axxcb", nil},
+ {`data`, "daXY data", build(1, 5, 9)},
+ {`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
+ {`zx+`, "zzx", build(1, 1, 3)},
+
+ // can backslash-escape any punctuation
+ {`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
+ `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
+ {`[\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~]+`,
+ `!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`, build(1, 0, 31)},
+ {"\\`", "`", build(1, 0, 1)},
+ {"[\\`]+", "`", build(1, 0, 1)},
+
+ // long set of matches (longer than startSize)
+ {
+ ".",
+ "qwertyuiopasdfghjklzxcvbnm1234567890",
+ build(36, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10,
+ 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20,
+ 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30,
+ 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36),
+ },
+}
+
+// build is a helper to construct a [][]int by extracting n sequences from x.
+// This represents n matches with len(x)/n submatches each.
+func build(n int, x ...int) [][]int {
+ ret := make([][]int, n)
+ runLength := len(x) / n
+ j := 0
+ for i := range ret {
+ ret[i] = make([]int, runLength)
+ copy(ret[i], x[j:])
+ j += runLength
+ if j > len(x) {
+ panic("invalid build entry")
+ }
+ }
+ return ret
+}
+
+// First the simple cases.
+
+func TestFind(t *testing.T) {
+ for _, test := range findTests {
+ re := MustCompile(test.pat)
+ if re.String() != test.pat {
+ t.Errorf("String() = `%s`; should be `%s`", re.String(), test.pat)
+ }
+ result := re.Find([]byte(test.text))
+ switch {
+ case len(test.matches) == 0 && len(result) == 0:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case test.matches != nil && result != nil:
+ expect := test.text[test.matches[0][0]:test.matches[0][1]]
+ if expect != string(result) {
+ t.Errorf("expected %q got %q: %s", expect, result, test)
+ }
+ }
+ }
+}
+
+func TestFindString(t *testing.T) {
+ for _, test := range findTests {
+ result := MustCompile(test.pat).FindString(test.text)
+ switch {
+ case len(test.matches) == 0 && len(result) == 0:
+ // ok
+ case test.matches == nil && result != "":
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == "":
+ // Tricky because an empty result has two meanings: no match or empty match.
+ if test.matches[0][0] != test.matches[0][1] {
+ t.Errorf("expected match; got none: %s", test)
+ }
+ case test.matches != nil && result != "":
+ expect := test.text[test.matches[0][0]:test.matches[0][1]]
+ if expect != result {
+ t.Errorf("expected %q got %q: %s", expect, result, test)
+ }
+ }
+ }
+}
+
+func testFindIndex(test *FindTest, result []int, t *testing.T) {
+ switch {
+ case len(test.matches) == 0 && len(result) == 0:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case test.matches != nil && result != nil:
+ expect := test.matches[0]
+ if expect[0] != result[0] || expect[1] != result[1] {
+ t.Errorf("expected %v got %v: %s", expect, result, test)
+ }
+ }
+}
+
+func TestFindIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindIndex(&test, MustCompile(test.pat).FindIndex([]byte(test.text)), t)
+ }
+}
+
+func TestFindStringIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindIndex(&test, MustCompile(test.pat).FindStringIndex(test.text), t)
+ }
+}
+
+func TestFindReaderIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindIndex(&test, MustCompile(test.pat).FindReaderIndex(strings.NewReader(test.text)), t)
+ }
+}
+
+// Now come the simple All cases.
+
+func TestFindAll(t *testing.T) {
+ for _, test := range findTests {
+ result := MustCompile(test.pat).FindAll([]byte(test.text), -1)
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case test.matches != nil && result != nil:
+ if len(test.matches) != len(result) {
+ t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+ continue
+ }
+ for k, e := range test.matches {
+ expect := test.text[e[0]:e[1]]
+ if expect != string(result[k]) {
+ t.Errorf("match %d: expected %q got %q: %s", k, expect, result[k], test)
+ }
+ }
+ }
+ }
+}
+
+func TestFindAllString(t *testing.T) {
+ for _, test := range findTests {
+ result := MustCompile(test.pat).FindAllString(test.text, -1)
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case test.matches != nil && result != nil:
+ if len(test.matches) != len(result) {
+ t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+ continue
+ }
+ for k, e := range test.matches {
+ expect := test.text[e[0]:e[1]]
+ if expect != result[k] {
+ t.Errorf("expected %q got %q: %s", expect, result, test)
+ }
+ }
+ }
+ }
+}
+
+func testFindAllIndex(test *FindTest, result [][]int, t *testing.T) {
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case test.matches != nil && result != nil:
+ if len(test.matches) != len(result) {
+ t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+ return
+ }
+ for k, e := range test.matches {
+ if e[0] != result[k][0] || e[1] != result[k][1] {
+ t.Errorf("match %d: expected %v got %v: %s", k, e, result[k], test)
+ }
+ }
+ }
+}
+
+func TestFindAllIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindAllIndex(&test, MustCompile(test.pat).FindAllIndex([]byte(test.text), -1), t)
+ }
+}
+
+func TestFindAllStringIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindAllIndex(&test, MustCompile(test.pat).FindAllStringIndex(test.text, -1), t)
+ }
+}
+
+// Now come the Submatch cases.
+
+func testSubmatchBytes(test *FindTest, n int, submatches []int, result [][]byte, t *testing.T) {
+ if len(submatches) != len(result)*2 {
+ t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
+ return
+ }
+ for k := 0; k < len(submatches); k += 2 {
+ if submatches[k] == -1 {
+ if result[k/2] != nil {
+ t.Errorf("match %d: expected nil got %q: %s", n, result, test)
+ }
+ continue
+ }
+ expect := test.text[submatches[k]:submatches[k+1]]
+ if expect != string(result[k/2]) {
+ t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
+ return
+ }
+ }
+}
+
+func TestFindSubmatch(t *testing.T) {
+ for _, test := range findTests {
+ result := MustCompile(test.pat).FindSubmatch([]byte(test.text))
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case test.matches != nil && result != nil:
+ testSubmatchBytes(&test, 0, test.matches[0], result, t)
+ }
+ }
+}
+
+func testSubmatchString(test *FindTest, n int, submatches []int, result []string, t *testing.T) {
+ if len(submatches) != len(result)*2 {
+ t.Errorf("match %d: expected %d submatches; got %d: %s", n, len(submatches)/2, len(result), test)
+ return
+ }
+ for k := 0; k < len(submatches); k += 2 {
+ if submatches[k] == -1 {
+ if result[k/2] != "" {
+ t.Errorf("match %d: expected nil got %q: %s", n, result, test)
+ }
+ continue
+ }
+ expect := test.text[submatches[k]:submatches[k+1]]
+ if expect != result[k/2] {
+ t.Errorf("match %d: expected %q got %q: %s", n, expect, result, test)
+ return
+ }
+ }
+}
+
+func TestFindStringSubmatch(t *testing.T) {
+ for _, test := range findTests {
+ result := MustCompile(test.pat).FindStringSubmatch(test.text)
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case test.matches != nil && result != nil:
+ testSubmatchString(&test, 0, test.matches[0], result, t)
+ }
+ }
+}
+
+func testSubmatchIndices(test *FindTest, n int, expect, result []int, t *testing.T) {
+ if len(expect) != len(result) {
+ t.Errorf("match %d: expected %d matches; got %d: %s", n, len(expect)/2, len(result)/2, test)
+ return
+ }
+ for k, e := range expect {
+ if e != result[k] {
+ t.Errorf("match %d: submatch error: expected %v got %v: %s", n, expect, result, test)
+ }
+ }
+}
+
+func testFindSubmatchIndex(test *FindTest, result []int, t *testing.T) {
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case test.matches != nil && result != nil:
+ testSubmatchIndices(test, 0, test.matches[0], result, t)
+ }
+}
+
+func TestFindSubmatchIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindSubmatchIndex(&test, MustCompile(test.pat).FindSubmatchIndex([]byte(test.text)), t)
+ }
+}
+
+func TestFindStringSubmatchIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindSubmatchIndex(&test, MustCompile(test.pat).FindStringSubmatchIndex(test.text), t)
+ }
+}
+
+func TestFindReaderSubmatchIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindSubmatchIndex(&test, MustCompile(test.pat).FindReaderSubmatchIndex(strings.NewReader(test.text)), t)
+ }
+}
+
+// Now come the monster AllSubmatch cases.
+
+func TestFindAllSubmatch(t *testing.T) {
+ for _, test := range findTests {
+ result := MustCompile(test.pat).FindAllSubmatch([]byte(test.text), -1)
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case len(test.matches) != len(result):
+ t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+ case test.matches != nil && result != nil:
+ for k, match := range test.matches {
+ testSubmatchBytes(&test, k, match, result[k], t)
+ }
+ }
+ }
+}
+
+func TestFindAllStringSubmatch(t *testing.T) {
+ for _, test := range findTests {
+ result := MustCompile(test.pat).FindAllStringSubmatch(test.text, -1)
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case len(test.matches) != len(result):
+ t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+ case test.matches != nil && result != nil:
+ for k, match := range test.matches {
+ testSubmatchString(&test, k, match, result[k], t)
+ }
+ }
+ }
+}
+
+func testFindAllSubmatchIndex(test *FindTest, result [][]int, t *testing.T) {
+ switch {
+ case test.matches == nil && result == nil:
+ // ok
+ case test.matches == nil && result != nil:
+ t.Errorf("expected no match; got one: %s", test)
+ case test.matches != nil && result == nil:
+ t.Errorf("expected match; got none: %s", test)
+ case len(test.matches) != len(result):
+ t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
+ case test.matches != nil && result != nil:
+ for k, match := range test.matches {
+ testSubmatchIndices(test, k, match, result[k], t)
+ }
+ }
+}
+
+func TestFindAllSubmatchIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllSubmatchIndex([]byte(test.text), -1), t)
+ }
+}
+
+func TestFindAllStringSubmatchIndex(t *testing.T) {
+ for _, test := range findTests {
+ testFindAllSubmatchIndex(&test, MustCompile(test.pat).FindAllStringSubmatchIndex(test.text, -1), t)
+ }
+}
diff --git a/libgo/go/old/regexp/regexp.go b/libgo/go/old/regexp/regexp.go
new file mode 100644
index 00000000000..e8d4c087cf8
--- /dev/null
+++ b/libgo/go/old/regexp/regexp.go
@@ -0,0 +1,1488 @@
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package regexp implements a simple regular expression library.
+//
+// The syntax of the regular expressions accepted is:
+//
+// regexp:
+// concatenation { '|' concatenation }
+// concatenation:
+// { closure }
+// closure:
+// term [ '*' | '+' | '?' ]
+// term:
+// '^'
+// '$'
+// '.'
+// character
+// '[' [ '^' ] { character-range } ']'
+// '(' regexp ')'
+// character-range:
+// character [ '-' character ]
+//
+// All characters are UTF-8-encoded code points. Backslashes escape special
+// characters, including inside character classes. The standard Go character
+// escapes are also recognized: \a \b \f \n \r \t \v.
+//
+// There are 16 methods of Regexp that match a regular expression and identify
+// the matched text. Their names are matched by this regular expression:
+//
+// Find(All)?(String)?(Submatch)?(Index)?
+//
+// If 'All' is present, the routine matches successive non-overlapping
+// matches of the entire expression. Empty matches abutting a preceding
+// match are ignored. The return value is a slice containing the successive
+// return values of the corresponding non-'All' routine. These routines take
+// an extra integer argument, n; if n >= 0, the function returns at most n
+// matches/submatches.
+//
+// If 'String' is present, the argument is a string; otherwise it is a slice
+// of bytes; return values are adjusted as appropriate.
+//
+// If 'Submatch' is present, the return value is a slice identifying the
+// successive submatches of the expression. Submatches are matches of
+// parenthesized subexpressions within the regular expression, numbered from
+// left to right in order of opening parenthesis. Submatch 0 is the match of
+// the entire expression, submatch 1 the match of the first parenthesized
+// subexpression, and so on.
+//
+// If 'Index' is present, matches and submatches are identified by byte index
+// pairs within the input string: result[2*n:2*n+1] identifies the indexes of
+// the nth submatch. The pair for n==0 identifies the match of the entire
+// expression. If 'Index' is not present, the match is identified by the
+// text of the match/submatch. If an index is negative, it means that
+// subexpression did not match any string in the input.
+//
+// There is also a subset of the methods that can be applied to text read
+// from a RuneReader:
+//
+// MatchReader, FindReaderIndex, FindReaderSubmatchIndex
+//
+// This set may grow. Note that regular expression matches may need to
+// examine text beyond the text returned by a match, so the methods that
+// match text from a RuneReader may read arbitrarily far into the input
+// before returning.
+//
+// (There are a few other methods that do not match this pattern.)
+//
+package regexp
+
+import (
+ "bytes"
+ "io"
+ "os"
+ "strings"
+ "utf8"
+)
+
+var debug = false
+
+// Error is the local type for a parsing error.
+type Error string
+
+func (e Error) String() string {
+ return string(e)
+}
+
+// Error codes returned by failures to parse an expression.
+var (
+ ErrInternal = Error("regexp: internal error")
+ ErrUnmatchedLpar = Error("regexp: unmatched '('")
+ ErrUnmatchedRpar = Error("regexp: unmatched ')'")
+ ErrUnmatchedLbkt = Error("regexp: unmatched '['")
+ ErrUnmatchedRbkt = Error("regexp: unmatched ']'")
+ ErrBadRange = Error("regexp: bad range in character class")
+ ErrExtraneousBackslash = Error("regexp: extraneous backslash")
+ ErrBadClosure = Error("regexp: repeated closure (**, ++, etc.)")
+ ErrBareClosure = Error("regexp: closure applies to nothing")
+ ErrBadBackslash = Error("regexp: illegal backslash escape")
+)
+
+const (
+ iStart = iota // beginning of program
+ iEnd // end of program: success
+ iBOT // '^' beginning of text
+ iEOT // '$' end of text
+ iChar // 'a' regular character
+ iCharClass // [a-z] character class
+ iAny // '.' any character including newline
+ iNotNL // [^\n] special case: any character but newline
+ iBra // '(' parenthesized expression: 2*braNum for left, 2*braNum+1 for right
+ iAlt // '|' alternation
+ iNop // do nothing; makes it easy to link without patching
+)
+
+// An instruction executed by the NFA
+type instr struct {
+ kind int // the type of this instruction: iChar, iAny, etc.
+ index int // used only in debugging; could be eliminated
+ next *instr // the instruction to execute after this one
+ // Special fields valid only for some items.
+ char int // iChar
+ braNum int // iBra, iEbra
+ cclass *charClass // iCharClass
+ left *instr // iAlt, other branch
+}
+
+func (i *instr) print() {
+ switch i.kind {
+ case iStart:
+ print("start")
+ case iEnd:
+ print("end")
+ case iBOT:
+ print("bot")
+ case iEOT:
+ print("eot")
+ case iChar:
+ print("char ", string(i.char))
+ case iCharClass:
+ i.cclass.print()
+ case iAny:
+ print("any")
+ case iNotNL:
+ print("notnl")
+ case iBra:
+ if i.braNum&1 == 0 {
+ print("bra", i.braNum/2)
+ } else {
+ print("ebra", i.braNum/2)
+ }
+ case iAlt:
+ print("alt(", i.left.index, ")")
+ case iNop:
+ print("nop")
+ }
+}
+
+// Regexp is the representation of a compiled regular expression.
+// The public interface is entirely through methods.
+// A Regexp is safe for concurrent use by multiple goroutines.
+type Regexp struct {
+ expr string // the original expression
+ prefix string // initial plain text string
+ prefixBytes []byte // initial plain text bytes
+ inst []*instr
+ start *instr // first instruction of machine
+ prefixStart *instr // where to start if there is a prefix
+ nbra int // number of brackets in expression, for subexpressions
+}
+
+type charClass struct {
+ negate bool // is character class negated? ([^a-z])
+ // slice of int, stored pairwise: [a-z] is (a,z); x is (x,x):
+ ranges []int
+ cmin, cmax int
+}
+
+func (cclass *charClass) print() {
+ print("charclass")
+ if cclass.negate {
+ print(" (negated)")
+ }
+ for i := 0; i < len(cclass.ranges); i += 2 {
+ l := cclass.ranges[i]
+ r := cclass.ranges[i+1]
+ if l == r {
+ print(" [", string(l), "]")
+ } else {
+ print(" [", string(l), "-", string(r), "]")
+ }
+ }
+}
+
+func (cclass *charClass) addRange(a, b int) {
+ // range is a through b inclusive
+ cclass.ranges = append(cclass.ranges, a, b)
+ if a < cclass.cmin {
+ cclass.cmin = a
+ }
+ if b > cclass.cmax {
+ cclass.cmax = b
+ }
+}
+
+func (cclass *charClass) matches(c int) bool {
+ if c < cclass.cmin || c > cclass.cmax {
+ return cclass.negate
+ }
+ ranges := cclass.ranges
+ for i := 0; i < len(ranges); i = i + 2 {
+ if ranges[i] <= c && c <= ranges[i+1] {
+ return !cclass.negate
+ }
+ }
+ return cclass.negate
+}
+
+func newCharClass() *instr {
+ i := &instr{kind: iCharClass}
+ i.cclass = new(charClass)
+ i.cclass.ranges = make([]int, 0, 4)
+ i.cclass.cmin = 0x10FFFF + 1 // MaxRune + 1
+ i.cclass.cmax = -1
+ return i
+}
+
+func (re *Regexp) add(i *instr) *instr {
+ i.index = len(re.inst)
+ re.inst = append(re.inst, i)
+ return i
+}
+
+type parser struct {
+ re *Regexp
+ nlpar int // number of unclosed lpars
+ pos int
+ ch int
+}
+
+func (p *parser) error(err Error) {
+ panic(err)
+}
+
+const endOfText = -1
+
+func (p *parser) c() int { return p.ch }
+
+func (p *parser) nextc() int {
+ if p.pos >= len(p.re.expr) {
+ p.ch = endOfText
+ } else {
+ c, w := utf8.DecodeRuneInString(p.re.expr[p.pos:])
+ p.ch = c
+ p.pos += w
+ }
+ return p.ch
+}
+
+func newParser(re *Regexp) *parser {
+ p := new(parser)
+ p.re = re
+ p.nextc() // load p.ch
+ return p
+}
+
+func special(c int) bool {
+ for _, r := range `\.+*?()|[]^$` {
+ if c == r {
+ return true
+ }
+ }
+ return false
+}
+
+func ispunct(c int) bool {
+ for _, r := range "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" {
+ if c == r {
+ return true
+ }
+ }
+ return false
+}
+
+var escapes = []byte("abfnrtv")
+var escaped = []byte("\a\b\f\n\r\t\v")
+
+func escape(c int) int {
+ for i, b := range escapes {
+ if int(b) == c {
+ return i
+ }
+ }
+ return -1
+}
+
+func (p *parser) checkBackslash() int {
+ c := p.c()
+ if c == '\\' {
+ c = p.nextc()
+ switch {
+ case c == endOfText:
+ p.error(ErrExtraneousBackslash)
+ case ispunct(c):
+ // c is as delivered
+ case escape(c) >= 0:
+ c = int(escaped[escape(c)])
+ default:
+ p.error(ErrBadBackslash)
+ }
+ }
+ return c
+}
+
+func (p *parser) charClass() *instr {
+ i := newCharClass()
+ cc := i.cclass
+ if p.c() == '^' {
+ cc.negate = true
+ p.nextc()
+ }
+ left := -1
+ for {
+ switch c := p.c(); c {
+ case ']', endOfText:
+ if left >= 0 {
+ p.error(ErrBadRange)
+ }
+ // Is it [^\n]?
+ if cc.negate && len(cc.ranges) == 2 &&
+ cc.ranges[0] == '\n' && cc.ranges[1] == '\n' {
+ nl := &instr{kind: iNotNL}
+ p.re.add(nl)
+ return nl
+ }
+ // Special common case: "[a]" -> "a"
+ if !cc.negate && len(cc.ranges) == 2 && cc.ranges[0] == cc.ranges[1] {
+ c := &instr{kind: iChar, char: cc.ranges[0]}
+ p.re.add(c)
+ return c
+ }
+ p.re.add(i)
+ return i
+ case '-': // do this before backslash processing
+ p.error(ErrBadRange)
+ default:
+ c = p.checkBackslash()
+ p.nextc()
+ switch {
+ case left < 0: // first of pair
+ if p.c() == '-' { // range
+ p.nextc()
+ left = c
+ } else { // single char
+ cc.addRange(c, c)
+ }
+ case left <= c: // second of pair
+ cc.addRange(left, c)
+ left = -1
+ default:
+ p.error(ErrBadRange)
+ }
+ }
+ }
+ panic("unreachable")
+}
+
+func (p *parser) term() (start, end *instr) {
+ switch c := p.c(); c {
+ case '|', endOfText:
+ return nil, nil
+ case '*', '+', '?':
+ p.error(ErrBareClosure)
+ case ')':
+ if p.nlpar == 0 {
+ p.error(ErrUnmatchedRpar)
+ }
+ return nil, nil
+ case ']':
+ p.error(ErrUnmatchedRbkt)
+ case '^':
+ p.nextc()
+ start = p.re.add(&instr{kind: iBOT})
+ return start, start
+ case '$':
+ p.nextc()
+ start = p.re.add(&instr{kind: iEOT})
+ return start, start
+ case '.':
+ p.nextc()
+ start = p.re.add(&instr{kind: iAny})
+ return start, start
+ case '[':
+ p.nextc()
+ start = p.charClass()
+ if p.c() != ']' {
+ p.error(ErrUnmatchedLbkt)
+ }
+ p.nextc()
+ return start, start
+ case '(':
+ p.nextc()
+ p.nlpar++
+ p.re.nbra++ // increment first so first subexpr is \1
+ nbra := p.re.nbra
+ start, end = p.regexp()
+ if p.c() != ')' {
+ p.error(ErrUnmatchedLpar)
+ }
+ p.nlpar--
+ p.nextc()
+ bra := &instr{kind: iBra, braNum: 2 * nbra}
+ p.re.add(bra)
+ ebra := &instr{kind: iBra, braNum: 2*nbra + 1}
+ p.re.add(ebra)
+ if start == nil {
+ if end == nil {
+ p.error(ErrInternal)
+ return
+ }
+ start = ebra
+ } else {
+ end.next = ebra
+ }
+ bra.next = start
+ return bra, ebra
+ default:
+ c = p.checkBackslash()
+ p.nextc()
+ start = &instr{kind: iChar, char: c}
+ p.re.add(start)
+ return start, start
+ }
+ panic("unreachable")
+}
+
+func (p *parser) closure() (start, end *instr) {
+ start, end = p.term()
+ if start == nil {
+ return
+ }
+ switch p.c() {
+ case '*':
+ // (start,end)*:
+ alt := &instr{kind: iAlt}
+ p.re.add(alt)
+ end.next = alt // after end, do alt
+ alt.left = start // alternate brach: return to start
+ start = alt // alt becomes new (start, end)
+ end = alt
+ case '+':
+ // (start,end)+:
+ alt := &instr{kind: iAlt}
+ p.re.add(alt)
+ end.next = alt // after end, do alt
+ alt.left = start // alternate brach: return to start
+ end = alt // start is unchanged; end is alt
+ case '?':
+ // (start,end)?:
+ alt := &instr{kind: iAlt}
+ p.re.add(alt)
+ nop := &instr{kind: iNop}
+ p.re.add(nop)
+ alt.left = start // alternate branch is start
+ alt.next = nop // follow on to nop
+ end.next = nop // after end, go to nop
+ start = alt // start is now alt
+ end = nop // end is nop pointed to by both branches
+ default:
+ return
+ }
+ switch p.nextc() {
+ case '*', '+', '?':
+ p.error(ErrBadClosure)
+ }
+ return
+}
+
+func (p *parser) concatenation() (start, end *instr) {
+ for {
+ nstart, nend := p.closure()
+ switch {
+ case nstart == nil: // end of this concatenation
+ if start == nil { // this is the empty string
+ nop := p.re.add(&instr{kind: iNop})
+ return nop, nop
+ }
+ return
+ case start == nil: // this is first element of concatenation
+ start, end = nstart, nend
+ default:
+ end.next = nstart
+ end = nend
+ }
+ }
+ panic("unreachable")
+}
+
+func (p *parser) regexp() (start, end *instr) {
+ start, end = p.concatenation()
+ for {
+ switch p.c() {
+ default:
+ return
+ case '|':
+ p.nextc()
+ nstart, nend := p.concatenation()
+ alt := &instr{kind: iAlt}
+ p.re.add(alt)
+ alt.left = start
+ alt.next = nstart
+ nop := &instr{kind: iNop}
+ p.re.add(nop)
+ end.next = nop
+ nend.next = nop
+ start, end = alt, nop
+ }
+ }
+ panic("unreachable")
+}
+
+func unNop(i *instr) *instr {
+ for i.kind == iNop {
+ i = i.next
+ }
+ return i
+}
+
+func (re *Regexp) eliminateNops() {
+ for _, inst := range re.inst {
+ if inst.kind == iEnd {
+ continue
+ }
+ inst.next = unNop(inst.next)
+ if inst.kind == iAlt {
+ inst.left = unNop(inst.left)
+ }
+ }
+}
+
+func (re *Regexp) dump() {
+ print("prefix <", re.prefix, ">\n")
+ for _, inst := range re.inst {
+ print(inst.index, ": ")
+ inst.print()
+ if inst.kind != iEnd {
+ print(" -> ", inst.next.index)
+ }
+ print("\n")
+ }
+}
+
+func (re *Regexp) doParse() {
+ p := newParser(re)
+ start := &instr{kind: iStart}
+ re.add(start)
+ s, e := p.regexp()
+ start.next = s
+ re.start = start
+ e.next = re.add(&instr{kind: iEnd})
+
+ if debug {
+ re.dump()
+ println()
+ }
+
+ re.eliminateNops()
+ if debug {
+ re.dump()
+ println()
+ }
+ re.setPrefix()
+ if debug {
+ re.dump()
+ println()
+ }
+}
+
+// Extract regular text from the beginning of the pattern,
+// possibly after a leading iBOT.
+// That text can be used by doExecute to speed up matching.
+func (re *Regexp) setPrefix() {
+ var b []byte
+ var utf = make([]byte, utf8.UTFMax)
+ var inst *instr
+ // First instruction is start; skip that. Also skip any initial iBOT.
+ inst = re.inst[0].next
+ for inst.kind == iBOT {
+ inst = inst.next
+ }
+Loop:
+ for ; inst.kind != iEnd; inst = inst.next {
+ // stop if this is not a char
+ if inst.kind != iChar {
+ break
+ }
+ // stop if this char can be followed by a match for an empty string,
+ // which includes closures, ^, and $.
+ switch inst.next.kind {
+ case iBOT, iEOT, iAlt:
+ break Loop
+ }
+ n := utf8.EncodeRune(utf, inst.char)
+ b = append(b, utf[0:n]...)
+ }
+ // point prefixStart instruction to first non-CHAR after prefix
+ re.prefixStart = inst
+ re.prefixBytes = b
+ re.prefix = string(b)
+}
+
+// String returns the source text used to compile the regular expression.
+func (re *Regexp) String() string {
+ return re.expr
+}
+
+// Compile parses a regular expression and returns, if successful, a Regexp
+// object that can be used to match against text.
+func Compile(str string) (regexp *Regexp, error os.Error) {
+ regexp = new(Regexp)
+ // doParse will panic if there is a parse error.
+ defer func() {
+ if e := recover(); e != nil {
+ regexp = nil
+ error = e.(Error) // Will re-panic if error was not an Error, e.g. nil-pointer exception
+ }
+ }()
+ regexp.expr = str
+ regexp.inst = make([]*instr, 0, 10)
+ regexp.doParse()
+ return
+}
+
+// MustCompile is like Compile but panics if the expression cannot be parsed.
+// It simplifies safe initialization of global variables holding compiled regular
+// expressions.
+func MustCompile(str string) *Regexp {
+ regexp, error := Compile(str)
+ if error != nil {
+ panic(`regexp: compiling "` + str + `": ` + error.String())
+ }
+ return regexp
+}
+
+// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
+func (re *Regexp) NumSubexp() int { return re.nbra }
+
+// The match arena allows us to reduce the garbage generated by tossing
+// match vectors away as we execute. Matches are ref counted and returned
+// to a free list when no longer active. Increases a simple benchmark by 22X.
+type matchArena struct {
+ head *matchVec
+ len int // length of match vector
+ pos int
+ atBOT bool // whether we're at beginning of text
+ atEOT bool // whether we're at end of text
+}
+
+type matchVec struct {
+ m []int // pairs of bracketing submatches. 0th is start,end
+ ref int
+ next *matchVec
+}
+
+func (a *matchArena) new() *matchVec {
+ if a.head == nil {
+ const N = 10
+ block := make([]matchVec, N)
+ for i := 0; i < N; i++ {
+ b := &block[i]
+ b.next = a.head
+ a.head = b
+ }
+ }
+ m := a.head
+ a.head = m.next
+ m.ref = 0
+ if m.m == nil {
+ m.m = make([]int, a.len)
+ }
+ return m
+}
+
+func (a *matchArena) free(m *matchVec) {
+ m.ref--
+ if m.ref == 0 {
+ m.next = a.head
+ a.head = m
+ }
+}
+
+func (a *matchArena) copy(m *matchVec) *matchVec {
+ m1 := a.new()
+ copy(m1.m, m.m)
+ return m1
+}
+
+func (a *matchArena) noMatch() *matchVec {
+ m := a.new()
+ for i := range m.m {
+ m.m[i] = -1 // no match seen; catches cases like "a(b)?c" on "ac"
+ }
+ m.ref = 1
+ return m
+}
+
+type state struct {
+ inst *instr // next instruction to execute
+ prefixed bool // this match began with a fixed prefix
+ match *matchVec
+}
+
+// Append new state to to-do list. Leftmost-longest wins so avoid
+// adding a state that's already active. The matchVec will be inc-ref'ed
+// if it is assigned to a state.
+func (a *matchArena) addState(s []state, inst *instr, prefixed bool, match *matchVec) []state {
+ switch inst.kind {
+ case iBOT:
+ if a.atBOT {
+ s = a.addState(s, inst.next, prefixed, match)
+ }
+ return s
+ case iEOT:
+ if a.atEOT {
+ s = a.addState(s, inst.next, prefixed, match)
+ }
+ return s
+ case iBra:
+ match.m[inst.braNum] = a.pos
+ s = a.addState(s, inst.next, prefixed, match)
+ return s
+ }
+ l := len(s)
+ // States are inserted in order so it's sufficient to see if we have the same
+ // instruction; no need to see if existing match is earlier (it is).
+ for i := 0; i < l; i++ {
+ if s[i].inst == inst {
+ return s
+ }
+ }
+ s = append(s, state{inst, prefixed, match})
+ match.ref++
+ if inst.kind == iAlt {
+ s = a.addState(s, inst.left, prefixed, a.copy(match))
+ // give other branch a copy of this match vector
+ s = a.addState(s, inst.next, prefixed, a.copy(match))
+ }
+ return s
+}
+
+// input abstracts different representations of the input text. It provides
+// one-character lookahead.
+type input interface {
+ step(pos int) (rune int, width int) // advance one rune
+ canCheckPrefix() bool // can we look ahead without losing info?
+ hasPrefix(re *Regexp) bool
+ index(re *Regexp, pos int) int
+}
+
+// inputString scans a string.
+type inputString struct {
+ str string
+}
+
+func newInputString(str string) *inputString {
+ return &inputString{str: str}
+}
+
+func (i *inputString) step(pos int) (int, int) {
+ if pos < len(i.str) {
+ return utf8.DecodeRuneInString(i.str[pos:len(i.str)])
+ }
+ return endOfText, 0
+}
+
+func (i *inputString) canCheckPrefix() bool {
+ return true
+}
+
+func (i *inputString) hasPrefix(re *Regexp) bool {
+ return strings.HasPrefix(i.str, re.prefix)
+}
+
+func (i *inputString) index(re *Regexp, pos int) int {
+ return strings.Index(i.str[pos:], re.prefix)
+}
+
+// inputBytes scans a byte slice.
+type inputBytes struct {
+ str []byte
+}
+
+func newInputBytes(str []byte) *inputBytes {
+ return &inputBytes{str: str}
+}
+
+func (i *inputBytes) step(pos int) (int, int) {
+ if pos < len(i.str) {
+ return utf8.DecodeRune(i.str[pos:len(i.str)])
+ }
+ return endOfText, 0
+}
+
+func (i *inputBytes) canCheckPrefix() bool {
+ return true
+}
+
+func (i *inputBytes) hasPrefix(re *Regexp) bool {
+ return bytes.HasPrefix(i.str, re.prefixBytes)
+}
+
+func (i *inputBytes) index(re *Regexp, pos int) int {
+ return bytes.Index(i.str[pos:], re.prefixBytes)
+}
+
+// inputReader scans a RuneReader.
+type inputReader struct {
+ r io.RuneReader
+ atEOT bool
+ pos int
+}
+
+func newInputReader(r io.RuneReader) *inputReader {
+ return &inputReader{r: r}
+}
+
+func (i *inputReader) step(pos int) (int, int) {
+ if !i.atEOT && pos != i.pos {
+ return endOfText, 0
+
+ }
+ r, w, err := i.r.ReadRune()
+ if err != nil {
+ i.atEOT = true
+ return endOfText, 0
+ }
+ i.pos += w
+ return r, w
+}
+
+func (i *inputReader) canCheckPrefix() bool {
+ return false
+}
+
+func (i *inputReader) hasPrefix(re *Regexp) bool {
+ return false
+}
+
+func (i *inputReader) index(re *Regexp, pos int) int {
+ return -1
+}
+
+// Search match starting from pos bytes into the input.
+func (re *Regexp) doExecute(i input, pos int) []int {
+ var s [2][]state
+ s[0] = make([]state, 0, 10)
+ s[1] = make([]state, 0, 10)
+ in, out := 0, 1
+ var final state
+ found := false
+ anchored := re.inst[0].next.kind == iBOT
+ if anchored && pos > 0 {
+ return nil
+ }
+ // fast check for initial plain substring
+ if i.canCheckPrefix() && re.prefix != "" {
+ advance := 0
+ if anchored {
+ if !i.hasPrefix(re) {
+ return nil
+ }
+ } else {
+ advance = i.index(re, pos)
+ if advance == -1 {
+ return nil
+ }
+ }
+ pos += advance
+ }
+ // We look one character ahead so we can match $, which checks whether
+ // we are at EOT.
+ nextChar, nextWidth := i.step(pos)
+ arena := &matchArena{
+ len: 2 * (re.nbra + 1),
+ pos: pos,
+ atBOT: pos == 0,
+ atEOT: nextChar == endOfText,
+ }
+ for c, startPos := 0, pos; c != endOfText; {
+ if !found && (pos == startPos || !anchored) {
+ // prime the pump if we haven't seen a match yet
+ match := arena.noMatch()
+ match.m[0] = pos
+ s[out] = arena.addState(s[out], re.start.next, false, match)
+ arena.free(match) // if addState saved it, ref was incremented
+ } else if len(s[out]) == 0 {
+ // machine has completed
+ break
+ }
+ in, out = out, in // old out state is new in state
+ // clear out old state
+ old := s[out]
+ for _, state := range old {
+ arena.free(state.match)
+ }
+ s[out] = old[0:0] // truncate state vector
+ c = nextChar
+ thisPos := pos
+ pos += nextWidth
+ nextChar, nextWidth = i.step(pos)
+ arena.atEOT = nextChar == endOfText
+ arena.atBOT = false
+ arena.pos = pos
+ for _, st := range s[in] {
+ switch st.inst.kind {
+ case iBOT:
+ case iEOT:
+ case iChar:
+ if c == st.inst.char {
+ s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+ }
+ case iCharClass:
+ if st.inst.cclass.matches(c) {
+ s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+ }
+ case iAny:
+ if c != endOfText {
+ s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+ }
+ case iNotNL:
+ if c != endOfText && c != '\n' {
+ s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
+ }
+ case iBra:
+ case iAlt:
+ case iEnd:
+ // choose leftmost longest
+ if !found || // first
+ st.match.m[0] < final.match.m[0] || // leftmost
+ (st.match.m[0] == final.match.m[0] && thisPos > final.match.m[1]) { // longest
+ if final.match != nil {
+ arena.free(final.match)
+ }
+ final = st
+ final.match.ref++
+ final.match.m[1] = thisPos
+ }
+ found = true
+ default:
+ st.inst.print()
+ panic("unknown instruction in execute")
+ }
+ }
+ }
+ if final.match == nil {
+ return nil
+ }
+ // if match found, back up start of match by width of prefix.
+ if final.prefixed && len(final.match.m) > 0 {
+ final.match.m[0] -= len(re.prefix)
+ }
+ return final.match.m
+}
+
+// LiteralPrefix returns a literal string that must begin any match
+// of the regular expression re. It returns the boolean true if the
+// literal string comprises the entire regular expression.
+func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
+ c := make([]int, len(re.inst)-2) // minus start and end.
+ // First instruction is start; skip that.
+ i := 0
+ for inst := re.inst[0].next; inst.kind != iEnd; inst = inst.next {
+ // stop if this is not a char
+ if inst.kind != iChar {
+ return string(c[:i]), false
+ }
+ c[i] = inst.char
+ i++
+ }
+ return string(c[:i]), true
+}
+
+// MatchReader returns whether the Regexp matches the text read by the
+// RuneReader. The return value is a boolean: true for match, false for no
+// match.
+func (re *Regexp) MatchReader(r io.RuneReader) bool {
+ return len(re.doExecute(newInputReader(r), 0)) > 0
+}
+
+// MatchString returns whether the Regexp matches the string s.
+// The return value is a boolean: true for match, false for no match.
+func (re *Regexp) MatchString(s string) bool { return len(re.doExecute(newInputString(s), 0)) > 0 }
+
+// Match returns whether the Regexp matches the byte slice b.
+// The return value is a boolean: true for match, false for no match.
+func (re *Regexp) Match(b []byte) bool { return len(re.doExecute(newInputBytes(b), 0)) > 0 }
+
+// MatchReader checks whether a textual regular expression matches the text
+// read by the RuneReader. More complicated queries need to use Compile and
+// the full Regexp interface.
+func MatchReader(pattern string, r io.RuneReader) (matched bool, error os.Error) {
+ re, err := Compile(pattern)
+ if err != nil {
+ return false, err
+ }
+ return re.MatchReader(r), nil
+}
+
+// MatchString checks whether a textual regular expression
+// matches a string. More complicated queries need
+// to use Compile and the full Regexp interface.
+func MatchString(pattern string, s string) (matched bool, error os.Error) {
+ re, err := Compile(pattern)
+ if err != nil {
+ return false, err
+ }
+ return re.MatchString(s), nil
+}
+
+// Match checks whether a textual regular expression
+// matches a byte slice. More complicated queries need
+// to use Compile and the full Regexp interface.
+func Match(pattern string, b []byte) (matched bool, error os.Error) {
+ re, err := Compile(pattern)
+ if err != nil {
+ return false, err
+ }
+ return re.Match(b), nil
+}
+
+// ReplaceAllString returns a copy of src in which all matches for the Regexp
+// have been replaced by repl. No support is provided for expressions
+// (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllString(src, repl string) string {
+ return re.ReplaceAllStringFunc(src, func(string) string { return repl })
+}
+
+// ReplaceAllStringFunc returns a copy of src in which all matches for the
+// Regexp have been replaced by the return value of of function repl (whose
+// first argument is the matched string). No support is provided for
+// expressions (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string {
+ lastMatchEnd := 0 // end position of the most recent match
+ searchPos := 0 // position where we next look for a match
+ buf := new(bytes.Buffer)
+ for searchPos <= len(src) {
+ a := re.doExecute(newInputString(src), searchPos)
+ if len(a) == 0 {
+ break // no more matches
+ }
+
+ // Copy the unmatched characters before this match.
+ io.WriteString(buf, src[lastMatchEnd:a[0]])
+
+ // Now insert a copy of the replacement string, but not for a
+ // match of the empty string immediately after another match.
+ // (Otherwise, we get double replacement for patterns that
+ // match both empty and nonempty strings.)
+ if a[1] > lastMatchEnd || a[0] == 0 {
+ io.WriteString(buf, repl(src[a[0]:a[1]]))
+ }
+ lastMatchEnd = a[1]
+
+ // Advance past this match; always advance at least one character.
+ _, width := utf8.DecodeRuneInString(src[searchPos:])
+ if searchPos+width > a[1] {
+ searchPos += width
+ } else if searchPos+1 > a[1] {
+ // This clause is only needed at the end of the input
+ // string. In that case, DecodeRuneInString returns width=0.
+ searchPos++
+ } else {
+ searchPos = a[1]
+ }
+ }
+
+ // Copy the unmatched characters after the last match.
+ io.WriteString(buf, src[lastMatchEnd:])
+
+ return buf.String()
+}
+
+// ReplaceAll returns a copy of src in which all matches for the Regexp
+// have been replaced by repl. No support is provided for expressions
+// (e.g. \1 or $1) in the replacement text.
+func (re *Regexp) ReplaceAll(src, repl []byte) []byte {
+ return re.ReplaceAllFunc(src, func([]byte) []byte { return repl })
+}
+
+// ReplaceAllFunc returns a copy of src in which all matches for the
+// Regexp have been replaced by the return value of of function repl (whose
+// first argument is the matched []byte). No support is provided for
+// expressions (e.g. \1 or $1) in the replacement string.
+func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
+ lastMatchEnd := 0 // end position of the most recent match
+ searchPos := 0 // position where we next look for a match
+ buf := new(bytes.Buffer)
+ for searchPos <= len(src) {
+ a := re.doExecute(newInputBytes(src), searchPos)
+ if len(a) == 0 {
+ break // no more matches
+ }
+
+ // Copy the unmatched characters before this match.
+ buf.Write(src[lastMatchEnd:a[0]])
+
+ // Now insert a copy of the replacement string, but not for a
+ // match of the empty string immediately after another match.
+ // (Otherwise, we get double replacement for patterns that
+ // match both empty and nonempty strings.)
+ if a[1] > lastMatchEnd || a[0] == 0 {
+ buf.Write(repl(src[a[0]:a[1]]))
+ }
+ lastMatchEnd = a[1]
+
+ // Advance past this match; always advance at least one character.
+ _, width := utf8.DecodeRune(src[searchPos:])
+ if searchPos+width > a[1] {
+ searchPos += width
+ } else if searchPos+1 > a[1] {
+ // This clause is only needed at the end of the input
+ // string. In that case, DecodeRuneInString returns width=0.
+ searchPos++
+ } else {
+ searchPos = a[1]
+ }
+ }
+
+ // Copy the unmatched characters after the last match.
+ buf.Write(src[lastMatchEnd:])
+
+ return buf.Bytes()
+}
+
+// QuoteMeta returns a string that quotes all regular expression metacharacters
+// inside the argument text; the returned string is a regular expression matching
+// the literal text. For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
+func QuoteMeta(s string) string {
+ b := make([]byte, 2*len(s))
+
+ // A byte loop is correct because all metacharacters are ASCII.
+ j := 0
+ for i := 0; i < len(s); i++ {
+ if special(int(s[i])) {
+ b[j] = '\\'
+ j++
+ }
+ b[j] = s[i]
+ j++
+ }
+ return string(b[0:j])
+}
+
+// Find matches in slice b if b is non-nil, otherwise find matches in string s.
+func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
+ var end int
+ if b == nil {
+ end = len(s)
+ } else {
+ end = len(b)
+ }
+
+ for pos, i, prevMatchEnd := 0, 0, -1; i < n && pos <= end; {
+ var in input
+ if b == nil {
+ in = newInputString(s)
+ } else {
+ in = newInputBytes(b)
+ }
+ matches := re.doExecute(in, pos)
+ if len(matches) == 0 {
+ break
+ }
+
+ accept := true
+ if matches[1] == pos {
+ // We've found an empty match.
+ if matches[0] == prevMatchEnd {
+ // We don't allow an empty match right
+ // after a previous match, so ignore it.
+ accept = false
+ }
+ var width int
+ // TODO: use step()
+ if b == nil {
+ _, width = utf8.DecodeRuneInString(s[pos:end])
+ } else {
+ _, width = utf8.DecodeRune(b[pos:end])
+ }
+ if width > 0 {
+ pos += width
+ } else {
+ pos = end + 1
+ }
+ } else {
+ pos = matches[1]
+ }
+ prevMatchEnd = matches[1]
+
+ if accept {
+ deliver(matches)
+ i++
+ }
+ }
+}
+
+// Find returns a slice holding the text of the leftmost match in b of the regular expression.
+// A return value of nil indicates no match.
+func (re *Regexp) Find(b []byte) []byte {
+ a := re.doExecute(newInputBytes(b), 0)
+ if a == nil {
+ return nil
+ }
+ return b[a[0]:a[1]]
+}
+
+// FindIndex returns a two-element slice of integers defining the location of
+// the leftmost match in b of the regular expression. The match itself is at
+// b[loc[0]:loc[1]].
+// A return value of nil indicates no match.
+func (re *Regexp) FindIndex(b []byte) (loc []int) {
+ a := re.doExecute(newInputBytes(b), 0)
+ if a == nil {
+ return nil
+ }
+ return a[0:2]
+}
+
+// FindString returns a string holding the text of the leftmost match in s of the regular
+// expression. If there is no match, the return value is an empty string,
+// but it will also be empty if the regular expression successfully matches
+// an empty string. Use FindStringIndex or FindStringSubmatch if it is
+// necessary to distinguish these cases.
+func (re *Regexp) FindString(s string) string {
+ a := re.doExecute(newInputString(s), 0)
+ if a == nil {
+ return ""
+ }
+ return s[a[0]:a[1]]
+}
+
+// FindStringIndex returns a two-element slice of integers defining the
+// location of the leftmost match in s of the regular expression. The match
+// itself is at s[loc[0]:loc[1]].
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringIndex(s string) []int {
+ a := re.doExecute(newInputString(s), 0)
+ if a == nil {
+ return nil
+ }
+ return a[0:2]
+}
+
+// FindReaderIndex returns a two-element slice of integers defining the
+// location of the leftmost match of the regular expression in text read from
+// the RuneReader. The match itself is at s[loc[0]:loc[1]]. A return
+// value of nil indicates no match.
+func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
+ a := re.doExecute(newInputReader(r), 0)
+ if a == nil {
+ return nil
+ }
+ return a[0:2]
+}
+
+// FindSubmatch returns a slice of slices holding the text of the leftmost
+// match of the regular expression in b and the matches, if any, of its
+// subexpressions, as defined by the 'Submatch' descriptions in the package
+// comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindSubmatch(b []byte) [][]byte {
+ a := re.doExecute(newInputBytes(b), 0)
+ if a == nil {
+ return nil
+ }
+ ret := make([][]byte, len(a)/2)
+ for i := range ret {
+ if a[2*i] >= 0 {
+ ret[i] = b[a[2*i]:a[2*i+1]]
+ }
+ }
+ return ret
+}
+
+// FindSubmatchIndex returns a slice holding the index pairs identifying the
+// leftmost match of the regular expression in b and the matches, if any, of
+// its subexpressions, as defined by the 'Submatch' and 'Index' descriptions
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindSubmatchIndex(b []byte) []int {
+ return re.doExecute(newInputBytes(b), 0)
+}
+
+// FindStringSubmatch returns a slice of strings holding the text of the
+// leftmost match of the regular expression in s and the matches, if any, of
+// its subexpressions, as defined by the 'Submatch' description in the
+// package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringSubmatch(s string) []string {
+ a := re.doExecute(newInputString(s), 0)
+ if a == nil {
+ return nil
+ }
+ ret := make([]string, len(a)/2)
+ for i := range ret {
+ if a[2*i] >= 0 {
+ ret[i] = s[a[2*i]:a[2*i+1]]
+ }
+ }
+ return ret
+}
+
+// FindStringSubmatchIndex returns a slice holding the index pairs
+// identifying the leftmost match of the regular expression in s and the
+// matches, if any, of its subexpressions, as defined by the 'Submatch' and
+// 'Index' descriptions in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindStringSubmatchIndex(s string) []int {
+ return re.doExecute(newInputString(s), 0)
+}
+
+// FindReaderSubmatchIndex returns a slice holding the index pairs
+// identifying the leftmost match of the regular expression of text read by
+// the RuneReader, and the matches, if any, of its subexpressions, as defined
+// by the 'Submatch' and 'Index' descriptions in the package comment. A
+// return value of nil indicates no match.
+func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
+ return re.doExecute(newInputReader(r), 0)
+}
+
+const startSize = 10 // The size at which to start a slice in the 'All' routines.
+
+// FindAll is the 'All' version of Find; it returns a slice of all successive
+// matches of the expression, as defined by the 'All' description in the
+// package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAll(b []byte, n int) [][]byte {
+ if n < 0 {
+ n = len(b) + 1
+ }
+ result := make([][]byte, 0, startSize)
+ re.allMatches("", b, n, func(match []int) {
+ result = append(result, b[match[0]:match[1]])
+ })
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
+
+// FindAllIndex is the 'All' version of FindIndex; it returns a slice of all
+// successive matches of the expression, as defined by the 'All' description
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllIndex(b []byte, n int) [][]int {
+ if n < 0 {
+ n = len(b) + 1
+ }
+ result := make([][]int, 0, startSize)
+ re.allMatches("", b, n, func(match []int) {
+ result = append(result, match[0:2])
+ })
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
+
+// FindAllString is the 'All' version of FindString; it returns a slice of all
+// successive matches of the expression, as defined by the 'All' description
+// in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllString(s string, n int) []string {
+ if n < 0 {
+ n = len(s) + 1
+ }
+ result := make([]string, 0, startSize)
+ re.allMatches(s, nil, n, func(match []int) {
+ result = append(result, s[match[0]:match[1]])
+ })
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
+
+// FindAllStringIndex is the 'All' version of FindStringIndex; it returns a
+// slice of all successive matches of the expression, as defined by the 'All'
+// description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringIndex(s string, n int) [][]int {
+ if n < 0 {
+ n = len(s) + 1
+ }
+ result := make([][]int, 0, startSize)
+ re.allMatches(s, nil, n, func(match []int) {
+ result = append(result, match[0:2])
+ })
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
+
+// FindAllSubmatch is the 'All' version of FindSubmatch; it returns a slice
+// of all successive matches of the expression, as defined by the 'All'
+// description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllSubmatch(b []byte, n int) [][][]byte {
+ if n < 0 {
+ n = len(b) + 1
+ }
+ result := make([][][]byte, 0, startSize)
+ re.allMatches("", b, n, func(match []int) {
+ slice := make([][]byte, len(match)/2)
+ for j := range slice {
+ if match[2*j] >= 0 {
+ slice[j] = b[match[2*j]:match[2*j+1]]
+ }
+ }
+ result = append(result, slice)
+ })
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
+
+// FindAllSubmatchIndex is the 'All' version of FindSubmatchIndex; it returns
+// a slice of all successive matches of the expression, as defined by the
+// 'All' description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllSubmatchIndex(b []byte, n int) [][]int {
+ if n < 0 {
+ n = len(b) + 1
+ }
+ result := make([][]int, 0, startSize)
+ re.allMatches("", b, n, func(match []int) {
+ result = append(result, match)
+ })
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
+
+// FindAllStringSubmatch is the 'All' version of FindStringSubmatch; it
+// returns a slice of all successive matches of the expression, as defined by
+// the 'All' description in the package comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringSubmatch(s string, n int) [][]string {
+ if n < 0 {
+ n = len(s) + 1
+ }
+ result := make([][]string, 0, startSize)
+ re.allMatches(s, nil, n, func(match []int) {
+ slice := make([]string, len(match)/2)
+ for j := range slice {
+ if match[2*j] >= 0 {
+ slice[j] = s[match[2*j]:match[2*j+1]]
+ }
+ }
+ result = append(result, slice)
+ })
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
+
+// FindAllStringSubmatchIndex is the 'All' version of
+// FindStringSubmatchIndex; it returns a slice of all successive matches of
+// the expression, as defined by the 'All' description in the package
+// comment.
+// A return value of nil indicates no match.
+func (re *Regexp) FindAllStringSubmatchIndex(s string, n int) [][]int {
+ if n < 0 {
+ n = len(s) + 1
+ }
+ result := make([][]int, 0, startSize)
+ re.allMatches(s, nil, n, func(match []int) {
+ result = append(result, match)
+ })
+ if len(result) == 0 {
+ return nil
+ }
+ return result
+}
diff --git a/libgo/go/old/template/template_test.go b/libgo/go/old/template/template_test.go
index eae8011eb38..9595eb189b3 100644
--- a/libgo/go/old/template/template_test.go
+++ b/libgo/go/old/template/template_test.go
@@ -6,7 +6,6 @@ package template
import (
"bytes"
- "container/vector"
"fmt"
"io"
"io/ioutil"
@@ -42,7 +41,7 @@ type S struct {
Empty []*T
Emptystring string
Null []*T
- Vec *vector.Vector
+ Vec []interface{}
True bool
False bool
Mp map[string]string
@@ -497,9 +496,7 @@ func testAll(t *testing.T, parseFunc func(*Test) (*Template, os.Error)) {
s.Pdata = []*T{&t1, &t2}
s.Empty = []*T{}
s.Null = nil
- s.Vec = new(vector.Vector)
- s.Vec.Push("elt1")
- s.Vec.Push("elt2")
+ s.Vec = []interface{}{"elt1", "elt2"}
s.True = true
s.False = false
s.Mp = make(map[string]string)
diff --git a/libgo/go/os/dir_plan9.go b/libgo/go/os/dir_plan9.go
index bbc2cb64726..bf17005dd5c 100644
--- a/libgo/go/os/dir_plan9.go
+++ b/libgo/go/os/dir_plan9.go
@@ -295,6 +295,6 @@ func pstring(b []byte, s string) []byte {
panic(NewError("string too long"))
}
b = pbit16(b, uint16(len(s)))
- b = append(b, []byte(s)...)
+ b = append(b, s...)
return b
}
diff --git a/libgo/go/os/dir_unix.go b/libgo/go/os/dir_unix.go
index 7835ed52b55..52959339512 100644
--- a/libgo/go/os/dir_unix.go
+++ b/libgo/go/os/dir_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package os
import (
diff --git a/libgo/go/os/env.go b/libgo/go/os/env.go
index 3772c090b8f..4844fa3e26d 100644
--- a/libgo/go/os/env.go
+++ b/libgo/go/os/env.go
@@ -16,9 +16,9 @@ func Expand(s string, mapping func(string) string) string {
i := 0
for j := 0; j < len(s); j++ {
if s[j] == '$' && j+1 < len(s) {
- buf = append(buf, []byte(s[i:j])...)
+ buf = append(buf, s[i:j]...)
name, w := getShellName(s[j+1:])
- buf = append(buf, []byte(mapping(name))...)
+ buf = append(buf, mapping(name)...)
j += w
i = j + 1
}
diff --git a/libgo/go/os/env_unix.go b/libgo/go/os/env_unix.go
index 9cc0b03d877..8dd84ae4f3a 100644
--- a/libgo/go/os/env_unix.go
+++ b/libgo/go/os/env_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
// Unix environment variables.
package os
diff --git a/libgo/go/os/error_plan9.go b/libgo/go/os/error_plan9.go
index cacfc150c43..91ace6d97a8 100644
--- a/libgo/go/os/error_plan9.go
+++ b/libgo/go/os/error_plan9.go
@@ -48,6 +48,7 @@ var (
EPERM = Eperm
EISDIR = syscall.EISDIR
+ EBADF = NewError("bad file descriptor")
ENAMETOOLONG = NewError("file name too long")
ERANGE = NewError("math result not representable")
EPIPE = NewError("Broken Pipe")
diff --git a/libgo/go/os/error_posix.go b/libgo/go/os/error_posix.go
index d43f1786d37..9dc258a796b 100644
--- a/libgo/go/os/error_posix.go
+++ b/libgo/go/os/error_posix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
package os
import syscall "syscall"
diff --git a/libgo/go/os/exec_posix.go b/libgo/go/os/exec_posix.go
index f37bfab589a..035b156cbdc 100644
--- a/libgo/go/os/exec_posix.go
+++ b/libgo/go/os/exec_posix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
package os
import (
diff --git a/libgo/go/os/exec_unix.go b/libgo/go/os/exec_unix.go
index 8a4b2e1b806..e1adb203e0a 100644
--- a/libgo/go/os/exec_unix.go
+++ b/libgo/go/os/exec_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package os
import (
@@ -38,7 +40,8 @@ func (p *Process) Wait(options int) (w *Waitmsg, err Error) {
if e != 0 {
return nil, NewSyscallError("wait", e)
}
- if options&WSTOPPED == 0 {
+ // With WNOHANG pid is 0 if child has not exited.
+ if pid1 != 0 && options&WSTOPPED == 0 {
p.done = true
}
w = new(Waitmsg)
diff --git a/libgo/go/os/file_posix.go b/libgo/go/os/file_posix.go
index 0791a0dc04b..5269149565b 100644
--- a/libgo/go/os/file_posix.go
+++ b/libgo/go/os/file_posix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd windows
+
package os
import (
@@ -21,39 +23,6 @@ func epipecheck(file *File, e int) {
}
}
-// Stat returns a FileInfo structure describing the named file and an error, if any.
-// If name names a valid symbolic link, the returned FileInfo describes
-// the file pointed at by the link and has fi.FollowedSymlink set to true.
-// If name names an invalid symbolic link, the returned FileInfo describes
-// the link itself and has fi.FollowedSymlink set to false.
-func Stat(name string) (fi *FileInfo, err Error) {
- var lstat, stat syscall.Stat_t
- e := syscall.Lstat(name, &lstat)
- if iserror(e) {
- return nil, &PathError{"stat", name, Errno(e)}
- }
- statp := &lstat
- if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
- e := syscall.Stat(name, &stat)
- if !iserror(e) {
- statp = &stat
- }
- }
- return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
-}
-
-// Lstat returns the FileInfo structure describing the named file and an
-// error, if any. If the file is a symbolic link, the returned FileInfo
-// describes the symbolic link. Lstat makes no attempt to follow the link.
-func Lstat(name string) (fi *FileInfo, err Error) {
- var stat syscall.Stat_t
- e := syscall.Lstat(name, &stat)
- if iserror(e) {
- return nil, &PathError{"lstat", name, Errno(e)}
- }
- return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
-}
-
// Remove removes the named file or directory.
func Remove(name string) Error {
// System call interface forces us to know
@@ -79,7 +48,7 @@ func Remove(name string) Error {
// both errors will be ENOTDIR, so it's okay to
// use the error from unlink.
// For windows syscall.ENOTDIR is set
- // to syscall.ERROR_DIRECTORY, hopefully it should
+ // to syscall.ERROR_PATH_NOT_FOUND, hopefully it should
// do the trick.
if e1 != syscall.ENOTDIR {
e = e1
diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go
index 8243701ad24..0ebaf23e2db 100644
--- a/libgo/go/os/file_unix.go
+++ b/libgo/go/os/file_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package os
import (
@@ -100,6 +102,39 @@ func (file *File) Stat() (fi *FileInfo, err Error) {
return fileInfoFromStat(file.name, new(FileInfo), &stat, &stat), nil
}
+// Stat returns a FileInfo structure describing the named file and an error, if any.
+// If name names a valid symbolic link, the returned FileInfo describes
+// the file pointed at by the link and has fi.FollowedSymlink set to true.
+// If name names an invalid symbolic link, the returned FileInfo describes
+// the link itself and has fi.FollowedSymlink set to false.
+func Stat(name string) (fi *FileInfo, err Error) {
+ var lstat, stat syscall.Stat_t
+ e := syscall.Lstat(name, &lstat)
+ if iserror(e) {
+ return nil, &PathError{"stat", name, Errno(e)}
+ }
+ statp := &lstat
+ if lstat.Mode&syscall.S_IFMT == syscall.S_IFLNK {
+ e := syscall.Stat(name, &stat)
+ if !iserror(e) {
+ statp = &stat
+ }
+ }
+ return fileInfoFromStat(name, new(FileInfo), &lstat, statp), nil
+}
+
+// Lstat returns the FileInfo structure describing the named file and an
+// error, if any. If the file is a symbolic link, the returned FileInfo
+// describes the symbolic link. Lstat makes no attempt to follow the link.
+func Lstat(name string) (fi *FileInfo, err Error) {
+ var stat syscall.Stat_t
+ e := syscall.Lstat(name, &stat)
+ if iserror(e) {
+ return nil, &PathError{"lstat", name, Errno(e)}
+ }
+ return fileInfoFromStat(name, new(FileInfo), &stat, &stat), nil
+}
+
// Readdir reads the contents of the directory associated with file and
// returns an array of up to n FileInfo structures, as would be returned
// by Lstat, in directory order. Subsequent calls on the same file will yield
diff --git a/libgo/go/os/inotify/inotify_linux.go b/libgo/go/os/inotify/inotify_linux.go
index 99fa5162223..ee3c75f63b1 100644
--- a/libgo/go/os/inotify/inotify_linux.go
+++ b/libgo/go/os/inotify/inotify_linux.go
@@ -131,7 +131,7 @@ func (w *Watcher) RemoveWatch(path string) os.Error {
if success == -1 {
return os.NewSyscallError("inotify_rm_watch", errno)
}
- w.watches[path] = nil, false
+ delete(w.watches, path)
return nil
}
diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go
index 3f7d3063106..3277fc22bfa 100644
--- a/libgo/go/os/os_test.go
+++ b/libgo/go/os/os_test.go
@@ -918,6 +918,12 @@ func TestHostname(t *testing.T) {
if syscall.OS == "windows" || syscall.OS == "plan9" {
return
}
+
+ // TODO(jsing): Fix nametomib() on OpenBSD
+ if syscall.OS == "openbsd" {
+ return
+ }
+
// Check internal Hostname() against the output of /bin/hostname.
// Allow that the internal Hostname returns a Fully Qualified Domain Name
// and the /bin/hostname only returns the first component
diff --git a/libgo/go/os/path.go b/libgo/go/os/path.go
index a8dfce30752..b190c51e6d7 100644
--- a/libgo/go/os/path.go
+++ b/libgo/go/os/path.go
@@ -68,7 +68,7 @@ func RemoveAll(path string) Error {
// Otherwise, is this a directory we need to recurse into?
dir, serr := Lstat(path)
if serr != nil {
- if serr, ok := serr.(*PathError); ok && serr.Error == ENOENT {
+ if serr, ok := serr.(*PathError); ok && (serr.Error == ENOENT || serr.Error == ENOTDIR) {
return nil
}
return serr
diff --git a/libgo/go/os/path_unix.go b/libgo/go/os/path_unix.go
index 0d327cddd3e..33045b60c45 100644
--- a/libgo/go/os/path_unix.go
+++ b/libgo/go/os/path_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package os
const (
diff --git a/libgo/go/os/str.go b/libgo/go/os/str.go
index 8dc9e4747df..e3606b61eb4 100644
--- a/libgo/go/os/str.go
+++ b/libgo/go/os/str.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build plan9
+
package os
func itoa(val int) string { // do it here rather than with fmt to avoid dependency
diff --git a/libgo/go/os/sys_bsd.go b/libgo/go/os/sys_bsd.go
index 188993b6961..b0d097a22a2 100644
--- a/libgo/go/os/sys_bsd.go
+++ b/libgo/go/os/sys_bsd.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd openbsd
+
// os code shared between *BSD systems including OS X (Darwin)
// and FreeBSD.
diff --git a/libgo/go/os/user/lookup_stubs.go b/libgo/go/os/user/lookup_stubs.go
index 2f08f70fd57..2d2de989f06 100644
--- a/libgo/go/os/user/lookup_stubs.go
+++ b/libgo/go/os/user/lookup_stubs.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build openbsd plan9 windows
+
package user
import (
diff --git a/libgo/go/os/user/lookup_unix.go b/libgo/go/os/user/lookup_unix.go
index 0f04012c02f..3336b52d03f 100644
--- a/libgo/go/os/user/lookup_unix.go
+++ b/libgo/go/os/user/lookup_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux
+
package user
import (
@@ -27,6 +29,17 @@ static int mygetpwuid_r(int uid, struct passwd *pwd,
func libc_getpwnam_r(name *byte, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwnam_r")
func libc_getpwuid_r(uid syscall.Uid_t, pwd *syscall.Passwd, buf *byte, buflen syscall.Size_t, result **syscall.Passwd) int __asm__ ("getpwuid_r")
+// bytePtrToString takes a NUL-terminated array of bytes and convert
+// it to a Go string.
+func bytePtrToString(p *byte) string {
+ a := (*[10000]byte)(unsafe.Pointer(p))
+ i := 0
+ for a[i] != 0 {
+ i++
+ }
+ return string(a[:i])
+}
+
func init() {
implemented = true
}
@@ -78,9 +91,9 @@ func lookup(uid int, username string, lookupByName bool) (*User, os.Error) {
u := &User{
Uid: int(pwd.Pw_uid),
Gid: int(pwd.Pw_gid),
- Username: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
- Name: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
- HomeDir: syscall.BytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
+ Username: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_name))),
+ Name: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_gecos))),
+ HomeDir: bytePtrToString((*byte)(unsafe.Pointer(pwd.Pw_dir))),
}
// The pw_gecos field isn't quite standardized. Some docs
// say: "It is expected to be a comma separated list of
diff --git a/libgo/go/path/filepath/match.go b/libgo/go/path/filepath/match.go
index 7fcc214c058..0ccc87e6560 100644
--- a/libgo/go/path/filepath/match.go
+++ b/libgo/go/path/filepath/match.go
@@ -215,7 +215,7 @@ func getEsc(chunk string) (r int, nchunk string, err os.Error) {
func Glob(pattern string) (matches []string, err os.Error) {
if !hasMeta(pattern) {
if _, err = os.Stat(pattern); err != nil {
- return
+ return nil, nil
}
return []string{pattern}, nil
}
diff --git a/libgo/go/path/filepath/match_test.go b/libgo/go/path/filepath/match_test.go
index 5fc7b9ca6e6..fa7aad945f4 100644
--- a/libgo/go/path/filepath/match_test.go
+++ b/libgo/go/path/filepath/match_test.go
@@ -125,6 +125,16 @@ func TestGlob(t *testing.T) {
t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result)
}
}
+ for _, pattern := range []string{"no_match", "../*/no_match"} {
+ matches, err := Glob(pattern)
+ if err != nil {
+ t.Errorf("Glob error for %q: %s", pattern, err)
+ continue
+ }
+ if len(matches) != 0 {
+ t.Errorf("Glob(%#q) = %#v want []", pattern, matches)
+ }
+ }
}
func TestGlobError(t *testing.T) {
diff --git a/libgo/go/path/filepath/path.go b/libgo/go/path/filepath/path.go
index 3d5b915c101..afb8f102d57 100644
--- a/libgo/go/path/filepath/path.go
+++ b/libgo/go/path/filepath/path.go
@@ -41,9 +41,12 @@ func Clean(path string) string {
vol := VolumeName(path)
path = path[len(vol):]
if path == "" {
+ if len(vol) > 1 && vol[1] != ':' {
+ // should be UNC
+ return FromSlash(vol)
+ }
return vol + "."
}
-
rooted := os.IsPathSeparator(path[0])
// Invariants:
@@ -144,8 +147,9 @@ func SplitList(path string) []string {
// If there is no Separator in path, Split returns an empty dir
// and file set to path.
func Split(path string) (dir, file string) {
+ vol := VolumeName(path)
i := len(path) - 1
- for i >= 0 && !os.IsPathSeparator(path[i]) {
+ for i >= len(vol) && !os.IsPathSeparator(path[i]) {
i--
}
return path[:i+1], path[i+1:]
@@ -254,38 +258,132 @@ func Abs(path string) (string, os.Error) {
return Join(wd, path), nil
}
-// Visitor methods are invoked for corresponding file tree entries
-// visited by Walk. The parameter path is the full path of f relative
-// to root.
-type Visitor interface {
- VisitDir(path string, f *os.FileInfo) bool
- VisitFile(path string, f *os.FileInfo)
+// Rel returns a relative path that is lexically equivalent to targpath when
+// joined to basepath with an intervening separator. That is,
+// Join(basepath, Rel(basepath, targpath)) is equivalent to targpath itself.
+// An error is returned if targpath can't be made relative to basepath or if
+// knowing the current working directory would be necessary to compute it.
+func Rel(basepath, targpath string) (string, os.Error) {
+ baseVol := VolumeName(basepath)
+ targVol := VolumeName(targpath)
+ base := Clean(basepath)
+ targ := Clean(targpath)
+ if targ == base {
+ return ".", nil
+ }
+ base = base[len(baseVol):]
+ targ = targ[len(targVol):]
+ if base == "." {
+ base = ""
+ }
+ // Can't use IsAbs - `\a` and `a` are both relative in Windows.
+ baseSlashed := len(base) > 0 && base[0] == Separator
+ targSlashed := len(targ) > 0 && targ[0] == Separator
+ if baseSlashed != targSlashed || baseVol != targVol {
+ return "", os.NewError("Rel: can't make " + targ + " relative to " + base)
+ }
+ // Position base[b0:bi] and targ[t0:ti] at the first differing elements.
+ bl := len(base)
+ tl := len(targ)
+ var b0, bi, t0, ti int
+ for {
+ for bi < bl && base[bi] != Separator {
+ bi++
+ }
+ for ti < tl && targ[ti] != Separator {
+ ti++
+ }
+ if targ[t0:ti] != base[b0:bi] {
+ break
+ }
+ if bi < bl {
+ bi++
+ }
+ if ti < tl {
+ ti++
+ }
+ b0 = bi
+ t0 = ti
+ }
+ if base[b0:bi] == ".." {
+ return "", os.NewError("Rel: can't make " + targ + " relative to " + base)
+ }
+ if b0 != bl {
+ // Base elements left. Must go up before going down.
+ seps := strings.Count(base[b0:bl], string(Separator))
+ buf := make([]byte, 3+seps*3+tl-t0)
+ n := copy(buf, "..")
+ for i := 0; i < seps; i++ {
+ buf[n] = Separator
+ copy(buf[n+1:], "..")
+ n += 3
+ }
+ if t0 != tl {
+ buf[n] = Separator
+ copy(buf[n+1:], targ[t0:])
+ }
+ return string(buf), nil
+ }
+ return targ[t0:], nil
}
-func walk(path string, f *os.FileInfo, v Visitor, errors chan<- os.Error) {
- if !f.IsDirectory() {
- v.VisitFile(path, f)
- return
+// SkipDir is used as a return value from WalkFuncs to indicate that
+// the directory named in the call is to be skipped. It is not returned
+// as an error by any function.
+var SkipDir = os.NewError("skip this directory")
+
+// WalkFunc is the type of the function called for each file or directory
+// visited by Walk. If there was a problem walking to the file or directory
+// named by path, the incoming error will describe the problem and the
+// function can decide how to handle that error (and Walk will not descend
+// into that directory). If an error is returned, processing stops. The
+// sole exception is that if path is a directory and the function returns the
+// special value SkipDir, the contents of the directory are skipped
+// and processing continues as usual on the next file.
+type WalkFunc func(path string, info *os.FileInfo, err os.Error) os.Error
+
+// walk recursively descends path, calling w.
+func walk(path string, info *os.FileInfo, walkFn WalkFunc) os.Error {
+ err := walkFn(path, info, nil)
+ if err != nil {
+ if info.IsDirectory() && err == SkipDir {
+ return nil
+ }
+ return err
}
- if !v.VisitDir(path, f) {
- return // skip directory entries
+ if !info.IsDirectory() {
+ return nil
}
list, err := readDir(path)
if err != nil {
- if errors != nil {
- errors <- err
+ return walkFn(path, info, err)
+ }
+
+ for _, fileInfo := range list {
+ if err = walk(Join(path, fileInfo.Name), fileInfo, walkFn); err != nil {
+ return err
}
}
+ return nil
+}
- for _, e := range list {
- walk(Join(path, e.Name), e, v, errors)
+// Walk walks the file tree rooted at root, calling walkFn for each file or
+// directory in the tree, including root. All errors that arise visiting files
+// and directories are filtered by walkFn. The files are walked in lexical
+// order, which makes the output deterministic but means that for very
+// large directories Walk can be inefficient.
+func Walk(root string, walkFn WalkFunc) os.Error {
+ info, err := os.Lstat(root)
+ if err != nil {
+ return walkFn(root, nil, err)
}
+ return walk(root, info, walkFn)
}
// readDir reads the directory named by dirname and returns
-// a list of sorted directory entries.
+// a sorted list of directory entries.
// Copied from io/ioutil to avoid the circular import.
func readDir(dirname string) ([]*os.FileInfo, os.Error) {
f, err := os.Open(dirname)
@@ -312,24 +410,6 @@ func (f fileInfoList) Len() int { return len(f) }
func (f fileInfoList) Less(i, j int) bool { return f[i].Name < f[j].Name }
func (f fileInfoList) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
-// Walk walks the file tree rooted at root, calling v.VisitDir or
-// v.VisitFile for each directory or file in the tree, including root.
-// If v.VisitDir returns false, Walk skips the directory's entries;
-// otherwise it invokes itself for each directory entry in sorted order.
-// An error reading a directory does not abort the Walk.
-// If errors != nil, Walk sends each directory read error
-// to the channel. Otherwise Walk discards the error.
-func Walk(root string, v Visitor, errors chan<- os.Error) {
- f, err := os.Lstat(root)
- if err != nil {
- if errors != nil {
- errors <- err
- }
- return // can't progress
- }
- walk(root, f, v, errors)
-}
-
// Base returns the last element of path.
// Trailing path separators are removed before extracting the last element.
// If the path is empty, Base returns ".".
diff --git a/libgo/go/path/filepath/path_test.go b/libgo/go/path/filepath/path_test.go
index e944bf4edb0..f8e055b9fc3 100644
--- a/libgo/go/path/filepath/path_test.go
+++ b/libgo/go/path/filepath/path_test.go
@@ -72,15 +72,23 @@ var wincleantests = []PathTest{
{`c:\abc`, `c:\abc`},
{`c:abc\..\..\.\.\..\def`, `c:..\..\def`},
{`c:\abc\def\..\..`, `c:\`},
+ {`c:\..\abc`, `c:\abc`},
{`c:..\abc`, `c:..\abc`},
{`\`, `\`},
{`/`, `\`},
+ {`\\i\..\c$`, `\c$`},
+ {`\\i\..\i\c$`, `\i\c$`},
+ {`\\i\..\I\c$`, `\I\c$`},
+ {`\\host\share\foo\..\bar`, `\\host\share\bar`},
+ {`//host/share/foo/../baz`, `\\host\share\baz`},
+ {`\\a\b\..\c`, `\\a\b\c`},
+ {`\\a\b`, `\\a\b`},
}
func TestClean(t *testing.T) {
tests := cleantests
if runtime.GOOS == "windows" {
- for i, _ := range tests {
+ for i := range tests {
tests[i].result = filepath.FromSlash(tests[i].result)
}
tests = append(tests, wincleantests...)
@@ -145,9 +153,25 @@ var unixsplittests = []SplitTest{
{"/", "/", ""},
}
+var winsplittests = []SplitTest{
+ {`c:`, `c:`, ``},
+ {`c:/`, `c:/`, ``},
+ {`c:/foo`, `c:/`, `foo`},
+ {`c:/foo/bar`, `c:/foo/`, `bar`},
+ {`//host/share`, `//host/share`, ``},
+ {`//host/share/`, `//host/share/`, ``},
+ {`//host/share/foo`, `//host/share/`, `foo`},
+ {`\\host\share`, `\\host\share`, ``},
+ {`\\host\share\`, `\\host\share\`, ``},
+ {`\\host\share\foo`, `\\host\share\`, `foo`},
+}
+
func TestSplit(t *testing.T) {
var splittests []SplitTest
splittests = unixsplittests
+ if runtime.GOOS == "windows" {
+ splittests = append(splittests, winsplittests...)
+ }
for _, test := range splittests {
if d, f := filepath.Split(test.path); d != test.dir || f != test.file {
t.Errorf("Split(%q) = %q, %q, want %q, %q", test.path, d, f, test.dir, test.file)
@@ -185,6 +209,8 @@ var winjointests = []JoinTest{
{[]string{`C:\Windows\`, ``}, `C:\Windows`},
{[]string{`C:\`, `Windows`}, `C:\Windows`},
{[]string{`C:`, `Windows`}, `C:\Windows`},
+ {[]string{`\\host\share`, `foo`}, `\\host\share\foo`},
+ {[]string{`//host/share`, `foo/bar`}, `\\host\share\foo\bar`},
}
// join takes a []string and passes it to Join.
@@ -279,9 +305,9 @@ func makeTree(t *testing.T) {
func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) }
-func checkMarks(t *testing.T) {
+func checkMarks(t *testing.T, report bool) {
walkTree(tree, tree.name, func(path string, n *Node) {
- if n.mark != 1 {
+ if n.mark != 1 && report {
t.Errorf("node %s mark = %d; expected 1", path, n.mark)
}
n.mark = 0
@@ -289,44 +315,41 @@ func checkMarks(t *testing.T) {
}
// Assumes that each node name is unique. Good enough for a test.
-func mark(name string) {
- name = filepath.ToSlash(name)
+// If clear is true, any incoming error is cleared before return. The errors
+// are always accumulated, though.
+func mark(path string, info *os.FileInfo, err os.Error, errors *[]os.Error, clear bool) os.Error {
+ if err != nil {
+ *errors = append(*errors, err)
+ if clear {
+ return nil
+ }
+ return err
+ }
walkTree(tree, tree.name, func(path string, n *Node) {
- if n.name == name {
+ if n.name == info.Name {
n.mark++
}
})
-}
-
-type TestVisitor struct{}
-
-func (v *TestVisitor) VisitDir(path string, f *os.FileInfo) bool {
- mark(f.Name)
- return true
-}
-
-func (v *TestVisitor) VisitFile(path string, f *os.FileInfo) {
- mark(f.Name)
+ return nil
}
func TestWalk(t *testing.T) {
makeTree(t)
-
- // 1) ignore error handling, expect none
- v := &TestVisitor{}
- filepath.Walk(tree.name, v, nil)
- checkMarks(t)
-
- // 2) handle errors, expect none
- errors := make(chan os.Error, 64)
- filepath.Walk(tree.name, v, errors)
- select {
- case err := <-errors:
+ errors := make([]os.Error, 0, 10)
+ clear := true
+ markFn := func(path string, info *os.FileInfo, err os.Error) os.Error {
+ return mark(path, info, err, &errors, clear)
+ }
+ // Expect no errors.
+ err := filepath.Walk(tree.name, markFn)
+ if err != nil {
t.Errorf("no error expected, found: %s", err)
- default:
- // ok
}
- checkMarks(t)
+ if len(errors) != 0 {
+ t.Errorf("unexpected errors: %s", errors)
+ }
+ checkMarks(t, true)
+ errors = errors[0:0]
// Test permission errors. Only possible if we're not root
// and only on some file systems (AFS, FAT). To avoid errors during
@@ -335,40 +358,50 @@ func TestWalk(t *testing.T) {
// introduce 2 errors: chmod top-level directories to 0
os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0)
os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0)
+
+ // 3) capture errors, expect two.
// mark respective subtrees manually
markTree(tree.entries[1])
markTree(tree.entries[3])
// correct double-marking of directory itself
tree.entries[1].mark--
tree.entries[3].mark--
+ err := filepath.Walk(tree.name, markFn)
+ if err != nil {
+ t.Errorf("expected no error return from Walk, %s", err)
+ }
+ if len(errors) != 2 {
+ t.Errorf("expected 2 errors, got %d: %s", len(errors), errors)
+ }
+ // the inaccessible subtrees were marked manually
+ checkMarks(t, true)
+ errors = errors[0:0]
- // 3) handle errors, expect two
- errors = make(chan os.Error, 64)
- os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0)
- filepath.Walk(tree.name, v, errors)
- Loop:
- for i := 1; i <= 2; i++ {
- select {
- case <-errors:
- // ok
- default:
- t.Errorf("%d. error expected, none found", i)
- break Loop
- }
+ // 4) capture errors, stop after first error.
+ // mark respective subtrees manually
+ markTree(tree.entries[1])
+ markTree(tree.entries[3])
+ // correct double-marking of directory itself
+ tree.entries[1].mark--
+ tree.entries[3].mark--
+ clear = false // error will stop processing
+ err = filepath.Walk(tree.name, markFn)
+ if err == nil {
+ t.Errorf("expected error return from Walk")
}
- select {
- case err := <-errors:
- t.Errorf("only two errors expected, found 3rd: %v", err)
- default:
- // ok
+ if len(errors) != 1 {
+ t.Errorf("expected 1 error, got %d: %s", len(errors), errors)
}
// the inaccessible subtrees were marked manually
- checkMarks(t)
+ checkMarks(t, false)
+ errors = errors[0:0]
+
+ // restore permissions
+ os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770)
+ os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770)
}
// cleanup
- os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770)
- os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770)
if err := os.RemoveAll(tree.name); err != nil {
t.Errorf("removeTree: %v", err)
}
@@ -421,6 +454,8 @@ var winisabstests = []IsAbsTest{
{`\`, false},
{`\Windows`, false},
{`c:a\b`, false},
+ {`\\host\share\foo`, true},
+ {`//host/share/foo/bar`, true},
}
func TestIsAbs(t *testing.T) {
@@ -540,10 +575,11 @@ var abstests = []string{
"pkg/../../AUTHORS",
"Make.pkg",
"pkg/Makefile",
-
- // Already absolute
+ ".",
"$GOROOT/src/Make.pkg",
"$GOROOT/src/../src/Make.pkg",
+ "$GOROOT/misc/cgo",
+ "$GOROOT",
}
func TestAbs(t *testing.T) {
@@ -557,14 +593,15 @@ func TestAbs(t *testing.T) {
os.Chdir(cwd)
for _, path := range abstests {
path = strings.Replace(path, "$GOROOT", goroot, -1)
- abspath, err := filepath.Abs(path)
- if err != nil {
- t.Errorf("Abs(%q) error: %v", path, err)
- }
info, err := os.Stat(path)
if err != nil {
t.Errorf("%s: %s", path, err)
}
+
+ abspath, err := filepath.Abs(path)
+ if err != nil {
+ t.Errorf("Abs(%q) error: %v", path, err)
+ }
absinfo, err := os.Stat(abspath)
if err != nil || absinfo.Ino != info.Ino {
t.Errorf("Abs(%q)=%q, not the same file", path, abspath)
@@ -579,3 +616,114 @@ func TestAbs(t *testing.T) {
}
*/
+
+type RelTests struct {
+ root, path, want string
+}
+
+var reltests = []RelTests{
+ {"a/b", "a/b", "."},
+ {"a/b/.", "a/b", "."},
+ {"a/b", "a/b/.", "."},
+ {"./a/b", "a/b", "."},
+ {"a/b", "./a/b", "."},
+ {"ab/cd", "ab/cde", "../cde"},
+ {"ab/cd", "ab/c", "../c"},
+ {"a/b", "a/b/c/d", "c/d"},
+ {"a/b", "a/b/../c", "../c"},
+ {"a/b/../c", "a/b", "../b"},
+ {"a/b/c", "a/c/d", "../../c/d"},
+ {"a/b", "c/d", "../../c/d"},
+ {"../../a/b", "../../a/b/c/d", "c/d"},
+ {"/a/b", "/a/b", "."},
+ {"/a/b/.", "/a/b", "."},
+ {"/a/b", "/a/b/.", "."},
+ {"/ab/cd", "/ab/cde", "../cde"},
+ {"/ab/cd", "/ab/c", "../c"},
+ {"/a/b", "/a/b/c/d", "c/d"},
+ {"/a/b", "/a/b/../c", "../c"},
+ {"/a/b/../c", "/a/b", "../b"},
+ {"/a/b/c", "/a/c/d", "../../c/d"},
+ {"/a/b", "/c/d", "../../c/d"},
+ {"/../../a/b", "/../../a/b/c/d", "c/d"},
+ {".", "a/b", "a/b"},
+ {".", "..", ".."},
+
+ // can't do purely lexically
+ {"..", ".", "err"},
+ {"..", "a", "err"},
+ {"../..", "..", "err"},
+ {"a", "/a", "err"},
+ {"/a", "a", "err"},
+}
+
+var winreltests = []RelTests{
+ {`C:a\b\c`, `C:a/b/d`, `..\d`},
+ {`C:\`, `D:\`, `err`},
+ {`C:`, `D:`, `err`},
+}
+
+func TestRel(t *testing.T) {
+ tests := append([]RelTests{}, reltests...)
+ if runtime.GOOS == "windows" {
+ for i := range tests {
+ tests[i].want = filepath.FromSlash(tests[i].want)
+ }
+ tests = append(tests, winreltests...)
+ }
+ for _, test := range tests {
+ got, err := filepath.Rel(test.root, test.path)
+ if test.want == "err" {
+ if err == nil {
+ t.Errorf("Rel(%q, %q)=%q, want error", test.root, test.path, got)
+ }
+ continue
+ }
+ if err != nil {
+ t.Errorf("Rel(%q, %q): want %q, got error: %s", test.root, test.path, test.want, err)
+ }
+ if got != test.want {
+ t.Errorf("Rel(%q, %q)=%q, want %q", test.root, test.path, got, test.want)
+ }
+ }
+}
+
+type VolumeNameTest struct {
+ path string
+ vol string
+}
+
+var volumenametests = []VolumeNameTest{
+ {`c:/foo/bar`, `c:`},
+ {`c:`, `c:`},
+ {``, ``},
+ {`\\\host`, ``},
+ {`\\\host\`, ``},
+ {`\\\host\share`, ``},
+ {`\\\host\\share`, ``},
+ {`\\host`, ``},
+ {`//host`, ``},
+ {`\\host\`, ``},
+ {`//host/`, ``},
+ {`\\host\share`, `\\host\share`},
+ {`//host/share`, `//host/share`},
+ {`\\host\share\`, `\\host\share`},
+ {`//host/share/`, `//host/share`},
+ {`\\host\share\foo`, `\\host\share`},
+ {`//host/share/foo`, `//host/share`},
+ {`\\host\share\\foo\\\bar\\\\baz`, `\\host\share`},
+ {`//host/share//foo///bar////baz`, `//host/share`},
+ {`\\host\share\foo\..\bar`, `\\host\share`},
+ {`//host/share/foo/../bar`, `//host/share`},
+}
+
+func TestVolumeName(t *testing.T) {
+ if runtime.GOOS != "windows" {
+ return
+ }
+ for _, v := range volumenametests {
+ if vol := filepath.VolumeName(v.path); vol != v.vol {
+ t.Errorf("VolumeName(%q)=%q, want %q", v.path, vol, v.vol)
+ }
+ }
+}
diff --git a/libgo/go/path/filepath/path_unix.go b/libgo/go/path/filepath/path_unix.go
index b2a4151c1a8..daf0eb2af7c 100644
--- a/libgo/go/path/filepath/path_unix.go
+++ b/libgo/go/path/filepath/path_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
package filepath
import "strings"
diff --git a/libgo/go/path/filepath/path_windows.go b/libgo/go/path/filepath/path_windows.go
index 2535697fd9e..9692fd978c5 100644
--- a/libgo/go/path/filepath/path_windows.go
+++ b/libgo/go/path/filepath/path_windows.go
@@ -4,7 +4,13 @@
package filepath
-import "strings"
+import (
+ "strings"
+)
+
+func isSlash(c uint8) bool {
+ return c == '\\' || c == '/'
+}
// IsAbs returns true if the path is absolute.
func IsAbs(path string) (b bool) {
@@ -16,11 +22,12 @@ func IsAbs(path string) (b bool) {
if path == "" {
return false
}
- return path[0] == '/' || path[0] == '\\'
+ return isSlash(path[0])
}
// VolumeName returns leading volume name.
// Given "C:\foo\bar" it returns "C:" under windows.
+// Given "\\host\share\foo" it returns "\\host\share".
// On other platforms it returns "".
func VolumeName(path string) (v string) {
if len(path) < 2 {
@@ -33,6 +40,30 @@ func VolumeName(path string) (v string) {
'A' <= c && c <= 'Z') {
return path[:2]
}
+ // is it UNC
+ if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
+ !isSlash(path[2]) && path[2] != '.' {
+ // first, leading `\\` and next shouldn't be `\`. its server name.
+ for n := 3; n < l-1; n++ {
+ // second, next '\' shouldn't be repeated.
+ if isSlash(path[n]) {
+ n++
+ // third, following something characters. its share name.
+ if !isSlash(path[n]) {
+ if path[n] == '.' {
+ break
+ }
+ for ; n < l; n++ {
+ if isSlash(path[n]) {
+ break
+ }
+ }
+ return path[:n]
+ }
+ break
+ }
+ }
+ }
return ""
}
diff --git a/libgo/go/rand/rand_test.go b/libgo/go/rand/rand_test.go
index 3ebc1141d1a..f997ff56c7b 100644
--- a/libgo/go/rand/rand_test.go
+++ b/libgo/go/rand/rand_test.go
@@ -30,11 +30,11 @@ func max(a, b float64) float64 {
}
func nearEqual(a, b, closeEnough, maxError float64) bool {
- absDiff := math.Fabs(a - b)
+ absDiff := math.Abs(a - b)
if absDiff < closeEnough { // Necessary when one value is zero and one value is close to zero.
return true
}
- return absDiff/max(math.Fabs(a), math.Fabs(b)) < maxError
+ return absDiff/max(math.Abs(a), math.Abs(b)) < maxError
}
var testSeeds = []int64{1, 1754801282, 1698661970, 1550503961}
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index b8c609ab87e..696bd56637e 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -6,7 +6,7 @@ package reflect_test
import (
"bytes"
- "container/vector"
+ "encoding/base64"
"fmt"
"io"
"os"
@@ -853,13 +853,13 @@ func TestIsNil(t *testing.T) {
func TestInterfaceExtraction(t *testing.T) {
var s struct {
- w io.Writer
+ W io.Writer
}
- s.w = os.Stdout
+ s.W = os.Stdout
v := Indirect(ValueOf(&s)).Field(0).Interface()
- if v != s.w.(interface{}) {
- t.Error("Interface() on interface: ", v, s.w)
+ if v != s.W.(interface{}) {
+ t.Error("Interface() on interface: ", v, s.W)
}
}
@@ -877,19 +877,20 @@ func TestMap(t *testing.T) {
t.Errorf("Len = %d, want %d", n, len(m))
}
keys := mv.MapKeys()
- i := 0
newmap := MakeMap(mv.Type())
for k, v := range m {
// Check that returned Keys match keys in range.
- // These aren't required to be in the same order,
- // but they are in this implementation, which makes
- // the test easier.
- if i >= len(keys) {
- t.Errorf("Missing key #%d %q", i, k)
- } else if kv := keys[i]; kv.String() != k {
- t.Errorf("Keys[%q] = %d, want %d", i, kv.Int(), k)
+ // These aren't required to be in the same order.
+ seen := false
+ for _, kv := range keys {
+ if kv.String() == k {
+ seen = true
+ break
+ }
+ }
+ if !seen {
+ t.Errorf("Missing key %q", k)
}
- i++
// Check that value lookup is correct.
vv := mv.MapIndex(ValueOf(k))
@@ -1190,18 +1191,18 @@ type D2 struct {
}
type S0 struct {
- a, b, c int
+ A, B, C int
D1
D2
}
type S1 struct {
- b int
+ B int
S0
}
type S2 struct {
- a int
+ A int
*S1
}
@@ -1216,36 +1217,36 @@ type S1y struct {
type S3 struct {
S1x
S2
- d, e int
+ D, E int
*S1y
}
type S4 struct {
*S4
- a int
+ A int
}
var fieldTests = []FTest{
{struct{}{}, "", nil, 0},
- {struct{}{}, "foo", nil, 0},
- {S0{a: 'a'}, "a", []int{0}, 'a'},
- {S0{}, "d", nil, 0},
- {S1{S0: S0{a: 'a'}}, "a", []int{1, 0}, 'a'},
- {S1{b: 'b'}, "b", []int{0}, 'b'},
+ {struct{}{}, "Foo", nil, 0},
+ {S0{A: 'a'}, "A", []int{0}, 'a'},
+ {S0{}, "D", nil, 0},
+ {S1{S0: S0{A: 'a'}}, "A", []int{1, 0}, 'a'},
+ {S1{B: 'b'}, "B", []int{0}, 'b'},
{S1{}, "S0", []int{1}, 0},
- {S1{S0: S0{c: 'c'}}, "c", []int{1, 2}, 'c'},
- {S2{a: 'a'}, "a", []int{0}, 'a'},
+ {S1{S0: S0{C: 'c'}}, "C", []int{1, 2}, 'c'},
+ {S2{A: 'a'}, "A", []int{0}, 'a'},
{S2{}, "S1", []int{1}, 0},
- {S2{S1: &S1{b: 'b'}}, "b", []int{1, 0}, 'b'},
- {S2{S1: &S1{S0: S0{c: 'c'}}}, "c", []int{1, 1, 2}, 'c'},
- {S2{}, "d", nil, 0},
+ {S2{S1: &S1{B: 'b'}}, "B", []int{1, 0}, 'b'},
+ {S2{S1: &S1{S0: S0{C: 'c'}}}, "C", []int{1, 1, 2}, 'c'},
+ {S2{}, "D", nil, 0},
{S3{}, "S1", nil, 0},
- {S3{S2: S2{a: 'a'}}, "a", []int{1, 0}, 'a'},
- {S3{}, "b", nil, 0},
- {S3{d: 'd'}, "d", []int{2}, 0},
- {S3{e: 'e'}, "e", []int{3}, 'e'},
- {S4{a: 'a'}, "a", []int{1}, 'a'},
- {S4{}, "b", nil, 0},
+ {S3{S2: S2{A: 'a'}}, "A", []int{1, 0}, 'a'},
+ {S3{}, "B", nil, 0},
+ {S3{D: 'd'}, "D", []int{2}, 0},
+ {S3{E: 'e'}, "E", []int{3}, 'e'},
+ {S4{A: 'a'}, "A", []int{1}, 'a'},
+ {S4{}, "B", nil, 0},
}
func TestFieldByIndex(t *testing.T) {
@@ -1322,8 +1323,8 @@ func TestFieldByName(t *testing.T) {
}
func TestImportPath(t *testing.T) {
- if path := TypeOf(vector.Vector{}).PkgPath(); path != "libgo_container.vector" {
- t.Errorf("TypeOf(vector.Vector{}).PkgPath() = %q, want \"libgo_container.vector\"", path)
+ if path := TypeOf(&base64.Encoding{}).Elem().PkgPath(); path != "libgo_encoding.base64" {
+ t.Errorf(`TypeOf(&base64.Encoding{}).Elem().PkgPath() = %q, want "libgo_encoding.base64"`, path)
}
}
@@ -1566,3 +1567,93 @@ func TestTagGet(t *testing.T) {
}
}
}
+
+func TestBytes(t *testing.T) {
+ type B []byte
+ x := B{1, 2, 3, 4}
+ y := ValueOf(x).Bytes()
+ if !bytes.Equal(x, y) {
+ t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
+ }
+ if &x[0] != &y[0] {
+ t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
+ }
+}
+
+func TestSetBytes(t *testing.T) {
+ type B []byte
+ var x B
+ y := []byte{1, 2, 3, 4}
+ ValueOf(&x).Elem().SetBytes(y)
+ if !bytes.Equal(x, y) {
+ t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
+ }
+ if &x[0] != &y[0] {
+ t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
+ }
+}
+
+type Private struct {
+ x int
+ y **int
+}
+
+func (p *Private) m() {
+}
+
+type Public struct {
+ X int
+ Y **int
+}
+
+func (p *Public) M() {
+}
+
+func TestUnexported(t *testing.T) {
+ var pub Public
+ v := ValueOf(&pub)
+ isValid(v.Elem().Field(0))
+ isValid(v.Elem().Field(1))
+ isValid(v.Elem().FieldByName("X"))
+ isValid(v.Elem().FieldByName("Y"))
+ isValid(v.Type().Method(0).Func)
+ isNonNil(v.Elem().Field(0).Interface())
+ isNonNil(v.Elem().Field(1).Interface())
+ isNonNil(v.Elem().FieldByName("X").Interface())
+ isNonNil(v.Elem().FieldByName("Y").Interface())
+ isNonNil(v.Type().Method(0).Func.Interface())
+
+ var priv Private
+ v = ValueOf(&priv)
+ isValid(v.Elem().Field(0))
+ isValid(v.Elem().Field(1))
+ isValid(v.Elem().FieldByName("x"))
+ isValid(v.Elem().FieldByName("y"))
+ isValid(v.Type().Method(0).Func)
+ shouldPanic(func() { v.Elem().Field(0).Interface() })
+ shouldPanic(func() { v.Elem().Field(1).Interface() })
+ shouldPanic(func() { v.Elem().FieldByName("x").Interface() })
+ shouldPanic(func() { v.Elem().FieldByName("y").Interface() })
+ shouldPanic(func() { v.Type().Method(0).Func.Interface() })
+}
+
+func shouldPanic(f func()) {
+ defer func() {
+ if recover() == nil {
+ panic("did not panic")
+ }
+ }()
+ f()
+}
+
+func isNonNil(x interface{}) {
+ if x == nil {
+ panic("nil interface")
+ }
+}
+
+func isValid(v Value) {
+ if !v.IsValid() {
+ panic("zero Value")
+ }
+}
diff --git a/libgo/go/reflect/deepequal.go b/libgo/go/reflect/deepequal.go
index a483135b017..63c28fe2024 100644
--- a/libgo/go/reflect/deepequal.go
+++ b/libgo/go/reflect/deepequal.go
@@ -104,7 +104,7 @@ func deepValueEqual(v1, v2 Value, visited map[uintptr]*visit, depth int) (b bool
return true
default:
// Normal equality suffices
- return v1.Interface() == v2.Interface()
+ return valueInterface(v1, false) == valueInterface(v2, false)
}
panic("Not reached")
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 6d0f4542431..9be7f830875 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -68,7 +68,7 @@ type Type interface {
Name() string
// PkgPath returns the type's package path.
- // The package path is a full package import path like "container/vector".
+ // The package path is a full package import path like "encoding/base64".
// PkgPath returns an empty string for unnamed types.
PkgPath() string
@@ -78,7 +78,7 @@ type Type interface {
// String returns a string representation of the type.
// The string representation may use shortened package names
- // (e.g., vector instead of "container/vector") and is not
+ // (e.g., base64 instead of "encoding/base64") and is not
// guaranteed to be unique among types. To test for equality,
// compare the Types directly.
String() string
@@ -717,7 +717,7 @@ type StructTag string
// Get returns the value associated with key in the tag string.
// If there is no such key in the tag, Get returns the empty string.
// If the tag does not have the conventional format, the value
-// returned by Get is unspecified,
+// returned by Get is unspecified.
func (tag StructTag) Get(key string) string {
for tag != "" {
// skip leading space
@@ -877,7 +877,7 @@ L:
fd = inf
}
- mark[t] = false, false
+ delete(mark, t)
return
}
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 6675a9a08d5..4a210758124 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -323,8 +323,31 @@ func packValue(flag uint32, typ *runtime.Type, word iword) Value {
return Value{Internal: *(*interface{})(unsafe.Pointer(&eface))}
}
+var dummy struct {
+ b bool
+ x interface{}
+}
+
+// Dummy annotation marking that the value x escapes,
+// for use in cases where the reflect code is so clever that
+// the compiler cannot follow.
+func escapes(x interface{}) {
+ if dummy.b {
+ dummy.x = x
+ }
+}
+
// valueFromAddr returns a Value using the given type and address.
func valueFromAddr(flag uint32, typ Type, addr unsafe.Pointer) Value {
+ // TODO(rsc): Eliminate this terrible hack.
+ // The escape analysis knows that addr is a pointer
+ // but it doesn't see addr get passed to anything
+ // that keeps it. packValue keeps it, but packValue
+ // takes a uintptr (iword(addr)), and integers (non-pointers)
+ // are assumed not to matter. The escapes function works
+ // because return values always escape (for now).
+ escapes(addr)
+
if flag&flagAddr != 0 {
// Addressable, so the internal value is
// an interface containing a pointer to the real value.
@@ -399,6 +422,18 @@ func (v Value) Bool() bool {
return *(*bool)(unsafe.Pointer(iv.addr))
}
+// Bytes returns v's underlying value.
+// It panics if v's underlying value is not a slice of bytes.
+func (v Value) Bytes() []byte {
+ iv := v.internal()
+ iv.mustBe(Slice)
+ typ := iv.typ.toType()
+ if typ.Elem().Kind() != Uint8 {
+ panic("reflect.Value.Bytes of non-byte slice")
+ }
+ return *(*[]byte)(iv.addr)
+}
+
// CanAddr returns true if the value's address can be obtained with Addr.
// Such values are called addressable. A value is addressable if it is
// an element of a slice, an element of an addressable array,
@@ -829,14 +864,7 @@ func (v Value) CanInterface() bool {
if iv.kind == Invalid {
panic(&ValueError{"reflect.Value.CanInterface", iv.kind})
}
- // TODO(rsc): Check flagRO too. Decide what to do about asking for
- // interface for a value obtained via an unexported field.
- // If the field were of a known type, say chan int or *sync.Mutex,
- // the caller could interfere with the data after getting the
- // interface. But fmt.Print depends on being able to look.
- // Now that reflect is more efficient the special cases in fmt
- // might be less important.
- return v.InternalMethod == 0
+ return v.InternalMethod == 0 && iv.flag&flagRO == 0
}
// Interface returns v's value as an interface{}.
@@ -844,22 +872,28 @@ func (v Value) CanInterface() bool {
// (as opposed to Type.Method), Interface cannot return an
// interface value, so it panics.
func (v Value) Interface() interface{} {
- return v.internal().Interface()
+ return valueInterface(v, true)
+}
+
+func valueInterface(v Value, safe bool) interface{} {
+ iv := v.internal()
+ return iv.valueInterface(safe)
}
-func (iv internalValue) Interface() interface{} {
+func (iv internalValue) valueInterface(safe bool) interface{} {
if iv.kind == 0 {
panic(&ValueError{"reflect.Value.Interface", iv.kind})
}
if iv.method {
panic("reflect.Value.Interface: cannot create interface value for method with bound receiver")
}
- /*
- if v.flag()&noExport != 0 {
- panic("reflect.Value.Interface: cannot return value obtained from unexported struct field")
- }
- */
+ if safe && iv.flag&flagRO != 0 {
+ // Do not allow access to unexported values via Interface,
+ // because they might be pointers that should not be
+ // writable or methods or function that should not be callable.
+ panic("reflect.Value.Interface: cannot return value obtained from unexported field or method")
+ }
if iv.kind == Interface {
// Special case: return the element inside the interface.
// Won't recurse further because an interface cannot contain an interface.
@@ -1222,6 +1256,19 @@ func (v Value) SetBool(x bool) {
*(*bool)(iv.addr) = x
}
+// SetBytes sets v's underlying value.
+// It panics if v's underlying value is not a slice of bytes.
+func (v Value) SetBytes(x []byte) {
+ iv := v.internal()
+ iv.mustBeAssignable()
+ iv.mustBe(Slice)
+ typ := iv.typ.toType()
+ if typ.Elem().Kind() != Uint8 {
+ panic("reflect.Value.SetBytes of non-byte slice")
+ }
+ *(*[]byte)(iv.addr) = x
+}
+
// SetComplex sets v's underlying value to x.
// It panics if v's Kind is not Complex64 or Complex128, or if CanSet() is false.
func (v Value) SetComplex(x complex128) {
@@ -1375,11 +1422,17 @@ func (v Value) Slice(beg, end int) Value {
typ = iv.typ.toType()
base = (*SliceHeader)(iv.addr).Data
}
- s := new(SliceHeader)
+
+ // Declare slice so that gc can see the base pointer in it.
+ var x []byte
+
+ // Reinterpret as *SliceHeader to edit.
+ s := (*SliceHeader)(unsafe.Pointer(&x))
s.Data = base + uintptr(beg)*typ.Elem().Size()
s.Len = end - beg
- s.Cap = cap - beg
- return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(s))
+ s.Cap = end - beg
+
+ return valueFromAddr(iv.flag&flagRO, typ, unsafe.Pointer(&x))
}
// String returns the string v's underlying value, as a string.
@@ -1394,6 +1447,8 @@ func (v Value) String() string {
case String:
return *(*string)(iv.addr)
}
+ // If you call String on a reflect.Value of other type, it's better to
+ // print something than to panic. Useful in debugging.
return "<" + iv.typ.String() + " Value>"
}
@@ -1600,12 +1655,17 @@ func MakeSlice(typ Type, len, cap int) Value {
if typ.Kind() != Slice {
panic("reflect: MakeSlice of non-slice type")
}
- s := &SliceHeader{
- Data: uintptr(unsafe.NewArray(typ.Elem(), cap)),
- Len: len,
- Cap: cap,
- }
- return valueFromAddr(0, typ, unsafe.Pointer(s))
+
+ // Declare slice so that gc can see the base pointer in it.
+ var x []byte
+
+ // Reinterpret as *SliceHeader to edit.
+ s := (*SliceHeader)(unsafe.Pointer(&x))
+ s.Data = uintptr(unsafe.NewArray(typ.Elem(), cap))
+ s.Len = len
+ s.Cap = cap
+
+ return valueFromAddr(0, typ, unsafe.Pointer(&x))
}
// MakeChan creates a new channel with the specified type and buffer size.
@@ -1648,6 +1708,14 @@ func ValueOf(i interface{}) Value {
if i == nil {
return Value{}
}
+
+ // TODO(rsc): Eliminate this terrible hack.
+ // In the call to packValue, eface.typ doesn't escape,
+ // and eface.word is an integer. So it looks like
+ // i (= eface) doesn't escape. But really it does,
+ // because eface.word is actually a pointer.
+ escapes(i)
+
// For an interface value with the noAddr bit set,
// the representation is identical to an empty interface.
eface := *(*emptyInterface)(unsafe.Pointer(&i))
@@ -1695,7 +1763,7 @@ func convertForAssignment(what string, addr unsafe.Pointer, dst Type, iv interna
if addr == nil {
addr = unsafe.Pointer(new(interface{}))
}
- x := iv.Interface()
+ x := iv.valueInterface(false)
if dst.NumMethod() == 0 {
*(*interface{})(addr) = x
} else {
diff --git a/libgo/go/regexp/all_test.go b/libgo/go/regexp/all_test.go
index 71edc4d18d3..77f32ca1a57 100644
--- a/libgo/go/regexp/all_test.go
+++ b/libgo/go/regexp/all_test.go
@@ -24,13 +24,13 @@ var good_re = []string{
`[a-z]`,
`[a-abc-c\-\]\[]`,
`[a-z]+`,
- `[]`,
`[abc]`,
`[^1234]`,
`[^\n]`,
`\!\\`,
}
+/*
type stringError struct {
re string
err os.Error
@@ -51,6 +51,7 @@ var bad_re = []stringError{
{`a??`, ErrBadClosure},
{`\x`, ErrBadBackslash},
}
+*/
func compileTest(t *testing.T, expr string, error os.Error) *Regexp {
re, err := Compile(expr)
@@ -66,11 +67,13 @@ func TestGoodCompile(t *testing.T) {
}
}
+/*
func TestBadCompile(t *testing.T) {
for i := 0; i < len(bad_re); i++ {
compileTest(t, bad_re[i].re, bad_re[i].err)
}
}
+*/
func matchTest(t *testing.T, test *FindTest) {
re := compileTest(t, test.pat, nil)
@@ -240,7 +243,7 @@ var metaTests = []MetaTest{
{`foo`, `foo`, `foo`, true},
{`foo\.\$`, `foo\\\.\\\$`, `foo.$`, true}, // has meta but no operator
{`foo.\$`, `foo\.\\\$`, `foo`, false}, // has escaped operators and real operators
- {`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[{\]}\\\|,<\.>/\?~`, `!@#`, false},
+ {`!@#$%^&*()_+-=[{]}\|,<.>/?~`, `!@#\$%\^&\*\(\)_\+-=\[\{\]\}\\\|,<\.>/\?~`, `!@#`, false},
}
func TestQuoteMeta(t *testing.T) {
diff --git a/libgo/go/regexp/exec.go b/libgo/go/regexp/exec.go
new file mode 100644
index 00000000000..3b0e3888524
--- /dev/null
+++ b/libgo/go/regexp/exec.go
@@ -0,0 +1,305 @@
+package regexp
+
+import "regexp/syntax"
+
+// A queue is a 'sparse array' holding pending threads of execution.
+// See http://research.swtch.com/2008/03/using-uninitialized-memory-for-fun-and.html
+type queue struct {
+ sparse []uint32
+ dense []entry
+}
+
+// A entry is an entry on a queue.
+// It holds both the instruction pc and the actual thread.
+// Some queue entries are just place holders so that the machine
+// knows it has considered that pc. Such entries have t == nil.
+type entry struct {
+ pc uint32
+ t *thread
+}
+
+// A thread is the state of a single path through the machine:
+// an instruction and a corresponding capture array.
+// See http://swtch.com/~rsc/regexp/regexp2.html
+type thread struct {
+ inst *syntax.Inst
+ cap []int
+}
+
+// A machine holds all the state during an NFA simulation for p.
+type machine struct {
+ re *Regexp // corresponding Regexp
+ p *syntax.Prog // compiled program
+ q0, q1 queue // two queues for runq, nextq
+ pool []*thread // pool of available threads
+ matched bool // whether a match was found
+ matchcap []int // capture information for the match
+}
+
+// progMachine returns a new machine running the prog p.
+func progMachine(p *syntax.Prog) *machine {
+ m := &machine{p: p}
+ n := len(m.p.Inst)
+ m.q0 = queue{make([]uint32, n), make([]entry, 0, n)}
+ m.q1 = queue{make([]uint32, n), make([]entry, 0, n)}
+ ncap := p.NumCap
+ if ncap < 2 {
+ ncap = 2
+ }
+ m.matchcap = make([]int, ncap)
+ return m
+}
+
+func (m *machine) init(ncap int) {
+ for _, t := range m.pool {
+ t.cap = t.cap[:ncap]
+ }
+ m.matchcap = m.matchcap[:ncap]
+}
+
+// alloc allocates a new thread with the given instruction.
+// It uses the free pool if possible.
+func (m *machine) alloc(i *syntax.Inst) *thread {
+ var t *thread
+ if n := len(m.pool); n > 0 {
+ t = m.pool[n-1]
+ m.pool = m.pool[:n-1]
+ } else {
+ t = new(thread)
+ t.cap = make([]int, len(m.matchcap), cap(m.matchcap))
+ }
+ t.inst = i
+ return t
+}
+
+// free returns t to the free pool.
+func (m *machine) free(t *thread) {
+ m.pool = append(m.pool, t)
+}
+
+// match runs the machine over the input starting at pos.
+// It reports whether a match was found.
+// If so, m.matchcap holds the submatch information.
+func (m *machine) match(i input, pos int) bool {
+ startCond := m.re.cond
+ if startCond == ^syntax.EmptyOp(0) { // impossible
+ return false
+ }
+ m.matched = false
+ for i := range m.matchcap {
+ m.matchcap[i] = -1
+ }
+ runq, nextq := &m.q0, &m.q1
+ rune, rune1 := endOfText, endOfText
+ width, width1 := 0, 0
+ rune, width = i.step(pos)
+ if rune != endOfText {
+ rune1, width1 = i.step(pos + width)
+ }
+ var flag syntax.EmptyOp
+ if pos == 0 {
+ flag = syntax.EmptyOpContext(-1, rune)
+ } else {
+ flag = i.context(pos)
+ }
+ for {
+ if len(runq.dense) == 0 {
+ if startCond&syntax.EmptyBeginText != 0 && pos != 0 {
+ // Anchored match, past beginning of text.
+ break
+ }
+ if m.matched {
+ // Have match; finished exploring alternatives.
+ break
+ }
+ if len(m.re.prefix) > 0 && rune1 != m.re.prefixRune && i.canCheckPrefix() {
+ // Match requires literal prefix; fast search for it.
+ advance := i.index(m.re, pos)
+ if advance < 0 {
+ break
+ }
+ pos += advance
+ rune, width = i.step(pos)
+ rune1, width1 = i.step(pos + width)
+ }
+ }
+ if !m.matched {
+ if len(m.matchcap) > 0 {
+ m.matchcap[0] = pos
+ }
+ m.add(runq, uint32(m.p.Start), pos, m.matchcap, flag, nil)
+ }
+ flag = syntax.EmptyOpContext(rune, rune1)
+ m.step(runq, nextq, pos, pos+width, rune, flag)
+ if width == 0 {
+ break
+ }
+ if len(m.matchcap) == 0 && m.matched {
+ // Found a match and not paying attention
+ // to where it is, so any match will do.
+ break
+ }
+ pos += width
+ rune, width = rune1, width1
+ if rune != endOfText {
+ rune1, width1 = i.step(pos + width)
+ }
+ runq, nextq = nextq, runq
+ }
+ m.clear(nextq)
+ return m.matched
+}
+
+// clear frees all threads on the thread queue.
+func (m *machine) clear(q *queue) {
+ for _, d := range q.dense {
+ if d.t != nil {
+ // m.free(d.t)
+ m.pool = append(m.pool, d.t)
+ }
+ }
+ q.dense = q.dense[:0]
+}
+
+// step executes one step of the machine, running each of the threads
+// on runq and appending new threads to nextq.
+// The step processes the rune c (which may be endOfText),
+// which starts at position pos and ends at nextPos.
+// nextCond gives the setting for the empty-width flags after c.
+func (m *machine) step(runq, nextq *queue, pos, nextPos, c int, nextCond syntax.EmptyOp) {
+ longest := m.re.longest
+ for j := 0; j < len(runq.dense); j++ {
+ d := &runq.dense[j]
+ t := d.t
+ if t == nil {
+ continue
+ }
+ if longest && m.matched && len(t.cap) > 0 && m.matchcap[0] < t.cap[0] {
+ // m.free(t)
+ m.pool = append(m.pool, t)
+ continue
+ }
+ i := t.inst
+ add := false
+ switch i.Op {
+ default:
+ panic("bad inst")
+
+ case syntax.InstMatch:
+ if len(t.cap) > 0 && (!longest || !m.matched || m.matchcap[1] < pos) {
+ t.cap[1] = pos
+ copy(m.matchcap, t.cap)
+ }
+ if !longest {
+ // First-match mode: cut off all lower-priority threads.
+ for _, d := range runq.dense[j+1:] {
+ if d.t != nil {
+ // m.free(d.t)
+ m.pool = append(m.pool, d.t)
+ }
+ }
+ runq.dense = runq.dense[:0]
+ }
+ m.matched = true
+
+ case syntax.InstRune:
+ add = i.MatchRune(c)
+ case syntax.InstRune1:
+ add = c == i.Rune[0]
+ case syntax.InstRuneAny:
+ add = true
+ case syntax.InstRuneAnyNotNL:
+ add = c != '\n'
+ }
+ if add {
+ t = m.add(nextq, i.Out, nextPos, t.cap, nextCond, t)
+ }
+ if t != nil {
+ // m.free(t)
+ m.pool = append(m.pool, t)
+ }
+ }
+ runq.dense = runq.dense[:0]
+}
+
+// add adds an entry to q for pc, unless the q already has such an entry.
+// It also recursively adds an entry for all instructions reachable from pc by following
+// empty-width conditions satisfied by cond. pos gives the current position
+// in the input.
+func (m *machine) add(q *queue, pc uint32, pos int, cap []int, cond syntax.EmptyOp, t *thread) *thread {
+ if pc == 0 {
+ return t
+ }
+ if j := q.sparse[pc]; j < uint32(len(q.dense)) && q.dense[j].pc == pc {
+ return t
+ }
+
+ j := len(q.dense)
+ q.dense = q.dense[:j+1]
+ d := &q.dense[j]
+ d.t = nil
+ d.pc = pc
+ q.sparse[pc] = uint32(j)
+
+ i := &m.p.Inst[pc]
+ switch i.Op {
+ default:
+ panic("unhandled")
+ case syntax.InstFail:
+ // nothing
+ case syntax.InstAlt, syntax.InstAltMatch:
+ t = m.add(q, i.Out, pos, cap, cond, t)
+ t = m.add(q, i.Arg, pos, cap, cond, t)
+ case syntax.InstEmptyWidth:
+ if syntax.EmptyOp(i.Arg)&^cond == 0 {
+ t = m.add(q, i.Out, pos, cap, cond, t)
+ }
+ case syntax.InstNop:
+ t = m.add(q, i.Out, pos, cap, cond, t)
+ case syntax.InstCapture:
+ if int(i.Arg) < len(cap) {
+ opos := cap[i.Arg]
+ cap[i.Arg] = pos
+ m.add(q, i.Out, pos, cap, cond, nil)
+ cap[i.Arg] = opos
+ } else {
+ t = m.add(q, i.Out, pos, cap, cond, t)
+ }
+ case syntax.InstMatch, syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny, syntax.InstRuneAnyNotNL:
+ if t == nil {
+ t = m.alloc(i)
+ } else {
+ t.inst = i
+ }
+ if len(cap) > 0 && &t.cap[0] != &cap[0] {
+ copy(t.cap, cap)
+ }
+ d.t = t
+ t = nil
+ }
+ return t
+}
+
+// empty is a non-nil 0-element slice,
+// so doExecute can avoid an allocation
+// when 0 captures are requested from a successful match.
+var empty = make([]int, 0)
+
+// doExecute finds the leftmost match in the input and returns
+// the position of its subexpressions.
+func (re *Regexp) doExecute(i input, pos int, ncap int) []int {
+ m := re.get()
+ m.init(ncap)
+ if !m.match(i, pos) {
+ re.put(m)
+ return nil
+ }
+ if ncap == 0 {
+ re.put(m)
+ return empty // empty but not nil
+ }
+ cap := make([]int, ncap)
+ copy(cap, m.matchcap)
+ re.put(m)
+ return cap
+}
diff --git a/libgo/go/regexp/exec_test.go b/libgo/go/regexp/exec_test.go
new file mode 100644
index 00000000000..905fd4ef12d
--- /dev/null
+++ b/libgo/go/regexp/exec_test.go
@@ -0,0 +1,734 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package regexp
+
+import (
+ "bufio"
+ "compress/bzip2"
+ "fmt"
+ "io"
+ old "old/regexp"
+ "os"
+ "path/filepath"
+ "rand"
+ "regexp/syntax"
+ "strconv"
+ "strings"
+ "testing"
+ "utf8"
+)
+
+// TestRE2 tests this package's regexp API against test cases
+// considered during RE2's exhaustive tests, which run all possible
+// regexps over a given set of atoms and operators, up to a given
+// complexity, over all possible strings over a given alphabet,
+// up to a given size. Rather than try to link with RE2, we read a
+// log file containing the test cases and the expected matches.
+// The log file, re2.txt, is generated by running 'make exhaustive-log'
+// in the open source RE2 distribution. http://code.google.com/p/re2/
+//
+// The test file format is a sequence of stanzas like:
+//
+// strings
+// "abc"
+// "123x"
+// regexps
+// "[a-z]+"
+// 0-3;0-3
+// -;-
+// "([0-9])([0-9])([0-9])"
+// -;-
+// -;0-3 0-1 1-2 2-3
+//
+// The stanza begins by defining a set of strings, quoted
+// using Go double-quote syntax, one per line. Then the
+// regexps section gives a sequence of regexps to run on
+// the strings. In the block that follows a regexp, each line
+// gives the semicolon-separated match results of running
+// the regexp on the corresponding string.
+// Each match result is either a single -, meaning no match, or a
+// space-separated sequence of pairs giving the match and
+// submatch indices. An unmatched subexpression formats
+// its pair as a single - (not illustrated above). For now
+// each regexp run produces two match results, one for a
+// ``full match'' that restricts the regexp to matching the entire
+// string or nothing, and one for a ``partial match'' that gives
+// the leftmost first match found in the string.
+//
+// Lines beginning with # are comments. Lines beginning with
+// a capital letter are test names printed during RE2's test suite
+// and are echoed into t but otherwise ignored.
+//
+// At time of writing, re2.txt is 32 MB but compresses to 760 kB,
+// so we store re2.txt.gz in the repository and decompress it on the fly.
+//
+func TestRE2Search(t *testing.T) {
+ testRE2(t, "testdata/re2-search.txt")
+}
+
+func TestRE2Exhaustive(t *testing.T) {
+ if testing.Short() {
+ t.Log("skipping TestRE2Exhaustive during short test")
+ return
+ }
+ testRE2(t, "testdata/re2-exhaustive.txt.bz2")
+}
+
+func testRE2(t *testing.T, file string) {
+ f, err := os.Open(file)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ var txt io.Reader
+ if strings.HasSuffix(file, ".bz2") {
+ z := bzip2.NewReader(f)
+ txt = z
+ file = file[:len(file)-len(".bz2")] // for error messages
+ } else {
+ txt = f
+ }
+ lineno := 0
+ r := bufio.NewReader(txt)
+ var (
+ str []string
+ input []string
+ inStrings bool
+ re *Regexp
+ refull *Regexp
+ nfail int
+ ncase int
+ )
+ for {
+ line, err := r.ReadString('\n')
+ if err != nil {
+ if err == os.EOF {
+ break
+ }
+ t.Fatalf("%s:%d: %v", file, lineno, err)
+ }
+ line = line[:len(line)-1] // chop \n
+ lineno++
+ switch {
+ case line == "":
+ t.Fatalf("%s:%d: unexpected blank line", file, lineno)
+ case line[0] == '#':
+ continue
+ case 'A' <= line[0] && line[0] <= 'Z':
+ // Test name.
+ t.Logf("%s\n", line)
+ continue
+ case line == "strings":
+ str = str[:0]
+ inStrings = true
+ case line == "regexps":
+ inStrings = false
+ case line[0] == '"':
+ q, err := strconv.Unquote(line)
+ if err != nil {
+ // Fatal because we'll get out of sync.
+ t.Fatalf("%s:%d: unquote %s: %v", file, lineno, line, err)
+ }
+ if inStrings {
+ str = append(str, q)
+ continue
+ }
+ // Is a regexp.
+ if len(input) != 0 {
+ t.Fatalf("%s:%d: out of sync: have %d strings left before %#q", file, lineno, len(input), q)
+ }
+ re, err = tryCompile(q)
+ if err != nil {
+ if err.String() == "error parsing regexp: invalid escape sequence: `\\C`" {
+ // We don't and likely never will support \C; keep going.
+ continue
+ }
+ t.Errorf("%s:%d: compile %#q: %v", file, lineno, q, err)
+ if nfail++; nfail >= 100 {
+ t.Fatalf("stopping after %d errors", nfail)
+ }
+ continue
+ }
+ full := `\A(?:` + q + `)\z`
+ refull, err = tryCompile(full)
+ if err != nil {
+ // Fatal because q worked, so this should always work.
+ t.Fatalf("%s:%d: compile full %#q: %v", file, lineno, full, err)
+ }
+ input = str
+ case line[0] == '-' || '0' <= line[0] && line[0] <= '9':
+ // A sequence of match results.
+ ncase++
+ if re == nil {
+ // Failed to compile: skip results.
+ continue
+ }
+ if len(input) == 0 {
+ t.Fatalf("%s:%d: out of sync: no input remaining", file, lineno)
+ }
+ var text string
+ text, input = input[0], input[1:]
+ if !isSingleBytes(text) && strings.Contains(re.String(), `\B`) {
+ // RE2's \B considers every byte position,
+ // so it sees 'not word boundary' in the
+ // middle of UTF-8 sequences. This package
+ // only considers the positions between runes,
+ // so it disagrees. Skip those cases.
+ continue
+ }
+ res := strings.Split(line, ";")
+ if len(res) != len(run) {
+ t.Fatalf("%s:%d: have %d test results, want %d", file, lineno, len(res), len(run))
+ }
+ for i := range res {
+ have, suffix := run[i](re, refull, text)
+ want := parseResult(t, file, lineno, res[i])
+ if !same(have, want) {
+ t.Errorf("%s:%d: %#q%s.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, re, suffix, text, have, want)
+ if nfail++; nfail >= 100 {
+ t.Fatalf("stopping after %d errors", nfail)
+ }
+ continue
+ }
+ b, suffix := match[i](re, refull, text)
+ if b != (want != nil) {
+ t.Errorf("%s:%d: %#q%s.MatchString(%#q) = %v, want %v", file, lineno, re, suffix, text, b, !b)
+ if nfail++; nfail >= 100 {
+ t.Fatalf("stopping after %d errors", nfail)
+ }
+ continue
+ }
+ }
+
+ default:
+ t.Fatalf("%s:%d: out of sync: %s\n", file, lineno, line)
+ }
+ }
+ if len(input) != 0 {
+ t.Fatalf("%s:%d: out of sync: have %d strings left at EOF", file, lineno, len(input))
+ }
+ t.Logf("%d cases tested", ncase)
+}
+
+var run = []func(*Regexp, *Regexp, string) ([]int, string){
+ runFull,
+ runPartial,
+ runFullLongest,
+ runPartialLongest,
+}
+
+func runFull(re, refull *Regexp, text string) ([]int, string) {
+ refull.longest = false
+ return refull.FindStringSubmatchIndex(text), "[full]"
+}
+
+func runPartial(re, refull *Regexp, text string) ([]int, string) {
+ re.longest = false
+ return re.FindStringSubmatchIndex(text), ""
+}
+
+func runFullLongest(re, refull *Regexp, text string) ([]int, string) {
+ refull.longest = true
+ return refull.FindStringSubmatchIndex(text), "[full,longest]"
+}
+
+func runPartialLongest(re, refull *Regexp, text string) ([]int, string) {
+ re.longest = true
+ return re.FindStringSubmatchIndex(text), "[longest]"
+}
+
+var match = []func(*Regexp, *Regexp, string) (bool, string){
+ matchFull,
+ matchPartial,
+ matchFullLongest,
+ matchPartialLongest,
+}
+
+func matchFull(re, refull *Regexp, text string) (bool, string) {
+ refull.longest = false
+ return refull.MatchString(text), "[full]"
+}
+
+func matchPartial(re, refull *Regexp, text string) (bool, string) {
+ re.longest = false
+ return re.MatchString(text), ""
+}
+
+func matchFullLongest(re, refull *Regexp, text string) (bool, string) {
+ refull.longest = true
+ return refull.MatchString(text), "[full,longest]"
+}
+
+func matchPartialLongest(re, refull *Regexp, text string) (bool, string) {
+ re.longest = true
+ return re.MatchString(text), "[longest]"
+}
+
+func isSingleBytes(s string) bool {
+ for _, c := range s {
+ if c >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
+
+func tryCompile(s string) (re *Regexp, err os.Error) {
+ // Protect against panic during Compile.
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("panic: %v", r)
+ }
+ }()
+ return Compile(s)
+}
+
+func parseResult(t *testing.T, file string, lineno int, res string) []int {
+ // A single - indicates no match.
+ if res == "-" {
+ return nil
+ }
+ // Otherwise, a space-separated list of pairs.
+ n := 1
+ for j := 0; j < len(res); j++ {
+ if res[j] == ' ' {
+ n++
+ }
+ }
+ out := make([]int, 2*n)
+ i := 0
+ n = 0
+ for j := 0; j <= len(res); j++ {
+ if j == len(res) || res[j] == ' ' {
+ // Process a single pair. - means no submatch.
+ pair := res[i:j]
+ if pair == "-" {
+ out[n] = -1
+ out[n+1] = -1
+ } else {
+ k := strings.Index(pair, "-")
+ if k < 0 {
+ t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
+ }
+ lo, err1 := strconv.Atoi(pair[:k])
+ hi, err2 := strconv.Atoi(pair[k+1:])
+ if err1 != nil || err2 != nil || lo > hi {
+ t.Fatalf("%s:%d: invalid pair %s", file, lineno, pair)
+ }
+ out[n] = lo
+ out[n+1] = hi
+ }
+ n += 2
+ i = j + 1
+ }
+ }
+ return out
+}
+
+func same(x, y []int) bool {
+ if len(x) != len(y) {
+ return false
+ }
+ for i, xi := range x {
+ if xi != y[i] {
+ return false
+ }
+ }
+ return true
+}
+
+// TestFowler runs this package's regexp API against the
+// POSIX regular expression tests collected by Glenn Fowler
+// at http://www2.research.att.com/~gsf/testregex/.
+func TestFowler(t *testing.T) {
+ files, err := filepath.Glob("testdata/*.dat")
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, file := range files {
+ t.Log(file)
+ testFowler(t, file)
+ }
+}
+
+var notab = MustCompilePOSIX(`[^\t]+`)
+
+func testFowler(t *testing.T, file string) {
+ f, err := os.Open(file)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ defer f.Close()
+ b := bufio.NewReader(f)
+ lineno := 0
+ lastRegexp := ""
+Reading:
+ for {
+ lineno++
+ line, err := b.ReadString('\n')
+ if err != nil {
+ if err != os.EOF {
+ t.Errorf("%s:%d: %v", file, lineno, err)
+ }
+ break Reading
+ }
+
+ // http://www2.research.att.com/~gsf/man/man1/testregex.html
+ //
+ // INPUT FORMAT
+ // Input lines may be blank, a comment beginning with #, or a test
+ // specification. A specification is five fields separated by one
+ // or more tabs. NULL denotes the empty string and NIL denotes the
+ // 0 pointer.
+ if line[0] == '#' || line[0] == '\n' {
+ continue Reading
+ }
+ line = line[:len(line)-1]
+ field := notab.FindAllString(line, -1)
+ for i, f := range field {
+ if f == "NULL" {
+ field[i] = ""
+ }
+ if f == "NIL" {
+ t.Logf("%s:%d: skip: %s", file, lineno, line)
+ continue Reading
+ }
+ }
+ if len(field) == 0 {
+ continue Reading
+ }
+
+ // Field 1: the regex(3) flags to apply, one character per REG_feature
+ // flag. The test is skipped if REG_feature is not supported by the
+ // implementation. If the first character is not [BEASKLP] then the
+ // specification is a global control line. One or more of [BEASKLP] may be
+ // specified; the test will be repeated for each mode.
+ //
+ // B basic BRE (grep, ed, sed)
+ // E REG_EXTENDED ERE (egrep)
+ // A REG_AUGMENTED ARE (egrep with negation)
+ // S REG_SHELL SRE (sh glob)
+ // K REG_SHELL|REG_AUGMENTED KRE (ksh glob)
+ // L REG_LITERAL LRE (fgrep)
+ //
+ // a REG_LEFT|REG_RIGHT implicit ^...$
+ // b REG_NOTBOL lhs does not match ^
+ // c REG_COMMENT ignore space and #...\n
+ // d REG_SHELL_DOT explicit leading . match
+ // e REG_NOTEOL rhs does not match $
+ // f REG_MULTIPLE multiple \n separated patterns
+ // g FNM_LEADING_DIR testfnmatch only -- match until /
+ // h REG_MULTIREF multiple digit backref
+ // i REG_ICASE ignore case
+ // j REG_SPAN . matches \n
+ // k REG_ESCAPE \ to ecape [...] delimiter
+ // l REG_LEFT implicit ^...
+ // m REG_MINIMAL minimal match
+ // n REG_NEWLINE explicit \n match
+ // o REG_ENCLOSED (|&) magic inside [@|&](...)
+ // p REG_SHELL_PATH explicit / match
+ // q REG_DELIMITED delimited pattern
+ // r REG_RIGHT implicit ...$
+ // s REG_SHELL_ESCAPED \ not special
+ // t REG_MUSTDELIM all delimiters must be specified
+ // u standard unspecified behavior -- errors not counted
+ // v REG_CLASS_ESCAPE \ special inside [...]
+ // w REG_NOSUB no subexpression match array
+ // x REG_LENIENT let some errors slide
+ // y REG_LEFT regexec() implicit ^...
+ // z REG_NULL NULL subexpressions ok
+ // $ expand C \c escapes in fields 2 and 3
+ // / field 2 is a regsubcomp() expression
+ // = field 3 is a regdecomp() expression
+ //
+ // Field 1 control lines:
+ //
+ // C set LC_COLLATE and LC_CTYPE to locale in field 2
+ //
+ // ?test ... output field 5 if passed and != EXPECTED, silent otherwise
+ // &test ... output field 5 if current and previous passed
+ // |test ... output field 5 if current passed and previous failed
+ // ; ... output field 2 if previous failed
+ // {test ... skip if failed until }
+ // } end of skip
+ //
+ // : comment comment copied as output NOTE
+ // :comment:test :comment: ignored
+ // N[OTE] comment comment copied as output NOTE
+ // T[EST] comment comment
+ //
+ // number use number for nmatch (20 by default)
+ flag := field[0]
+ switch flag[0] {
+ case '?', '&', '|', ';', '{', '}':
+ // Ignore all the control operators.
+ // Just run everything.
+ flag = flag[1:]
+ if flag == "" {
+ continue Reading
+ }
+ case ':':
+ i := strings.Index(flag[1:], ":")
+ if i < 0 {
+ t.Logf("skip: %s", line)
+ continue Reading
+ }
+ flag = flag[1+i+1:]
+ case 'C', 'N', 'T', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ t.Logf("skip: %s", line)
+ continue Reading
+ }
+
+ // Can check field count now that we've handled the myriad comment formats.
+ if len(field) < 4 {
+ t.Errorf("%s:%d: too few fields: %s", file, lineno, line)
+ continue Reading
+ }
+
+ // Expand C escapes (a.k.a. Go escapes).
+ if strings.Contains(flag, "$") {
+ f := `"` + field[1] + `"`
+ if field[1], err = strconv.Unquote(f); err != nil {
+ t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
+ }
+ f = `"` + field[2] + `"`
+ if field[2], err = strconv.Unquote(f); err != nil {
+ t.Errorf("%s:%d: cannot unquote %s", file, lineno, f)
+ }
+ }
+
+ // Field 2: the regular expression pattern; SAME uses the pattern from
+ // the previous specification.
+ //
+ if field[1] == "SAME" {
+ field[1] = lastRegexp
+ }
+ lastRegexp = field[1]
+
+ // Field 3: the string to match.
+ text := field[2]
+
+ // Field 4: the test outcome...
+ ok, shouldCompile, shouldMatch, pos := parseFowlerResult(field[3])
+ if !ok {
+ t.Errorf("%s:%d: cannot parse result %#q", file, lineno, field[3])
+ continue Reading
+ }
+
+ // Field 5: optional comment appended to the report.
+
+ Testing:
+ // Run test once for each specified capital letter mode that we support.
+ for _, c := range flag {
+ pattern := field[1]
+ syn := syntax.POSIX | syntax.ClassNL
+ switch c {
+ default:
+ continue Testing
+ case 'E':
+ // extended regexp (what we support)
+ case 'L':
+ // literal
+ pattern = QuoteMeta(pattern)
+ }
+
+ for _, c := range flag {
+ switch c {
+ case 'i':
+ syn |= syntax.FoldCase
+ }
+ }
+
+ re, err := compile(pattern, syn, true)
+ if err != nil {
+ if shouldCompile {
+ t.Errorf("%s:%d: %#q did not compile", file, lineno, pattern)
+ }
+ continue Testing
+ }
+ if !shouldCompile {
+ t.Errorf("%s:%d: %#q should not compile", file, lineno, pattern)
+ continue Testing
+ }
+ match := re.MatchString(text)
+ if match != shouldMatch {
+ t.Errorf("%s:%d: %#q.Match(%#q) = %v, want %v", file, lineno, pattern, text, match, shouldMatch)
+ continue Testing
+ }
+ have := re.FindStringSubmatchIndex(text)
+ if (len(have) > 0) != match {
+ t.Errorf("%s:%d: %#q.Match(%#q) = %v, but %#q.FindSubmatchIndex(%#q) = %v", file, lineno, pattern, text, match, pattern, text, have)
+ continue Testing
+ }
+ if len(have) > len(pos) {
+ have = have[:len(pos)]
+ }
+ if !same(have, pos) {
+ t.Errorf("%s:%d: %#q.FindSubmatchIndex(%#q) = %v, want %v", file, lineno, pattern, text, have, pos)
+ }
+ }
+ }
+}
+
+func parseFowlerResult(s string) (ok, compiled, matched bool, pos []int) {
+ // Field 4: the test outcome. This is either one of the posix error
+ // codes (with REG_ omitted) or the match array, a list of (m,n)
+ // entries with m and n being first and last+1 positions in the
+ // field 3 string, or NULL if REG_NOSUB is in effect and success
+ // is expected. BADPAT is acceptable in place of any regcomp(3)
+ // error code. The match[] array is initialized to (-2,-2) before
+ // each test. All array elements from 0 to nmatch-1 must be specified
+ // in the outcome. Unspecified endpoints (offset -1) are denoted by ?.
+ // Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a
+ // matched (?{...}) expression, where x is the text enclosed by {...},
+ // o is the expression ordinal counting from 1, and n is the length of
+ // the unmatched portion of the subject string. If x starts with a
+ // number then that is the return value of re_execf(), otherwise 0 is
+ // returned.
+ switch {
+ case s == "":
+ // Match with no position information.
+ ok = true
+ compiled = true
+ matched = true
+ return
+ case s == "NOMATCH":
+ // Match failure.
+ ok = true
+ compiled = true
+ matched = false
+ return
+ case 'A' <= s[0] && s[0] <= 'Z':
+ // All the other error codes are compile errors.
+ ok = true
+ compiled = false
+ return
+ }
+ compiled = true
+
+ var x []int
+ for s != "" {
+ var end byte = ')'
+ if len(x)%2 == 0 {
+ if s[0] != '(' {
+ ok = false
+ return
+ }
+ s = s[1:]
+ end = ','
+ }
+ i := 0
+ for i < len(s) && s[i] != end {
+ i++
+ }
+ if i == 0 || i == len(s) {
+ ok = false
+ return
+ }
+ var v = -1
+ var err os.Error
+ if s[:i] != "?" {
+ v, err = strconv.Atoi(s[:i])
+ if err != nil {
+ ok = false
+ return
+ }
+ }
+ x = append(x, v)
+ s = s[i+1:]
+ }
+ if len(x)%2 != 0 {
+ ok = false
+ return
+ }
+ ok = true
+ matched = true
+ pos = x
+ return
+}
+
+var text []byte
+
+func makeText(n int) []byte {
+ if len(text) >= n {
+ return text[:n]
+ }
+ text = make([]byte, n)
+ for i := range text {
+ if rand.Intn(30) == 0 {
+ text[i] = '\n'
+ } else {
+ text[i] = byte(rand.Intn(0x7E+1-0x20) + 0x20)
+ }
+ }
+ return text
+}
+
+func benchmark(b *testing.B, re string, n int) {
+ r := MustCompile(re)
+ t := makeText(n)
+ b.ResetTimer()
+ b.SetBytes(int64(n))
+ for i := 0; i < b.N; i++ {
+ if r.Match(t) {
+ panic("match!")
+ }
+ }
+}
+
+func benchold(b *testing.B, re string, n int) {
+ r := old.MustCompile(re)
+ t := makeText(n)
+ b.ResetTimer()
+ b.SetBytes(int64(n))
+ for i := 0; i < b.N; i++ {
+ if r.Match(t) {
+ panic("match!")
+ }
+ }
+}
+
+const (
+ easy0 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+ easy1 = "A[AB]B[BC]C[CD]D[DE]E[EF]F[FG]G[GH]H[HI]I[IJ]J$"
+ medium = "[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+ hard = "[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$"
+ parens = "([ -~])*(A)(B)(C)(D)(E)(F)(G)(H)(I)(J)(K)(L)(M)" +
+ "(N)(O)(P)(Q)(R)(S)(T)(U)(V)(W)(X)(Y)(Z)$"
+)
+
+func BenchmarkMatchEasy0_1K(b *testing.B) { benchmark(b, easy0, 1<<10) }
+func BenchmarkMatchEasy0_1K_Old(b *testing.B) { benchold(b, easy0, 1<<10) }
+func BenchmarkMatchEasy0_1M(b *testing.B) { benchmark(b, easy0, 1<<20) }
+func BenchmarkMatchEasy0_1M_Old(b *testing.B) { benchold(b, easy0, 1<<20) }
+func BenchmarkMatchEasy0_32K(b *testing.B) { benchmark(b, easy0, 32<<10) }
+func BenchmarkMatchEasy0_32K_Old(b *testing.B) { benchold(b, easy0, 32<<10) }
+func BenchmarkMatchEasy0_32M(b *testing.B) { benchmark(b, easy0, 32<<20) }
+func BenchmarkMatchEasy0_32M_Old(b *testing.B) { benchold(b, easy0, 32<<20) }
+func BenchmarkMatchEasy1_1K(b *testing.B) { benchmark(b, easy1, 1<<10) }
+func BenchmarkMatchEasy1_1K_Old(b *testing.B) { benchold(b, easy1, 1<<10) }
+func BenchmarkMatchEasy1_1M(b *testing.B) { benchmark(b, easy1, 1<<20) }
+func BenchmarkMatchEasy1_1M_Old(b *testing.B) { benchold(b, easy1, 1<<20) }
+func BenchmarkMatchEasy1_32K(b *testing.B) { benchmark(b, easy1, 32<<10) }
+func BenchmarkMatchEasy1_32K_Old(b *testing.B) { benchold(b, easy1, 32<<10) }
+func BenchmarkMatchEasy1_32M(b *testing.B) { benchmark(b, easy1, 32<<20) }
+func BenchmarkMatchEasy1_32M_Old(b *testing.B) { benchold(b, easy1, 32<<20) }
+func BenchmarkMatchMedium_1K(b *testing.B) { benchmark(b, medium, 1<<10) }
+func BenchmarkMatchMedium_1K_Old(b *testing.B) { benchold(b, medium, 1<<10) }
+func BenchmarkMatchMedium_1M(b *testing.B) { benchmark(b, medium, 1<<20) }
+func BenchmarkMatchMedium_1M_Old(b *testing.B) { benchold(b, medium, 1<<20) }
+func BenchmarkMatchMedium_32K(b *testing.B) { benchmark(b, medium, 32<<10) }
+func BenchmarkMatchMedium_32K_Old(b *testing.B) { benchold(b, medium, 32<<10) }
+func BenchmarkMatchMedium_32M(b *testing.B) { benchmark(b, medium, 32<<20) }
+func BenchmarkMatchMedium_32M_Old(b *testing.B) { benchold(b, medium, 32<<20) }
+func BenchmarkMatchHard_1K(b *testing.B) { benchmark(b, hard, 1<<10) }
+func BenchmarkMatchHard_1K_Old(b *testing.B) { benchold(b, hard, 1<<10) }
+func BenchmarkMatchHard_1M(b *testing.B) { benchmark(b, hard, 1<<20) }
+func BenchmarkMatchHard_1M_Old(b *testing.B) { benchold(b, hard, 1<<20) }
+func BenchmarkMatchHard_32K(b *testing.B) { benchmark(b, hard, 32<<10) }
+func BenchmarkMatchHard_32K_Old(b *testing.B) { benchold(b, hard, 32<<10) }
+func BenchmarkMatchHard_32M(b *testing.B) { benchmark(b, hard, 32<<20) }
+func BenchmarkMatchHard_32M_Old(b *testing.B) { benchold(b, hard, 32<<20) }
diff --git a/libgo/go/regexp/find_test.go b/libgo/go/regexp/find_test.go
index 83b249e3cef..e07eb7d5c05 100644
--- a/libgo/go/regexp/find_test.go
+++ b/libgo/go/regexp/find_test.go
@@ -58,8 +58,8 @@ var findTests = []FindTest{
{`(([^xyz]*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 3, 4)},
{`((a|b|c)*(d))`, "abcd", build(1, 0, 4, 0, 4, 2, 3, 3, 4)},
{`(((a|b|c)*)(d))`, "abcd", build(1, 0, 4, 0, 4, 0, 3, 2, 3, 3, 4)},
- {`\a\b\f\n\r\t\v`, "\a\b\f\n\r\t\v", build(1, 0, 7)},
- {`[\a\b\f\n\r\t\v]+`, "\a\b\f\n\r\t\v", build(1, 0, 7)},
+ {`\a\f\n\r\t\v`, "\a\f\n\r\t\v", build(1, 0, 6)},
+ {`[\a\f\n\r\t\v]+`, "\a\f\n\r\t\v", build(1, 0, 6)},
{`a*(|(b))c*`, "aacc", build(1, 0, 4, 2, 2, -1, -1)},
{`(.*).*`, "ab", build(1, 0, 2, 0, 2)},
@@ -80,6 +80,32 @@ var findTests = []FindTest{
{`data`, "daXY data", build(1, 5, 9)},
{`da(.)a$`, "daXY data", build(1, 5, 9, 7, 8)},
{`zx+`, "zzx", build(1, 1, 3)},
+ {`ab$`, "abcab", build(1, 3, 5)},
+ {`(aa)*$`, "a", build(1, 1, 1, -1, -1)},
+ {`(?:.|(?:.a))`, "", nil},
+ {`(?:A(?:A|a))`, "Aa", build(1, 0, 2)},
+ {`(?:A|(?:A|a))`, "a", build(1, 0, 1)},
+ {`(a){0}`, "", build(1, 0, 0, -1, -1)},
+ {`(?-s)(?:(?:^).)`, "\n", nil},
+ {`(?s)(?:(?:^).)`, "\n", build(1, 0, 1)},
+ {`(?:(?:^).)`, "\n", nil},
+ {`\b`, "x", build(2, 0, 0, 1, 1)},
+ {`\b`, "xx", build(2, 0, 0, 2, 2)},
+ {`\b`, "x y", build(4, 0, 0, 1, 1, 2, 2, 3, 3)},
+ {`\b`, "xx yy", build(4, 0, 0, 2, 2, 3, 3, 5, 5)},
+ {`\B`, "x", nil},
+ {`\B`, "xx", build(1, 1, 1)},
+ {`\B`, "x y", nil},
+ {`\B`, "xx yy", build(2, 1, 1, 4, 4)},
+
+ // RE2 tests
+ {`[^\S\s]`, "abcd", nil},
+ {`[^\S[:space:]]`, "abcd", nil},
+ {`[^\D\d]`, "abcd", nil},
+ {`[^\D[:digit:]]`, "abcd", nil},
+ {`(?i)\W`, "x", nil},
+ {`(?i)\W`, "k", nil},
+ {`(?i)\W`, "s", nil},
// can backslash-escape any punctuation
{`\!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\{\|\}\~`,
@@ -209,7 +235,7 @@ func TestFindAll(t *testing.T) {
case test.matches == nil && result != nil:
t.Errorf("expected no match; got one: %s", test)
case test.matches != nil && result == nil:
- t.Errorf("expected match; got none: %s", test)
+ t.Fatalf("expected match; got none: %s", test)
case test.matches != nil && result != nil:
if len(test.matches) != len(result) {
t.Errorf("expected %d matches; got %d: %s", len(test.matches), len(result), test)
diff --git a/libgo/go/regexp/regexp.go b/libgo/go/regexp/regexp.go
index e8d4c087cf8..2325f6204b1 100644
--- a/libgo/go/regexp/regexp.go
+++ b/libgo/go/regexp/regexp.go
@@ -3,27 +3,12 @@
// Package regexp implements a simple regular expression library.
//
-// The syntax of the regular expressions accepted is:
+// The syntax of the regular expressions accepted is the same
+// general syntax used by Perl, Python, and other languages.
+// More precisely, it is the syntax accepted by RE2 and described at
+// http://code.google.com/p/re2/wiki/Syntax, except for \C.
//
-// regexp:
-// concatenation { '|' concatenation }
-// concatenation:
-// { closure }
-// closure:
-// term [ '*' | '+' | '?' ]
-// term:
-// '^'
-// '$'
-// '.'
-// character
-// '[' [ '^' ] { character-range } ']'
-// '(' regexp ')'
-// character-range:
-// character [ '-' character ]
-//
-// All characters are UTF-8-encoded code points. Backslashes escape special
-// characters, including inside character classes. The standard Go character
-// escapes are also recognized: \a \b \f \n \r \t \v.
+// All characters are UTF-8-encoded code points.
//
// There are 16 methods of Regexp that match a regular expression and identify
// the matched text. Their names are matched by this regular expression:
@@ -72,7 +57,10 @@ import (
"bytes"
"io"
"os"
+ "regexp/syntax"
+ "strconv"
"strings"
+ "sync"
"utf8"
)
@@ -85,528 +73,24 @@ func (e Error) String() string {
return string(e)
}
-// Error codes returned by failures to parse an expression.
-var (
- ErrInternal = Error("regexp: internal error")
- ErrUnmatchedLpar = Error("regexp: unmatched '('")
- ErrUnmatchedRpar = Error("regexp: unmatched ')'")
- ErrUnmatchedLbkt = Error("regexp: unmatched '['")
- ErrUnmatchedRbkt = Error("regexp: unmatched ']'")
- ErrBadRange = Error("regexp: bad range in character class")
- ErrExtraneousBackslash = Error("regexp: extraneous backslash")
- ErrBadClosure = Error("regexp: repeated closure (**, ++, etc.)")
- ErrBareClosure = Error("regexp: closure applies to nothing")
- ErrBadBackslash = Error("regexp: illegal backslash escape")
-)
-
-const (
- iStart = iota // beginning of program
- iEnd // end of program: success
- iBOT // '^' beginning of text
- iEOT // '$' end of text
- iChar // 'a' regular character
- iCharClass // [a-z] character class
- iAny // '.' any character including newline
- iNotNL // [^\n] special case: any character but newline
- iBra // '(' parenthesized expression: 2*braNum for left, 2*braNum+1 for right
- iAlt // '|' alternation
- iNop // do nothing; makes it easy to link without patching
-)
-
-// An instruction executed by the NFA
-type instr struct {
- kind int // the type of this instruction: iChar, iAny, etc.
- index int // used only in debugging; could be eliminated
- next *instr // the instruction to execute after this one
- // Special fields valid only for some items.
- char int // iChar
- braNum int // iBra, iEbra
- cclass *charClass // iCharClass
- left *instr // iAlt, other branch
-}
-
-func (i *instr) print() {
- switch i.kind {
- case iStart:
- print("start")
- case iEnd:
- print("end")
- case iBOT:
- print("bot")
- case iEOT:
- print("eot")
- case iChar:
- print("char ", string(i.char))
- case iCharClass:
- i.cclass.print()
- case iAny:
- print("any")
- case iNotNL:
- print("notnl")
- case iBra:
- if i.braNum&1 == 0 {
- print("bra", i.braNum/2)
- } else {
- print("ebra", i.braNum/2)
- }
- case iAlt:
- print("alt(", i.left.index, ")")
- case iNop:
- print("nop")
- }
-}
-
// Regexp is the representation of a compiled regular expression.
// The public interface is entirely through methods.
// A Regexp is safe for concurrent use by multiple goroutines.
type Regexp struct {
- expr string // the original expression
- prefix string // initial plain text string
- prefixBytes []byte // initial plain text bytes
- inst []*instr
- start *instr // first instruction of machine
- prefixStart *instr // where to start if there is a prefix
- nbra int // number of brackets in expression, for subexpressions
-}
-
-type charClass struct {
- negate bool // is character class negated? ([^a-z])
- // slice of int, stored pairwise: [a-z] is (a,z); x is (x,x):
- ranges []int
- cmin, cmax int
-}
-
-func (cclass *charClass) print() {
- print("charclass")
- if cclass.negate {
- print(" (negated)")
- }
- for i := 0; i < len(cclass.ranges); i += 2 {
- l := cclass.ranges[i]
- r := cclass.ranges[i+1]
- if l == r {
- print(" [", string(l), "]")
- } else {
- print(" [", string(l), "-", string(r), "]")
- }
- }
-}
-
-func (cclass *charClass) addRange(a, b int) {
- // range is a through b inclusive
- cclass.ranges = append(cclass.ranges, a, b)
- if a < cclass.cmin {
- cclass.cmin = a
- }
- if b > cclass.cmax {
- cclass.cmax = b
- }
-}
-
-func (cclass *charClass) matches(c int) bool {
- if c < cclass.cmin || c > cclass.cmax {
- return cclass.negate
- }
- ranges := cclass.ranges
- for i := 0; i < len(ranges); i = i + 2 {
- if ranges[i] <= c && c <= ranges[i+1] {
- return !cclass.negate
- }
- }
- return cclass.negate
-}
-
-func newCharClass() *instr {
- i := &instr{kind: iCharClass}
- i.cclass = new(charClass)
- i.cclass.ranges = make([]int, 0, 4)
- i.cclass.cmin = 0x10FFFF + 1 // MaxRune + 1
- i.cclass.cmax = -1
- return i
-}
-
-func (re *Regexp) add(i *instr) *instr {
- i.index = len(re.inst)
- re.inst = append(re.inst, i)
- return i
-}
-
-type parser struct {
- re *Regexp
- nlpar int // number of unclosed lpars
- pos int
- ch int
-}
-
-func (p *parser) error(err Error) {
- panic(err)
-}
-
-const endOfText = -1
-
-func (p *parser) c() int { return p.ch }
-
-func (p *parser) nextc() int {
- if p.pos >= len(p.re.expr) {
- p.ch = endOfText
- } else {
- c, w := utf8.DecodeRuneInString(p.re.expr[p.pos:])
- p.ch = c
- p.pos += w
- }
- return p.ch
-}
-
-func newParser(re *Regexp) *parser {
- p := new(parser)
- p.re = re
- p.nextc() // load p.ch
- return p
-}
-
-func special(c int) bool {
- for _, r := range `\.+*?()|[]^$` {
- if c == r {
- return true
- }
- }
- return false
-}
-
-func ispunct(c int) bool {
- for _, r := range "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" {
- if c == r {
- return true
- }
- }
- return false
-}
-
-var escapes = []byte("abfnrtv")
-var escaped = []byte("\a\b\f\n\r\t\v")
-
-func escape(c int) int {
- for i, b := range escapes {
- if int(b) == c {
- return i
- }
- }
- return -1
-}
-
-func (p *parser) checkBackslash() int {
- c := p.c()
- if c == '\\' {
- c = p.nextc()
- switch {
- case c == endOfText:
- p.error(ErrExtraneousBackslash)
- case ispunct(c):
- // c is as delivered
- case escape(c) >= 0:
- c = int(escaped[escape(c)])
- default:
- p.error(ErrBadBackslash)
- }
- }
- return c
-}
-
-func (p *parser) charClass() *instr {
- i := newCharClass()
- cc := i.cclass
- if p.c() == '^' {
- cc.negate = true
- p.nextc()
- }
- left := -1
- for {
- switch c := p.c(); c {
- case ']', endOfText:
- if left >= 0 {
- p.error(ErrBadRange)
- }
- // Is it [^\n]?
- if cc.negate && len(cc.ranges) == 2 &&
- cc.ranges[0] == '\n' && cc.ranges[1] == '\n' {
- nl := &instr{kind: iNotNL}
- p.re.add(nl)
- return nl
- }
- // Special common case: "[a]" -> "a"
- if !cc.negate && len(cc.ranges) == 2 && cc.ranges[0] == cc.ranges[1] {
- c := &instr{kind: iChar, char: cc.ranges[0]}
- p.re.add(c)
- return c
- }
- p.re.add(i)
- return i
- case '-': // do this before backslash processing
- p.error(ErrBadRange)
- default:
- c = p.checkBackslash()
- p.nextc()
- switch {
- case left < 0: // first of pair
- if p.c() == '-' { // range
- p.nextc()
- left = c
- } else { // single char
- cc.addRange(c, c)
- }
- case left <= c: // second of pair
- cc.addRange(left, c)
- left = -1
- default:
- p.error(ErrBadRange)
- }
- }
- }
- panic("unreachable")
-}
-
-func (p *parser) term() (start, end *instr) {
- switch c := p.c(); c {
- case '|', endOfText:
- return nil, nil
- case '*', '+', '?':
- p.error(ErrBareClosure)
- case ')':
- if p.nlpar == 0 {
- p.error(ErrUnmatchedRpar)
- }
- return nil, nil
- case ']':
- p.error(ErrUnmatchedRbkt)
- case '^':
- p.nextc()
- start = p.re.add(&instr{kind: iBOT})
- return start, start
- case '$':
- p.nextc()
- start = p.re.add(&instr{kind: iEOT})
- return start, start
- case '.':
- p.nextc()
- start = p.re.add(&instr{kind: iAny})
- return start, start
- case '[':
- p.nextc()
- start = p.charClass()
- if p.c() != ']' {
- p.error(ErrUnmatchedLbkt)
- }
- p.nextc()
- return start, start
- case '(':
- p.nextc()
- p.nlpar++
- p.re.nbra++ // increment first so first subexpr is \1
- nbra := p.re.nbra
- start, end = p.regexp()
- if p.c() != ')' {
- p.error(ErrUnmatchedLpar)
- }
- p.nlpar--
- p.nextc()
- bra := &instr{kind: iBra, braNum: 2 * nbra}
- p.re.add(bra)
- ebra := &instr{kind: iBra, braNum: 2*nbra + 1}
- p.re.add(ebra)
- if start == nil {
- if end == nil {
- p.error(ErrInternal)
- return
- }
- start = ebra
- } else {
- end.next = ebra
- }
- bra.next = start
- return bra, ebra
- default:
- c = p.checkBackslash()
- p.nextc()
- start = &instr{kind: iChar, char: c}
- p.re.add(start)
- return start, start
- }
- panic("unreachable")
-}
-
-func (p *parser) closure() (start, end *instr) {
- start, end = p.term()
- if start == nil {
- return
- }
- switch p.c() {
- case '*':
- // (start,end)*:
- alt := &instr{kind: iAlt}
- p.re.add(alt)
- end.next = alt // after end, do alt
- alt.left = start // alternate brach: return to start
- start = alt // alt becomes new (start, end)
- end = alt
- case '+':
- // (start,end)+:
- alt := &instr{kind: iAlt}
- p.re.add(alt)
- end.next = alt // after end, do alt
- alt.left = start // alternate brach: return to start
- end = alt // start is unchanged; end is alt
- case '?':
- // (start,end)?:
- alt := &instr{kind: iAlt}
- p.re.add(alt)
- nop := &instr{kind: iNop}
- p.re.add(nop)
- alt.left = start // alternate branch is start
- alt.next = nop // follow on to nop
- end.next = nop // after end, go to nop
- start = alt // start is now alt
- end = nop // end is nop pointed to by both branches
- default:
- return
- }
- switch p.nextc() {
- case '*', '+', '?':
- p.error(ErrBadClosure)
- }
- return
-}
-
-func (p *parser) concatenation() (start, end *instr) {
- for {
- nstart, nend := p.closure()
- switch {
- case nstart == nil: // end of this concatenation
- if start == nil { // this is the empty string
- nop := p.re.add(&instr{kind: iNop})
- return nop, nop
- }
- return
- case start == nil: // this is first element of concatenation
- start, end = nstart, nend
- default:
- end.next = nstart
- end = nend
- }
- }
- panic("unreachable")
-}
-
-func (p *parser) regexp() (start, end *instr) {
- start, end = p.concatenation()
- for {
- switch p.c() {
- default:
- return
- case '|':
- p.nextc()
- nstart, nend := p.concatenation()
- alt := &instr{kind: iAlt}
- p.re.add(alt)
- alt.left = start
- alt.next = nstart
- nop := &instr{kind: iNop}
- p.re.add(nop)
- end.next = nop
- nend.next = nop
- start, end = alt, nop
- }
- }
- panic("unreachable")
-}
-
-func unNop(i *instr) *instr {
- for i.kind == iNop {
- i = i.next
- }
- return i
-}
-
-func (re *Regexp) eliminateNops() {
- for _, inst := range re.inst {
- if inst.kind == iEnd {
- continue
- }
- inst.next = unNop(inst.next)
- if inst.kind == iAlt {
- inst.left = unNop(inst.left)
- }
- }
-}
-
-func (re *Regexp) dump() {
- print("prefix <", re.prefix, ">\n")
- for _, inst := range re.inst {
- print(inst.index, ": ")
- inst.print()
- if inst.kind != iEnd {
- print(" -> ", inst.next.index)
- }
- print("\n")
- }
-}
-
-func (re *Regexp) doParse() {
- p := newParser(re)
- start := &instr{kind: iStart}
- re.add(start)
- s, e := p.regexp()
- start.next = s
- re.start = start
- e.next = re.add(&instr{kind: iEnd})
-
- if debug {
- re.dump()
- println()
- }
-
- re.eliminateNops()
- if debug {
- re.dump()
- println()
- }
- re.setPrefix()
- if debug {
- re.dump()
- println()
- }
-}
-
-// Extract regular text from the beginning of the pattern,
-// possibly after a leading iBOT.
-// That text can be used by doExecute to speed up matching.
-func (re *Regexp) setPrefix() {
- var b []byte
- var utf = make([]byte, utf8.UTFMax)
- var inst *instr
- // First instruction is start; skip that. Also skip any initial iBOT.
- inst = re.inst[0].next
- for inst.kind == iBOT {
- inst = inst.next
- }
-Loop:
- for ; inst.kind != iEnd; inst = inst.next {
- // stop if this is not a char
- if inst.kind != iChar {
- break
- }
- // stop if this char can be followed by a match for an empty string,
- // which includes closures, ^, and $.
- switch inst.next.kind {
- case iBOT, iEOT, iAlt:
- break Loop
- }
- n := utf8.EncodeRune(utf, inst.char)
- b = append(b, utf[0:n]...)
- }
- // point prefixStart instruction to first non-CHAR after prefix
- re.prefixStart = inst
- re.prefixBytes = b
- re.prefix = string(b)
+ // read-only after Compile
+ expr string // as passed to Compile
+ prog *syntax.Prog // compiled program
+ prefix string // required prefix in unanchored matches
+ prefixBytes []byte // prefix, as a []byte
+ prefixComplete bool // prefix is the entire regexp
+ prefixRune int // first rune in prefix
+ cond syntax.EmptyOp // empty-width conditions required at start of match
+ numSubexp int
+ longest bool
+
+ // cache of machines for running regexp
+ mu sync.Mutex
+ machine []*machine
}
// String returns the source text used to compile the regular expression.
@@ -614,21 +98,96 @@ func (re *Regexp) String() string {
return re.expr
}
-// Compile parses a regular expression and returns, if successful, a Regexp
-// object that can be used to match against text.
-func Compile(str string) (regexp *Regexp, error os.Error) {
- regexp = new(Regexp)
- // doParse will panic if there is a parse error.
- defer func() {
- if e := recover(); e != nil {
- regexp = nil
- error = e.(Error) // Will re-panic if error was not an Error, e.g. nil-pointer exception
- }
- }()
- regexp.expr = str
- regexp.inst = make([]*instr, 0, 10)
- regexp.doParse()
- return
+// Compile parses a regular expression and returns, if successful,
+// a Regexp object that can be used to match against text.
+//
+// When matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses the one that a backtracking search would have found first.
+// This so-called leftmost-first matching is the same semantics
+// that Perl, Python, and other implementations use, although this
+// package implements it without the expense of backtracking.
+// For POSIX leftmost-longest matching, see CompilePOSIX.
+func Compile(expr string) (*Regexp, os.Error) {
+ return compile(expr, syntax.Perl, false)
+}
+
+// CompilePOSIX is like Compile but restricts the regular expression
+// to POSIX ERE (egrep) syntax and changes the match semantics to
+// leftmost-longest.
+//
+// That is, when matching against text, the regexp returns a match that
+// begins as early as possible in the input (leftmost), and among those
+// it chooses a match that is as long as possible.
+// This so-called leftmost-longest matching is the same semantics
+// that early regular expression implementations used and that POSIX
+// specifies.
+//
+// However, there can be multiple leftmost-longest matches, with different
+// submatch choices, and here this package diverges from POSIX.
+// Among the possible leftmost-longest matches, this package chooses
+// the one that a backtracking search would have found first, while POSIX
+// specifies that the match be chosen to maximize the length of the first
+// subexpression, then the second, and so on from left to right.
+// The POSIX rule is computationally prohibitive and not even well-defined.
+// See http://swtch.com/~rsc/regexp/regexp2.html#posix for details.
+func CompilePOSIX(expr string) (*Regexp, os.Error) {
+ return compile(expr, syntax.POSIX, true)
+}
+
+func compile(expr string, mode syntax.Flags, longest bool) (*Regexp, os.Error) {
+ re, err := syntax.Parse(expr, mode)
+ if err != nil {
+ return nil, err
+ }
+ maxCap := re.MaxCap()
+ re = re.Simplify()
+ prog, err := syntax.Compile(re)
+ if err != nil {
+ return nil, err
+ }
+ regexp := &Regexp{
+ expr: expr,
+ prog: prog,
+ numSubexp: maxCap,
+ cond: prog.StartCond(),
+ longest: longest,
+ }
+ regexp.prefix, regexp.prefixComplete = prog.Prefix()
+ if regexp.prefix != "" {
+ // TODO(rsc): Remove this allocation by adding
+ // IndexString to package bytes.
+ regexp.prefixBytes = []byte(regexp.prefix)
+ regexp.prefixRune, _ = utf8.DecodeRuneInString(regexp.prefix)
+ }
+ return regexp, nil
+}
+
+// get returns a machine to use for matching re.
+// It uses the re's machine cache if possible, to avoid
+// unnecessary allocation.
+func (re *Regexp) get() *machine {
+ re.mu.Lock()
+ if n := len(re.machine); n > 0 {
+ z := re.machine[n-1]
+ re.machine = re.machine[:n-1]
+ re.mu.Unlock()
+ return z
+ }
+ re.mu.Unlock()
+ z := progMachine(re.prog)
+ z.re = re
+ return z
+}
+
+// put returns a machine to the re's machine cache.
+// There is no attempt to limit the size of the cache, so it will
+// grow to the maximum number of simultaneous matches
+// run using re. (The cache empties when re gets garbage collected.)
+func (re *Regexp) put(z *machine) {
+ re.mu.Lock()
+ re.machine = append(re.machine, z)
+ re.mu.Unlock()
}
// MustCompile is like Compile but panics if the expression cannot be parsed.
@@ -637,116 +196,35 @@ func Compile(str string) (regexp *Regexp, error os.Error) {
func MustCompile(str string) *Regexp {
regexp, error := Compile(str)
if error != nil {
- panic(`regexp: compiling "` + str + `": ` + error.String())
+ panic(`regexp: Compile(` + quote(str) + `): ` + error.String())
}
return regexp
}
-// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
-func (re *Regexp) NumSubexp() int { return re.nbra }
-
-// The match arena allows us to reduce the garbage generated by tossing
-// match vectors away as we execute. Matches are ref counted and returned
-// to a free list when no longer active. Increases a simple benchmark by 22X.
-type matchArena struct {
- head *matchVec
- len int // length of match vector
- pos int
- atBOT bool // whether we're at beginning of text
- atEOT bool // whether we're at end of text
-}
-
-type matchVec struct {
- m []int // pairs of bracketing submatches. 0th is start,end
- ref int
- next *matchVec
-}
-
-func (a *matchArena) new() *matchVec {
- if a.head == nil {
- const N = 10
- block := make([]matchVec, N)
- for i := 0; i < N; i++ {
- b := &block[i]
- b.next = a.head
- a.head = b
- }
- }
- m := a.head
- a.head = m.next
- m.ref = 0
- if m.m == nil {
- m.m = make([]int, a.len)
- }
- return m
-}
-
-func (a *matchArena) free(m *matchVec) {
- m.ref--
- if m.ref == 0 {
- m.next = a.head
- a.head = m
+// MustCompilePOSIX is like CompilePOSIX but panics if the expression cannot be parsed.
+// It simplifies safe initialization of global variables holding compiled regular
+// expressions.
+func MustCompilePOSIX(str string) *Regexp {
+ regexp, error := CompilePOSIX(str)
+ if error != nil {
+ panic(`regexp: CompilePOSIX(` + quote(str) + `): ` + error.String())
}
+ return regexp
}
-func (a *matchArena) copy(m *matchVec) *matchVec {
- m1 := a.new()
- copy(m1.m, m.m)
- return m1
-}
-
-func (a *matchArena) noMatch() *matchVec {
- m := a.new()
- for i := range m.m {
- m.m[i] = -1 // no match seen; catches cases like "a(b)?c" on "ac"
+func quote(s string) string {
+ if strconv.CanBackquote(s) {
+ return "`" + s + "`"
}
- m.ref = 1
- return m
+ return strconv.Quote(s)
}
-type state struct {
- inst *instr // next instruction to execute
- prefixed bool // this match began with a fixed prefix
- match *matchVec
+// NumSubexp returns the number of parenthesized subexpressions in this Regexp.
+func (re *Regexp) NumSubexp() int {
+ return re.numSubexp
}
-// Append new state to to-do list. Leftmost-longest wins so avoid
-// adding a state that's already active. The matchVec will be inc-ref'ed
-// if it is assigned to a state.
-func (a *matchArena) addState(s []state, inst *instr, prefixed bool, match *matchVec) []state {
- switch inst.kind {
- case iBOT:
- if a.atBOT {
- s = a.addState(s, inst.next, prefixed, match)
- }
- return s
- case iEOT:
- if a.atEOT {
- s = a.addState(s, inst.next, prefixed, match)
- }
- return s
- case iBra:
- match.m[inst.braNum] = a.pos
- s = a.addState(s, inst.next, prefixed, match)
- return s
- }
- l := len(s)
- // States are inserted in order so it's sufficient to see if we have the same
- // instruction; no need to see if existing match is earlier (it is).
- for i := 0; i < l; i++ {
- if s[i].inst == inst {
- return s
- }
- }
- s = append(s, state{inst, prefixed, match})
- match.ref++
- if inst.kind == iAlt {
- s = a.addState(s, inst.left, prefixed, a.copy(match))
- // give other branch a copy of this match vector
- s = a.addState(s, inst.next, prefixed, a.copy(match))
- }
- return s
-}
+const endOfText = -1
// input abstracts different representations of the input text. It provides
// one-character lookahead.
@@ -755,6 +233,7 @@ type input interface {
canCheckPrefix() bool // can we look ahead without losing info?
hasPrefix(re *Regexp) bool
index(re *Regexp, pos int) int
+ context(pos int) syntax.EmptyOp
}
// inputString scans a string.
@@ -768,7 +247,11 @@ func newInputString(str string) *inputString {
func (i *inputString) step(pos int) (int, int) {
if pos < len(i.str) {
- return utf8.DecodeRuneInString(i.str[pos:len(i.str)])
+ c := i.str[pos]
+ if c < utf8.RuneSelf {
+ return int(c), 1
+ }
+ return utf8.DecodeRuneInString(i.str[pos:])
}
return endOfText, 0
}
@@ -785,6 +268,17 @@ func (i *inputString) index(re *Regexp, pos int) int {
return strings.Index(i.str[pos:], re.prefix)
}
+func (i *inputString) context(pos int) syntax.EmptyOp {
+ r1, r2 := -1, -1
+ if pos > 0 && pos <= len(i.str) {
+ r1, _ = utf8.DecodeLastRuneInString(i.str[:pos])
+ }
+ if pos < len(i.str) {
+ r2, _ = utf8.DecodeRuneInString(i.str[pos:])
+ }
+ return syntax.EmptyOpContext(r1, r2)
+}
+
// inputBytes scans a byte slice.
type inputBytes struct {
str []byte
@@ -796,7 +290,11 @@ func newInputBytes(str []byte) *inputBytes {
func (i *inputBytes) step(pos int) (int, int) {
if pos < len(i.str) {
- return utf8.DecodeRune(i.str[pos:len(i.str)])
+ c := i.str[pos]
+ if c < utf8.RuneSelf {
+ return int(c), 1
+ }
+ return utf8.DecodeRune(i.str[pos:])
}
return endOfText, 0
}
@@ -813,6 +311,17 @@ func (i *inputBytes) index(re *Regexp, pos int) int {
return bytes.Index(i.str[pos:], re.prefixBytes)
}
+func (i *inputBytes) context(pos int) syntax.EmptyOp {
+ r1, r2 := -1, -1
+ if pos > 0 && pos <= len(i.str) {
+ r1, _ = utf8.DecodeLastRune(i.str[:pos])
+ }
+ if pos < len(i.str) {
+ r2, _ = utf8.DecodeRune(i.str[pos:])
+ }
+ return syntax.EmptyOpContext(r1, r2)
+}
+
// inputReader scans a RuneReader.
type inputReader struct {
r io.RuneReader
@@ -850,150 +359,35 @@ func (i *inputReader) index(re *Regexp, pos int) int {
return -1
}
-// Search match starting from pos bytes into the input.
-func (re *Regexp) doExecute(i input, pos int) []int {
- var s [2][]state
- s[0] = make([]state, 0, 10)
- s[1] = make([]state, 0, 10)
- in, out := 0, 1
- var final state
- found := false
- anchored := re.inst[0].next.kind == iBOT
- if anchored && pos > 0 {
- return nil
- }
- // fast check for initial plain substring
- if i.canCheckPrefix() && re.prefix != "" {
- advance := 0
- if anchored {
- if !i.hasPrefix(re) {
- return nil
- }
- } else {
- advance = i.index(re, pos)
- if advance == -1 {
- return nil
- }
- }
- pos += advance
- }
- // We look one character ahead so we can match $, which checks whether
- // we are at EOT.
- nextChar, nextWidth := i.step(pos)
- arena := &matchArena{
- len: 2 * (re.nbra + 1),
- pos: pos,
- atBOT: pos == 0,
- atEOT: nextChar == endOfText,
- }
- for c, startPos := 0, pos; c != endOfText; {
- if !found && (pos == startPos || !anchored) {
- // prime the pump if we haven't seen a match yet
- match := arena.noMatch()
- match.m[0] = pos
- s[out] = arena.addState(s[out], re.start.next, false, match)
- arena.free(match) // if addState saved it, ref was incremented
- } else if len(s[out]) == 0 {
- // machine has completed
- break
- }
- in, out = out, in // old out state is new in state
- // clear out old state
- old := s[out]
- for _, state := range old {
- arena.free(state.match)
- }
- s[out] = old[0:0] // truncate state vector
- c = nextChar
- thisPos := pos
- pos += nextWidth
- nextChar, nextWidth = i.step(pos)
- arena.atEOT = nextChar == endOfText
- arena.atBOT = false
- arena.pos = pos
- for _, st := range s[in] {
- switch st.inst.kind {
- case iBOT:
- case iEOT:
- case iChar:
- if c == st.inst.char {
- s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
- }
- case iCharClass:
- if st.inst.cclass.matches(c) {
- s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
- }
- case iAny:
- if c != endOfText {
- s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
- }
- case iNotNL:
- if c != endOfText && c != '\n' {
- s[out] = arena.addState(s[out], st.inst.next, st.prefixed, st.match)
- }
- case iBra:
- case iAlt:
- case iEnd:
- // choose leftmost longest
- if !found || // first
- st.match.m[0] < final.match.m[0] || // leftmost
- (st.match.m[0] == final.match.m[0] && thisPos > final.match.m[1]) { // longest
- if final.match != nil {
- arena.free(final.match)
- }
- final = st
- final.match.ref++
- final.match.m[1] = thisPos
- }
- found = true
- default:
- st.inst.print()
- panic("unknown instruction in execute")
- }
- }
- }
- if final.match == nil {
- return nil
- }
- // if match found, back up start of match by width of prefix.
- if final.prefixed && len(final.match.m) > 0 {
- final.match.m[0] -= len(re.prefix)
- }
- return final.match.m
+func (i *inputReader) context(pos int) syntax.EmptyOp {
+ return 0
}
// LiteralPrefix returns a literal string that must begin any match
// of the regular expression re. It returns the boolean true if the
// literal string comprises the entire regular expression.
func (re *Regexp) LiteralPrefix() (prefix string, complete bool) {
- c := make([]int, len(re.inst)-2) // minus start and end.
- // First instruction is start; skip that.
- i := 0
- for inst := re.inst[0].next; inst.kind != iEnd; inst = inst.next {
- // stop if this is not a char
- if inst.kind != iChar {
- return string(c[:i]), false
- }
- c[i] = inst.char
- i++
- }
- return string(c[:i]), true
+ return re.prefix, re.prefixComplete
}
// MatchReader returns whether the Regexp matches the text read by the
// RuneReader. The return value is a boolean: true for match, false for no
// match.
func (re *Regexp) MatchReader(r io.RuneReader) bool {
- return len(re.doExecute(newInputReader(r), 0)) > 0
+ return re.doExecute(newInputReader(r), 0, 0) != nil
}
// MatchString returns whether the Regexp matches the string s.
// The return value is a boolean: true for match, false for no match.
-func (re *Regexp) MatchString(s string) bool { return len(re.doExecute(newInputString(s), 0)) > 0 }
+func (re *Regexp) MatchString(s string) bool {
+ return re.doExecute(newInputString(s), 0, 0) != nil
+}
// Match returns whether the Regexp matches the byte slice b.
// The return value is a boolean: true for match, false for no match.
-func (re *Regexp) Match(b []byte) bool { return len(re.doExecute(newInputBytes(b), 0)) > 0 }
+func (re *Regexp) Match(b []byte) bool {
+ return re.doExecute(newInputBytes(b), 0, 0) != nil
+}
// MatchReader checks whether a textual regular expression matches the text
// read by the RuneReader. More complicated queries need to use Compile and
@@ -1044,7 +438,7 @@ func (re *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) str
searchPos := 0 // position where we next look for a match
buf := new(bytes.Buffer)
for searchPos <= len(src) {
- a := re.doExecute(newInputString(src), searchPos)
+ a := re.doExecute(newInputString(src), searchPos, 2)
if len(a) == 0 {
break // no more matches
}
@@ -1096,7 +490,7 @@ func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
searchPos := 0 // position where we next look for a match
buf := new(bytes.Buffer)
for searchPos <= len(src) {
- a := re.doExecute(newInputBytes(src), searchPos)
+ a := re.doExecute(newInputBytes(src), searchPos, 2)
if len(a) == 0 {
break // no more matches
}
@@ -1132,6 +526,12 @@ func (re *Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte {
return buf.Bytes()
}
+var specialBytes = []byte(`\.+*?()|[]{}^$`)
+
+func special(b byte) bool {
+ return bytes.IndexByte(specialBytes, b) >= 0
+}
+
// QuoteMeta returns a string that quotes all regular expression metacharacters
// inside the argument text; the returned string is a regular expression matching
// the literal text. For example, QuoteMeta(`[foo]`) returns `\[foo\]`.
@@ -1141,7 +541,7 @@ func QuoteMeta(s string) string {
// A byte loop is correct because all metacharacters are ASCII.
j := 0
for i := 0; i < len(s); i++ {
- if special(int(s[i])) {
+ if special(s[i]) {
b[j] = '\\'
j++
}
@@ -1151,6 +551,23 @@ func QuoteMeta(s string) string {
return string(b[0:j])
}
+// The number of capture values in the program may correspond
+// to fewer capturing expressions than are in the regexp.
+// For example, "(a){0}" turns into an empty program, so the
+// maximum capture in the program is 0 but we need to return
+// an expression for \1. Pad appends -1s to the slice a as needed.
+func (re *Regexp) pad(a []int) []int {
+ if a == nil {
+ // No match.
+ return nil
+ }
+ n := (1 + re.numSubexp) * 2
+ for len(a) < n {
+ a = append(a, -1)
+ }
+ return a
+}
+
// Find matches in slice b if b is non-nil, otherwise find matches in string s.
func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
var end int
@@ -1167,7 +584,7 @@ func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
} else {
in = newInputBytes(b)
}
- matches := re.doExecute(in, pos)
+ matches := re.doExecute(in, pos, re.prog.NumCap)
if len(matches) == 0 {
break
}
@@ -1198,7 +615,7 @@ func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
prevMatchEnd = matches[1]
if accept {
- deliver(matches)
+ deliver(re.pad(matches))
i++
}
}
@@ -1207,7 +624,7 @@ func (re *Regexp) allMatches(s string, b []byte, n int, deliver func([]int)) {
// Find returns a slice holding the text of the leftmost match in b of the regular expression.
// A return value of nil indicates no match.
func (re *Regexp) Find(b []byte) []byte {
- a := re.doExecute(newInputBytes(b), 0)
+ a := re.doExecute(newInputBytes(b), 0, 2)
if a == nil {
return nil
}
@@ -1219,7 +636,7 @@ func (re *Regexp) Find(b []byte) []byte {
// b[loc[0]:loc[1]].
// A return value of nil indicates no match.
func (re *Regexp) FindIndex(b []byte) (loc []int) {
- a := re.doExecute(newInputBytes(b), 0)
+ a := re.doExecute(newInputBytes(b), 0, 2)
if a == nil {
return nil
}
@@ -1232,7 +649,7 @@ func (re *Regexp) FindIndex(b []byte) (loc []int) {
// an empty string. Use FindStringIndex or FindStringSubmatch if it is
// necessary to distinguish these cases.
func (re *Regexp) FindString(s string) string {
- a := re.doExecute(newInputString(s), 0)
+ a := re.doExecute(newInputString(s), 0, 2)
if a == nil {
return ""
}
@@ -1244,7 +661,7 @@ func (re *Regexp) FindString(s string) string {
// itself is at s[loc[0]:loc[1]].
// A return value of nil indicates no match.
func (re *Regexp) FindStringIndex(s string) []int {
- a := re.doExecute(newInputString(s), 0)
+ a := re.doExecute(newInputString(s), 0, 2)
if a == nil {
return nil
}
@@ -1256,7 +673,7 @@ func (re *Regexp) FindStringIndex(s string) []int {
// the RuneReader. The match itself is at s[loc[0]:loc[1]]. A return
// value of nil indicates no match.
func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
- a := re.doExecute(newInputReader(r), 0)
+ a := re.doExecute(newInputReader(r), 0, 2)
if a == nil {
return nil
}
@@ -1269,13 +686,13 @@ func (re *Regexp) FindReaderIndex(r io.RuneReader) []int {
// comment.
// A return value of nil indicates no match.
func (re *Regexp) FindSubmatch(b []byte) [][]byte {
- a := re.doExecute(newInputBytes(b), 0)
+ a := re.doExecute(newInputBytes(b), 0, re.prog.NumCap)
if a == nil {
return nil
}
- ret := make([][]byte, len(a)/2)
+ ret := make([][]byte, 1+re.numSubexp)
for i := range ret {
- if a[2*i] >= 0 {
+ if 2*i < len(a) && a[2*i] >= 0 {
ret[i] = b[a[2*i]:a[2*i+1]]
}
}
@@ -1288,7 +705,7 @@ func (re *Regexp) FindSubmatch(b []byte) [][]byte {
// in the package comment.
// A return value of nil indicates no match.
func (re *Regexp) FindSubmatchIndex(b []byte) []int {
- return re.doExecute(newInputBytes(b), 0)
+ return re.pad(re.doExecute(newInputBytes(b), 0, re.prog.NumCap))
}
// FindStringSubmatch returns a slice of strings holding the text of the
@@ -1297,13 +714,13 @@ func (re *Regexp) FindSubmatchIndex(b []byte) []int {
// package comment.
// A return value of nil indicates no match.
func (re *Regexp) FindStringSubmatch(s string) []string {
- a := re.doExecute(newInputString(s), 0)
+ a := re.doExecute(newInputString(s), 0, re.prog.NumCap)
if a == nil {
return nil
}
- ret := make([]string, len(a)/2)
+ ret := make([]string, 1+re.numSubexp)
for i := range ret {
- if a[2*i] >= 0 {
+ if 2*i < len(a) && a[2*i] >= 0 {
ret[i] = s[a[2*i]:a[2*i+1]]
}
}
@@ -1316,7 +733,7 @@ func (re *Regexp) FindStringSubmatch(s string) []string {
// 'Index' descriptions in the package comment.
// A return value of nil indicates no match.
func (re *Regexp) FindStringSubmatchIndex(s string) []int {
- return re.doExecute(newInputString(s), 0)
+ return re.pad(re.doExecute(newInputString(s), 0, re.prog.NumCap))
}
// FindReaderSubmatchIndex returns a slice holding the index pairs
@@ -1325,7 +742,7 @@ func (re *Regexp) FindStringSubmatchIndex(s string) []int {
// by the 'Submatch' and 'Index' descriptions in the package comment. A
// return value of nil indicates no match.
func (re *Regexp) FindReaderSubmatchIndex(r io.RuneReader) []int {
- return re.doExecute(newInputReader(r), 0)
+ return re.pad(re.doExecute(newInputReader(r), 0, re.prog.NumCap))
}
const startSize = 10 // The size at which to start a slice in the 'All' routines.
diff --git a/libgo/go/regexp/syntax/compile.go b/libgo/go/regexp/syntax/compile.go
new file mode 100644
index 00000000000..c415d39a57e
--- /dev/null
+++ b/libgo/go/regexp/syntax/compile.go
@@ -0,0 +1,288 @@
+package syntax
+
+import (
+ "os"
+ "unicode"
+)
+
+// A patchList is a list of instruction pointers that need to be filled in (patched).
+// Because the pointers haven't been filled in yet, we can reuse their storage
+// to hold the list. It's kind of sleazy, but works well in practice.
+// See http://swtch.com/~rsc/regexp/regexp1.html for inspiration.
+//
+// These aren't really pointers: they're integers, so we can reinterpret them
+// this way without using package unsafe. A value l denotes
+// p.inst[l>>1].Out (l&1==0) or .Arg (l&1==1).
+// l == 0 denotes the empty list, okay because we start every program
+// with a fail instruction, so we'll never want to point at its output link.
+type patchList uint32
+
+func (l patchList) next(p *Prog) patchList {
+ i := &p.Inst[l>>1]
+ if l&1 == 0 {
+ return patchList(i.Out)
+ }
+ return patchList(i.Arg)
+}
+
+func (l patchList) patch(p *Prog, val uint32) {
+ for l != 0 {
+ i := &p.Inst[l>>1]
+ if l&1 == 0 {
+ l = patchList(i.Out)
+ i.Out = val
+ } else {
+ l = patchList(i.Arg)
+ i.Arg = val
+ }
+ }
+}
+
+func (l1 patchList) append(p *Prog, l2 patchList) patchList {
+ if l1 == 0 {
+ return l2
+ }
+ if l2 == 0 {
+ return l1
+ }
+
+ last := l1
+ for {
+ next := last.next(p)
+ if next == 0 {
+ break
+ }
+ last = next
+ }
+
+ i := &p.Inst[last>>1]
+ if last&1 == 0 {
+ i.Out = uint32(l2)
+ } else {
+ i.Arg = uint32(l2)
+ }
+ return l1
+}
+
+// A frag represents a compiled program fragment.
+type frag struct {
+ i uint32 // index of first instruction
+ out patchList // where to record end instruction
+}
+
+type compiler struct {
+ p *Prog
+}
+
+// Compile compiles the regexp into a program to be executed.
+// The regexp should have been simplified already (returned from re.Simplify).
+func Compile(re *Regexp) (*Prog, os.Error) {
+ var c compiler
+ c.init()
+ f := c.compile(re)
+ f.out.patch(c.p, c.inst(InstMatch).i)
+ c.p.Start = int(f.i)
+ return c.p, nil
+}
+
+func (c *compiler) init() {
+ c.p = new(Prog)
+ c.p.NumCap = 2 // implicit ( and ) for whole match $0
+ c.inst(InstFail)
+}
+
+var anyRuneNotNL = []int{0, '\n' - 1, '\n' + 1, unicode.MaxRune}
+var anyRune = []int{0, unicode.MaxRune}
+
+func (c *compiler) compile(re *Regexp) frag {
+ switch re.Op {
+ case OpNoMatch:
+ return c.fail()
+ case OpEmptyMatch:
+ return c.nop()
+ case OpLiteral:
+ if len(re.Rune) == 0 {
+ return c.nop()
+ }
+ var f frag
+ for j := range re.Rune {
+ f1 := c.rune(re.Rune[j:j+1], re.Flags)
+ if j == 0 {
+ f = f1
+ } else {
+ f = c.cat(f, f1)
+ }
+ }
+ return f
+ case OpCharClass:
+ return c.rune(re.Rune, re.Flags)
+ case OpAnyCharNotNL:
+ return c.rune(anyRuneNotNL, 0)
+ case OpAnyChar:
+ return c.rune(anyRune, 0)
+ case OpBeginLine:
+ return c.empty(EmptyBeginLine)
+ case OpEndLine:
+ return c.empty(EmptyEndLine)
+ case OpBeginText:
+ return c.empty(EmptyBeginText)
+ case OpEndText:
+ return c.empty(EmptyEndText)
+ case OpWordBoundary:
+ return c.empty(EmptyWordBoundary)
+ case OpNoWordBoundary:
+ return c.empty(EmptyNoWordBoundary)
+ case OpCapture:
+ bra := c.cap(uint32(re.Cap << 1))
+ sub := c.compile(re.Sub[0])
+ ket := c.cap(uint32(re.Cap<<1 | 1))
+ return c.cat(c.cat(bra, sub), ket)
+ case OpStar:
+ return c.star(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+ case OpPlus:
+ return c.plus(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+ case OpQuest:
+ return c.quest(c.compile(re.Sub[0]), re.Flags&NonGreedy != 0)
+ case OpConcat:
+ if len(re.Sub) == 0 {
+ return c.nop()
+ }
+ var f frag
+ for i, sub := range re.Sub {
+ if i == 0 {
+ f = c.compile(sub)
+ } else {
+ f = c.cat(f, c.compile(sub))
+ }
+ }
+ return f
+ case OpAlternate:
+ var f frag
+ for _, sub := range re.Sub {
+ f = c.alt(f, c.compile(sub))
+ }
+ return f
+ }
+ panic("regexp: unhandled case in compile")
+}
+
+func (c *compiler) inst(op InstOp) frag {
+ // TODO: impose length limit
+ f := frag{i: uint32(len(c.p.Inst))}
+ c.p.Inst = append(c.p.Inst, Inst{Op: op})
+ return f
+}
+
+func (c *compiler) nop() frag {
+ f := c.inst(InstNop)
+ f.out = patchList(f.i << 1)
+ return f
+}
+
+func (c *compiler) fail() frag {
+ return frag{}
+}
+
+func (c *compiler) cap(arg uint32) frag {
+ f := c.inst(InstCapture)
+ f.out = patchList(f.i << 1)
+ c.p.Inst[f.i].Arg = arg
+
+ if c.p.NumCap < int(arg)+1 {
+ c.p.NumCap = int(arg) + 1
+ }
+ return f
+}
+
+func (c *compiler) cat(f1, f2 frag) frag {
+ // concat of failure is failure
+ if f1.i == 0 || f2.i == 0 {
+ return frag{}
+ }
+
+ // TODO: elide nop
+
+ f1.out.patch(c.p, f2.i)
+ return frag{f1.i, f2.out}
+}
+
+func (c *compiler) alt(f1, f2 frag) frag {
+ // alt of failure is other
+ if f1.i == 0 {
+ return f2
+ }
+ if f2.i == 0 {
+ return f1
+ }
+
+ f := c.inst(InstAlt)
+ i := &c.p.Inst[f.i]
+ i.Out = f1.i
+ i.Arg = f2.i
+ f.out = f1.out.append(c.p, f2.out)
+ return f
+}
+
+func (c *compiler) quest(f1 frag, nongreedy bool) frag {
+ f := c.inst(InstAlt)
+ i := &c.p.Inst[f.i]
+ if nongreedy {
+ i.Arg = f1.i
+ f.out = patchList(f.i << 1)
+ } else {
+ i.Out = f1.i
+ f.out = patchList(f.i<<1 | 1)
+ }
+ f.out = f.out.append(c.p, f1.out)
+ return f
+}
+
+func (c *compiler) star(f1 frag, nongreedy bool) frag {
+ f := c.inst(InstAlt)
+ i := &c.p.Inst[f.i]
+ if nongreedy {
+ i.Arg = f1.i
+ f.out = patchList(f.i << 1)
+ } else {
+ i.Out = f1.i
+ f.out = patchList(f.i<<1 | 1)
+ }
+ f1.out.patch(c.p, f.i)
+ return f
+}
+
+func (c *compiler) plus(f1 frag, nongreedy bool) frag {
+ return frag{f1.i, c.star(f1, nongreedy).out}
+}
+
+func (c *compiler) empty(op EmptyOp) frag {
+ f := c.inst(InstEmptyWidth)
+ c.p.Inst[f.i].Arg = uint32(op)
+ f.out = patchList(f.i << 1)
+ return f
+}
+
+func (c *compiler) rune(rune []int, flags Flags) frag {
+ f := c.inst(InstRune)
+ i := &c.p.Inst[f.i]
+ i.Rune = rune
+ flags &= FoldCase // only relevant flag is FoldCase
+ if len(rune) != 1 || unicode.SimpleFold(rune[0]) == rune[0] {
+ // and sometimes not even that
+ flags &^= FoldCase
+ }
+ i.Arg = uint32(flags)
+ f.out = patchList(f.i << 1)
+
+ // Special cases for exec machine.
+ switch {
+ case flags&FoldCase == 0 && (len(rune) == 1 || len(rune) == 2 && rune[0] == rune[1]):
+ i.Op = InstRune1
+ case len(rune) == 2 && rune[0] == 0 && rune[1] == unicode.MaxRune:
+ i.Op = InstRuneAny
+ case len(rune) == 4 && rune[0] == 0 && rune[1] == '\n'-1 && rune[2] == '\n'+1 && rune[3] == unicode.MaxRune:
+ i.Op = InstRuneAnyNotNL
+ }
+
+ return f
+}
diff --git a/libgo/go/regexp/syntax/parse.go b/libgo/go/regexp/syntax/parse.go
new file mode 100644
index 00000000000..7013459019c
--- /dev/null
+++ b/libgo/go/regexp/syntax/parse.go
@@ -0,0 +1,1861 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syntax
+
+import (
+ "os"
+ "sort"
+ "strings"
+ "unicode"
+ "utf8"
+)
+
+// An Error describes a failure to parse a regular expression
+// and gives the offending expression.
+type Error struct {
+ Code ErrorCode
+ Expr string
+}
+
+func (e *Error) String() string {
+ return "error parsing regexp: " + e.Code.String() + ": `" + e.Expr + "`"
+}
+
+// An ErrorCode describes a failure to parse a regular expression.
+type ErrorCode string
+
+const (
+ // Unexpected error
+ ErrInternalError ErrorCode = "regexp/syntax: internal error"
+
+ // Parse errors
+ ErrInvalidCharClass ErrorCode = "invalid character class"
+ ErrInvalidCharRange ErrorCode = "invalid character class range"
+ ErrInvalidEscape ErrorCode = "invalid escape sequence"
+ ErrInvalidNamedCapture ErrorCode = "invalid named capture"
+ ErrInvalidPerlOp ErrorCode = "invalid or unsupported Perl syntax"
+ ErrInvalidRepeatOp ErrorCode = "invalid nested repetition operator"
+ ErrInvalidRepeatSize ErrorCode = "invalid repeat count"
+ ErrInvalidUTF8 ErrorCode = "invalid UTF-8"
+ ErrMissingBracket ErrorCode = "missing closing ]"
+ ErrMissingParen ErrorCode = "missing closing )"
+ ErrMissingRepeatArgument ErrorCode = "missing argument to repetition operator"
+ ErrTrailingBackslash ErrorCode = "trailing backslash at end of expression"
+)
+
+func (e ErrorCode) String() string {
+ return string(e)
+}
+
+// Flags control the behavior of the parser and record information about regexp context.
+type Flags uint16
+
+const (
+ FoldCase Flags = 1 << iota // case-insensitive match
+ Literal // treat pattern as literal string
+ ClassNL // allow character classes like [^a-z] and [[:space:]] to match newline
+ DotNL // allow . to match newline
+ OneLine // treat ^ and $ as only matching at beginning and end of text
+ NonGreedy // make repetition operators default to non-greedy
+ PerlX // allow Perl extensions
+ UnicodeGroups // allow \p{Han}, \P{Han} for Unicode group and negation
+ WasDollar // regexp OpEndText was $, not \z
+ Simple // regexp contains no counted repetition
+
+ MatchNL = ClassNL | DotNL
+
+ Perl = ClassNL | OneLine | PerlX | UnicodeGroups // as close to Perl as possible
+ POSIX Flags = 0 // POSIX syntax
+)
+
+// Pseudo-ops for parsing stack.
+const (
+ opLeftParen = opPseudo + iota
+ opVerticalBar
+)
+
+type parser struct {
+ flags Flags // parse mode flags
+ stack []*Regexp // stack of parsed expressions
+ free *Regexp
+ numCap int // number of capturing groups seen
+ wholeRegexp string
+ tmpClass []int // temporary char class work space
+}
+
+func (p *parser) newRegexp(op Op) *Regexp {
+ re := p.free
+ if re != nil {
+ p.free = re.Sub0[0]
+ *re = Regexp{}
+ } else {
+ re = new(Regexp)
+ }
+ re.Op = op
+ return re
+}
+
+func (p *parser) reuse(re *Regexp) {
+ re.Sub0[0] = p.free
+ p.free = re
+}
+
+// Parse stack manipulation.
+
+// push pushes the regexp re onto the parse stack and returns the regexp.
+func (p *parser) push(re *Regexp) *Regexp {
+ if re.Op == OpCharClass && len(re.Rune) == 2 && re.Rune[0] == re.Rune[1] {
+ // Single rune.
+ if p.maybeConcat(re.Rune[0], p.flags&^FoldCase) {
+ return nil
+ }
+ re.Op = OpLiteral
+ re.Rune = re.Rune[:1]
+ re.Flags = p.flags &^ FoldCase
+ } else if re.Op == OpCharClass && len(re.Rune) == 4 &&
+ re.Rune[0] == re.Rune[1] && re.Rune[2] == re.Rune[3] &&
+ unicode.SimpleFold(re.Rune[0]) == re.Rune[2] &&
+ unicode.SimpleFold(re.Rune[2]) == re.Rune[0] ||
+ re.Op == OpCharClass && len(re.Rune) == 2 &&
+ re.Rune[0]+1 == re.Rune[1] &&
+ unicode.SimpleFold(re.Rune[0]) == re.Rune[1] &&
+ unicode.SimpleFold(re.Rune[1]) == re.Rune[0] {
+ // Case-insensitive rune like [Aa] or [Δδ].
+ if p.maybeConcat(re.Rune[0], p.flags|FoldCase) {
+ return nil
+ }
+
+ // Rewrite as (case-insensitive) literal.
+ re.Op = OpLiteral
+ re.Rune = re.Rune[:1]
+ re.Flags = p.flags | FoldCase
+ } else {
+ // Incremental concatenation.
+ p.maybeConcat(-1, 0)
+ }
+
+ p.stack = append(p.stack, re)
+ return re
+}
+
+// maybeConcat implements incremental concatenation
+// of literal runes into string nodes. The parser calls this
+// before each push, so only the top fragment of the stack
+// might need processing. Since this is called before a push,
+// the topmost literal is no longer subject to operators like *
+// (Otherwise ab* would turn into (ab)*.)
+// If r >= 0 and there's a node left over, maybeConcat uses it
+// to push r with the given flags.
+// maybeConcat reports whether r was pushed.
+func (p *parser) maybeConcat(r int, flags Flags) bool {
+ n := len(p.stack)
+ if n < 2 {
+ return false
+ }
+
+ re1 := p.stack[n-1]
+ re2 := p.stack[n-2]
+ if re1.Op != OpLiteral || re2.Op != OpLiteral || re1.Flags&FoldCase != re2.Flags&FoldCase {
+ return false
+ }
+
+ // Push re1 into re2.
+ re2.Rune = append(re2.Rune, re1.Rune...)
+
+ // Reuse re1 if possible.
+ if r >= 0 {
+ re1.Rune = re1.Rune0[:1]
+ re1.Rune[0] = r
+ re1.Flags = flags
+ return true
+ }
+
+ p.stack = p.stack[:n-1]
+ p.reuse(re1)
+ return false // did not push r
+}
+
+// newLiteral returns a new OpLiteral Regexp with the given flags
+func (p *parser) newLiteral(r int, flags Flags) *Regexp {
+ re := p.newRegexp(OpLiteral)
+ re.Flags = flags
+ if flags&FoldCase != 0 {
+ r = minFoldRune(r)
+ }
+ re.Rune0[0] = r
+ re.Rune = re.Rune0[:1]
+ return re
+}
+
+// minFoldRune returns the minimum rune fold-equivalent to r.
+func minFoldRune(r int) int {
+ if r < MinFold || r > MaxFold {
+ return r
+ }
+ min := r
+ r0 := r
+ for r = unicode.SimpleFold(r); r != r0; r = unicode.SimpleFold(r) {
+ if min > r {
+ min = r
+ }
+ }
+ return min
+}
+
+// literal pushes a literal regexp for the rune r on the stack
+// and returns that regexp.
+func (p *parser) literal(r int) {
+ p.push(p.newLiteral(r, p.flags))
+}
+
+// op pushes a regexp with the given op onto the stack
+// and returns that regexp.
+func (p *parser) op(op Op) *Regexp {
+ re := p.newRegexp(op)
+ re.Flags = p.flags
+ return p.push(re)
+}
+
+// repeat replaces the top stack element with itself repeated according to op, min, max.
+// before is the regexp suffix starting at the repetition operator.
+// after is the regexp suffix following after the repetition operator.
+// repeat returns an updated 'after' and an error, if any.
+func (p *parser) repeat(op Op, min, max int, before, after, lastRepeat string) (string, os.Error) {
+ flags := p.flags
+ if p.flags&PerlX != 0 {
+ if len(after) > 0 && after[0] == '?' {
+ after = after[1:]
+ flags ^= NonGreedy
+ }
+ if lastRepeat != "" {
+ // In Perl it is not allowed to stack repetition operators:
+ // a** is a syntax error, not a doubled star, and a++ means
+ // something else entirely, which we don't support!
+ return "", &Error{ErrInvalidRepeatOp, lastRepeat[:len(lastRepeat)-len(after)]}
+ }
+ }
+ n := len(p.stack)
+ if n == 0 {
+ return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
+ }
+ sub := p.stack[n-1]
+ if sub.Op >= opPseudo {
+ return "", &Error{ErrMissingRepeatArgument, before[:len(before)-len(after)]}
+ }
+ re := p.newRegexp(op)
+ re.Min = min
+ re.Max = max
+ re.Flags = flags
+ re.Sub = re.Sub0[:1]
+ re.Sub[0] = sub
+ p.stack[n-1] = re
+ return after, nil
+}
+
+// concat replaces the top of the stack (above the topmost '|' or '(') with its concatenation.
+func (p *parser) concat() *Regexp {
+ p.maybeConcat(-1, 0)
+
+ // Scan down to find pseudo-operator | or (.
+ i := len(p.stack)
+ for i > 0 && p.stack[i-1].Op < opPseudo {
+ i--
+ }
+ subs := p.stack[i:]
+ p.stack = p.stack[:i]
+
+ // Empty concatenation is special case.
+ if len(subs) == 0 {
+ return p.push(p.newRegexp(OpEmptyMatch))
+ }
+
+ return p.push(p.collapse(subs, OpConcat))
+}
+
+// alternate replaces the top of the stack (above the topmost '(') with its alternation.
+func (p *parser) alternate() *Regexp {
+ // Scan down to find pseudo-operator (.
+ // There are no | above (.
+ i := len(p.stack)
+ for i > 0 && p.stack[i-1].Op < opPseudo {
+ i--
+ }
+ subs := p.stack[i:]
+ p.stack = p.stack[:i]
+
+ // Make sure top class is clean.
+ // All the others already are (see swapVerticalBar).
+ if len(subs) > 0 {
+ cleanAlt(subs[len(subs)-1])
+ }
+
+ // Empty alternate is special case
+ // (shouldn't happen but easy to handle).
+ if len(subs) == 0 {
+ return p.push(p.newRegexp(OpNoMatch))
+ }
+
+ return p.push(p.collapse(subs, OpAlternate))
+}
+
+// cleanAlt cleans re for eventual inclusion in an alternation.
+func cleanAlt(re *Regexp) {
+ switch re.Op {
+ case OpCharClass:
+ re.Rune = cleanClass(&re.Rune)
+ if len(re.Rune) == 2 && re.Rune[0] == 0 && re.Rune[1] == unicode.MaxRune {
+ re.Rune = nil
+ re.Op = OpAnyChar
+ return
+ }
+ if len(re.Rune) == 4 && re.Rune[0] == 0 && re.Rune[1] == '\n'-1 && re.Rune[2] == '\n'+1 && re.Rune[3] == unicode.MaxRune {
+ re.Rune = nil
+ re.Op = OpAnyCharNotNL
+ return
+ }
+ if cap(re.Rune)-len(re.Rune) > 100 {
+ // re.Rune will not grow any more.
+ // Make a copy or inline to reclaim storage.
+ re.Rune = append(re.Rune0[:0], re.Rune...)
+ }
+ }
+}
+
+// collapse returns the result of applying op to sub.
+// If sub contains op nodes, they all get hoisted up
+// so that there is never a concat of a concat or an
+// alternate of an alternate.
+func (p *parser) collapse(subs []*Regexp, op Op) *Regexp {
+ if len(subs) == 1 {
+ return subs[0]
+ }
+ re := p.newRegexp(op)
+ re.Sub = re.Sub0[:0]
+ for _, sub := range subs {
+ if sub.Op == op {
+ re.Sub = append(re.Sub, sub.Sub...)
+ p.reuse(sub)
+ } else {
+ re.Sub = append(re.Sub, sub)
+ }
+ }
+ if op == OpAlternate {
+ re.Sub = p.factor(re.Sub, re.Flags)
+ if len(re.Sub) == 1 {
+ old := re
+ re = re.Sub[0]
+ p.reuse(old)
+ }
+ }
+ return re
+}
+
+// factor factors common prefixes from the alternation list sub.
+// It returns a replacement list that reuses the same storage and
+// frees (passes to p.reuse) any removed *Regexps.
+//
+// For example,
+// ABC|ABD|AEF|BCX|BCY
+// simplifies by literal prefix extraction to
+// A(B(C|D)|EF)|BC(X|Y)
+// which simplifies by character class introduction to
+// A(B[CD]|EF)|BC[XY]
+//
+func (p *parser) factor(sub []*Regexp, flags Flags) []*Regexp {
+ if len(sub) < 2 {
+ return sub
+ }
+
+ // Round 1: Factor out common literal prefixes.
+ var str []int
+ var strflags Flags
+ start := 0
+ out := sub[:0]
+ for i := 0; i <= len(sub); i++ {
+ // Invariant: the Regexps that were in sub[0:start] have been
+ // used or marked for reuse, and the slice space has been reused
+ // for out (len(out) <= start).
+ //
+ // Invariant: sub[start:i] consists of regexps that all begin
+ // with str as modified by strflags.
+ var istr []int
+ var iflags Flags
+ if i < len(sub) {
+ istr, iflags = p.leadingString(sub[i])
+ if iflags == strflags {
+ same := 0
+ for same < len(str) && same < len(istr) && str[same] == istr[same] {
+ same++
+ }
+ if same > 0 {
+ // Matches at least one rune in current range.
+ // Keep going around.
+ str = str[:same]
+ continue
+ }
+ }
+ }
+
+ // Found end of a run with common leading literal string:
+ // sub[start:i] all begin with str[0:len(str)], but sub[i]
+ // does not even begin with str[0].
+ //
+ // Factor out common string and append factored expression to out.
+ if i == start {
+ // Nothing to do - run of length 0.
+ } else if i == start+1 {
+ // Just one: don't bother factoring.
+ out = append(out, sub[start])
+ } else {
+ // Construct factored form: prefix(suffix1|suffix2|...)
+ prefix := p.newRegexp(OpLiteral)
+ prefix.Flags = strflags
+ prefix.Rune = append(prefix.Rune[:0], str...)
+
+ for j := start; j < i; j++ {
+ sub[j] = p.removeLeadingString(sub[j], len(str))
+ }
+ suffix := p.collapse(sub[start:i], OpAlternate) // recurse
+
+ re := p.newRegexp(OpConcat)
+ re.Sub = append(re.Sub[:0], prefix, suffix)
+ out = append(out, re)
+ }
+
+ // Prepare for next iteration.
+ start = i
+ str = istr
+ strflags = iflags
+ }
+ sub = out
+
+ // Round 2: Factor out common complex prefixes,
+ // just the first piece of each concatenation,
+ // whatever it is. This is good enough a lot of the time.
+ start = 0
+ out = sub[:0]
+ var first *Regexp
+ for i := 0; i <= len(sub); i++ {
+ // Invariant: the Regexps that were in sub[0:start] have been
+ // used or marked for reuse, and the slice space has been reused
+ // for out (len(out) <= start).
+ //
+ // Invariant: sub[start:i] consists of regexps that all begin with ifirst.
+ var ifirst *Regexp
+ if i < len(sub) {
+ ifirst = p.leadingRegexp(sub[i])
+ if first != nil && first.Equal(ifirst) {
+ continue
+ }
+ }
+
+ // Found end of a run with common leading regexp:
+ // sub[start:i] all begin with first but sub[i] does not.
+ //
+ // Factor out common regexp and append factored expression to out.
+ if i == start {
+ // Nothing to do - run of length 0.
+ } else if i == start+1 {
+ // Just one: don't bother factoring.
+ out = append(out, sub[start])
+ } else {
+ // Construct factored form: prefix(suffix1|suffix2|...)
+ prefix := first
+ for j := start; j < i; j++ {
+ reuse := j != start // prefix came from sub[start]
+ sub[j] = p.removeLeadingRegexp(sub[j], reuse)
+ }
+ suffix := p.collapse(sub[start:i], OpAlternate) // recurse
+
+ re := p.newRegexp(OpConcat)
+ re.Sub = append(re.Sub[:0], prefix, suffix)
+ out = append(out, re)
+ }
+
+ // Prepare for next iteration.
+ start = i
+ first = ifirst
+ }
+ sub = out
+
+ // Round 3: Collapse runs of single literals into character classes.
+ start = 0
+ out = sub[:0]
+ for i := 0; i <= len(sub); i++ {
+ // Invariant: the Regexps that were in sub[0:start] have been
+ // used or marked for reuse, and the slice space has been reused
+ // for out (len(out) <= start).
+ //
+ // Invariant: sub[start:i] consists of regexps that are either
+ // literal runes or character classes.
+ if i < len(sub) && isCharClass(sub[i]) {
+ continue
+ }
+
+ // sub[i] is not a char or char class;
+ // emit char class for sub[start:i]...
+ if i == start {
+ // Nothing to do - run of length 0.
+ } else if i == start+1 {
+ out = append(out, sub[start])
+ } else {
+ // Make new char class.
+ // Start with most complex regexp in sub[start].
+ max := start
+ for j := start + 1; j < i; j++ {
+ if sub[max].Op < sub[j].Op || sub[max].Op == sub[j].Op && len(sub[max].Rune) < len(sub[j].Rune) {
+ max = j
+ }
+ }
+ sub[start], sub[max] = sub[max], sub[start]
+
+ for j := start + 1; j < i; j++ {
+ mergeCharClass(sub[start], sub[j])
+ p.reuse(sub[j])
+ }
+ cleanAlt(sub[start])
+ out = append(out, sub[start])
+ }
+
+ // ... and then emit sub[i].
+ if i < len(sub) {
+ out = append(out, sub[i])
+ }
+ start = i + 1
+ }
+ sub = out
+
+ // Round 4: Collapse runs of empty matches into a single empty match.
+ start = 0
+ out = sub[:0]
+ for i := range sub {
+ if i+1 < len(sub) && sub[i].Op == OpEmptyMatch && sub[i+1].Op == OpEmptyMatch {
+ continue
+ }
+ out = append(out, sub[i])
+ }
+ sub = out
+
+ return sub
+}
+
+// leadingString returns the leading literal string that re begins with.
+// The string refers to storage in re or its children.
+func (p *parser) leadingString(re *Regexp) ([]int, Flags) {
+ if re.Op == OpConcat && len(re.Sub) > 0 {
+ re = re.Sub[0]
+ }
+ if re.Op != OpLiteral {
+ return nil, 0
+ }
+ return re.Rune, re.Flags & FoldCase
+}
+
+// removeLeadingString removes the first n leading runes
+// from the beginning of re. It returns the replacement for re.
+func (p *parser) removeLeadingString(re *Regexp, n int) *Regexp {
+ if re.Op == OpConcat && len(re.Sub) > 0 {
+ // Removing a leading string in a concatenation
+ // might simplify the concatenation.
+ sub := re.Sub[0]
+ sub = p.removeLeadingString(sub, n)
+ re.Sub[0] = sub
+ if sub.Op == OpEmptyMatch {
+ p.reuse(sub)
+ switch len(re.Sub) {
+ case 0, 1:
+ // Impossible but handle.
+ re.Op = OpEmptyMatch
+ re.Sub = nil
+ case 2:
+ old := re
+ re = re.Sub[1]
+ p.reuse(old)
+ default:
+ copy(re.Sub, re.Sub[1:])
+ re.Sub = re.Sub[:len(re.Sub)-1]
+ }
+ }
+ return re
+ }
+
+ if re.Op == OpLiteral {
+ re.Rune = re.Rune[:copy(re.Rune, re.Rune[n:])]
+ if len(re.Rune) == 0 {
+ re.Op = OpEmptyMatch
+ }
+ }
+ return re
+}
+
+// leadingRegexp returns the leading regexp that re begins with.
+// The regexp refers to storage in re or its children.
+func (p *parser) leadingRegexp(re *Regexp) *Regexp {
+ if re.Op == OpEmptyMatch {
+ return nil
+ }
+ if re.Op == OpConcat && len(re.Sub) > 0 {
+ sub := re.Sub[0]
+ if sub.Op == OpEmptyMatch {
+ return nil
+ }
+ return sub
+ }
+ return re
+}
+
+// removeLeadingRegexp removes the leading regexp in re.
+// It returns the replacement for re.
+// If reuse is true, it passes the removed regexp (if no longer needed) to p.reuse.
+func (p *parser) removeLeadingRegexp(re *Regexp, reuse bool) *Regexp {
+ if re.Op == OpConcat && len(re.Sub) > 0 {
+ if reuse {
+ p.reuse(re.Sub[0])
+ }
+ re.Sub = re.Sub[:copy(re.Sub, re.Sub[1:])]
+ switch len(re.Sub) {
+ case 0:
+ re.Op = OpEmptyMatch
+ re.Sub = nil
+ case 1:
+ old := re
+ re = re.Sub[0]
+ p.reuse(old)
+ }
+ return re
+ }
+ if reuse {
+ p.reuse(re)
+ }
+ return p.newRegexp(OpEmptyMatch)
+}
+
+func literalRegexp(s string, flags Flags) *Regexp {
+ re := &Regexp{Op: OpLiteral}
+ re.Flags = flags
+ re.Rune = re.Rune0[:0] // use local storage for small strings
+ for _, c := range s {
+ if len(re.Rune) >= cap(re.Rune) {
+ // string is too long to fit in Rune0. let Go handle it
+ re.Rune = []int(s)
+ break
+ }
+ re.Rune = append(re.Rune, c)
+ }
+ return re
+}
+
+// Parsing.
+
+func Parse(s string, flags Flags) (*Regexp, os.Error) {
+ if flags&Literal != 0 {
+ // Trivial parser for literal string.
+ if err := checkUTF8(s); err != nil {
+ return nil, err
+ }
+ return literalRegexp(s, flags), nil
+ }
+
+ // Otherwise, must do real work.
+ var (
+ p parser
+ err os.Error
+ c int
+ op Op
+ lastRepeat string
+ min, max int
+ )
+ p.flags = flags
+ p.wholeRegexp = s
+ t := s
+ for t != "" {
+ repeat := ""
+ BigSwitch:
+ switch t[0] {
+ default:
+ if c, t, err = nextRune(t); err != nil {
+ return nil, err
+ }
+ p.literal(c)
+
+ case '(':
+ if p.flags&PerlX != 0 && len(t) >= 2 && t[1] == '?' {
+ // Flag changes and non-capturing groups.
+ if t, err = p.parsePerlFlags(t); err != nil {
+ return nil, err
+ }
+ break
+ }
+ p.numCap++
+ p.op(opLeftParen).Cap = p.numCap
+ t = t[1:]
+ case '|':
+ if err = p.parseVerticalBar(); err != nil {
+ return nil, err
+ }
+ t = t[1:]
+ case ')':
+ if err = p.parseRightParen(); err != nil {
+ return nil, err
+ }
+ t = t[1:]
+ case '^':
+ if p.flags&OneLine != 0 {
+ p.op(OpBeginText)
+ } else {
+ p.op(OpBeginLine)
+ }
+ t = t[1:]
+ case '$':
+ if p.flags&OneLine != 0 {
+ p.op(OpEndText).Flags |= WasDollar
+ } else {
+ p.op(OpEndLine)
+ }
+ t = t[1:]
+ case '.':
+ if p.flags&DotNL != 0 {
+ p.op(OpAnyChar)
+ } else {
+ p.op(OpAnyCharNotNL)
+ }
+ t = t[1:]
+ case '[':
+ if t, err = p.parseClass(t); err != nil {
+ return nil, err
+ }
+ case '*', '+', '?':
+ before := t
+ switch t[0] {
+ case '*':
+ op = OpStar
+ case '+':
+ op = OpPlus
+ case '?':
+ op = OpQuest
+ }
+ after := t[1:]
+ if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil {
+ return nil, err
+ }
+ repeat = before
+ t = after
+ case '{':
+ op = OpRepeat
+ before := t
+ min, max, after, ok := p.parseRepeat(t)
+ if !ok {
+ // If the repeat cannot be parsed, { is a literal.
+ p.literal('{')
+ t = t[1:]
+ break
+ }
+ if min < 0 || min > 1000 || max > 1000 || max >= 0 && min > max {
+ // Numbers were too big, or max is present and min > max.
+ return nil, &Error{ErrInvalidRepeatSize, before[:len(before)-len(after)]}
+ }
+ if after, err = p.repeat(op, min, max, before, after, lastRepeat); err != nil {
+ return nil, err
+ }
+ repeat = before
+ t = after
+ case '\\':
+ if p.flags&PerlX != 0 && len(t) >= 2 {
+ switch t[1] {
+ case 'A':
+ p.op(OpBeginText)
+ t = t[2:]
+ break BigSwitch
+ case 'b':
+ p.op(OpWordBoundary)
+ t = t[2:]
+ break BigSwitch
+ case 'B':
+ p.op(OpNoWordBoundary)
+ t = t[2:]
+ break BigSwitch
+ case 'C':
+ // any byte; not supported
+ return nil, &Error{ErrInvalidEscape, t[:2]}
+ case 'Q':
+ // \Q ... \E: the ... is always literals
+ var lit string
+ if i := strings.Index(t, `\E`); i < 0 {
+ lit = t[2:]
+ t = ""
+ } else {
+ lit = t[2:i]
+ t = t[i+2:]
+ }
+ p.push(literalRegexp(lit, p.flags))
+ break BigSwitch
+ case 'z':
+ p.op(OpEndText)
+ t = t[2:]
+ break BigSwitch
+ }
+ }
+
+ re := p.newRegexp(OpCharClass)
+ re.Flags = p.flags
+
+ // Look for Unicode character group like \p{Han}
+ if len(t) >= 2 && (t[1] == 'p' || t[1] == 'P') {
+ r, rest, err := p.parseUnicodeClass(t, re.Rune0[:0])
+ if err != nil {
+ return nil, err
+ }
+ if r != nil {
+ re.Rune = r
+ t = rest
+ p.push(re)
+ break BigSwitch
+ }
+ }
+
+ // Perl character class escape.
+ if r, rest := p.parsePerlClassEscape(t, re.Rune0[:0]); r != nil {
+ re.Rune = r
+ t = rest
+ p.push(re)
+ break BigSwitch
+ }
+ p.reuse(re)
+
+ // Ordinary single-character escape.
+ if c, t, err = p.parseEscape(t); err != nil {
+ return nil, err
+ }
+ p.literal(c)
+ }
+ lastRepeat = repeat
+ }
+
+ p.concat()
+ if p.swapVerticalBar() {
+ // pop vertical bar
+ p.stack = p.stack[:len(p.stack)-1]
+ }
+ p.alternate()
+
+ n := len(p.stack)
+ if n != 1 {
+ return nil, &Error{ErrMissingParen, s}
+ }
+ return p.stack[0], nil
+}
+
+// parseRepeat parses {min} (max=min) or {min,} (max=-1) or {min,max}.
+// If s is not of that form, it returns ok == false.
+// If s has the right form but the values are too big, it returns min == -1, ok == true.
+func (p *parser) parseRepeat(s string) (min, max int, rest string, ok bool) {
+ if s == "" || s[0] != '{' {
+ return
+ }
+ s = s[1:]
+ var ok1 bool
+ if min, s, ok1 = p.parseInt(s); !ok1 {
+ return
+ }
+ if s == "" {
+ return
+ }
+ if s[0] != ',' {
+ max = min
+ } else {
+ s = s[1:]
+ if s == "" {
+ return
+ }
+ if s[0] == '}' {
+ max = -1
+ } else if max, s, ok1 = p.parseInt(s); !ok1 {
+ return
+ } else if max < 0 {
+ // parseInt found too big a number
+ min = -1
+ }
+ }
+ if s == "" || s[0] != '}' {
+ return
+ }
+ rest = s[1:]
+ ok = true
+ return
+}
+
+// parsePerlFlags parses a Perl flag setting or non-capturing group or both,
+// like (?i) or (?: or (?i:. It removes the prefix from s and updates the parse state.
+// The caller must have ensured that s begins with "(?".
+func (p *parser) parsePerlFlags(s string) (rest string, err os.Error) {
+ t := s
+
+ // Check for named captures, first introduced in Python's regexp library.
+ // As usual, there are three slightly different syntaxes:
+ //
+ // (?P<name>expr) the original, introduced by Python
+ // (?<name>expr) the .NET alteration, adopted by Perl 5.10
+ // (?'name'expr) another .NET alteration, adopted by Perl 5.10
+ //
+ // Perl 5.10 gave in and implemented the Python version too,
+ // but they claim that the last two are the preferred forms.
+ // PCRE and languages based on it (specifically, PHP and Ruby)
+ // support all three as well. EcmaScript 4 uses only the Python form.
+ //
+ // In both the open source world (via Code Search) and the
+ // Google source tree, (?P<expr>name) is the dominant form,
+ // so that's the one we implement. One is enough.
+ if len(t) > 4 && t[2] == 'P' && t[3] == '<' {
+ // Pull out name.
+ end := strings.IndexRune(t, '>')
+ if end < 0 {
+ if err = checkUTF8(t); err != nil {
+ return "", err
+ }
+ return "", &Error{ErrInvalidNamedCapture, s}
+ }
+
+ capture := t[:end+1] // "(?P<name>"
+ name := t[4:end] // "name"
+ if err = checkUTF8(name); err != nil {
+ return "", err
+ }
+ if !isValidCaptureName(name) {
+ return "", &Error{ErrInvalidNamedCapture, capture}
+ }
+
+ // Like ordinary capture, but named.
+ p.numCap++
+ re := p.op(opLeftParen)
+ re.Cap = p.numCap
+ re.Name = name
+ return t[end+1:], nil
+ }
+
+ // Non-capturing group. Might also twiddle Perl flags.
+ var c int
+ t = t[2:] // skip (?
+ flags := p.flags
+ sign := +1
+ sawFlag := false
+Loop:
+ for t != "" {
+ if c, t, err = nextRune(t); err != nil {
+ return "", err
+ }
+ switch c {
+ default:
+ break Loop
+
+ // Flags.
+ case 'i':
+ flags |= FoldCase
+ sawFlag = true
+ case 'm':
+ flags &^= OneLine
+ sawFlag = true
+ case 's':
+ flags |= DotNL
+ sawFlag = true
+ case 'U':
+ flags |= NonGreedy
+ sawFlag = true
+
+ // Switch to negation.
+ case '-':
+ if sign < 0 {
+ break Loop
+ }
+ sign = -1
+ // Invert flags so that | above turn into &^ and vice versa.
+ // We'll invert flags again before using it below.
+ flags = ^flags
+ sawFlag = false
+
+ // End of flags, starting group or not.
+ case ':', ')':
+ if sign < 0 {
+ if !sawFlag {
+ break Loop
+ }
+ flags = ^flags
+ }
+ if c == ':' {
+ // Open new group
+ p.op(opLeftParen)
+ }
+ p.flags = flags
+ return t, nil
+ }
+ }
+
+ return "", &Error{ErrInvalidPerlOp, s[:len(s)-len(t)]}
+}
+
+// isValidCaptureName reports whether name
+// is a valid capture name: [A-Za-z0-9_]+.
+// PCRE limits names to 32 bytes.
+// Python rejects names starting with digits.
+// We don't enforce either of those.
+func isValidCaptureName(name string) bool {
+ if name == "" {
+ return false
+ }
+ for _, c := range name {
+ if c != '_' && !isalnum(c) {
+ return false
+ }
+ }
+ return true
+}
+
+// parseInt parses a decimal integer.
+func (p *parser) parseInt(s string) (n int, rest string, ok bool) {
+ if s == "" || s[0] < '0' || '9' < s[0] {
+ return
+ }
+ // Disallow leading zeros.
+ if len(s) >= 2 && s[0] == '0' && '0' <= s[1] && s[1] <= '9' {
+ return
+ }
+ t := s
+ for s != "" && '0' <= s[0] && s[0] <= '9' {
+ s = s[1:]
+ }
+ rest = s
+ ok = true
+ // Have digits, compute value.
+ t = t[:len(t)-len(s)]
+ for i := 0; i < len(t); i++ {
+ // Avoid overflow.
+ if n >= 1e8 {
+ n = -1
+ break
+ }
+ n = n*10 + int(t[i]) - '0'
+ }
+ return
+}
+
+// can this be represented as a character class?
+// single-rune literal string, char class, ., and .|\n.
+func isCharClass(re *Regexp) bool {
+ return re.Op == OpLiteral && len(re.Rune) == 1 ||
+ re.Op == OpCharClass ||
+ re.Op == OpAnyCharNotNL ||
+ re.Op == OpAnyChar
+}
+
+// does re match r?
+func matchRune(re *Regexp, r int) bool {
+ switch re.Op {
+ case OpLiteral:
+ return len(re.Rune) == 1 && re.Rune[0] == r
+ case OpCharClass:
+ for i := 0; i < len(re.Rune); i += 2 {
+ if re.Rune[i] <= r && r <= re.Rune[i+1] {
+ return true
+ }
+ }
+ return false
+ case OpAnyCharNotNL:
+ return r != '\n'
+ case OpAnyChar:
+ return true
+ }
+ return false
+}
+
+// parseVerticalBar handles a | in the input.
+func (p *parser) parseVerticalBar() os.Error {
+ p.concat()
+
+ // The concatenation we just parsed is on top of the stack.
+ // If it sits above an opVerticalBar, swap it below
+ // (things below an opVerticalBar become an alternation).
+ // Otherwise, push a new vertical bar.
+ if !p.swapVerticalBar() {
+ p.op(opVerticalBar)
+ }
+
+ return nil
+}
+
+// mergeCharClass makes dst = dst|src.
+// The caller must ensure that dst.Op >= src.Op,
+// to reduce the amount of copying.
+func mergeCharClass(dst, src *Regexp) {
+ switch dst.Op {
+ case OpAnyChar:
+ // src doesn't add anything.
+ case OpAnyCharNotNL:
+ // src might add \n
+ if matchRune(src, '\n') {
+ dst.Op = OpAnyChar
+ }
+ case OpCharClass:
+ // src is simpler, so either literal or char class
+ if src.Op == OpLiteral {
+ dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
+ } else {
+ dst.Rune = appendClass(dst.Rune, src.Rune)
+ }
+ case OpLiteral:
+ // both literal
+ if src.Rune[0] == dst.Rune[0] && src.Flags == dst.Flags {
+ break
+ }
+ dst.Op = OpCharClass
+ dst.Rune = appendLiteral(dst.Rune[:0], dst.Rune[0], dst.Flags)
+ dst.Rune = appendLiteral(dst.Rune, src.Rune[0], src.Flags)
+ }
+}
+
+// If the top of the stack is an element followed by an opVerticalBar
+// swapVerticalBar swaps the two and returns true.
+// Otherwise it returns false.
+func (p *parser) swapVerticalBar() bool {
+ // If above and below vertical bar are literal or char class,
+ // can merge into a single char class.
+ n := len(p.stack)
+ if n >= 3 && p.stack[n-2].Op == opVerticalBar && isCharClass(p.stack[n-1]) && isCharClass(p.stack[n-3]) {
+ re1 := p.stack[n-1]
+ re3 := p.stack[n-3]
+ // Make re3 the more complex of the two.
+ if re1.Op > re3.Op {
+ re1, re3 = re3, re1
+ p.stack[n-3] = re3
+ }
+ mergeCharClass(re3, re1)
+ p.reuse(re1)
+ p.stack = p.stack[:n-1]
+ return true
+ }
+
+ if n >= 2 {
+ re1 := p.stack[n-1]
+ re2 := p.stack[n-2]
+ if re2.Op == opVerticalBar {
+ if n >= 3 {
+ // Now out of reach.
+ // Clean opportunistically.
+ cleanAlt(p.stack[n-3])
+ }
+ p.stack[n-2] = re1
+ p.stack[n-1] = re2
+ return true
+ }
+ }
+ return false
+}
+
+// parseRightParen handles a ) in the input.
+func (p *parser) parseRightParen() os.Error {
+ p.concat()
+ if p.swapVerticalBar() {
+ // pop vertical bar
+ p.stack = p.stack[:len(p.stack)-1]
+ }
+ p.alternate()
+
+ n := len(p.stack)
+ if n < 2 {
+ return &Error{ErrInternalError, ""}
+ }
+ re1 := p.stack[n-1]
+ re2 := p.stack[n-2]
+ p.stack = p.stack[:n-2]
+ if re2.Op != opLeftParen {
+ return &Error{ErrMissingParen, p.wholeRegexp}
+ }
+ // Restore flags at time of paren.
+ p.flags = re2.Flags
+ if re2.Cap == 0 {
+ // Just for grouping.
+ p.push(re1)
+ } else {
+ re2.Op = OpCapture
+ re2.Sub = re2.Sub0[:1]
+ re2.Sub[0] = re1
+ p.push(re2)
+ }
+ return nil
+}
+
+// parseEscape parses an escape sequence at the beginning of s
+// and returns the rune.
+func (p *parser) parseEscape(s string) (r int, rest string, err os.Error) {
+ t := s[1:]
+ if t == "" {
+ return 0, "", &Error{ErrTrailingBackslash, ""}
+ }
+ c, t, err := nextRune(t)
+ if err != nil {
+ return 0, "", err
+ }
+
+Switch:
+ switch c {
+ default:
+ if c < utf8.RuneSelf && !isalnum(c) {
+ // Escaped non-word characters are always themselves.
+ // PCRE is not quite so rigorous: it accepts things like
+ // \q, but we don't. We once rejected \_, but too many
+ // programs and people insist on using it, so allow \_.
+ return c, t, nil
+ }
+
+ // Octal escapes.
+ case '1', '2', '3', '4', '5', '6', '7':
+ // Single non-zero digit is a backreference; not supported
+ if t == "" || t[0] < '0' || t[0] > '7' {
+ break
+ }
+ fallthrough
+ case '0':
+ // Consume up to three octal digits; already have one.
+ r = c - '0'
+ for i := 1; i < 3; i++ {
+ if t == "" || t[0] < '0' || t[0] > '7' {
+ break
+ }
+ r = r*8 + int(t[0]) - '0'
+ t = t[1:]
+ }
+ return r, t, nil
+
+ // Hexadecimal escapes.
+ case 'x':
+ if t == "" {
+ break
+ }
+ if c, t, err = nextRune(t); err != nil {
+ return 0, "", err
+ }
+ if c == '{' {
+ // Any number of digits in braces.
+ // Perl accepts any text at all; it ignores all text
+ // after the first non-hex digit. We require only hex digits,
+ // and at least one.
+ nhex := 0
+ r = 0
+ for {
+ if t == "" {
+ break Switch
+ }
+ if c, t, err = nextRune(t); err != nil {
+ return 0, "", err
+ }
+ if c == '}' {
+ break
+ }
+ v := unhex(c)
+ if v < 0 {
+ break Switch
+ }
+ r = r*16 + v
+ if r > unicode.MaxRune {
+ break Switch
+ }
+ nhex++
+ }
+ if nhex == 0 {
+ break Switch
+ }
+ return r, t, nil
+ }
+
+ // Easy case: two hex digits.
+ x := unhex(c)
+ if c, t, err = nextRune(t); err != nil {
+ return 0, "", err
+ }
+ y := unhex(c)
+ if x < 0 || y < 0 {
+ break
+ }
+ return x*16 + y, t, nil
+
+ // C escapes. There is no case 'b', to avoid misparsing
+ // the Perl word-boundary \b as the C backspace \b
+ // when in POSIX mode. In Perl, /\b/ means word-boundary
+ // but /[\b]/ means backspace. We don't support that.
+ // If you want a backspace, embed a literal backspace
+ // character or use \x08.
+ case 'a':
+ return '\a', t, err
+ case 'f':
+ return '\f', t, err
+ case 'n':
+ return '\n', t, err
+ case 'r':
+ return '\r', t, err
+ case 't':
+ return '\t', t, err
+ case 'v':
+ return '\v', t, err
+ }
+ return 0, "", &Error{ErrInvalidEscape, s[:len(s)-len(t)]}
+}
+
+// parseClassChar parses a character class character at the beginning of s
+// and returns it.
+func (p *parser) parseClassChar(s, wholeClass string) (r int, rest string, err os.Error) {
+ if s == "" {
+ return 0, "", &Error{Code: ErrMissingBracket, Expr: wholeClass}
+ }
+
+ // Allow regular escape sequences even though
+ // many need not be escaped in this context.
+ if s[0] == '\\' {
+ return p.parseEscape(s)
+ }
+
+ return nextRune(s)
+}
+
+type charGroup struct {
+ sign int
+ class []int
+}
+
+// parsePerlClassEscape parses a leading Perl character class escape like \d
+// from the beginning of s. If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parsePerlClassEscape(s string, r []int) (out []int, rest string) {
+ if p.flags&PerlX == 0 || len(s) < 2 || s[0] != '\\' {
+ return
+ }
+ g := perlGroup[s[0:2]]
+ if g.sign == 0 {
+ return
+ }
+ return p.appendGroup(r, g), s[2:]
+}
+
+// parseNamedClass parses a leading POSIX named character class like [:alnum:]
+// from the beginning of s. If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parseNamedClass(s string, r []int) (out []int, rest string, err os.Error) {
+ if len(s) < 2 || s[0] != '[' || s[1] != ':' {
+ return
+ }
+
+ i := strings.Index(s[2:], ":]")
+ if i < 0 {
+ return
+ }
+ i += 2
+ name, s := s[0:i+2], s[i+2:]
+ g := posixGroup[name]
+ if g.sign == 0 {
+ return nil, "", &Error{ErrInvalidCharRange, name}
+ }
+ return p.appendGroup(r, g), s, nil
+}
+
+func (p *parser) appendGroup(r []int, g charGroup) []int {
+ if p.flags&FoldCase == 0 {
+ if g.sign < 0 {
+ r = appendNegatedClass(r, g.class)
+ } else {
+ r = appendClass(r, g.class)
+ }
+ } else {
+ tmp := p.tmpClass[:0]
+ tmp = appendFoldedClass(tmp, g.class)
+ p.tmpClass = tmp
+ tmp = cleanClass(&p.tmpClass)
+ if g.sign < 0 {
+ r = appendNegatedClass(r, tmp)
+ } else {
+ r = appendClass(r, tmp)
+ }
+ }
+ return r
+}
+
+var anyTable = &unicode.RangeTable{
+ []unicode.Range16{{0, 1<<16 - 1, 1}},
+ []unicode.Range32{{1 << 16, unicode.MaxRune, 1}},
+}
+
+// unicodeTable returns the unicode.RangeTable identified by name
+// and the table of additional fold-equivalent code points.
+func unicodeTable(name string) (*unicode.RangeTable, *unicode.RangeTable) {
+ // Special case: "Any" means any.
+ if name == "Any" {
+ return anyTable, anyTable
+ }
+ if t := unicode.Categories[name]; t != nil {
+ return t, unicode.FoldCategory[name]
+ }
+ if t := unicode.Scripts[name]; t != nil {
+ return t, unicode.FoldScript[name]
+ }
+ return nil, nil
+}
+
+// parseUnicodeClass parses a leading Unicode character class like \p{Han}
+// from the beginning of s. If one is present, it appends the characters to r
+// and returns the new slice r and the remainder of the string.
+func (p *parser) parseUnicodeClass(s string, r []int) (out []int, rest string, err os.Error) {
+ if p.flags&UnicodeGroups == 0 || len(s) < 2 || s[0] != '\\' || s[1] != 'p' && s[1] != 'P' {
+ return
+ }
+
+ // Committed to parse or return error.
+ sign := +1
+ if s[1] == 'P' {
+ sign = -1
+ }
+ t := s[2:]
+ c, t, err := nextRune(t)
+ if err != nil {
+ return
+ }
+ var seq, name string
+ if c != '{' {
+ // Single-letter name.
+ seq = s[:len(s)-len(t)]
+ name = seq[2:]
+ } else {
+ // Name is in braces.
+ end := strings.IndexRune(s, '}')
+ if end < 0 {
+ if err = checkUTF8(s); err != nil {
+ return
+ }
+ return nil, "", &Error{ErrInvalidCharRange, s}
+ }
+ seq, t = s[:end+1], s[end+1:]
+ name = s[3:end]
+ if err = checkUTF8(name); err != nil {
+ return
+ }
+ }
+
+ // Group can have leading negation too. \p{^Han} == \P{Han}, \P{^Han} == \p{Han}.
+ if name != "" && name[0] == '^' {
+ sign = -sign
+ name = name[1:]
+ }
+
+ tab, fold := unicodeTable(name)
+ if tab == nil {
+ return nil, "", &Error{ErrInvalidCharRange, seq}
+ }
+
+ if p.flags&FoldCase == 0 || fold == nil {
+ if sign > 0 {
+ r = appendTable(r, tab)
+ } else {
+ r = appendNegatedTable(r, tab)
+ }
+ } else {
+ // Merge and clean tab and fold in a temporary buffer.
+ // This is necessary for the negative case and just tidy
+ // for the positive case.
+ tmp := p.tmpClass[:0]
+ tmp = appendTable(tmp, tab)
+ tmp = appendTable(tmp, fold)
+ p.tmpClass = tmp
+ tmp = cleanClass(&p.tmpClass)
+ if sign > 0 {
+ r = appendClass(r, tmp)
+ } else {
+ r = appendNegatedClass(r, tmp)
+ }
+ }
+ return r, t, nil
+}
+
+// parseClass parses a character class at the beginning of s
+// and pushes it onto the parse stack.
+func (p *parser) parseClass(s string) (rest string, err os.Error) {
+ t := s[1:] // chop [
+ re := p.newRegexp(OpCharClass)
+ re.Flags = p.flags
+ re.Rune = re.Rune0[:0]
+
+ sign := +1
+ if t != "" && t[0] == '^' {
+ sign = -1
+ t = t[1:]
+
+ // If character class does not match \n, add it here,
+ // so that negation later will do the right thing.
+ if p.flags&ClassNL == 0 {
+ re.Rune = append(re.Rune, '\n', '\n')
+ }
+ }
+
+ class := re.Rune
+ first := true // ] and - are okay as first char in class
+ for t == "" || t[0] != ']' || first {
+ // POSIX: - is only okay unescaped as first or last in class.
+ // Perl: - is okay anywhere.
+ if t != "" && t[0] == '-' && p.flags&PerlX == 0 && !first && (len(t) == 1 || t[1] != ']') {
+ _, size := utf8.DecodeRuneInString(t[1:])
+ return "", &Error{Code: ErrInvalidCharRange, Expr: t[:1+size]}
+ }
+ first = false
+
+ // Look for POSIX [:alnum:] etc.
+ if len(t) > 2 && t[0] == '[' && t[1] == ':' {
+ nclass, nt, err := p.parseNamedClass(t, class)
+ if err != nil {
+ return "", err
+ }
+ if nclass != nil {
+ class, t = nclass, nt
+ continue
+ }
+ }
+
+ // Look for Unicode character group like \p{Han}.
+ nclass, nt, err := p.parseUnicodeClass(t, class)
+ if err != nil {
+ return "", err
+ }
+ if nclass != nil {
+ class, t = nclass, nt
+ continue
+ }
+
+ // Look for Perl character class symbols (extension).
+ if nclass, nt := p.parsePerlClassEscape(t, class); nclass != nil {
+ class, t = nclass, nt
+ continue
+ }
+
+ // Single character or simple range.
+ rng := t
+ var lo, hi int
+ if lo, t, err = p.parseClassChar(t, s); err != nil {
+ return "", err
+ }
+ hi = lo
+ // [a-] means (a|-) so check for final ].
+ if len(t) >= 2 && t[0] == '-' && t[1] != ']' {
+ t = t[1:]
+ if hi, t, err = p.parseClassChar(t, s); err != nil {
+ return "", err
+ }
+ if hi < lo {
+ rng = rng[:len(rng)-len(t)]
+ return "", &Error{Code: ErrInvalidCharRange, Expr: rng}
+ }
+ }
+ if p.flags&FoldCase == 0 {
+ class = AppendRange(class, lo, hi)
+ } else {
+ class = appendFoldedRange(class, lo, hi)
+ }
+ }
+ t = t[1:] // chop ]
+
+ // Use &re.Rune instead of &class to avoid allocation.
+ re.Rune = class
+ class = cleanClass(&re.Rune)
+ if sign < 0 {
+ class = negateClass(class)
+ }
+ re.Rune = class
+ p.push(re)
+ return t, nil
+}
+
+// cleanClass sorts the ranges (pairs of elements of r),
+// merges them, and eliminates duplicates.
+func cleanClass(rp *[]int) []int {
+
+ // Sort by lo increasing, hi decreasing to break ties.
+ sort.Sort(ranges{rp})
+
+ r := *rp
+ if len(r) < 2 {
+ return r
+ }
+
+ // Merge abutting, overlapping.
+ w := 2 // write index
+ for i := 2; i < len(r); i += 2 {
+ lo, hi := r[i], r[i+1]
+ if lo <= r[w-1]+1 {
+ // merge with previous range
+ if hi > r[w-1] {
+ r[w-1] = hi
+ }
+ continue
+ }
+ // new disjoint range
+ r[w] = lo
+ r[w+1] = hi
+ w += 2
+ }
+
+ return r[:w]
+}
+
+// appendLiteral returns the result of appending the literal x to the class r.
+func appendLiteral(r []int, x int, flags Flags) []int {
+ if flags&FoldCase != 0 {
+ return appendFoldedRange(r, x, x)
+ }
+ return AppendRange(r, x, x)
+}
+
+// AppendRange returns the result of appending the range lo-hi to the class r.
+func AppendRange(r []int, lo, hi int) []int {
+ // Expand last range or next to last range if it overlaps or abuts.
+ // Checking two ranges helps when appending case-folded
+ // alphabets, so that one range can be expanding A-Z and the
+ // other expanding a-z.
+ n := len(r)
+ for i := 2; i <= 4; i += 2 { // twice, using i=2, i=4
+ if n >= i {
+ rlo, rhi := r[n-i], r[n-i+1]
+ if lo <= rhi+1 && rlo <= hi+1 {
+ if lo < rlo {
+ r[n-i] = lo
+ }
+ if hi > rhi {
+ r[n-i+1] = hi
+ }
+ return r
+ }
+ }
+ }
+
+ return append(r, lo, hi)
+}
+
+const (
+ // minimum and maximum runes involved in folding.
+ // checked during test.
+ MinFold = 0x0041
+ MaxFold = 0x1044f
+)
+
+// appendFoldedRange returns the result of appending the range lo-hi
+// and its case folding-equivalent runes to the class r.
+func appendFoldedRange(r []int, lo, hi int) []int {
+ // Optimizations.
+ if lo <= MinFold && hi >= MaxFold {
+ // Range is full: folding can't add more.
+ return AppendRange(r, lo, hi)
+ }
+ if hi < MinFold || lo > MaxFold {
+ // Range is outside folding possibilities.
+ return AppendRange(r, lo, hi)
+ }
+ if lo < MinFold {
+ // [lo, MinFold-1] needs no folding.
+ r = AppendRange(r, lo, MinFold-1)
+ lo = MinFold
+ }
+ if hi > MaxFold {
+ // [MaxFold+1, hi] needs no folding.
+ r = AppendRange(r, MaxFold+1, hi)
+ hi = MaxFold
+ }
+
+ // Brute force. Depend on AppendRange to coalesce ranges on the fly.
+ for c := lo; c <= hi; c++ {
+ r = AppendRange(r, c, c)
+ f := unicode.SimpleFold(c)
+ for f != c {
+ r = AppendRange(r, f, f)
+ f = unicode.SimpleFold(f)
+ }
+ }
+ return r
+}
+
+// appendClass returns the result of appending the class x to the class r.
+// It assume x is clean.
+func appendClass(r []int, x []int) []int {
+ for i := 0; i < len(x); i += 2 {
+ r = AppendRange(r, x[i], x[i+1])
+ }
+ return r
+}
+
+// appendFolded returns the result of appending the case folding of the class x to the class r.
+func appendFoldedClass(r []int, x []int) []int {
+ for i := 0; i < len(x); i += 2 {
+ r = appendFoldedRange(r, x[i], x[i+1])
+ }
+ return r
+}
+
+// appendNegatedClass returns the result of appending the negation of the class x to the class r.
+// It assumes x is clean.
+func appendNegatedClass(r []int, x []int) []int {
+ nextLo := 0
+ for i := 0; i < len(x); i += 2 {
+ lo, hi := x[i], x[i+1]
+ if nextLo <= lo-1 {
+ r = AppendRange(r, nextLo, lo-1)
+ }
+ nextLo = hi + 1
+ }
+ if nextLo <= unicode.MaxRune {
+ r = AppendRange(r, nextLo, unicode.MaxRune)
+ }
+ return r
+}
+
+// appendTable returns the result of appending x to the class r.
+func appendTable(r []int, x *unicode.RangeTable) []int {
+ for _, xr := range x.R16 {
+ lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
+ if stride == 1 {
+ r = AppendRange(r, lo, hi)
+ continue
+ }
+ for c := lo; c <= hi; c += stride {
+ r = AppendRange(r, c, c)
+ }
+ }
+ for _, xr := range x.R32 {
+ lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
+ if stride == 1 {
+ r = AppendRange(r, lo, hi)
+ continue
+ }
+ for c := lo; c <= hi; c += stride {
+ r = AppendRange(r, c, c)
+ }
+ }
+ return r
+}
+
+// appendNegatedTable returns the result of appending the negation of x to the class r.
+func appendNegatedTable(r []int, x *unicode.RangeTable) []int {
+ nextLo := 0 // lo end of next class to add
+ for _, xr := range x.R16 {
+ lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
+ if stride == 1 {
+ if nextLo <= lo-1 {
+ r = AppendRange(r, nextLo, lo-1)
+ }
+ nextLo = hi + 1
+ continue
+ }
+ for c := lo; c <= hi; c += stride {
+ if nextLo <= c-1 {
+ r = AppendRange(r, nextLo, c-1)
+ }
+ nextLo = c + 1
+ }
+ }
+ for _, xr := range x.R32 {
+ lo, hi, stride := int(xr.Lo), int(xr.Hi), int(xr.Stride)
+ if stride == 1 {
+ if nextLo <= lo-1 {
+ r = AppendRange(r, nextLo, lo-1)
+ }
+ nextLo = hi + 1
+ continue
+ }
+ for c := lo; c <= hi; c += stride {
+ if nextLo <= c-1 {
+ r = AppendRange(r, nextLo, c-1)
+ }
+ nextLo = c + 1
+ }
+ }
+ if nextLo <= unicode.MaxRune {
+ r = AppendRange(r, nextLo, unicode.MaxRune)
+ }
+ return r
+}
+
+// negateClass overwrites r and returns r's negation.
+// It assumes the class r is already clean.
+func negateClass(r []int) []int {
+ nextLo := 0 // lo end of next class to add
+ w := 0 // write index
+ for i := 0; i < len(r); i += 2 {
+ lo, hi := r[i], r[i+1]
+ if nextLo <= lo-1 {
+ r[w] = nextLo
+ r[w+1] = lo - 1
+ w += 2
+ }
+ nextLo = hi + 1
+ }
+ r = r[:w]
+ if nextLo <= unicode.MaxRune {
+ // It's possible for the negation to have one more
+ // range - this one - than the original class, so use append.
+ r = append(r, nextLo, unicode.MaxRune)
+ }
+ return r
+}
+
+// ranges implements sort.Interface on a []rune.
+// The choice of receiver type definition is strange
+// but avoids an allocation since we already have
+// a *[]int.
+type ranges struct {
+ p *[]int
+}
+
+func (ra ranges) Less(i, j int) bool {
+ p := *ra.p
+ i *= 2
+ j *= 2
+ return p[i] < p[j] || p[i] == p[j] && p[i+1] > p[j+1]
+}
+
+func (ra ranges) Len() int {
+ return len(*ra.p) / 2
+}
+
+func (ra ranges) Swap(i, j int) {
+ p := *ra.p
+ i *= 2
+ j *= 2
+ p[i], p[i+1], p[j], p[j+1] = p[j], p[j+1], p[i], p[i+1]
+}
+
+func checkUTF8(s string) os.Error {
+ for s != "" {
+ rune, size := utf8.DecodeRuneInString(s)
+ if rune == utf8.RuneError && size == 1 {
+ return &Error{Code: ErrInvalidUTF8, Expr: s}
+ }
+ s = s[size:]
+ }
+ return nil
+}
+
+func nextRune(s string) (c int, t string, err os.Error) {
+ c, size := utf8.DecodeRuneInString(s)
+ if c == utf8.RuneError && size == 1 {
+ return 0, "", &Error{Code: ErrInvalidUTF8, Expr: s}
+ }
+ return c, s[size:], nil
+}
+
+func isalnum(c int) bool {
+ return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
+}
+
+func unhex(c int) int {
+ if '0' <= c && c <= '9' {
+ return c - '0'
+ }
+ if 'a' <= c && c <= 'f' {
+ return c - 'a' + 10
+ }
+ if 'A' <= c && c <= 'F' {
+ return c - 'A' + 10
+ }
+ return -1
+}
diff --git a/libgo/go/regexp/syntax/parse_test.go b/libgo/go/regexp/syntax/parse_test.go
new file mode 100644
index 00000000000..5d9085bfb1f
--- /dev/null
+++ b/libgo/go/regexp/syntax/parse_test.go
@@ -0,0 +1,552 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syntax_test
+
+import (
+ . "regexp/syntax"
+ "bytes"
+ "fmt"
+ "testing"
+ "unicode"
+)
+
+type parseTest struct {
+ Regexp string
+ Dump string
+}
+
+var parseTests = []parseTest{
+ // Base cases
+ {`a`, `lit{a}`},
+ {`a.`, `cat{lit{a}dot{}}`},
+ {`a.b`, `cat{lit{a}dot{}lit{b}}`},
+ {`ab`, `str{ab}`},
+ {`a.b.c`, `cat{lit{a}dot{}lit{b}dot{}lit{c}}`},
+ {`abc`, `str{abc}`},
+ {`a|^`, `alt{lit{a}bol{}}`},
+ {`a|b`, `cc{0x61-0x62}`},
+ {`(a)`, `cap{lit{a}}`},
+ {`(a)|b`, `alt{cap{lit{a}}lit{b}}`},
+ {`a*`, `star{lit{a}}`},
+ {`a+`, `plus{lit{a}}`},
+ {`a?`, `que{lit{a}}`},
+ {`a{2}`, `rep{2,2 lit{a}}`},
+ {`a{2,3}`, `rep{2,3 lit{a}}`},
+ {`a{2,}`, `rep{2,-1 lit{a}}`},
+ {`a*?`, `nstar{lit{a}}`},
+ {`a+?`, `nplus{lit{a}}`},
+ {`a??`, `nque{lit{a}}`},
+ {`a{2}?`, `nrep{2,2 lit{a}}`},
+ {`a{2,3}?`, `nrep{2,3 lit{a}}`},
+ {`a{2,}?`, `nrep{2,-1 lit{a}}`},
+ // Malformed { } are treated as literals.
+ {`x{1001`, `str{x{1001}`},
+ {`x{9876543210`, `str{x{9876543210}`},
+ {`x{9876543210,`, `str{x{9876543210,}`},
+ {`x{2,1`, `str{x{2,1}`},
+ {`x{1,9876543210`, `str{x{1,9876543210}`},
+ {``, `emp{}`},
+ {`|`, `emp{}`}, // alt{emp{}emp{}} but got factored
+ {`|x|`, `alt{emp{}lit{x}emp{}}`},
+ {`.`, `dot{}`},
+ {`^`, `bol{}`},
+ {`$`, `eol{}`},
+ {`\|`, `lit{|}`},
+ {`\(`, `lit{(}`},
+ {`\)`, `lit{)}`},
+ {`\*`, `lit{*}`},
+ {`\+`, `lit{+}`},
+ {`\?`, `lit{?}`},
+ {`{`, `lit{{}`},
+ {`}`, `lit{}}`},
+ {`\.`, `lit{.}`},
+ {`\^`, `lit{^}`},
+ {`\$`, `lit{$}`},
+ {`\\`, `lit{\}`},
+ {`[ace]`, `cc{0x61 0x63 0x65}`},
+ {`[abc]`, `cc{0x61-0x63}`},
+ {`[a-z]`, `cc{0x61-0x7a}`},
+ {`[a]`, `lit{a}`},
+ {`\-`, `lit{-}`},
+ {`-`, `lit{-}`},
+ {`\_`, `lit{_}`},
+ {`abc`, `str{abc}`},
+ {`abc|def`, `alt{str{abc}str{def}}`},
+ {`abc|def|ghi`, `alt{str{abc}str{def}str{ghi}}`},
+
+ // Posix and Perl extensions
+ {`[[:lower:]]`, `cc{0x61-0x7a}`},
+ {`[a-z]`, `cc{0x61-0x7a}`},
+ {`[^[:lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
+ {`[[:^lower:]]`, `cc{0x0-0x60 0x7b-0x10ffff}`},
+ {`(?i)[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+ {`(?i)[a-z]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+ {`(?i)[^[:lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+ {`(?i)[[:^lower:]]`, `cc{0x0-0x40 0x5b-0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+ {`\d`, `cc{0x30-0x39}`},
+ {`\D`, `cc{0x0-0x2f 0x3a-0x10ffff}`},
+ {`\s`, `cc{0x9-0xa 0xc-0xd 0x20}`},
+ {`\S`, `cc{0x0-0x8 0xb 0xe-0x1f 0x21-0x10ffff}`},
+ {`\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a}`},
+ {`\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x10ffff}`},
+ {`(?i)\w`, `cc{0x30-0x39 0x41-0x5a 0x5f 0x61-0x7a 0x17f 0x212a}`},
+ {`(?i)\W`, `cc{0x0-0x2f 0x3a-0x40 0x5b-0x5e 0x60 0x7b-0x17e 0x180-0x2129 0x212b-0x10ffff}`},
+ {`[^\\]`, `cc{0x0-0x5b 0x5d-0x10ffff}`},
+ // { `\C`, `byte{}` }, // probably never
+
+ // Unicode, negatives, and a double negative.
+ {`\p{Braille}`, `cc{0x2800-0x28ff}`},
+ {`\P{Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+ {`\p{^Braille}`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+ {`\P{^Braille}`, `cc{0x2800-0x28ff}`},
+ {`\pZ`, `cc{0x20 0xa0 0x1680 0x180e 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
+ {`[\p{Braille}]`, `cc{0x2800-0x28ff}`},
+ {`[\P{Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+ {`[\p{^Braille}]`, `cc{0x0-0x27ff 0x2900-0x10ffff}`},
+ {`[\P{^Braille}]`, `cc{0x2800-0x28ff}`},
+ {`[\pZ]`, `cc{0x20 0xa0 0x1680 0x180e 0x2000-0x200a 0x2028-0x2029 0x202f 0x205f 0x3000}`},
+ {`\p{Lu}`, mkCharClass(unicode.IsUpper)},
+ {`[\p{Lu}]`, mkCharClass(unicode.IsUpper)},
+ {`(?i)[\p{Lu}]`, mkCharClass(isUpperFold)},
+ {`\p{Any}`, `dot{}`},
+ {`\p{^Any}`, `cc{}`},
+
+ // Hex, octal.
+ {`[\012-\234]\141`, `cat{cc{0xa-0x9c}lit{a}}`},
+ {`[\x{41}-\x7a]\x61`, `cat{cc{0x41-0x7a}lit{a}}`},
+
+ // More interesting regular expressions.
+ {`a{,2}`, `str{a{,2}}`},
+ {`\.\^\$\\`, `str{.^$\}`},
+ {`[a-zABC]`, `cc{0x41-0x43 0x61-0x7a}`},
+ {`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
+ {`[α-ε☺]`, `cc{0x3b1-0x3b5 0x263a}`}, // utf-8
+ {`a*{`, `cat{star{lit{a}}lit{{}}`},
+
+ // Test precedences
+ {`(?:ab)*`, `star{str{ab}}`},
+ {`(ab)*`, `star{cap{str{ab}}}`},
+ {`ab|cd`, `alt{str{ab}str{cd}}`},
+ {`a(b|c)d`, `cat{lit{a}cap{cc{0x62-0x63}}lit{d}}`},
+
+ // Test flattening.
+ {`(?:a)`, `lit{a}`},
+ {`(?:ab)(?:cd)`, `str{abcd}`},
+ {`(?:a+b+)(?:c+d+)`, `cat{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
+ {`(?:a+|b+)|(?:c+|d+)`, `alt{plus{lit{a}}plus{lit{b}}plus{lit{c}}plus{lit{d}}}`},
+ {`(?:a|b)|(?:c|d)`, `cc{0x61-0x64}`},
+ {`a|.`, `dot{}`},
+ {`.|a`, `dot{}`},
+ {`(?:[abc]|A|Z|hello|world)`, `alt{cc{0x41 0x5a 0x61-0x63}str{hello}str{world}}`},
+ {`(?:[abc]|A|Z)`, `cc{0x41 0x5a 0x61-0x63}`},
+
+ // Test Perl quoted literals
+ {`\Q+|*?{[\E`, `str{+|*?{[}`},
+ {`\Q+\E+`, `plus{lit{+}}`},
+ {`\Q\\E`, `lit{\}`},
+ {`\Q\\\E`, `str{\\}`},
+
+ // Test Perl \A and \z
+ {`(?m)^`, `bol{}`},
+ {`(?m)$`, `eol{}`},
+ {`(?-m)^`, `bot{}`},
+ {`(?-m)$`, `eot{}`},
+ {`(?m)\A`, `bot{}`},
+ {`(?m)\z`, `eot{\z}`},
+ {`(?-m)\A`, `bot{}`},
+ {`(?-m)\z`, `eot{\z}`},
+
+ // Test named captures
+ {`(?P<name>a)`, `cap{name:lit{a}}`},
+
+ // Case-folded literals
+ {`[Aa]`, `litfold{A}`},
+ {`[\x{100}\x{101}]`, `litfold{Ä€}`},
+ {`[Δδ]`, `litfold{Δ}`},
+
+ // Strings
+ {`abcde`, `str{abcde}`},
+ {`[Aa][Bb]cd`, `cat{strfold{AB}str{cd}}`},
+
+ // Factoring.
+ {`abc|abd|aef|bcx|bcy`, `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}cat{str{bc}cc{0x78-0x79}}}`},
+ {`ax+y|ax+z|ay+w`, `cat{lit{a}alt{cat{plus{lit{x}}cc{0x79-0x7a}}cat{plus{lit{y}}lit{w}}}}`},
+
+ // Bug fixes.
+ {`(?:.)`, `dot{}`},
+ {`(?:x|(?:xa))`, `cat{lit{x}alt{emp{}lit{a}}}`},
+ {`(?:.|(?:.a))`, `cat{dot{}alt{emp{}lit{a}}}`},
+ {`(?:A(?:A|a))`, `cat{lit{A}litfold{A}}`},
+ {`(?:A|a)`, `litfold{A}`},
+ {`A|(?:A|a)`, `litfold{A}`},
+ {`(?s).`, `dot{}`},
+ {`(?-s).`, `dnl{}`},
+ {`(?:(?:^).)`, `cat{bol{}dot{}}`},
+ {`(?-s)(?:(?:^).)`, `cat{bol{}dnl{}}`},
+
+ // RE2 prefix_tests
+ {`abc|abd`, `cat{str{ab}cc{0x63-0x64}}`},
+ {`a(?:b)c|abd`, `cat{str{ab}cc{0x63-0x64}}`},
+ {`abc|abd|aef|bcx|bcy`,
+ `alt{cat{lit{a}alt{cat{lit{b}cc{0x63-0x64}}str{ef}}}` +
+ `cat{str{bc}cc{0x78-0x79}}}`},
+ {`abc|x|abd`, `alt{str{abc}lit{x}str{abd}}`},
+ {`(?i)abc|ABD`, `cat{strfold{AB}cc{0x43-0x44 0x63-0x64}}`},
+ {`[ab]c|[ab]d`, `cat{cc{0x61-0x62}cc{0x63-0x64}}`},
+ {`(?:xx|yy)c|(?:xx|yy)d`,
+ `cat{alt{str{xx}str{yy}}cc{0x63-0x64}}`},
+ {`x{2}|x{2}[0-9]`,
+ `cat{rep{2,2 lit{x}}alt{emp{}cc{0x30-0x39}}}`},
+ {`x{2}y|x{2}[0-9]y`,
+ `cat{rep{2,2 lit{x}}alt{lit{y}cat{cc{0x30-0x39}lit{y}}}}`},
+}
+
+const testFlags = MatchNL | PerlX | UnicodeGroups
+
+func TestParseSimple(t *testing.T) {
+ testParseDump(t, parseTests, testFlags)
+}
+
+var foldcaseTests = []parseTest{
+ {`AbCdE`, `strfold{ABCDE}`},
+ {`[Aa]`, `litfold{A}`},
+ {`a`, `litfold{A}`},
+
+ // 0x17F is an old English long s (looks like an f) and folds to s.
+ // 0x212A is the Kelvin symbol and folds to k.
+ {`A[F-g]`, `cat{litfold{A}cc{0x41-0x7a 0x17f 0x212a}}`}, // [Aa][A-z...]
+ {`[[:upper:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+ {`[[:lower:]]`, `cc{0x41-0x5a 0x61-0x7a 0x17f 0x212a}`},
+}
+
+func TestParseFoldCase(t *testing.T) {
+ testParseDump(t, foldcaseTests, FoldCase)
+}
+
+var literalTests = []parseTest{
+ {"(|)^$.[*+?]{5,10},\\", "str{(|)^$.[*+?]{5,10},\\}"},
+}
+
+func TestParseLiteral(t *testing.T) {
+ testParseDump(t, literalTests, Literal)
+}
+
+var matchnlTests = []parseTest{
+ {`.`, `dot{}`},
+ {"\n", "lit{\n}"},
+ {`[^a]`, `cc{0x0-0x60 0x62-0x10ffff}`},
+ {`[a\n]`, `cc{0xa 0x61}`},
+}
+
+func TestParseMatchNL(t *testing.T) {
+ testParseDump(t, matchnlTests, MatchNL)
+}
+
+var nomatchnlTests = []parseTest{
+ {`.`, `dnl{}`},
+ {"\n", "lit{\n}"},
+ {`[^a]`, `cc{0x0-0x9 0xb-0x60 0x62-0x10ffff}`},
+ {`[a\n]`, `cc{0xa 0x61}`},
+}
+
+func TestParseNoMatchNL(t *testing.T) {
+ testParseDump(t, nomatchnlTests, 0)
+}
+
+// Test Parse -> Dump.
+func testParseDump(t *testing.T, tests []parseTest, flags Flags) {
+ for _, tt := range tests {
+ re, err := Parse(tt.Regexp, flags)
+ if err != nil {
+ t.Errorf("Parse(%#q): %v", tt.Regexp, err)
+ continue
+ }
+ d := dump(re)
+ if d != tt.Dump {
+ t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
+ }
+ }
+}
+
+// dump prints a string representation of the regexp showing
+// the structure explicitly.
+func dump(re *Regexp) string {
+ var b bytes.Buffer
+ dumpRegexp(&b, re)
+ return b.String()
+}
+
+var opNames = []string{
+ OpNoMatch: "no",
+ OpEmptyMatch: "emp",
+ OpLiteral: "lit",
+ OpCharClass: "cc",
+ OpAnyCharNotNL: "dnl",
+ OpAnyChar: "dot",
+ OpBeginLine: "bol",
+ OpEndLine: "eol",
+ OpBeginText: "bot",
+ OpEndText: "eot",
+ OpWordBoundary: "wb",
+ OpNoWordBoundary: "nwb",
+ OpCapture: "cap",
+ OpStar: "star",
+ OpPlus: "plus",
+ OpQuest: "que",
+ OpRepeat: "rep",
+ OpConcat: "cat",
+ OpAlternate: "alt",
+}
+
+// dumpRegexp writes an encoding of the syntax tree for the regexp re to b.
+// It is used during testing to distinguish between parses that might print
+// the same using re's String method.
+func dumpRegexp(b *bytes.Buffer, re *Regexp) {
+ if int(re.Op) >= len(opNames) || opNames[re.Op] == "" {
+ fmt.Fprintf(b, "op%d", re.Op)
+ } else {
+ switch re.Op {
+ default:
+ b.WriteString(opNames[re.Op])
+ case OpStar, OpPlus, OpQuest, OpRepeat:
+ if re.Flags&NonGreedy != 0 {
+ b.WriteByte('n')
+ }
+ b.WriteString(opNames[re.Op])
+ case OpLiteral:
+ if len(re.Rune) > 1 {
+ b.WriteString("str")
+ } else {
+ b.WriteString("lit")
+ }
+ if re.Flags&FoldCase != 0 {
+ for _, r := range re.Rune {
+ if unicode.SimpleFold(r) != r {
+ b.WriteString("fold")
+ break
+ }
+ }
+ }
+ }
+ }
+ b.WriteByte('{')
+ switch re.Op {
+ case OpEndText:
+ if re.Flags&WasDollar == 0 {
+ b.WriteString(`\z`)
+ }
+ case OpLiteral:
+ for _, r := range re.Rune {
+ b.WriteRune(r)
+ }
+ case OpConcat, OpAlternate:
+ for _, sub := range re.Sub {
+ dumpRegexp(b, sub)
+ }
+ case OpStar, OpPlus, OpQuest:
+ dumpRegexp(b, re.Sub[0])
+ case OpRepeat:
+ fmt.Fprintf(b, "%d,%d ", re.Min, re.Max)
+ dumpRegexp(b, re.Sub[0])
+ case OpCapture:
+ if re.Name != "" {
+ b.WriteString(re.Name)
+ b.WriteByte(':')
+ }
+ dumpRegexp(b, re.Sub[0])
+ case OpCharClass:
+ sep := ""
+ for i := 0; i < len(re.Rune); i += 2 {
+ b.WriteString(sep)
+ sep = " "
+ lo, hi := re.Rune[i], re.Rune[i+1]
+ if lo == hi {
+ fmt.Fprintf(b, "%#x", lo)
+ } else {
+ fmt.Fprintf(b, "%#x-%#x", lo, hi)
+ }
+ }
+ }
+ b.WriteByte('}')
+}
+
+func mkCharClass(f func(int) bool) string {
+ re := &Regexp{Op: OpCharClass}
+ lo := -1
+ for i := 0; i <= unicode.MaxRune; i++ {
+ if f(i) {
+ if lo < 0 {
+ lo = i
+ }
+ } else {
+ if lo >= 0 {
+ re.Rune = append(re.Rune, lo, i-1)
+ lo = -1
+ }
+ }
+ }
+ if lo >= 0 {
+ re.Rune = append(re.Rune, lo, unicode.MaxRune)
+ }
+ return dump(re)
+}
+
+func isUpperFold(rune int) bool {
+ if unicode.IsUpper(rune) {
+ return true
+ }
+ c := unicode.SimpleFold(rune)
+ for c != rune {
+ if unicode.IsUpper(c) {
+ return true
+ }
+ c = unicode.SimpleFold(c)
+ }
+ return false
+}
+
+func TestFoldConstants(t *testing.T) {
+ last := -1
+ for i := 0; i <= unicode.MaxRune; i++ {
+ if unicode.SimpleFold(i) == i {
+ continue
+ }
+ if last == -1 && MinFold != i {
+ t.Errorf("MinFold=%#U should be %#U", MinFold, i)
+ }
+ last = i
+ }
+ if MaxFold != last {
+ t.Errorf("MaxFold=%#U should be %#U", MaxFold, last)
+ }
+}
+
+func TestAppendRangeCollapse(t *testing.T) {
+ // AppendRange should collapse each of the new ranges
+ // into the earlier ones (it looks back two ranges), so that
+ // the slice never grows very large.
+ // Note that we are not calling cleanClass.
+ var r []int
+ for i := 'A'; i <= 'Z'; i++ {
+ r = AppendRange(r, i, i)
+ r = AppendRange(r, i+'a'-'A', i+'a'-'A')
+ }
+ if string(r) != "AZaz" {
+ t.Errorf("AppendRange interlaced A-Z a-z = %s, want AZaz", string(r))
+ }
+}
+
+var invalidRegexps = []string{
+ `(`,
+ `)`,
+ `(a`,
+ `(a|b|`,
+ `(a|b`,
+ `[a-z`,
+ `([a-z)`,
+ `x{1001}`,
+ `x{9876543210}`,
+ `x{2,1}`,
+ `x{1,9876543210}`,
+ "\xff", // Invalid UTF-8
+ "[\xff]",
+ "[\\\xff]",
+ "\\\xff",
+ `(?P<name>a`,
+ `(?P<name>`,
+ `(?P<name`,
+ `(?P<x y>a)`,
+ `(?P<>a)`,
+ `[a-Z]`,
+ `(?i)[a-Z]`,
+ `a{100000}`,
+ `a{100000,}`,
+}
+
+var onlyPerl = []string{
+ `[a-b-c]`,
+ `\Qabc\E`,
+ `\Q*+?{[\E`,
+ `\Q\\E`,
+ `\Q\\\E`,
+ `\Q\\\\E`,
+ `\Q\\\\\E`,
+ `(?:a)`,
+ `(?P<name>a)`,
+}
+
+var onlyPOSIX = []string{
+ "a++",
+ "a**",
+ "a?*",
+ "a+*",
+ "a{1}*",
+ ".{1}{2}.{3}",
+}
+
+func TestParseInvalidRegexps(t *testing.T) {
+ for _, regexp := range invalidRegexps {
+ if re, err := Parse(regexp, Perl); err == nil {
+ t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re))
+ }
+ if re, err := Parse(regexp, POSIX); err == nil {
+ t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re))
+ }
+ }
+ for _, regexp := range onlyPerl {
+ if _, err := Parse(regexp, Perl); err != nil {
+ t.Errorf("Parse(%#q, Perl): %v", regexp, err)
+ }
+ if re, err := Parse(regexp, POSIX); err == nil {
+ t.Errorf("Parse(%#q, POSIX) = %s, should have failed", regexp, dump(re))
+ }
+ }
+ for _, regexp := range onlyPOSIX {
+ if re, err := Parse(regexp, Perl); err == nil {
+ t.Errorf("Parse(%#q, Perl) = %s, should have failed", regexp, dump(re))
+ }
+ if _, err := Parse(regexp, POSIX); err != nil {
+ t.Errorf("Parse(%#q, POSIX): %v", regexp, err)
+ }
+ }
+}
+
+func TestToStringEquivalentParse(t *testing.T) {
+ for _, tt := range parseTests {
+ re, err := Parse(tt.Regexp, testFlags)
+ if err != nil {
+ t.Errorf("Parse(%#q): %v", tt.Regexp, err)
+ continue
+ }
+ d := dump(re)
+ if d != tt.Dump {
+ t.Errorf("Parse(%#q).Dump() = %#q want %#q", tt.Regexp, d, tt.Dump)
+ continue
+ }
+
+ s := re.String()
+ if s != tt.Regexp {
+ // If ToString didn't return the original regexp,
+ // it must have found one with fewer parens.
+ // Unfortunately we can't check the length here, because
+ // ToString produces "\\{" for a literal brace,
+ // but "{" is a shorter equivalent in some contexts.
+ nre, err := Parse(s, testFlags)
+ if err != nil {
+ t.Errorf("Parse(%#q.String() = %#q): %v", tt.Regexp, t, err)
+ continue
+ }
+ nd := dump(nre)
+ if d != nd {
+ t.Errorf("Parse(%#q) -> %#q; %#q vs %#q", tt.Regexp, s, d, nd)
+ }
+
+ ns := nre.String()
+ if s != ns {
+ t.Errorf("Parse(%#q) -> %#q -> %#q", tt.Regexp, s, ns)
+ }
+ }
+ }
+}
diff --git a/libgo/go/exp/regexp/syntax/perl_groups.go b/libgo/go/regexp/syntax/perl_groups.go
index 05b392c40d8..05b392c40d8 100644
--- a/libgo/go/exp/regexp/syntax/perl_groups.go
+++ b/libgo/go/regexp/syntax/perl_groups.go
diff --git a/libgo/go/regexp/syntax/prog.go b/libgo/go/regexp/syntax/prog.go
new file mode 100644
index 00000000000..ced45da077b
--- /dev/null
+++ b/libgo/go/regexp/syntax/prog.go
@@ -0,0 +1,306 @@
+package syntax
+
+import (
+ "bytes"
+ "strconv"
+ "unicode"
+)
+
+// Compiled program.
+// May not belong in this package, but convenient for now.
+
+// A Prog is a compiled regular expression program.
+type Prog struct {
+ Inst []Inst
+ Start int // index of start instruction
+ NumCap int // number of InstCapture insts in re
+}
+
+// An InstOp is an instruction opcode.
+type InstOp uint8
+
+const (
+ InstAlt InstOp = iota
+ InstAltMatch
+ InstCapture
+ InstEmptyWidth
+ InstMatch
+ InstFail
+ InstNop
+ InstRune
+ InstRune1
+ InstRuneAny
+ InstRuneAnyNotNL
+)
+
+// An EmptyOp specifies a kind or mixture of zero-width assertions.
+type EmptyOp uint8
+
+const (
+ EmptyBeginLine EmptyOp = 1 << iota
+ EmptyEndLine
+ EmptyBeginText
+ EmptyEndText
+ EmptyWordBoundary
+ EmptyNoWordBoundary
+)
+
+// EmptyOpContext returns the zero-width assertions
+// satisfied at the position between the runes r1 and r2.
+// Passing r1 == -1 indicates that the position is
+// at the beginning of the text.
+// Passing r2 == -1 indicates that the position is
+// at the end of the text.
+func EmptyOpContext(r1, r2 int) EmptyOp {
+ var op EmptyOp
+ if r1 < 0 {
+ op |= EmptyBeginText | EmptyBeginLine
+ }
+ if r1 == '\n' {
+ op |= EmptyBeginLine
+ }
+ if r2 < 0 {
+ op |= EmptyEndText | EmptyEndLine
+ }
+ if r2 == '\n' {
+ op |= EmptyEndLine
+ }
+ if IsWordChar(r1) != IsWordChar(r2) {
+ op |= EmptyWordBoundary
+ } else {
+ op |= EmptyNoWordBoundary
+ }
+ return op
+}
+
+// IsWordChar reports whether r is consider a ``word character''
+// during the evaluation of the \b and \B zero-width assertions.
+// These assertions are ASCII-only: the word characters are [A-Za-z0-9_].
+func IsWordChar(r int) bool {
+ return 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' || '0' <= r && r <= '9' || r == '_'
+}
+
+// An Inst is a single instruction in a regular expression program.
+type Inst struct {
+ Op InstOp
+ Out uint32 // all but InstMatch, InstFail
+ Arg uint32 // InstAlt, InstAltMatch, InstCapture, InstEmptyWidth
+ Rune []int
+}
+
+func (p *Prog) String() string {
+ var b bytes.Buffer
+ dumpProg(&b, p)
+ return b.String()
+}
+
+// skipNop follows any no-op or capturing instructions
+// and returns the resulting pc.
+func (p *Prog) skipNop(pc uint32) *Inst {
+ i := &p.Inst[pc]
+ for i.Op == InstNop || i.Op == InstCapture {
+ pc = i.Out
+ i = &p.Inst[pc]
+ }
+ return i
+}
+
+// op returns i.Op but merges all the Rune special cases into InstRune
+func (i *Inst) op() InstOp {
+ op := i.Op
+ switch op {
+ case InstRune1, InstRuneAny, InstRuneAnyNotNL:
+ op = InstRune
+ }
+ return op
+}
+
+// Prefix returns a literal string that all matches for the
+// regexp must start with. Complete is true if the prefix
+// is the entire match.
+func (p *Prog) Prefix() (prefix string, complete bool) {
+ i := p.skipNop(uint32(p.Start))
+
+ // Avoid allocation of buffer if prefix is empty.
+ if i.op() != InstRune || len(i.Rune) != 1 {
+ return "", i.Op == InstMatch
+ }
+
+ // Have prefix; gather characters.
+ var buf bytes.Buffer
+ for i.op() == InstRune && len(i.Rune) == 1 && Flags(i.Arg)&FoldCase == 0 {
+ buf.WriteRune(i.Rune[0])
+ i = p.skipNop(i.Out)
+ }
+ return buf.String(), i.Op == InstMatch
+}
+
+// StartCond returns the leading empty-width conditions that must
+// be true in any match. It returns ^EmptyOp(0) if no matches are possible.
+func (p *Prog) StartCond() EmptyOp {
+ var flag EmptyOp
+ pc := uint32(p.Start)
+ i := &p.Inst[pc]
+Loop:
+ for {
+ switch i.Op {
+ case InstEmptyWidth:
+ flag |= EmptyOp(i.Arg)
+ case InstFail:
+ return ^EmptyOp(0)
+ case InstCapture, InstNop:
+ // skip
+ default:
+ break Loop
+ }
+ pc = i.Out
+ i = &p.Inst[pc]
+ }
+ return flag
+}
+
+// MatchRune returns true if the instruction matches (and consumes) r.
+// It should only be called when i.Op == InstRune.
+func (i *Inst) MatchRune(r int) bool {
+ rune := i.Rune
+
+ // Special case: single-rune slice is from literal string, not char class.
+ if len(rune) == 1 {
+ r0 := rune[0]
+ if r == r0 {
+ return true
+ }
+ if Flags(i.Arg)&FoldCase != 0 {
+ for r1 := unicode.SimpleFold(r0); r1 != r0; r1 = unicode.SimpleFold(r1) {
+ if r == r1 {
+ return true
+ }
+ }
+ }
+ return false
+ }
+
+ // Peek at the first few pairs.
+ // Should handle ASCII well.
+ for j := 0; j < len(rune) && j <= 8; j += 2 {
+ if r < rune[j] {
+ return false
+ }
+ if r <= rune[j+1] {
+ return true
+ }
+ }
+
+ // Otherwise binary search.
+ lo := 0
+ hi := len(rune) / 2
+ for lo < hi {
+ m := lo + (hi-lo)/2
+ if c := rune[2*m]; c <= r {
+ if r <= rune[2*m+1] {
+ return true
+ }
+ lo = m + 1
+ } else {
+ hi = m
+ }
+ }
+ return false
+}
+
+// As per re2's Prog::IsWordChar. Determines whether rune is an ASCII word char.
+// Since we act on runes, it would be easy to support Unicode here.
+func wordRune(rune int) bool {
+ return rune == '_' ||
+ ('A' <= rune && rune <= 'Z') ||
+ ('a' <= rune && rune <= 'z') ||
+ ('0' <= rune && rune <= '9')
+}
+
+// MatchEmptyWidth returns true if the instruction matches
+// an empty string between the runes before and after.
+// It should only be called when i.Op == InstEmptyWidth.
+func (i *Inst) MatchEmptyWidth(before int, after int) bool {
+ switch EmptyOp(i.Arg) {
+ case EmptyBeginLine:
+ return before == '\n' || before == -1
+ case EmptyEndLine:
+ return after == '\n' || after == -1
+ case EmptyBeginText:
+ return before == -1
+ case EmptyEndText:
+ return after == -1
+ case EmptyWordBoundary:
+ return wordRune(before) != wordRune(after)
+ case EmptyNoWordBoundary:
+ return wordRune(before) == wordRune(after)
+ }
+ panic("unknown empty width arg")
+}
+
+func (i *Inst) String() string {
+ var b bytes.Buffer
+ dumpInst(&b, i)
+ return b.String()
+}
+
+func bw(b *bytes.Buffer, args ...string) {
+ for _, s := range args {
+ b.WriteString(s)
+ }
+}
+
+func dumpProg(b *bytes.Buffer, p *Prog) {
+ for j := range p.Inst {
+ i := &p.Inst[j]
+ pc := strconv.Itoa(j)
+ if len(pc) < 3 {
+ b.WriteString(" "[len(pc):])
+ }
+ if j == p.Start {
+ pc += "*"
+ }
+ bw(b, pc, "\t")
+ dumpInst(b, i)
+ bw(b, "\n")
+ }
+}
+
+func u32(i uint32) string {
+ return strconv.Uitoa64(uint64(i))
+}
+
+func dumpInst(b *bytes.Buffer, i *Inst) {
+ switch i.Op {
+ case InstAlt:
+ bw(b, "alt -> ", u32(i.Out), ", ", u32(i.Arg))
+ case InstAltMatch:
+ bw(b, "altmatch -> ", u32(i.Out), ", ", u32(i.Arg))
+ case InstCapture:
+ bw(b, "cap ", u32(i.Arg), " -> ", u32(i.Out))
+ case InstEmptyWidth:
+ bw(b, "empty ", u32(i.Arg), " -> ", u32(i.Out))
+ case InstMatch:
+ bw(b, "match")
+ case InstFail:
+ bw(b, "fail")
+ case InstNop:
+ bw(b, "nop -> ", u32(i.Out))
+ case InstRune:
+ if i.Rune == nil {
+ // shouldn't happen
+ bw(b, "rune <nil>")
+ }
+ bw(b, "rune ", strconv.QuoteToASCII(string(i.Rune)))
+ if Flags(i.Arg)&FoldCase != 0 {
+ bw(b, "/i")
+ }
+ bw(b, " -> ", u32(i.Out))
+ case InstRune1:
+ bw(b, "rune1 ", strconv.QuoteToASCII(string(i.Rune)), " -> ", u32(i.Out))
+ case InstRuneAny:
+ bw(b, "any -> ", u32(i.Out))
+ case InstRuneAnyNotNL:
+ bw(b, "anynotnl -> ", u32(i.Out))
+ }
+}
diff --git a/libgo/go/regexp/syntax/prog_test.go b/libgo/go/regexp/syntax/prog_test.go
new file mode 100644
index 00000000000..70959f6790a
--- /dev/null
+++ b/libgo/go/regexp/syntax/prog_test.go
@@ -0,0 +1,102 @@
+package syntax_test
+
+import (
+ . "regexp/syntax"
+ "testing"
+)
+
+var compileTests = []struct {
+ Regexp string
+ Prog string
+}{
+ {"a", ` 0 fail
+ 1* rune1 "a" -> 2
+ 2 match
+`},
+ {"[A-M][n-z]", ` 0 fail
+ 1* rune "AM" -> 2
+ 2 rune "nz" -> 3
+ 3 match
+`},
+ {"", ` 0 fail
+ 1* nop -> 2
+ 2 match
+`},
+ {"a?", ` 0 fail
+ 1 rune1 "a" -> 3
+ 2* alt -> 1, 3
+ 3 match
+`},
+ {"a??", ` 0 fail
+ 1 rune1 "a" -> 3
+ 2* alt -> 3, 1
+ 3 match
+`},
+ {"a+", ` 0 fail
+ 1* rune1 "a" -> 2
+ 2 alt -> 1, 3
+ 3 match
+`},
+ {"a+?", ` 0 fail
+ 1* rune1 "a" -> 2
+ 2 alt -> 3, 1
+ 3 match
+`},
+ {"a*", ` 0 fail
+ 1 rune1 "a" -> 2
+ 2* alt -> 1, 3
+ 3 match
+`},
+ {"a*?", ` 0 fail
+ 1 rune1 "a" -> 2
+ 2* alt -> 3, 1
+ 3 match
+`},
+ {"a+b+", ` 0 fail
+ 1* rune1 "a" -> 2
+ 2 alt -> 1, 3
+ 3 rune1 "b" -> 4
+ 4 alt -> 3, 5
+ 5 match
+`},
+ {"(a+)(b+)", ` 0 fail
+ 1* cap 2 -> 2
+ 2 rune1 "a" -> 3
+ 3 alt -> 2, 4
+ 4 cap 3 -> 5
+ 5 cap 4 -> 6
+ 6 rune1 "b" -> 7
+ 7 alt -> 6, 8
+ 8 cap 5 -> 9
+ 9 match
+`},
+ {"a+|b+", ` 0 fail
+ 1 rune1 "a" -> 2
+ 2 alt -> 1, 6
+ 3 rune1 "b" -> 4
+ 4 alt -> 3, 6
+ 5* alt -> 1, 3
+ 6 match
+`},
+ {"A[Aa]", ` 0 fail
+ 1* rune1 "A" -> 2
+ 2 rune "A"/i -> 3
+ 3 match
+`},
+ {"(?:(?:^).)", ` 0 fail
+ 1* empty 4 -> 2
+ 2 anynotnl -> 3
+ 3 match
+`},
+}
+
+func TestCompile(t *testing.T) {
+ for _, tt := range compileTests {
+ re, _ := Parse(tt.Regexp, Perl)
+ p, _ := Compile(re)
+ s := p.String()
+ if s != tt.Prog {
+ t.Errorf("compiled %#q:\n--- have\n%s---\n--- want\n%s---", tt.Regexp, s, tt.Prog)
+ }
+ }
+}
diff --git a/libgo/go/regexp/syntax/regexp.go b/libgo/go/regexp/syntax/regexp.go
new file mode 100644
index 00000000000..033848df28a
--- /dev/null
+++ b/libgo/go/regexp/syntax/regexp.go
@@ -0,0 +1,305 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package syntax parses regular expressions into syntax trees.
+// WORK IN PROGRESS.
+package syntax
+
+// Note to implementers:
+// In this package, re is always a *Regexp and r is always a rune.
+
+import (
+ "bytes"
+ "strconv"
+ "strings"
+ "unicode"
+)
+
+// A Regexp is a node in a regular expression syntax tree.
+type Regexp struct {
+ Op Op // operator
+ Flags Flags
+ Sub []*Regexp // subexpressions, if any
+ Sub0 [1]*Regexp // storage for short Sub
+ Rune []int // matched runes, for OpLiteral, OpCharClass
+ Rune0 [2]int // storage for short Rune
+ Min, Max int // min, max for OpRepeat
+ Cap int // capturing index, for OpCapture
+ Name string // capturing name, for OpCapture
+}
+
+// An Op is a single regular expression operator.
+type Op uint8
+
+// Operators are listed in precedence order, tightest binding to weakest.
+// Character class operators are listed simplest to most complex
+// (OpLiteral, OpCharClass, OpAnyCharNotNL, OpAnyChar).
+
+const (
+ OpNoMatch Op = 1 + iota // matches no strings
+ OpEmptyMatch // matches empty string
+ OpLiteral // matches Runes sequence
+ OpCharClass // matches Runes interpreted as range pair list
+ OpAnyCharNotNL // matches any character
+ OpAnyChar // matches any character
+ OpBeginLine // matches empty string at beginning of line
+ OpEndLine // matches empty string at end of line
+ OpBeginText // matches empty string at beginning of text
+ OpEndText // matches empty string at end of text
+ OpWordBoundary // matches word boundary `\b`
+ OpNoWordBoundary // matches word non-boundary `\B`
+ OpCapture // capturing subexpression with index Cap, optional name Name
+ OpStar // matches Sub[0] zero or more times
+ OpPlus // matches Sub[0] one or more times
+ OpQuest // matches Sub[0] zero or one times
+ OpRepeat // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit)
+ OpConcat // matches concatenation of Subs
+ OpAlternate // matches alternation of Subs
+)
+
+const opPseudo Op = 128 // where pseudo-ops start
+
+// Equal returns true if x and y have identical structure.
+func (x *Regexp) Equal(y *Regexp) bool {
+ if x == nil || y == nil {
+ return x == y
+ }
+ if x.Op != y.Op {
+ return false
+ }
+ switch x.Op {
+ case OpEndText:
+ // The parse flags remember whether this is \z or \Z.
+ if x.Flags&WasDollar != y.Flags&WasDollar {
+ return false
+ }
+
+ case OpLiteral, OpCharClass:
+ if len(x.Rune) != len(y.Rune) {
+ return false
+ }
+ for i, r := range x.Rune {
+ if r != y.Rune[i] {
+ return false
+ }
+ }
+
+ case OpAlternate, OpConcat:
+ if len(x.Sub) != len(y.Sub) {
+ return false
+ }
+ for i, sub := range x.Sub {
+ if !sub.Equal(y.Sub[i]) {
+ return false
+ }
+ }
+
+ case OpStar, OpPlus, OpQuest:
+ if x.Flags&NonGreedy != y.Flags&NonGreedy || !x.Sub[0].Equal(y.Sub[0]) {
+ return false
+ }
+
+ case OpRepeat:
+ if x.Flags&NonGreedy != y.Flags&NonGreedy || x.Min != y.Min || x.Max != y.Max || !x.Sub[0].Equal(y.Sub[0]) {
+ return false
+ }
+
+ case OpCapture:
+ if x.Cap != y.Cap || x.Name != y.Name || !x.Sub[0].Equal(y.Sub[0]) {
+ return false
+ }
+ }
+ return true
+}
+
+// writeRegexp writes the Perl syntax for the regular expression re to b.
+func writeRegexp(b *bytes.Buffer, re *Regexp) {
+ switch re.Op {
+ default:
+ b.WriteString("<invalid op" + strconv.Itoa(int(re.Op)) + ">")
+ case OpNoMatch:
+ b.WriteString(`[^\x00-\x{10FFFF}]`)
+ case OpEmptyMatch:
+ b.WriteString(`(?:)`)
+ case OpLiteral:
+ if re.Flags&FoldCase != 0 {
+ b.WriteString(`(?i:`)
+ }
+ for _, r := range re.Rune {
+ escape(b, r, false)
+ }
+ if re.Flags&FoldCase != 0 {
+ b.WriteString(`)`)
+ }
+ case OpCharClass:
+ if len(re.Rune)%2 != 0 {
+ b.WriteString(`[invalid char class]`)
+ break
+ }
+ b.WriteRune('[')
+ if len(re.Rune) == 0 {
+ b.WriteString(`^\x00-\x{10FFFF}`)
+ } else if re.Rune[0] == 0 && re.Rune[len(re.Rune)-1] == unicode.MaxRune {
+ // Contains 0 and MaxRune. Probably a negated class.
+ // Print the gaps.
+ b.WriteRune('^')
+ for i := 1; i < len(re.Rune)-1; i += 2 {
+ lo, hi := re.Rune[i]+1, re.Rune[i+1]-1
+ escape(b, lo, lo == '-')
+ if lo != hi {
+ b.WriteRune('-')
+ escape(b, hi, hi == '-')
+ }
+ }
+ } else {
+ for i := 0; i < len(re.Rune); i += 2 {
+ lo, hi := re.Rune[i], re.Rune[i+1]
+ escape(b, lo, lo == '-')
+ if lo != hi {
+ b.WriteRune('-')
+ escape(b, hi, hi == '-')
+ }
+ }
+ }
+ b.WriteRune(']')
+ case OpAnyCharNotNL:
+ b.WriteString(`(?-s:.)`)
+ case OpAnyChar:
+ b.WriteString(`(?s:.)`)
+ case OpBeginLine:
+ b.WriteRune('^')
+ case OpEndLine:
+ b.WriteRune('$')
+ case OpBeginText:
+ b.WriteString(`\A`)
+ case OpEndText:
+ if re.Flags&WasDollar != 0 {
+ b.WriteString(`(?-m:$)`)
+ } else {
+ b.WriteString(`\z`)
+ }
+ case OpWordBoundary:
+ b.WriteString(`\b`)
+ case OpNoWordBoundary:
+ b.WriteString(`\B`)
+ case OpCapture:
+ if re.Name != "" {
+ b.WriteString(`(?P<`)
+ b.WriteString(re.Name)
+ b.WriteRune('>')
+ } else {
+ b.WriteRune('(')
+ }
+ if re.Sub[0].Op != OpEmptyMatch {
+ writeRegexp(b, re.Sub[0])
+ }
+ b.WriteRune(')')
+ case OpStar, OpPlus, OpQuest, OpRepeat:
+ if sub := re.Sub[0]; sub.Op > OpCapture || sub.Op == OpLiteral && len(sub.Rune) > 1 {
+ b.WriteString(`(?:`)
+ writeRegexp(b, sub)
+ b.WriteString(`)`)
+ } else {
+ writeRegexp(b, sub)
+ }
+ switch re.Op {
+ case OpStar:
+ b.WriteRune('*')
+ case OpPlus:
+ b.WriteRune('+')
+ case OpQuest:
+ b.WriteRune('?')
+ case OpRepeat:
+ b.WriteRune('{')
+ b.WriteString(strconv.Itoa(re.Min))
+ if re.Max != re.Min {
+ b.WriteRune(',')
+ if re.Max >= 0 {
+ b.WriteString(strconv.Itoa(re.Max))
+ }
+ }
+ b.WriteRune('}')
+ }
+ if re.Flags&NonGreedy != 0 {
+ b.WriteRune('?')
+ }
+ case OpConcat:
+ for _, sub := range re.Sub {
+ if sub.Op == OpAlternate {
+ b.WriteString(`(?:`)
+ writeRegexp(b, sub)
+ b.WriteString(`)`)
+ } else {
+ writeRegexp(b, sub)
+ }
+ }
+ case OpAlternate:
+ for i, sub := range re.Sub {
+ if i > 0 {
+ b.WriteRune('|')
+ }
+ writeRegexp(b, sub)
+ }
+ }
+}
+
+func (re *Regexp) String() string {
+ var b bytes.Buffer
+ writeRegexp(&b, re)
+ return b.String()
+}
+
+const meta = `\.+*?()|[]{}^$`
+
+func escape(b *bytes.Buffer, r int, force bool) {
+ if unicode.IsPrint(r) {
+ if strings.IndexRune(meta, r) >= 0 || force {
+ b.WriteRune('\\')
+ }
+ b.WriteRune(r)
+ return
+ }
+
+ switch r {
+ case '\a':
+ b.WriteString(`\a`)
+ case '\f':
+ b.WriteString(`\f`)
+ case '\n':
+ b.WriteString(`\n`)
+ case '\r':
+ b.WriteString(`\r`)
+ case '\t':
+ b.WriteString(`\t`)
+ case '\v':
+ b.WriteString(`\v`)
+ default:
+ if r < 0x100 {
+ b.WriteString(`\x`)
+ s := strconv.Itob(r, 16)
+ if len(s) == 1 {
+ b.WriteRune('0')
+ }
+ b.WriteString(s)
+ break
+ }
+ b.WriteString(`\x{`)
+ b.WriteString(strconv.Itob(r, 16))
+ b.WriteString(`}`)
+ }
+}
+
+// MaxCap walks the regexp to find the maximum capture index.
+func (re *Regexp) MaxCap() int {
+ m := 0
+ if re.Op == OpCapture {
+ m = re.Cap
+ }
+ for _, sub := range re.Sub {
+ if n := sub.MaxCap(); m < n {
+ m = n
+ }
+ }
+ return m
+}
diff --git a/libgo/go/exp/regexp/syntax/simplify.go b/libgo/go/regexp/syntax/simplify.go
index 72390417bbe..72390417bbe 100644
--- a/libgo/go/exp/regexp/syntax/simplify.go
+++ b/libgo/go/regexp/syntax/simplify.go
diff --git a/libgo/go/regexp/syntax/simplify_test.go b/libgo/go/regexp/syntax/simplify_test.go
new file mode 100644
index 00000000000..92a9d3d6da3
--- /dev/null
+++ b/libgo/go/regexp/syntax/simplify_test.go
@@ -0,0 +1,152 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syntax_test
+
+import . "regexp/syntax"
+import "testing"
+
+var simplifyTests = []struct {
+ Regexp string
+ Simple string
+}{
+ // Already-simple constructs
+ {`a`, `a`},
+ {`ab`, `ab`},
+ {`a|b`, `[a-b]`},
+ {`ab|cd`, `ab|cd`},
+ {`(ab)*`, `(ab)*`},
+ {`(ab)+`, `(ab)+`},
+ {`(ab)?`, `(ab)?`},
+ {`.`, `(?s:.)`},
+ {`^`, `^`},
+ {`$`, `$`},
+ {`[ac]`, `[ac]`},
+ {`[^ac]`, `[^ac]`},
+
+ // Posix character classes
+ {`[[:alnum:]]`, `[0-9A-Za-z]`},
+ {`[[:alpha:]]`, `[A-Za-z]`},
+ {`[[:blank:]]`, `[\t ]`},
+ {`[[:cntrl:]]`, `[\x00-\x1f\x7f]`},
+ {`[[:digit:]]`, `[0-9]`},
+ {`[[:graph:]]`, `[!-~]`},
+ {`[[:lower:]]`, `[a-z]`},
+ {`[[:print:]]`, `[ -~]`},
+ {`[[:punct:]]`, "[!-/:-@\\[-`\\{-~]"},
+ {`[[:space:]]`, `[\t-\r ]`},
+ {`[[:upper:]]`, `[A-Z]`},
+ {`[[:xdigit:]]`, `[0-9A-Fa-f]`},
+
+ // Perl character classes
+ {`\d`, `[0-9]`},
+ {`\s`, `[\t-\n\f-\r ]`},
+ {`\w`, `[0-9A-Z_a-z]`},
+ {`\D`, `[^0-9]`},
+ {`\S`, `[^\t-\n\f-\r ]`},
+ {`\W`, `[^0-9A-Z_a-z]`},
+ {`[\d]`, `[0-9]`},
+ {`[\s]`, `[\t-\n\f-\r ]`},
+ {`[\w]`, `[0-9A-Z_a-z]`},
+ {`[\D]`, `[^0-9]`},
+ {`[\S]`, `[^\t-\n\f-\r ]`},
+ {`[\W]`, `[^0-9A-Z_a-z]`},
+
+ // Posix repetitions
+ {`a{1}`, `a`},
+ {`a{2}`, `aa`},
+ {`a{5}`, `aaaaa`},
+ {`a{0,1}`, `a?`},
+ // The next three are illegible because Simplify inserts (?:)
+ // parens instead of () parens to avoid creating extra
+ // captured subexpressions. The comments show a version with fewer parens.
+ {`(a){0,2}`, `(?:(a)(a)?)?`}, // (aa?)?
+ {`(a){0,4}`, `(?:(a)(?:(a)(?:(a)(a)?)?)?)?`}, // (a(a(aa?)?)?)?
+ {`(a){2,6}`, `(a)(a)(?:(a)(?:(a)(?:(a)(a)?)?)?)?`}, // aa(a(a(aa?)?)?)?
+ {`a{0,2}`, `(?:aa?)?`}, // (aa?)?
+ {`a{0,4}`, `(?:a(?:a(?:aa?)?)?)?`}, // (a(a(aa?)?)?)?
+ {`a{2,6}`, `aa(?:a(?:a(?:aa?)?)?)?`}, // aa(a(a(aa?)?)?)?
+ {`a{0,}`, `a*`},
+ {`a{1,}`, `a+`},
+ {`a{2,}`, `aa+`},
+ {`a{5,}`, `aaaaa+`},
+
+ // Test that operators simplify their arguments.
+ {`(?:a{1,}){1,}`, `a+`},
+ {`(a{1,}b{1,})`, `(a+b+)`},
+ {`a{1,}|b{1,}`, `a+|b+`},
+ {`(?:a{1,})*`, `(?:a+)*`},
+ {`(?:a{1,})+`, `a+`},
+ {`(?:a{1,})?`, `(?:a+)?`},
+ {``, `(?:)`},
+ {`a{0}`, `(?:)`},
+
+ // Character class simplification
+ {`[ab]`, `[a-b]`},
+ {`[a-za-za-z]`, `[a-z]`},
+ {`[A-Za-zA-Za-z]`, `[A-Za-z]`},
+ {`[ABCDEFGH]`, `[A-H]`},
+ {`[AB-CD-EF-GH]`, `[A-H]`},
+ {`[W-ZP-XE-R]`, `[E-Z]`},
+ {`[a-ee-gg-m]`, `[a-m]`},
+ {`[a-ea-ha-m]`, `[a-m]`},
+ {`[a-ma-ha-e]`, `[a-m]`},
+ {`[a-zA-Z0-9 -~]`, `[ -~]`},
+
+ // Empty character classes
+ {`[^[:cntrl:][:^cntrl:]]`, `[^\x00-\x{10FFFF}]`},
+
+ // Full character classes
+ {`[[:cntrl:][:^cntrl:]]`, `(?s:.)`},
+
+ // Unicode case folding.
+ {`(?i)A`, `(?i:A)`},
+ {`(?i)a`, `(?i:A)`},
+ {`(?i)[A]`, `(?i:A)`},
+ {`(?i)[a]`, `(?i:A)`},
+ {`(?i)K`, `(?i:K)`},
+ {`(?i)k`, `(?i:K)`},
+ {`(?i)\x{212a}`, "(?i:K)"},
+ {`(?i)[K]`, "[Kk\u212A]"},
+ {`(?i)[k]`, "[Kk\u212A]"},
+ {`(?i)[\x{212a}]`, "[Kk\u212A]"},
+ {`(?i)[a-z]`, "[A-Za-z\u017F\u212A]"},
+ {`(?i)[\x00-\x{FFFD}]`, "[\\x00-\uFFFD]"},
+ {`(?i)[\x00-\x{10FFFF}]`, `(?s:.)`},
+
+ // Empty string as a regular expression.
+ // The empty string must be preserved inside parens in order
+ // to make submatches work right, so these tests are less
+ // interesting than they might otherwise be. String inserts
+ // explicit (?:) in place of non-parenthesized empty strings,
+ // to make them easier to spot for other parsers.
+ {`(a|b|)`, `([a-b]|(?:))`},
+ {`(|)`, `()`},
+ {`a()`, `a()`},
+ {`(()|())`, `(()|())`},
+ {`(a|)`, `(a|(?:))`},
+ {`ab()cd()`, `ab()cd()`},
+ {`()`, `()`},
+ {`()*`, `()*`},
+ {`()+`, `()+`},
+ {`()?`, `()?`},
+ {`(){0}`, `(?:)`},
+ {`(){1}`, `()`},
+ {`(){1,}`, `()+`},
+ {`(){0,2}`, `(?:()()?)?`},
+}
+
+func TestSimplify(t *testing.T) {
+ for _, tt := range simplifyTests {
+ re, err := Parse(tt.Regexp, MatchNL|Perl&^OneLine)
+ if err != nil {
+ t.Errorf("Parse(%#q) = error %v", tt.Regexp, err)
+ continue
+ }
+ s := re.Simplify().String()
+ if s != tt.Simple {
+ t.Errorf("Simplify(%#q) = %#q, want %#q", tt.Regexp, s, tt.Simple)
+ }
+ }
+}
diff --git a/libgo/go/regexp/testdata/README b/libgo/go/regexp/testdata/README
new file mode 100644
index 00000000000..b1b301be83f
--- /dev/null
+++ b/libgo/go/regexp/testdata/README
@@ -0,0 +1,23 @@
+AT&T POSIX Test Files
+See textregex.c for copyright + license.
+
+testregex.c http://www2.research.att.com/~gsf/testregex/testregex.c
+basic.dat http://www2.research.att.com/~gsf/testregex/basic.dat
+nullsubexpr.dat http://www2.research.att.com/~gsf/testregex/nullsubexpr.dat
+repetition.dat http://www2.research.att.com/~gsf/testregex/repetition.dat
+
+The test data has been edited to reflect RE2/Go differences:
+ * In a star of a possibly empty match like (a*)* matching x,
+ the no match case runs the starred subexpression zero times,
+ not once. This is consistent with (a*)* matching a, which
+ runs the starred subexpression one time, not twice.
+ * The submatch choice is first match, not the POSIX rule.
+
+Such changes are marked with 'RE2/Go'.
+
+
+RE2 Test Files
+
+re2-exhaustive.txt.bz2 and re2-search.txt are built by running
+'make log' in the RE2 distribution. http://code.google.com/p/re2/.
+The exhaustive file is compressed because it is huge.
diff --git a/libgo/go/regexp/testdata/basic.dat b/libgo/go/regexp/testdata/basic.dat
new file mode 100644
index 00000000000..7859290ba1d
--- /dev/null
+++ b/libgo/go/regexp/testdata/basic.dat
@@ -0,0 +1,221 @@
+NOTE all standard compliant implementations should pass these : 2002-05-31
+
+BE abracadabra$ abracadabracadabra (7,18)
+BE a...b abababbb (2,7)
+BE XXXXXX ..XXXXXX (2,8)
+E \) () (1,2)
+BE a] a]a (0,2)
+B } } (0,1)
+E \} } (0,1)
+BE \] ] (0,1)
+B ] ] (0,1)
+E ] ] (0,1)
+B { { (0,1)
+B } } (0,1)
+BE ^a ax (0,1)
+BE \^a a^a (1,3)
+BE a\^ a^ (0,2)
+BE a$ aa (1,2)
+BE a\$ a$ (0,2)
+BE ^$ NULL (0,0)
+E $^ NULL (0,0)
+E a($) aa (1,2)(2,2)
+E a*(^a) aa (0,1)(0,1)
+E (..)*(...)* a (0,0)
+E (..)*(...)* abcd (0,4)(2,4)
+E (ab|a)(bc|c) abc (0,3)(0,2)(2,3)
+E (ab)c|abc abc (0,3)(0,2)
+E a{0}b ab (1,2)
+E (a*)(b?)(b+)b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7)
+E (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7)
+E a{9876543210} NULL BADBR
+E ((a|a)|a) a (0,1)(0,1)(0,1)
+E (a*)(a|aa) aaaa (0,4)(0,3)(3,4)
+E a*(a.|aa) aaaa (0,4)(2,4)
+E a(b)|c(d)|a(e)f aef (0,3)(?,?)(?,?)(1,2)
+E (a|b)?.* b (0,1)(0,1)
+E (a|b)c|a(b|c) ac (0,2)(0,1)
+E (a|b)c|a(b|c) ab (0,2)(?,?)(1,2)
+E (a|b)*c|(a|ab)*c abc (0,3)(1,2)
+E (a|b)*c|(a|ab)*c xc (1,2)
+E (.a|.b).*|.*(.a|.b) xa (0,2)(0,2)
+E a?(ab|ba)ab abab (0,4)(0,2)
+E a?(ac{0}b|ba)ab abab (0,4)(0,2)
+E ab|abab abbabab (0,2)
+E aba|bab|bba baaabbbaba (5,8)
+E aba|bab baaabbbaba (6,9)
+E (aa|aaa)*|(a|aaaaa) aa (0,2)(0,2)
+E (a.|.a.)*|(a|.a...) aa (0,2)(0,2)
+E ab|a xabc (1,3)
+E ab|a xxabc (2,4)
+Ei (Ab|cD)* aBcD (0,4)(2,4)
+BE [^-] --a (2,3)
+BE [a-]* --a (0,3)
+BE [a-m-]* --amoma-- (0,4)
+E :::1:::0:|:::1:1:0: :::0:::1:::1:::0: (8,17)
+E :::1:::0:|:::1:1:1: :::0:::1:::1:::0: (8,17)
+{E [[:upper:]] A (0,1) [[<element>]] not supported
+E [[:lower:]]+ `az{ (1,3)
+E [[:upper:]]+ @AZ[ (1,3)
+# No collation in Go
+#BE [[-]] [[-]] (2,4)
+#BE [[.NIL.]] NULL ECOLLATE
+#BE [[=aleph=]] NULL ECOLLATE
+}
+BE$ \n \n (0,1)
+BEn$ \n \n (0,1)
+BE$ [^a] \n (0,1)
+BE$ \na \na (0,2)
+E (a)(b)(c) abc (0,3)(0,1)(1,2)(2,3)
+BE xxx xxx (0,3)
+E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 6, (0,6)
+E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) 2/7 (0,3)
+E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 1,Feb 6 (5,11)
+E3 ((((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))) x (0,1)(0,1)(0,1)
+E3 ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))* xx (0,2)(1,2)(1,2)
+E a?(ab|ba)* ababababababababababababababababababababababababababababababababababababababababa (0,81)(79,81)
+E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabbbbaa (18,25)
+E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabaa (18,22)
+E aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac (7,11)
+BE$ .* \x01\xff (0,2)
+E aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa (53,57)
+L aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa NOMATCH
+E a*a*a*a*a*b aaaaaaaaab (0,10)
+BE ^ NULL (0,0)
+BE $ NULL (0,0)
+BE ^$ NULL (0,0)
+BE ^a$ a (0,1)
+BE abc abc (0,3)
+BE abc xabcy (1,4)
+BE abc ababc (2,5)
+BE ab*c abc (0,3)
+BE ab*bc abc (0,3)
+BE ab*bc abbc (0,4)
+BE ab*bc abbbbc (0,6)
+E ab+bc abbc (0,4)
+E ab+bc abbbbc (0,6)
+E ab?bc abbc (0,4)
+E ab?bc abc (0,3)
+E ab?c abc (0,3)
+BE ^abc$ abc (0,3)
+BE ^abc abcc (0,3)
+BE abc$ aabc (1,4)
+BE ^ abc (0,0)
+BE $ abc (3,3)
+BE a.c abc (0,3)
+BE a.c axc (0,3)
+BE a.*c axyzc (0,5)
+BE a[bc]d abd (0,3)
+BE a[b-d]e ace (0,3)
+BE a[b-d] aac (1,3)
+BE a[-b] a- (0,2)
+BE a[b-] a- (0,2)
+BE a] a] (0,2)
+BE a[]]b a]b (0,3)
+BE a[^bc]d aed (0,3)
+BE a[^-b]c adc (0,3)
+BE a[^]b]c adc (0,3)
+E ab|cd abc (0,2)
+E ab|cd abcd (0,2)
+E a\(b a(b (0,3)
+E a\(*b ab (0,2)
+E a\(*b a((b (0,4)
+E ((a)) abc (0,1)(0,1)(0,1)
+E (a)b(c) abc (0,3)(0,1)(2,3)
+E a+b+c aabbabc (4,7)
+E a* aaa (0,3)
+#E (a*)* - (0,0)(0,0)
+E (a*)* - (0,0)(?,?) RE2/Go
+E (a*)+ - (0,0)(0,0)
+#E (a*|b)* - (0,0)(0,0)
+E (a*|b)* - (0,0)(?,?) RE2/Go
+E (a+|b)* ab (0,2)(1,2)
+E (a+|b)+ ab (0,2)(1,2)
+E (a+|b)? ab (0,1)(0,1)
+BE [^ab]* cde (0,3)
+#E (^)* - (0,0)(0,0)
+E (^)* - (0,0)(?,?) RE2/Go
+BE a* NULL (0,0)
+E ([abc])*d abbbcd (0,6)(4,5)
+E ([abc])*bcd abcd (0,4)(0,1)
+E a|b|c|d|e e (0,1)
+E (a|b|c|d|e)f ef (0,2)(0,1)
+#E ((a*|b))* - (0,0)(0,0)(0,0)
+E ((a*|b))* - (0,0)(?,?)(?,?) RE2/Go
+BE abcd*efg abcdefg (0,7)
+BE ab* xabyabbbz (1,3)
+BE ab* xayabbbz (1,2)
+E (ab|cd)e abcde (2,5)(2,4)
+BE [abhgefdc]ij hij (0,3)
+E (a|b)c*d abcd (1,4)(1,2)
+E (ab|ab*)bc abc (0,3)(0,1)
+E a([bc]*)c* abc (0,3)(1,3)
+E a([bc]*)(c*d) abcd (0,4)(1,3)(3,4)
+E a([bc]+)(c*d) abcd (0,4)(1,3)(3,4)
+E a([bc]*)(c+d) abcd (0,4)(1,2)(2,4)
+E a[bcd]*dcdcde adcdcde (0,7)
+E (ab|a)b*c abc (0,3)(0,2)
+E ((a)(b)c)(d) abcd (0,4)(0,3)(0,1)(1,2)(3,4)
+BE [A-Za-z_][A-Za-z0-9_]* alpha (0,5)
+E ^a(bc+|b[eh])g|.h$ abh (1,3)
+E (bc+d$|ef*g.|h?i(j|k)) effgz (0,5)(0,5)
+E (bc+d$|ef*g.|h?i(j|k)) ij (0,2)(0,2)(1,2)
+E (bc+d$|ef*g.|h?i(j|k)) reffgz (1,6)(1,6)
+E (((((((((a))))))))) a (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)
+BE multiple words multiple words yeah (0,14)
+E (.*)c(.*) abcde (0,5)(0,2)(3,5)
+BE abcd abcd (0,4)
+E a(bc)d abcd (0,4)(1,3)
+E a[-]?c ac (0,3)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qaddafi (0,15)(?,?)(10,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mo'ammar Gadhafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Kaddafi (0,15)(?,?)(10,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qadhafi (0,15)(?,?)(10,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gadafi (0,14)(?,?)(10,11)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadafi (0,15)(?,?)(11,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moamar Gaddafi (0,14)(?,?)(9,11)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadhdhafi (0,18)(?,?)(13,15)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Khaddafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafy (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghadafi (0,15)(?,?)(11,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muamar Kaddafi (0,14)(?,?)(9,11)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Quathafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gheddafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Khadafy (0,15)(?,?)(11,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Qudhafi (0,15)(?,?)(10,12)
+E a+(b|c)*d+ aabcdd (0,6)(3,4)
+E ^.+$ vivi (0,4)
+E ^(.+)$ vivi (0,4)(0,4)
+E ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby (0,19)(0,7)(16,19)
+E ^([^!]+!)?([^!]+)$ bas (0,3)(?,?)(0,3)
+E ^([^!]+!)?([^!]+)$ bar!bas (0,7)(0,4)(4,7)
+E ^([^!]+!)?([^!]+)$ foo!bas (0,7)(0,4)(4,7)
+E ^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(4,8)(8,11)
+E ((foo)|(bar))!bas bar!bas (0,7)(0,3)(?,?)(0,3)
+E ((foo)|(bar))!bas foo!bar!bas (4,11)(4,7)(?,?)(4,7)
+E ((foo)|(bar))!bas foo!bas (0,7)(0,3)(0,3)
+E ((foo)|bar)!bas bar!bas (0,7)(0,3)
+E ((foo)|bar)!bas foo!bar!bas (4,11)(4,7)
+E ((foo)|bar)!bas foo!bas (0,7)(0,3)(0,3)
+E (foo|(bar))!bas bar!bas (0,7)(0,3)(0,3)
+E (foo|(bar))!bas foo!bar!bas (4,11)(4,7)(4,7)
+E (foo|(bar))!bas foo!bas (0,7)(0,3)
+E (foo|bar)!bas bar!bas (0,7)(0,3)
+E (foo|bar)!bas foo!bar!bas (4,11)(4,7)
+E (foo|bar)!bas foo!bas (0,7)(0,3)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas (0,3)(?,?)(0,3)
+E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas (0,7)(0,4)(4,7)
+E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(?,?)(?,?)(4,8)(8,11)
+E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas (0,7)(0,4)(4,7)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas (0,3)(0,3)(?,?)(0,3)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas (0,7)(0,7)(0,4)(4,7)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas (0,7)(0,7)(0,4)(4,7)
+E .*(/XXX).* /XXX (0,4)(0,4)
+E .*(\\XXX).* \XXX (0,4)(0,4)
+E \\XXX \XXX (0,4)
+E .*(/000).* /000 (0,4)(0,4)
+E .*(\\000).* \000 (0,4)(0,4)
+E \\000 \000 (0,4)
diff --git a/libgo/go/regexp/testdata/nullsubexpr.dat b/libgo/go/regexp/testdata/nullsubexpr.dat
new file mode 100644
index 00000000000..2e18fbb9170
--- /dev/null
+++ b/libgo/go/regexp/testdata/nullsubexpr.dat
@@ -0,0 +1,79 @@
+NOTE null subexpression matches : 2002-06-06
+
+E (a*)* a (0,1)(0,1)
+#E SAME x (0,0)(0,0)
+E SAME x (0,0)(?,?) RE2/Go
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E (a*)+ a (0,1)(0,1)
+E SAME x (0,0)(0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E (a+)* a (0,1)(0,1)
+E SAME x (0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E (a+)+ a (0,1)(0,1)
+E SAME x NOMATCH
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+
+E ([a]*)* a (0,1)(0,1)
+#E SAME x (0,0)(0,0)
+E SAME x (0,0)(?,?) RE2/Go
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E ([a]*)+ a (0,1)(0,1)
+E SAME x (0,0)(0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E ([^b]*)* a (0,1)(0,1)
+#E SAME b (0,0)(0,0)
+E SAME b (0,0)(?,?) RE2/Go
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaab (0,6)(0,6)
+E ([ab]*)* a (0,1)(0,1)
+E SAME aaaaaa (0,6)(0,6)
+E SAME ababab (0,6)(0,6)
+E SAME bababa (0,6)(0,6)
+E SAME b (0,1)(0,1)
+E SAME bbbbbb (0,6)(0,6)
+E SAME aaaabcde (0,5)(0,5)
+E ([^a]*)* b (0,1)(0,1)
+E SAME bbbbbb (0,6)(0,6)
+#E SAME aaaaaa (0,0)(0,0)
+E SAME aaaaaa (0,0)(?,?) RE2/Go
+E ([^ab]*)* ccccxx (0,6)(0,6)
+#E SAME ababab (0,0)(0,0)
+E SAME ababab (0,0)(?,?) RE2/Go
+
+E ((z)+|a)* zabcde (0,2)(1,2)
+
+#{E a+? aaaaaa (0,1) no *? +? mimimal match ops
+#E (a) aaa (0,1)(0,1)
+#E (a*?) aaa (0,0)(0,0)
+#E (a)*? aaa (0,0)
+#E (a*?)*? aaa (0,0)
+#}
+
+B \(a*\)*\(x\) x (0,1)(0,0)(0,1)
+B \(a*\)*\(x\) ax (0,2)(0,1)(1,2)
+B \(a*\)*\(x\) axa (0,2)(0,1)(1,2)
+B \(a*\)*\(x\)\(\1\) x (0,1)(0,0)(0,1)(1,1)
+B \(a*\)*\(x\)\(\1\) ax (0,2)(1,1)(1,2)(2,2)
+B \(a*\)*\(x\)\(\1\) axa (0,3)(0,1)(1,2)(2,3)
+B \(a*\)*\(x\)\(\1\)\(x\) axax (0,4)(0,1)(1,2)(2,3)(3,4)
+B \(a*\)*\(x\)\(\1\)\(x\) axxa (0,3)(1,1)(1,2)(2,2)(2,3)
+
+#E (a*)*(x) x (0,1)(0,0)(0,1)
+E (a*)*(x) x (0,1)(?,?)(0,1) RE2/Go
+E (a*)*(x) ax (0,2)(0,1)(1,2)
+E (a*)*(x) axa (0,2)(0,1)(1,2)
+
+E (a*)+(x) x (0,1)(0,0)(0,1)
+E (a*)+(x) ax (0,2)(0,1)(1,2)
+E (a*)+(x) axa (0,2)(0,1)(1,2)
+
+E (a*){2}(x) x (0,1)(0,0)(0,1)
+E (a*){2}(x) ax (0,2)(1,1)(1,2)
+E (a*){2}(x) axa (0,2)(1,1)(1,2)
diff --git a/libgo/go/regexp/testdata/re2-search.txt b/libgo/go/regexp/testdata/re2-search.txt
new file mode 100644
index 00000000000..f648e5527f7
--- /dev/null
+++ b/libgo/go/regexp/testdata/re2-search.txt
@@ -0,0 +1,3667 @@
+# RE2 basic search tests built by make log
+# Thu Sep 8 13:43:43 EDT 2011
+Regexp.SearchTests
+strings
+""
+"a"
+regexps
+"a"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"zyzzyva"
+regexps
+"a"
+-;-;-;-
+-;6-7;-;6-7
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;6-7;-;6-7
+strings
+""
+"aa"
+regexps
+"a+"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:a+)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:a+)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:a+)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"ab"
+regexps
+"(a+|b)+"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"^(?:(a+|b)+)$"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"^(?:(a+|b)+)"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+"(?:(a+|b)+)$"
+-;-;-;-
+0-2 1-2;0-2 1-2;0-2 1-2;0-2 1-2
+strings
+""
+"xabcdx"
+regexps
+"ab|cd"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+"^(?:ab|cd)"
+-;-;-;-
+-;-;-;-
+"(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello\ngoodbye\n"
+regexps
+"h.*od?"
+-;-;-;-
+-;0-5;-;0-5
+"^(?:h.*od?)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*od?)"
+-;-;-;-
+-;0-5;-;0-5
+"(?:h.*od?)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello\ngoodbye\n"
+regexps
+"h.*o"
+-;-;-;-
+-;0-5;-;0-5
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;0-5;-;0-5
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"goodbye\nhello\n"
+regexps
+"h.*o"
+-;-;-;-
+-;8-13;-;8-13
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;-;-;-
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"hello world"
+regexps
+"h.*o"
+-;-;-;-
+-;0-8;-;0-8
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;0-8;-;0-8
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"othello, world"
+regexps
+"h.*o"
+-;-;-;-
+-;2-11;-;2-11
+"^(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+"^(?:h.*o)"
+-;-;-;-
+-;-;-;-
+"(?:h.*o)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aaaaaaa"
+regexps
+"[^\\s\\S]"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\s\\S])$"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\s\\S])"
+-;-;-;-
+-;-;-;-
+"(?:[^\\s\\S])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aaaaaaa"
+regexps
+"a"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:a)$"
+-;-;-;-
+-;6-7;-;6-7
+strings
+""
+"aaaaaaa"
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-7;0-7;0-7;0-7
+strings
+""
+""
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"a*"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:a*)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:a*)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"xabcdx"
+regexps
+"ab|cd"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+"^(?:ab|cd)"
+-;-;-;-
+-;-;-;-
+"(?:ab|cd)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"cab"
+regexps
+"a"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"cab"
+regexps
+"a*b"
+-;-;-;-
+-;1-3;-;1-3
+"^(?:a*b)$"
+-;-;-;-
+-;-;-;-
+"^(?:a*b)"
+-;-;-;-
+-;-;-;-
+"(?:a*b)$"
+-;-;-;-
+-;1-3;-;1-3
+strings
+""
+"x"
+regexps
+"((((((((((((((((((((x))))))))))))))))))))"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"^(?:((((((((((((((((((((x)))))))))))))))))))))$"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"^(?:((((((((((((((((((((x)))))))))))))))))))))"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+"(?:((((((((((((((((((((x)))))))))))))))))))))$"
+-;-;-;-
+0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1;0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1 0-1
+strings
+""
+"xxxabcdxxx"
+regexps
+"[abcd]"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:[abcd])$"
+-;-;-;-
+-;-;-;-
+"^(?:[abcd])"
+-;-;-;-
+-;-;-;-
+"(?:[abcd])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[^x]"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:[^x])$"
+-;-;-;-
+-;-;-;-
+"^(?:[^x])"
+-;-;-;-
+-;-;-;-
+"(?:[^x])$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[abcd]+"
+-;-;-;-
+-;3-7;-;3-7
+"^(?:[abcd]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[abcd]+)"
+-;-;-;-
+-;-;-;-
+"(?:[abcd]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xxxabcdxxx"
+regexps
+"[^x]+"
+-;-;-;-
+-;3-7;-;3-7
+"^(?:[^x]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^x]+)"
+-;-;-;-
+-;-;-;-
+"(?:[^x]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"(fo|foo)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:(fo|foo))$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:(fo|foo))"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:(fo|foo))$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"(foo|fo)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|fo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|fo))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|fo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"aA"
+regexps
+"aa"
+-;-;-;-
+-;-;-;-
+"^(?:aa)$"
+-;-;-;-
+-;-;-;-
+"^(?:aa)"
+-;-;-;-
+-;-;-;-
+"(?:aa)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"Aa"
+regexps
+"a"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;1-2;-;1-2
+strings
+""
+"A"
+regexps
+"a"
+-;-;-;-
+-;-;-;-
+"^(?:a)$"
+-;-;-;-
+-;-;-;-
+"^(?:a)"
+-;-;-;-
+-;-;-;-
+"(?:a)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc"
+regexps
+"ABC"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)$"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)"
+-;-;-;-
+-;-;-;-
+"(?:ABC)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XABCY"
+regexps
+"abc"
+-;-;-;-
+-;-;-;-
+"^(?:abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:abc)"
+-;-;-;-
+-;-;-;-
+"(?:abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xabcy"
+regexps
+"ABC"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)$"
+-;-;-;-
+-;-;-;-
+"^(?:ABC)"
+-;-;-;-
+-;-;-;-
+"(?:ABC)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"foo|bar|[A-Z]"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:foo|bar|[A-Z])$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:foo|bar|[A-Z])"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:foo|bar|[A-Z])$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"foo"
+regexps
+"^(foo|bar|[A-Z])"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z]))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"bar"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"X"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+strings
+""
+"XY"
+regexps
+"^(foo|bar|[A-Z])$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo|bar|[A-Z])$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo|bar|[A-Z])$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"^(fo|foo)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^(fo|foo)$)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^(fo|foo)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^(fo|foo)$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"fo"
+regexps
+"^^(fo|foo)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^^(fo|foo)$)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^^(fo|foo)$)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^^(fo|foo)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^^(fo|foo)$)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^^(fo|foo)$)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"^$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^^^^^^^^$$$$$$$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^$$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^$$$$$$$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^^^^^^^$$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"$"
+0-0;0-0;0-0;0-0
+-;1-1;-;1-1
+"^(?:$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$)$"
+0-0;0-0;0-0;0-0
+-;1-1;-;1-1
+strings
+""
+"nofoo foo that"
+regexps
+"\\bfoo\\b"
+-;-;-;-
+-;6-9;-;6-9
+"^(?:\\bfoo\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bfoo\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bfoo\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"faoa x"
+regexps
+"a\\b"
+-;-;-;-
+-;3-4;-;3-4
+"^(?:a\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\b)"
+-;-;-;-
+-;-;-;-
+"(?:a\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar x"
+regexps
+"\\bbar"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bbar)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\nbar x"
+regexps
+"\\bbar"
+-;-;-;-
+-;4-7;-;4-7
+"^(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar"
+regexps
+"bar\\b"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\b)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\b)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"foobar\nxxx"
+regexps
+"bar\\b"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\b)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:\\b)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+"foo"
+regexps
+"\\b(foo|bar|[A-Z])"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z]))"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z]))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"X"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-1 0-1;0-1 0-1;0-1 0-1;0-1 0-1
+strings
+""
+"XY"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"foo\n"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"ffoo bbar N x"
+regexps
+"\\b(foo|bar|[A-Z])\\b"
+-;-;-;-
+-;10-11 10-11;-;10-11 10-11
+"^(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b(foo|bar|[A-Z])\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b(foo|bar|[A-Z])\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"\\b(fo|foo)\\b"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:\\b(fo|foo)\\b)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"\\b(fo|foo)\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:\\b(fo|foo)\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"\\b\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:\\b\\b)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+""
+regexps
+"\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\b$"
+-;-;-;-
+-;1-1;-;1-1
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;1-1;-;1-1
+strings
+""
+"y x"
+regexps
+"\\b$"
+-;-;-;-
+-;3-3;-;3-3
+"^(?:\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:\\b$)$"
+-;-;-;-
+-;3-3;-;3-3
+strings
+""
+"x"
+regexps
+"\\b.$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\b.$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"fo"
+regexps
+"^\\b(fo|foo)\\b"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"^(?:^\\b(fo|foo)\\b)"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+"(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-2 0-2;0-2 0-2;0-2 0-2;0-2 0-2
+strings
+""
+"foo"
+regexps
+"^\\b(fo|foo)\\b"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:^\\b(fo|foo)\\b)"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"(?:^\\b(fo|foo)\\b)$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+""
+regexps
+"^\\b"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:^\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\b\\b"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b\\b"
+-;-;-;-
+-;0-0;-;0-0
+"^(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b\\b)"
+-;-;-;-
+-;0-0;-;0-0
+"(?:^\\b\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\b$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\b$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\b.$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^\\b.$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x"
+regexps
+"^\\b.\\b$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.\\b$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^\\b.\\b$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^\\b.\\b$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+""
+regexps
+"^^^^^^^^\\b$$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\b.$$$$$$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^^^^^^^^\\b.$$$$$$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:^^^^^^^^\\b.$$$$$$)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:^^^^^^^^\\b.$$$$$$)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\b$$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\b$$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\b$$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"n foo xfoox that"
+regexps
+"\\Bfoo\\B"
+-;-;-;-
+-;7-10;-;7-10
+"^(?:\\Bfoo\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bfoo\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bfoo\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"faoa x"
+regexps
+"a\\B"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:a\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\B)"
+-;-;-;-
+-;-;-;-
+"(?:a\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"bar x"
+regexps
+"\\Bbar"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\nbar x"
+regexps
+"\\Bbar"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bbar)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bbar)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar"
+regexps
+"bar\\B"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foobar\nxxx"
+regexps
+"bar\\B"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:bar\\B)"
+-;-;-;-
+-;-;-;-
+"(?:bar\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foox"
+regexps
+"(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"^(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;0-3 0-3;-;0-3 0-3
+"(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo\n"
+regexps
+"(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"\\B(foo|bar|[A-Z])"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z]))$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z]))"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z]))$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xXy"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-2 1-2;-;1-2 1-2
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XY"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"XYZ"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-2 1-2;-;1-2 1-2
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abara"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo_"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo\n"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo bar vNx"
+regexps
+"\\B(foo|bar|[A-Z])\\B"
+-;-;-;-
+-;9-10 9-10;-;9-10 9-10
+"^(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|bar|[A-Z])\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|bar|[A-Z])\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfoo"
+regexps
+"\\B(fo|foo)\\B"
+-;-;-;-
+-;1-3 1-3;-;1-3 1-3
+"^(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfooo"
+regexps
+"\\B(foo|fo)\\B"
+-;-;-;-
+-;1-4 1-4;-;1-4 1-4
+"^(?:\\B(foo|fo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(foo|fo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(foo|fo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"y x"
+regexps
+"\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\B.$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B.$)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B.$)"
+-;-;-;-
+-;-;-;-
+"(?:\\B.$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"fo"
+regexps
+"^\\B(fo|foo)\\B"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"^\\B(fo|foo)\\B"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B\\B"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B\\B)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B\\B"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B\\B)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B\\B)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+""
+regexps
+"^\\B$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^\\B$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^\\B$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^\\B$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^\\B$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\B.$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B.$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^\\B.\\B$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.\\B$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\B.\\B$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\B.\\B$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^^^^^^^^\\B$$$$$$$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^^^^^^^^\\B$$$$$$$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\B.$$$$$$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\B.$$$$$$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^^^^^^^^\\B.$$$$$$)"
+-;-;-;-
+-;-;-;-
+"(?:^^^^^^^^\\B.$$$$$$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^^^^^^^^\\B$$$$$$$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^^^^^^^\\B$$$$$$$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^^^^^^^^\\B$$$$$$$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"\\bx\\b"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\bx\\b)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"x>"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"<x"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;1-2;-;1-2
+strings
+""
+"<x>"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"ax"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"«x"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;2-3;-;2-3
+strings
+""
+"x»"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"«x»"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"áxβ"
+regexps
+"\\bx\\b"
+-;-;-;-
+-;2-3;-;2-3
+"^(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\bx\\b)"
+-;-;-;-
+-;-;-;-
+"(?:\\bx\\b)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"axb"
+regexps
+"\\Bx\\B"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"áxβ"
+regexps
+"\\Bx\\B"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\Bx\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\Bx\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+""
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+""
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+0-0;0-0;0-0;0-0
+strings
+""
+"x"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\ny"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"^$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"^$^"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^$^)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:^$^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"x\n\ny"
+regexps
+"$^$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:$^$)"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"(?:$^$)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"foo$bar"
+regexps
+"^(foo\\$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo\\$)$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^(foo\\$)$)"
+-;-;-;-
+-;-;-;-
+"(?:^(foo\\$)$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo$bar"
+regexps
+"(foo\\$)"
+-;-;-;-
+-;0-4 0-4;-;0-4 0-4
+"^(?:(foo\\$))$"
+-;-;-;-
+-;-;-;-
+"^(?:(foo\\$))"
+-;-;-;-
+-;0-4 0-4;-;0-4 0-4
+"(?:(foo\\$))$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc"
+regexps
+"^...$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^...$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^...$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^...$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"本"
+regexps
+"^本$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^本$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^本$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^本$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"日本語"
+regexps
+"^...$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+strings
+""
+".本."
+regexps
+"^...$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+strings
+""
+"本"
+regexps
+"^\\C\\C\\C$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^\\C\\C\\C$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"^(?:^\\C\\C\\C$)"
+-;-;-;-
+0-3;0-3;0-3;0-3
+"(?:^\\C\\C\\C$)$"
+-;-;-;-
+0-3;0-3;0-3;0-3
+strings
+""
+"本"
+regexps
+"^\\C$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\C$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"日本語"
+regexps
+"^\\C\\C\\C$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C\\C\\C$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^\\C\\C\\C$)"
+-;-;-;-
+-;-;-;-
+"(?:^\\C\\C\\C$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"日本語"
+regexps
+"^...$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"^(?:^...$)"
+-;-;-;-
+0-9;0-9;0-9;0-9
+"(?:^...$)$"
+-;-;-;-
+0-9;0-9;0-9;0-9
+strings
+""
+"日本語"
+regexps
+"^.........$"
+-;-;-;-
+-;-;-;-
+"^(?:^.........$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^.........$)"
+-;-;-;-
+-;-;-;-
+"(?:^.........$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+".本."
+regexps
+"^...$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"^(?:^...$)"
+-;-;-;-
+0-5;0-5;0-5;0-5
+"(?:^...$)$"
+-;-;-;-
+0-5;0-5;0-5;0-5
+strings
+""
+".本."
+regexps
+"^.....$"
+-;-;-;-
+-;-;-;-
+"^(?:^.....$)$"
+-;-;-;-
+-;-;-;-
+"^(?:^.....$)"
+-;-;-;-
+-;-;-;-
+"(?:^.....$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"xfooo"
+regexps
+"\\B(fo|foo)\\B"
+-;-;-;-
+-;1-3 1-3;-;1-4 1-4
+"^(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\B(fo|foo)\\B)"
+-;-;-;-
+-;-;-;-
+"(?:\\B(fo|foo)\\B)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"foo"
+regexps
+"(fo|foo)"
+-;-;-;-
+0-3 0-3;0-2 0-2;0-3 0-3;0-3 0-3
+"^(?:(fo|foo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+"^(?:(fo|foo))"
+-;-;-;-
+0-3 0-3;0-2 0-2;0-3 0-3;0-3 0-3
+"(?:(fo|foo))$"
+-;-;-;-
+0-3 0-3;0-3 0-3;0-3 0-3;0-3 0-3
+strings
+""
+"a"
+regexps
+"\\141"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\141)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\141)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\141)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"0"
+regexps
+"\\060"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\060)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\060)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\060)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"00"
+regexps
+"\\0600"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\0600)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\0600)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\0600)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"08"
+regexps
+"\\608"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\608)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\608)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\608)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+""
+regexps
+"\\01"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\01)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\01)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\01)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"8"
+regexps
+"\\018"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\018)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"^(?:\\018)"
+-;-;-;-
+0-2;0-2;0-2;0-2
+"(?:\\018)$"
+-;-;-;-
+0-2;0-2;0-2;0-2
+strings
+""
+"a"
+regexps
+"\\x{61}"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{61})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{61})"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x{61})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"\\x61"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x61)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x61)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x61)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"\\x{00000061}"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{00000061})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:\\x{00000061})"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:\\x{00000061})$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"aαβb"
+regexps
+"\\p{Greek}+"
+-;-;-;-
+-;1-5;-;1-5
+"^(?:\\p{Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{Greek}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{Greek}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aαβb"
+regexps
+"\\P{Greek}+"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\P{Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{Greek}+)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\P{Greek}+)$"
+-;-;-;-
+-;5-6;-;5-6
+strings
+""
+"aαβb"
+regexps
+"\\p{^Greek}+"
+-;-;-;-
+-;0-1;-;0-1
+"^(?:\\p{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^Greek}+)"
+-;-;-;-
+-;0-1;-;0-1
+"(?:\\p{^Greek}+)$"
+-;-;-;-
+-;5-6;-;5-6
+strings
+""
+"aαβb"
+regexps
+"\\P{^Greek}+"
+-;-;-;-
+-;1-5;-;1-5
+"^(?:\\P{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{^Greek}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\P{^Greek}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123"
+regexps
+"[^0-9]+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:[^0-9]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^0-9]+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:[^0-9]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{Nd}+"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:\\p{Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{Nd}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{Nd}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{^Nd}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\p{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^Nd}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\p{^Nd}+)$"
+-;-;-;-
+-;6-22;-;6-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\P{Nd}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\P{Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{Nd}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\P{Nd}+)$"
+-;-;-;-
+-;6-22;-;6-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\P{^Nd}+"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:\\P{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\P{^Nd}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\P{^Nd}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\pN+"
+-;-;-;-
+-;3-22;-;3-22
+"^(?:\\pN+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\pN+)"
+-;-;-;-
+-;-;-;-
+"(?:\\pN+)$"
+-;-;-;-
+-;3-22;-;3-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{N}+"
+-;-;-;-
+-;3-22;-;3-22
+"^(?:\\p{N}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{N}+)"
+-;-;-;-
+-;-;-;-
+"(?:\\p{N}+)$"
+-;-;-;-
+-;3-22;-;3-22
+strings
+""
+"abc123²³¼½¾₀₉"
+regexps
+"\\p{^N}+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:\\p{^N}+)$"
+-;-;-;-
+-;-;-;-
+"^(?:\\p{^N}+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:\\p{^N}+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abc123"
+regexps
+"\\p{Any}+"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"^(?:\\p{Any}+)$"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"^(?:\\p{Any}+)"
+-;-;-;-
+0-6;0-6;0-6;0-6
+"(?:\\p{Any}+)$"
+-;-;-;-
+0-6;0-6;0-6;0-6
+strings
+""
+"@AaB"
+regexps
+"(?i)[@-A]+"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?i)[@-A]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?i)[@-A]+)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?i)[@-A]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aAzZ"
+regexps
+"(?i)[A-Z]+"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"^(?:(?i)[A-Z]+)$"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"^(?:(?i)[A-Z]+)"
+-;-;-;-
+0-4;0-4;0-4;0-4
+"(?:(?i)[A-Z]+)$"
+-;-;-;-
+0-4;0-4;0-4;0-4
+strings
+""
+"Aa\\"
+regexps
+"(?i)[^\\\\]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:(?i)[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?i)[^\\\\]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:(?i)[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"acegikmoqsuwyACEGIKMOQSUWY"
+regexps
+"(?i)[acegikmoqsuwy]+"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"^(?:(?i)[acegikmoqsuwy]+)$"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"^(?:(?i)[acegikmoqsuwy]+)"
+-;-;-;-
+0-26;0-26;0-26;0-26
+"(?:(?i)[acegikmoqsuwy]+)$"
+-;-;-;-
+0-26;0-26;0-26;0-26
+strings
+""
+"@AaB"
+regexps
+"[@-A]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:[@-A]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[@-A]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:[@-A]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aAzZ"
+regexps
+"[A-Z]+"
+-;-;-;-
+-;1-2;-;1-2
+"^(?:[A-Z]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[A-Z]+)"
+-;-;-;-
+-;-;-;-
+"(?:[A-Z]+)$"
+-;-;-;-
+-;3-4;-;3-4
+strings
+""
+"Aa\\"
+regexps
+"[^\\\\]+"
+-;-;-;-
+-;0-2;-;0-2
+"^(?:[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[^\\\\]+)"
+-;-;-;-
+-;0-2;-;0-2
+"(?:[^\\\\]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"acegikmoqsuwyACEGIKMOQSUWY"
+regexps
+"[acegikmoqsuwy]+"
+-;-;-;-
+-;0-13;-;0-13
+"^(?:[acegikmoqsuwy]+)$"
+-;-;-;-
+-;-;-;-
+"^(?:[acegikmoqsuwy]+)"
+-;-;-;-
+-;0-13;-;0-13
+"(?:[acegikmoqsuwy]+)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"^abc"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"^abc"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:^abc)"
+-;-;-;-
+-;-;-;-
+"(?:^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"^[ay]*[bx]+c"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:^[ay]*[bx]+c)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"^[ay]*[bx]+c"
+-;-;-;-
+-;0-4;-;0-4
+"^(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:^[ay]*[bx]+c)"
+-;-;-;-
+-;0-4;-;0-4
+"(?:^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"def$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)"
+-;-;-;-
+-;-;-;-
+"(?:def$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"def$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:def$)"
+-;-;-;-
+-;-;-;-
+"(?:def$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"d[ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:d[ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"d[ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"[dz][ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"[dz][ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)^abc"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"(?m)^abc"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^abc)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)^abc)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)^[ay]*[bx]+c"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^[ay]*[bx]+c)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"aabcdef"
+regexps
+"(?m)^[ay]*[bx]+c"
+-;-;-;-
+-;0-4;-;0-4
+"^(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)^[ay]*[bx]+c)"
+-;-;-;-
+-;0-4;-;0-4
+"(?:(?m)^[ay]*[bx]+c)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)def$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)def$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)def$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)def$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)def$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)d[ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)d[ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)d[ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)d[ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"abcdef"
+regexps
+"(?m)[dz][ex][fy]$"
+-;-;-;-
+-;3-6;-;3-6
+"^(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;3-6;-;3-6
+strings
+""
+"abcdeff"
+regexps
+"(?m)[dz][ex][fy]$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+"^(?:(?m)[dz][ex][fy]$)"
+-;-;-;-
+-;-;-;-
+"(?:(?m)[dz][ex][fy]$)$"
+-;-;-;-
+-;-;-;-
+strings
+""
+"a"
+regexps
+"^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"a"
+regexps
+"^^"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"^(?:^^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+"^(?:^^)"
+0-0;0-0;0-0;0-0
+-;0-0;-;0-0
+"(?:^^)$"
+0-0;0-0;0-0;0-0
+-;-;-;-
+strings
+""
+"a"
+regexps
+"a"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"ab*"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:ab*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:ab*)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:ab*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"a"
+regexps
+"a\\C*"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"^(?:a\\C*)"
+-;-;-;-
+0-1;0-1;0-1;0-1
+"(?:a\\C*)$"
+-;-;-;-
+0-1;0-1;0-1;0-1
+strings
+""
+"baba"
+regexps
+"a\\C*|ba\\C"
+-;-;-;-
+-;0-3;-;0-3
+"^(?:a\\C*|ba\\C)$"
+-;-;-;-
+-;-;-;-
+"^(?:a\\C*|ba\\C)"
+-;-;-;-
+-;0-3;-;0-3
+"(?:a\\C*|ba\\C)$"
+-;-;-;-
+-;1-4;-;1-4
diff --git a/libgo/go/regexp/testdata/repetition.dat b/libgo/go/regexp/testdata/repetition.dat
new file mode 100644
index 00000000000..e6361f51a97
--- /dev/null
+++ b/libgo/go/regexp/testdata/repetition.dat
@@ -0,0 +1,163 @@
+NOTE implicit vs. explicit repetitions : 2009-02-02
+
+# Glenn Fowler <gsf@research.att.com>
+# conforming matches (column 4) must match one of the following BREs
+# NOMATCH
+# (0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)*
+# (0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)*
+# i.e., each 3-tuple has two identical elements and one (?,?)
+
+E ((..)|(.)) NULL NOMATCH
+E ((..)|(.))((..)|(.)) NULL NOMATCH
+E ((..)|(.))((..)|(.))((..)|(.)) NULL NOMATCH
+
+E ((..)|(.)){1} NULL NOMATCH
+E ((..)|(.)){2} NULL NOMATCH
+E ((..)|(.)){3} NULL NOMATCH
+
+E ((..)|(.))* NULL (0,0)
+
+E ((..)|(.)) a (0,1)(0,1)(?,?)(0,1)
+E ((..)|(.))((..)|(.)) a NOMATCH
+E ((..)|(.))((..)|(.))((..)|(.)) a NOMATCH
+
+E ((..)|(.)){1} a (0,1)(0,1)(?,?)(0,1)
+E ((..)|(.)){2} a NOMATCH
+E ((..)|(.)){3} a NOMATCH
+
+E ((..)|(.))* a (0,1)(0,1)(?,?)(0,1)
+
+E ((..)|(.)) aa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aa (0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)
+E ((..)|(.))((..)|(.))((..)|(.)) aa NOMATCH
+
+E ((..)|(.)){1} aa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aa (0,2)(1,2)(?,?)(1,2)
+E ((..)|(.)){3} aa NOMATCH
+
+E ((..)|(.))* aa (0,2)(0,2)(0,2)(?,?)
+
+E ((..)|(.)) aaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aaa (0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)
+E ((..)|(.))((..)|(.))((..)|(.)) aaa (0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3)
+
+E ((..)|(.)){1} aaa (0,2)(0,2)(0,2)(?,?)
+#E ((..)|(.)){2} aaa (0,3)(2,3)(?,?)(2,3)
+E ((..)|(.)){2} aaa (0,3)(2,3)(0,2)(2,3) RE2/Go
+E ((..)|(.)){3} aaa (0,3)(2,3)(?,?)(2,3)
+
+#E ((..)|(.))* aaa (0,3)(2,3)(?,?)(2,3)
+E ((..)|(.))* aaa (0,3)(2,3)(0,2)(2,3) RE2/Go
+
+E ((..)|(.)) aaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E ((..)|(.))((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4)
+
+E ((..)|(.)){1} aaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aaaa (0,4)(2,4)(2,4)(?,?)
+#E ((..)|(.)){3} aaaa (0,4)(3,4)(?,?)(3,4)
+E ((..)|(.)){3} aaaa (0,4)(3,4)(0,2)(3,4) RE2/Go
+
+E ((..)|(.))* aaaa (0,4)(2,4)(2,4)(?,?)
+
+E ((..)|(.)) aaaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E ((..)|(.))((..)|(.))((..)|(.)) aaaaa (0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5)
+
+E ((..)|(.)){1} aaaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aaaaa (0,4)(2,4)(2,4)(?,?)
+#E ((..)|(.)){3} aaaaa (0,5)(4,5)(?,?)(4,5)
+E ((..)|(.)){3} aaaaa (0,5)(4,5)(2,4)(4,5) RE2/Go
+
+#E ((..)|(.))* aaaaa (0,5)(4,5)(?,?)(4,5)
+E ((..)|(.))* aaaaa (0,5)(4,5)(2,4)(4,5) RE2/Go
+
+E ((..)|(.)) aaaaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aaaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E ((..)|(.))((..)|(.))((..)|(.)) aaaaaa (0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?)
+
+E ((..)|(.)){1} aaaaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aaaaaa (0,4)(2,4)(2,4)(?,?)
+E ((..)|(.)){3} aaaaaa (0,6)(4,6)(4,6)(?,?)
+
+E ((..)|(.))* aaaaaa (0,6)(4,6)(4,6)(?,?)
+
+NOTE additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02
+
+# These test a bug in OS X / FreeBSD / NetBSD, and libtree.
+# Linux/GLIBC gets the {8,} and {8,8} wrong.
+
+:HA#100:E X(.?){0,}Y X1234567Y (0,9)(7,8)
+:HA#101:E X(.?){1,}Y X1234567Y (0,9)(7,8)
+:HA#102:E X(.?){2,}Y X1234567Y (0,9)(7,8)
+:HA#103:E X(.?){3,}Y X1234567Y (0,9)(7,8)
+:HA#104:E X(.?){4,}Y X1234567Y (0,9)(7,8)
+:HA#105:E X(.?){5,}Y X1234567Y (0,9)(7,8)
+:HA#106:E X(.?){6,}Y X1234567Y (0,9)(7,8)
+:HA#107:E X(.?){7,}Y X1234567Y (0,9)(7,8)
+:HA#108:E X(.?){8,}Y X1234567Y (0,9)(8,8)
+#:HA#110:E X(.?){0,8}Y X1234567Y (0,9)(7,8)
+:HA#110:E X(.?){0,8}Y X1234567Y (0,9)(8,8) RE2/Go
+#:HA#111:E X(.?){1,8}Y X1234567Y (0,9)(7,8)
+:HA#111:E X(.?){1,8}Y X1234567Y (0,9)(8,8) RE2/Go
+#:HA#112:E X(.?){2,8}Y X1234567Y (0,9)(7,8)
+:HA#112:E X(.?){2,8}Y X1234567Y (0,9)(8,8) RE2/Go
+#:HA#113:E X(.?){3,8}Y X1234567Y (0,9)(7,8)
+:HA#113:E X(.?){3,8}Y X1234567Y (0,9)(8,8) RE2/Go
+#:HA#114:E X(.?){4,8}Y X1234567Y (0,9)(7,8)
+:HA#114:E X(.?){4,8}Y X1234567Y (0,9)(8,8) RE2/Go
+#:HA#115:E X(.?){5,8}Y X1234567Y (0,9)(7,8)
+:HA#115:E X(.?){5,8}Y X1234567Y (0,9)(8,8) RE2/Go
+#:HA#116:E X(.?){6,8}Y X1234567Y (0,9)(7,8)
+:HA#116:E X(.?){6,8}Y X1234567Y (0,9)(8,8) RE2/Go
+#:HA#117:E X(.?){7,8}Y X1234567Y (0,9)(7,8)
+:HA#117:E X(.?){7,8}Y X1234567Y (0,9)(8,8) RE2/Go
+:HA#118:E X(.?){8,8}Y X1234567Y (0,9)(8,8)
+
+# These test a fixed bug in my regex-tdfa that did not keep the expanded
+# form properly grouped, so right association did the wrong thing with
+# these ambiguous patterns (crafted just to test my code when I became
+# suspicious of my implementation). The first subexpression should use
+# "ab" then "a" then "bcd".
+
+# OS X / FreeBSD / NetBSD badly fail many of these, with impossible
+# results like (0,6)(4,5)(6,6).
+
+:HA#260:E (a|ab|c|bcd){0,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#261:E (a|ab|c|bcd){1,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#262:E (a|ab|c|bcd){2,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#263:E (a|ab|c|bcd){3,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#264:E (a|ab|c|bcd){4,}(d*) ababcd NOMATCH
+:HA#265:E (a|ab|c|bcd){0,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#266:E (a|ab|c|bcd){1,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#267:E (a|ab|c|bcd){2,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#268:E (a|ab|c|bcd){3,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#269:E (a|ab|c|bcd){4,10}(d*) ababcd NOMATCH
+:HA#270:E (a|ab|c|bcd)*(d*) ababcd (0,6)(3,6)(6,6)
+:HA#271:E (a|ab|c|bcd)+(d*) ababcd (0,6)(3,6)(6,6)
+
+# The above worked on Linux/GLIBC but the following often fail.
+# They also trip up OS X / FreeBSD / NetBSD:
+
+#:HA#280:E (ab|a|c|bcd){0,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#280:E (ab|a|c|bcd){0,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+#:HA#281:E (ab|a|c|bcd){1,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#281:E (ab|a|c|bcd){1,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+#:HA#282:E (ab|a|c|bcd){2,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#282:E (ab|a|c|bcd){2,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+#:HA#283:E (ab|a|c|bcd){3,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#283:E (ab|a|c|bcd){3,}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+:HA#284:E (ab|a|c|bcd){4,}(d*) ababcd NOMATCH
+#:HA#285:E (ab|a|c|bcd){0,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#285:E (ab|a|c|bcd){0,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+#:HA#286:E (ab|a|c|bcd){1,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#286:E (ab|a|c|bcd){1,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+#:HA#287:E (ab|a|c|bcd){2,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#287:E (ab|a|c|bcd){2,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+#:HA#288:E (ab|a|c|bcd){3,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#288:E (ab|a|c|bcd){3,10}(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+:HA#289:E (ab|a|c|bcd){4,10}(d*) ababcd NOMATCH
+#:HA#290:E (ab|a|c|bcd)*(d*) ababcd (0,6)(3,6)(6,6)
+:HA#290:E (ab|a|c|bcd)*(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
+#:HA#291:E (ab|a|c|bcd)+(d*) ababcd (0,6)(3,6)(6,6)
+:HA#291:E (ab|a|c|bcd)+(d*) ababcd (0,6)(4,5)(5,6) RE2/Go
diff --git a/libgo/go/regexp/testdata/testregex.c b/libgo/go/regexp/testdata/testregex.c
new file mode 100644
index 00000000000..37545d057f8
--- /dev/null
+++ b/libgo/go/regexp/testdata/testregex.c
@@ -0,0 +1,2286 @@
+#pragma prototyped noticed
+
+/*
+ * regex(3) test harness
+ *
+ * build: cc -o testregex testregex.c
+ * help: testregex --man
+ * note: REG_* features are detected by #ifdef; if REG_* are enums
+ * then supply #define REG_foo REG_foo for each enum REG_foo
+ *
+ * Glenn Fowler <gsf@research.att.com>
+ * AT&T Research
+ *
+ * PLEASE: publish your tests so everyone can benefit
+ *
+ * The following license covers testregex.c and all associated test data.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following disclaimer:
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static const char id[] = "\n@(#)$Id: testregex (AT&T Research) 2010-06-10 $\0\n";
+
+#if _PACKAGE_ast
+#include <ast.h>
+#else
+#include <sys/types.h>
+#endif
+
+#include <stdio.h>
+#include <regex.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef __STDC__
+#include <stdlib.h>
+#include <locale.h>
+#endif
+
+#ifndef RE_DUP_MAX
+#define RE_DUP_MAX 32767
+#endif
+
+#if !_PACKAGE_ast
+#undef REG_DISCIPLINE
+#endif
+
+#ifndef REG_DELIMITED
+#undef _REG_subcomp
+#endif
+
+#define TEST_ARE 0x00000001
+#define TEST_BRE 0x00000002
+#define TEST_ERE 0x00000004
+#define TEST_KRE 0x00000008
+#define TEST_LRE 0x00000010
+#define TEST_SRE 0x00000020
+
+#define TEST_EXPAND 0x00000100
+#define TEST_LENIENT 0x00000200
+
+#define TEST_QUERY 0x00000400
+#define TEST_SUB 0x00000800
+#define TEST_UNSPECIFIED 0x00001000
+#define TEST_VERIFY 0x00002000
+#define TEST_AND 0x00004000
+#define TEST_OR 0x00008000
+
+#define TEST_DELIMIT 0x00010000
+#define TEST_OK 0x00020000
+#define TEST_SAME 0x00040000
+
+#define TEST_ACTUAL 0x00100000
+#define TEST_BASELINE 0x00200000
+#define TEST_FAIL 0x00400000
+#define TEST_PASS 0x00800000
+#define TEST_SUMMARY 0x01000000
+
+#define TEST_IGNORE_ERROR 0x02000000
+#define TEST_IGNORE_OVER 0x04000000
+#define TEST_IGNORE_POSITION 0x08000000
+
+#define TEST_CATCH 0x10000000
+#define TEST_VERBOSE 0x20000000
+
+#define TEST_DECOMP 0x40000000
+
+#define TEST_GLOBAL (TEST_ACTUAL|TEST_AND|TEST_BASELINE|TEST_CATCH|TEST_FAIL|TEST_IGNORE_ERROR|TEST_IGNORE_OVER|TEST_IGNORE_POSITION|TEST_OR|TEST_PASS|TEST_SUMMARY|TEST_VERBOSE)
+
+#ifdef REG_DISCIPLINE
+
+
+#include <stk.h>
+
+typedef struct Disc_s
+{
+ regdisc_t disc;
+ int ordinal;
+ Sfio_t* sp;
+} Disc_t;
+
+static void*
+compf(const regex_t* re, const char* xstr, size_t xlen, regdisc_t* disc)
+{
+ Disc_t* dp = (Disc_t*)disc;
+
+ return (void*)((char*)0 + ++dp->ordinal);
+}
+
+static int
+execf(const regex_t* re, void* data, const char* xstr, size_t xlen, const char* sstr, size_t slen, char** snxt, regdisc_t* disc)
+{
+ Disc_t* dp = (Disc_t*)disc;
+
+ sfprintf(dp->sp, "{%-.*s}(%lu:%d)", xlen, xstr, (char*)data - (char*)0, slen);
+ return atoi(xstr);
+}
+
+static void*
+resizef(void* handle, void* data, size_t size)
+{
+ if (!size)
+ return 0;
+ return stkalloc((Sfio_t*)handle, size);
+}
+
+#endif
+
+#ifndef NiL
+#ifdef __STDC__
+#define NiL 0
+#else
+#define NiL (char*)0
+#endif
+#endif
+
+#define H(x) do{if(html)fprintf(stderr,x);}while(0)
+#define T(x) fprintf(stderr,x)
+
+static void
+help(int html)
+{
+H("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\">\n");
+H("<HTML>\n");
+H("<HEAD>\n");
+H("<TITLE>testregex man document</TITLE>\n");
+H("</HEAD>\n");
+H("<BODY bgcolor=white>\n");
+H("<PRE>\n");
+T("NAME\n");
+T(" testregex - regex(3) test harness\n");
+T("\n");
+T("SYNOPSIS\n");
+T(" testregex [ options ]\n");
+T("\n");
+T("DESCRIPTION\n");
+T(" testregex reads regex(3) test specifications, one per line, from the\n");
+T(" standard input and writes one output line for each failed test. A\n");
+T(" summary line is written after all tests are done. Each successful\n");
+T(" test is run again with REG_NOSUB. Unsupported features are noted\n");
+T(" before the first test, and tests requiring these features are\n");
+T(" silently ignored.\n");
+T("\n");
+T("OPTIONS\n");
+T(" -c catch signals and non-terminating calls\n");
+T(" -e ignore error return mismatches\n");
+T(" -h list help on standard error\n");
+T(" -n do not repeat successful tests with regnexec()\n");
+T(" -o ignore match[] overrun errors\n");
+T(" -p ignore negative position mismatches\n");
+T(" -s use stack instead of malloc\n");
+T(" -x do not repeat successful tests with REG_NOSUB\n");
+T(" -v list each test line\n");
+T(" -A list failed test lines with actual answers\n");
+T(" -B list all test lines with actual answers\n");
+T(" -F list failed test lines\n");
+T(" -P list passed test lines\n");
+T(" -S output one summary line\n");
+T("\n");
+T("INPUT FORMAT\n");
+T(" Input lines may be blank, a comment beginning with #, or a test\n");
+T(" specification. A specification is five fields separated by one\n");
+T(" or more tabs. NULL denotes the empty string and NIL denotes the\n");
+T(" 0 pointer.\n");
+T("\n");
+T(" Field 1: the regex(3) flags to apply, one character per REG_feature\n");
+T(" flag. The test is skipped if REG_feature is not supported by the\n");
+T(" implementation. If the first character is not [BEASKLP] then the\n");
+T(" specification is a global control line. One or more of [BEASKLP] may be\n");
+T(" specified; the test will be repeated for each mode.\n");
+T("\n");
+T(" B basic BRE (grep, ed, sed)\n");
+T(" E REG_EXTENDED ERE (egrep)\n");
+T(" A REG_AUGMENTED ARE (egrep with negation)\n");
+T(" S REG_SHELL SRE (sh glob)\n");
+T(" K REG_SHELL|REG_AUGMENTED KRE (ksh glob)\n");
+T(" L REG_LITERAL LRE (fgrep)\n");
+T("\n");
+T(" a REG_LEFT|REG_RIGHT implicit ^...$\n");
+T(" b REG_NOTBOL lhs does not match ^\n");
+T(" c REG_COMMENT ignore space and #...\\n\n");
+T(" d REG_SHELL_DOT explicit leading . match\n");
+T(" e REG_NOTEOL rhs does not match $\n");
+T(" f REG_MULTIPLE multiple \\n separated patterns\n");
+T(" g FNM_LEADING_DIR testfnmatch only -- match until /\n");
+T(" h REG_MULTIREF multiple digit backref\n");
+T(" i REG_ICASE ignore case\n");
+T(" j REG_SPAN . matches \\n\n");
+T(" k REG_ESCAPE \\ to ecape [...] delimiter\n");
+T(" l REG_LEFT implicit ^...\n");
+T(" m REG_MINIMAL minimal match\n");
+T(" n REG_NEWLINE explicit \\n match\n");
+T(" o REG_ENCLOSED (|&) magic inside [@|&](...)\n");
+T(" p REG_SHELL_PATH explicit / match\n");
+T(" q REG_DELIMITED delimited pattern\n");
+T(" r REG_RIGHT implicit ...$\n");
+T(" s REG_SHELL_ESCAPED \\ not special\n");
+T(" t REG_MUSTDELIM all delimiters must be specified\n");
+T(" u standard unspecified behavior -- errors not counted\n");
+T(" v REG_CLASS_ESCAPE \\ special inside [...]\n");
+T(" w REG_NOSUB no subexpression match array\n");
+T(" x REG_LENIENT let some errors slide\n");
+T(" y REG_LEFT regexec() implicit ^...\n");
+T(" z REG_NULL NULL subexpressions ok\n");
+T(" $ expand C \\c escapes in fields 2 and 3\n");
+T(" / field 2 is a regsubcomp() expression\n");
+T(" = field 3 is a regdecomp() expression\n");
+T("\n");
+T(" Field 1 control lines:\n");
+T("\n");
+T(" C set LC_COLLATE and LC_CTYPE to locale in field 2\n");
+T("\n");
+T(" ?test ... output field 5 if passed and != EXPECTED, silent otherwise\n");
+T(" &test ... output field 5 if current and previous passed\n");
+T(" |test ... output field 5 if current passed and previous failed\n");
+T(" ; ... output field 2 if previous failed\n");
+T(" {test ... skip if failed until }\n");
+T(" } end of skip\n");
+T("\n");
+T(" : comment comment copied as output NOTE\n");
+T(" :comment:test :comment: ignored\n");
+T(" N[OTE] comment comment copied as output NOTE\n");
+T(" T[EST] comment comment\n");
+T("\n");
+T(" number use number for nmatch (20 by default)\n");
+T("\n");
+T(" Field 2: the regular expression pattern; SAME uses the pattern from\n");
+T(" the previous specification. RE_DUP_MAX inside {...} expands to the\n");
+T(" value from <limits.h>.\n");
+T("\n");
+T(" Field 3: the string to match. X...{RE_DUP_MAX} expands to RE_DUP_MAX\n");
+T(" copies of X.\n");
+T("\n");
+T(" Field 4: the test outcome. This is either one of the posix error\n");
+T(" codes (with REG_ omitted) or the match array, a list of (m,n)\n");
+T(" entries with m and n being first and last+1 positions in the\n");
+T(" field 3 string, or NULL if REG_NOSUB is in effect and success\n");
+T(" is expected. BADPAT is acceptable in place of any regcomp(3)\n");
+T(" error code. The match[] array is initialized to (-2,-2) before\n");
+T(" each test. All array elements from 0 to nmatch-1 must be specified\n");
+T(" in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
+T(" Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
+T(" matched (?{...}) expression, where x is the text enclosed by {...},\n");
+T(" o is the expression ordinal counting from 1, and n is the length of\n");
+T(" the unmatched portion of the subject string. If x starts with a\n");
+T(" number then that is the return value of re_execf(), otherwise 0 is\n");
+T(" returned. RE_DUP_MAX[-+]N expands to the <limits.h> value -+N.\n");
+T("\n");
+T(" Field 5: optional comment appended to the report.\n");
+T("\n");
+T("CAVEAT\n");
+T(" If a regex implementation misbehaves with memory then all bets are off.\n");
+T("\n");
+T("CONTRIBUTORS\n");
+T(" Glenn Fowler gsf@research.att.com (ksh strmatch, regex extensions)\n");
+T(" David Korn dgk@research.att.com (ksh glob matcher)\n");
+T(" Doug McIlroy mcilroy@dartmouth.edu (ast regex/testre in C++)\n");
+T(" Tom Lord lord@regexps.com (rx tests)\n");
+T(" Henry Spencer henry@zoo.toronto.edu (original public regex)\n");
+T(" Andrew Hume andrew@research.att.com (gre tests)\n");
+T(" John Maddock John_Maddock@compuserve.com (regex++ tests)\n");
+T(" Philip Hazel ph10@cam.ac.uk (pcre tests)\n");
+T(" Ville Laurikari vl@iki.fi (libtre tests)\n");
+H("</PRE>\n");
+H("</BODY>\n");
+H("</HTML>\n");
+}
+
+#ifndef elementsof
+#define elementsof(x) (sizeof(x)/sizeof(x[0]))
+#endif
+
+#ifndef streq
+#define streq(a,b) (*(a)==*(b)&&!strcmp(a,b))
+#endif
+
+#define HUNG 2
+#define NOTEST (~0)
+
+#ifndef REG_TEST_DEFAULT
+#define REG_TEST_DEFAULT 0
+#endif
+
+#ifndef REG_EXEC_DEFAULT
+#define REG_EXEC_DEFAULT 0
+#endif
+
+static const char* unsupported[] =
+{
+ "BASIC",
+#ifndef REG_EXTENDED
+ "EXTENDED",
+#endif
+#ifndef REG_AUGMENTED
+ "AUGMENTED",
+#endif
+#ifndef REG_SHELL
+ "SHELL",
+#endif
+
+#ifndef REG_CLASS_ESCAPE
+ "CLASS_ESCAPE",
+#endif
+#ifndef REG_COMMENT
+ "COMMENT",
+#endif
+#ifndef REG_DELIMITED
+ "DELIMITED",
+#endif
+#ifndef REG_DISCIPLINE
+ "DISCIPLINE",
+#endif
+#ifndef REG_ESCAPE
+ "ESCAPE",
+#endif
+#ifndef REG_ICASE
+ "ICASE",
+#endif
+#ifndef REG_LEFT
+ "LEFT",
+#endif
+#ifndef REG_LENIENT
+ "LENIENT",
+#endif
+#ifndef REG_LITERAL
+ "LITERAL",
+#endif
+#ifndef REG_MINIMAL
+ "MINIMAL",
+#endif
+#ifndef REG_MULTIPLE
+ "MULTIPLE",
+#endif
+#ifndef REG_MULTIREF
+ "MULTIREF",
+#endif
+#ifndef REG_MUSTDELIM
+ "MUSTDELIM",
+#endif
+#ifndef REG_NEWLINE
+ "NEWLINE",
+#endif
+#ifndef REG_NOTBOL
+ "NOTBOL",
+#endif
+#ifndef REG_NOTEOL
+ "NOTEOL",
+#endif
+#ifndef REG_NULL
+ "NULL",
+#endif
+#ifndef REG_RIGHT
+ "RIGHT",
+#endif
+#ifndef REG_SHELL_DOT
+ "SHELL_DOT",
+#endif
+#ifndef REG_SHELL_ESCAPED
+ "SHELL_ESCAPED",
+#endif
+#ifndef REG_SHELL_GROUP
+ "SHELL_GROUP",
+#endif
+#ifndef REG_SHELL_PATH
+ "SHELL_PATH",
+#endif
+#ifndef REG_SPAN
+ "SPAN",
+#endif
+#if REG_NOSUB & REG_TEST_DEFAULT
+ "SUBMATCH",
+#endif
+#if !_REG_nexec
+ "regnexec",
+#endif
+#if !_REG_subcomp
+ "regsubcomp",
+#endif
+#if !_REG_decomp
+ "redecomp",
+#endif
+ 0
+};
+
+#ifndef REG_CLASS_ESCAPE
+#define REG_CLASS_ESCAPE NOTEST
+#endif
+#ifndef REG_COMMENT
+#define REG_COMMENT NOTEST
+#endif
+#ifndef REG_DELIMITED
+#define REG_DELIMITED NOTEST
+#endif
+#ifndef REG_ESCAPE
+#define REG_ESCAPE NOTEST
+#endif
+#ifndef REG_ICASE
+#define REG_ICASE NOTEST
+#endif
+#ifndef REG_LEFT
+#define REG_LEFT NOTEST
+#endif
+#ifndef REG_LENIENT
+#define REG_LENIENT 0
+#endif
+#ifndef REG_MINIMAL
+#define REG_MINIMAL NOTEST
+#endif
+#ifndef REG_MULTIPLE
+#define REG_MULTIPLE NOTEST
+#endif
+#ifndef REG_MULTIREF
+#define REG_MULTIREF NOTEST
+#endif
+#ifndef REG_MUSTDELIM
+#define REG_MUSTDELIM NOTEST
+#endif
+#ifndef REG_NEWLINE
+#define REG_NEWLINE NOTEST
+#endif
+#ifndef REG_NOTBOL
+#define REG_NOTBOL NOTEST
+#endif
+#ifndef REG_NOTEOL
+#define REG_NOTEOL NOTEST
+#endif
+#ifndef REG_NULL
+#define REG_NULL NOTEST
+#endif
+#ifndef REG_RIGHT
+#define REG_RIGHT NOTEST
+#endif
+#ifndef REG_SHELL_DOT
+#define REG_SHELL_DOT NOTEST
+#endif
+#ifndef REG_SHELL_ESCAPED
+#define REG_SHELL_ESCAPED NOTEST
+#endif
+#ifndef REG_SHELL_GROUP
+#define REG_SHELL_GROUP NOTEST
+#endif
+#ifndef REG_SHELL_PATH
+#define REG_SHELL_PATH NOTEST
+#endif
+#ifndef REG_SPAN
+#define REG_SPAN NOTEST
+#endif
+
+#define REG_UNKNOWN (-1)
+
+#ifndef REG_ENEWLINE
+#define REG_ENEWLINE (REG_UNKNOWN-1)
+#endif
+#ifndef REG_ENULL
+#ifndef REG_EMPTY
+#define REG_ENULL (REG_UNKNOWN-2)
+#else
+#define REG_ENULL REG_EMPTY
+#endif
+#endif
+#ifndef REG_ECOUNT
+#define REG_ECOUNT (REG_UNKNOWN-3)
+#endif
+#ifndef REG_BADESC
+#define REG_BADESC (REG_UNKNOWN-4)
+#endif
+#ifndef REG_EMEM
+#define REG_EMEM (REG_UNKNOWN-5)
+#endif
+#ifndef REG_EHUNG
+#define REG_EHUNG (REG_UNKNOWN-6)
+#endif
+#ifndef REG_EBUS
+#define REG_EBUS (REG_UNKNOWN-7)
+#endif
+#ifndef REG_EFAULT
+#define REG_EFAULT (REG_UNKNOWN-8)
+#endif
+#ifndef REG_EFLAGS
+#define REG_EFLAGS (REG_UNKNOWN-9)
+#endif
+#ifndef REG_EDELIM
+#define REG_EDELIM (REG_UNKNOWN-9)
+#endif
+
+static const struct { int code; char* name; } codes[] =
+{
+ REG_UNKNOWN, "UNKNOWN",
+ REG_NOMATCH, "NOMATCH",
+ REG_BADPAT, "BADPAT",
+ REG_ECOLLATE, "ECOLLATE",
+ REG_ECTYPE, "ECTYPE",
+ REG_EESCAPE, "EESCAPE",
+ REG_ESUBREG, "ESUBREG",
+ REG_EBRACK, "EBRACK",
+ REG_EPAREN, "EPAREN",
+ REG_EBRACE, "EBRACE",
+ REG_BADBR, "BADBR",
+ REG_ERANGE, "ERANGE",
+ REG_ESPACE, "ESPACE",
+ REG_BADRPT, "BADRPT",
+ REG_ENEWLINE, "ENEWLINE",
+ REG_ENULL, "ENULL",
+ REG_ECOUNT, "ECOUNT",
+ REG_BADESC, "BADESC",
+ REG_EMEM, "EMEM",
+ REG_EHUNG, "EHUNG",
+ REG_EBUS, "EBUS",
+ REG_EFAULT, "EFAULT",
+ REG_EFLAGS, "EFLAGS",
+ REG_EDELIM, "EDELIM",
+};
+
+static struct
+{
+ regmatch_t NOMATCH;
+ int errors;
+ int extracted;
+ int ignored;
+ int lineno;
+ int passed;
+ int signals;
+ int unspecified;
+ int verify;
+ int warnings;
+ char* file;
+ char* stack;
+ char* which;
+ jmp_buf gotcha;
+#ifdef REG_DISCIPLINE
+ Disc_t disc;
+#endif
+} state;
+
+static void
+quote(char* s, int len, unsigned long test)
+{
+ unsigned char* u = (unsigned char*)s;
+ unsigned char* e;
+ int c;
+#ifdef MB_CUR_MAX
+ int w;
+#endif
+
+ if (!u)
+ printf("NIL");
+ else if (!*u && len <= 1)
+ printf("NULL");
+ else if (test & TEST_EXPAND)
+ {
+ if (len < 0)
+ len = strlen((char*)u);
+ e = u + len;
+ if (test & TEST_DELIMIT)
+ printf("\"");
+ while (u < e)
+ switch (c = *u++)
+ {
+ case '\\':
+ printf("\\\\");
+ break;
+ case '"':
+ if (test & TEST_DELIMIT)
+ printf("\\\"");
+ else
+ printf("\"");
+ break;
+ case '\a':
+ printf("\\a");
+ break;
+ case '\b':
+ printf("\\b");
+ break;
+ case 033:
+ printf("\\e");
+ break;
+ case '\f':
+ printf("\\f");
+ break;
+ case '\n':
+ printf("\\n");
+ break;
+ case '\r':
+ printf("\\r");
+ break;
+ case '\t':
+ printf("\\t");
+ break;
+ case '\v':
+ printf("\\v");
+ break;
+ default:
+#ifdef MB_CUR_MAX
+ s = (char*)u - 1;
+ if ((w = mblen(s, (char*)e - s)) > 1)
+ {
+ u += w - 1;
+ fwrite(s, 1, w, stdout);
+ }
+ else
+#endif
+ if (!iscntrl(c) && isprint(c))
+ putchar(c);
+ else
+ printf("\\x%02x", c);
+ break;
+ }
+ if (test & TEST_DELIMIT)
+ printf("\"");
+ }
+ else
+ printf("%s", s);
+}
+
+static void
+report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test)
+{
+ if (state.file)
+ printf("%s:", state.file);
+ printf("%d:", state.lineno);
+ if (re)
+ {
+ printf(" ");
+ quote(re, -1, test|TEST_DELIMIT);
+ if (s)
+ {
+ printf(" versus ");
+ quote(s, len, test|TEST_DELIMIT);
+ }
+ }
+ if (test & TEST_UNSPECIFIED)
+ {
+ state.unspecified++;
+ printf(" unspecified behavior");
+ }
+ else
+ state.errors++;
+ if (state.which)
+ printf(" %s", state.which);
+ if (flags & REG_NOSUB)
+ printf(" NOSUB");
+ if (fun)
+ printf(" %s", fun);
+ if (comment[strlen(comment)-1] == '\n')
+ printf(" %s", comment);
+ else
+ {
+ printf(" %s: ", comment);
+ if (msg)
+ printf("%s: ", msg);
+ }
+}
+
+static void
+error(regex_t* preg, int code)
+{
+ char* msg;
+ char buf[256];
+
+ switch (code)
+ {
+ case REG_EBUS:
+ msg = "bus error";
+ break;
+ case REG_EFAULT:
+ msg = "memory fault";
+ break;
+ case REG_EHUNG:
+ msg = "did not terminate";
+ break;
+ default:
+ regerror(code, preg, msg = buf, sizeof buf);
+ break;
+ }
+ printf("%s\n", msg);
+}
+
+static void
+bad(char* comment, char* re, char* s, int len, unsigned long test)
+{
+ printf("bad test case ");
+ report(comment, NiL, re, s, len, NiL, 0, test);
+ exit(1);
+}
+
+static int
+escape(char* s)
+{
+ char* b;
+ char* t;
+ char* q;
+ char* e;
+ int c;
+
+ for (b = t = s; *t = *s; s++, t++)
+ if (*s == '\\')
+ switch (*++s)
+ {
+ case '\\':
+ break;
+ case 'a':
+ *t = '\a';
+ break;
+ case 'b':
+ *t = '\b';
+ break;
+ case 'c':
+ if (*t = *++s)
+ *t &= 037;
+ else
+ s--;
+ break;
+ case 'e':
+ case 'E':
+ *t = 033;
+ break;
+ case 'f':
+ *t = '\f';
+ break;
+ case 'n':
+ *t = '\n';
+ break;
+ case 'r':
+ *t = '\r';
+ break;
+ case 's':
+ *t = ' ';
+ break;
+ case 't':
+ *t = '\t';
+ break;
+ case 'v':
+ *t = '\v';
+ break;
+ case 'u':
+ case 'x':
+ c = 0;
+ q = c == 'u' ? (s + 5) : (char*)0;
+ e = s + 1;
+ while (!e || !q || s < q)
+ {
+ switch (*++s)
+ {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ c = (c << 4) + *s - 'a' + 10;
+ continue;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ c = (c << 4) + *s - 'A' + 10;
+ continue;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ c = (c << 4) + *s - '0';
+ continue;
+ case '{':
+ case '[':
+ if (s != e)
+ {
+ s--;
+ break;
+ }
+ e = 0;
+ continue;
+ case '}':
+ case ']':
+ if (e)
+ s--;
+ break;
+ default:
+ s--;
+ break;
+ }
+ break;
+ }
+ *t = c;
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c = *s - '0';
+ q = s + 2;
+ while (s < q)
+ {
+ switch (*++s)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ c = (c << 3) + *s - '0';
+ break;
+ default:
+ q = --s;
+ break;
+ }
+ }
+ *t = c;
+ break;
+ default:
+ *(s + 1) = 0;
+ bad("invalid C \\ escape\n", s - 1, NiL, 0, 0);
+ }
+ return t - b;
+}
+
+static void
+matchoffprint(int off)
+{
+ switch (off)
+ {
+ case -2:
+ printf("X");
+ break;
+ case -1:
+ printf("?");
+ break;
+ default:
+ printf("%d", off);
+ break;
+ }
+}
+
+static void
+matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test)
+{
+ int i;
+
+ for (; nmatch > nsub + 1; nmatch--)
+ if ((match[nmatch-1].rm_so != -1 || match[nmatch-1].rm_eo != -1) && (!(test & TEST_IGNORE_POSITION) || match[nmatch-1].rm_so >= 0 && match[nmatch-1].rm_eo >= 0))
+ break;
+ for (i = 0; i < nmatch; i++)
+ {
+ printf("(");
+ matchoffprint(match[i].rm_so);
+ printf(",");
+ matchoffprint(match[i].rm_eo);
+ printf(")");
+ }
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE)))
+ {
+ if (ans)
+ printf(" expected: %s", ans);
+ printf("\n");
+ }
+}
+
+static int
+matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test)
+{
+ char* p;
+ int i;
+ int m;
+ int n;
+
+ if (streq(ans, "OK"))
+ return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY);
+ for (i = 0, p = ans; i < nmatch && *p; i++)
+ {
+ if (*p == '{')
+ {
+#ifdef REG_DISCIPLINE
+ char* x;
+
+ if (!(x = sfstruse(state.disc.sp)))
+ bad("out of space [discipline string]\n", NiL, NiL, 0, 0);
+ if (strcmp(p, x))
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ return 0;
+ report("callout failed", NiL, re, s, len, NiL, flags, test);
+ quote(p, -1, test);
+ printf(" expected, ");
+ quote(x, -1, test);
+ printf(" returned\n");
+ }
+#endif
+ break;
+ }
+ if (*p++ != '(')
+ bad("improper answer\n", re, s, -1, test);
+ if (*p == '?')
+ {
+ m = -1;
+ p++;
+ }
+ else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
+ {
+ m = RE_DUP_MAX;
+ p += 10;
+ if (*p == '+' || *p == '-')
+ m += strtol(p, &p, 10);
+ }
+ else
+ m = strtol(p, &p, 10);
+ if (*p++ != ',')
+ bad("improper answer\n", re, s, -1, test);
+ if (*p == '?')
+ {
+ n = -1;
+ p++;
+ }
+ else if (*p == 'R' && !memcmp(p, "RE_DUP_MAX", 10))
+ {
+ n = RE_DUP_MAX;
+ p += 10;
+ if (*p == '+' || *p == '-')
+ n += strtol(p, &p, 10);
+ }
+ else
+ n = strtol(p, &p, 10);
+ if (*p++ != ')')
+ bad("improper answer\n", re, s, -1, test);
+ if (m!=match[i].rm_so || n!=match[i].rm_eo)
+ {
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
+ {
+ report("failed: match was", NiL, re, s, len, NiL, flags, test);
+ matchprint(match, nmatch, nsub, ans, test);
+ }
+ return 0;
+ }
+ }
+ for (; i < nmatch; i++)
+ {
+ if (match[i].rm_so!=-1 || match[i].rm_eo!=-1)
+ {
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_VERIFY)))
+ {
+ if ((test & TEST_IGNORE_POSITION) && (match[i].rm_so<0 || match[i].rm_eo<0))
+ {
+ state.ignored++;
+ return 0;
+ }
+ if (!(test & TEST_SUMMARY))
+ {
+ report("failed: match was", NiL, re, s, len, NiL, flags, test);
+ matchprint(match, nmatch, nsub, ans, test);
+ }
+ }
+ return 0;
+ }
+ }
+ if (!(test & TEST_IGNORE_OVER) && match[nmatch].rm_so != state.NOMATCH.rm_so)
+ {
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)))
+ {
+ report("failed: overran match array", NiL, re, s, len, NiL, flags, test);
+ matchprint(match, nmatch + 1, nsub, NiL, test);
+ }
+ return 0;
+ }
+ return 1;
+}
+
+static void
+sigunblock(int s)
+{
+#ifdef SIG_SETMASK
+ int op;
+ sigset_t mask;
+
+ sigemptyset(&mask);
+ if (s)
+ {
+ sigaddset(&mask, s);
+ op = SIG_UNBLOCK;
+ }
+ else op = SIG_SETMASK;
+ sigprocmask(op, &mask, NiL);
+#else
+#ifdef sigmask
+ sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L);
+#endif
+#endif
+}
+
+static void
+gotcha(int sig)
+{
+ int ret;
+
+ signal(sig, gotcha);
+ alarm(0);
+ state.signals++;
+ switch (sig)
+ {
+ case SIGALRM:
+ ret = REG_EHUNG;
+ break;
+ case SIGBUS:
+ ret = REG_EBUS;
+ break;
+ default:
+ ret = REG_EFAULT;
+ break;
+ }
+ sigunblock(sig);
+ longjmp(state.gotcha, ret);
+}
+
+static char*
+getline(FILE* fp)
+{
+ static char buf[32 * 1024];
+
+ register char* s = buf;
+ register char* e = &buf[sizeof(buf)];
+ register char* b;
+
+ for (;;)
+ {
+ if (!(b = fgets(s, e - s, fp)))
+ return 0;
+ state.lineno++;
+ s += strlen(s);
+ if (s == b || *--s != '\n' || s == b || *(s - 1) != '\\')
+ {
+ *s = 0;
+ break;
+ }
+ s--;
+ }
+ return buf;
+}
+
+static unsigned long
+note(unsigned long level, char* msg, unsigned long skip, unsigned long test)
+{
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)) && !skip)
+ {
+ printf("NOTE\t");
+ if (msg)
+ printf("%s: ", msg);
+ printf("skipping lines %d", state.lineno);
+ }
+ return skip | level;
+}
+
+#define TABS(n) &ts[7-((n)&7)]
+
+static char ts[] = "\t\t\t\t\t\t\t";
+
+static unsigned long
+extract(int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
+{
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_OK|TEST_PASS|TEST_SUMMARY))
+ {
+ state.extracted = 1;
+ if (test & TEST_OK)
+ {
+ state.passed++;
+ if ((test & TEST_VERIFY) && !(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+ {
+ if (msg && strcmp(msg, "EXPECTED"))
+ printf("NOTE\t%s\n", msg);
+ return skip;
+ }
+ test &= ~(TEST_PASS|TEST_QUERY);
+ }
+ if (test & (TEST_QUERY|TEST_VERIFY))
+ {
+ if (test & TEST_BASELINE)
+ test &= ~(TEST_BASELINE|TEST_PASS);
+ else
+ test |= TEST_PASS;
+ skip |= level;
+ }
+ if (!(test & TEST_OK))
+ {
+ if (test & TEST_UNSPECIFIED)
+ state.unspecified++;
+ else
+ state.errors++;
+ }
+ if (test & (TEST_PASS|TEST_SUMMARY))
+ return skip;
+ test &= ~TEST_DELIMIT;
+ printf("%s%s", spec, TABS(*tabs++));
+ if ((test & (TEST_BASELINE|TEST_SAME)) == (TEST_BASELINE|TEST_SAME))
+ printf("SAME");
+ else
+ quote(re, -1, test);
+ printf("%s", TABS(*tabs++));
+ quote(s, -1, test);
+ printf("%s", TABS(*tabs++));
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE)) || !accept && !match)
+ printf("%s", ans);
+ else if (accept)
+ printf("%s", accept);
+ else
+ matchprint(match, nmatch, nsub, NiL, test);
+ if (msg)
+ printf("%s%s", TABS(*tabs++), msg);
+ putchar('\n');
+ }
+ else if (test & TEST_QUERY)
+ skip = note(level, msg, skip, test);
+ else if (test & TEST_VERIFY)
+ state.extracted = 1;
+ return skip;
+}
+
+static int
+catchfree(regex_t* preg, int flags, int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test)
+{
+ int eret;
+
+ if (!(test & TEST_CATCH))
+ {
+ regfree(preg);
+ eret = 0;
+ }
+ else if (!(eret = setjmp(state.gotcha)))
+ {
+ alarm(HUNG);
+ regfree(preg);
+ alarm(0);
+ }
+ else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ extract(tabs, spec, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+ else
+ {
+ report("failed", "regfree", re, NiL, -1, msg, flags, test);
+ error(preg, eret);
+ }
+ return eret;
+}
+
+static char*
+expand(char* os, char* ot)
+{
+ char* s = os;
+ char* t;
+ int n = 0;
+ int r;
+ long m;
+
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case '{':
+ n++;
+ continue;
+ case '}':
+ n--;
+ continue;
+ case 'R':
+ if (n == 1 && !memcmp(s, "E_DUP_MAX", 9))
+ {
+ s--;
+ for (t = ot; os < s; *t++ = *os++);
+ r = ((t - ot) >= 5 && t[-1] == '{' && t[-2] == '.' && t[-3] == '.' && t[-4] == '.') ? t[-5] : 0;
+ os = ot;
+ m = RE_DUP_MAX;
+ if (*(s += 10) == '+' || *s == '-')
+ m += strtol(s, &s, 10);
+ if (r)
+ {
+ t -= 5;
+ while (m-- > 0)
+ *t++ = r;
+ while (*s && *s++ != '}');
+ }
+ else
+ t += snprintf(t, 32, "%ld", m);
+ while (*t = *s++)
+ t++;
+ break;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ return os;
+}
+
+int
+main(int argc, char** argv)
+{
+ int flags;
+ int cflags;
+ int eflags;
+ int nmatch;
+ int nexec;
+ int nstr;
+ int cret;
+ int eret;
+ int nsub;
+ int i;
+ int j;
+ int expected;
+ int got;
+ int locale;
+ int subunitlen;
+ int testno;
+ unsigned long level;
+ unsigned long skip;
+ char* p;
+ char* line;
+ char* spec;
+ char* re;
+ char* s;
+ char* ans;
+ char* msg;
+ char* fun;
+ char* ppat;
+ char* subunit;
+ char* version;
+ char* field[6];
+ char* delim[6];
+ FILE* fp;
+ int tabs[6];
+ char unit[64];
+ regmatch_t match[100];
+ regex_t preg;
+
+ static char pat[32 * 1024];
+ static char patbuf[32 * 1024];
+ static char strbuf[32 * 1024];
+
+ int nonosub = REG_NOSUB == 0;
+ int nonexec = 0;
+
+ unsigned long test = 0;
+
+ static char* filter[] = { "-", 0 };
+
+ state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2;
+ p = unit;
+ version = (char*)id + 10;
+ while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p))
+ p++;
+ *p = 0;
+ while ((p = *++argv) && *p == '-')
+ for (;;)
+ {
+ switch (*++p)
+ {
+ case 0:
+ break;
+ case 'c':
+ test |= TEST_CATCH;
+ continue;
+ case 'e':
+ test |= TEST_IGNORE_ERROR;
+ continue;
+ case 'h':
+ case '?':
+ help(0);
+ return 2;
+ case '-':
+ help(p[1] == 'h');
+ return 2;
+ case 'n':
+ nonexec = 1;
+ continue;
+ case 'o':
+ test |= TEST_IGNORE_OVER;
+ continue;
+ case 'p':
+ test |= TEST_IGNORE_POSITION;
+ continue;
+ case 's':
+#ifdef REG_DISCIPLINE
+ if (!(state.stack = stkalloc(stkstd, 0)))
+ fprintf(stderr, "%s: out of space [stack]", unit);
+ state.disc.disc.re_resizef = resizef;
+ state.disc.disc.re_resizehandle = (void*)stkstd;
+#endif
+ continue;
+ case 'x':
+ nonosub = 1;
+ continue;
+ case 'v':
+ test |= TEST_VERBOSE;
+ continue;
+ case 'A':
+ test |= TEST_ACTUAL;
+ continue;
+ case 'B':
+ test |= TEST_BASELINE;
+ continue;
+ case 'F':
+ test |= TEST_FAIL;
+ continue;
+ case 'P':
+ test |= TEST_PASS;
+ continue;
+ case 'S':
+ test |= TEST_SUMMARY;
+ continue;
+ default:
+ fprintf(stderr, "%s: %c: invalid option\n", unit, *p);
+ return 2;
+ }
+ break;
+ }
+ if (!*argv)
+ argv = filter;
+ locale = 0;
+ while (state.file = *argv++)
+ {
+ if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0"))
+ {
+ state.file = 0;
+ fp = stdin;
+ }
+ else if (!(fp = fopen(state.file, "r")))
+ {
+ fprintf(stderr, "%s: %s: cannot read\n", unit, state.file);
+ return 2;
+ }
+ testno = state.errors = state.ignored = state.lineno = state.passed =
+ state.signals = state.unspecified = state.warnings = 0;
+ skip = 0;
+ level = 1;
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+ {
+ printf("TEST\t%s ", unit);
+ if (s = state.file)
+ {
+ subunit = p = 0;
+ for (;;)
+ {
+ switch (*s++)
+ {
+ case 0:
+ break;
+ case '/':
+ subunit = s;
+ continue;
+ case '.':
+ p = s - 1;
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ if (!subunit)
+ subunit = state.file;
+ if (p < subunit)
+ p = s - 1;
+ subunitlen = p - subunit;
+ printf("%-.*s ", subunitlen, subunit);
+ }
+ else
+ subunit = 0;
+ for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++)
+ putchar(*s);
+ if (test & TEST_CATCH)
+ printf(", catch");
+ if (test & TEST_IGNORE_ERROR)
+ printf(", ignore error code mismatches");
+ if (test & TEST_IGNORE_POSITION)
+ printf(", ignore negative position mismatches");
+#ifdef REG_DISCIPLINE
+ if (state.stack)
+ printf(", stack");
+#endif
+ if (test & TEST_VERBOSE)
+ printf(", verbose");
+ printf("\n");
+#ifdef REG_VERSIONID
+ if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0)
+ s = pat;
+ else
+#endif
+#ifdef REG_TEST_VERSION
+ s = REG_TEST_VERSION;
+#else
+ s = "regex";
+#endif
+ printf("NOTE\t%s\n", s);
+ if (elementsof(unsupported) > 1)
+ {
+#if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED)
+ i = 0;
+#else
+ i = REG_EXTENDED != 0;
+#endif
+ for (got = 0; i < elementsof(unsupported) - 1; i++)
+ {
+ if (!got)
+ {
+ got = 1;
+ printf("NOTE\tunsupported: %s", unsupported[i]);
+ }
+ else
+ printf(",%s", unsupported[i]);
+ }
+ if (got)
+ printf("\n");
+ }
+ }
+#ifdef REG_DISCIPLINE
+ state.disc.disc.re_version = REG_VERSION;
+ state.disc.disc.re_compf = compf;
+ state.disc.disc.re_execf = execf;
+ if (!(state.disc.sp = sfstropen()))
+ bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0);
+ preg.re_disc = &state.disc.disc;
+#endif
+ if (test & TEST_CATCH)
+ {
+ signal(SIGALRM, gotcha);
+ signal(SIGBUS, gotcha);
+ signal(SIGSEGV, gotcha);
+ }
+ while (p = getline(fp))
+ {
+
+ /* parse: */
+
+ line = p;
+ if (*p == ':' && !isspace(*(p + 1)))
+ {
+ while (*++p && *p != ':');
+ if (!*p++)
+ {
+ if (test & TEST_BASELINE)
+ printf("%s\n", line);
+ continue;
+ }
+ }
+ while (isspace(*p))
+ p++;
+ if (*p == 0 || *p == '#' || *p == 'T')
+ {
+ if (test & TEST_BASELINE)
+ printf("%s\n", line);
+ continue;
+ }
+ if (*p == ':' || *p == 'N')
+ {
+ if (test & TEST_BASELINE)
+ printf("%s\n", line);
+ else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+ {
+ while (*++p && !isspace(*p));
+ while (isspace(*p))
+ p++;
+ printf("NOTE %s\n", p);
+ }
+ continue;
+ }
+ j = 0;
+ i = 0;
+ field[i++] = p;
+ for (;;)
+ {
+ switch (*p++)
+ {
+ case 0:
+ p--;
+ j = 0;
+ goto checkfield;
+ case '\t':
+ *(delim[i] = p - 1) = 0;
+ j = 1;
+ checkfield:
+ s = field[i - 1];
+ if (streq(s, "NIL"))
+ field[i - 1] = 0;
+ else if (streq(s, "NULL"))
+ *s = 0;
+ while (*p == '\t')
+ {
+ p++;
+ j++;
+ }
+ tabs[i - 1] = j;
+ if (!*p)
+ break;
+ if (i >= elementsof(field))
+ bad("too many fields\n", NiL, NiL, 0, 0);
+ field[i++] = p;
+ /*FALLTHROUGH*/
+ default:
+ continue;
+ }
+ break;
+ }
+ if (!(spec = field[0]))
+ bad("NIL spec\n", NiL, NiL, 0, 0);
+
+ /* interpret: */
+
+ cflags = REG_TEST_DEFAULT;
+ eflags = REG_EXEC_DEFAULT;
+ test &= TEST_GLOBAL;
+ state.extracted = 0;
+ nmatch = 20;
+ nsub = -1;
+ for (p = spec; *p; p++)
+ {
+ if (isdigit(*p))
+ {
+ nmatch = strtol(p, &p, 10);
+ if (nmatch >= elementsof(match))
+ bad("nmatch must be < 100\n", NiL, NiL, 0, 0);
+ p--;
+ continue;
+ }
+ switch (*p)
+ {
+ case 'A':
+ test |= TEST_ARE;
+ continue;
+ case 'B':
+ test |= TEST_BRE;
+ continue;
+ case 'C':
+ if (!(test & TEST_QUERY) && !(skip & level))
+ bad("locale must be nested\n", NiL, NiL, 0, 0);
+ test &= ~TEST_QUERY;
+ if (locale)
+ bad("locale nesting not supported\n", NiL, NiL, 0, 0);
+ if (i != 2)
+ bad("locale field expected\n", NiL, NiL, 0, 0);
+ if (!(skip & level))
+ {
+#if defined(LC_COLLATE) && defined(LC_CTYPE)
+ s = field[1];
+ if (!s || streq(s, "POSIX"))
+ s = "C";
+ if ((ans = setlocale(LC_COLLATE, s)) && streq(ans, "POSIX"))
+ ans = "C";
+ if (!ans || !streq(ans, s) && streq(s, "C"))
+ ans = 0;
+ else if ((ans = setlocale(LC_CTYPE, s)) && streq(ans, "POSIX"))
+ ans = "C";
+ if (!ans || !streq(ans, s) && streq(s, "C"))
+ skip = note(level, s, skip, test);
+ else
+ {
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+ printf("NOTE \"%s\" locale\n", s);
+ locale = level;
+ }
+#else
+ skip = note(level, skip, test, "locales not supported");
+#endif
+ }
+ cflags = NOTEST;
+ continue;
+ case 'E':
+ test |= TEST_ERE;
+ continue;
+ case 'K':
+ test |= TEST_KRE;
+ continue;
+ case 'L':
+ test |= TEST_LRE;
+ continue;
+ case 'S':
+ test |= TEST_SRE;
+ continue;
+
+ case 'a':
+ cflags |= REG_LEFT|REG_RIGHT;
+ continue;
+ case 'b':
+ eflags |= REG_NOTBOL;
+ continue;
+ case 'c':
+ cflags |= REG_COMMENT;
+ continue;
+ case 'd':
+ cflags |= REG_SHELL_DOT;
+ continue;
+ case 'e':
+ eflags |= REG_NOTEOL;
+ continue;
+ case 'f':
+ cflags |= REG_MULTIPLE;
+ continue;
+ case 'g':
+ cflags |= NOTEST;
+ continue;
+ case 'h':
+ cflags |= REG_MULTIREF;
+ continue;
+ case 'i':
+ cflags |= REG_ICASE;
+ continue;
+ case 'j':
+ cflags |= REG_SPAN;
+ continue;
+ case 'k':
+ cflags |= REG_ESCAPE;
+ continue;
+ case 'l':
+ cflags |= REG_LEFT;
+ continue;
+ case 'm':
+ cflags |= REG_MINIMAL;
+ continue;
+ case 'n':
+ cflags |= REG_NEWLINE;
+ continue;
+ case 'o':
+ cflags |= REG_SHELL_GROUP;
+ continue;
+ case 'p':
+ cflags |= REG_SHELL_PATH;
+ continue;
+ case 'q':
+ cflags |= REG_DELIMITED;
+ continue;
+ case 'r':
+ cflags |= REG_RIGHT;
+ continue;
+ case 's':
+ cflags |= REG_SHELL_ESCAPED;
+ continue;
+ case 't':
+ cflags |= REG_MUSTDELIM;
+ continue;
+ case 'u':
+ test |= TEST_UNSPECIFIED;
+ continue;
+ case 'v':
+ cflags |= REG_CLASS_ESCAPE;
+ continue;
+ case 'w':
+ cflags |= REG_NOSUB;
+ continue;
+ case 'x':
+ if (REG_LENIENT)
+ cflags |= REG_LENIENT;
+ else
+ test |= TEST_LENIENT;
+ continue;
+ case 'y':
+ eflags |= REG_LEFT;
+ continue;
+ case 'z':
+ cflags |= REG_NULL;
+ continue;
+
+ case '$':
+ test |= TEST_EXPAND;
+ continue;
+
+ case '/':
+ test |= TEST_SUB;
+ continue;
+
+ case '=':
+ test |= TEST_DECOMP;
+ continue;
+
+ case '?':
+ test |= TEST_VERIFY;
+ test &= ~(TEST_AND|TEST_OR);
+ state.verify = state.passed;
+ continue;
+ case '&':
+ test |= TEST_VERIFY|TEST_AND;
+ test &= ~TEST_OR;
+ continue;
+ case '|':
+ test |= TEST_VERIFY|TEST_OR;
+ test &= ~TEST_AND;
+ continue;
+ case ';':
+ test |= TEST_OR;
+ test &= ~TEST_AND;
+ continue;
+
+ case '{':
+ level <<= 1;
+ if (skip & (level >> 1))
+ {
+ skip |= level;
+ cflags = NOTEST;
+ }
+ else
+ {
+ skip &= ~level;
+ test |= TEST_QUERY;
+ }
+ continue;
+ case '}':
+ if (level == 1)
+ bad("invalid {...} nesting\n", NiL, NiL, 0, 0);
+ if ((skip & level) && !(skip & (level>>1)))
+ {
+ if (!(test & (TEST_BASELINE|TEST_SUMMARY)))
+ {
+ if (test & (TEST_ACTUAL|TEST_FAIL))
+ printf("}\n");
+ else if (!(test & TEST_PASS))
+ printf("-%d\n", state.lineno);
+ }
+ }
+#if defined(LC_COLLATE) && defined(LC_CTYPE)
+ else if (locale & level)
+ {
+ locale = 0;
+ if (!(skip & level))
+ {
+ s = "C";
+ setlocale(LC_COLLATE, s);
+ setlocale(LC_CTYPE, s);
+ if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)))
+ printf("NOTE \"%s\" locale\n", s);
+ else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS))
+ printf("}\n");
+ }
+ else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL))
+ printf("}\n");
+ }
+#endif
+ level >>= 1;
+ cflags = NOTEST;
+ continue;
+
+ default:
+ bad("bad spec\n", spec, NiL, 0, test);
+ break;
+
+ }
+ break;
+ }
+ if ((cflags|eflags) == NOTEST || (skip & level) && (test & TEST_BASELINE))
+ {
+ if (test & TEST_BASELINE)
+ {
+ while (i > 1)
+ *delim[--i] = '\t';
+ printf("%s\n", line);
+ }
+ continue;
+ }
+ if (test & TEST_OR)
+ {
+ if (!(test & TEST_VERIFY))
+ {
+ test &= ~TEST_OR;
+ if (state.passed == state.verify && i > 1)
+ printf("NOTE\t%s\n", field[1]);
+ continue;
+ }
+ else if (state.passed > state.verify)
+ continue;
+ }
+ else if (test & TEST_AND)
+ {
+ if (state.passed == state.verify)
+ continue;
+ state.passed = state.verify;
+ }
+ if (i < ((test & TEST_DECOMP) ? 3 : 4))
+ bad("too few fields\n", NiL, NiL, 0, test);
+ while (i < elementsof(field))
+ field[i++] = 0;
+ if (re = field[1])
+ {
+ if (streq(re, "SAME"))
+ {
+ re = ppat;
+ test |= TEST_SAME;
+ }
+ else
+ {
+ if (test & TEST_EXPAND)
+ escape(re);
+ re = expand(re, patbuf);
+ strcpy(ppat = pat, re);
+ }
+ }
+ else
+ ppat = 0;
+ nstr = -1;
+ if (s = field[2])
+ {
+ s = expand(s, strbuf);
+ if (test & TEST_EXPAND)
+ {
+ nstr = escape(s);
+#if _REG_nexec
+ if (nstr != strlen(s))
+ nexec = nstr;
+#endif
+ }
+ }
+ if (!(ans = field[(test & TEST_DECOMP) ? 2 : 3]))
+ bad("NIL answer\n", NiL, NiL, 0, test);
+ msg = field[4];
+ fflush(stdout);
+ if (test & TEST_SUB)
+#if _REG_subcomp
+ cflags |= REG_DELIMITED;
+#else
+ continue;
+#endif
+#if !_REG_decomp
+ if (test & TEST_DECOMP)
+ continue;
+#endif
+
+ compile:
+
+ if (state.extracted || (skip & level))
+ continue;
+#if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL))
+#ifdef REG_EXTENDED
+ if (REG_EXTENDED != 0 && (test & TEST_BRE))
+#else
+ if (test & TEST_BRE)
+#endif
+ {
+ test &= ~TEST_BRE;
+ flags = cflags;
+ state.which = "BRE";
+ }
+ else
+#endif
+#ifdef REG_EXTENDED
+ if (test & TEST_ERE)
+ {
+ test &= ~TEST_ERE;
+ flags = cflags | REG_EXTENDED;
+ state.which = "ERE";
+ }
+ else
+#endif
+#ifdef REG_AUGMENTED
+ if (test & TEST_ARE)
+ {
+ test &= ~TEST_ARE;
+ flags = cflags | REG_AUGMENTED;
+ state.which = "ARE";
+ }
+ else
+#endif
+#ifdef REG_LITERAL
+ if (test & TEST_LRE)
+ {
+ test &= ~TEST_LRE;
+ flags = cflags | REG_LITERAL;
+ state.which = "LRE";
+ }
+ else
+#endif
+#ifdef REG_SHELL
+ if (test & TEST_SRE)
+ {
+ test &= ~TEST_SRE;
+ flags = cflags | REG_SHELL;
+ state.which = "SRE";
+ }
+ else
+#ifdef REG_AUGMENTED
+ if (test & TEST_KRE)
+ {
+ test &= ~TEST_KRE;
+ flags = cflags | REG_SHELL | REG_AUGMENTED;
+ state.which = "KRE";
+ }
+ else
+#endif
+#endif
+ {
+ if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
+ extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK);
+ continue;
+ }
+ if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE)
+ {
+ printf("test %-3d %s ", state.lineno, state.which);
+ quote(re, -1, test|TEST_DELIMIT);
+ printf(" ");
+ quote(s, nstr, test|TEST_DELIMIT);
+ printf("\n");
+ }
+
+ nosub:
+ fun = "regcomp";
+#if _REG_nexec
+ if (nstr >= 0 && nstr != strlen(s))
+ nexec = nstr;
+
+ else
+#endif
+ nexec = -1;
+ if (state.extracted || (skip & level))
+ continue;
+ if (!(test & TEST_QUERY))
+ testno++;
+#ifdef REG_DISCIPLINE
+ if (state.stack)
+ stkset(stkstd, state.stack, 0);
+ flags |= REG_DISCIPLINE;
+ state.disc.ordinal = 0;
+ sfstrseek(state.disc.sp, 0, SEEK_SET);
+#endif
+ if (!(test & TEST_CATCH))
+ cret = regcomp(&preg, re, flags);
+ else if (!(cret = setjmp(state.gotcha)))
+ {
+ alarm(HUNG);
+ cret = regcomp(&preg, re, flags);
+ alarm(0);
+ }
+#if _REG_subcomp
+ if (!cret && (test & TEST_SUB))
+ {
+ fun = "regsubcomp";
+ p = re + preg.re_npat;
+ if (!(test & TEST_CATCH))
+ cret = regsubcomp(&preg, p, NiL, 0, 0);
+ else if (!(cret = setjmp(state.gotcha)))
+ {
+ alarm(HUNG);
+ cret = regsubcomp(&preg, p, NiL, 0, 0);
+ alarm(0);
+ }
+ if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST))
+ {
+ if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+ continue;
+ cret = REG_EFLAGS;
+ }
+ }
+#endif
+#if _REG_decomp
+ if (!cret && (test & TEST_DECOMP))
+ {
+ char buf[128];
+
+ if ((j = nmatch) > sizeof(buf))
+ j = sizeof(buf);
+ fun = "regdecomp";
+ p = re + preg.re_npat;
+ if (!(test & TEST_CATCH))
+ i = regdecomp(&preg, -1, buf, j);
+ else if (!(cret = setjmp(state.gotcha)))
+ {
+ alarm(HUNG);
+ i = regdecomp(&preg, -1, buf, j);
+ alarm(0);
+ }
+ if (!cret)
+ {
+ catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+ if (i > j)
+ {
+ if (i != (strlen(ans) + 1))
+ {
+ report("failed", fun, re, s, nstr, msg, flags, test);
+ printf(" %d byte buffer supplied, %d byte buffer required\n", j, i);
+ }
+ }
+ else if (strcmp(buf, ans))
+ {
+ report("failed", fun, re, s, nstr, msg, flags, test);
+ quote(ans, -1, test|TEST_DELIMIT);
+ printf(" expected, ");
+ quote(buf, -1, test|TEST_DELIMIT);
+ printf(" returned\n");
+ }
+ continue;
+ }
+ }
+#endif
+ if (!cret)
+ {
+ if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(')
+ {
+ for (p = ans; *p; p++)
+ if (*p == '(')
+ nsub++;
+ else if (*p == '{')
+ nsub--;
+ if (nsub >= 0)
+ {
+ if (test & TEST_IGNORE_OVER)
+ {
+ if (nmatch > nsub)
+ nmatch = nsub + 1;
+ }
+ else if (nsub != preg.re_nsub)
+ {
+ if (nsub > preg.re_nsub)
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+ else
+ {
+ report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test);
+ printf("at least %d expected, %d returned\n", nsub, preg.re_nsub);
+ state.errors++;
+ }
+ }
+ else
+ nsub = preg.re_nsub;
+ }
+ }
+ }
+ if (!(test & (TEST_DECOMP|TEST_SUB)) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH"))
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+ else if (!(test & TEST_LENIENT))
+ {
+ report("failed", fun, re, NiL, -1, msg, flags, test);
+ printf("%s expected, OK returned\n", ans);
+ }
+ catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+ continue;
+ }
+ }
+ else
+ {
+ if (test & TEST_LENIENT)
+ /* we'll let it go this time */;
+ else if (!*ans || ans[0]=='(' || cret == REG_BADPAT && streq(ans, "NOMATCH"))
+ {
+ got = 0;
+ for (i = 1; i < elementsof(codes); i++)
+ if (cret==codes[i].code)
+ got = i;
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+ else
+ {
+ report("failed", fun, re, NiL, -1, msg, flags, test);
+ printf("%s returned: ", codes[got].name);
+ error(&preg, cret);
+ }
+ }
+ else
+ {
+ expected = got = 0;
+ for (i = 1; i < elementsof(codes); i++)
+ {
+ if (streq(ans, codes[i].name))
+ expected = i;
+ if (cret==codes[i].code)
+ got = i;
+ }
+ if (!expected)
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+ else
+ {
+ report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test);
+ printf("%s expected, %s returned\n", ans, codes[got].name);
+ }
+ }
+ else if (cret != codes[expected].code && cret != REG_BADPAT)
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+ else if (test & TEST_IGNORE_ERROR)
+ state.ignored++;
+ else
+ {
+ report("should fail and did", fun, re, NiL, -1, msg, flags, test);
+ printf("%s expected, %s returned: ", ans, codes[got].name);
+ state.errors--;
+ state.warnings++;
+ error(&preg, cret);
+ }
+ }
+ }
+ goto compile;
+ }
+
+#if _REG_nexec
+ execute:
+ if (nexec >= 0)
+ fun = "regnexec";
+ else
+#endif
+ fun = "regexec";
+
+ for (i = 0; i < elementsof(match); i++)
+ match[i] = state.NOMATCH;
+
+#if _REG_nexec
+ if (nexec >= 0)
+ {
+ eret = regnexec(&preg, s, nexec, nmatch, match, eflags);
+ s[nexec] = 0;
+ }
+ else
+#endif
+ {
+ if (!(test & TEST_CATCH))
+ eret = regexec(&preg, s, nmatch, match, eflags);
+ else if (!(eret = setjmp(state.gotcha)))
+ {
+ alarm(HUNG);
+ eret = regexec(&preg, s, nmatch, match, eflags);
+ alarm(0);
+ }
+ }
+#if _REG_subcomp
+ if ((test & TEST_SUB) && !eret)
+ {
+ fun = "regsubexec";
+ if (!(test & TEST_CATCH))
+ eret = regsubexec(&preg, s, nmatch, match);
+ else if (!(eret = setjmp(state.gotcha)))
+ {
+ alarm(HUNG);
+ eret = regsubexec(&preg, s, nmatch, match);
+ alarm(0);
+ }
+ }
+#endif
+ if (flags & REG_NOSUB)
+ {
+ if (eret)
+ {
+ if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT);
+ else
+ {
+ report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test);
+ error(&preg, eret);
+ }
+ }
+ }
+ else if (streq(ans, "NOMATCH"))
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+ else
+ {
+ report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
+ error(&preg, eret);
+ }
+ }
+ }
+ else if (eret)
+ {
+ if (eret != REG_NOMATCH || !streq(ans, "NOMATCH"))
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT);
+ else
+ {
+ report("failed", fun, re, s, nstr, msg, flags, test);
+ if (eret != REG_NOMATCH)
+ error(&preg, eret);
+ else if (*ans)
+ printf("expected: %s\n", ans);
+ else
+ printf("\n");
+ }
+ }
+ }
+ else if (streq(ans, "NOMATCH"))
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+ else
+ {
+ report("should fail and didn't", fun, re, s, nstr, msg, flags, test);
+ matchprint(match, nmatch, nsub, NiL, test);
+ }
+ }
+#if _REG_subcomp
+ else if (test & TEST_SUB)
+ {
+ p = preg.re_sub->re_buf;
+ if (strcmp(p, ans))
+ {
+ report("failed", fun, re, s, nstr, msg, flags, test);
+ quote(ans, -1, test|TEST_DELIMIT);
+ printf(" expected, ");
+ quote(p, -1, test|TEST_DELIMIT);
+ printf(" returned\n");
+ }
+ }
+#endif
+ else if (!*ans)
+ {
+ if (match[0].rm_so != state.NOMATCH.rm_so)
+ {
+ if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test);
+ else
+ {
+ report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test);
+ matchprint(match, nmatch, nsub, NiL, test);
+ }
+ }
+ }
+ else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test))
+ {
+#if _REG_nexec
+ if (nexec < 0 && !nonexec)
+ {
+ nexec = nstr >= 0 ? nstr : strlen(s);
+ s[nexec] = '\n';
+ testno++;
+ goto execute;
+ }
+#endif
+ if (!(test & (TEST_DECOMP|TEST_SUB|TEST_VERIFY)) && !nonosub)
+ {
+ if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+ continue;
+ flags |= REG_NOSUB;
+ goto nosub;
+ }
+ if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK);
+ }
+ else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))
+ skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT);
+ if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test))
+ continue;
+ goto compile;
+ }
+ if (test & TEST_SUMMARY)
+ printf("tests=%-4d errors=%-4d warnings=%-2d ignored=%-2d unspecified=%-2d signals=%d\n", testno, state.errors, state.warnings, state.ignored, state.unspecified, state.signals);
+ else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS)))
+ {
+ printf("TEST\t%s", unit);
+ if (subunit)
+ printf(" %-.*s", subunitlen, subunit);
+ printf(", %d test%s", testno, testno == 1 ? "" : "s");
+ if (state.ignored)
+ printf(", %d ignored mismatche%s", state.ignored, state.ignored == 1 ? "" : "s");
+ if (state.warnings)
+ printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s");
+ if (state.unspecified)
+ printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s");
+ if (state.signals)
+ printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s");
+ printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s");
+ }
+ if (fp != stdin)
+ fclose(fp);
+ }
+ return 0;
+}
diff --git a/libgo/go/rpc/client.go b/libgo/go/rpc/client.go
index 4acfdf6d962..3dc6df1c4b3 100644
--- a/libgo/go/rpc/client.go
+++ b/libgo/go/rpc/client.go
@@ -85,7 +85,8 @@ func (client *Client) send(c *Call) {
client.request.Seq = c.seq
client.request.ServiceMethod = c.ServiceMethod
if err := client.codec.WriteRequest(&client.request, c.Args); err != nil {
- panic("rpc: client encode error: " + err.String())
+ c.Error = err
+ c.done()
}
}
@@ -104,7 +105,7 @@ func (client *Client) input() {
seq := response.Seq
client.mutex.Lock()
c := client.pending[seq]
- client.pending[seq] = c, false
+ delete(client.pending, seq)
client.mutex.Unlock()
if response.Error == "" {
@@ -251,10 +252,10 @@ func (client *Client) Close() os.Error {
// the same Call object. If done is nil, Go will allocate a new channel.
// If non-nil, done must be buffered or Go will deliberately crash.
func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call {
- c := new(Call)
- c.ServiceMethod = serviceMethod
- c.Args = args
- c.Reply = reply
+ call := new(Call)
+ call.ServiceMethod = serviceMethod
+ call.Args = args
+ call.Reply = reply
if done == nil {
done = make(chan *Call, 10) // buffered.
} else {
@@ -266,14 +267,14 @@ func (client *Client) Go(serviceMethod string, args interface{}, reply interface
log.Panic("rpc: done channel is unbuffered")
}
}
- c.Done = done
+ call.Done = done
if client.shutdown {
- c.Error = ErrShutdown
- c.done()
- return c
+ call.Error = ErrShutdown
+ call.done()
+ return call
}
- client.send(c)
- return c
+ client.send(call)
+ return call
}
// Call invokes the named function, waits for it to complete, and returns its error status.
diff --git a/libgo/go/rpc/jsonrpc/client.go b/libgo/go/rpc/jsonrpc/client.go
index 577d0ce4295..17e9b9388a0 100644
--- a/libgo/go/rpc/jsonrpc/client.go
+++ b/libgo/go/rpc/jsonrpc/client.go
@@ -79,7 +79,7 @@ func (c *clientCodec) ReadResponseHeader(r *rpc.Response) os.Error {
c.mutex.Lock()
r.ServiceMethod = c.pending[c.resp.Id]
- c.pending[c.resp.Id] = "", false
+ delete(c.pending, c.resp.Id)
c.mutex.Unlock()
r.Error = ""
diff --git a/libgo/go/rpc/jsonrpc/server.go b/libgo/go/rpc/jsonrpc/server.go
index 9801fdf221e..61b5abff551 100644
--- a/libgo/go/rpc/jsonrpc/server.go
+++ b/libgo/go/rpc/jsonrpc/server.go
@@ -107,7 +107,7 @@ func (c *serverCodec) WriteResponse(r *rpc.Response, x interface{}) os.Error {
c.mutex.Unlock()
return os.NewError("invalid sequence number in response")
}
- c.pending[r.Seq] = nil, false
+ delete(c.pending, r.Seq)
c.mutex.Unlock()
if b == nil {
diff --git a/libgo/go/rpc/server.go b/libgo/go/rpc/server.go
index 74507442862..f03710061a4 100644
--- a/libgo/go/rpc/server.go
+++ b/libgo/go/rpc/server.go
@@ -97,7 +97,7 @@
if err != nil {
log.Fatal("arith error:", err)
}
- fmt.Printf("Arith: %d*%d=%d", args.A, args.B, *reply)
+ fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
or
diff --git a/libgo/go/rpc/server_test.go b/libgo/go/rpc/server_test.go
index e7bbfbe97d2..029741b28b5 100644
--- a/libgo/go/rpc/server_test.go
+++ b/libgo/go/rpc/server_test.go
@@ -14,6 +14,7 @@ import (
"runtime"
"strings"
"sync"
+ "sync/atomic"
"testing"
"time"
)
@@ -466,6 +467,32 @@ func TestCountMallocsOverHTTP(t *testing.T) {
fmt.Printf("mallocs per HTTP rpc round trip: %d\n", countMallocs(dialHTTP, t))
}
+type writeCrasher struct{}
+
+func (writeCrasher) Close() os.Error {
+ return nil
+}
+
+func (writeCrasher) Read(p []byte) (int, os.Error) {
+ return 0, os.EOF
+}
+
+func (writeCrasher) Write(p []byte) (int, os.Error) {
+ return 0, os.NewError("fake write failure")
+}
+
+func TestClientWriteError(t *testing.T) {
+ c := NewClient(writeCrasher{})
+ res := false
+ err := c.Call("foo", 1, &res)
+ if err == nil {
+ t.Fatal("expected error")
+ }
+ if err.String() != "fake write failure" {
+ t.Error("unexpected value of error:", err)
+ }
+}
+
func benchmarkEndToEnd(dial func() (*Client, os.Error), b *testing.B) {
b.StopTimer()
once.Do(startServer)
@@ -477,19 +504,79 @@ func benchmarkEndToEnd(dial func() (*Client, os.Error), b *testing.B) {
// Synchronous calls
args := &Args{7, 8}
- reply := new(Reply)
+ procs := runtime.GOMAXPROCS(-1)
+ N := int32(b.N)
+ var wg sync.WaitGroup
+ wg.Add(procs)
b.StartTimer()
- for i := 0; i < b.N; i++ {
- err = client.Call("Arith.Add", args, reply)
- if err != nil {
- fmt.Printf("Add: expected no error but got string %q", err.String())
- break
- }
- if reply.C != args.A+args.B {
- fmt.Printf("Add: expected %d got %d", reply.C, args.A+args.B)
- break
- }
+
+ for p := 0; p < procs; p++ {
+ go func() {
+ reply := new(Reply)
+ for atomic.AddInt32(&N, -1) >= 0 {
+ err = client.Call("Arith.Add", args, reply)
+ if err != nil {
+ fmt.Printf("Add: expected no error but got string %q", err.String())
+ panic("rpc error")
+ }
+ if reply.C != args.A+args.B {
+ fmt.Printf("Add: expected %d got %d", reply.C, args.A+args.B)
+ panic("rpc error")
+ }
+ }
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+}
+
+func benchmarkEndToEndAsync(dial func() (*Client, os.Error), b *testing.B) {
+ const MaxConcurrentCalls = 100
+ b.StopTimer()
+ once.Do(startServer)
+ client, err := dial()
+ if err != nil {
+ fmt.Println("error dialing", err)
+ return
}
+
+ // Asynchronous calls
+ args := &Args{7, 8}
+ procs := 4 * runtime.GOMAXPROCS(-1)
+ send := int32(b.N)
+ recv := int32(b.N)
+ var wg sync.WaitGroup
+ wg.Add(procs)
+ gate := make(chan bool, MaxConcurrentCalls)
+ res := make(chan *Call, MaxConcurrentCalls)
+ b.StartTimer()
+
+ for p := 0; p < procs; p++ {
+ go func() {
+ for atomic.AddInt32(&send, -1) >= 0 {
+ gate <- true
+ reply := new(Reply)
+ client.Go("Arith.Add", args, reply, res)
+ }
+ }()
+ go func() {
+ for call := range res {
+ a := call.Args.(*Args).A
+ b := call.Args.(*Args).B
+ c := call.Reply.(*Reply).C
+ if a+b != c {
+ fmt.Printf("Add: expected %d got %d", a+b, c)
+ panic("incorrect reply")
+ }
+ <-gate
+ if atomic.AddInt32(&recv, -1) == 0 {
+ close(res)
+ }
+ }
+ wg.Done()
+ }()
+ }
+ wg.Wait()
}
func BenchmarkEndToEnd(b *testing.B) {
@@ -499,3 +586,11 @@ func BenchmarkEndToEnd(b *testing.B) {
func BenchmarkEndToEndHTTP(b *testing.B) {
benchmarkEndToEnd(dialHTTP, b)
}
+
+func BenchmarkEndToEndAsync(b *testing.B) {
+ benchmarkEndToEndAsync(dialDirect, b)
+}
+
+func BenchmarkEndToEndAsyncHTTP(b *testing.B) {
+ benchmarkEndToEndAsync(dialHTTP, b)
+}
diff --git a/libgo/go/runtime/chan_test.go b/libgo/go/runtime/chan_test.go
index 46ddfd7e88f..7cea906ceae 100644
--- a/libgo/go/runtime/chan_test.go
+++ b/libgo/go/runtime/chan_test.go
@@ -59,6 +59,57 @@ func TestPseudoRandomSend(t *testing.T) {
t.Errorf("Want pseudo random, got %d zeros and %d ones", n0, n1)
}
+func TestMultiConsumer(t *testing.T) {
+ const nwork = 23
+ const niter = 271828
+
+ pn := []int{2, 3, 7, 11, 13, 17, 19, 23, 27, 31}
+
+ q := make(chan int, nwork*3)
+ r := make(chan int, nwork*3)
+
+ // workers
+ var wg sync.WaitGroup
+ for i := 0; i < nwork; i++ {
+ wg.Add(1)
+ go func(w int) {
+ for v := range q {
+ // mess with the fifo-ish nature of range
+ if pn[w%len(pn)] == v {
+ runtime.Gosched()
+ }
+ r <- v
+ }
+ wg.Done()
+ }(i)
+ }
+
+ // feeder & closer
+ expect := 0
+ go func() {
+ for i := 0; i < niter; i++ {
+ v := pn[i%len(pn)]
+ expect += v
+ q <- v
+ }
+ close(q) // no more work
+ wg.Wait() // workers done
+ close(r) // ... so there can be no more results
+ }()
+
+ // consume & check
+ n := 0
+ s := 0
+ for v := range r {
+ n++
+ s += v
+ }
+ if n != niter || s != expect {
+ t.Errorf("Expected sum %d (got %d) from %d iter (saw %d)",
+ expect, s, niter, n)
+ }
+}
+
func BenchmarkSelectUncontended(b *testing.B) {
const CallsPerSched = 1000
procs := runtime.GOMAXPROCS(-1)
diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go
index 9da3423c618..7c986daee63 100644
--- a/libgo/go/runtime/extern.go
+++ b/libgo/go/runtime/extern.go
@@ -131,8 +131,8 @@ func Semrelease(s *uint32)
// The argument x must be a pointer to an object allocated by
// calling new or by taking the address of a composite literal.
// The argument f must be a function that takes a single argument
-// of x's type and returns no arguments. If either of these is not
-// true, SetFinalizer aborts the program.
+// of x's type and can have arbitrary ignored return values.
+// If either of these is not true, SetFinalizer aborts the program.
//
// Finalizers are run in dependency order: if A points at B, both have
// finalizers, and they are otherwise unreachable, only the finalizer
@@ -156,9 +156,6 @@ func Semrelease(s *uint32)
// A single goroutine runs all finalizers for a program, sequentially.
// If a finalizer must run for a long time, it should do so by starting
// a new goroutine.
-//
-// TODO(rsc): allow f to have (ignored) return values
-//
func SetFinalizer(x, f interface{})
func getgoroot() string
diff --git a/libgo/go/runtime/gc_test.go b/libgo/go/runtime/gc_test.go
new file mode 100644
index 00000000000..fad60a36804
--- /dev/null
+++ b/libgo/go/runtime/gc_test.go
@@ -0,0 +1,24 @@
+package runtime_test
+
+import (
+ "runtime"
+ "testing"
+)
+
+func TestGcSys(t *testing.T) {
+ for i := 0; i < 1000000; i++ {
+ workthegc()
+ }
+
+ // Should only be using a few MB.
+ runtime.UpdateMemStats()
+ sys := runtime.MemStats.Sys
+ t.Logf("using %d MB", sys>>20)
+ if sys > 10e6 {
+ t.Fatalf("using too much memory: %d MB", sys>>20)
+ }
+}
+
+func workthegc() []byte {
+ return make([]byte, 1029)
+}
diff --git a/libgo/go/runtime/mfinal_test.go b/libgo/go/runtime/mfinal_test.go
new file mode 100644
index 00000000000..de632717a57
--- /dev/null
+++ b/libgo/go/runtime/mfinal_test.go
@@ -0,0 +1,64 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+ "runtime"
+ "sync"
+ "sync/atomic"
+ "testing"
+)
+
+func fin(v *int) {
+}
+
+func BenchmarkFinalizer(b *testing.B) {
+ const CallsPerSched = 1000
+ procs := runtime.GOMAXPROCS(-1)
+ N := int32(b.N / CallsPerSched)
+ var wg sync.WaitGroup
+ wg.Add(procs)
+ for p := 0; p < procs; p++ {
+ go func() {
+ var data [CallsPerSched]*int
+ for i := 0; i < CallsPerSched; i++ {
+ data[i] = new(int)
+ }
+ for atomic.AddInt32(&N, -1) >= 0 {
+ runtime.Gosched()
+ for i := 0; i < CallsPerSched; i++ {
+ runtime.SetFinalizer(data[i], fin)
+ }
+ for i := 0; i < CallsPerSched; i++ {
+ runtime.SetFinalizer(data[i], nil)
+ }
+ }
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+}
+
+func BenchmarkFinalizerRun(b *testing.B) {
+ const CallsPerSched = 1000
+ procs := runtime.GOMAXPROCS(-1)
+ N := int32(b.N / CallsPerSched)
+ var wg sync.WaitGroup
+ wg.Add(procs)
+ for p := 0; p < procs; p++ {
+ go func() {
+ for atomic.AddInt32(&N, -1) >= 0 {
+ runtime.Gosched()
+ for i := 0; i < CallsPerSched; i++ {
+ v := new(int)
+ runtime.SetFinalizer(v, fin)
+ }
+ runtime.GC()
+ }
+ wg.Done()
+ }()
+ }
+ wg.Wait()
+}
diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go
index 4486d5525f7..5f128c01cf1 100644
--- a/libgo/go/runtime/pprof/pprof_test.go
+++ b/libgo/go/runtime/pprof/pprof_test.go
@@ -22,9 +22,6 @@ func TestCPUProfile(t *testing.T) {
case "plan9":
// unimplemented
return
- case "windows":
- // unimplemented
- return
}
buf := make([]byte, 100000)
diff --git a/libgo/go/scanner/scanner.go b/libgo/go/scanner/scanner.go
index 8fbcb9c1155..29e5f8c7428 100644
--- a/libgo/go/scanner/scanner.go
+++ b/libgo/go/scanner/scanner.go
@@ -164,9 +164,12 @@ type Scanner struct {
// for values ch > ' '). The field may be changed at any time.
Whitespace uint64
- // Current token position. The Offset, Line, and Column fields
- // are set by Scan(); the Filename field is left untouched by the
- // Scanner.
+ // Start position of most recently scanned token; set by Scan.
+ // Calling Init or Next invalidates the position (Line == 0).
+ // The Filename field is always left untouched by the Scanner.
+ // If an error is reported (via Error) and Position is invalid,
+ // the scanner is not inside a token. Call Pos to obtain an error
+ // position in that case.
Position
}
@@ -201,6 +204,7 @@ func (s *Scanner) Init(src io.Reader) *Scanner {
s.ErrorCount = 0
s.Mode = GoTokens
s.Whitespace = GoWhitespace
+ s.Line = 0 // invalidate token position
return s
}
@@ -302,6 +306,7 @@ func (s *Scanner) next() int {
// get the current position.
func (s *Scanner) Next() int {
s.tokPos = -1 // don't collect token text
+ s.Line = 0 // invalidate token position
ch := s.Peek()
s.ch = s.next()
return ch
@@ -323,7 +328,11 @@ func (s *Scanner) error(msg string) {
s.Error(s, msg)
return
}
- fmt.Fprintf(os.Stderr, "%s: %s\n", s.Position, msg)
+ pos := s.Position
+ if !pos.IsValid() {
+ pos = s.Pos()
+ }
+ fmt.Fprintf(os.Stderr, "%s: %s\n", pos, msg)
}
func (s *Scanner) scanIdentifier() int {
@@ -520,6 +529,7 @@ func (s *Scanner) Scan() int {
// reset token text position
s.tokPos = -1
+ s.Line = 0
redo:
// skip white space
diff --git a/libgo/go/scanner/scanner_test.go b/libgo/go/scanner/scanner_test.go
index 8403d615354..bbbba128348 100644
--- a/libgo/go/scanner/scanner_test.go
+++ b/libgo/go/scanner/scanner_test.go
@@ -100,11 +100,8 @@ var tokenList = []token{
{Ident, "_abc_123_"},
{Ident, "_äöü"},
{Ident, "_本"},
- // TODO for unknown reasons these fail when checking the literals
- /*
- token{Ident, "äöü"},
- token{Ident, "本"},
- */
+ {Ident, "äöü"},
+ {Ident, "本"},
{Ident, "aÛ°Û±Û¸"},
{Ident, "foo६४"},
{Ident, "bar9876"},
@@ -365,14 +362,14 @@ func TestScanNext(t *testing.T) {
checkTok(t, s, 1, s.Scan(), Ident, "if")
checkTok(t, s, 1, s.Scan(), Ident, "a")
checkTok(t, s, 1, s.Scan(), '=', "=")
- checkTok(t, s, 1, s.Next(), '=', "")
- checkTok(t, s, 1, s.Next(), ' ', "")
- checkTok(t, s, 1, s.Next(), 'b', "")
+ checkTok(t, s, 0, s.Next(), '=', "")
+ checkTok(t, s, 0, s.Next(), ' ', "")
+ checkTok(t, s, 0, s.Next(), 'b', "")
checkTok(t, s, 1, s.Scan(), Ident, "cd")
checkTok(t, s, 1, s.Scan(), '{', "{")
checkTok(t, s, 2, s.Scan(), Ident, "a")
checkTok(t, s, 2, s.Scan(), '+', "+")
- checkTok(t, s, 2, s.Next(), '=', "")
+ checkTok(t, s, 0, s.Next(), '=', "")
checkTok(t, s, 2, s.Scan(), Ident, "c")
checkTok(t, s, 3, s.Scan(), '}', "}")
checkTok(t, s, 3, s.Scan(), -1, "")
diff --git a/libgo/go/sort/example_test.go b/libgo/go/sort/example_test.go
new file mode 100644
index 00000000000..2f5ee90818c
--- /dev/null
+++ b/libgo/go/sort/example_test.go
@@ -0,0 +1,17 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sort_test
+
+import (
+ "fmt"
+ "sort"
+)
+
+// [1 2 3 4 5 6]
+func ExampleInts() {
+ s := []int{5, 2, 6, 3, 1, 4}
+ sort.Ints(s)
+ fmt.Println(s)
+}
diff --git a/libgo/go/sort/export_test.go b/libgo/go/sort/export_test.go
new file mode 100644
index 00000000000..b6e30ceb570
--- /dev/null
+++ b/libgo/go/sort/export_test.go
@@ -0,0 +1,9 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sort
+
+func Heapsort(data Interface) {
+ heapSort(data, 0, data.Len())
+}
diff --git a/libgo/go/sort/sort.go b/libgo/go/sort/sort.go
index 0a4a4375f05..83ee170cbab 100644
--- a/libgo/go/sort/sort.go
+++ b/libgo/go/sort/sort.go
@@ -37,10 +37,47 @@ func insertionSort(data Interface, a, b int) {
}
}
+// siftDown implements the heap property on data[lo, hi).
+// first is an offset into the array where the root of the heap lies.
+func siftDown(data Interface, lo, hi, first int) {
+ root := lo
+ for {
+ child := 2*root + 1
+ if child >= hi {
+ break
+ }
+ if child+1 < hi && data.Less(first+child, first+child+1) {
+ child++
+ }
+ if !data.Less(first+root, first+child) {
+ return
+ }
+ data.Swap(first+root, first+child)
+ root = child
+ }
+}
+
+func heapSort(data Interface, a, b int) {
+ first := a
+ lo := 0
+ hi := b - a
+
+ // Build heap with greatest element at top.
+ for i := (hi - 1) / 2; i >= 0; i-- {
+ siftDown(data, i, hi, first)
+ }
+
+ // Pop elements, largest first, into end of data.
+ for i := hi - 1; i >= 0; i-- {
+ data.Swap(first, first+i)
+ siftDown(data, lo, i, first)
+ }
+}
+
// Quicksort, following Bentley and McIlroy,
// ``Engineering a Sort Function,'' SP&E November 1993.
-// Move the median of the three values data[a], data[b], data[c] into data[a].
+// medianOfThree moves the median of the three values data[a], data[b], data[c] into data[a].
func medianOfThree(data Interface, a, b, c int) {
m0 := b
m1 := a
@@ -123,16 +160,21 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
return lo + b - a, hi - (d - c)
}
-func quickSort(data Interface, a, b int) {
+func quickSort(data Interface, a, b, maxDepth int) {
for b-a > 7 {
+ if maxDepth == 0 {
+ heapSort(data, a, b)
+ return
+ }
+ maxDepth--
mlo, mhi := doPivot(data, a, b)
// Avoiding recursion on the larger subproblem guarantees
// a stack depth of at most lg(b-a).
if mlo-a < b-mhi {
- quickSort(data, a, mlo)
+ quickSort(data, a, mlo, maxDepth)
a = mhi // i.e., quickSort(data, mhi, b)
} else {
- quickSort(data, mhi, b)
+ quickSort(data, mhi, b, maxDepth)
b = mlo // i.e., quickSort(data, a, mlo)
}
}
@@ -141,7 +183,16 @@ func quickSort(data Interface, a, b int) {
}
}
-func Sort(data Interface) { quickSort(data, 0, data.Len()) }
+func Sort(data Interface) {
+ // Switch to heapsort if depth of 2*ceil(lg(n)) is reached.
+ n := data.Len()
+ maxDepth := 0
+ for 1<<uint(maxDepth) < n {
+ maxDepth++
+ }
+ maxDepth *= 2
+ quickSort(data, 0, data.Len(), maxDepth)
+}
func IsSorted(data Interface) bool {
n := data.Len()
diff --git a/libgo/go/sort/sort_test.go b/libgo/go/sort/sort_test.go
index 5007a92a562..a5640151cb2 100644
--- a/libgo/go/sort/sort_test.go
+++ b/libgo/go/sort/sort_test.go
@@ -169,6 +169,13 @@ func (d *testingData) Swap(i, j int) {
d.data[i], d.data[j] = d.data[j], d.data[i]
}
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
func lg(n int) int {
i := 0
for 1<<uint(i) < n {
@@ -177,7 +184,7 @@ func lg(n int) int {
return i
}
-func TestBentleyMcIlroy(t *testing.T) {
+func testBentleyMcIlroy(t *testing.T, sort func(Interface)) {
sizes := []int{100, 1023, 1024, 1025}
if testing.Short() {
sizes = []int{100, 127, 128, 129}
@@ -253,7 +260,7 @@ func TestBentleyMcIlroy(t *testing.T) {
desc := fmt.Sprintf("n=%d m=%d dist=%s mode=%s", n, m, dists[dist], modes[mode])
d := &testingData{desc, t, mdata[0:n], n * lg(n) * 12 / 10, 0}
- Sort(d)
+ sort(d)
// If we were testing C qsort, we'd have to make a copy
// of the slice and sort it ourselves and then compare
@@ -274,9 +281,58 @@ func TestBentleyMcIlroy(t *testing.T) {
}
}
-func min(a, b int) int {
- if a < b {
- return a
+func TestSortBM(t *testing.T) {
+ testBentleyMcIlroy(t, Sort)
+}
+
+func TestHeapsortBM(t *testing.T) {
+ testBentleyMcIlroy(t, Heapsort)
+}
+
+// This is based on the "antiquicksort" implementation by M. Douglas McIlroy.
+// See http://www.cs.dartmouth.edu/~doug/mdmspe.pdf for more info.
+type adversaryTestingData struct {
+ data []int
+ keys map[int]int
+ candidate int
+}
+
+func (d *adversaryTestingData) Len() int { return len(d.data) }
+
+func (d *adversaryTestingData) Less(i, j int) bool {
+ if _, present := d.keys[i]; !present {
+ if _, present := d.keys[j]; !present {
+ if i == d.candidate {
+ d.keys[i] = len(d.keys)
+ } else {
+ d.keys[j] = len(d.keys)
+ }
+ }
}
- return b
+
+ if _, present := d.keys[i]; !present {
+ d.candidate = i
+ return false
+ }
+ if _, present := d.keys[j]; !present {
+ d.candidate = j
+ return true
+ }
+
+ return d.keys[i] >= d.keys[j]
+}
+
+func (d *adversaryTestingData) Swap(i, j int) {
+ d.data[i], d.data[j] = d.data[j], d.data[i]
+}
+
+func TestAdversary(t *testing.T) {
+ const size = 100
+ data := make([]int, size)
+ for i := 0; i < size; i++ {
+ data[i] = i
+ }
+
+ d := &adversaryTestingData{data, make(map[int]int), 0}
+ Sort(d) // This should degenerate to heapsort.
}
diff --git a/libgo/go/strconv/atof.go b/libgo/go/strconv/atof.go
index 38b38053ce0..86c56f7fd7e 100644
--- a/libgo/go/strconv/atof.go
+++ b/libgo/go/strconv/atof.go
@@ -56,8 +56,9 @@ func special(s string) (f float64, ok bool) {
}
// TODO(rsc): Better truncation handling.
-func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
+func (b *decimal) set(s string) (ok bool) {
i := 0
+ b.neg = false
// optional sign
if i >= len(s) {
@@ -67,12 +68,11 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
case s[i] == '+':
i++
case s[i] == '-':
- neg = true
+ b.neg = true
i++
}
// digits
- b := new(decimal)
sawdot := false
sawdigits := false
for ; i < len(s); i++ {
@@ -137,7 +137,6 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
return
}
- d = b
ok = true
return
}
@@ -145,7 +144,7 @@ func stringToDecimal(s string) (neg bool, d *decimal, trunc bool, ok bool) {
// decimal power of ten to binary power of two.
var powtab = []int{1, 3, 6, 9, 13, 16, 19, 23, 26}
-func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uint64, overflow bool) {
+func (d *decimal) floatBits(flt *floatInfo) (b uint64, overflow bool) {
var exp int
var mant uint64
@@ -209,7 +208,8 @@ func decimalToFloatBits(neg bool, d *decimal, trunc bool, flt *floatInfo) (b uin
}
// Extract 1+flt.mantbits bits.
- mant = d.Shift(int(1 + flt.mantbits)).RoundedInteger()
+ d.Shift(int(1 + flt.mantbits))
+ mant = d.RoundedInteger()
// Rounding might have added a bit; shift down.
if mant == 2<<flt.mantbits {
@@ -236,7 +236,7 @@ out:
// Assemble bits.
bits := mant & (uint64(1)<<flt.mantbits - 1)
bits |= uint64((exp-flt.bias)&(1<<flt.expbits-1)) << flt.mantbits
- if neg {
+ if d.neg {
bits |= 1 << flt.mantbits << flt.expbits
}
return bits, overflow
@@ -244,24 +244,24 @@ out:
// Compute exact floating-point integer from d's digits.
// Caller is responsible for avoiding overflow.
-func decimalAtof64Int(neg bool, d *decimal) float64 {
+func (d *decimal) atof64int() float64 {
f := 0.0
for i := 0; i < d.nd; i++ {
f = f*10 + float64(d.d[i]-'0')
}
- if neg {
- f *= -1 // BUG work around 6g f = -f.
+ if d.neg {
+ f = -f
}
return f
}
-func decimalAtof32Int(neg bool, d *decimal) float32 {
+func (d *decimal) atof32int() float32 {
f := float32(0)
for i := 0; i < d.nd; i++ {
f = f*10 + float32(d.d[i]-'0')
}
- if neg {
- f *= -1 // BUG work around 6g f = -f.
+ if d.neg {
+ f = -f
}
return f
}
@@ -281,7 +281,7 @@ var float32pow10 = []float32{1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1
// value is exact integer * exact power of ten
// value is exact integer / exact power of ten
// These all produce potentially inexact but correctly rounded answers.
-func decimalAtof64(neg bool, d *decimal, trunc bool) (f float64, ok bool) {
+func (d *decimal) atof64() (f float64, ok bool) {
// Exact integers are <= 10^15.
// Exact powers of ten are <= 10^22.
if d.nd > 15 {
@@ -289,11 +289,11 @@ func decimalAtof64(neg bool, d *decimal, trunc bool) (f float64, ok bool) {
}
switch {
case d.dp == d.nd: // int
- f := decimalAtof64Int(neg, d)
+ f := d.atof64int()
return f, true
case d.dp > d.nd && d.dp <= 15+22: // int * 10^k
- f := decimalAtof64Int(neg, d)
+ f := d.atof64int()
k := d.dp - d.nd
// If exponent is big but number of digits is not,
// can move a few zeros into the integer part.
@@ -304,7 +304,7 @@ func decimalAtof64(neg bool, d *decimal, trunc bool) (f float64, ok bool) {
return f * float64pow10[k], true
case d.dp < d.nd && d.nd-d.dp <= 22: // int / 10^k
- f := decimalAtof64Int(neg, d)
+ f := d.atof64int()
return f / float64pow10[d.nd-d.dp], true
}
return
@@ -312,7 +312,7 @@ func decimalAtof64(neg bool, d *decimal, trunc bool) (f float64, ok bool) {
// If possible to convert decimal d to 32-bit float f exactly,
// entirely in floating-point math, do so, avoiding the machinery above.
-func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) {
+func (d *decimal) atof32() (f float32, ok bool) {
// Exact integers are <= 10^7.
// Exact powers of ten are <= 10^10.
if d.nd > 7 {
@@ -320,11 +320,11 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) {
}
switch {
case d.dp == d.nd: // int
- f := decimalAtof32Int(neg, d)
+ f := d.atof32int()
return f, true
case d.dp > d.nd && d.dp <= 7+10: // int * 10^k
- f := decimalAtof32Int(neg, d)
+ f := d.atof32int()
k := d.dp - d.nd
// If exponent is big but number of digits is not,
// can move a few zeros into the integer part.
@@ -335,7 +335,7 @@ func decimalAtof32(neg bool, d *decimal, trunc bool) (f float32, ok bool) {
return f * float32pow10[k], true
case d.dp < d.nd && d.nd-d.dp <= 10: // int / 10^k
- f := decimalAtof32Int(neg, d)
+ f := d.atof32int()
return f / float32pow10[d.nd-d.dp], true
}
return
@@ -360,16 +360,16 @@ func Atof32(s string) (f float32, err os.Error) {
return float32(val), nil
}
- neg, d, trunc, ok := stringToDecimal(s)
- if !ok {
+ var d decimal
+ if !d.set(s) {
return 0, &NumError{s, os.EINVAL}
}
if optimize {
- if f, ok := decimalAtof32(neg, d, trunc); ok {
+ if f, ok := d.atof32(); ok {
return f, nil
}
}
- b, ovf := decimalToFloatBits(neg, d, trunc, &float32info)
+ b, ovf := d.floatBits(&float32info)
f = math.Float32frombits(uint32(b))
if ovf {
err = &NumError{s, os.ERANGE}
@@ -385,16 +385,16 @@ func Atof64(s string) (f float64, err os.Error) {
return val, nil
}
- neg, d, trunc, ok := stringToDecimal(s)
- if !ok {
+ var d decimal
+ if !d.set(s) {
return 0, &NumError{s, os.EINVAL}
}
if optimize {
- if f, ok := decimalAtof64(neg, d, trunc); ok {
+ if f, ok := d.atof64(); ok {
return f, nil
}
}
- b, ovf := decimalToFloatBits(neg, d, trunc, &float64info)
+ b, ovf := d.floatBits(&float64info)
f = math.Float64frombits(b)
if ovf {
err = &NumError{s, os.ERANGE}
diff --git a/libgo/go/strconv/atof_test.go b/libgo/go/strconv/atof_test.go
index 0fdd0ea982b..23aafc1e5d7 100644
--- a/libgo/go/strconv/atof_test.go
+++ b/libgo/go/strconv/atof_test.go
@@ -34,6 +34,7 @@ var atoftests = []atofTest{
{"100000000000000016777215", "1.0000000000000001e+23", nil},
{"100000000000000016777216", "1.0000000000000003e+23", nil},
{"-1", "-1", nil},
+ {"-0.1", "-0.1", nil},
{"-0", "-0", nil},
{"1e-20", "1e-20", nil},
{"625e-3", "0.625", nil},
diff --git a/libgo/go/strconv/decimal.go b/libgo/go/strconv/decimal.go
index 783065bfbf2..f572ea4a22d 100644
--- a/libgo/go/strconv/decimal.go
+++ b/libgo/go/strconv/decimal.go
@@ -14,9 +14,10 @@ package strconv
type decimal struct {
// TODO(rsc): Can make d[] a bit smaller and add
// truncated bool;
- d [2000]byte // digits
- nd int // number of digits used
- dp int // decimal point
+ d [2000]byte // digits
+ nd int // number of digits used
+ dp int // decimal point
+ neg bool
}
func (a *decimal) String() string {
@@ -266,8 +267,7 @@ func leftShift(a *decimal, k uint) {
}
// Binary shift left (k > 0) or right (k < 0).
-// Returns receiver for convenience.
-func (a *decimal) Shift(k int) *decimal {
+func (a *decimal) Shift(k int) {
switch {
case a.nd == 0:
// nothing to do: a == 0
@@ -284,7 +284,6 @@ func (a *decimal) Shift(k int) *decimal {
}
rightShift(a, uint(-k))
}
- return a
}
// If we chop a at nd digits, should we round up?
diff --git a/libgo/go/strconv/decimal_test.go b/libgo/go/strconv/decimal_test.go
index 9b790351673..deb2e02f610 100644
--- a/libgo/go/strconv/decimal_test.go
+++ b/libgo/go/strconv/decimal_test.go
@@ -32,7 +32,9 @@ var shifttests = []shiftTest{
func TestDecimalShift(t *testing.T) {
for i := 0; i < len(shifttests); i++ {
test := &shifttests[i]
- s := NewDecimal(test.i).Shift(test.shift).String()
+ d := NewDecimal(test.i)
+ d.Shift(test.shift)
+ s := d.String()
if s != test.out {
t.Errorf("Decimal %v << %v = %v, want %v",
test.i, test.shift, s, test.out)
@@ -108,7 +110,9 @@ var roundinttests = []roundIntTest{
func TestDecimalRoundedInteger(t *testing.T) {
for i := 0; i < len(roundinttests); i++ {
test := roundinttests[i]
- int := NewDecimal(test.i).Shift(test.shift).RoundedInteger()
+ d := NewDecimal(test.i)
+ d.Shift(test.shift)
+ int := d.RoundedInteger()
if int != test.int {
t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v",
test.i, test.shift, int, test.int)
diff --git a/libgo/go/strconv/ftoa.go b/libgo/go/strconv/ftoa.go
index b6049c54589..07fe806b97d 100644
--- a/libgo/go/strconv/ftoa.go
+++ b/libgo/go/strconv/ftoa.go
@@ -98,7 +98,8 @@ func genericFtoa(bits uint64, fmt byte, prec int, flt *floatInfo) string {
// The shift is exp - flt.mantbits because mant is a 1-bit integer
// followed by a flt.mantbits fraction, and we are treating it as
// a 1+flt.mantbits-bit integer.
- d := newDecimal(mant).Shift(exp - int(flt.mantbits))
+ d := newDecimal(mant)
+ d.Shift(exp - int(flt.mantbits))
// Round appropriately.
// Negative precision means "only as much as needed to be exact."
@@ -183,7 +184,8 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
// d = mant << (exp - mantbits)
// Next highest floating point number is mant+1 << exp-mantbits.
// Our upper bound is halfway inbetween, mant*2+1 << exp-mantbits-1.
- upper := newDecimal(mant*2 + 1).Shift(exp - int(flt.mantbits) - 1)
+ upper := newDecimal(mant*2 + 1)
+ upper.Shift(exp - int(flt.mantbits) - 1)
// d = mant << (exp - mantbits)
// Next lowest floating point number is mant-1 << exp-mantbits,
@@ -201,7 +203,8 @@ func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
mantlo = mant*2 - 1
explo = exp - 1
}
- lower := newDecimal(mantlo*2 + 1).Shift(explo - int(flt.mantbits) - 1)
+ lower := newDecimal(mantlo*2 + 1)
+ lower.Shift(explo - int(flt.mantbits) - 1)
// The upper and lower bounds are possible outputs only if
// the original mantissa is even, so that IEEE round-to-even
diff --git a/libgo/go/strconv/quote.go b/libgo/go/strconv/quote.go
index 05e49d32ddf..bbb9783ce8d 100644
--- a/libgo/go/strconv/quote.go
+++ b/libgo/go/strconv/quote.go
@@ -288,6 +288,22 @@ func Unquote(s string) (t string, err os.Error) {
if quote != '"' && quote != '\'' {
return "", os.EINVAL
}
+ if strings.Index(s, "\n") >= 0 {
+ return "", os.EINVAL
+ }
+
+ // Is it trivial? Avoid allocation.
+ if strings.Index(s, `\`) < 0 && strings.IndexRune(s, int(quote)) < 0 {
+ switch quote {
+ case '"':
+ return s, nil
+ case '\'':
+ r, size := utf8.DecodeRuneInString(s)
+ if size == len(s) && (r != utf8.RuneError || size != 1) {
+ return s, nil
+ }
+ }
+ }
var buf bytes.Buffer
for len(s) > 0 {
diff --git a/libgo/go/strconv/quote_test.go b/libgo/go/strconv/quote_test.go
index 4d615db443a..0311f77a3a7 100644
--- a/libgo/go/strconv/quote_test.go
+++ b/libgo/go/strconv/quote_test.go
@@ -168,6 +168,7 @@ var unquotetests = []unQuoteTest{
{"`\\xFF`", `\xFF`},
{"`\\377`", `\377`},
{"`\\`", `\`},
+ {"`\n`", "\n"},
{"` `", ` `},
{"` `", ` `},
}
@@ -189,6 +190,9 @@ var misquoted = []string{
"`\"",
`"\'"`,
`'\"'`,
+ "\"\n\"",
+ "\"\\n\n\"",
+ "'\n'",
}
func TestUnquote(t *testing.T) {
@@ -211,3 +215,15 @@ func TestUnquote(t *testing.T) {
}
}
}
+
+func BenchmarkUnquoteEasy(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Unquote(`"Give me a rock, paper and scissors and I will move the world."`)
+ }
+}
+
+func BenchmarkUnquoteHard(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ Unquote(`"\x47ive me a \x72ock, \x70aper and \x73cissors and \x49 will move the world."`)
+ }
+}
diff --git a/libgo/go/strings/export_test.go b/libgo/go/strings/export_test.go
new file mode 100644
index 00000000000..dcfec513ccf
--- /dev/null
+++ b/libgo/go/strings/export_test.go
@@ -0,0 +1,9 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strings
+
+func (r *Replacer) Replacer() interface{} {
+ return r.r
+}
diff --git a/libgo/go/strings/replace.go b/libgo/go/strings/replace.go
new file mode 100644
index 00000000000..64a7f208b93
--- /dev/null
+++ b/libgo/go/strings/replace.go
@@ -0,0 +1,315 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strings
+
+import (
+ "io"
+ "os"
+)
+
+// A Replacer replaces a list of strings with replacements.
+type Replacer struct {
+ r replacer
+}
+
+// replacer is the interface that a replacement algorithm needs to implement.
+type replacer interface {
+ Replace(s string) string
+ WriteString(w io.Writer, s string) (n int, err os.Error)
+}
+
+// byteBitmap represents bytes which are sought for replacement.
+// byteBitmap is 256 bits wide, with a bit set for each old byte to be
+// replaced.
+type byteBitmap [256 / 32]uint32
+
+func (m *byteBitmap) set(b byte) {
+ m[b>>5] |= uint32(1 << (b & 31))
+}
+
+// NewReplacer returns a new Replacer from a list of old, new string pairs.
+// Replacements are performed in order, without overlapping matches.
+func NewReplacer(oldnew ...string) *Replacer {
+ if len(oldnew)%2 == 1 {
+ panic("strings.NewReplacer: odd argument count")
+ }
+
+ // Possible implementations.
+ var (
+ bb byteReplacer
+ bs byteStringReplacer
+ gen genericReplacer
+ )
+
+ allOldBytes, allNewBytes := true, true
+ for len(oldnew) > 0 {
+ old, new := oldnew[0], oldnew[1]
+ oldnew = oldnew[2:]
+ if len(old) != 1 {
+ allOldBytes = false
+ }
+ if len(new) != 1 {
+ allNewBytes = false
+ }
+
+ // generic
+ gen.p = append(gen.p, pair{old, new})
+
+ // byte -> string
+ if allOldBytes {
+ bs.old.set(old[0])
+ bs.new[old[0]] = []byte(new)
+ }
+
+ // byte -> byte
+ if allOldBytes && allNewBytes {
+ bb.old.set(old[0])
+ bb.new[old[0]] = new[0]
+ }
+ }
+
+ if allOldBytes && allNewBytes {
+ return &Replacer{r: &bb}
+ }
+ if allOldBytes {
+ return &Replacer{r: &bs}
+ }
+ return &Replacer{r: &gen}
+}
+
+// Replace returns a copy of s with all replacements performed.
+func (r *Replacer) Replace(s string) string {
+ return r.r.Replace(s)
+}
+
+// WriteString writes s to w with all replacements performed.
+func (r *Replacer) WriteString(w io.Writer, s string) (n int, err os.Error) {
+ return r.r.WriteString(w, s)
+}
+
+// genericReplacer is the fully generic (and least optimized) algorithm.
+// It's used as a fallback when nothing faster can be used.
+type genericReplacer struct {
+ p []pair
+}
+
+type pair struct{ old, new string }
+
+type appendSliceWriter struct {
+ b []byte
+}
+
+func (w *appendSliceWriter) Write(p []byte) (int, os.Error) {
+ w.b = append(w.b, p...)
+ return len(p), nil
+}
+
+func (r *genericReplacer) Replace(s string) string {
+ // TODO(bradfitz): optimized version
+ n, _ := r.WriteString(discard, s)
+ w := appendSliceWriter{make([]byte, 0, n)}
+ r.WriteString(&w, s)
+ return string(w.b)
+}
+
+func (r *genericReplacer) WriteString(w io.Writer, s string) (n int, err os.Error) {
+ lastEmpty := false // the last replacement was of the empty string
+Input:
+ // TODO(bradfitz): optimized version
+ for i := 0; i < len(s); {
+ for _, p := range r.p {
+ if p.old == "" && lastEmpty {
+ // Don't let old match twice in a row.
+ // (it doesn't advance the input and
+ // would otherwise loop forever)
+ continue
+ }
+ if HasPrefix(s[i:], p.old) {
+ if p.new != "" {
+ wn, err := w.Write([]byte(p.new))
+ n += wn
+ if err != nil {
+ return n, err
+ }
+ }
+ i += len(p.old)
+ lastEmpty = p.old == ""
+ continue Input
+ }
+ }
+ wn, err := w.Write([]byte{s[i]})
+ n += wn
+ if err != nil {
+ return n, err
+ }
+ i++
+ }
+
+ // Final empty match at end.
+ for _, p := range r.p {
+ if p.old == "" {
+ if p.new != "" {
+ wn, err := w.Write([]byte(p.new))
+ n += wn
+ if err != nil {
+ return n, err
+ }
+ }
+ break
+ }
+ }
+
+ return n, nil
+}
+
+// byteReplacer is the implementation that's used when all the "old"
+// and "new" values are single ASCII bytes.
+type byteReplacer struct {
+ // old has a bit set for each old byte that should be replaced.
+ old byteBitmap
+
+ // replacement byte, indexed by old byte. only valid if
+ // corresponding old bit is set.
+ new [256]byte
+}
+
+func (r *byteReplacer) Replace(s string) string {
+ var buf []byte // lazily allocated
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+ if buf == nil {
+ buf = []byte(s)
+ }
+ buf[i] = r.new[b]
+ }
+ }
+ if buf == nil {
+ return s
+ }
+ return string(buf)
+}
+
+func (r *byteReplacer) WriteString(w io.Writer, s string) (n int, err os.Error) {
+ // TODO(bradfitz): use io.WriteString with slices of s, avoiding allocation.
+ bufsize := 32 << 10
+ if len(s) < bufsize {
+ bufsize = len(s)
+ }
+ buf := make([]byte, bufsize)
+
+ for len(s) > 0 {
+ ncopy := copy(buf, s[:])
+ s = s[ncopy:]
+ for i, b := range buf[:ncopy] {
+ if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+ buf[i] = r.new[b]
+ }
+ }
+ wn, err := w.Write(buf[:ncopy])
+ n += wn
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+}
+
+// byteStringReplacer is the implementation that's used when all the
+// "old" values are single ASCII bytes but the "new" values vary in
+// size.
+type byteStringReplacer struct {
+ // old has a bit set for each old byte that should be replaced.
+ old byteBitmap
+
+ // replacement string, indexed by old byte. only valid if
+ // corresponding old bit is set.
+ new [256][]byte
+}
+
+func (r *byteStringReplacer) Replace(s string) string {
+ newSize := 0
+ anyChanges := false
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+ anyChanges = true
+ newSize += len(r.new[b])
+ } else {
+ newSize++
+ }
+ }
+ if !anyChanges {
+ return s
+ }
+ buf := make([]byte, newSize)
+ bi := buf
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+ n := copy(bi[:], r.new[b])
+ bi = bi[n:]
+ } else {
+ bi[0] = b
+ bi = bi[1:]
+ }
+ }
+ return string(buf)
+}
+
+// WriteString maintains one buffer that's at most 32KB. The bytes in
+// s are enumerated and the buffer is filled. If it reaches its
+// capacity or a byte has a replacement, the buffer is flushed to w.
+func (r *byteStringReplacer) WriteString(w io.Writer, s string) (n int, err os.Error) {
+ // TODO(bradfitz): use io.WriteString with slices of s instead.
+ bufsize := 32 << 10
+ if len(s) < bufsize {
+ bufsize = len(s)
+ }
+ buf := make([]byte, bufsize)
+ bi := buf[:0]
+
+ for i := 0; i < len(s); i++ {
+ b := s[i]
+ var new []byte
+ if r.old[b>>5]&uint32(1<<(b&31)) != 0 {
+ new = r.new[b]
+ } else {
+ bi = append(bi, b)
+ }
+ if len(bi) == cap(bi) || (len(bi) > 0 && len(new) > 0) {
+ nw, err := w.Write(bi)
+ n += nw
+ if err != nil {
+ return n, err
+ }
+ bi = buf[:0]
+ }
+ if len(new) > 0 {
+ nw, err := w.Write(new)
+ n += nw
+ if err != nil {
+ return n, err
+ }
+ }
+ }
+ if len(bi) > 0 {
+ nw, err := w.Write(bi)
+ n += nw
+ if err != nil {
+ return n, err
+ }
+ }
+ return n, nil
+}
+
+// strings is too low-level to import io/ioutil
+var discard io.Writer = devNull(0)
+
+type devNull int
+
+func (devNull) Write(p []byte) (int, os.Error) {
+ return len(p), nil
+}
diff --git a/libgo/go/strings/replace_test.go b/libgo/go/strings/replace_test.go
new file mode 100644
index 00000000000..e337856c64d
--- /dev/null
+++ b/libgo/go/strings/replace_test.go
@@ -0,0 +1,174 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package strings_test
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ . "strings"
+ "testing"
+)
+
+var _ = log.Printf
+
+type ReplacerTest struct {
+ r *Replacer
+ in string
+ out string
+}
+
+var htmlEscaper = NewReplacer("&", "&amp;", "<", "&lt;", ">", "&gt;", "\"", "&quot;")
+
+// The http package's old HTML escaping function.
+func oldhtmlEscape(s string) string {
+ s = Replace(s, "&", "&amp;", -1)
+ s = Replace(s, "<", "&lt;", -1)
+ s = Replace(s, ">", "&gt;", -1)
+ s = Replace(s, "\"", "&quot;", -1)
+ s = Replace(s, "'", "&apos;", -1)
+ return s
+}
+
+var replacer = NewReplacer("aaa", "3[aaa]", "aa", "2[aa]", "a", "1[a]", "i", "i",
+ "longerst", "most long", "longer", "medium", "long", "short",
+ "X", "Y", "Y", "Z")
+
+var capitalLetters = NewReplacer("a", "A", "b", "B")
+
+var blankToXReplacer = NewReplacer("", "X", "o", "O")
+
+var ReplacerTests = []ReplacerTest{
+ // byte->string
+ {htmlEscaper, "No changes", "No changes"},
+ {htmlEscaper, "I <3 escaping & stuff", "I &lt;3 escaping &amp; stuff"},
+ {htmlEscaper, "&&&", "&amp;&amp;&amp;"},
+
+ // generic
+ {replacer, "fooaaabar", "foo3[aaa]b1[a]r"},
+ {replacer, "long, longerst, longer", "short, most long, medium"},
+ {replacer, "XiX", "YiY"},
+
+ // byte->byte
+ {capitalLetters, "brad", "BrAd"},
+ {capitalLetters, Repeat("a", (32<<10)+123), Repeat("A", (32<<10)+123)},
+
+ // hitting "" special case
+ {blankToXReplacer, "oo", "XOXOX"},
+}
+
+func TestReplacer(t *testing.T) {
+ for i, tt := range ReplacerTests {
+ if s := tt.r.Replace(tt.in); s != tt.out {
+ t.Errorf("%d. Replace(%q) = %q, want %q", i, tt.in, s, tt.out)
+ }
+ var buf bytes.Buffer
+ n, err := tt.r.WriteString(&buf, tt.in)
+ if err != nil {
+ t.Errorf("%d. WriteString: %v", i, err)
+ continue
+ }
+ got := buf.String()
+ if got != tt.out {
+ t.Errorf("%d. WriteString(%q) wrote %q, want %q", i, tt.in, got, tt.out)
+ continue
+ }
+ if n != len(tt.out) {
+ t.Errorf("%d. WriteString(%q) wrote correct string but reported %d bytes; want %d (%q)",
+ i, tt.in, n, len(tt.out), tt.out)
+ }
+ }
+}
+
+// pickAlgorithmTest is a test that verifies that given input for a
+// Replacer that we pick the correct algorithm.
+type pickAlgorithmTest struct {
+ r *Replacer
+ want string // name of algorithm
+}
+
+var pickAlgorithmTests = []pickAlgorithmTest{
+ {capitalLetters, "*strings.byteReplacer"},
+ {NewReplacer("12", "123"), "*strings.genericReplacer"},
+ {NewReplacer("1", "12"), "*strings.byteStringReplacer"},
+ {htmlEscaper, "*strings.byteStringReplacer"},
+}
+
+func TestPickAlgorithm(t *testing.T) {
+ for i, tt := range pickAlgorithmTests {
+ got := fmt.Sprintf("%T", tt.r.Replacer())
+ if got != tt.want {
+ t.Errorf("%d. algorithm = %s, want %s", i, got, tt.want)
+ }
+ }
+}
+
+func BenchmarkGenericMatch(b *testing.B) {
+ str := Repeat("A", 100) + Repeat("B", 100)
+ generic := NewReplacer("a", "A", "b", "B", "12", "123") // varying lengths forces generic
+ for i := 0; i < b.N; i++ {
+ generic.Replace(str)
+ }
+}
+
+func BenchmarkByteByteNoMatch(b *testing.B) {
+ str := Repeat("A", 100) + Repeat("B", 100)
+ for i := 0; i < b.N; i++ {
+ capitalLetters.Replace(str)
+ }
+}
+
+func BenchmarkByteByteMatch(b *testing.B) {
+ str := Repeat("a", 100) + Repeat("b", 100)
+ for i := 0; i < b.N; i++ {
+ capitalLetters.Replace(str)
+ }
+}
+
+func BenchmarkByteStringMatch(b *testing.B) {
+ str := "<" + Repeat("a", 99) + Repeat("b", 99) + ">"
+ for i := 0; i < b.N; i++ {
+ htmlEscaper.Replace(str)
+ }
+}
+
+func BenchmarkHTMLEscapeNew(b *testing.B) {
+ str := "I <3 to escape HTML & other text too."
+ for i := 0; i < b.N; i++ {
+ htmlEscaper.Replace(str)
+ }
+}
+
+func BenchmarkHTMLEscapeOld(b *testing.B) {
+ str := "I <3 to escape HTML & other text too."
+ for i := 0; i < b.N; i++ {
+ oldhtmlEscape(str)
+ }
+}
+
+// BenchmarkByteByteReplaces compares byteByteImpl against multiple Replaces.
+func BenchmarkByteByteReplaces(b *testing.B) {
+ str := Repeat("a", 100) + Repeat("b", 100)
+ for i := 0; i < b.N; i++ {
+ Replace(Replace(str, "a", "A", -1), "b", "B", -1)
+ }
+}
+
+// BenchmarkByteByteMap compares byteByteImpl against Map.
+func BenchmarkByteByteMap(b *testing.B) {
+ str := Repeat("a", 100) + Repeat("b", 100)
+ fn := func(r int) int {
+ switch r {
+ case 'a':
+ return int('A')
+ case 'b':
+ return int('B')
+ }
+ return r
+ }
+ for i := 0; i < b.N; i++ {
+ Map(fn, str)
+ }
+}
diff --git a/libgo/go/strings/strings.go b/libgo/go/strings/strings.go
index c547297e66c..58301febdf8 100644
--- a/libgo/go/strings/strings.go
+++ b/libgo/go/strings/strings.go
@@ -583,3 +583,58 @@ func Replace(s, old, new string, n int) string {
w += copy(t[w:], s[start:])
return string(t[0:w])
}
+
+// EqualFold reports whether s and t, interpreted as UTF-8 strings,
+// are equal under Unicode case-folding.
+func EqualFold(s, t string) bool {
+ for s != "" && t != "" {
+ // Extract first rune from each string.
+ var sr, tr int
+ if s[0] < utf8.RuneSelf {
+ sr, s = int(s[0]), s[1:]
+ } else {
+ r, size := utf8.DecodeRuneInString(s)
+ sr, s = r, s[size:]
+ }
+ if t[0] < utf8.RuneSelf {
+ tr, t = int(t[0]), t[1:]
+ } else {
+ r, size := utf8.DecodeRuneInString(t)
+ tr, t = r, t[size:]
+ }
+
+ // If they match, keep going; if not, return false.
+
+ // Easy case.
+ if tr == sr {
+ continue
+ }
+
+ // Make sr < tr to simplify what follows.
+ if tr < sr {
+ tr, sr = sr, tr
+ }
+ // Fast check for ASCII.
+ if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
+ // ASCII, and sr is upper case. tr must be lower case.
+ if tr == sr+'a'-'A' {
+ continue
+ }
+ return false
+ }
+
+ // General case. SimpleFold(x) returns the next equivalent rune > x
+ // or wraps around to smaller values.
+ r := unicode.SimpleFold(sr)
+ for r != sr && r < tr {
+ r = unicode.SimpleFold(r)
+ }
+ if r == tr {
+ continue
+ }
+ return false
+ }
+
+ // One string is empty. Are both?
+ return s == t
+}
diff --git a/libgo/go/strings/strings_test.go b/libgo/go/strings/strings_test.go
index 409d4da0e23..0859ddd9623 100644
--- a/libgo/go/strings/strings_test.go
+++ b/libgo/go/strings/strings_test.go
@@ -120,13 +120,11 @@ func TestLastIndex(t *testing.T) { runIndexTests(t, LastIndex, "LastIndex", l
func TestIndexAny(t *testing.T) { runIndexTests(t, IndexAny, "IndexAny", indexAnyTests) }
func TestLastIndexAny(t *testing.T) { runIndexTests(t, LastIndexAny, "LastIndexAny", lastIndexAnyTests) }
-type IndexRuneTest struct {
+var indexRuneTests = []struct {
s string
rune int
out int
-}
-
-var indexRuneTests = []IndexRuneTest{
+}{
{"a A x", 'A', 2},
{"some_text=some_value", '=', 9},
{"☺a", 'a', 3},
@@ -170,13 +168,11 @@ func BenchmarkIndex(b *testing.B) {
}
}
-type ExplodeTest struct {
+var explodetests = []struct {
s string
n int
a []string
-}
-
-var explodetests = []ExplodeTest{
+}{
{"", -1, []string{}},
{abcd, 4, []string{"a", "b", "c", "d"}},
{faces, 3, []string{"☺", "☻", "☹"}},
@@ -308,15 +304,16 @@ func TestFields(t *testing.T) {
}
}
+var FieldsFuncTests = []FieldsTest{
+ {"", []string{}},
+ {"XX", []string{}},
+ {"XXhiXXX", []string{"hi"}},
+ {"aXXbXXXcX", []string{"a", "b", "c"}},
+}
+
func TestFieldsFunc(t *testing.T) {
pred := func(c int) bool { return c == 'X' }
- var fieldsFuncTests = []FieldsTest{
- {"", []string{}},
- {"XX", []string{}},
- {"XXhiXXX", []string{"hi"}},
- {"aXXbXXXcX", []string{"a", "b", "c"}},
- }
- for _, tt := range fieldsFuncTests {
+ for _, tt := range FieldsFuncTests {
a := FieldsFunc(tt.s, pred)
if !eq(a, tt.a) {
t.Errorf("FieldsFunc(%q) = %v, want %v", tt.s, a, tt.a)
@@ -491,12 +488,10 @@ func TestSpecialCase(t *testing.T) {
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
-type TrimTest struct {
+var trimTests = []struct {
f func(string, string) string
in, cutset, out string
-}
-
-var trimTests = []TrimTest{
+}{
{Trim, "abba", "a", "bb"},
{Trim, "abba", "ab", ""},
{TrimLeft, "abba", "ab", ""},
@@ -555,11 +550,6 @@ var isValidRune = predicate{
"IsValidRune",
}
-type TrimFuncTest struct {
- f predicate
- in, out string
-}
-
func not(p predicate) predicate {
return predicate{
func(r int) bool {
@@ -569,7 +559,10 @@ func not(p predicate) predicate {
}
}
-var trimFuncTests = []TrimFuncTest{
+var trimFuncTests = []struct {
+ f predicate
+ in, out string
+}{
{isSpace, space + " hello " + space, "hello"},
{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
@@ -588,13 +581,11 @@ func TestTrimFunc(t *testing.T) {
}
}
-type IndexFuncTest struct {
+var indexFuncTests = []struct {
in string
f predicate
first, last int
-}
-
-var indexFuncTests = []IndexFuncTest{
+}{
{"", isValidRune, -1, -1},
{"abc", isDigit, -1, -1},
{"0123", isDigit, 0, 3},
@@ -692,12 +683,10 @@ func TestCaseConsistency(t *testing.T) {
*/
}
-type RepeatTest struct {
+var RepeatTests = []struct {
in, out string
count int
-}
-
-var RepeatTests = []RepeatTest{
+}{
{"", "", 0},
{"", "", 1},
{"", "", 2},
@@ -729,13 +718,11 @@ func runesEqual(a, b []int) bool {
return true
}
-type RunesTest struct {
+var RunesTests = []struct {
in string
out []int
lossy bool
-}
-
-var RunesTests = []RunesTest{
+}{
{"", []int{}, false},
{" ", []int{32}, false},
{"ABC", []int{65, 66, 67}, false},
@@ -846,14 +833,12 @@ func TestReadRune(t *testing.T) {
}
}
-type ReplaceTest struct {
+var ReplaceTests = []struct {
in string
old, new string
n int
out string
-}
-
-var ReplaceTests = []ReplaceTest{
+}{
{"hello", "l", "L", 0, "hello"},
{"hello", "l", "L", -1, "heLLo"},
{"hello", "x", "X", -1, "hello"},
@@ -883,11 +868,9 @@ func TestReplace(t *testing.T) {
}
}
-type TitleTest struct {
+var TitleTests = []struct {
in, out string
-}
-
-var TitleTests = []TitleTest{
+}{
{"", ""},
{"a", "A"},
{" aaa aaa aaa ", " Aaa Aaa Aaa "},
@@ -905,12 +888,10 @@ func TestTitle(t *testing.T) {
}
}
-type ContainsTest struct {
+var ContainsTests = []struct {
str, substr string
expected bool
-}
-
-var ContainsTests = []ContainsTest{
+}{
{"abc", "bc", true},
{"abc", "bcd", false},
{"abc", "", true},
@@ -925,3 +906,31 @@ func TestContains(t *testing.T) {
}
}
}
+
+var EqualFoldTests = []struct {
+ s, t string
+ out bool
+}{
+ {"abc", "abc", true},
+ {"ABcd", "ABcd", true},
+ {"123abc", "123ABC", true},
+ {"αβδ", "ΑΒΔ", true},
+ {"abc", "xyz", false},
+ {"abc", "XYZ", false},
+ {"abcdefghijk", "abcdefghijX", false},
+ {"abcdefghijk", "abcdefghij\u212A", true},
+ {"abcdefghijK", "abcdefghij\u212A", true},
+ {"abcdefghijkz", "abcdefghij\u212Ay", false},
+ {"abcdefghijKz", "abcdefghij\u212Ay", false},
+}
+
+func TestEqualFold(t *testing.T) {
+ for _, tt := range EqualFoldTests {
+ if out := EqualFold(tt.s, tt.t); out != tt.out {
+ t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.s, tt.t, out, tt.out)
+ }
+ if out := EqualFold(tt.t, tt.s); out != tt.out {
+ t.Errorf("EqualFold(%#q, %#q) = %v, want %v", tt.t, tt.s, out, tt.out)
+ }
+ }
+}
diff --git a/libgo/go/sync/atomic/atomic.c b/libgo/go/sync/atomic/atomic.c
index 6660a7d4a91..e5de5ee3c79 100644
--- a/libgo/go/sync/atomic/atomic.c
+++ b/libgo/go/sync/atomic/atomic.c
@@ -51,6 +51,15 @@ CompareAndSwapUintptr (uintptr_t *val, uintptr_t old, uintptr_t new)
return __sync_bool_compare_and_swap (val, old, new);
}
+_Bool CompareAndSwapPointer (void **, void *, void *)
+ asm ("libgo_sync.atomic.CompareAndSwapPointer");
+
+_Bool
+CompareAndSwapPointer (void **val, void *old, void *new)
+{
+ return __sync_bool_compare_and_swap (val, old, new);
+}
+
int32_t AddInt32 (int32_t *, int32_t)
asm ("libgo_sync.atomic.AddInt32");
@@ -110,6 +119,20 @@ LoadInt32 (int32_t *addr)
return v;
}
+int64_t LoadInt64 (int64_t *addr)
+ asm ("libgo_sync.atomic.LoadInt64");
+
+int64_t
+LoadInt64 (int64_t *addr)
+{
+ int64_t v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, v))
+ v = *addr;
+ return v;
+}
+
uint32_t LoadUint32 (uint32_t *addr)
asm ("libgo_sync.atomic.LoadUint32");
@@ -123,3 +146,123 @@ LoadUint32 (uint32_t *addr)
v = *addr;
return v;
}
+
+uint64_t LoadUint64 (uint64_t *addr)
+ asm ("libgo_sync.atomic.LoadUint64");
+
+uint64_t
+LoadUint64 (uint64_t *addr)
+{
+ uint64_t v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, v))
+ v = *addr;
+ return v;
+}
+
+uintptr_t LoadUintptr (uintptr_t *addr)
+ asm ("libgo_sync.atomic.LoadUintptr");
+
+uintptr_t
+LoadUintptr (uintptr_t *addr)
+{
+ uintptr_t v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, v))
+ v = *addr;
+ return v;
+}
+
+void *LoadPointer (void **addr)
+ asm ("libgo_sync.atomic.LoadPointer");
+
+void *
+LoadPointer (void **addr)
+{
+ void *v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, v))
+ v = *addr;
+ return v;
+}
+
+void StoreInt32 (int32_t *addr, int32_t val)
+ asm ("libgo_sync.atomic.StoreInt32");
+
+void
+StoreInt32 (int32_t *addr, int32_t val)
+{
+ int32_t v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, val))
+ v = *addr;
+}
+
+void StoreInt64 (int64_t *addr, int64_t val)
+ asm ("libgo_sync.atomic.StoreInt64");
+
+void
+StoreInt64 (int64_t *addr, int64_t val)
+{
+ int64_t v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, val))
+ v = *addr;
+}
+
+void StoreUint32 (uint32_t *addr, uint32_t val)
+ asm ("libgo_sync.atomic.StoreUint32");
+
+void
+StoreUint32 (uint32_t *addr, uint32_t val)
+{
+ uint32_t v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, val))
+ v = *addr;
+}
+
+void StoreUint64 (uint64_t *addr, uint64_t val)
+ asm ("libgo_sync.atomic.StoreUint64");
+
+void
+StoreUint64 (uint64_t *addr, uint64_t val)
+{
+ uint64_t v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, val))
+ v = *addr;
+}
+
+void StoreUintptr (uintptr_t *addr, uintptr_t val)
+ asm ("libgo_sync.atomic.StoreUintptr");
+
+void
+StoreUintptr (uintptr_t *addr, uintptr_t val)
+{
+ uintptr_t v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, val))
+ v = *addr;
+}
+
+void StorePointer (void **addr, void *val)
+ asm ("libgo_sync.atomic.StorePointer");
+
+void
+StorePointer (void **addr, void *val)
+{
+ void *v;
+
+ v = *addr;
+ while (! __sync_bool_compare_and_swap (addr, v, val))
+ v = *addr;
+}
diff --git a/libgo/go/sync/atomic/atomic_test.go b/libgo/go/sync/atomic/atomic_test.go
index 2229e58d0c7..02ee24b3556 100644
--- a/libgo/go/sync/atomic/atomic_test.go
+++ b/libgo/go/sync/atomic/atomic_test.go
@@ -164,17 +164,17 @@ func TestCompareAndSwapInt32(t *testing.T) {
for val := int32(1); val+val > val; val += val {
x.i = val
if !CompareAndSwapInt32(&x.i, val, val+1) {
- t.Errorf("should have swapped %#x %#x", val, val+1)
+ t.Fatalf("should have swapped %#x %#x", val, val+1)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
x.i = val + 1
if CompareAndSwapInt32(&x.i, val, val+2) {
- t.Errorf("should not have swapped %#x %#x", val, val+2)
+ t.Fatalf("should not have swapped %#x %#x", val, val+2)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
}
if x.before != magic32 || x.after != magic32 {
@@ -193,17 +193,17 @@ func TestCompareAndSwapUint32(t *testing.T) {
for val := uint32(1); val+val > val; val += val {
x.i = val
if !CompareAndSwapUint32(&x.i, val, val+1) {
- t.Errorf("should have swapped %#x %#x", val, val+1)
+ t.Fatalf("should have swapped %#x %#x", val, val+1)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
x.i = val + 1
if CompareAndSwapUint32(&x.i, val, val+2) {
- t.Errorf("should not have swapped %#x %#x", val, val+2)
+ t.Fatalf("should not have swapped %#x %#x", val, val+2)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
}
if x.before != magic32 || x.after != magic32 {
@@ -226,17 +226,17 @@ func TestCompareAndSwapInt64(t *testing.T) {
for val := int64(1); val+val > val; val += val {
x.i = val
if !CompareAndSwapInt64(&x.i, val, val+1) {
- t.Errorf("should have swapped %#x %#x", val, val+1)
+ t.Fatalf("should have swapped %#x %#x", val, val+1)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
x.i = val + 1
if CompareAndSwapInt64(&x.i, val, val+2) {
- t.Errorf("should not have swapped %#x %#x", val, val+2)
+ t.Fatalf("should not have swapped %#x %#x", val, val+2)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
}
if x.before != magic64 || x.after != magic64 {
@@ -259,17 +259,17 @@ func TestCompareAndSwapUint64(t *testing.T) {
for val := uint64(1); val+val > val; val += val {
x.i = val
if !CompareAndSwapUint64(&x.i, val, val+1) {
- t.Errorf("should have swapped %#x %#x", val, val+1)
+ t.Fatalf("should have swapped %#x %#x", val, val+1)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
x.i = val + 1
if CompareAndSwapUint64(&x.i, val, val+2) {
- t.Errorf("should not have swapped %#x %#x", val, val+2)
+ t.Fatalf("should not have swapped %#x %#x", val, val+2)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
}
if x.before != magic64 || x.after != magic64 {
@@ -290,17 +290,48 @@ func TestCompareAndSwapUintptr(t *testing.T) {
for val := uintptr(1); val+val > val; val += val {
x.i = val
if !CompareAndSwapUintptr(&x.i, val, val+1) {
- t.Errorf("should have swapped %#x %#x", val, val+1)
+ t.Fatalf("should have swapped %#x %#x", val, val+1)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
x.i = val + 1
if CompareAndSwapUintptr(&x.i, val, val+2) {
- t.Errorf("should not have swapped %#x %#x", val, val+2)
+ t.Fatalf("should not have swapped %#x %#x", val, val+2)
}
if x.i != val+1 {
- t.Errorf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ }
+ }
+ if x.before != magicptr || x.after != magicptr {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+ }
+}
+
+func TestCompareAndSwapPointer(t *testing.T) {
+ var x struct {
+ before uintptr
+ i unsafe.Pointer
+ after uintptr
+ }
+ var m uint64 = magic64
+ magicptr := uintptr(m)
+ x.before = magicptr
+ x.after = magicptr
+ for val := uintptr(1); val+val > val; val += val {
+ x.i = unsafe.Pointer(val)
+ if !CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+1)) {
+ t.Fatalf("should have swapped %#x %#x", val, val+1)
+ }
+ if x.i != unsafe.Pointer(val+1) {
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
+ }
+ x.i = unsafe.Pointer(val + 1)
+ if CompareAndSwapPointer(&x.i, unsafe.Pointer(val), unsafe.Pointer(val+2)) {
+ t.Fatalf("should not have swapped %#x %#x", val, val+2)
+ }
+ if x.i != unsafe.Pointer(val+1) {
+ t.Fatalf("wrong x.i after swap: x.i=%#x val+1=%#x", x.i, val+1)
}
}
if x.before != magicptr || x.after != magicptr {
@@ -348,6 +379,236 @@ func TestLoadUint32(t *testing.T) {
}
}
+func TestLoadInt64(t *testing.T) {
+ if test64err != nil {
+ t.Logf("Skipping 64-bit tests: %v", test64err)
+ return
+ }
+ var x struct {
+ before int64
+ i int64
+ after int64
+ }
+ x.before = magic64
+ x.after = magic64
+ for delta := int64(1); delta+delta > delta; delta += delta {
+ k := LoadInt64(&x.i)
+ if k != x.i {
+ t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+ }
+ x.i += delta
+ }
+ if x.before != magic64 || x.after != magic64 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+ }
+}
+
+func TestLoadUint64(t *testing.T) {
+ if test64err != nil {
+ t.Logf("Skipping 64-bit tests: %v", test64err)
+ return
+ }
+ var x struct {
+ before uint64
+ i uint64
+ after uint64
+ }
+ x.before = magic64
+ x.after = magic64
+ for delta := uint64(1); delta+delta > delta; delta += delta {
+ k := LoadUint64(&x.i)
+ if k != x.i {
+ t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+ }
+ x.i += delta
+ }
+ if x.before != magic64 || x.after != magic64 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+ }
+}
+
+func TestLoadUintptr(t *testing.T) {
+ var x struct {
+ before uintptr
+ i uintptr
+ after uintptr
+ }
+ var m uint64 = magic64
+ magicptr := uintptr(m)
+ x.before = magicptr
+ x.after = magicptr
+ for delta := uintptr(1); delta+delta > delta; delta += delta {
+ k := LoadUintptr(&x.i)
+ if k != x.i {
+ t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+ }
+ x.i += delta
+ }
+ if x.before != magicptr || x.after != magicptr {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+ }
+}
+
+func TestLoadPointer(t *testing.T) {
+ var x struct {
+ before uintptr
+ i unsafe.Pointer
+ after uintptr
+ }
+ var m uint64 = magic64
+ magicptr := uintptr(m)
+ x.before = magicptr
+ x.after = magicptr
+ for delta := uintptr(1); delta+delta > delta; delta += delta {
+ k := LoadPointer(&x.i)
+ if k != x.i {
+ t.Fatalf("delta=%d i=%d k=%d", delta, x.i, k)
+ }
+ x.i = unsafe.Pointer(uintptr(x.i) + delta)
+ }
+ if x.before != magicptr || x.after != magicptr {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+ }
+}
+
+func TestStoreInt32(t *testing.T) {
+ var x struct {
+ before int32
+ i int32
+ after int32
+ }
+ x.before = magic32
+ x.after = magic32
+ v := int32(0)
+ for delta := int32(1); delta+delta > delta; delta += delta {
+ StoreInt32(&x.i, v)
+ if x.i != v {
+ t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+ }
+ v += delta
+ }
+ if x.before != magic32 || x.after != magic32 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+ }
+}
+
+func TestStoreUint32(t *testing.T) {
+ var x struct {
+ before uint32
+ i uint32
+ after uint32
+ }
+ x.before = magic32
+ x.after = magic32
+ v := uint32(0)
+ for delta := uint32(1); delta+delta > delta; delta += delta {
+ StoreUint32(&x.i, v)
+ if x.i != v {
+ t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+ }
+ v += delta
+ }
+ if x.before != magic32 || x.after != magic32 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magic32, magic32)
+ }
+}
+
+func TestStoreInt64(t *testing.T) {
+ if test64err != nil {
+ t.Logf("Skipping 64-bit tests: %v", test64err)
+ return
+ }
+ var x struct {
+ before int64
+ i int64
+ after int64
+ }
+ x.before = magic64
+ x.after = magic64
+ v := int64(0)
+ for delta := int64(1); delta+delta > delta; delta += delta {
+ StoreInt64(&x.i, v)
+ if x.i != v {
+ t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+ }
+ v += delta
+ }
+ if x.before != magic64 || x.after != magic64 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+ }
+}
+
+func TestStoreUint64(t *testing.T) {
+ if test64err != nil {
+ t.Logf("Skipping 64-bit tests: %v", test64err)
+ return
+ }
+ var x struct {
+ before uint64
+ i uint64
+ after uint64
+ }
+ x.before = magic64
+ x.after = magic64
+ v := uint64(0)
+ for delta := uint64(1); delta+delta > delta; delta += delta {
+ StoreUint64(&x.i, v)
+ if x.i != v {
+ t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+ }
+ v += delta
+ }
+ if x.before != magic64 || x.after != magic64 {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, uint64(magic64), uint64(magic64))
+ }
+}
+
+func TestStoreUintptr(t *testing.T) {
+ var x struct {
+ before uintptr
+ i uintptr
+ after uintptr
+ }
+ var m uint64 = magic64
+ magicptr := uintptr(m)
+ x.before = magicptr
+ x.after = magicptr
+ v := uintptr(0)
+ for delta := uintptr(1); delta+delta > delta; delta += delta {
+ StoreUintptr(&x.i, v)
+ if x.i != v {
+ t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+ }
+ v += delta
+ }
+ if x.before != magicptr || x.after != magicptr {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+ }
+}
+
+func TestStorePointer(t *testing.T) {
+ var x struct {
+ before uintptr
+ i unsafe.Pointer
+ after uintptr
+ }
+ var m uint64 = magic64
+ magicptr := uintptr(m)
+ x.before = magicptr
+ x.after = magicptr
+ v := unsafe.Pointer(uintptr(0))
+ for delta := uintptr(1); delta+delta > delta; delta += delta {
+ StorePointer(&x.i, unsafe.Pointer(v))
+ if x.i != v {
+ t.Fatalf("delta=%d i=%d v=%d", delta, x.i, v)
+ }
+ v = unsafe.Pointer(uintptr(v) + delta)
+ }
+ if x.before != magicptr || x.after != magicptr {
+ t.Fatalf("wrong magic: %#x _ %#x != %#x _ %#x", x.before, x.after, magicptr, magicptr)
+ }
+}
+
// Tests of correct behavior, with contention.
// (Is the function atomic?)
//
@@ -366,6 +627,7 @@ var hammer32 = []struct {
{"CompareAndSwapInt32", hammerCompareAndSwapInt32},
{"CompareAndSwapUint32", hammerCompareAndSwapUint32},
{"CompareAndSwapUintptr", hammerCompareAndSwapUintptr32},
+ {"CompareAndSwapPointer", hammerCompareAndSwapPointer32},
}
func init() {
@@ -436,6 +698,20 @@ func hammerCompareAndSwapUintptr32(uval *uint32, count int) {
}
}
+func hammerCompareAndSwapPointer32(uval *uint32, count int) {
+ // only safe when uintptr is 32-bit.
+ // not called on 64-bit systems.
+ val := (*unsafe.Pointer)(unsafe.Pointer(uval))
+ for i := 0; i < count; i++ {
+ for {
+ v := *val
+ if CompareAndSwapPointer(val, v, unsafe.Pointer(uintptr(v)+1)) {
+ break
+ }
+ }
+ }
+}
+
func TestHammer32(t *testing.T) {
const p = 4
n := 100000
@@ -460,7 +736,7 @@ func TestHammer32(t *testing.T) {
<-c
}
if val != uint32(n)*p {
- t.Errorf("%s: val=%d want %d", tt.name, val, n*p)
+ t.Fatalf("%s: val=%d want %d", tt.name, val, n*p)
}
}
}
@@ -475,6 +751,7 @@ var hammer64 = []struct {
{"CompareAndSwapInt64", hammerCompareAndSwapInt64},
{"CompareAndSwapUint64", hammerCompareAndSwapUint64},
{"CompareAndSwapUintptr", hammerCompareAndSwapUintptr64},
+ {"CompareAndSwapPointer", hammerCompareAndSwapPointer64},
}
func init() {
@@ -545,6 +822,20 @@ func hammerCompareAndSwapUintptr64(uval *uint64, count int) {
}
}
+func hammerCompareAndSwapPointer64(uval *uint64, count int) {
+ // only safe when uintptr is 64-bit.
+ // not called on 32-bit systems.
+ val := (*unsafe.Pointer)(unsafe.Pointer(uval))
+ for i := 0; i < count; i++ {
+ for {
+ v := *val
+ if CompareAndSwapPointer(val, v, unsafe.Pointer(uintptr(v)+1)) {
+ break
+ }
+ }
+ }
+}
+
func TestHammer64(t *testing.T) {
if test64err != nil {
t.Logf("Skipping 64-bit tests: %v", test64err)
@@ -573,63 +864,141 @@ func TestHammer64(t *testing.T) {
<-c
}
if val != uint64(n)*p {
- t.Errorf("%s: val=%d want %d", tt.name, val, n*p)
+ t.Fatalf("%s: val=%d want %d", tt.name, val, n*p)
}
}
}
-func hammerLoadInt32(t *testing.T, uval *uint32) {
- val := (*int32)(unsafe.Pointer(uval))
- for {
- v := LoadInt32(val)
+func hammerStoreLoadInt32(t *testing.T, valp unsafe.Pointer) {
+ val := (*int32)(valp)
+ v := LoadInt32(val)
+ vlo := v & ((1 << 16) - 1)
+ vhi := v >> 16
+ if vlo != vhi {
+ t.Fatalf("Int32: %#x != %#x", vlo, vhi)
+ }
+ new := v + 1 + 1<<16
+ if vlo == 1e4 {
+ new = 0
+ }
+ StoreInt32(val, new)
+}
+
+func hammerStoreLoadUint32(t *testing.T, valp unsafe.Pointer) {
+ val := (*uint32)(valp)
+ v := LoadUint32(val)
+ vlo := v & ((1 << 16) - 1)
+ vhi := v >> 16
+ if vlo != vhi {
+ t.Fatalf("Uint32: %#x != %#x", vlo, vhi)
+ }
+ new := v + 1 + 1<<16
+ if vlo == 1e4 {
+ new = 0
+ }
+ StoreUint32(val, new)
+}
+
+func hammerStoreLoadInt64(t *testing.T, valp unsafe.Pointer) {
+ val := (*int64)(valp)
+ v := LoadInt64(val)
+ vlo := v & ((1 << 32) - 1)
+ vhi := v >> 32
+ if vlo != vhi {
+ t.Fatalf("Int64: %#x != %#x", vlo, vhi)
+ }
+ new := v + 1 + 1<<32
+ StoreInt64(val, new)
+}
+
+func hammerStoreLoadUint64(t *testing.T, valp unsafe.Pointer) {
+ val := (*uint64)(valp)
+ v := LoadUint64(val)
+ vlo := v & ((1 << 32) - 1)
+ vhi := v >> 32
+ if vlo != vhi {
+ t.Fatalf("Uint64: %#x != %#x", vlo, vhi)
+ }
+ new := v + 1 + 1<<32
+ StoreUint64(val, new)
+}
+
+func hammerStoreLoadUintptr(t *testing.T, valp unsafe.Pointer) {
+ val := (*uintptr)(valp)
+ var test64 uint64 = 1 << 50
+ arch32 := uintptr(test64) == 0
+ v := LoadUintptr(val)
+ new := v
+ if arch32 {
vlo := v & ((1 << 16) - 1)
vhi := v >> 16
if vlo != vhi {
- t.Fatalf("LoadInt32: %#x != %#x", vlo, vhi)
+ t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
}
- new := v + 1 + 1<<16
+ new = v + 1 + 1<<16
if vlo == 1e4 {
new = 0
}
- if CompareAndSwapInt32(val, v, new) {
- break
+ } else {
+ vlo := v & ((1 << 32) - 1)
+ vhi := v >> 32
+ if vlo != vhi {
+ t.Fatalf("Uintptr: %#x != %#x", vlo, vhi)
}
+ inc := uint64(1 + 1<<32)
+ new = v + uintptr(inc)
}
+ StoreUintptr(val, new)
}
-func hammerLoadUint32(t *testing.T, val *uint32) {
- for {
- v := LoadUint32(val)
+func hammerStoreLoadPointer(t *testing.T, valp unsafe.Pointer) {
+ val := (*unsafe.Pointer)(valp)
+ var test64 uint64 = 1 << 50
+ arch32 := uintptr(test64) == 0
+ v := uintptr(LoadPointer(val))
+ new := v
+ if arch32 {
vlo := v & ((1 << 16) - 1)
vhi := v >> 16
if vlo != vhi {
- t.Fatalf("LoadUint32: %#x != %#x", vlo, vhi)
+ t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
}
- new := v + 1 + 1<<16
+ new = v + 1 + 1<<16
if vlo == 1e4 {
new = 0
}
- if CompareAndSwapUint32(val, v, new) {
- break
+ } else {
+ vlo := v & ((1 << 32) - 1)
+ vhi := v >> 32
+ if vlo != vhi {
+ t.Fatalf("Pointer: %#x != %#x", vlo, vhi)
}
+ inc := uint64(1 + 1<<32)
+ new = v + uintptr(inc)
}
+ StorePointer(val, unsafe.Pointer(new))
}
-func TestHammerLoad(t *testing.T) {
- tests := [...]func(*testing.T, *uint32){hammerLoadInt32, hammerLoadUint32}
- n := 100000
+func TestHammerStoreLoad(t *testing.T) {
+ var tests []func(*testing.T, unsafe.Pointer)
+ tests = append(tests, hammerStoreLoadInt32, hammerStoreLoadUint32,
+ hammerStoreLoadUintptr, hammerStoreLoadPointer)
+ if test64err == nil {
+ tests = append(tests, hammerStoreLoadInt64, hammerStoreLoadUint64)
+ }
+ n := int(1e6)
if testing.Short() {
- n = 10000
+ n = int(1e4)
}
const procs = 8
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(procs))
for _, tt := range tests {
c := make(chan int)
- var val uint32
+ var val uint64
for p := 0; p < procs; p++ {
go func() {
for i := 0; i < n; i++ {
- tt(t, &val)
+ tt(t, unsafe.Pointer(&val))
}
c <- 1
}()
@@ -639,3 +1008,169 @@ func TestHammerLoad(t *testing.T) {
}
}
}
+
+func TestStoreLoadSeqCst32(t *testing.T) {
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+ N := int32(1e3)
+ if testing.Short() {
+ N = int32(1e2)
+ }
+ c := make(chan bool, 2)
+ X := [2]int32{}
+ ack := [2][3]int32{{-1, -1, -1}, {-1, -1, -1}}
+ for p := 0; p < 2; p++ {
+ go func(me int) {
+ he := 1 - me
+ for i := int32(1); i < N; i++ {
+ StoreInt32(&X[me], i)
+ my := LoadInt32(&X[he])
+ StoreInt32(&ack[me][i%3], my)
+ for w := 1; LoadInt32(&ack[he][i%3]) == -1; w++ {
+ if w%1000 == 0 {
+ runtime.Gosched()
+ }
+ }
+ his := LoadInt32(&ack[he][i%3])
+ if (my != i && my != i-1) || (his != i && his != i-1) {
+ t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
+ }
+ if my != i && his != i {
+ t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
+ }
+ ack[me][(i-1)%3] = -1
+ }
+ c <- true
+ }(p)
+ }
+ <-c
+ <-c
+}
+
+func TestStoreLoadSeqCst64(t *testing.T) {
+ if test64err != nil {
+ t.Logf("Skipping 64-bit tests: %v", test64err)
+ return
+ }
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+ N := int64(1e3)
+ if testing.Short() {
+ N = int64(1e2)
+ }
+ c := make(chan bool, 2)
+ X := [2]int64{}
+ ack := [2][3]int64{{-1, -1, -1}, {-1, -1, -1}}
+ for p := 0; p < 2; p++ {
+ go func(me int) {
+ he := 1 - me
+ for i := int64(1); i < N; i++ {
+ StoreInt64(&X[me], i)
+ my := LoadInt64(&X[he])
+ StoreInt64(&ack[me][i%3], my)
+ for w := 1; LoadInt64(&ack[he][i%3]) == -1; w++ {
+ if w%1000 == 0 {
+ runtime.Gosched()
+ }
+ }
+ his := LoadInt64(&ack[he][i%3])
+ if (my != i && my != i-1) || (his != i && his != i-1) {
+ t.Fatalf("invalid values: %d/%d (%d)", my, his, i)
+ }
+ if my != i && his != i {
+ t.Fatalf("store/load are not sequentially consistent: %d/%d (%d)", my, his, i)
+ }
+ ack[me][(i-1)%3] = -1
+ }
+ c <- true
+ }(p)
+ }
+ <-c
+ <-c
+}
+
+func TestStoreLoadRelAcq32(t *testing.T) {
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+ N := int32(1e3)
+ if testing.Short() {
+ N = int32(1e2)
+ }
+ c := make(chan bool, 2)
+ type Data struct {
+ signal int32
+ pad1 [128]int8
+ data1 int32
+ pad2 [128]int8
+ data2 float32
+ }
+ var X Data
+ for p := int32(0); p < 2; p++ {
+ go func(p int32) {
+ for i := int32(1); i < N; i++ {
+ if (i+p)%2 == 0 {
+ X.data1 = i
+ X.data2 = float32(i)
+ StoreInt32(&X.signal, i)
+ } else {
+ for w := 1; LoadInt32(&X.signal) != i; w++ {
+ if w%1000 == 0 {
+ runtime.Gosched()
+ }
+ }
+ d1 := X.data1
+ d2 := X.data2
+ if d1 != i || d2 != float32(i) {
+ t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)
+ }
+ }
+ }
+ c <- true
+ }(p)
+ }
+ <-c
+ <-c
+}
+
+func TestStoreLoadRelAcq64(t *testing.T) {
+ if test64err != nil {
+ t.Logf("Skipping 64-bit tests: %v", test64err)
+ return
+ }
+ defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
+ N := int64(1e3)
+ if testing.Short() {
+ N = int64(1e2)
+ }
+ c := make(chan bool, 2)
+ type Data struct {
+ signal int64
+ pad1 [128]int8
+ data1 int64
+ pad2 [128]int8
+ data2 float64
+ }
+ var X Data
+ for p := int64(0); p < 2; p++ {
+ go func(p int64) {
+ for i := int64(1); i < N; i++ {
+ if (i+p)%2 == 0 {
+ X.data1 = i
+ X.data2 = float64(i)
+ StoreInt64(&X.signal, i)
+ } else {
+ for w := 1; LoadInt64(&X.signal) != i; w++ {
+ if w%1000 == 0 {
+ runtime.Gosched()
+ }
+ }
+ d1 := X.data1
+ d2 := X.data2
+ if d1 != i || d2 != float64(i) {
+ t.Fatalf("incorrect data: %d/%d (%d)", d1, d2, i)
+ }
+ }
+ }
+ c <- true
+ }(p)
+ }
+ <-c
+ <-c
+}
diff --git a/libgo/go/sync/atomic/doc.go b/libgo/go/sync/atomic/doc.go
index b35eb539c05..ecb4808ce58 100644
--- a/libgo/go/sync/atomic/doc.go
+++ b/libgo/go/sync/atomic/doc.go
@@ -22,9 +22,13 @@
//
package atomic
+import (
+ "unsafe"
+)
+
// BUG(rsc): On ARM, the 64-bit functions use instructions unavailable before ARM 11.
//
-// On x86-32, the 64-bit functions use instructions unavailable before the Pentium.
+// On x86-32, the 64-bit functions use instructions unavailable before the Pentium MMX.
// CompareAndSwapInt32 executes the compare-and-swap operation for an int32 value.
func CompareAndSwapInt32(val *int32, old, new int32) (swapped bool)
@@ -41,6 +45,9 @@ func CompareAndSwapUint64(val *uint64, old, new uint64) (swapped bool)
// CompareAndSwapUintptr executes the compare-and-swap operation for a uintptr value.
func CompareAndSwapUintptr(val *uintptr, old, new uintptr) (swapped bool)
+// CompareAndSwapPointer executes the compare-and-swap operation for a unsafe.Pointer value.
+func CompareAndSwapPointer(val *unsafe.Pointer, old, new unsafe.Pointer) (swapped bool)
+
// AddInt32 atomically adds delta to *val and returns the new value.
func AddInt32(val *int32, delta int32) (new int32)
@@ -59,9 +66,39 @@ func AddUintptr(val *uintptr, delta uintptr) (new uintptr)
// LoadInt32 atomically loads *addr.
func LoadInt32(addr *int32) (val int32)
+// LoadInt64 atomically loads *addr.
+func LoadInt64(addr *int64) (val int64)
+
// LoadUint32 atomically loads *addr.
func LoadUint32(addr *uint32) (val uint32)
+// LoadUint64 atomically loads *addr.
+func LoadUint64(addr *uint64) (val uint64)
+
+// LoadUintptr atomically loads *addr.
+func LoadUintptr(addr *uintptr) (val uintptr)
+
+// LoadPointer atomically loads *addr.
+func LoadPointer(addr *unsafe.Pointer) (val unsafe.Pointer)
+
+// StoreInt32 atomically stores val into *addr.
+func StoreInt32(addr *int32, val int32)
+
+// StoreInt64 atomically stores val into *addr.
+func StoreInt64(addr *int64, val int64)
+
+// StoreUint32 atomically stores val into *addr.
+func StoreUint32(addr *uint32, val uint32)
+
+// StoreUint64 atomically stores val into *addr.
+func StoreUint64(addr *uint64, val uint64)
+
+// StoreUintptr atomically stores val into *addr.
+func StoreUintptr(addr *uintptr, val uintptr)
+
+// StorePointer atomically stores val into *addr.
+func StorePointer(addr *unsafe.Pointer, val unsafe.Pointer)
+
// Helper for ARM. Linker will discard on other systems
func panic64() {
panic("sync/atomic: broken 64-bit atomic operations (buggy QEMU)")
diff --git a/libgo/go/syscall/bpf_bsd.go b/libgo/go/syscall/bpf_bsd.go
new file mode 100644
index 00000000000..06a2953e7fe
--- /dev/null
+++ b/libgo/go/syscall/bpf_bsd.go
@@ -0,0 +1,169 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd openbsd
+
+// Berkeley packet filter for BSD variants
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func BpfStmt(code, k int) *BpfInsn {
+ return &BpfInsn{Code: uint16(code), K: uint32(k)}
+}
+
+func BpfJump(code, k, jt, jf int) *BpfInsn {
+ return &BpfInsn{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
+}
+
+func BpfBuflen(fd int) (int, int) {
+ var l int
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGBLEN, uintptr(unsafe.Pointer(&l)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return l, 0
+}
+
+func SetBpfBuflen(fd, l int) (int, int) {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSBLEN, uintptr(unsafe.Pointer(&l)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return l, 0
+}
+
+func BpfDatalink(fd int) (int, int) {
+ var t int
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGDLT, uintptr(unsafe.Pointer(&t)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return t, 0
+}
+
+func SetBpfDatalink(fd, t int) (int, int) {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSDLT, uintptr(unsafe.Pointer(&t)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return t, 0
+}
+
+func SetBpfPromisc(fd, m int) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCPROMISC, uintptr(unsafe.Pointer(&m)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func FlushBpf(fd int) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCFLUSH, 0)
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+type ivalue struct {
+ name [IFNAMSIZ]byte
+ value int16
+}
+
+func BpfInterface(fd int, name string) (string, int) {
+ var iv ivalue
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGETIF, uintptr(unsafe.Pointer(&iv)))
+ if e := int(ep); e != 0 {
+ return "", e
+ }
+ return name, 0
+}
+
+func SetBpfInterface(fd int, name string) int {
+ var iv ivalue
+ copy(iv.name[:], []byte(name))
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETIF, uintptr(unsafe.Pointer(&iv)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func BpfTimeout(fd int) (*Timeval, int) {
+ var tv Timeval
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGRTIMEOUT, uintptr(unsafe.Pointer(&tv)))
+ if e := int(ep); e != 0 {
+ return nil, e
+ }
+ return &tv, 0
+}
+
+func SetBpfTimeout(fd int, tv *Timeval) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSRTIMEOUT, uintptr(unsafe.Pointer(tv)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func BpfStats(fd int) (*BpfStat, int) {
+ var s BpfStat
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGSTATS, uintptr(unsafe.Pointer(&s)))
+ if e := int(ep); e != 0 {
+ return nil, e
+ }
+ return &s, 0
+}
+
+func SetBpfImmediate(fd, m int) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCIMMEDIATE, uintptr(unsafe.Pointer(&m)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func SetBpf(fd int, i []BpfInsn) int {
+ var p BpfProgram
+ p.Len = uint32(len(i))
+ p.Insns = (*BpfInsn)(unsafe.Pointer(&i[0]))
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSETF, uintptr(unsafe.Pointer(&p)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func CheckBpfVersion(fd int) int {
+ var v BpfVersion
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCVERSION, uintptr(unsafe.Pointer(&v)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ if v.Major != BPF_MAJOR_VERSION || v.Minor != BPF_MINOR_VERSION {
+ return EINVAL
+ }
+ return 0
+}
+
+func BpfHeadercmpl(fd int) (int, int) {
+ var f int
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCGHDRCMPLT, uintptr(unsafe.Pointer(&f)))
+ if e := int(ep); e != 0 {
+ return 0, e
+ }
+ return f, 0
+}
+
+func SetBpfHeadercmpl(fd, f int) int {
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(fd), BIOCSHDRCMPLT, uintptr(unsafe.Pointer(&f)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
diff --git a/libgo/go/syscall/errno.c b/libgo/go/syscall/errno.c
new file mode 100644
index 00000000000..854b5aaec28
--- /dev/null
+++ b/libgo/go/syscall/errno.c
@@ -0,0 +1,25 @@
+/* errno.c -- functions for getting and setting errno
+
+ Copyright 2010 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file. */
+
+#include <errno.h>
+
+/* errno is typically a macro. These functions set
+ and get errno specific to the libc being used. */
+
+int GetErrno() asm ("libgo_syscall.syscall.GetErrno");
+void SetErrno(int) asm ("libgo_syscall.syscall.SetErrno");
+
+int
+GetErrno()
+{
+ return errno;
+}
+
+void
+SetErrno(int value)
+{
+ errno = value;
+}
diff --git a/libgo/go/syscall/errstr.go b/libgo/go/syscall/errstr.go
new file mode 100644
index 00000000000..d9f3fe82eb4
--- /dev/null
+++ b/libgo/go/syscall/errstr.go
@@ -0,0 +1,27 @@
+// errstr.go -- Error strings.
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+//sysnb strerror_r(errnum int, buf []byte) (errno int)
+//strerror_r(errnum int, buf *byte, buflen Size_t) int
+
+func Errstr(errnum int) string {
+ for len := 128; ; len *= 2 {
+ b := make([]byte, len)
+ err := strerror_r(errnum, b)
+ if err == 0 {
+ i := 0
+ for b[i] != 0 {
+ i++
+ }
+ return string(b[:i])
+ }
+ if err != ERANGE {
+ return "Errstr failure"
+ }
+ }
+}
diff --git a/libgo/go/syscall/errstr_linux.go b/libgo/go/syscall/errstr_linux.go
new file mode 100644
index 00000000000..00fca80fc14
--- /dev/null
+++ b/libgo/go/syscall/errstr_linux.go
@@ -0,0 +1,23 @@
+// errstr_rtems.go -- RTEMS specific error strings.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+import "unsafe"
+
+//sysnb strerror_r(errnum int, b []byte) (errstr *byte)
+//strerror_r(errnum int, b *byte, len Size_t) *byte
+
+func Errstr(errnum int) string {
+ a := make([]byte, 128)
+ p := strerror_r(errnum, a)
+ b := (*[1000]byte)(unsafe.Pointer(p))
+ i := 0
+ for b[i] != 0 {
+ i++
+ }
+ return string(b[:i])
+}
diff --git a/libgo/go/syscall/errstr_nor.go b/libgo/go/syscall/errstr_nor.go
new file mode 100644
index 00000000000..2fb61c29adc
--- /dev/null
+++ b/libgo/go/syscall/errstr_nor.go
@@ -0,0 +1,33 @@
+// errstr.go -- Error strings when there is no strerror_r.
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+import (
+ "sync"
+ "unsafe"
+)
+
+//sysnb strerror(errnum int) (buf *byte)
+//strerror(errnum int) *byte
+
+var errstr_lock sync.Mutex
+
+func Errstr(errno int) string {
+ errstr_lock.Lock()
+
+ bp := strerror(errno)
+ b := (*[1000]byte)(unsafe.Pointer(bp))
+ i := 0
+ for b[i] != 0 {
+ i++
+ }
+ s := string(b[:i])
+
+ errstr_lock.Unlock()
+
+ return s
+}
diff --git a/libgo/go/syscall/exec_stubs.go b/libgo/go/syscall/exec_stubs.go
new file mode 100644
index 00000000000..02b9ec34cf3
--- /dev/null
+++ b/libgo/go/syscall/exec_stubs.go
@@ -0,0 +1,23 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Stubs for fork, exec and wait.
+
+package syscall
+
+func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
+ return -1, ENOSYS;
+}
+
+func Exec(argv0 string, argv []string, envv []string) (err int) {
+ return ENOSYS;
+}
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+ return -1, ENOSYS;
+}
+
+func raw_ptrace(request int, pid int, addr *byte, data *byte) int {
+ return ENOSYS
+}
diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go
new file mode 100644
index 00000000000..60e9770ce23
--- /dev/null
+++ b/libgo/go/syscall/exec_unix.go
@@ -0,0 +1,449 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Fork, exec, wait, etc.
+
+package syscall
+
+import (
+ "sync"
+ "unsafe"
+)
+
+//sysnb raw_fork() (pid Pid_t, errno int)
+//fork() Pid_t
+
+//sysnb raw_setsid() (errno int)
+//setsid() Pid_t
+
+//sysnb raw_chroot(path *byte) (errno int)
+//chroot(path *byte) int
+
+//sysnb raw_chdir(path *byte) (errno int)
+//chdir(path *byte) int
+
+//sysnb raw_fcntl(fd int, cmd int, arg int) (val int, errno int)
+//fcntl(fd int, cmd int, arg int) int
+
+//sysnb raw_close(fd int) (errno int)
+//close(fd int) int
+
+//sysnb raw_ioctl(fd int, cmd int, val int) (rval int, errno int)
+//ioctl(fd int, cmd int, val int) int
+
+//sysnb raw_execve(argv0 *byte, argv **byte, envv **byte) (errno int)
+//execve(argv0 *byte, argv **byte, envv **byte) int
+
+//sysnb raw_read(fd int, p *byte, np int) (n int, errno int)
+//read(fd int, buf *byte, count Size_t) Ssize_t
+
+//sysnb raw_write(fd int, buf *byte, count int) int
+//write(fd int, buf *byte, count Size_t) Ssize_t
+
+//sysnb raw_exit(status int)
+//_exit(status int)
+
+// Lock synchronizing creation of new file descriptors with fork.
+//
+// We want the child in a fork/exec sequence to inherit only the
+// file descriptors we intend. To do that, we mark all file
+// descriptors close-on-exec and then, in the child, explicitly
+// unmark the ones we want the exec'ed program to keep.
+// Unix doesn't make this easy: there is, in general, no way to
+// allocate a new file descriptor close-on-exec. Instead you
+// have to allocate the descriptor and then mark it close-on-exec.
+// If a fork happens between those two events, the child's exec
+// will inherit an unwanted file descriptor.
+//
+// This lock solves that race: the create new fd/mark close-on-exec
+// operation is done holding ForkLock for reading, and the fork itself
+// is done holding ForkLock for writing. At least, that's the idea.
+// There are some complications.
+//
+// Some system calls that create new file descriptors can block
+// for arbitrarily long times: open on a hung NFS server or named
+// pipe, accept on a socket, and so on. We can't reasonably grab
+// the lock across those operations.
+//
+// It is worse to inherit some file descriptors than others.
+// If a non-malicious child accidentally inherits an open ordinary file,
+// that's not a big deal. On the other hand, if a long-lived child
+// accidentally inherits the write end of a pipe, then the reader
+// of that pipe will not see EOF until that child exits, potentially
+// causing the parent program to hang. This is a common problem
+// in threaded C programs that use popen.
+//
+// Luckily, the file descriptors that are most important not to
+// inherit are not the ones that can take an arbitrarily long time
+// to create: pipe returns instantly, and the net package uses
+// non-blocking I/O to accept on a listening socket.
+// The rules for which file descriptor-creating operations use the
+// ForkLock are as follows:
+//
+// 1) Pipe. Does not block. Use the ForkLock.
+// 2) Socket. Does not block. Use the ForkLock.
+// 3) Accept. If using non-blocking mode, use the ForkLock.
+// Otherwise, live with the race.
+// 4) Open. Can block. Use O_CLOEXEC if available (GNU/Linux).
+// Otherwise, live with the race.
+// 5) Dup. Does not block. Use the ForkLock.
+// On GNU/Linux, could use fcntl F_DUPFD_CLOEXEC
+// instead of the ForkLock, but only for dup(fd, -1).
+
+var ForkLock sync.RWMutex
+
+// Convert array of string to array
+// of NUL-terminated byte pointer.
+func StringSlicePtr(ss []string) []*byte {
+ bb := make([]*byte, len(ss)+1)
+ for i := 0; i < len(ss); i++ {
+ bb[i] = StringBytePtr(ss[i])
+ }
+ bb[len(ss)] = nil
+ return bb
+}
+
+func CloseOnExec(fd int) { fcntl(fd, F_SETFD, FD_CLOEXEC) }
+
+func SetNonblock(fd int, nonblocking bool) (errno int) {
+ flag, err := fcntl(fd, F_GETFL, 0)
+ if err != 0 {
+ return err
+ }
+ if nonblocking {
+ flag |= O_NONBLOCK
+ } else {
+ flag &= ^O_NONBLOCK
+ }
+ _, err = fcntl(fd, F_SETFL, flag)
+ return err
+}
+
+// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
+// If a dup or exec fails, write the errno int to pipe.
+// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
+// In the child, this function must not acquire any locks, because
+// they might have been locked at the time of the fork. This means
+// no rescheduling, no malloc calls, and no new stack segments.
+// The calls to RawSyscall are okay because they are assembly
+// functions that do not grow the stack.
+func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err int) {
+ // Declare all variables at top in case any
+ // declarations require heap allocation (e.g., err1).
+ var r1 Pid_t
+ var err1 int
+ var nextfd int
+ var i int
+
+ // guard against side effects of shuffling fds below.
+ fd := append([]int(nil), attr.Files...)
+
+ // About to call fork.
+ // No more allocation or calls of non-assembly functions.
+ r1, err1 = raw_fork()
+ if err1 != 0 {
+ return 0, int(err1)
+ }
+
+ if r1 != 0 {
+ // parent; return PID
+ return int(r1), 0
+ }
+
+ // Fork succeeded, now in child.
+
+ // Enable tracing if requested.
+ if sys.Ptrace {
+ err1 = raw_ptrace(_PTRACE_TRACEME, 0, nil, nil)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Session ID
+ if sys.Setsid {
+ err1 = raw_setsid()
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Set process group
+ if sys.Setpgid {
+ err1 = Setpgid(0, 0)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Chroot
+ if chroot != nil {
+ err1 = raw_chroot(chroot)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // User and groups
+ if cred := sys.Credential; cred != nil {
+ ngroups := len(cred.Groups)
+ if ngroups == 0 {
+ err1 = setgroups(0, nil)
+ } else {
+ groups := make([]Gid_t, ngroups)
+ for i, v := range cred.Groups {
+ groups[i] = Gid_t(v)
+ }
+ err1 = setgroups(ngroups, &groups[0])
+ }
+ if err1 != 0 {
+ goto childerror
+ }
+ err1 = Setgid(int(cred.Gid))
+ if err1 != 0 {
+ goto childerror
+ }
+ err1 = Setuid(int(cred.Uid))
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Chdir
+ if dir != nil {
+ err1 = raw_chdir(dir)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Pass 1: look for fd[i] < i and move those up above len(fd)
+ // so that pass 2 won't stomp on an fd it needs later.
+ nextfd = int(len(fd))
+ if pipe < nextfd {
+ _, err1 = Dup2(pipe, nextfd)
+ if err1 != 0 {
+ goto childerror
+ }
+ raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
+ pipe = nextfd
+ nextfd++
+ }
+ for i = 0; i < len(fd); i++ {
+ if fd[i] >= 0 && fd[i] < int(i) {
+ _, err1 = Dup2(fd[i], nextfd)
+ if err1 != 0 {
+ goto childerror
+ }
+ raw_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
+ fd[i] = nextfd
+ nextfd++
+ if nextfd == pipe { // don't stomp on pipe
+ nextfd++
+ }
+ }
+ }
+
+ // Pass 2: dup fd[i] down onto i.
+ for i = 0; i < len(fd); i++ {
+ if fd[i] == -1 {
+ raw_close(i)
+ continue
+ }
+ if fd[i] == int(i) {
+ // Dup2(i, i) won't clear close-on-exec flag on
+ // GNU/Linux, probably not elsewhere either.
+ _, err1 = raw_fcntl(fd[i], F_SETFD, 0)
+ if err1 != 0 {
+ goto childerror
+ }
+ continue
+ }
+ // The new fd is created NOT close-on-exec,
+ // which is exactly what we want.
+ _, err1 = Dup2(fd[i], i)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // By convention, we don't close-on-exec the fds we are
+ // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
+ // Programs that know they inherit fds >= 3 will need
+ // to set them close-on-exec.
+ for i = len(fd); i < 3; i++ {
+ raw_close(i)
+ }
+
+ // Detach fd 0 from tty
+ if sys.Noctty {
+ _, err1 = raw_ioctl(0, TIOCNOTTY, 0)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Make fd 0 the tty
+ if sys.Setctty {
+ _, err1 = raw_ioctl(0, TIOCSCTTY, 0)
+ if err1 != 0 {
+ goto childerror
+ }
+ }
+
+ // Time to exec.
+ err1 = raw_execve(argv0, &argv[0], &envv[0])
+
+childerror:
+ // send error code on pipe
+ raw_write(pipe, (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+ for {
+ raw_exit(253)
+ }
+
+ // Calling panic is not actually safe,
+ // but the for loop above won't break
+ // and this shuts up the compiler.
+ panic("unreached")
+}
+
+// Credential holds user and group identities to be assumed
+// by a child process started by StartProcess.
+type Credential struct {
+ Uid uint32 // User ID.
+ Gid uint32 // Group ID.
+ Groups []uint32 // Supplementary group IDs.
+}
+
+// ProcAttr holds attributes that will be applied to a new process started
+// by StartProcess.
+type ProcAttr struct {
+ Dir string // Current working directory.
+ Env []string // Environment.
+ Files []int // File descriptors.
+ Sys *SysProcAttr
+}
+
+type SysProcAttr struct {
+ Chroot string // Chroot.
+ Credential *Credential // Credential.
+ Ptrace bool // Enable tracing.
+ Setsid bool // Create session.
+ Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
+ Setctty bool // Set controlling terminal to fd 0
+ Noctty bool // Detach fd 0 from controlling terminal
+}
+
+var zeroProcAttr ProcAttr
+var zeroSysProcAttr SysProcAttr
+
+func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
+ var p [2]int
+ var n int
+ var err1 uintptr
+ var wstatus WaitStatus
+
+ if attr == nil {
+ attr = &zeroProcAttr
+ }
+ sys := attr.Sys
+ if sys == nil {
+ sys = &zeroSysProcAttr
+ }
+
+ p[0] = -1
+ p[1] = -1
+
+ // Convert args to C form.
+ argv0p := StringBytePtr(argv0)
+ argvp := StringSlicePtr(argv)
+ envvp := StringSlicePtr(attr.Env)
+
+ if OS == "freebsd" && len(argv[0]) > len(argv0) {
+ argvp[0] = argv0p
+ }
+
+ var chroot *byte
+ if sys.Chroot != "" {
+ chroot = StringBytePtr(sys.Chroot)
+ }
+ var dir *byte
+ if attr.Dir != "" {
+ dir = StringBytePtr(attr.Dir)
+ }
+
+ // Acquire the fork lock so that no other threads
+ // create new fds that are not yet close-on-exec
+ // before we fork.
+ ForkLock.Lock()
+
+ // Allocate child status pipe close on exec.
+ if err = Pipe(p[0:]); err != 0 {
+ goto error
+ }
+ if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
+ goto error
+ }
+ if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
+ goto error
+ }
+
+ // Kick off child.
+ pid, err = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
+ if err != 0 {
+ goto error
+ }
+ ForkLock.Unlock()
+
+ // Read child error status from pipe.
+ Close(p[1])
+ n, err = raw_read(p[0], (*byte)(unsafe.Pointer(&err1)), int(unsafe.Sizeof(err1)))
+ Close(p[0])
+ if err != 0 || n != 0 {
+ if n == int(unsafe.Sizeof(err1)) {
+ err = int(err1)
+ }
+ if err == 0 {
+ err = EPIPE
+ }
+
+ // Child failed; wait for it to exit, to make sure
+ // the zombies don't accumulate.
+ _, err1 := Wait4(pid, &wstatus, 0, nil)
+ for err1 == EINTR {
+ _, err1 = Wait4(pid, &wstatus, 0, nil)
+ }
+ return 0, err
+ }
+
+ // Read got EOF, so pipe closed on exec, so exec succeeded.
+ return pid, 0
+
+error:
+ if p[0] >= 0 {
+ Close(p[0])
+ Close(p[1])
+ }
+ ForkLock.Unlock()
+ return 0, err
+}
+
+// Combination of fork and exec, careful to be thread safe.
+func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
+ return forkExec(argv0, argv, attr)
+}
+
+// StartProcess wraps ForkExec for package os.
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
+ pid, err = forkExec(argv0, argv, attr)
+ return pid, 0, err
+}
+
+// Ordinary exec.
+func Exec(argv0 string, argv []string, envv []string) (err int) {
+ err1 := raw_execve(StringBytePtr(argv0),
+ &StringSlicePtr(argv)[0],
+ &StringSlicePtr(envv)[0])
+ return int(err1)
+}
diff --git a/libgo/go/syscall/exec_windows.go b/libgo/go/syscall/exec_windows.go
new file mode 100644
index 00000000000..e8b540ad160
--- /dev/null
+++ b/libgo/go/syscall/exec_windows.go
@@ -0,0 +1,327 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Fork, exec, wait, etc.
+
+package syscall
+
+import (
+ "sync"
+ "unsafe"
+ "utf16"
+)
+
+var ForkLock sync.RWMutex
+
+// EscapeArg rewrites command line argument s as prescribed
+// in http://msdn.microsoft.com/en-us/library/ms880421.
+// This function returns "" (2 double quotes) if s is empty.
+// Alternatively, these transformations are done:
+// - every back slash (\) is doubled, but only if immediately
+// followed by double quote (");
+// - every double quote (") is escaped by back slash (\);
+// - finally, s is wrapped with double quotes (arg -> "arg"),
+// but only if there is space or tab inside s.
+func EscapeArg(s string) string {
+ if len(s) == 0 {
+ return "\"\""
+ }
+ n := len(s)
+ hasSpace := false
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '"', '\\':
+ n++
+ case ' ', '\t':
+ hasSpace = true
+ }
+ }
+ if hasSpace {
+ n += 2
+ }
+ if n == len(s) {
+ return s
+ }
+
+ qs := make([]byte, n)
+ j := 0
+ if hasSpace {
+ qs[j] = '"'
+ j++
+ }
+ slashes := 0
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ default:
+ slashes = 0
+ qs[j] = s[i]
+ case '\\':
+ slashes++
+ qs[j] = s[i]
+ case '"':
+ for ; slashes > 0; slashes-- {
+ qs[j] = '\\'
+ j++
+ }
+ qs[j] = '\\'
+ j++
+ qs[j] = s[i]
+ }
+ j++
+ }
+ if hasSpace {
+ for ; slashes > 0; slashes-- {
+ qs[j] = '\\'
+ j++
+ }
+ qs[j] = '"'
+ j++
+ }
+ return string(qs[:j])
+}
+
+// makeCmdLine builds a command line out of args by escaping "special"
+// characters and joining the arguments with spaces.
+func makeCmdLine(args []string) string {
+ var s string
+ for _, v := range args {
+ if s != "" {
+ s += " "
+ }
+ s += EscapeArg(v)
+ }
+ return s
+}
+
+// createEnvBlock converts an array of environment strings into
+// the representation required by CreateProcess: a sequence of NUL
+// terminated strings followed by a nil.
+// Last bytes are two UCS-2 NULs, or four NUL bytes.
+func createEnvBlock(envv []string) *uint16 {
+ if len(envv) == 0 {
+ return &utf16.Encode([]int("\x00\x00"))[0]
+ }
+ length := 0
+ for _, s := range envv {
+ length += len(s) + 1
+ }
+ length += 1
+
+ b := make([]byte, length)
+ i := 0
+ for _, s := range envv {
+ l := len(s)
+ copy(b[i:i+l], []byte(s))
+ copy(b[i+l:i+l+1], []byte{0})
+ i = i + l + 1
+ }
+ copy(b[i:i+1], []byte{0})
+
+ return &utf16.Encode([]int(string(b)))[0]
+}
+
+func CloseOnExec(fd Handle) {
+ SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0)
+}
+
+func SetNonblock(fd Handle, nonblocking bool) (errno int) {
+ return 0
+}
+
+// getFullPath retrieves the full path of the specified file.
+// Just a wrapper for Windows GetFullPathName api.
+func getFullPath(name string) (path string, err int) {
+ p := StringToUTF16Ptr(name)
+ buf := make([]uint16, 100)
+ n, err := GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
+ if err != 0 {
+ return "", err
+ }
+ if n > uint32(len(buf)) {
+ // Windows is asking for bigger buffer.
+ buf = make([]uint16, n)
+ n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil)
+ if err != 0 {
+ return "", err
+ }
+ if n > uint32(len(buf)) {
+ return "", EINVAL
+ }
+ }
+ return UTF16ToString(buf[:n]), 0
+}
+
+func isSlash(c uint8) bool {
+ return c == '\\' || c == '/'
+}
+
+func normalizeDir(dir string) (name string, err int) {
+ ndir, err := getFullPath(dir)
+ if err != 0 {
+ return "", err
+ }
+ if len(ndir) > 2 && isSlash(ndir[0]) && isSlash(ndir[1]) {
+ // dir cannot have \\server\share\path form
+ return "", EINVAL
+ }
+ return ndir, 0
+}
+
+func volToUpper(ch int) int {
+ if 'a' <= ch && ch <= 'z' {
+ ch += 'A' - 'a'
+ }
+ return ch
+}
+
+func joinExeDirAndFName(dir, p string) (name string, err int) {
+ if len(p) == 0 {
+ return "", EINVAL
+ }
+ if len(p) > 2 && isSlash(p[0]) && isSlash(p[1]) {
+ // \\server\share\path form
+ return p, 0
+ }
+ if len(p) > 1 && p[1] == ':' {
+ // has drive letter
+ if len(p) == 2 {
+ return "", EINVAL
+ }
+ if isSlash(p[2]) {
+ return p, 0
+ } else {
+ d, err := normalizeDir(dir)
+ if err != 0 {
+ return "", err
+ }
+ if volToUpper(int(p[0])) == volToUpper(int(d[0])) {
+ return getFullPath(d + "\\" + p[2:])
+ } else {
+ return getFullPath(p)
+ }
+ }
+ } else {
+ // no drive letter
+ d, err := normalizeDir(dir)
+ if err != 0 {
+ return "", err
+ }
+ if isSlash(p[0]) {
+ return getFullPath(d[:2] + p)
+ } else {
+ return getFullPath(d + "\\" + p)
+ }
+ }
+ // we shouldn't be here
+ return "", EINVAL
+}
+
+type ProcAttr struct {
+ Dir string
+ Env []string
+ Files []Handle
+ Sys *SysProcAttr
+}
+
+type SysProcAttr struct {
+ HideWindow bool
+ CmdLine string // used if non-empty, else the windows command line is built by escaping the arguments passed to StartProcess
+}
+
+var zeroProcAttr ProcAttr
+var zeroSysProcAttr SysProcAttr
+
+func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
+ if len(argv0) == 0 {
+ return 0, 0, EWINDOWS
+ }
+ if attr == nil {
+ attr = &zeroProcAttr
+ }
+ sys := attr.Sys
+ if sys == nil {
+ sys = &zeroSysProcAttr
+ }
+
+ if len(attr.Files) > 3 {
+ return 0, 0, EWINDOWS
+ }
+
+ if len(attr.Dir) != 0 {
+ // StartProcess assumes that argv0 is relative to attr.Dir,
+ // because it implies Chdir(attr.Dir) before executing argv0.
+ // Windows CreateProcess assumes the opposite: it looks for
+ // argv0 relative to the current directory, and, only once the new
+ // process is started, it does Chdir(attr.Dir). We are adjusting
+ // for that difference here by making argv0 absolute.
+ var err int
+ argv0, err = joinExeDirAndFName(attr.Dir, argv0)
+ if err != 0 {
+ return 0, 0, err
+ }
+ }
+ argv0p := StringToUTF16Ptr(argv0)
+
+ var cmdline string
+ // Windows CreateProcess takes the command line as a single string:
+ // use attr.CmdLine if set, else build the command line by escaping
+ // and joining each argument with spaces
+ if sys.CmdLine != "" {
+ cmdline = sys.CmdLine
+ } else {
+ cmdline = makeCmdLine(argv)
+ }
+
+ var argvp *uint16
+ if len(cmdline) != 0 {
+ argvp = StringToUTF16Ptr(cmdline)
+ }
+
+ var dirp *uint16
+ if len(attr.Dir) != 0 {
+ dirp = StringToUTF16Ptr(attr.Dir)
+ }
+
+ // Acquire the fork lock so that no other threads
+ // create new fds that are not yet close-on-exec
+ // before we fork.
+ ForkLock.Lock()
+ defer ForkLock.Unlock()
+
+ p, _ := GetCurrentProcess()
+ fd := make([]Handle, len(attr.Files))
+ for i := range attr.Files {
+ if attr.Files[i] > 0 {
+ err := DuplicateHandle(p, Handle(attr.Files[i]), p, &fd[i], 0, true, DUPLICATE_SAME_ACCESS)
+ if err != 0 {
+ return 0, 0, err
+ }
+ defer CloseHandle(Handle(fd[i]))
+ }
+ }
+ si := new(StartupInfo)
+ si.Cb = uint32(unsafe.Sizeof(*si))
+ si.Flags = STARTF_USESTDHANDLES
+ if sys.HideWindow {
+ si.Flags |= STARTF_USESHOWWINDOW
+ si.ShowWindow = SW_HIDE
+ }
+ si.StdInput = fd[0]
+ si.StdOutput = fd[1]
+ si.StdErr = fd[2]
+
+ pi := new(ProcessInformation)
+
+ err = CreateProcess(argv0p, argvp, nil, nil, true, CREATE_UNICODE_ENVIRONMENT, createEnvBlock(attr.Env), dirp, si, pi)
+ if err != 0 {
+ return 0, 0, err
+ }
+ defer CloseHandle(Handle(pi.Thread))
+
+ return int(pi.ProcessId), int(pi.Process), 0
+}
+
+func Exec(argv0 string, argv []string, envv []string) (err int) {
+ return EWINDOWS
+}
diff --git a/libgo/go/syscall/libcall_irix.go b/libgo/go/syscall/libcall_irix.go
new file mode 100644
index 00000000000..ae453559713
--- /dev/null
+++ b/libgo/go/syscall/libcall_irix.go
@@ -0,0 +1,8 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int)
+//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go
new file mode 100644
index 00000000000..3948e51ae28
--- /dev/null
+++ b/libgo/go/syscall/libcall_linux.go
@@ -0,0 +1,333 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// GNU/Linux library calls.
+
+package syscall
+
+import "unsafe"
+
+//sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, errno int)
+//openat(dirfd int, path *byte, flags int, mode Mode_t) int
+
+//sys futimesat(dirfd int, path *byte, times *[2]Timeval) (errno int)
+//futimesat(dirfd int, path *byte, times *[2]Timeval) int
+func Futimesat(dirfd int, path string, tv []Timeval) (errno int) {
+ if len(tv) != 2 {
+ return EINVAL
+ }
+ return futimesat(dirfd, StringBytePtr(path), (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
+func Futimes(fd int, tv []Timeval) (errno int) {
+ // Believe it or not, this is the best we can do on GNU/Linux
+ // (and is what glibc does).
+ return Utimes("/proc/self/fd/"+itoa(fd), tv)
+}
+
+//sys ptrace(request int, pid int, addr uintptr, data uintptr) (errno int)
+//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int)
+//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
+
+func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno int) {
+ // The peek requests are machine-size oriented, so we wrap it
+ // to retrieve arbitrary-length data.
+
+ // The ptrace syscall differs from glibc's ptrace.
+ // Peeks returns the word in *data, not as the return value.
+
+ var buf [sizeofPtr]byte
+
+ // Leading edge. PEEKTEXT/PEEKDATA don't require aligned
+ // access (PEEKUSER warns that it might), but if we don't
+ // align our reads, we might straddle an unmapped page
+ // boundary and not get the bytes leading up to the page
+ // boundary.
+ n := 0
+ if addr%sizeofPtr != 0 {
+ errno = ptrace(req, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
+ if errno != 0 {
+ return 0, errno
+ }
+ n += copy(out, buf[addr%sizeofPtr:])
+ out = out[n:]
+ }
+
+ // Remainder.
+ for len(out) > 0 {
+ // We use an internal buffer to gaurantee alignment.
+ // It's not documented if this is necessary, but we're paranoid.
+ errno = ptrace(req, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
+ if errno != 0 {
+ return n, errno
+ }
+ copied := copy(out, buf[0:])
+ n += copied
+ out = out[copied:]
+ }
+
+ return n, 0
+}
+
+func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
+ return ptracePeek(PTRACE_PEEKTEXT, pid, addr, out)
+}
+
+func PtracePeekData(pid int, addr uintptr, out []byte) (count int, errno int) {
+ return ptracePeek(PTRACE_PEEKDATA, pid, addr, out)
+}
+
+func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, errno int) {
+ // As for ptracePeek, we need to align our accesses to deal
+ // with the possibility of straddling an invalid page.
+
+ // Leading edge.
+ n := 0
+ if addr%sizeofPtr != 0 {
+ var buf [sizeofPtr]byte
+ errno = ptrace(peekReq, pid, addr-addr%sizeofPtr, uintptr(unsafe.Pointer(&buf[0])))
+ if errno != 0 {
+ return 0, errno
+ }
+ n += copy(buf[addr%sizeofPtr:], data)
+ word := *((*uintptr)(unsafe.Pointer(&buf[0])))
+ errno = ptrace(pokeReq, pid, addr-addr%sizeofPtr, word)
+ if errno != 0 {
+ return 0, errno
+ }
+ data = data[n:]
+ }
+
+ // Interior.
+ for len(data) > int(sizeofPtr) {
+ word := *((*uintptr)(unsafe.Pointer(&data[0])))
+ errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
+ if errno != 0 {
+ return n, errno
+ }
+ n += int(sizeofPtr)
+ data = data[sizeofPtr:]
+ }
+
+ // Trailing edge.
+ if len(data) > 0 {
+ var buf [sizeofPtr]byte
+ errno = ptrace(peekReq, pid, addr+uintptr(n), uintptr(unsafe.Pointer(&buf[0])))
+ if errno != 0 {
+ return n, errno
+ }
+ copy(buf[0:], data)
+ word := *((*uintptr)(unsafe.Pointer(&buf[0])))
+ errno = ptrace(pokeReq, pid, addr+uintptr(n), word)
+ if errno != 0 {
+ return n, errno
+ }
+ n += len(data)
+ }
+
+ return n, 0
+}
+
+func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
+ return ptracePoke(PTRACE_POKETEXT, PTRACE_PEEKTEXT, pid, addr, data)
+}
+
+func PtracePokeData(pid int, addr uintptr, data []byte) (count int, errno int) {
+ return ptracePoke(PTRACE_POKEDATA, PTRACE_PEEKDATA, pid, addr, data)
+}
+
+func PtraceGetRegs(pid int, regsout *PtraceRegs) (errno int) {
+ return ptrace(PTRACE_GETREGS, pid, 0, uintptr(unsafe.Pointer(regsout)))
+}
+
+func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
+ return ptrace(PTRACE_SETREGS, pid, 0, uintptr(unsafe.Pointer(regs)))
+}
+
+func PtraceSetOptions(pid int, options int) (errno int) {
+ return ptrace(PTRACE_SETOPTIONS, pid, 0, uintptr(options))
+}
+
+func PtraceGetEventMsg(pid int) (msg uint, errno int) {
+ var data _C_long
+ errno = ptrace(PTRACE_GETEVENTMSG, pid, 0, uintptr(unsafe.Pointer(&data)))
+ msg = uint(data)
+ return
+}
+
+func PtraceCont(pid int, signal int) (errno int) {
+ return ptrace(PTRACE_CONT, pid, 0, uintptr(signal))
+}
+
+func PtraceSingleStep(pid int) (errno int) { return ptrace(PTRACE_SINGLESTEP, pid, 0, 0) }
+
+func PtraceAttach(pid int) (errno int) { return ptrace(PTRACE_ATTACH, pid, 0, 0) }
+
+func PtraceDetach(pid int) (errno int) { return ptrace(PTRACE_DETACH, pid, 0, 0) }
+
+// FIXME: mksysinfo needs to produce LINUX_REBOOT_MAGIC[12].
+
+// //sys reboot(magic1 uint, magic2 uint, cmd int, arg string) (errno int)
+// //reboot(magic1 uint, magic2 uint, cmd int, arg *byte) int
+// func Reboot(cmd int) (errno int) {
+// return reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, "")
+// }
+
+//sys Acct(path string) (errno int)
+//acct(path *byte) int
+
+// FIXME: mksysinfo Timex
+// //sys Adjtimex(buf *Timex) (state int, errno int)
+// //adjtimex(buf *Timex) int
+
+//sys Faccessat(dirfd int, path string, mode uint32, flags int) (errno int)
+//faccessat(dirfd int, pathname *byte, mode int, flags int) int
+
+// FIXME: Only in glibc 2.10 and later.
+// //sys Fallocate(fd int, mode uint32, off int64, len int64) (errno int)
+// //fallocate(fd int, mode int, offset Offset_t, len Offset_t) int
+
+//sys Fchmodat(dirfd int, path string, mode uint32, flags int) (errno int)
+//fchmodat(dirfd int, pathname *byte, mode Mode_t, flags int) int
+
+//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (errno int)
+//fchownat(dirfd int, path *byte, owner Uid_t, group Gid_t, flags int) int
+
+//sys Flock(fd int, how int) (errno int)
+//flock(fd int, how int) int
+
+// FIXME: mksysinfo statfs
+// //sys Fstatfs(fd int, buf *Statfs_t) (errno int)
+// //fstatfs(fd int, buf *Statfs_t) int
+
+// FIXME: Only available as a syscall.
+// //sysnb Gettid() (tid int)
+// //gettid() Pid_t
+
+//sys Ioperm(from int, num int, on int) (errno int)
+//ioperm(from _C_long, num _C_long, on int) int
+
+//sys Iopl(level int) (errno int)
+//iopl(level int) int
+
+// FIXME: mksysinfo linux_dirent
+// Or just abandon this function.
+// //sys Getdents(fd int, buf []byte) (n int, errno int)
+// //getdents64(fd int, buf *byte, count uint)
+
+//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, errno int)
+//inotify_add_watch(fd int, pathname *byte, mask uint32) int
+
+//sysnb InotifyInit() (fd int, errno int)
+//inotify_init() int
+
+// FIXME: Only in glibc 2.9 and later.
+// //sysnb InotifyInit1(flags int) (fd int, errno int)
+// //inotify_init1(flags int) int
+
+//sysnb InotifyRmWatch(fd int, watchdesc uint32) (success int, errno int)
+//inotify_rm_watch(fd int, wd uint32) int
+
+//sys Klogctl(typ int, buf []byte) (n int, errno int)
+//klogctl(typ int, bufp *byte, len int) int
+
+//sys Mkdirat(dirfd int, path string, mode uint32) (errno int)
+//mkdirat(dirfd int, path *byte, mode Mode_t) int
+
+//sys Mknodat(dirfd int, path string, mode uint32, dev int) (errno int)
+//mknodat(dirfd int, path *byte, mode Mode_t, dev _dev_t) int
+
+//sys PivotRoot(newroot string, putold string) (errno int)
+//pivot_root(newroot *byte, putold *byte) int
+
+//sys Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (errno int)
+//renameat(olddirfd int, oldpath *byte, newdirfd int, newpath *byte) int
+
+//sys sendfile(outfd int, infd int, offset *Offset_t, count int) (written int, errno int)
+//sendfile64(outfd int, infd int, offset *Offset_t, count Size_t) Ssize_t
+func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
+ var soff Offset_t
+ var psoff *Offset_t
+ if offset != nil {
+ psoff = &soff
+ }
+ written, errno = sendfile(outfd, infd, psoff, count)
+ if offset != nil {
+ *offset = int64(soff)
+ }
+ return
+}
+
+//sys Setfsgid(gid int) (errno int)
+//setfsgid(gid Gid_t) int
+
+//sys Setfsuid(uid int) (errno int)
+//setfsuid(uid Uid_t) int
+
+//sysnb Setresgid(rgid int, egid int, sgid int) (errno int)
+//setresgid(rgid Gid_t, egid Gid_t, sgid Gid_t) int
+
+//sysnb Setresuid(ruid int, eguid int, suid int) (errno int)
+//setresuid(ruid Uid_t, euid Uid_t, suid Uid_t) int
+
+//sys splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len int, flags int) (n int64, errno int)
+//splice(rfd int, roff *_loff_t, wfd int, woff *_loff_t, len Size_t, flags uint) Ssize_t
+func Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, errno int) {
+ var lroff _loff_t
+ var plroff *_loff_t
+ if (roff != nil) {
+ plroff = &lroff
+ }
+ var lwoff _loff_t
+ var plwoff *_loff_t
+ if (woff != nil) {
+ plwoff = &lwoff
+ }
+ n, errno = splice(rfd, plroff, wfd, plwoff, len, flags)
+ if (roff != nil) {
+ *roff = int64(lroff)
+ }
+ if (woff != nil) {
+ *woff = int64(lwoff)
+ }
+ return
+}
+
+// FIXME: mksysinfo statfs
+// //sys Statfs(path string, buf *Statfs_t) (errno int)
+// //statfs(path *byte, buf *Statfs_t) int
+
+// FIXME: Only in glibc 2.6 and later.
+// //sys SyncFileRange(fd int, off int64, n int64, flags int) (errno int)
+// //sync_file_range(fd int, off Offset_t, n Offset_t, flags uint) int
+
+// FIXME: mksysinfo Sysinfo_t
+// //sysnb Sysinfo(info *Sysinfo_t) (errno int)
+// //sysinfo(info *Sysinfo_t) int
+
+//sys Tee(rfd int, wfd int, len int, flags int) (n int64, errno int)
+//tee(rfd int, wfd int, len Size_t, flags uint) Ssize_t
+
+// FIXME: Only available as a syscall.
+// //sysnb Tgkill(tgid int, tid int, sig int) (errno int)
+// //tgkill(tgid int, tid int, sig int) int
+
+//sys unlinkat(dirfd int, path string, flags int) (errno int)
+//unlinkat(dirfd int, path *byte, flags int) int
+
+func Unlinkat(dirfd int, path string) (errno int) {
+ return unlinkat(dirfd, path, 0)
+}
+
+//sys Unmount(target string, flags int) (errno int) = SYS_UMOUNT2
+//umount2(target *byte, flags int) int
+
+//sys Unshare(flags int) (errno int)
+//unshare(flags int) int
+
+// FIXME: mksysinfo Ustat_t
+// //sys Ustat(dev int, ubuf *Ustat_t) (errno int)
+// //ustat(dev _dev_t, ubuf *Ustat_t) int
diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go
new file mode 100644
index 00000000000..87ed4e628fd
--- /dev/null
+++ b/libgo/go/syscall/libcall_posix.go
@@ -0,0 +1,385 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// POSIX library calls.
+// This file is compiled as ordinary Go code,
+// but it is also input to mksyscall,
+// which parses the //sys lines and generates library call stubs.
+// Note that sometimes we use a lowercase //sys name and
+// wrap it in our own nicer implementation.
+
+package syscall
+
+import "unsafe"
+
+/*
+ * Wrapped
+ */
+
+//sysnb pipe(p *[2]int) (errno int)
+//pipe(p *[2]int) int
+func Pipe(p []int) (errno int) {
+ if len(p) != 2 {
+ return EINVAL
+ }
+ var pp [2]int
+ errno = pipe(&pp)
+ p[0] = pp[0]
+ p[1] = pp[1]
+ return
+}
+
+//sys utimes(path string, times *[2]Timeval) (errno int)
+//utimes(path *byte, times *[2]Timeval) int
+func Utimes(path string, tv []Timeval) (errno int) {
+ if len(tv) != 2 {
+ return EINVAL
+ }
+ return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
+}
+
+//sys getcwd(buf *byte, size Size_t) (errno int)
+//getcwd(buf *byte, size Size_t) *byte
+
+const ImplementsGetwd = true
+
+func Getwd() (ret string, errno int) {
+ for len := Size_t(4096); ; len *= 2 {
+ b := make([]byte, len)
+ err := getcwd(&b[0], len)
+ if err == 0 {
+ i := 0;
+ for b[i] != 0 {
+ i++;
+ }
+ return string(b[0:i]), 0;
+ }
+ if err != ERANGE {
+ return "", err
+ }
+ }
+}
+
+//sysnb getgroups(size int, list *Gid_t) (nn int, errno int)
+//getgroups(size int, list *Gid_t) int
+
+func Getgroups() (gids []int, errno int) {
+ n, err := getgroups(0, nil)
+ if err != 0 {
+ return nil, errno
+ }
+ if n == 0 {
+ return nil, 0
+ }
+
+ // Sanity check group count. Max is 1<<16 on GNU/Linux.
+ if n < 0 || n > 1<<20 {
+ return nil, EINVAL
+ }
+
+ a := make([]Gid_t, n)
+ n, err = getgroups(n, &a[0])
+ if err != 0 {
+ return nil, errno
+ }
+ gids = make([]int, n)
+ for i, v := range a[0:n] {
+ gids[i] = int(v)
+ }
+ return
+}
+
+//sysnb setgroups(n int, list *Gid_t) (errno int)
+//setgroups(n Size_t, list *Gid_t) int
+
+func Setgroups(gids []int) (errno int) {
+ if len(gids) == 0 {
+ return setgroups(0, nil)
+ }
+
+ a := make([]Gid_t, len(gids))
+ for i, v := range gids {
+ a[i] = Gid_t(v)
+ }
+ return setgroups(len(a), &a[0])
+}
+
+type WaitStatus uint32
+
+// The WaitStatus methods are implemented in C, to pick up the macros
+// #defines in <sys/wait.h>.
+
+func (w WaitStatus) Exited() bool
+func (w WaitStatus) Signaled() bool
+func (w WaitStatus) Stopped() bool
+func (w WaitStatus) Continued() bool
+func (w WaitStatus) CoreDump() bool
+func (w WaitStatus) ExitStatus() int
+func (w WaitStatus) Signal() int
+func (w WaitStatus) StopSignal() int
+func (w WaitStatus) TrapCause() int
+
+//sys Mkfifo(path string, mode uint32) (errno int)
+//mkfifo(path *byte, mode Mode_t) int
+
+//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, errno int)
+//select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) int
+
+const nfdbits = unsafe.Sizeof(fds_bits_type) * 8
+
+type FdSet struct {
+ Bits [(FD_SETSIZE + nfdbits - 1) / nfdbits]fds_bits_type
+}
+
+func FDSet(fd int, set *FdSet) {
+ set.Bits[fd / nfdbits] |= (1 << (uint)(fd % nfdbits))
+}
+
+func FDClr(fd int, set *FdSet) {
+ set.Bits[fd / nfdbits] &^= (1 << (uint)(fd % nfdbits))
+}
+
+func FDIsSet(fd int, set *FdSet) bool {
+ if set.Bits[fd / nfdbits] & (1 << (uint)(fd % nfdbits)) != 0 {
+ return true
+ } else {
+ return false
+ }
+}
+
+func FDZero(set *FdSet) {
+ for i := range set.Bits {
+ set.Bits[i] = 0
+ }
+}
+
+//sys Access(path string, mode uint32) (errno int)
+//access(path *byte, mode int) int
+
+//sys Chdir(path string) (errno int)
+//chdir(path *byte) int
+
+//sys Chmod(path string, mode uint32) (errno int)
+//chmod(path *byte, mode Mode_t) int
+
+//sys Chown(path string, uid int, gid int) (errno int)
+//chown(path *byte, uid Uid_t, gid Gid_t) int
+
+//sys Chroot(path string) (errno int)
+//chroot(path *byte) int
+
+//sys Close(fd int) (errno int)
+//close(fd int) int
+
+//sys Creat(path string, mode uint32) (fd int, errno int)
+//creat(path *byte, mode Mode_t) int
+
+//sysnb Dup(oldfd int) (fd int, errno int)
+//dup(oldfd int) int
+
+//sysnb Dup2(oldfd int, newfd int) (fd int, errno int)
+//dup2(oldfd int, newfd int) int
+
+//sys Exit(code int)
+//exit(code int)
+
+//sys Fchdir(fd int) (errno int)
+//fchdir(fd int) int
+
+//sys Fchmod(fd int, mode uint32) (errno int)
+//fchmod(fd int, mode Mode_t) int
+
+//sys Fchown(fd int, uid int, gid int) (errno int)
+//fchown(fd int, uid Uid_t, gid Gid_t) int
+
+//sys fcntl(fd int, cmd int, arg int) (val int, errno int)
+//fcntl(fd int, cmd int, arg int) int
+
+//sys Fdatasync(fd int) (errno int)
+//fdatasync(fd int) int
+
+//sys Fsync(fd int) (errno int)
+//fsync(fd int) int
+
+//sysnb Getegid() (egid int)
+//getegid() Gid_t
+
+//sysnb Geteuid() (euid int)
+//geteuid() Uid_t
+
+//sysnb Getgid() (gid int)
+//getgid() Gid_t
+
+//sysnb Getpagesize() (pagesize int)
+//getpagesize() int
+
+//sysnb Getpgid(pid int) (pgid int, errno int)
+//getpgid(pid Pid_t) Pid_t
+
+//sysnb Getpgrp() (pid int)
+//getpgrp() Pid_t
+
+//sysnb Getpid() (pid int)
+//getpid() Pid_t
+
+//sysnb Getppid() (ppid int)
+//getppid() Pid_t
+
+// FIXME: mksysinfo Rlimit
+// //sysnb Getrlimit(resource int, rlim *Rlimit) (errno int)
+// //getrlimit(resource int, rlim *Rlimit) int
+
+//sysnb Getrusage(who int, rusage *Rusage) (errno int)
+//getrusage(who int, rusage *Rusage) int
+
+//sysnb gettimeofday(tv *Timeval, tz *byte) (errno int)
+//gettimeofday(tv *Timeval, tz *byte) int
+func Gettimeofday(tv *Timeval) (errno int) {
+ return gettimeofday(tv, nil)
+}
+
+//sysnb Getuid() (uid int)
+//getuid() Uid_t
+
+//sysnb Kill(pid int, sig int) (errno int)
+//kill(pid Pid_t, sig int) int
+
+//sys Lchown(path string, uid int, gid int) (errno int)
+//lchown(path *byte, uid Uid_t, gid Gid_t) int
+
+//sys Link(oldpath string, newpath string) (errno int)
+//link(oldpath *byte, newpath *byte) int
+
+//sys Mkdir(path string, mode uint32) (errno int)
+//mkdir(path *byte, mode Mode_t) int
+
+//sys Mknod(path string, mode uint32, dev int) (errno int)
+//mknod(path *byte, mode Mode_t, dev _dev_t) int
+
+//sys Mount(source string, target string, fstype string, flags int, data string) (errno int)
+//mount(source *byte, target *byte, fstype *byte, flags _C_long, data *byte) int
+
+//sys Nanosleep(time *Timespec, leftover *Timespec) (errno int)
+//nanosleep(time *Timespec, leftover *Timespec) int
+
+//sys Pause() (errno int)
+//pause() int
+
+//sys Read(fd int, p []byte) (n int, errno int)
+//read(fd int, buf *byte, count Size_t) Ssize_t
+
+//sys Readlink(path string, buf []byte) (n int, errno int)
+//readlink(path *byte, buf *byte, bufsiz Size_t) Ssize_t
+
+//sys Rename(oldpath string, newpath string) (errno int)
+//rename(oldpath *byte, newpath *byte) int
+
+//sys Rmdir(path string) (errno int)
+//rmdir(path *byte) int
+
+//sys Setdomainname(p []byte) (errno int)
+//setdomainname(name *byte, len Size_t) int
+
+//sys Sethostname(p []byte) (errno int)
+//sethostname(name *byte, len Size_t) int
+
+//sysnb Setgid(gid int) (errno int)
+//setgid(gid Gid_t) int
+
+//sysnb Setregid(rgid int, egid int) (errno int)
+//setregid(rgid Gid_t, egid Gid_t) int
+
+//sysnb Setpgid(pid int, pgid int) (errno int)
+//setpgid(pid Pid_t, pgid Pid_t) int
+
+//sysnb Setreuid(ruid int, euid int) (errno int)
+//setreuid(ruid Uid_t, euid Uid_t) int
+
+// FIXME: mksysinfo Rlimit
+// //sysnb Setrlimit(resource int, rlim *Rlimit) (errno int)
+// //setrlimit(resource int, rlim *Rlimit) int
+
+//sysnb Setsid() (pid int, errno int)
+//setsid() Pid_t
+
+//sysnb settimeofday(tv *Timeval, tz *byte) (errno int)
+//settimeofday(tv *Timeval, tz *byte) int
+
+func Settimeofday(tv *Timeval) (errno int) {
+ return settimeofday(tv, nil)
+}
+
+//sysnb Setuid(uid int) (errno int)
+//setuid(uid Uid_t) int
+
+//sys Symlink(oldpath string, newpath string) (errno int)
+//symlink(oldpath *byte, newpath *byte) int
+
+//sys Sync()
+//sync()
+
+// FIXME: mksysinfo Time_t
+// //sysnb Time(t *Time_t) (tt Time_t, errno int)
+// //time(t *Time_t) Time_t
+
+// FIXME: mksysinfo Tms
+// //sysnb Times(tms *Tms) (ticks uintptr, errno int)
+// //times(tms *Tms) _clock_t
+
+//sysnb Umask(mask int) (oldmask int)
+//umask(mask Mode_t) Mode_t
+
+//sys Unlink(path string) (errno int)
+//unlink(path *byte) int
+
+// FIXME: mksysinfo Utimbuf
+// //sys Utime(path string, buf *Utimbuf) (errno int)
+// //utime(path *byte, buf *Utimbuf) int
+
+//sys Write(fd int, p []byte) (n int, errno int)
+//write(fd int, buf *byte, count Size_t) Ssize_t
+
+//sys munmap(addr uintptr, length uintptr) (errno int)
+//munmap(addr *byte, length Size_t) int
+
+//sys Madvise(b []byte, advice int) (errno int)
+//madvise(addr *byte, len Size_t, advice int) int
+
+//sys Mprotect(b []byte, prot int) (errno int)
+//mprotect(addr *byte, len Size_t, prot int) int
+
+//sys Mlock(b []byte) (errno int)
+//mlock(addr *byte, len Size_t) int
+
+//sys Munlock(b []byte) (errno int)
+//munlock(addr *byte, len Size_t) int
+
+//sys Mlockall(flags int) (errno int)
+//mlockall(flags int) int
+
+//sys Munlockall() (errno int)
+//munlockall() int
+
+func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
+
+func NsecToTimespec(nsec int64) (ts Timespec) {
+ ts.Sec = Timespec_sec_t(nsec / 1e9)
+ ts.Nsec = Timespec_nsec_t(nsec % 1e9)
+ return
+}
+
+func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
+
+func NsecToTimeval(nsec int64) (tv Timeval) {
+ nsec += 999 // round up to microsecond
+ tv.Sec = Timeval_sec_t(nsec / 1e9)
+ tv.Usec = Timeval_usec_t(nsec % 1e9 / 1e3)
+ return
+}
+
+//sysnb Tcgetattr(fd int, p *Termios) (errno int)
+//tcgetattr(fd int, p *Termios) int
+
+//sys Tcsetattr(fd int, actions int, p *Termios) (errno int)
+//tcsetattr(fd int, actions int, p *Termios) int
diff --git a/libgo/go/syscall/libcall_posix_largefile.go b/libgo/go/syscall/libcall_posix_largefile.go
new file mode 100644
index 00000000000..acfafecc581
--- /dev/null
+++ b/libgo/go/syscall/libcall_posix_largefile.go
@@ -0,0 +1,37 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// POSIX library calls on systems which use the largefile interface.
+
+package syscall
+
+//sys Fstat(fd int, stat *Stat_t) (errno int)
+//fstat64(fd int, stat *Stat_t) int
+
+//sys Ftruncate(fd int, length int64) (errno int)
+//ftruncate64(fd int, length Offset_t) int
+
+//sys Lstat(path string, stat *Stat_t) (errno int)
+//lstat64(path *byte, stat *Stat_t) int
+
+//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int)
+//mmap64(addr *byte, length Size_t, prot int, flags int, fd int, offset Offset_t) *byte
+
+//sys Open(path string, mode int, perm uint32) (fd int, errno int)
+//open64(path *byte, mode int, perm Mode_t) int
+
+//sys Pread(fd int, p []byte, offset int64) (n int, errno int)
+//pread64(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys Pwrite(fd int, p []byte, offset int64) (n int, errno int)
+//pwrite64(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys Seek(fd int, offset int64, whence int) (off int64, errno int)
+//lseek64(fd int, offset Offset_t, whence int) Offset_t
+
+//sys Stat(path string, stat *Stat_t) (errno int)
+//stat64(path *byte, stat *Stat_t) int
+
+//sys Truncate(path string, length int64) (errno int)
+//truncate64(path *byte, length Offset_t) int
diff --git a/libgo/go/syscall/libcall_posix_regfile.go b/libgo/go/syscall/libcall_posix_regfile.go
new file mode 100644
index 00000000000..b71da0ceb48
--- /dev/null
+++ b/libgo/go/syscall/libcall_posix_regfile.go
@@ -0,0 +1,38 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// POSIX library calls on systems which do not use the largefile
+// interface.
+
+package syscall
+
+//sys Fstat(fd int, stat *Stat_t) (errno int)
+//fstat(fd int, stat *Stat_t) int
+
+//sys Ftruncate(fd int, length int64) (errno int)
+//ftruncate(fd int, length Offset_t) int
+
+//sys Lstat(path string, stat *Stat_t) (errno int)
+//lstat(path *byte, stat *Stat_t) int
+
+//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, errno int)
+//mmap(addr *byte, length Size_t, prot int, flags int, fd int, offset Offset_t) *byte
+
+//sys Open(path string, mode int, perm uint32) (fd int, errno int)
+//open(path *byte, mode int, perm Mode_t) int
+
+//sys Pread(fd int, p []byte, offset int64) (n int, errno int)
+//pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys Pwrite(fd int, p []byte, offset int64) (n int, errno int)
+//pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t
+
+//sys Seek(fd int, offset int64, whence int) (off int64, errno int)
+//lseek(fd int, offset Offset_t, whence int) Offset_t
+
+//sys Stat(path string, stat *Stat_t) (errno int)
+//stat(path *byte, stat *Stat_t) int
+
+//sys Truncate(path string, length int64) (errno int)
+//truncate(path *byte, length Offset_t) int
diff --git a/libgo/go/syscall/libcall_solaris_386.go b/libgo/go/syscall/libcall_solaris_386.go
new file mode 100644
index 00000000000..9c4e966f1ae
--- /dev/null
+++ b/libgo/go/syscall/libcall_solaris_386.go
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>.
+//sysnb Uname(buf *Utsname) (errno int)
+//_nuname(buf *Utsname) int
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int)
+//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/libgo/go/syscall/libcall_solaris_amd64.go b/libgo/go/syscall/libcall_solaris_amd64.go
new file mode 100644
index 00000000000..f0d335dbb67
--- /dev/null
+++ b/libgo/go/syscall/libcall_solaris_amd64.go
@@ -0,0 +1,10 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+// 64-bit ptrace(3C) doesn't exist
+func raw_ptrace(request int, pid int, addr *byte, data *byte) int {
+ return ENOSYS
+}
diff --git a/libgo/go/syscall/libcall_solaris_sparc.go b/libgo/go/syscall/libcall_solaris_sparc.go
new file mode 100644
index 00000000000..ae453559713
--- /dev/null
+++ b/libgo/go/syscall/libcall_solaris_sparc.go
@@ -0,0 +1,8 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+//sysnb raw_ptrace(request int, pid int, addr *byte, data *byte) (errno int)
+//ptrace(request int, pid Pid_t, addr *byte, data *byte) _C_long
diff --git a/libgo/go/syscall/libcall_solaris_sparc64.go b/libgo/go/syscall/libcall_solaris_sparc64.go
new file mode 100644
index 00000000000..f0d335dbb67
--- /dev/null
+++ b/libgo/go/syscall/libcall_solaris_sparc64.go
@@ -0,0 +1,10 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+// 64-bit ptrace(3C) doesn't exist
+func raw_ptrace(request int, pid int, addr *byte, data *byte) int {
+ return ENOSYS
+}
diff --git a/libgo/go/syscall/libcall_support.go b/libgo/go/syscall/libcall_support.go
new file mode 100644
index 00000000000..daed8073caf
--- /dev/null
+++ b/libgo/go/syscall/libcall_support.go
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Declarations for functions which are actually written in C.
+
+package syscall
+
+func entersyscall()
+func exitsyscall()
+func GetErrno() int
+func SetErrno(int)
diff --git a/libgo/go/syscall/libcall_uname.go b/libgo/go/syscall/libcall_uname.go
new file mode 100644
index 00000000000..e4c32b12d6a
--- /dev/null
+++ b/libgo/go/syscall/libcall_uname.go
@@ -0,0 +1,8 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+//sysnb Uname(buf *Utsname) (errno int)
+//uname(buf *Utsname) int
diff --git a/libgo/go/syscall/libcall_wait4.go b/libgo/go/syscall/libcall_wait4.go
new file mode 100644
index 00000000000..7a63bc71e97
--- /dev/null
+++ b/libgo/go/syscall/libcall_wait4.go
@@ -0,0 +1,21 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// For systems with the wait4 library call.
+
+package syscall
+
+//sys wait4(pid Pid_t, status *int, options int, rusage *Rusage) (wpid Pid_t, errno int)
+//wait4(pid Pid_t, status *int, options int, rusage *Rusage) Pid_t
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+ var status int
+ r, err := wait4(Pid_t(pid), &status, options, rusage)
+ wpid = int(r)
+ errno = err
+ if wstatus != nil {
+ *wstatus = WaitStatus(status)
+ }
+ return
+}
diff --git a/libgo/go/syscall/libcall_waitpid.go b/libgo/go/syscall/libcall_waitpid.go
new file mode 100644
index 00000000000..014446307e3
--- /dev/null
+++ b/libgo/go/syscall/libcall_waitpid.go
@@ -0,0 +1,21 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// For systems with the waitpid library call.
+
+package syscall
+
+//sys waitpid(pid Pid_t, status *int, options int) (wpid Pid_t, errno int)
+//waitpid(pid Pid_t, status *int, options int) Pid_t
+
+func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
+ var status int
+ r, err := waitpid(Pid_t(pid), &status, options)
+ wpid = int(r)
+ errno = err
+ if wstatus != nil {
+ *wstatus = WaitStatus(status)
+ }
+ return
+}
diff --git a/libgo/go/syscall/lsf_linux.go b/libgo/go/syscall/lsf_linux.go
new file mode 100644
index 00000000000..0976688b9e7
--- /dev/null
+++ b/libgo/go/syscall/lsf_linux.go
@@ -0,0 +1,78 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// GNU/Linux socket filter
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func LsfStmt(code, k int) *SockFilter {
+ return &SockFilter{Code: uint16(code), K: uint32(k)}
+}
+
+func LsfJump(code, k, jt, jf int) *SockFilter {
+ return &SockFilter{Code: uint16(code), Jt: uint8(jt), Jf: uint8(jf), K: uint32(k)}
+}
+
+func LsfSocket(ifindex, proto int) (int, int) {
+ var lsall SockaddrLinklayer
+ s, e := Socket(AF_PACKET, SOCK_RAW, proto)
+ if e != 0 {
+ return 0, e
+ }
+ p := (*[2]byte)(unsafe.Pointer(&lsall.Protocol))
+ p[0] = byte(proto >> 8)
+ p[1] = byte(proto)
+ lsall.Ifindex = ifindex
+ e = Bind(s, &lsall)
+ if e != 0 {
+ Close(s)
+ return 0, e
+ }
+ return s, 0
+}
+
+type iflags struct {
+ name [IFNAMSIZ]byte
+ flags uint16
+}
+
+func SetLsfPromisc(name string, m bool) int {
+ s, e := Socket(AF_INET, SOCK_DGRAM, 0)
+ if e != 0 {
+ return e
+ }
+ defer Close(s)
+ var ifl iflags
+ copy(ifl.name[:], []byte(name))
+ _, _, ep := Syscall(SYS_IOCTL, uintptr(s), SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ if m {
+ ifl.flags |= uint16(IFF_PROMISC)
+ } else {
+ ifl.flags &= ^uint16(IFF_PROMISC)
+ }
+ _, _, ep = Syscall(SYS_IOCTL, uintptr(s), SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifl)))
+ if e := int(ep); e != 0 {
+ return e
+ }
+ return 0
+}
+
+func AttachLsf(fd int, i []SockFilter) int {
+ var p SockFprog
+ p.Len = uint16(len(i))
+ p.Filter = (*SockFilter)(unsafe.Pointer(&i[0]))
+ return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, uintptr(unsafe.Pointer(&p)), unsafe.Sizeof(p))
+}
+
+func DetachLsf(fd int) int {
+ var dummy int
+ return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, uintptr(unsafe.Pointer(&dummy)), unsafe.Sizeof(dummy))
+}
diff --git a/libgo/go/syscall/mksyscall.awk b/libgo/go/syscall/mksyscall.awk
new file mode 100644
index 00000000000..1b612f3fb99
--- /dev/null
+++ b/libgo/go/syscall/mksyscall.awk
@@ -0,0 +1,263 @@
+# Copyright 2011 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This AWK script reads a Go file with comments describing syscall
+# functions and the C routines they map to. It generates the Go code
+# which calls the C routines.
+
+# The syscall functins are marked by lines beginning with "//sys" and
+# read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * The parameter lists must give a type for each argument:
+# the (x, y, z int) shorthand is not allowed.
+# * If the return parameter is an error number, it must be named errno.
+
+# A line beginning with //sysnb is like //sys, except that the
+# goroutine will not be suspended during the execution of the library
+# call. This must only be used for library calls which can never
+# block, as otherwise the library call could cause all goroutines to
+# hang.
+
+# After the //sys or //sysnb line comes a second line which describes
+# the C function. The name must be the name of the function in the C
+# library, and may be the same as the Go function. The limitations on
+# the argument list are the same as for the //sys line, but there must
+# be at most one result parameter, and it must be given as just a
+# type, without a name.
+
+BEGIN {
+ print "// This file was automatically generated by mksyscall.awk"
+ print ""
+ print "package syscall"
+ print ""
+ print "import \"unsafe\""
+ print ""
+ status = 0
+}
+
+/^\/\/sys/ {
+ if ($1 == "//sysnb") {
+ blocking = 0
+ } else {
+ blocking = 1
+ }
+
+ line = $0
+
+ if (match(line, "//sys(nb)?[ ]*[a-zA-Z0-9_]+\\([^()]*\\) *(\\(([^()]+)\\))?") == 0) {
+ print "unmatched line:", $0 | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ # Sets a[1] = //sysnb, a[2] == function name.
+ split(line, a, "[ (]*")
+ gofnname = a[2]
+
+ off = match(line, "\\([^()]*\\)")
+ end = index(substr(line, off, length(line) - off + 1), ")")
+ gofnparams = substr(line, off + 1, end - 2)
+
+ line = substr(line, off + end, length(line) - (off + end) + 1)
+ off = match(line, "\\([^()]*\\)")
+ if (off == 0) {
+ gofnresults = ""
+ } else {
+ end = index(substr(line, off, length(line) - off + 1), ")")
+ gofnresults = substr(line, off + 1, end - 2)
+ }
+
+ getline
+ line = $0
+
+ if (match(line, "//[a-zA-Z0-9_]+\\([^()]*\\)") == 0) {
+ print "unmatched C line", $0, "after", gofnname | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ split(line, a, "[ (]*")
+ cfnname = substr(a[1], 3, length(a[1]) - 2)
+
+ off = match(line, "\\([^()]*\\)")
+ end = index(substr(line, off, length(line) - off + 1), ")")
+ cfnparams = substr(line, off + 1, end - 2)
+
+ line = substr(line, off + end + 1, length(line) - (off + end) + 1)
+ while (substr(line, 1, 1) == " ") {
+ line = substr(line, 2, length(line) - 1)
+ }
+ end = index(line, " ")
+ if (end != 0) {
+ line = substr(line, 1, end)
+ }
+ cfnresult = line
+
+ printf("// Automatically generated wrapper for %s/%s\n", gofnname, cfnname)
+ printf("func c_%s(%s) %s%s__asm__(\"%s\")\n",
+ cfnname, cfnparams, cfnresult, cfnresult == "" ? "" : " ", cfnname)
+ printf("func %s(%s) %s%s%s%s{\n",
+ gofnname, gofnparams, gofnresults == "" ? "" : "(", gofnresults,
+ gofnresults == "" ? "" : ")", gofnresults == "" ? "" : " ")
+
+ if (blocking) {
+ print "\tentersyscall()"
+ }
+
+ loc = gofnname "/" cfnname ":"
+
+ split(gofnparams, goargs, ", *")
+ split(cfnparams, cargs, ", *")
+ args = ""
+ carg = 1
+ for (goarg = 1; goargs[goarg] != ""; goarg++) {
+ if (cargs[carg] == "") {
+ print loc, "not enough C parameters"
+ }
+
+ if (args != "") {
+ args = args ", "
+ }
+
+ if (split(goargs[goarg], a) != 2) {
+ print loc, "bad parameter:", goargs[goarg] | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ goname = a[1]
+ gotype = a[2]
+
+ if (split(cargs[carg], a) != 2) {
+ print loc, "bad C parameter:", cargs[carg] | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ ctype = a[2]
+
+ if (gotype ~ /^\*/) {
+ if (gotype != ctype) {
+ print loc, "Go/C pointer type mismatch:", gotype, ctype | "cat 1>&2"
+ status = 1
+ next
+ }
+ args = args goname
+ } else if (gotype == "string") {
+ if (ctype != "*byte") {
+ print loc, "Go string not matched to C *byte:", gotype, ctype | "cat 1>&2"
+ status = 1
+ next
+ }
+ args = args "StringBytePtr(" goname ")"
+ } else if (gotype ~ /^\[\](.*)/) {
+ if (ctype !~ /^\*/ || cargs[carg + 1] == "") {
+ print loc, "bad C type for slice:", gotype, ctype | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ # Convert a slice into a pair of pointer, length.
+ # Don't try to take the address of the zeroth element of a
+ # nil slice.
+ printf("\tvar _p%d %s\n", goarg, ctype)
+ printf("\tif len(%s) > 0 {\n", goname)
+ printf("\t\t_p%d = (%s)(unsafe.Pointer(&%s[0]))\n", goarg, ctype, goname)
+ printf("\t} else {\n")
+ printf("\t\t_p%d = (%s)(unsafe.Pointer(&_zero))\n", goarg, ctype)
+ printf("\t}\n")
+
+ ++carg
+ if (split(cargs[carg], cparam) != 2) {
+ print loc, "bad C parameter:", cargs[carg] | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ args = sprintf("%s_p%d, %s(len(%s))", args, goarg, cparam[2], goname)
+ } else if (gotype == "uintptr" && ctype ~ /^\*/) {
+ args = sprintf("%s(%s)(unsafe.Pointer(%s))", args, ctype, goname)
+ } else {
+ args = sprintf("%s%s(%s)", args, ctype, goname)
+ }
+
+ carg++
+ }
+
+ if (cargs[carg] != "") {
+ print loc, "too many C parameters" | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ printf("\t")
+ if (gofnresults != "") {
+ printf("_r := ")
+ }
+ printf("c_%s(%s)\n", cfnname, args)
+
+ if (gofnresults != "") {
+ fields = split(gofnresults, goresults, ", *")
+ if (fields > 2) {
+ print loc, "too many Go results" | "cat 1>&2"
+ status = 1
+ next
+ }
+ usedr = 0
+ for (goresult = 1; goresults[goresult] != ""; goresult++) {
+ if (split(goresults[goresult], goparam) != 2) {
+ print loc, "bad result:", goresults[goresult] | "cat 1>&2"
+ status = 1
+ next
+ }
+
+ goname = goparam[1]
+ gotype = goparam[2]
+
+ if (goname == "errno") {
+ if (cfnresult ~ /^\*/) {
+ print "\tif _r == nil {"
+ } else {
+ print "\tif _r < 0 {"
+ }
+ print "\t\terrno = GetErrno()"
+ print "\t}"
+ } else if (gotype == "uintptr" && cfnresult ~ /^\*/) {
+ printf("\t%s = (%s)(unsafe.Pointer(_r))\n", goname, gotype)
+ } else {
+ if (usedr) {
+ print loc, "two parameters but no errno parameter" | "cat 1>&2"
+ status = 1
+ next
+ }
+ printf("\t%s = (%s)(_r)\n", goname, gotype)
+ usedr = 1
+ }
+ }
+ }
+
+ if (blocking) {
+ print "\texitsyscall()"
+ }
+
+ if (gofnresults != "") {
+ print "\treturn"
+ }
+
+ print "}"
+
+ print ""
+
+ next
+}
+
+{ next }
+
+END {
+ if (status != 0) {
+ print "*** mksyscall.awk failed" | "cat 1>&2"
+ exit status
+ }
+}
diff --git a/libgo/go/syscall/netlink_linux.go b/libgo/go/syscall/netlink_linux.go
new file mode 100644
index 00000000000..4ee78d62f25
--- /dev/null
+++ b/libgo/go/syscall/netlink_linux.go
@@ -0,0 +1,229 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Netlink sockets and messages
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+// Round the length of a netlink message up to align it properly.
+func nlmAlignOf(msglen int) int {
+ return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1)
+}
+
+// Round the length of a netlink route attribute up to align it
+// properly.
+func rtaAlignOf(attrlen int) int {
+ return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
+}
+
+// NetlinkRouteRequest represents the request message to receive
+// routing and link states from the kernel.
+type NetlinkRouteRequest struct {
+ Header NlMsghdr
+ Data RtGenmsg
+}
+
+func (rr *NetlinkRouteRequest) toWireFormat() []byte {
+ b := make([]byte, rr.Header.Len)
+ b[0] = byte(rr.Header.Len)
+ b[1] = byte(rr.Header.Len >> 8)
+ b[2] = byte(rr.Header.Len >> 16)
+ b[3] = byte(rr.Header.Len >> 24)
+ b[4] = byte(rr.Header.Type)
+ b[5] = byte(rr.Header.Type >> 8)
+ b[6] = byte(rr.Header.Flags)
+ b[7] = byte(rr.Header.Flags >> 8)
+ b[8] = byte(rr.Header.Seq)
+ b[9] = byte(rr.Header.Seq >> 8)
+ b[10] = byte(rr.Header.Seq >> 16)
+ b[11] = byte(rr.Header.Seq >> 24)
+ b[12] = byte(rr.Header.Pid)
+ b[13] = byte(rr.Header.Pid >> 8)
+ b[14] = byte(rr.Header.Pid >> 16)
+ b[15] = byte(rr.Header.Pid >> 24)
+ b[16] = byte(rr.Data.Family)
+ return b
+}
+
+func newNetlinkRouteRequest(proto, seq, family int) []byte {
+ rr := &NetlinkRouteRequest{}
+ rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
+ rr.Header.Type = uint16(proto)
+ rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
+ rr.Header.Seq = uint32(seq)
+ rr.Data.Family = uint8(family)
+ return rr.toWireFormat()
+}
+
+// NetlinkRIB returns routing information base, as known as RIB,
+// which consists of network facility information, states and
+// parameters.
+func NetlinkRIB(proto, family int) ([]byte, int) {
+ var (
+ s int
+ e int
+ lsanl SockaddrNetlink
+ seq int
+ tab []byte
+ )
+
+ s, e = Socket(AF_NETLINK, SOCK_RAW, 0)
+ if e != 0 {
+ return nil, e
+ }
+ defer Close(s)
+
+ lsanl.Family = AF_NETLINK
+ e = Bind(s, &lsanl)
+ if e != 0 {
+ return nil, e
+ }
+
+ seq++
+ wb := newNetlinkRouteRequest(proto, seq, family)
+ e = Sendto(s, wb, 0, &lsanl)
+ if e != 0 {
+ return nil, e
+ }
+
+ for {
+ var (
+ rb []byte
+ nr int
+ lsa Sockaddr
+ )
+
+ rb = make([]byte, Getpagesize())
+ nr, _, e = Recvfrom(s, rb, 0)
+ if e != 0 {
+ return nil, e
+ }
+ if nr < NLMSG_HDRLEN {
+ return nil, EINVAL
+ }
+ rb = rb[:nr]
+ tab = append(tab, rb...)
+
+ msgs, _ := ParseNetlinkMessage(rb)
+ for _, m := range msgs {
+ if lsa, e = Getsockname(s); e != 0 {
+ return nil, e
+ }
+ switch v := lsa.(type) {
+ case *SockaddrNetlink:
+ if m.Header.Seq != uint32(seq) || m.Header.Pid != v.Pid {
+ return nil, EINVAL
+ }
+ default:
+ return nil, EINVAL
+ }
+ if m.Header.Type == NLMSG_DONE {
+ goto done
+ }
+ if m.Header.Type == NLMSG_ERROR {
+ return nil, EINVAL
+ }
+ }
+ }
+
+done:
+ return tab, 0
+}
+
+// NetlinkMessage represents the netlink message.
+type NetlinkMessage struct {
+ Header NlMsghdr
+ Data []byte
+}
+
+// ParseNetlinkMessage parses buf as netlink messages and returns
+// the slice containing the NetlinkMessage structs.
+func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, int) {
+ var (
+ h *NlMsghdr
+ dbuf []byte
+ dlen int
+ e int
+ msgs []NetlinkMessage
+ )
+
+ for len(buf) >= NLMSG_HDRLEN {
+ h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf)
+ if e != 0 {
+ break
+ }
+ m := NetlinkMessage{}
+ m.Header = *h
+ m.Data = dbuf[:int(h.Len)-NLMSG_HDRLEN]
+ msgs = append(msgs, m)
+ buf = buf[dlen:]
+ }
+
+ return msgs, e
+}
+
+func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, int) {
+ h := (*NlMsghdr)(unsafe.Pointer(&buf[0]))
+ if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(buf) {
+ return nil, nil, 0, EINVAL
+ }
+ return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), 0
+}
+
+// NetlinkRouteAttr represents the netlink route attribute.
+type NetlinkRouteAttr struct {
+ Attr RtAttr
+ Value []byte
+}
+
+// ParseNetlinkRouteAttr parses msg's payload as netlink route
+// attributes and returns the slice containing the NetlinkRouteAttr
+// structs.
+func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
+ var (
+ buf []byte
+ a *RtAttr
+ alen int
+ vbuf []byte
+ e int
+ attrs []NetlinkRouteAttr
+ )
+
+ switch msg.Header.Type {
+ case RTM_NEWLINK, RTM_DELLINK:
+ buf = msg.Data[SizeofIfInfomsg:]
+ case RTM_NEWADDR, RTM_DELADDR:
+ buf = msg.Data[SizeofIfAddrmsg:]
+ case RTM_NEWROUTE, RTM_DELROUTE:
+ buf = msg.Data[SizeofRtMsg:]
+ default:
+ return nil, EINVAL
+ }
+
+ for len(buf) >= SizeofRtAttr {
+ a, vbuf, alen, e = netlinkRouteAttrAndValue(buf)
+ if e != 0 {
+ break
+ }
+ ra := NetlinkRouteAttr{}
+ ra.Attr = *a
+ ra.Value = vbuf[:int(a.Len)-SizeofRtAttr]
+ attrs = append(attrs, ra)
+ buf = buf[alen:]
+ }
+
+ return attrs, 0
+}
+
+func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, int) {
+ h := (*RtAttr)(unsafe.Pointer(&buf[0]))
+ if int(h.Len) < SizeofRtAttr || int(h.Len) > len(buf) {
+ return nil, nil, 0, EINVAL
+ }
+ return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), 0
+}
diff --git a/libgo/go/syscall/route_bsd.go b/libgo/go/syscall/route_bsd.go
new file mode 100644
index 00000000000..f6b124b64e4
--- /dev/null
+++ b/libgo/go/syscall/route_bsd.go
@@ -0,0 +1,197 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd openbsd
+
+// Routing sockets and messages
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+// Round the length of a raw sockaddr up to align it properly.
+func rsaAlignOf(salen int) int {
+ salign := sizeofPtr
+ // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
+ // aligned access to BSD subsystem.
+ if darwinAMD64 {
+ salign = 4
+ }
+ if salen == 0 {
+ return salign
+ }
+ return (salen + salign - 1) & ^(salign - 1)
+}
+
+// RouteRIB returns routing information base, as known as RIB,
+// which consists of network facility information, states and
+// parameters.
+func RouteRIB(facility, param int) ([]byte, int) {
+ var (
+ tab []byte
+ e int
+ )
+
+ mib := []_C_int{CTL_NET, AF_ROUTE, 0, 0, _C_int(facility), _C_int(param)}
+
+ // Find size.
+ n := uintptr(0)
+ if e = sysctl(mib, nil, &n, nil, 0); e != 0 {
+ return nil, e
+ }
+ if n == 0 {
+ return nil, 0
+ }
+
+ tab = make([]byte, n)
+ if e = sysctl(mib, &tab[0], &n, nil, 0); e != 0 {
+ return nil, e
+ }
+
+ return tab[:n], 0
+}
+
+// RoutingMessage represents a routing message.
+type RoutingMessage interface {
+ sockaddr() []Sockaddr
+}
+
+const anyMessageLen = int(unsafe.Sizeof(anyMessage{}))
+
+type anyMessage struct {
+ Msglen uint16
+ Version uint8
+ Type uint8
+}
+
+// RouteMessage represents a routing message containing routing
+// entries.
+type RouteMessage struct {
+ Header RtMsghdr
+ Data []byte
+}
+
+const rtaRtMask = RTA_DST | RTA_GATEWAY | RTA_NETMASK | RTA_GENMASK
+
+func (m *RouteMessage) sockaddr() []Sockaddr {
+ var (
+ af int
+ sas [4]Sockaddr
+ )
+
+ buf := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaRtMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+ switch i {
+ case RTAX_DST, RTAX_GATEWAY:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != 0 {
+ return nil
+ }
+ if i == RTAX_DST {
+ af = int(rsa.Family)
+ }
+ sas[i] = sa
+ case RTAX_NETMASK, RTAX_GENMASK:
+ switch af {
+ case AF_INET:
+ rsa4 := (*RawSockaddrInet4)(unsafe.Pointer(&buf[0]))
+ sa := new(SockaddrInet4)
+ for j := 0; rsa4.Len > 0 && j < int(rsa4.Len)-int(unsafe.Offsetof(rsa4.Addr)); j++ {
+ sa.Addr[j] = rsa4.Addr[j]
+ }
+ sas[i] = sa
+ case AF_INET6:
+ rsa6 := (*RawSockaddrInet6)(unsafe.Pointer(&buf[0]))
+ sa := new(SockaddrInet6)
+ for j := 0; rsa6.Len > 0 && j < int(rsa6.Len)-int(unsafe.Offsetof(rsa6.Addr)); j++ {
+ sa.Addr[j] = rsa6.Addr[j]
+ }
+ sas[i] = sa
+ }
+ }
+ buf = buf[rsaAlignOf(int(rsa.Len)):]
+ }
+
+ return sas[:]
+}
+
+// InterfaceMessage represents a routing message containing
+// network interface entries.
+type InterfaceMessage struct {
+ Header IfMsghdr
+ Data []byte
+}
+
+func (m *InterfaceMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&RTA_IFP == 0 {
+ return nil
+ }
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(&m.Data[0])))
+ if e != 0 {
+ return nil
+ }
+ return append(sas, sa)
+}
+
+// InterfaceAddrMessage represents a routing message containing
+// network interface address entries.
+type InterfaceAddrMessage struct {
+ Header IfaMsghdr
+ Data []byte
+}
+
+const rtaIfaMask = RTA_IFA | RTA_NETMASK | RTA_BRD
+
+func (m *InterfaceAddrMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&rtaIfaMask == 0 {
+ return nil
+ }
+
+ buf := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaIfaMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+ switch i {
+ case RTAX_IFA:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != 0 {
+ return nil
+ }
+ sas = append(sas, sa)
+ case RTAX_NETMASK, RTAX_BRD:
+ // nothing to do
+ }
+ buf = buf[rsaAlignOf(int(rsa.Len)):]
+ }
+
+ return sas
+}
+
+// ParseRoutingMessage parses buf as routing messages and returns
+// the slice containing the RoutingMessage interfaces.
+func ParseRoutingMessage(buf []byte) (msgs []RoutingMessage, errno int) {
+ for len(buf) >= anyMessageLen {
+ any := (*anyMessage)(unsafe.Pointer(&buf[0]))
+ if any.Version != RTM_VERSION {
+ return nil, EINVAL
+ }
+ msgs = append(msgs, any.toRoutingMessage(buf))
+ buf = buf[any.Msglen:]
+ }
+ return msgs, 0
+}
+
+// ParseRoutingMessage parses msg's payload as raw sockaddrs and
+// returns the slice containing the Sockaddr interfaces.
+func ParseRoutingSockaddr(msg RoutingMessage) (sas []Sockaddr, errno int) {
+ return append(sas, msg.sockaddr()...), 0
+}
diff --git a/libgo/go/syscall/route_darwin.go b/libgo/go/syscall/route_darwin.go
new file mode 100644
index 00000000000..9d3a701daba
--- /dev/null
+++ b/libgo/go/syscall/route_darwin.go
@@ -0,0 +1,77 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Routing sockets and messages for Darwin
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+ switch any.Type {
+ case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+ p := (*RouteMessage)(unsafe.Pointer(any))
+ rtm := &RouteMessage{}
+ rtm.Header = p.Header
+ rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
+ return rtm
+ case RTM_IFINFO:
+ p := (*InterfaceMessage)(unsafe.Pointer(any))
+ ifm := &InterfaceMessage{}
+ ifm.Header = p.Header
+ ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
+ return ifm
+ case RTM_NEWADDR, RTM_DELADDR:
+ p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+ ifam := &InterfaceAddrMessage{}
+ ifam.Header = p.Header
+ ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
+ return ifam
+ case RTM_NEWMADDR2, RTM_DELMADDR:
+ p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
+ ifmam := &InterfaceMulticastAddrMessage{}
+ ifmam.Header = p.Header
+ ifmam.Data = buf[SizeofIfmaMsghdr2:any.Msglen]
+ return ifmam
+ }
+ return nil
+}
+
+// InterfaceMulticastAddrMessage represents a routing message
+// containing network interface address entries.
+type InterfaceMulticastAddrMessage struct {
+ Header IfmaMsghdr2
+ Data []byte
+}
+
+const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
+
+func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&rtaIfmaMask == 0 {
+ return nil
+ }
+
+ buf := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+ switch i {
+ case RTAX_IFA:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != 0 {
+ return nil
+ }
+ sas = append(sas, sa)
+ case RTAX_GATEWAY, RTAX_IFP:
+ // nothing to do
+ }
+ buf = buf[rsaAlignOf(int(rsa.Len)):]
+ }
+
+ return sas
+}
diff --git a/libgo/go/syscall/route_freebsd.go b/libgo/go/syscall/route_freebsd.go
new file mode 100644
index 00000000000..0d61d08b08c
--- /dev/null
+++ b/libgo/go/syscall/route_freebsd.go
@@ -0,0 +1,77 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Routing sockets and messages for FreeBSD
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+ switch any.Type {
+ case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+ p := (*RouteMessage)(unsafe.Pointer(any))
+ rtm := &RouteMessage{}
+ rtm.Header = p.Header
+ rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
+ return rtm
+ case RTM_IFINFO:
+ p := (*InterfaceMessage)(unsafe.Pointer(any))
+ ifm := &InterfaceMessage{}
+ ifm.Header = p.Header
+ ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
+ return ifm
+ case RTM_NEWADDR, RTM_DELADDR:
+ p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+ ifam := &InterfaceAddrMessage{}
+ ifam.Header = p.Header
+ ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
+ return ifam
+ case RTM_NEWMADDR, RTM_DELMADDR:
+ p := (*InterfaceMulticastAddrMessage)(unsafe.Pointer(any))
+ ifmam := &InterfaceMulticastAddrMessage{}
+ ifmam.Header = p.Header
+ ifmam.Data = buf[SizeofIfmaMsghdr:any.Msglen]
+ return ifmam
+ }
+ return nil
+}
+
+// InterfaceMulticastAddrMessage represents a routing message
+// containing network interface address entries.
+type InterfaceMulticastAddrMessage struct {
+ Header IfmaMsghdr
+ Data []byte
+}
+
+const rtaIfmaMask = RTA_GATEWAY | RTA_IFP | RTA_IFA
+
+func (m *InterfaceMulticastAddrMessage) sockaddr() (sas []Sockaddr) {
+ if m.Header.Addrs&rtaIfmaMask == 0 {
+ return nil
+ }
+
+ buf := m.Data[:]
+ for i := uint(0); i < RTAX_MAX; i++ {
+ if m.Header.Addrs&rtaIfmaMask&(1<<i) == 0 {
+ continue
+ }
+ rsa := (*RawSockaddr)(unsafe.Pointer(&buf[0]))
+ switch i {
+ case RTAX_IFA:
+ sa, e := anyToSockaddr((*RawSockaddrAny)(unsafe.Pointer(rsa)))
+ if e != 0 {
+ return nil
+ }
+ sas = append(sas, sa)
+ case RTAX_GATEWAY, RTAX_IFP:
+ // nothing to do
+ }
+ buf = buf[rsaAlignOf(int(rsa.Len)):]
+ }
+
+ return sas
+}
diff --git a/libgo/go/syscall/route_openbsd.go b/libgo/go/syscall/route_openbsd.go
new file mode 100644
index 00000000000..30e1cac46fc
--- /dev/null
+++ b/libgo/go/syscall/route_openbsd.go
@@ -0,0 +1,35 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Routing sockets and messages for OpenBSD
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+func (any *anyMessage) toRoutingMessage(buf []byte) RoutingMessage {
+ switch any.Type {
+ case RTM_ADD, RTM_DELETE, RTM_CHANGE, RTM_GET, RTM_LOSING, RTM_REDIRECT, RTM_MISS, RTM_LOCK, RTM_RESOLVE:
+ p := (*RouteMessage)(unsafe.Pointer(any))
+ rtm := &RouteMessage{}
+ rtm.Header = p.Header
+ rtm.Data = buf[SizeofRtMsghdr:any.Msglen]
+ return rtm
+ case RTM_IFINFO:
+ p := (*InterfaceMessage)(unsafe.Pointer(any))
+ ifm := &InterfaceMessage{}
+ ifm.Header = p.Header
+ ifm.Data = buf[SizeofIfMsghdr:any.Msglen]
+ return ifm
+ case RTM_NEWADDR, RTM_DELADDR:
+ p := (*InterfaceAddrMessage)(unsafe.Pointer(any))
+ ifam := &InterfaceAddrMessage{}
+ ifam.Header = p.Header
+ ifam.Data = buf[SizeofIfaMsghdr:any.Msglen]
+ return ifam
+ }
+ return nil
+}
diff --git a/libgo/go/syscall/sleep_rtems.go b/libgo/go/syscall/sleep_rtems.go
new file mode 100644
index 00000000000..8992eb53c3e
--- /dev/null
+++ b/libgo/go/syscall/sleep_rtems.go
@@ -0,0 +1,13 @@
+// sleep_rtems.go -- Sleep on RTEMS.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+func Sleep(nsec int64) (errno int) {
+ ts := NsecToTimespec(nsec)
+ errno = Nanosleep(&ts, nil)
+ return
+}
diff --git a/libgo/go/syscall/sleep_select.go b/libgo/go/syscall/sleep_select.go
new file mode 100644
index 00000000000..3ebaf58f969
--- /dev/null
+++ b/libgo/go/syscall/sleep_select.go
@@ -0,0 +1,13 @@
+// sleep_select.go -- Sleep using select.
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+func Sleep(nsec int64) (errno int) {
+ tv := NsecToTimeval(nsec);
+ _, err := Select(0, nil, nil, nil, &tv);
+ return err;
+}
diff --git a/libgo/go/syscall/sockcmsg_linux.go b/libgo/go/syscall/sockcmsg_linux.go
new file mode 100644
index 00000000000..b025ca52101
--- /dev/null
+++ b/libgo/go/syscall/sockcmsg_linux.go
@@ -0,0 +1,38 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Socket control messages
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+// UnixCredentials encodes credentials into a socket control message
+// for sending to another process. This can be used for
+// authentication.
+func UnixCredentials(ucred *Ucred) []byte {
+ buf := make([]byte, CmsgSpace(SizeofUcred))
+ cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
+ cmsg.Level = SOL_SOCKET
+ cmsg.Type = SCM_CREDENTIALS
+ cmsg.SetLen(CmsgLen(SizeofUcred))
+ *((*Ucred)(cmsgData(cmsg))) = *ucred
+ return buf
+}
+
+// ParseUnixCredentials decodes a socket control message that contains
+// credentials in a Ucred structure. To receive such a message, the
+// SO_PASSCRED option must be enabled on the socket.
+func ParseUnixCredentials(msg *SocketControlMessage) (*Ucred, int) {
+ if msg.Header.Level != SOL_SOCKET {
+ return nil, EINVAL
+ }
+ if msg.Header.Type != SCM_CREDENTIALS {
+ return nil, EINVAL
+ }
+ ucred := *(*Ucred)(unsafe.Pointer(&msg.Data[0]))
+ return &ucred, 0
+}
diff --git a/libgo/go/syscall/sockcmsg_unix.go b/libgo/go/syscall/sockcmsg_unix.go
new file mode 100644
index 00000000000..c9872aeba31
--- /dev/null
+++ b/libgo/go/syscall/sockcmsg_unix.go
@@ -0,0 +1,115 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux openbsd
+
+// Socket control messages
+
+package syscall
+
+import (
+ "unsafe"
+)
+
+// Round the length of a raw sockaddr up to align it propery.
+func cmsgAlignOf(salen int) int {
+ salign := sizeofPtr
+ // NOTE: It seems like 64-bit Darwin kernel still requires 32-bit
+ // aligned access to BSD subsystem.
+ if darwinAMD64 {
+ salign = 4
+ }
+ if salen == 0 {
+ return salign
+ }
+ return (salen + salign - 1) & ^(salign - 1)
+}
+
+// CmsgLen returns the value to store in the Len field of the Cmsghdr
+// structure, taking into account any necessary alignment.
+func CmsgLen(datalen int) int {
+ return cmsgAlignOf(SizeofCmsghdr) + datalen
+}
+
+// CmsgSpace returns the number of bytes an ancillary element with
+// payload of the passed data length occupies.
+func CmsgSpace(datalen int) int {
+ return cmsgAlignOf(SizeofCmsghdr) + cmsgAlignOf(datalen)
+}
+
+func cmsgData(cmsg *Cmsghdr) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(unsafe.Pointer(cmsg)) + SizeofCmsghdr)
+}
+
+type SocketControlMessage struct {
+ Header Cmsghdr
+ Data []byte
+}
+
+func ParseSocketControlMessage(buf []byte) ([]SocketControlMessage, int) {
+ var (
+ h *Cmsghdr
+ dbuf []byte
+ e int
+ cmsgs []SocketControlMessage
+ )
+
+ for len(buf) >= CmsgLen(0) {
+ h, dbuf, e = socketControlMessageHeaderAndData(buf)
+ if e != 0 {
+ break
+ }
+ m := SocketControlMessage{}
+ m.Header = *h
+ m.Data = dbuf[:int(h.Len)-cmsgAlignOf(SizeofCmsghdr)]
+ cmsgs = append(cmsgs, m)
+ buf = buf[cmsgAlignOf(int(h.Len)):]
+ }
+
+ return cmsgs, e
+}
+
+func socketControlMessageHeaderAndData(buf []byte) (*Cmsghdr, []byte, int) {
+ h := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
+ if h.Len < SizeofCmsghdr || int(h.Len) > len(buf) {
+ return nil, nil, EINVAL
+ }
+ return h, buf[cmsgAlignOf(SizeofCmsghdr):], 0
+}
+
+// UnixRights encodes a set of open file descriptors into a socket
+// control message for sending to another process.
+func UnixRights(fds ...int) []byte {
+ datalen := len(fds) * 4
+ buf := make([]byte, CmsgSpace(datalen))
+ cmsg := (*Cmsghdr)(unsafe.Pointer(&buf[0]))
+ cmsg.Level = SOL_SOCKET
+ cmsg.Type = SCM_RIGHTS
+ cmsg.SetLen(CmsgLen(datalen))
+
+ data := uintptr(cmsgData(cmsg))
+ for _, fd := range fds {
+ *(*int32)(unsafe.Pointer(data)) = int32(fd)
+ data += 4
+ }
+
+ return buf
+}
+
+// ParseUnixRights decodes a socket control message that contains an
+// integer array of open file descriptors from another process.
+func ParseUnixRights(msg *SocketControlMessage) ([]int, int) {
+ if msg.Header.Level != SOL_SOCKET {
+ return nil, EINVAL
+ }
+ if msg.Header.Type != SCM_RIGHTS {
+ return nil, EINVAL
+ }
+ fds := make([]int, len(msg.Data)>>2)
+ for i, j := 0, 0; i < len(msg.Data); i += 4 {
+ fds[j] = int(*(*int32)(unsafe.Pointer(&msg.Data[i])))
+ j++
+ }
+ return fds, 0
+}
diff --git a/libgo/go/syscall/socket.go b/libgo/go/syscall/socket.go
new file mode 100644
index 00000000000..e0218ba359d
--- /dev/null
+++ b/libgo/go/syscall/socket.go
@@ -0,0 +1,419 @@
+// socket.go -- Socket handling.
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Low-level socket interface.
+// Only for implementing net package.
+// DO NOT USE DIRECTLY.
+
+package syscall
+
+import "unsafe"
+
+// For testing: clients can set this flag to force
+// creation of IPv6 sockets to return EAFNOSUPPORT.
+var SocketDisableIPv6 bool
+
+type Sockaddr interface {
+ sockaddr() (ptr *RawSockaddrAny, len Socklen_t, errno int) // lowercase; only we can define Sockaddrs
+}
+
+type RawSockaddrAny struct {
+ Addr RawSockaddr
+ Pad [12]int8
+}
+
+const SizeofSockaddrAny = 0x1c
+
+type SockaddrInet4 struct {
+ Port int
+ Addr [4]byte
+ raw RawSockaddrInet4
+}
+
+func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ if sa.Port < 0 || sa.Port > 0xFFFF {
+ return nil, 0, EINVAL
+ }
+ sa.raw.Family = AF_INET
+ n := sa.raw.setLen()
+ p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
+ p[0] = byte(sa.Port>>8)
+ p[1] = byte(sa.Port)
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i]
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0
+}
+
+type SockaddrInet6 struct {
+ Port int
+ ZoneId uint32
+ Addr [16]byte
+ raw RawSockaddrInet6
+}
+
+func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ if sa.Port < 0 || sa.Port > 0xFFFF {
+ return nil, 0, EINVAL
+ }
+ sa.raw.Family = AF_INET6
+ n := sa.raw.setLen()
+ p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
+ p[0] = byte(sa.Port>>8)
+ p[1] = byte(sa.Port)
+ sa.raw.Scope_id = sa.ZoneId
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i]
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0
+}
+
+type SockaddrUnix struct {
+ Name string
+ raw RawSockaddrUnix
+}
+
+func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ name := sa.Name
+ n := len(name)
+ if n >= len(sa.raw.Path) || n == 0 {
+ return nil, 0, EINVAL
+ }
+ sa.raw.Family = AF_UNIX
+ sa.raw.setLen(n)
+ for i := 0; i < n; i++ {
+ sa.raw.Path[i] = int8(name[i])
+ }
+ if sa.raw.Path[0] == '@' {
+ sa.raw.Path[0] = 0
+ }
+
+ // length is family (uint16), name, NUL.
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 2 + Socklen_t(n) + 1, 0
+}
+
+func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
+ switch rsa.Addr.Family {
+ case AF_UNIX:
+ pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
+ sa := new(SockaddrUnix)
+ n, err := pp.getLen()
+ if err != 0 {
+ return nil, err
+ }
+ bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
+ sa.Name = string(bytes[0:n]);
+ return sa, 0;
+
+ case AF_INET:
+ pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
+ sa := new(SockaddrInet4);
+ p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+ sa.Port = int(p[0])<<8 + int(p[1]);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i];
+ }
+ return sa, 0;
+
+ case AF_INET6:
+ pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
+ sa := new(SockaddrInet6);
+ p := (*[2]byte)(unsafe.Pointer(&pp.Port));
+ sa.Port = int(p[0])<<8 + int(p[1]);
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i];
+ }
+ return sa, 0;
+ }
+ return anyToSockaddrOS(rsa)
+}
+
+//sys accept(fd int, sa *RawSockaddrAny, len *Socklen_t) (nfd int, errno int)
+//accept(fd int, sa *RawSockaddrAny, len *Socklen_t) int
+
+func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ nfd, errno = accept(fd, &rsa, &len)
+ if errno != 0 {
+ return
+ }
+ sa, errno = anyToSockaddr(&rsa)
+ if errno != 0 {
+ Close(nfd)
+ nfd = 0
+ }
+ return
+}
+
+//sysnb getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) (errno int)
+//getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) int
+
+func Getsockname(fd int) (sa Sockaddr, errno int) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ if errno = getsockname(fd, &rsa, &len); errno != 0 {
+ return
+ }
+ return anyToSockaddr(&rsa)
+}
+
+//sysnb getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) (errno int)
+//getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) int
+
+func Getpeername(fd int) (sa Sockaddr, errno int) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ if getpeername(fd, &rsa, &len); errno != 0 {
+ return
+ }
+ return anyToSockaddr(&rsa)
+}
+
+//sys bind(fd int, sa *RawSockaddrAny, len Socklen_t) (errno int)
+//bind(fd int, sa *RawSockaddrAny, len Socklen_t) int
+
+func Bind(fd int, sa Sockaddr) (errno int) {
+ ptr, n, err := sa.sockaddr()
+ if err != 0 {
+ return err
+ }
+ return bind(fd, ptr, n)
+}
+
+//sys connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) (errno int)
+//connect(s int, addr *RawSockaddrAny, addrlen Socklen_t) int
+
+func Connect(fd int, sa Sockaddr) (errno int) {
+ ptr, n, err := sa.sockaddr()
+ if err != 0 {
+ return err
+ }
+ return connect(fd, ptr, n)
+}
+
+//sysnb socket(domain int, typ int, proto int) (fd int, errno int)
+//socket(domain int, typ int, protocol int) int
+
+func Socket(domain, typ, proto int) (fd, errno int) {
+ if domain == AF_INET6 && SocketDisableIPv6 {
+ return -1, EAFNOSUPPORT
+ }
+ fd, errno = socket(domain, typ, proto)
+ return
+}
+
+//sysnb socketpair(domain int, typ int, proto int, fd *[2]int) (errno int)
+//socketpair(domain int, typ int, protocol int, fd *[2]int) int
+
+func Socketpair(domain, typ, proto int) (fd [2]int, errno int) {
+ errno = socketpair(domain, typ, proto, &fd)
+ return
+}
+
+//sys getsockopt(s int, level int, name int, val uintptr, vallen *Socklen_t) (errno int)
+//getsockopt(s int, level int, name int, val *byte, vallen *Socklen_t) int
+
+func GetsockoptInt(fd, level, opt int) (value, errno int) {
+ var n int32
+ vallen := Socklen_t(4)
+ errno = getsockopt(fd, level, opt, (uintptr)(unsafe.Pointer(&n)), &vallen)
+ return int(n), errno
+}
+
+func GetsockoptInet4Addr(fd, level, opt int) (value [4]byte, errno int) {
+ vallen := Socklen_t(4)
+ errno = getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value[0])), &vallen)
+ return value, errno
+}
+
+func GetsockoptIPMreq(fd, level, opt int) (*IPMreq, int) {
+ var value IPMreq
+ vallen := Socklen_t(SizeofIPMreq)
+ errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+ return &value, errno
+}
+
+/* FIXME: mksysinfo needs to support IPMreqn.
+
+func GetsockoptIPMreqn(fd, level, opt int) (*IPMreqn, int) {
+ var value IPMreqn
+ vallen := Socklen_t(SizeofIPMreqn)
+ errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+ return &value, errno
+}
+
+*/
+
+/* FIXME: mksysinfo needs to support IPv6Mreq.
+
+func GetsockoptIPv6Mreq(fd, level, opt int) (*IPv6Mreq, int) {
+ var value IPv6Mreq
+ vallen := Socklen_t(SizeofIPv6Mreq)
+ errno := getsockopt(fd, level, opt, uintptr(unsafe.Pointer(&value)), &vallen)
+ return &value, errno
+}
+
+*/
+
+//sys setsockopt(s int, level int, name int, val *byte, vallen Socklen_t) (errno int)
+//setsockopt(s int, level int, optname int, val *byte, vallen Socklen_t) int
+
+func SetsockoptInt(fd, level, opt int, value int) (errno int) {
+ var n = int32(value)
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&n)), 4)
+}
+
+func SetsockoptInet4Addr(fd, level, opt int, value [4]byte) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&value[0])), 4)
+}
+
+func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(tv)), Socklen_t(unsafe.Sizeof(*tv)))
+}
+
+type Linger struct {
+ Onoff int32;
+ Linger int32;
+}
+
+func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(l)), Socklen_t(unsafe.Sizeof(*l)));
+}
+
+func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+/* FIXME: mksysinfo needs to support IMPreqn.
+
+func SetsockoptIPMreqn(fd, level, opt int, mreq *IPMreqn) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+*/
+
+func SetsockoptIPv6Mreq(fd, level, opt int, mreq *IPv6Mreq) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(mreq)), Socklen_t(unsafe.Sizeof(*mreq)))
+}
+
+func SetsockoptString(fd, level, opt int, s string) (errno int) {
+ return setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&[]byte(s)[0])), Socklen_t(len(s)))
+}
+
+//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *Socklen_t) (n int, errno int)
+//recvfrom(fd int, buf *byte, len Size_t, flags int, from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t
+
+func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
+ var rsa RawSockaddrAny
+ var len Socklen_t = SizeofSockaddrAny
+ if n, errno = recvfrom(fd, p, flags, &rsa, &len); errno != 0 {
+ return
+ }
+ from, errno = anyToSockaddr(&rsa)
+ return
+}
+
+//sys sendto(s int, buf []byte, flags int, to *RawSockaddrAny, tolen Socklen_t) (errno int)
+//sendto(s int, buf *byte, len Size_t, flags int, to *RawSockaddrAny, tolen Socklen_t) Ssize_t
+
+func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
+ ptr, n, err := to.sockaddr()
+ if err != 0 {
+ return err
+ }
+ return sendto(fd, p, flags, ptr, n)
+}
+
+//sys recvmsg(s int, msg *Msghdr, flags int) (n int, errno int)
+//recvmsg(s int, msg *Msghdr, flags int) Ssize_t
+
+func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
+ var msg Msghdr
+ var rsa RawSockaddrAny
+ msg.Name = (*byte)(unsafe.Pointer(&rsa))
+ msg.Namelen = uint32(SizeofSockaddrAny)
+ var iov Iovec
+ if len(p) > 0 {
+ iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+ iov.SetLen(len(p))
+ }
+ var dummy byte
+ if len(oob) > 0 {
+ // receive at least one normal byte
+ if len(p) == 0 {
+ iov.Base = &dummy
+ iov.SetLen(1)
+ }
+ msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ msg.SetControllen(len(oob))
+ }
+ msg.Iov = &iov
+ msg.Iovlen = 1
+ if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
+ return
+ }
+ oobn = int(msg.Controllen)
+ recvflags = int(msg.Flags)
+ // source address is only specified if the socket is unconnected
+ if rsa.Addr.Family != AF_UNSPEC {
+ from, errno = anyToSockaddr(&rsa)
+ }
+ return
+}
+
+//sys sendmsg(s int, msg *Msghdr, flags int) (errno int)
+//sendmsg(s int, msg *Msghdr, flags int) Ssize_t
+
+func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
+ var ptr *RawSockaddrAny
+ var salen Socklen_t
+ if to != nil {
+ var err int
+ ptr, salen, err = to.sockaddr()
+ if err != 0 {
+ return err
+ }
+ }
+ var msg Msghdr
+ msg.Name = (*byte)(unsafe.Pointer(ptr))
+ msg.Namelen = uint32(salen)
+ var iov Iovec
+ if len(p) > 0 {
+ iov.Base = (*byte)(unsafe.Pointer(&p[0]))
+ iov.SetLen(len(p))
+ }
+ var dummy byte
+ if len(oob) > 0 {
+ // send at least one normal byte
+ if len(p) == 0 {
+ iov.Base = &dummy
+ iov.SetLen(1)
+ }
+ msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
+ msg.SetControllen(len(oob))
+ }
+ msg.Iov = &iov
+ msg.Iovlen = 1
+ if errno = sendmsg(fd, &msg, flags); errno != 0 {
+ return
+ }
+ return
+}
+
+//sys Listen(fd int, n int) (errno int)
+//listen(fd int, n int) int
+
+//sys Shutdown(fd int, how int) (errno int)
+//shutdown(fd int, how int) int
+
+func (iov *Iovec) SetLen(length int) {
+ iov.Len = Iovec_len_t(length)
+}
+
+func (msghdr *Msghdr) SetControllen(length int) {
+ msghdr.Controllen = Msghdr_controllen_t(length)
+}
diff --git a/libgo/syscalls/socket_bsd.go b/libgo/go/syscall/socket_bsd.go
index 735baf98684..735baf98684 100644
--- a/libgo/syscalls/socket_bsd.go
+++ b/libgo/go/syscall/socket_bsd.go
diff --git a/libgo/go/syscall/socket_irix.go b/libgo/go/syscall/socket_irix.go
new file mode 100644
index 00000000000..8bd55b8b4d9
--- /dev/null
+++ b/libgo/go/syscall/socket_irix.go
@@ -0,0 +1,129 @@
+// socket_irix.go -- Socket handling specific to IRIX 6.
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+const SizeofSockaddrUnix = 110
+
+type RawSockaddrInet4 struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]uint8
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+ return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+ return SizeofSockaddrInet6
+}
+
+type RawSockaddrUnix struct {
+ Family uint16
+ Path [108]int8
+}
+
+func (sa *RawSockaddrUnix) setLen(int) {
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, int) {
+ if sa.Path[0] == 0 {
+ // "Abstract" Unix domain socket.
+ // Rewrite leading NUL as @ for textual display.
+ // (This is the standard convention.)
+ // Not friendly to overwrite in place,
+ // but the callers below don't care.
+ sa.Path[0] = '@'
+ }
+
+ // Assume path ends at NUL.
+ // This is not technically the GNU/Linux semantics for
+ // abstract Unix domain sockets--they are supposed
+ // to be uninterpreted fixed-size binary blobs--but
+ // everyone uses this convention.
+ n := 0
+ for n < len(sa.Path)-3 && sa.Path[n] != 0 {
+ n++
+ }
+
+ return n, 0
+}
+
+type RawSockaddr struct {
+ Family uint16
+ Data [14]int8
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (errno int) {
+ return ENOSYS
+}
+
+// struct ip_mreg is provived in <netinet/in.h>, but protected with _SGIAPI.
+// This could be enabled with -D_SGI_SOURCE, but conflicts with
+// -D_XOPEN_SOURCE=500 required for msg_control etc. in struct msghgr, so
+// simply provide it here.
+type IPMreq struct {
+ Multiaddr [4]byte
+ Interface [4]byte
+}
+
+// Similarly, <netdb.h> only provides struct addrinfo, AI_* and EAI_* if
+// _NO_XOPEN4 && _NO_XOPEN5.
+type Addrinfo struct {
+ Ai_flags int32
+ Ai_family int32
+ Ai_socktype int32
+ Ai_protocol int32
+ Ai_addrlen int32
+ Ai_canonname *uint8
+ Ai_addr *_sockaddr
+ Ai_next *Addrinfo
+}
+
+const (
+ AI_PASSIVE = 0x00000001
+ AI_CANONNAME = 0x00000002
+ AI_NUMERICHOST = 0x00000004
+ AI_NUMERICSERV = 0x00000008
+ AI_ALL = 0x00000100
+ AI_ADDRCONFIG = 0x00000400
+ AI_V4MAPPED = 0x00000800
+ AI_DEFAULT = (AI_V4MAPPED | AI_ADDRCONFIG)
+)
+
+const (
+ EAI_ADDRFAMILY = 1
+ EAI_AGAIN = 2
+ EAI_BADFLAGS = 3
+ EAI_FAIL = 4
+ EAI_FAMILY = 5
+ EAI_MEMORY = 6
+ EAI_NODATA = 7
+ EAI_NONAME = 8
+ EAI_SERVICE = 9
+ EAI_SOCKTYPE = 10
+ EAI_SYSTEM = 11
+ EAI_BADHINTS = 12
+ EAI_OVERFLOW = 13
+ EAI_MAX = 14
+)
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
+ return nil, EAFNOSUPPORT;
+}
diff --git a/libgo/go/syscall/socket_linux.go b/libgo/go/syscall/socket_linux.go
new file mode 100644
index 00000000000..49aac87bb7a
--- /dev/null
+++ b/libgo/go/syscall/socket_linux.go
@@ -0,0 +1,174 @@
+// socket_linux.go -- Socket handling specific to GNU/Linux.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+import "unsafe"
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 28
+const SizeofSockaddrUnix = 110
+const SizeofSockaddrLinklayer = 20
+const SizeofSockaddrNetlink = 12
+
+type SockaddrLinklayer struct {
+ Protocol uint16
+ Ifindex int
+ Hatype uint16
+ Pkttype uint8
+ Halen uint8
+ Addr [8]byte
+ raw RawSockaddrLinklayer
+}
+
+func (sa *SockaddrLinklayer) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
+ return nil, 0, EINVAL
+ }
+ sa.raw.Family = AF_PACKET
+ sa.raw.Protocol = sa.Protocol
+ sa.raw.Ifindex = int32(sa.Ifindex)
+ sa.raw.Hatype = sa.Hatype
+ sa.raw.Pkttype = sa.Pkttype
+ sa.raw.Halen = sa.Halen
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.raw.Addr[i] = sa.Addr[i]
+ }
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrLinklayer, 0
+}
+
+type SockaddrNetlink struct {
+ Family uint16
+ Pad uint16
+ Pid uint32
+ Groups uint32
+ raw RawSockaddrNetlink
+}
+
+func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
+ sa.raw.Family = AF_NETLINK
+ sa.raw.Pad = sa.Pad
+ sa.raw.Pid = sa.Pid
+ sa.raw.Groups = sa.Groups
+ return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrNetlink, 0
+}
+
+type RawSockaddrInet4 struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]uint8
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+ return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+ return SizeofSockaddrInet6
+}
+
+type RawSockaddrUnix struct {
+ Family uint16
+ Path [108]int8
+}
+
+func (sa *RawSockaddrUnix) setLen(int) {
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, int) {
+ if sa.Path[0] == 0 {
+ // "Abstract" Unix domain socket.
+ // Rewrite leading NUL as @ for textual display.
+ // (This is the standard convention.)
+ // Not friendly to overwrite in place,
+ // but the callers below don't care.
+ sa.Path[0] = '@'
+ }
+
+ // Assume path ends at NUL.
+ // This is not technically the GNU/Linux semantics for
+ // abstract Unix domain sockets--they are supposed
+ // to be uninterpreted fixed-size binary blobs--but
+ // everyone uses this convention.
+ n := 0
+ for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
+ n++
+ }
+
+ return n, 0
+}
+
+type RawSockaddrLinklayer struct {
+ Family uint16
+ Protocol uint16
+ Ifindex int32
+ Hatype uint16
+ Pkttype uint8
+ Halen uint8
+ Addr [8]uint8
+}
+
+type RawSockaddrNetlink struct {
+ Family uint16
+ Pad uint16
+ Pid uint32
+ Groups uint32
+}
+
+type RawSockaddr struct {
+ Family uint16
+ Data [14]int8
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (errno int) {
+ return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)
+}
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
+ switch rsa.Addr.Family {
+ case AF_NETLINK:
+ pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa))
+ sa := new(SockaddrNetlink)
+ sa.Family = pp.Family
+ sa.Pad = pp.Pad
+ sa.Pid = pp.Pid
+ sa.Groups = pp.Groups
+ return sa, 0
+
+ case AF_PACKET:
+ pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa))
+ sa := new(SockaddrLinklayer)
+ sa.Protocol = pp.Protocol
+ sa.Ifindex = int(pp.Ifindex)
+ sa.Hatype = pp.Hatype
+ sa.Pkttype = pp.Pkttype
+ sa.Halen = pp.Halen
+ for i := 0; i < len(sa.Addr); i++ {
+ sa.Addr[i] = pp.Addr[i]
+ }
+ return sa, 0
+ }
+ return nil, EAFNOSUPPORT
+}
+
+//sysnb EpollCreate(size int) (fd int, errno int)
+//epoll_create(size int) int
+
+//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (errno int)
+//epoll_ctl(epfd int, op int, fd int, event *EpollEvent) int
+
+//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, errno int)
+//epoll_wait(epfd int, events *EpollEvent, maxevents int, timeout int) int
diff --git a/libgo/go/syscall/socket_solaris.go b/libgo/go/syscall/socket_solaris.go
new file mode 100644
index 00000000000..0c3e6c9724e
--- /dev/null
+++ b/libgo/go/syscall/socket_solaris.go
@@ -0,0 +1,80 @@
+// socket_solaris.go -- Socket handling specific to Solaris.
+
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+const SizeofSockaddrInet4 = 16
+const SizeofSockaddrInet6 = 32
+const SizeofSockaddrUnix = 110
+
+type RawSockaddrInet4 struct {
+ Family uint16
+ Port uint16
+ Addr [4]byte /* in_addr */
+ Zero [8]uint8
+}
+
+func (sa *RawSockaddrInet4) setLen() Socklen_t {
+ return SizeofSockaddrInet4
+}
+
+type RawSockaddrInet6 struct {
+ Family uint16
+ Port uint16
+ Flowinfo uint32
+ Addr [16]byte /* in6_addr */
+ Scope_id uint32
+ Src_id uint32
+}
+
+func (sa *RawSockaddrInet6) setLen() Socklen_t {
+ return SizeofSockaddrInet6
+}
+
+type RawSockaddrUnix struct {
+ Family uint16
+ Path [108]int8
+}
+
+func (sa *RawSockaddrUnix) setLen(int) {
+}
+
+func (sa *RawSockaddrUnix) getLen() (int, int) {
+ if sa.Path[0] == 0 {
+ // "Abstract" Unix domain socket.
+ // Rewrite leading NUL as @ for textual display.
+ // (This is the standard convention.)
+ // Not friendly to overwrite in place,
+ // but the callers below don't care.
+ sa.Path[0] = '@'
+ }
+
+ // Assume path ends at NUL.
+ // This is not technically the GNU/Linux semantics for
+ // abstract Unix domain sockets--they are supposed
+ // to be uninterpreted fixed-size binary blobs--but
+ // everyone uses this convention.
+ n := 0
+ for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
+ n++
+ }
+
+ return n, 0
+}
+
+type RawSockaddr struct {
+ Family uint16
+ Data [14]int8
+}
+
+// BindToDevice binds the socket associated with fd to device.
+func BindToDevice(fd int, device string) (errno int) {
+ return ENOSYS
+}
+
+func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
+ return nil, EAFNOSUPPORT;
+}
diff --git a/libgo/go/syscall/str.go b/libgo/go/syscall/str.go
new file mode 100644
index 00000000000..0fce842e8c1
--- /dev/null
+++ b/libgo/go/syscall/str.go
@@ -0,0 +1,20 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package syscall
+
+func itoa(val int) string { // do it here rather than with fmt to avoid dependency
+ if val < 0 {
+ return "-" + itoa(-val)
+ }
+ var buf [32]byte // big enough for int64
+ i := len(buf) - 1
+ for val >= 10 {
+ buf[i] = byte(val%10 + '0')
+ i--
+ val /= 10
+ }
+ buf[i] = byte(val + '0')
+ return string(buf[i:])
+}
diff --git a/libgo/go/syscall/syscall.go b/libgo/go/syscall/syscall.go
new file mode 100644
index 00000000000..a802ba0bbf2
--- /dev/null
+++ b/libgo/go/syscall/syscall.go
@@ -0,0 +1,35 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package syscall contains an interface to the low-level operating system
+// primitives. The details vary depending on the underlying system.
+// Its primary use is inside other packages that provide a more portable
+// interface to the system, such as "os", "time" and "net". Use those
+// packages rather than this one if you can.
+// For details of the functions and data types in this package consult
+// the manuals for the appropriate operating system.
+// These calls return errno == 0 to indicate success; otherwise
+// errno is an operating system error number describing the failure.
+package syscall
+
+import "unsafe"
+
+// StringByteSlice returns a NUL-terminated slice of bytes
+// containing the text of s.
+func StringByteSlice(s string) []byte {
+ a := make([]byte, len(s)+1)
+ copy(a, s)
+ return a
+}
+
+// StringBytePtr returns a pointer to a NUL-terminated array of bytes
+// containing the text of s.
+func StringBytePtr(s string) *byte { return &StringByteSlice(s)[0] }
+
+// Single-word zero for use when we need a valid pointer to 0 bytes.
+// See mksyscall.pl.
+var _zero uintptr
+
+var dummy *byte
+const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
diff --git a/libgo/syscalls/syscall_linux_386.go b/libgo/go/syscall/syscall_linux_386.go
index aca9c7bf5ef..aca9c7bf5ef 100644
--- a/libgo/syscalls/syscall_linux_386.go
+++ b/libgo/go/syscall/syscall_linux_386.go
diff --git a/libgo/syscalls/syscall_linux_alpha.go b/libgo/go/syscall/syscall_linux_alpha.go
index d58f8eb13a5..d58f8eb13a5 100644
--- a/libgo/syscalls/syscall_linux_alpha.go
+++ b/libgo/go/syscall/syscall_linux_alpha.go
diff --git a/libgo/syscalls/syscall_linux_amd64.go b/libgo/go/syscall/syscall_linux_amd64.go
index 9932579cc10..9932579cc10 100644
--- a/libgo/syscalls/syscall_linux_amd64.go
+++ b/libgo/go/syscall/syscall_linux_amd64.go
diff --git a/libgo/go/syscall/syscall_stubs.go b/libgo/go/syscall/syscall_stubs.go
new file mode 100644
index 00000000000..76c05cb546a
--- /dev/null
+++ b/libgo/go/syscall/syscall_stubs.go
@@ -0,0 +1,27 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// These are stubs.
+
+package syscall
+
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ z := -1
+ return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ z := -1
+ return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ z := -1
+ return uintptr(z), 0, uintptr(ENOSYS)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ z := -1
+ return uintptr(z), 0, uintptr(ENOSYS)
+}
diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go
new file mode 100644
index 00000000000..c734b2cf06a
--- /dev/null
+++ b/libgo/go/syscall/syscall_unix.go
@@ -0,0 +1,159 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux openbsd
+
+package syscall
+
+import (
+ "sync"
+ "unsafe"
+)
+
+var (
+ Stdin = 0
+ Stdout = 1
+ Stderr = 2
+)
+
+func c_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 __asm__ ("syscall");
+func c_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 __asm__ ("syscall");
+
+// Do a system call. We look at the size of uintptr to see how to pass
+// the arguments, so that we don't pass a 64-bit value when the function
+// expects a 32-bit one.
+func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ entersyscall()
+ var r uintptr
+ if unsafe.Sizeof(r) == 4 {
+ r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
+ r = uintptr(r1)
+ } else {
+ r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
+ r = uintptr(r1)
+ }
+ errno := GetErrno()
+ exitsyscall()
+ return r, 0, uintptr(errno)
+}
+
+func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ entersyscall()
+ var r uintptr
+ if unsafe.Sizeof(r) == 4 {
+ r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
+ int32(a4), int32(a5), int32(a6))
+ r = uintptr(r1)
+ } else {
+ r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
+ int64(a4), int64(a5), int64(a6))
+ r = uintptr(r1)
+ }
+ errno := GetErrno()
+ exitsyscall()
+ return r, 0, uintptr(errno)
+}
+
+func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
+ var r uintptr
+ if unsafe.Sizeof(r) == 4 {
+ r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0)
+ r = uintptr(r1)
+ } else {
+ r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0)
+ r = uintptr(r1)
+ }
+ errno := GetErrno()
+ return r, 0, uintptr(errno)
+}
+
+func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
+ var r uintptr
+ if unsafe.Sizeof(r) == 4 {
+ r1 := c_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
+ int32(a4), int32(a5), int32(a6))
+ r = uintptr(r1)
+ } else {
+ r1 := c_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
+ int64(a4), int64(a5), int64(a6))
+ r = uintptr(r1)
+ }
+ errno := GetErrno()
+ return r, 0, uintptr(errno)
+}
+
+// Mmap manager, for use by operating system-specific implementations.
+// Gccgo only has one implementation but we do this to correspond to gc.
+
+type mmapper struct {
+ sync.Mutex
+ active map[*byte][]byte // active mappings; key is last byte in mapping
+ mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, int)
+ munmap func(addr uintptr, length uintptr) int
+}
+
+func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+ if length <= 0 {
+ return nil, EINVAL
+ }
+
+ // Map the requested memory.
+ addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
+ if errno != 0 {
+ return nil, errno
+ }
+
+ // Slice memory layout
+ var sl = struct {
+ addr uintptr
+ len int
+ cap int
+ }{addr, length, length}
+
+ // Use unsafe to turn sl into a []byte.
+ b := *(*[]byte)(unsafe.Pointer(&sl))
+
+ // Register mapping in m and return it.
+ p := &b[cap(b)-1]
+ m.Lock()
+ defer m.Unlock()
+ m.active[p] = b
+ return b, 0
+}
+
+func (m *mmapper) Munmap(data []byte) (errno int) {
+ if len(data) == 0 || len(data) != cap(data) {
+ return EINVAL
+ }
+
+ // Find the base of the mapping.
+ p := &data[cap(data)-1]
+ m.Lock()
+ defer m.Unlock()
+ b := m.active[p]
+ if b == nil || &b[0] != &data[0] {
+ return EINVAL
+ }
+
+ // Unmap the memory and update m.
+ if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != 0 {
+ return errno
+ }
+ m.active[p] = nil, false
+ return 0
+}
+
+var mapper = &mmapper{
+ active: make(map[*byte][]byte),
+ mmap: mmap,
+ munmap: munmap,
+}
+
+func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
+ return mapper.Mmap(fd, offset, length, prot, flags)
+}
+
+func Munmap(b []byte) (errno int) {
+ return mapper.Munmap(b)
+}
diff --git a/libgo/go/syscall/wait.c b/libgo/go/syscall/wait.c
new file mode 100644
index 00000000000..d3c90d74ea1
--- /dev/null
+++ b/libgo/go/syscall/wait.c
@@ -0,0 +1,107 @@
+/* wait.c -- functions for getting wait status values.
+
+ Copyright 2011 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file.
+
+ We use C code to extract the wait status so that we can easily be
+ OS-independent. */
+
+#define _GNU_SOURCE
+#define __EXTENSIONS__
+
+#include <stdint.h>
+#include <sys/wait.h>
+
+extern _Bool Exited (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Exited.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+Exited (uint32_t *w)
+{
+ return WIFEXITED (*w) != 0;
+}
+
+extern _Bool Signaled (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Signaled.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+Signaled (uint32_t *w)
+{
+ return WIFSIGNALED (*w) != 0;
+}
+
+extern _Bool Stopped (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Stopped.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+Stopped (uint32_t *w)
+{
+ return WIFSTOPPED (*w) != 0;
+}
+
+extern _Bool Continued (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Continued.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+Continued (uint32_t *w)
+{
+ return WIFCONTINUED (*w) != 0;
+}
+
+extern _Bool CoreDump (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.CoreDump.N32_libgo_syscall.syscall.WaitStatus");
+
+_Bool
+CoreDump (uint32_t *w)
+{
+ return WCOREDUMP (*w) != 0;
+}
+
+extern int ExitStatus (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.ExitStatus.N32_libgo_syscall.syscall.WaitStatus");
+
+int
+ExitStatus (uint32_t *w)
+{
+ if (!WIFEXITED (*w))
+ return -1;
+ return WEXITSTATUS (*w);
+}
+
+extern int Signal (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.Signal.N32_libgo_syscall.syscall.WaitStatus");
+
+int
+Signal (uint32_t *w)
+{
+ if (!WIFSIGNALED (*w))
+ return -1;
+ return WTERMSIG (*w);
+}
+
+extern int StopSignal (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.StopSignal.N32_libgo_syscall.syscall.WaitStatus");
+
+int
+StopSignal (uint32_t *w)
+{
+ if (!WIFSTOPPED (*w))
+ return -1;
+ return WSTOPSIG (*w);
+}
+
+extern int TrapCause (uint32_t *w)
+ __asm__ ("libgo_syscall.syscall.TrapCause.N32_libgo_syscall.syscall.WaitStatus");
+
+int
+TrapCause (uint32_t *w __attribute__ ((unused)))
+{
+#ifndef __linux__
+ return -1;
+#else
+ if (!WIFSTOPPED (*w) || WSTOPSIG (*w) != SIGTRAP)
+ return -1;
+ return *w >> 16;
+#endif
+}
diff --git a/libgo/go/template/exec.go b/libgo/go/template/exec.go
index f1590b3bb63..e7fad72fe71 100644
--- a/libgo/go/template/exec.go
+++ b/libgo/go/template/exec.go
@@ -511,7 +511,7 @@ func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Valu
// are much more constrained, so it makes more sense there than here.
// Besides, one is almost always all you need.
switch {
- case value.Kind() == reflect.Ptr && value.Elem().Type().AssignableTo(typ):
+ case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
value = value.Elem()
case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
value = value.Addr()
diff --git a/libgo/go/template/exec_test.go b/libgo/go/template/exec_test.go
index 8e1894ea03b..50b0ad2b75f 100644
--- a/libgo/go/template/exec_test.go
+++ b/libgo/go/template/exec_test.go
@@ -231,7 +231,7 @@ var execTests = []execTest{
{"dot complex", "<{{.}}>", "<(16.2-17i)>", 16.2 - 17i, true},
{"dot string", "<{{.}}>", "<hello>", "hello", true},
{"dot slice", "<{{.}}>", "<[-1 -2 -3]>", []int{-1, -2, -3}, true},
- {"dot map", "<{{.}}>", "<map[two:22 one:11]>", map[string]int{"one": 11, "two": 22}, true},
+ {"dot map", "<{{.}}>", "<map[two:22]>", map[string]int{"two": 22}, true},
{"dot struct", "<{{.}}>", "<{7 seven}>", struct {
a int
b string
@@ -493,6 +493,50 @@ func TestExecute(t *testing.T) {
testExecute(execTests, nil, t)
}
+var delimPairs = []string{
+ "", "", // default
+ "{{", "}}", // same as default
+ "<<", ">>", // distinct
+ "|", "|", // same
+ "(日)", "(本)", // peculiar
+}
+
+func TestDelims(t *testing.T) {
+ const hello = "Hello, world"
+ var value = struct{ Str string }{hello}
+ for i := 0; i < len(delimPairs); i += 2 {
+ text := ".Str"
+ left := delimPairs[i+0]
+ trueLeft := left
+ right := delimPairs[i+1]
+ trueRight := right
+ if left == "" { // default case
+ trueLeft = "{{"
+ }
+ if right == "" { // default case
+ trueRight = "}}"
+ }
+ text = trueLeft + text + trueRight
+ // Now add a comment
+ text += trueLeft + "/*comment*/" + trueRight
+ // Now add an action containing a string.
+ text += trueLeft + `"` + trueLeft + `"` + trueRight
+ // At this point text looks like `{{.Str}}{{/*comment*/}}{{"{{"}}`.
+ tmpl, err := New("delims").Delims(left, right).Parse(text)
+ if err != nil {
+ t.Fatalf("delim %q text %q parse err %s", left, text, err)
+ }
+ var b = new(bytes.Buffer)
+ err = tmpl.Execute(b, value)
+ if err != nil {
+ t.Fatalf("delim %q exec err %s", left, err)
+ }
+ if b.String() != hello+trueLeft {
+ t.Errorf("expected %q got %q", hello+trueLeft, b.String())
+ }
+ }
+}
+
// Check that an error from a method flows back to the top.
func TestExecuteError(t *testing.T) {
b := new(bytes.Buffer)
@@ -538,18 +582,19 @@ type Tree struct {
Left, Right *Tree
}
+// Use different delimiters to test Set.Delims.
const treeTemplate = `
- {{define "tree"}}
+ (define "tree")
[
- {{.Val}}
- {{with .Left}}
- {{template "tree" .}}
- {{end}}
- {{with .Right}}
- {{template "tree" .}}
- {{end}}
+ (.Val)
+ (with .Left)
+ (template "tree" .)
+ (end)
+ (with .Right)
+ (template "tree" .)
+ (end)
]
- {{end}}
+ (end)
`
func TestTree(t *testing.T) {
@@ -590,7 +635,7 @@ func TestTree(t *testing.T) {
},
}
set := new(Set)
- _, err := set.Parse(treeTemplate)
+ _, err := set.Delims("(", ")").Parse(treeTemplate)
if err != nil {
t.Fatal("parse error:", err)
}
diff --git a/libgo/go/template/helper.go b/libgo/go/template/helper.go
index c9b09985651..1dc90f7ff40 100644
--- a/libgo/go/template/helper.go
+++ b/libgo/go/template/helper.go
@@ -210,7 +210,8 @@ func ParseTemplateFiles(filenames ...string) (*Set, os.Error) {
}
// ParseTemplateGlob creates a set by parsing the files matched
-// by the pattern, each of which defines a single template. Each
+// by the pattern, each of which defines a single template. The pattern
+// is processed by filepath.Glob and must match at least one file. Each
// template will be named the base name of its file.
// Unlike with ParseGlob, each file should be a stand-alone template
// definition suitable for Template.Parse (not Set.Parse); that is, the
@@ -225,6 +226,9 @@ func ParseTemplateGlob(pattern string) (*Set, os.Error) {
if err != nil {
return nil, err
}
+ if len(filenames) == 0 {
+ return nil, fmt.Errorf("pattern matches no files: %#q", pattern)
+ }
for _, filename := range filenames {
t, err := ParseFile(filename)
if err != nil {
diff --git a/libgo/go/template/parse.go b/libgo/go/template/parse.go
index b089c599a47..3068a77bed9 100644
--- a/libgo/go/template/parse.go
+++ b/libgo/go/template/parse.go
@@ -14,6 +14,8 @@ import (
type Template struct {
name string
*parse.Tree
+ leftDelim string
+ rightDelim string
// We use two maps, one for parsing and one for execution.
// This separation makes the API cleaner since it doesn't
// expose reflection to the client.
@@ -38,6 +40,16 @@ func New(name string) *Template {
}
}
+// Delims sets the action delimiters, to be used in a subsequent
+// parse, to the specified strings.
+// An empty delimiter stands for the corresponding default: {{ or }}.
+// The return value is the template, so calls can be chained.
+func (t *Template) Delims(left, right string) *Template {
+ t.leftDelim = left
+ t.rightDelim = right
+ return t
+}
+
// Funcs adds the elements of the argument map to the template's function
// map. It panics if a value in the map is not a function with appropriate
// return type.
@@ -51,7 +63,7 @@ func (t *Template) Funcs(funcMap FuncMap) *Template {
// Parse parses the template definition string to construct an internal
// representation of the template for execution.
func (t *Template) Parse(s string) (tmpl *Template, err os.Error) {
- t.Tree, err = parse.New(t.name).Parse(s, t.parseFuncs, builtins)
+ t.Tree, err = parse.New(t.name).Parse(s, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)
if err != nil {
return nil, err
}
@@ -67,7 +79,7 @@ func (t *Template) ParseInSet(s string, set *Set) (tmpl *Template, err os.Error)
if set != nil {
setFuncs = set.parseFuncs
}
- t.Tree, err = parse.New(t.name).Parse(s, t.parseFuncs, setFuncs, builtins)
+ t.Tree, err = parse.New(t.name).Parse(s, t.leftDelim, t.rightDelim, t.parseFuncs, setFuncs, builtins)
if err != nil {
return nil, err
}
diff --git a/libgo/go/template/parse/lex.go b/libgo/go/template/parse/lex.go
index 83ad6c628bf..16ff590d3b4 100644
--- a/libgo/go/template/parse/lex.go
+++ b/libgo/go/template/parse/lex.go
@@ -119,13 +119,15 @@ type stateFn func(*lexer) stateFn
// lexer holds the state of the scanner.
type lexer struct {
- name string // the name of the input; used only for error reports.
- input string // the string being scanned.
- state stateFn // the next lexing function to enter
- pos int // current position in the input.
- start int // start position of this item.
- width int // width of last rune read from input.
- items chan item // channel of scanned items.
+ name string // the name of the input; used only for error reports.
+ input string // the string being scanned.
+ leftDelim string // start of action.
+ rightDelim string // end of action.
+ state stateFn // the next lexing function to enter.
+ pos int // current position in the input.
+ start int // start position of this item.
+ width int // width of last rune read from input.
+ items chan item // channel of scanned items.
}
// next returns the next rune in the input.
@@ -205,12 +207,20 @@ func (l *lexer) nextItem() item {
}
// lex creates a new scanner for the input string.
-func lex(name, input string) *lexer {
+func lex(name, input, left, right string) *lexer {
+ if left == "" {
+ left = leftDelim
+ }
+ if right == "" {
+ right = rightDelim
+ }
l := &lexer{
- name: name,
- input: input,
- state: lexText,
- items: make(chan item, 2), // Two items of buffering is sufficient for all state functions
+ name: name,
+ input: input,
+ leftDelim: left,
+ rightDelim: right,
+ state: lexText,
+ items: make(chan item, 2), // Two items of buffering is sufficient for all state functions
}
return l
}
@@ -220,14 +230,14 @@ func lex(name, input string) *lexer {
const (
leftDelim = "{{"
rightDelim = "}}"
- leftComment = "{{/*"
- rightComment = "*/}}"
+ leftComment = "/*"
+ rightComment = "*/"
)
// lexText scans until an opening action delimiter, "{{".
func lexText(l *lexer) stateFn {
for {
- if strings.HasPrefix(l.input[l.pos:], leftDelim) {
+ if strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
if l.pos > l.start {
l.emit(itemText)
}
@@ -247,28 +257,28 @@ func lexText(l *lexer) stateFn {
// lexLeftDelim scans the left delimiter, which is known to be present.
func lexLeftDelim(l *lexer) stateFn {
- if strings.HasPrefix(l.input[l.pos:], leftComment) {
+ if strings.HasPrefix(l.input[l.pos:], l.leftDelim+leftComment) {
return lexComment
}
- l.pos += len(leftDelim)
+ l.pos += len(l.leftDelim)
l.emit(itemLeftDelim)
return lexInsideAction
}
// lexComment scans a comment. The left comment marker is known to be present.
func lexComment(l *lexer) stateFn {
- i := strings.Index(l.input[l.pos:], rightComment)
+ i := strings.Index(l.input[l.pos:], rightComment+l.rightDelim)
if i < 0 {
return l.errorf("unclosed comment")
}
- l.pos += i + len(rightComment)
+ l.pos += i + len(rightComment) + len(l.rightDelim)
l.ignore()
return lexText
}
// lexRightDelim scans the right delimiter, which is known to be present.
func lexRightDelim(l *lexer) stateFn {
- l.pos += len(rightDelim)
+ l.pos += len(l.rightDelim)
l.emit(itemRightDelim)
return lexText
}
@@ -278,7 +288,7 @@ func lexInsideAction(l *lexer) stateFn {
// Either number, quoted string, or identifier.
// Spaces separate and are ignored.
// Pipe symbols separate and are emitted.
- if strings.HasPrefix(l.input[l.pos:], rightDelim) {
+ if strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
return lexRightDelim
}
switch r := l.next(); {
diff --git a/libgo/go/template/parse/lex_test.go b/libgo/go/template/parse/lex_test.go
index d71c8e66df2..6ee1b470102 100644
--- a/libgo/go/template/parse/lex_test.go
+++ b/libgo/go/template/parse/lex_test.go
@@ -201,8 +201,8 @@ var lexTests = []lexTest{
}
// collect gathers the emitted items into a slice.
-func collect(t *lexTest) (items []item) {
- l := lex(t.name, t.input)
+func collect(t *lexTest, left, right string) (items []item) {
+ l := lex(t.name, t.input, left, right)
for {
item := l.nextItem()
items = append(items, item)
@@ -215,7 +215,41 @@ func collect(t *lexTest) (items []item) {
func TestLex(t *testing.T) {
for _, test := range lexTests {
- items := collect(&test)
+ items := collect(&test, "", "")
+ if !reflect.DeepEqual(items, test.items) {
+ t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
+ }
+ }
+}
+
+// Some easy cases from above, but with delimiters $$ and @@
+var lexDelimTests = []lexTest{
+ {"punctuation", "$$,@%{{}}@@", []item{
+ tLeftDelim,
+ {itemChar, ","},
+ {itemChar, "@"},
+ {itemChar, "%"},
+ {itemChar, "{"},
+ {itemChar, "{"},
+ {itemChar, "}"},
+ {itemChar, "}"},
+ tRightDelim,
+ tEOF,
+ }},
+ {"empty action", `$$@@`, []item{tLeftDelim, tRightDelim, tEOF}},
+ {"for", `$$for @@`, []item{tLeftDelim, tFor, tRightDelim, tEOF}},
+ {"quote", `$$"abc \n\t\" "@@`, []item{tLeftDelim, tQuote, tRightDelim, tEOF}},
+ {"raw quote", "$$" + raw + "@@", []item{tLeftDelim, tRawQuote, tRightDelim, tEOF}},
+}
+
+var (
+ tLeftDelim = item{itemLeftDelim, "$$"}
+ tRightDelim = item{itemRightDelim, "@@"}
+)
+
+func TestDelims(t *testing.T) {
+ for _, test := range lexDelimTests {
+ items := collect(&test, "$$", "@@")
if !reflect.DeepEqual(items, test.items) {
t.Errorf("%s: got\n\t%v\nexpected\n\t%v", test.name, items, test.items)
}
diff --git a/libgo/go/template/parse/node.go b/libgo/go/template/parse/node.go
index 6f0b429b958..7411327a651 100644
--- a/libgo/go/template/parse/node.go
+++ b/libgo/go/template/parse/node.go
@@ -390,8 +390,8 @@ func (e *elseNode) String() string {
return "{{else}}"
}
-// IfNode represents an {{if}} action and its commands.
-type IfNode struct {
+// BranchNode is the common representation of if, range, and with.
+type BranchNode struct {
NodeType
Line int // The line number in the input.
Pipe *PipeNode // The pipeline to be evaluated.
@@ -399,35 +399,49 @@ type IfNode struct {
ElseList *ListNode // What to execute if the value is empty (nil if absent).
}
-func newIf(line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
- return &IfNode{NodeType: NodeIf, Line: line, Pipe: pipe, List: list, ElseList: elseList}
+func (b *BranchNode) String() string {
+ name := ""
+ switch b.NodeType {
+ case NodeIf:
+ name = "if"
+ case NodeRange:
+ name = "range"
+ case NodeWith:
+ name = "with"
+ default:
+ panic("unknown branch type")
+ }
+ if b.ElseList != nil {
+ return fmt.Sprintf("({{%s %s}} %s {{else}} %s)", name, b.Pipe, b.List, b.ElseList)
+ }
+ return fmt.Sprintf("({{%s %s}} %s)", name, b.Pipe, b.List)
}
-func (i *IfNode) String() string {
- if i.ElseList != nil {
- return fmt.Sprintf("({{if %s}} %s {{else}} %s)", i.Pipe, i.List, i.ElseList)
- }
- return fmt.Sprintf("({{if %s}} %s)", i.Pipe, i.List)
+// IfNode represents an {{if}} action and its commands.
+type IfNode struct {
+ BranchNode
+}
+
+func newIf(line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
+ return &IfNode{BranchNode{NodeType: NodeIf, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
// RangeNode represents a {{range}} action and its commands.
type RangeNode struct {
- NodeType
- Line int // The line number in the input.
- Pipe *PipeNode // The pipeline to be evaluated.
- List *ListNode // What to execute if the value is non-empty.
- ElseList *ListNode // What to execute if the value is empty (nil if absent).
+ BranchNode
}
func newRange(line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
- return &RangeNode{NodeType: NodeRange, Line: line, Pipe: pipe, List: list, ElseList: elseList}
+ return &RangeNode{BranchNode{NodeType: NodeRange, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
-func (r *RangeNode) String() string {
- if r.ElseList != nil {
- return fmt.Sprintf("({{range %s}} %s {{else}} %s)", r.Pipe, r.List, r.ElseList)
- }
- return fmt.Sprintf("({{range %s}} %s)", r.Pipe, r.List)
+// WithNode represents a {{with}} action and its commands.
+type WithNode struct {
+ BranchNode
+}
+
+func newWith(line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
+ return &WithNode{BranchNode{NodeType: NodeWith, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
}
// TemplateNode represents a {{template}} action.
@@ -448,23 +462,3 @@ func (t *TemplateNode) String() string {
}
return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
}
-
-// WithNode represents a {{with}} action and its commands.
-type WithNode struct {
- NodeType
- Line int // The line number in the input.
- Pipe *PipeNode // The pipeline to be evaluated.
- List *ListNode // What to execute if the value is non-empty.
- ElseList *ListNode // What to execute if the value is empty (nil if absent).
-}
-
-func newWith(line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
- return &WithNode{NodeType: NodeWith, Line: line, Pipe: pipe, List: list, ElseList: elseList}
-}
-
-func (w *WithNode) String() string {
- if w.ElseList != nil {
- return fmt.Sprintf("({{with %s}} %s {{else}} %s)", w.Pipe, w.List, w.ElseList)
- }
- return fmt.Sprintf("({{with %s}} %s)", w.Pipe, w.List)
-}
diff --git a/libgo/go/template/parse/parse.go b/libgo/go/template/parse/parse.go
index 6918074664e..9934d8221db 100644
--- a/libgo/go/template/parse/parse.go
+++ b/libgo/go/template/parse/parse.go
@@ -145,10 +145,11 @@ func (t *Tree) atEOF() bool {
}
// Parse parses the template definition string to construct an internal
-// representation of the template for execution.
-func (t *Tree) Parse(s string, funcs ...map[string]interface{}) (tree *Tree, err os.Error) {
+// representation of the template for execution. If either action delimiter
+// string is empty, the default ("{{" or "}}") is used.
+func (t *Tree) Parse(s, leftDelim, rightDelim string, funcs ...map[string]interface{}) (tree *Tree, err os.Error) {
defer t.recover(&err)
- t.startParse(funcs, lex(t.Name, s))
+ t.startParse(funcs, lex(t.Name, s, leftDelim, rightDelim))
t.parse(true)
t.stopParse()
return t, nil
diff --git a/libgo/go/template/parse/parse_test.go b/libgo/go/template/parse/parse_test.go
index 1928c319dec..f05f6e3874c 100644
--- a/libgo/go/template/parse/parse_test.go
+++ b/libgo/go/template/parse/parse_test.go
@@ -236,7 +236,7 @@ var builtins = map[string]interface{}{
func TestParse(t *testing.T) {
for _, test := range parseTests {
- tmpl, err := New(test.name).Parse(test.input, builtins)
+ tmpl, err := New(test.name).Parse(test.input, "", "", builtins)
switch {
case err == nil && !test.ok:
t.Errorf("%q: expected error; got none", test.name)
diff --git a/libgo/go/template/parse/set.go b/libgo/go/template/parse/set.go
index dca41ea76cd..b909f71cd76 100644
--- a/libgo/go/template/parse/set.go
+++ b/libgo/go/template/parse/set.go
@@ -13,10 +13,10 @@ import (
// Set returns a slice of Trees created by parsing the template set
// definition in the argument string. If an error is encountered,
// parsing stops and an empty slice is returned with the error.
-func Set(text string, funcs ...map[string]interface{}) (tree map[string]*Tree, err os.Error) {
+func Set(text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (tree map[string]*Tree, err os.Error) {
tree = make(map[string]*Tree)
defer (*Tree)(nil).recover(&err)
- lex := lex("set", text)
+ lex := lex("set", text, leftDelim, rightDelim)
const context = "define clause"
for {
t := New("set") // name will be updated once we know it.
diff --git a/libgo/go/template/set.go b/libgo/go/template/set.go
index f778fd1693f..712961b7314 100644
--- a/libgo/go/template/set.go
+++ b/libgo/go/template/set.go
@@ -17,6 +17,8 @@ import (
// A template may be a member of multiple sets.
type Set struct {
tmpl map[string]*Template
+ leftDelim string
+ rightDelim string
parseFuncs FuncMap
execFuncs map[string]reflect.Value
}
@@ -29,6 +31,16 @@ func (s *Set) init() {
}
}
+// Delims sets the action delimiters, to be used in a subsequent
+// parse, to the specified strings.
+// An empty delimiter stands for the corresponding default: {{ or }}.
+// The return value is the set, so calls can be chained.
+func (s *Set) Delims(left, right string) *Set {
+ s.leftDelim = left
+ s.rightDelim = right
+ return s
+}
+
// Funcs adds the elements of the argument map to the set's function map. It
// panics if a value in the map is not a function with appropriate return
// type.
@@ -93,7 +105,7 @@ func (s *Set) Execute(wr io.Writer, name string, data interface{}) os.Error {
// to the set. If a template is redefined, the element in the set is
// overwritten with the new definition.
func (s *Set) Parse(text string) (*Set, os.Error) {
- trees, err := parse.Set(text, s.parseFuncs, builtins)
+ trees, err := parse.Set(text, s.leftDelim, s.rightDelim, s.parseFuncs, builtins)
if err != nil {
return nil, err
}
diff --git a/libgo/go/testing/example.go b/libgo/go/testing/example.go
new file mode 100644
index 00000000000..f148951d4fe
--- /dev/null
+++ b/libgo/go/testing/example.go
@@ -0,0 +1,84 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package testing
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os"
+ "time"
+)
+
+type InternalExample struct {
+ Name string
+ F func()
+ Output string
+}
+
+func RunExamples(examples []InternalExample) (ok bool) {
+ ok = true
+
+ stdout, stderr := os.Stdout, os.Stderr
+ defer func() {
+ os.Stdout, os.Stderr = stdout, stderr
+ if e := recover(); e != nil {
+ if err, ok := e.(os.Error); ok {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ panic(e)
+ }
+ }()
+
+ for _, eg := range examples {
+ if *chatty {
+ fmt.Fprintln(os.Stderr, "=== RUN:", eg.Name)
+ }
+
+ // capture stdout and stderr for testing purposes
+ r, w, err := os.Pipe()
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ os.Stdout, os.Stderr = w, w
+ outC := make(chan string)
+ go func() {
+ buf := new(bytes.Buffer)
+ _, err := io.Copy(buf, r)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+ outC <- buf.String()
+ }()
+
+ // run example
+ ns := -time.Nanoseconds()
+ eg.F()
+ ns += time.Nanoseconds()
+
+ // close pipe, restore stdout/stderr, get output
+ w.Close()
+ os.Stdout, os.Stderr = stdout, stderr
+ out := <-outC
+
+ // report any errors
+ if out != eg.Output {
+ fmt.Fprintf(
+ os.Stderr,
+ "--- FAIL: %s\ngot:\n%s\nwant:\n%s\n",
+ eg.Name, out, eg.Output,
+ )
+ ok = false
+ } else if *chatty {
+ tstr := fmt.Sprintf("(%.2f seconds)", float64(ns)/1e9)
+ fmt.Fprintln(os.Stderr, "--- PASS:", eg.Name, tstr)
+ }
+ }
+
+ return
+}
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index ec4a4537176..a555cb4a156 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -44,8 +44,8 @@ import (
"os"
"runtime"
"runtime/pprof"
- "strings"
"strconv"
+ "strings"
"time"
)
@@ -65,6 +65,7 @@ var (
cpuProfile = flag.String("test.cpuprofile", "", "write a cpu profile to the named file during execution")
timeout = flag.Int64("test.timeout", 0, "if > 0, sets time limit for tests in seconds")
cpuListStr = flag.String("test.cpu", "", "comma-separated list of number of CPUs to use for each test")
+ parallel = flag.Int("test.parallel", runtime.GOMAXPROCS(0), "maximum test parallelism")
cpuList []int
)
@@ -92,9 +93,12 @@ func tabify(s string) string {
// T is a type passed to Test functions to manage test state and support formatted test logs.
// Logs are accumulated during execution and dumped to standard error when done.
type T struct {
- errors string
- failed bool
- ch chan *T
+ name string // Name of test.
+ errors string // Error string from test.
+ failed bool // Test has failed.
+ ch chan *T // Output for serial tests.
+ startParallel chan bool // Parallel tests will wait on this.
+ ns int64 // Duration of test in nanoseconds.
}
// Fail marks the Test function as having failed but continues execution.
@@ -106,6 +110,7 @@ func (t *T) Failed() bool { return t.failed }
// FailNow marks the Test function as having failed and stops its execution.
// Execution will continue at the next Test.
func (t *T) FailNow() {
+ t.ns = time.Nanoseconds() - t.ns
t.Fail()
t.ch <- t
runtime.Goexit()
@@ -145,6 +150,13 @@ func (t *T) Fatalf(format string, args ...interface{}) {
t.FailNow()
}
+// Parallel signals that this test is to be run in parallel with (and only with)
+// other parallel tests in this CPU group.
+func (t *T) Parallel() {
+ t.ch <- nil // Release main testing loop
+ <-t.startParallel // Wait for serial tests to finish
+}
+
// An internal type but exported because it is cross-package; part of the implementation
// of gotest.
type InternalTest struct {
@@ -153,73 +165,97 @@ type InternalTest struct {
}
func tRunner(t *T, test *InternalTest) {
+ t.ns = time.Nanoseconds()
test.F(t)
+ t.ns = time.Nanoseconds() - t.ns
t.ch <- t
}
// An internal function but exported because it is cross-package; part of the implementation
// of gotest.
-func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest, benchmarks []InternalBenchmark) {
+func Main(matchString func(pat, str string) (bool, os.Error), tests []InternalTest, benchmarks []InternalBenchmark, examples []InternalExample) {
flag.Parse()
parseCpuList()
before()
startAlarm()
- RunTests(matchString, tests)
+ testOk := RunTests(matchString, tests)
+ exampleOk := RunExamples(examples)
+ if !testOk || !exampleOk {
+ fmt.Fprintln(os.Stderr, "FAIL")
+ os.Exit(1)
+ }
+ fmt.Fprintln(os.Stderr, "PASS")
stopAlarm()
RunBenchmarks(matchString, benchmarks)
after()
}
-func RunTests(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) {
- ok := true
+func report(t *T) {
+ tstr := fmt.Sprintf("(%.2f seconds)", float64(t.ns)/1e9)
+ format := "--- %s: %s %s\n%s"
+ if t.failed {
+ fmt.Fprintf(os.Stderr, format, "FAIL", t.name, tstr, t.errors)
+ } else if *chatty {
+ fmt.Fprintf(os.Stderr, format, "PASS", t.name, tstr, t.errors)
+ }
+}
+
+func RunTests(matchString func(pat, str string) (bool, os.Error), tests []InternalTest) (ok bool) {
+ ok = true
if len(tests) == 0 {
- println("testing: warning: no tests to run")
+ fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
+ return
}
- for i := 0; i < len(tests); i++ {
- matched, err := matchString(*match, tests[i].Name)
- if err != nil {
- println("invalid regexp for -test.run:", err.String())
- os.Exit(1)
- }
- if !matched {
- continue
- }
- for _, procs := range cpuList {
- runtime.GOMAXPROCS(procs)
+ ch := make(chan *T)
+ for _, procs := range cpuList {
+ runtime.GOMAXPROCS(procs)
+
+ numParallel := 0
+ startParallel := make(chan bool)
+
+ for i := 0; i < len(tests); i++ {
+ matched, err := matchString(*match, tests[i].Name)
+ if err != nil {
+ println("invalid regexp for -test.run:", err.String())
+ os.Exit(1)
+ }
+ if !matched {
+ continue
+ }
testName := tests[i].Name
if procs != 1 {
testName = fmt.Sprintf("%s-%d", tests[i].Name, procs)
}
+ t := &T{ch: ch, name: testName, startParallel: startParallel}
if *chatty {
- println("=== RUN ", testName)
+ println("=== RUN", t.name)
}
- ns := -time.Nanoseconds()
- t := new(T)
- t.ch = make(chan *T)
go tRunner(t, &tests[i])
- <-t.ch
- ns += time.Nanoseconds()
- tstr := fmt.Sprintf("(%.2f seconds)", float64(ns)/1e9)
- if p := runtime.GOMAXPROCS(-1); t.failed == false && p != procs {
- t.failed = true
- t.errors = fmt.Sprintf("%s left GOMAXPROCS set to %d\n", testName, p)
+ out := <-t.ch
+ if out == nil { // Parallel run.
+ numParallel++
+ continue
}
- if t.failed {
- println("--- FAIL:", testName, tstr)
- print(t.errors)
- ok = false
- } else if *chatty {
- println("--- PASS:", testName, tstr)
- print(t.errors)
+ report(t)
+ ok = ok && !out.failed
+ }
+
+ running := 0
+ for numParallel+running > 0 {
+ if running < *parallel && numParallel > 0 {
+ startParallel <- true
+ running++
+ numParallel--
+ continue
}
+ t := <-ch
+ report(t)
+ ok = ok && !t.failed
+ running--
}
}
- if !ok {
- println("FAIL")
- os.Exit(1)
- }
- println("PASS")
+ return
}
// before runs before all testing.
diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go
index 5ddd54812f3..50e96a5c259 100644
--- a/libgo/go/time/format.go
+++ b/libgo/go/time/format.go
@@ -232,9 +232,27 @@ var longMonthNames = []string{
"December",
}
+// match returns true if s1 and s2 match ignoring case.
+// It is assumed s1 and s2 are the same length.
+func match(s1, s2 string) bool {
+ for i := 0; i < len(s1); i++ {
+ c1 := s1[i]
+ c2 := s2[i]
+ if c1 != c2 {
+ // Switch to lower-case; 'a'-'A' is known to be a single bit.
+ c1 |= 'a' - 'A'
+ c2 |= 'a' - 'A'
+ if c1 != c2 || c1 < 'a' || c1 > 'z' {
+ return false
+ }
+ }
+ }
+ return true
+}
+
func lookup(tab []string, val string) (int, string, os.Error) {
for i, v := range tab {
- if len(val) >= len(v) && val[0:len(v)] == v {
+ if len(val) >= len(v) && match(val[0:len(v)], v) {
return i, val[len(v):], nil
}
}
@@ -296,9 +314,9 @@ func (t *Time) Format(layout string) string {
case stdZeroMonth:
p = zeroPad(t.Month)
case stdWeekDay:
- p = shortDayNames[t.Weekday]
+ p = shortDayNames[t.Weekday()]
case stdLongWeekDay:
- p = longDayNames[t.Weekday]
+ p = longDayNames[t.Weekday()]
case stdDay:
p = strconv.Itoa(t.Day)
case stdUnderDay:
@@ -485,7 +503,8 @@ func skip(value, prefix string) (string, os.Error) {
// (such as having the wrong day of the week), the returned value will also
// be inconsistent. In any case, the elements of the returned time will be
// sane: hours in 0..23, minutes in 0..59, day of month in 1..31, etc.
-// Years must be in the range 0000..9999.
+// Years must be in the range 0000..9999. The day of the week is checked
+// for syntax but it is otherwise ignored.
func Parse(alayout, avalue string) (*Time, os.Error) {
var t Time
rangeErrString := "" // set if a value is out of range
@@ -538,9 +557,10 @@ func Parse(alayout, avalue string) (*Time, os.Error) {
rangeErrString = "month"
}
case stdWeekDay:
- t.Weekday, value, err = lookup(shortDayNames, value)
+ // Ignore weekday except for error checking.
+ _, value, err = lookup(shortDayNames, value)
case stdLongWeekDay:
- t.Weekday, value, err = lookup(longDayNames, value)
+ _, value, err = lookup(longDayNames, value)
case stdDay, stdUnderDay, stdZeroDay:
if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
value = value[1:]
diff --git a/libgo/go/time/internal_test.go b/libgo/go/time/internal_test.go
new file mode 100644
index 00000000000..d7e7076539f
--- /dev/null
+++ b/libgo/go/time/internal_test.go
@@ -0,0 +1,12 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package time
+
+func init() {
+ // force US/Pacific for time zone tests
+ onceSetupZone.Do(setupTestingZone)
+}
+
+var Interrupt = interrupt
diff --git a/libgo/go/time/sleep_test.go b/libgo/go/time/sleep_test.go
index 9b59767af3d..9d16c52ff52 100644
--- a/libgo/go/time/sleep_test.go
+++ b/libgo/go/time/sleep_test.go
@@ -7,7 +7,6 @@ package time_test
import (
"fmt"
"os"
- "syscall"
"testing"
"sort"
. "time"
@@ -17,7 +16,7 @@ func TestSleep(t *testing.T) {
const delay = int64(100e6)
go func() {
Sleep(delay / 2)
- syscall.Kill(os.Getpid(), syscall.SIGCHLD)
+ Interrupt()
}()
start := Nanoseconds()
Sleep(delay)
diff --git a/libgo/go/time/sys_plan9.go b/libgo/go/time/sys_plan9.go
index abe8649a24b..9ae0161ba84 100644
--- a/libgo/go/time/sys_plan9.go
+++ b/libgo/go/time/sys_plan9.go
@@ -16,3 +16,8 @@ func sysSleep(t int64) os.Error {
}
return nil
}
+
+// for testing: whatever interrupts a sleep
+func interrupt() {
+ // cannot predict pid, don't want to kill group
+}
diff --git a/libgo/go/time/sys_posix.go b/libgo/go/time/sys_posix.go
deleted file mode 100644
index 0d1eb72fcf5..00000000000
--- a/libgo/go/time/sys_posix.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package time
-
-import (
- "os"
- "syscall"
-)
-
-func sysSleep(t int64) os.Error {
- errno := syscall.Sleep(t)
- if errno != 0 && errno != syscall.EINTR {
- return os.NewSyscallError("sleep", errno)
- }
- return nil
-}
diff --git a/libgo/go/time/sys_unix.go b/libgo/go/time/sys_unix.go
new file mode 100644
index 00000000000..0119bdf7bf9
--- /dev/null
+++ b/libgo/go/time/sys_unix.go
@@ -0,0 +1,25 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin freebsd linux openbsd
+
+package time
+
+import (
+ "os"
+ "syscall"
+)
+
+func sysSleep(t int64) os.Error {
+ errno := syscall.Sleep(t)
+ if errno != 0 && errno != syscall.EINTR {
+ return os.NewSyscallError("sleep", errno)
+ }
+ return nil
+}
+
+// for testing: whatever interrupts a sleep
+func interrupt() {
+ syscall.Kill(os.Getpid(), syscall.SIGCHLD)
+}
diff --git a/libgo/go/time/sys_windows.go b/libgo/go/time/sys_windows.go
new file mode 100644
index 00000000000..feff90b8b09
--- /dev/null
+++ b/libgo/go/time/sys_windows.go
@@ -0,0 +1,22 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package time
+
+import (
+ "os"
+ "syscall"
+)
+
+func sysSleep(t int64) os.Error {
+ errno := syscall.Sleep(t)
+ if errno != 0 && errno != syscall.EINTR {
+ return os.NewSyscallError("sleep", errno)
+ }
+ return nil
+}
+
+// for testing: whatever interrupts a sleep
+func interrupt() {
+}
diff --git a/libgo/go/time/time.go b/libgo/go/time/time.go
index 0e05da48447..859b3167278 100644
--- a/libgo/go/time/time.go
+++ b/libgo/go/time/time.go
@@ -22,7 +22,6 @@ type Time struct {
Month, Day int // Jan-2 is 1, 2
Hour, Minute, Second int // 15:04:05 is 15, 4, 5.
Nanosecond int // Fractional second.
- Weekday int // Sunday, Monday, ...
ZoneOffset int // seconds east of UTC, e.g. -7*60*60 for -0700
Zone string // e.g., "MST"
}
@@ -63,12 +62,6 @@ func SecondsToUTC(sec int64) *Time {
t.Minute = int((sec / 60) % 60)
t.Second = int(sec % 60)
- // Day 0 = January 1, 1970 was a Thursday
- t.Weekday = int((day + Thursday) % 7)
- if t.Weekday < 0 {
- t.Weekday += 7
- }
-
// Change day from 0 = 1970 to 0 = 2001,
// to make leap year calculations easier
// (2001 begins 4-, 100-, and 400-year cycles ending in a leap year.)
@@ -228,3 +221,19 @@ func (t *Time) Seconds() int64 {
func (t *Time) Nanoseconds() int64 {
return t.Seconds()*1e9 + int64(t.Nanosecond)
}
+
+// Weekday returns the time's day of the week. Sunday is day 0.
+func (t *Time) Weekday() int {
+ sec := t.Seconds() + int64(t.ZoneOffset)
+ day := sec / secondsPerDay
+ sec -= day * secondsPerDay
+ if sec < 0 {
+ day--
+ }
+ // Day 0 = January 1, 1970 was a Thursday
+ weekday := int((day + Thursday) % 7)
+ if weekday < 0 {
+ weekday += 7
+ }
+ return weekday
+}
diff --git a/libgo/go/time/time_test.go b/libgo/go/time/time_test.go
index dceed491aa0..353976c9693 100644
--- a/libgo/go/time/time_test.go
+++ b/libgo/go/time/time_test.go
@@ -5,7 +5,6 @@
package time_test
import (
- "os"
"strconv"
"strings"
"testing"
@@ -13,13 +12,6 @@ import (
. "time"
)
-func init() {
- // Force US Pacific time for daylight-savings
- // tests below (localtests). Needs to be set
- // before the first call into the time library.
- os.Setenv("TZ", "America/Los_Angeles")
-}
-
// We should be in PST/PDT, but if the time zone files are missing we
// won't be. The purpose of this test is to at least explain why some of
// the subsequent tests fail.
@@ -38,31 +30,31 @@ type TimeTest struct {
}
var utctests = []TimeTest{
- {0, Time{1970, 1, 1, 0, 0, 0, 0, Thursday, 0, "UTC"}},
- {1221681866, Time{2008, 9, 17, 20, 4, 26, 0, Wednesday, 0, "UTC"}},
- {-1221681866, Time{1931, 4, 16, 3, 55, 34, 0, Thursday, 0, "UTC"}},
- {-11644473600, Time{1601, 1, 1, 0, 0, 0, 0, Monday, 0, "UTC"}},
- {599529660, Time{1988, 12, 31, 0, 1, 0, 0, Saturday, 0, "UTC"}},
- {978220860, Time{2000, 12, 31, 0, 1, 0, 0, Sunday, 0, "UTC"}},
- {1e18, Time{31688740476, 10, 23, 1, 46, 40, 0, Friday, 0, "UTC"}},
- {-1e18, Time{-31688736537, 3, 10, 22, 13, 20, 0, Tuesday, 0, "UTC"}},
- {0x7fffffffffffffff, Time{292277026596, 12, 4, 15, 30, 7, 0, Sunday, 0, "UTC"}},
- {-0x8000000000000000, Time{-292277022657, 1, 27, 8, 29, 52, 0, Sunday, 0, "UTC"}},
+ {0, Time{1970, 1, 1, 0, 0, 0, 0, 0, "UTC"}},
+ {1221681866, Time{2008, 9, 17, 20, 4, 26, 0, 0, "UTC"}},
+ {-1221681866, Time{1931, 4, 16, 3, 55, 34, 0, 0, "UTC"}},
+ {-11644473600, Time{1601, 1, 1, 0, 0, 0, 0, 0, "UTC"}},
+ {599529660, Time{1988, 12, 31, 0, 1, 0, 0, 0, "UTC"}},
+ {978220860, Time{2000, 12, 31, 0, 1, 0, 0, 0, "UTC"}},
+ {1e18, Time{31688740476, 10, 23, 1, 46, 40, 0, 0, "UTC"}},
+ {-1e18, Time{-31688736537, 3, 10, 22, 13, 20, 0, 0, "UTC"}},
+ {0x7fffffffffffffff, Time{292277026596, 12, 4, 15, 30, 7, 0, 0, "UTC"}},
+ {-0x8000000000000000, Time{-292277022657, 1, 27, 8, 29, 52, 0, 0, "UTC"}},
}
var nanoutctests = []TimeTest{
- {0, Time{1970, 1, 1, 0, 0, 0, 1e8, Thursday, 0, "UTC"}},
- {1221681866, Time{2008, 9, 17, 20, 4, 26, 2e8, Wednesday, 0, "UTC"}},
+ {0, Time{1970, 1, 1, 0, 0, 0, 1e8, 0, "UTC"}},
+ {1221681866, Time{2008, 9, 17, 20, 4, 26, 2e8, 0, "UTC"}},
}
var localtests = []TimeTest{
- {0, Time{1969, 12, 31, 16, 0, 0, 0, Wednesday, -8 * 60 * 60, "PST"}},
- {1221681866, Time{2008, 9, 17, 13, 4, 26, 0, Wednesday, -7 * 60 * 60, "PDT"}},
+ {0, Time{1969, 12, 31, 16, 0, 0, 0, -8 * 60 * 60, "PST"}},
+ {1221681866, Time{2008, 9, 17, 13, 4, 26, 0, -7 * 60 * 60, "PDT"}},
}
var nanolocaltests = []TimeTest{
- {0, Time{1969, 12, 31, 16, 0, 0, 1e8, Wednesday, -8 * 60 * 60, "PST"}},
- {1221681866, Time{2008, 9, 17, 13, 4, 26, 3e8, Wednesday, -7 * 60 * 60, "PDT"}},
+ {0, Time{1969, 12, 31, 16, 0, 0, 1e8, -8 * 60 * 60, "PST"}},
+ {1221681866, Time{2008, 9, 17, 13, 4, 26, 3e8, -7 * 60 * 60, "PDT"}},
}
func same(t, u *Time) bool {
@@ -73,7 +65,7 @@ func same(t, u *Time) bool {
t.Minute == u.Minute &&
t.Second == u.Second &&
t.Nanosecond == u.Nanosecond &&
- t.Weekday == u.Weekday &&
+ t.Weekday() == u.Weekday() &&
t.ZoneOffset == u.ZoneOffset &&
t.Zone == u.Zone
}
@@ -181,9 +173,9 @@ type TimeFormatTest struct {
}
var rfc3339Formats = []TimeFormatTest{
- {Time{2008, 9, 17, 20, 4, 26, 0, Wednesday, 0, "UTC"}, "2008-09-17T20:04:26Z"},
- {Time{1994, 9, 17, 20, 4, 26, 0, Wednesday, -18000, "EST"}, "1994-09-17T20:04:26-05:00"},
- {Time{2000, 12, 26, 1, 15, 6, 0, Wednesday, 15600, "OTO"}, "2000-12-26T01:15:06+04:20"},
+ {Time{2008, 9, 17, 20, 4, 26, 0, 0, "UTC"}, "2008-09-17T20:04:26Z"},
+ {Time{1994, 9, 17, 20, 4, 26, 0, -18000, "EST"}, "1994-09-17T20:04:26-05:00"},
+ {Time{2000, 12, 26, 1, 15, 6, 0, 15600, "OTO"}, "2000-12-26T01:15:06+04:20"},
}
func TestRFC3339Conversion(t *testing.T) {
@@ -260,6 +252,9 @@ var parseTests = []ParseTest{
// Amount of white space should not matter.
{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
{"ANSIC", ANSIC, "Thu Feb 4 21:00:57 2010", false, true, 1, 0},
+ // Case should not matter
+ {"ANSIC", ANSIC, "THU FEB 4 21:00:57 2010", false, true, 1, 0},
+ {"ANSIC", ANSIC, "thu feb 4 21:00:57 2010", false, true, 1, 0},
// Fractional seconds.
{"millisecond", "Mon Jan _2 15:04:05.000 2006", "Thu Feb 4 21:00:57.012 2010", false, true, 1, 3},
{"microsecond", "Mon Jan _2 15:04:05.000000 2006", "Thu Feb 4 21:00:57.012345 2010", false, true, 1, 6},
@@ -331,8 +326,8 @@ func checkTime(time *Time, test *ParseTest, t *testing.T) {
if test.hasTZ && time.ZoneOffset != -28800 {
t.Errorf("%s: bad tz offset: %d not %d", test.name, time.ZoneOffset, -28800)
}
- if test.hasWD && time.Weekday != 4 {
- t.Errorf("%s: bad weekday: %d not %d", test.name, time.Weekday, 4)
+ if test.hasWD && time.Weekday() != 4 {
+ t.Errorf("%s: bad weekday: %d not %d", test.name, time.Weekday(), 4)
}
}
@@ -458,11 +453,11 @@ func Test12AMIsMidnight(t *testing.T) {
// Check that a time without a Zone still produces a (numeric) time zone
// when formatted with MST as a requested zone.
func TestMissingZone(t *testing.T) {
- time, err := Parse(RubyDate, "Tue Feb 02 16:10:03 -0500 2006")
+ time, err := Parse(RubyDate, "Thu Feb 02 16:10:03 -0500 2006")
if err != nil {
t.Fatal("error parsing date:", err)
}
- expect := "Tue Feb 2 16:10:03 -0500 2006" // -0500 not EST
+ expect := "Thu Feb 2 16:10:03 -0500 2006" // -0500 not EST
str := time.Format(UnixDate) // uses MST as its time zone
if str != expect {
t.Errorf("expected %q got %q", expect, str)
diff --git a/libgo/go/time/zoneinfo_plan9.go b/libgo/go/time/zoneinfo_plan9.go
index 3c3e7c42446..577ef85bd68 100644
--- a/libgo/go/time/zoneinfo_plan9.go
+++ b/libgo/go/time/zoneinfo_plan9.go
@@ -57,3 +57,19 @@ func setupZone() {
}
zones = parseZones(t)
}
+
+func setupTestingZone() {
+ f, err := os.Open("/adm/timezone/US_Pacific")
+ if err != nil {
+ return
+ }
+ defer f.Close()
+ l, _ := f.Seek(0, 2)
+ f.Seek(0, 0)
+ buf := make([]byte, l)
+ _, err = f.Read(buf)
+ if err != nil {
+ return
+ }
+ zones = parseZones(string(buf))
+}
diff --git a/libgo/go/time/zoneinfo_posix.go b/libgo/go/time/zoneinfo_posix.go
index b49216410ff..b0fa6c33b65 100644
--- a/libgo/go/time/zoneinfo_posix.go
+++ b/libgo/go/time/zoneinfo_posix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd plan9
+
package time
import "sync"
diff --git a/libgo/go/time/zoneinfo_unix.go b/libgo/go/time/zoneinfo_unix.go
index f3ea7b6fdab..0dc42353136 100644
--- a/libgo/go/time/zoneinfo_unix.go
+++ b/libgo/go/time/zoneinfo_unix.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// +build darwin freebsd linux openbsd
+
// Parse "zoneinfo" time zone file.
// This is a fairly standard file format used on OS X, Linux, BSD, Sun, and others.
// See tzfile(5), http://en.wikipedia.org/wiki/Zoneinfo,
@@ -185,6 +187,11 @@ func readinfofile(name string) ([]zonetime, bool) {
return parseinfo(buf)
}
+func setupTestingZone() {
+ os.Setenv("TZ", "America/Los_Angeles")
+ setupZone()
+}
+
func setupZone() {
// consult $TZ to find the time zone to use.
// no $TZ means use the system default /etc/localtime.
diff --git a/libgo/go/time/zoneinfo_windows.go b/libgo/go/time/zoneinfo_windows.go
index fabc0060110..41c48192dd8 100644
--- a/libgo/go/time/zoneinfo_windows.go
+++ b/libgo/go/time/zoneinfo_windows.go
@@ -27,9 +27,30 @@ type zone struct {
prev *zone
}
+// BUG(rsc): On Windows, time zone abbreviations are unavailable.
+// This package constructs them using the capital letters from a longer
+// time zone description.
+
// Populate zone struct with Windows supplied information. Returns true, if data is valid.
func (z *zone) populate(bias, biasdelta int32, d *syscall.Systemtime, name []uint16) (dateisgood bool) {
- z.name = syscall.UTF16ToString(name)
+ // name is 'Pacific Standard Time' but we want 'PST'.
+ // Extract just capital letters. It's not perfect but the
+ // information we need is not available from the kernel.
+ // Because time zone abbreviations are not unique,
+ // Windows refuses to expose them.
+ //
+ // http://social.msdn.microsoft.com/Forums/eu/vclanguage/thread/a87e1d25-fb71-4fe0-ae9c-a9578c9753eb
+ // http://stackoverflow.com/questions/4195948/windows-time-zone-abbreviations-in-asp-net
+ short := make([]uint16, len(name))
+ w := 0
+ for _, c := range name {
+ if 'A' <= c && c <= 'Z' {
+ short[w] = c
+ w++
+ }
+ }
+ z.name = syscall.UTF16ToString(short[:w])
+
z.offset = int(bias)
z.year = int64(d.Year)
z.month = int(d.Month)
@@ -49,7 +70,15 @@ func (z *zone) populate(bias, biasdelta int32, d *syscall.Systemtime, name []uin
// Pre-calculate cutoff time in seconds since the Unix epoch, if data is supplied in "absolute" format.
func (z *zone) preCalculateAbsSec() {
if z.year != 0 {
- z.abssec = (&Time{z.year, int(z.month), int(z.day), int(z.hour), int(z.minute), int(z.second), 0, 0, 0, ""}).Seconds()
+ t := &Time{
+ Year: z.year,
+ Month: int(z.month),
+ Day: int(z.day),
+ Hour: int(z.hour),
+ Minute: int(z.minute),
+ Second: int(z.second),
+ }
+ z.abssec = t.Seconds()
// Time given is in "local" time. Adjust it for "utc".
z.abssec -= int64(z.prev.offset)
}
@@ -62,9 +91,16 @@ func (z *zone) cutoffSeconds(year int64) int64 {
// z.dayofweek is appropriate weekday (Sunday=0 to Saturday=6)
// z.day is week within the month (1 to 5, where 5 is last week of the month)
// z.hour, z.minute and z.second are absolute time
- t := &Time{year, int(z.month), 1, int(z.hour), int(z.minute), int(z.second), 0, 0, 0, ""}
+ t := &Time{
+ Year: year,
+ Month: int(z.month),
+ Day: 1,
+ Hour: int(z.hour),
+ Minute: int(z.minute),
+ Second: int(z.second),
+ }
t = SecondsToUTC(t.Seconds())
- i := int(z.dayofweek) - t.Weekday
+ i := int(z.dayofweek) - t.Weekday()
if i < 0 {
i += 7
}
@@ -129,6 +165,10 @@ func setupZone() {
initError = os.NewSyscallError("GetTimeZoneInformation", e)
return
}
+ setupZoneFromTZI(&i)
+}
+
+func setupZoneFromTZI(i *syscall.Timezoneinformation) {
if !tz.std.populate(i.Bias, i.StandardBias, &i.StandardDate, i.StandardName[0:]) {
tz.disabled = true
tz.offsetIfDisabled = tz.std.offset
@@ -144,6 +184,23 @@ func setupZone() {
tz.januaryIsStd = tz.dst.cutoffSeconds(t.Year) < tz.std.cutoffSeconds(t.Year)
}
+var usPacific = syscall.Timezoneinformation{
+ Bias: 8 * 60,
+ StandardName: [32]uint16{
+ 'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'S', 't', 'a', 'n', 'd', 'a', 'r', 'd', ' ', 'T', 'i', 'm', 'e',
+ },
+ StandardDate: syscall.Systemtime{Month: 11, Day: 1, Hour: 2},
+ DaylightName: [32]uint16{
+ 'P', 'a', 'c', 'i', 'f', 'i', 'c', ' ', 'D', 'a', 'y', 'l', 'i', 'g', 'h', 't', ' ', 'T', 'i', 'm', 'e',
+ },
+ DaylightDate: syscall.Systemtime{Month: 3, Day: 2, Hour: 2},
+ DaylightBias: -60,
+}
+
+func setupTestingZone() {
+ setupZoneFromTZI(&usPacific)
+}
+
// Look up the correct time zone (daylight savings or not) for the given unix time, in the current location.
func lookupTimezone(sec int64) (zone string, offset int) {
onceSetupZone.Do(setupZone)
diff --git a/libgo/go/try/try.go b/libgo/go/try/try.go
deleted file mode 100644
index 2a3dbf9870e..00000000000
--- a/libgo/go/try/try.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package try contains the executable part of the gotry command.
-// It is not intended for general use.
-package try
-
-import (
- "fmt"
- "io"
- "os"
- "reflect"
- "unicode"
-)
-
-var output io.Writer = os.Stdout // redirected when testing
-
-// Main is called directly from the gotry-generated Go source file to perform
-// the evaluations.
-func Main(pkg, firstArg string, functions map[string]interface{}, args []interface{}) {
- switch len(args) {
- case 0:
- // Nothing to do.
- case 1:
- // Compiler has already evaluated the expression; just print the result.
- printSlice(firstArg, args)
- default:
- // See if methods satisfy the expressions.
- tryMethods(pkg, firstArg, args)
- // See if functions satisfy the expressions.
- for name, fn := range functions {
- tryFunction(pkg, name, fn, args)
- }
- }
-}
-
-// printSlice prints the zeroth element of the args slice, which should (by construction)
-// itself be a slice of interface{}.
-func printSlice(firstArg string, args []interface{}) {
- // Args should be length 1 and a slice.
- if len(args) != 1 {
- return
- }
- arg, ok := args[0].([]interface{})
- if !ok {
- return
- }
- fmt.Fprintf(output, "%s = ", firstArg)
- if len(arg) > 1 {
- fmt.Fprint(output, "(")
- }
- for i, a := range arg {
- if i > 0 {
- fmt.Fprint(output, ", ")
- }
- fmt.Fprintf(output, "%#v", a)
- }
- if len(arg) > 1 {
- fmt.Fprint(output, ")")
- }
- fmt.Fprint(output, "\n")
-}
-
-// tryMethods sees if the zeroth arg has methods, and if so treats them as potential
-// functions to satisfy the remaining arguments.
-func tryMethods(pkg, firstArg string, args []interface{}) {
- defer func() { recover() }()
- // Is the first argument something with methods?
- v := reflect.ValueOf(args[0])
- typ := v.Type()
- if typ.NumMethod() == 0 {
- return
- }
- for i := 0; i < typ.NumMethod(); i++ {
- if unicode.IsUpper(int(typ.Method(i).Name[0])) {
- tryMethod(pkg, firstArg, typ.Method(i), args)
- }
- }
-}
-
-// tryMethod converts a method to a function for tryOneFunction.
-func tryMethod(pkg, firstArg string, method reflect.Method, args []interface{}) {
- rfn := method.Func
- typ := method.Type
- name := method.Name
- tryOneFunction(pkg, firstArg, name, typ, rfn, args)
-}
-
-// tryFunction sees if fn satisfies the arguments.
-func tryFunction(pkg, name string, fn interface{}, args []interface{}) {
- defer func() { recover() }()
- rfn := reflect.ValueOf(fn)
- typ := rfn.Type()
- tryOneFunction(pkg, "", name, typ, rfn, args)
-}
-
-// tryOneFunction is the common code for tryMethod and tryFunction.
-func tryOneFunction(pkg, firstArg, name string, typ reflect.Type, rfn reflect.Value, args []interface{}) {
- // Any results?
- if typ.NumOut() == 0 {
- return // Nothing to do.
- }
- // Right number of arguments + results?
- if typ.NumIn()+typ.NumOut() != len(args) {
- return
- }
- // Right argument and result types?
- for i, a := range args {
- if i < typ.NumIn() {
- if !compatible(a, typ.In(i)) {
- return
- }
- } else {
- if !compatible(a, typ.Out(i-typ.NumIn())) {
- return
- }
- }
- }
- // Build the call args.
- argsVal := make([]reflect.Value, typ.NumIn()+typ.NumOut())
- for i, a := range args {
- argsVal[i] = reflect.ValueOf(a)
- }
- // Call the function and see if the results are as expected.
- resultVal := rfn.Call(argsVal[:typ.NumIn()])
- for i, v := range resultVal {
- if !reflect.DeepEqual(v.Interface(), args[i+typ.NumIn()]) {
- return
- }
- }
- // Present the result including a godoc command to get more information.
- firstIndex := 0
- if firstArg != "" {
- fmt.Fprintf(output, "%s.%s(", firstArg, name)
- firstIndex = 1
- } else {
- fmt.Fprintf(output, "%s.%s(", pkg, name)
- }
- for i := firstIndex; i < typ.NumIn(); i++ {
- if i > firstIndex {
- fmt.Fprint(output, ", ")
- }
- fmt.Fprintf(output, "%#v", args[i])
- }
- fmt.Fprint(output, ") = ")
- if typ.NumOut() > 1 {
- fmt.Fprint(output, "(")
- }
- for i := 0; i < typ.NumOut(); i++ {
- if i > 0 {
- fmt.Fprint(output, ", ")
- }
- fmt.Fprintf(output, "%#v", resultVal[i].Interface())
- }
- if typ.NumOut() > 1 {
- fmt.Fprint(output, ")")
- }
- fmt.Fprintf(output, " // godoc %s %s\n", pkg, name)
-}
-
-// compatible reports whether the argument is compatible with the type.
-func compatible(arg interface{}, typ reflect.Type) bool {
- if reflect.TypeOf(arg) == typ {
- return true
- }
- if arg == nil {
- // nil is OK if the type is an interface.
- if typ.Kind() == reflect.Interface {
- return true
- }
- }
- return false
-}
diff --git a/libgo/go/try/try_test.go b/libgo/go/try/try_test.go
deleted file mode 100644
index 617b2c7c3fd..00000000000
--- a/libgo/go/try/try_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package try
-
-import (
- "bytes"
- "regexp" // Used as the package to try.
- "testing"
-)
-
-// The global functions in package regexp at time of writing.
-// Doesn't need to be updated unless the entries in this list become invalid.
-var functions = map[string]interface{}{
- "Compile": regexp.Compile,
- "Match": regexp.Match,
- "MatchString": regexp.MatchString,
- "MustCompile": regexp.MustCompile,
- "QuoteMeta": regexp.QuoteMeta,
-}
-
-// A wraps arguments to make the test cases nicer to read.
-func A(args ...interface{}) []interface{} {
- return args
-}
-
-type Test struct {
- firstArg string // only needed if there is exactly one argument
- result string // minus final newline; might be just the godoc string
- args []interface{}
-}
-
-var testRE = regexp.MustCompile("a(.)(.)d")
-
-var tests = []Test{
- // A simple expression. The final value is a slice in case the expression is multivalue.
- {"3+4", "3+4 = 7", A([]interface{}{7})},
- // A search for a function.
- {"", "regexp QuoteMeta", A("([])", `\(\[\]\)`)},
- // A search for a function with multiple return values.
- {"", "regexp MatchString", A("abc", "xabcd", true, nil)},
- // Searches for methods.
- {"", "regexp MatchString", A(testRE, "xabcde", true)},
- {"", "regexp NumSubexp", A(testRE, 2)},
-}
-
-func TestAll(t *testing.T) {
- re := regexp.MustCompile(".*// godoc ")
- for _, test := range tests {
- b := new(bytes.Buffer)
- output = b
- Main("regexp", test.firstArg, functions, test.args)
- expect := test.result + "\n"
- got := re.ReplaceAllString(b.String(), "")
- if got != expect {
- t.Errorf("expected %q; got %q", expect, got)
- }
- }
-}
diff --git a/libgo/go/unicode/script_test.go b/libgo/go/unicode/script_test.go
index b37ad183615..dfd636d8399 100644
--- a/libgo/go/unicode/script_test.go
+++ b/libgo/go/unicode/script_test.go
@@ -206,7 +206,7 @@ func TestScripts(t *testing.T) {
if !Is(Scripts[test.script], test.rune) {
t.Errorf("IsScript(%U, %s) = false, want true", test.rune, test.script)
}
- notTested[test.script] = false, false
+ delete(notTested, test.script)
}
for _, test := range outTest {
if Is(Scripts[test.script], test.rune) {
@@ -230,7 +230,7 @@ func TestCategories(t *testing.T) {
if !Is(Categories[test.script], test.rune) {
t.Errorf("IsCategory(%U, %s) = false, want true", test.rune, test.script)
}
- notTested[test.script] = false, false
+ delete(notTested, test.script)
}
for k := range notTested {
t.Error("category not tested:", k)
@@ -249,7 +249,7 @@ func TestProperties(t *testing.T) {
if !Is(Properties[test.script], test.rune) {
t.Errorf("IsCategory(%U, %s) = false, want true", test.rune, test.script)
}
- notTested[test.script] = false, false
+ delete(notTested, test.script)
}
for k := range notTested {
t.Error("property not tested:", k)
diff --git a/libgo/go/url/url.go b/libgo/go/url/url.go
index d07b016118f..dd1f93d14c4 100644
--- a/libgo/go/url/url.go
+++ b/libgo/go/url/url.go
@@ -517,7 +517,7 @@ func (v Values) Add(key, value string) {
// Del deletes the values associated with key.
func (v Values) Del(key string) {
- v[key] = nil, false
+ delete(v, key)
}
// ParseQuery parses the URL-encoded query string and returns
@@ -532,20 +532,28 @@ func ParseQuery(query string) (m Values, err os.Error) {
}
func parseQuery(m Values, query string) (err os.Error) {
- for _, kv := range strings.Split(query, "&") {
- if len(kv) == 0 {
+ for query != "" {
+ key := query
+ if i := strings.IndexAny(key, "&;"); i >= 0 {
+ key, query = key[:i], key[i+1:]
+ } else {
+ query = ""
+ }
+ if key == "" {
continue
}
- kvPair := strings.SplitN(kv, "=", 2)
-
- var key, value string
- var e os.Error
- key, e = QueryUnescape(kvPair[0])
- if e == nil && len(kvPair) > 1 {
- value, e = QueryUnescape(kvPair[1])
+ value := ""
+ if i := strings.Index(key, "="); i >= 0 {
+ key, value = key[:i], key[i+1:]
+ }
+ key, err1 := QueryUnescape(key)
+ if err1 != nil {
+ err = err1
+ continue
}
- if e != nil {
- err = e
+ value, err1 = QueryUnescape(value)
+ if err1 != nil {
+ err = err1
continue
}
m[key] = append(m[key], value)
diff --git a/libgo/go/url/url_test.go b/libgo/go/url/url_test.go
index af394d4fb4a..8c27e18e1aa 100644
--- a/libgo/go/url/url_test.go
+++ b/libgo/go/url/url_test.go
@@ -11,11 +11,6 @@ import (
"testing"
)
-// TODO(rsc):
-// test Unescape
-// test Escape
-// test Parse
-
type URLTest struct {
in string
out *URL
@@ -696,3 +691,60 @@ func TestQueryValues(t *testing.T) {
t.Errorf("second Get(bar) = %q, want %q", g, e)
}
}
+
+type parseTest struct {
+ query string
+ out Values
+}
+
+var parseTests = []parseTest{
+ {
+ query: "a=1&b=2",
+ out: Values{"a": []string{"1"}, "b": []string{"2"}},
+ },
+ {
+ query: "a=1&a=2&a=banana",
+ out: Values{"a": []string{"1", "2", "banana"}},
+ },
+ {
+ query: "ascii=%3Ckey%3A+0x90%3E",
+ out: Values{"ascii": []string{"<key: 0x90>"}},
+ },
+ {
+ query: "a=1;b=2",
+ out: Values{"a": []string{"1"}, "b": []string{"2"}},
+ },
+ {
+ query: "a=1&a=2;a=banana",
+ out: Values{"a": []string{"1", "2", "banana"}},
+ },
+}
+
+func TestParseQuery(t *testing.T) {
+ for i, test := range parseTests {
+ form, err := ParseQuery(test.query)
+ if err != nil {
+ t.Errorf("test %d: Unexpected error: %v", i, err)
+ continue
+ }
+ if len(form) != len(test.out) {
+ t.Errorf("test %d: len(form) = %d, want %d", i, len(form), len(test.out))
+ }
+ for k, evs := range test.out {
+ vs, ok := form[k]
+ if !ok {
+ t.Errorf("test %d: Missing key %q", i, k)
+ continue
+ }
+ if len(vs) != len(evs) {
+ t.Errorf("test %d: len(form[%q]) = %d, want %d", i, k, len(vs), len(evs))
+ continue
+ }
+ for j, ev := range evs {
+ if v := vs[j]; v != ev {
+ t.Errorf("test %d: form[%q][%d] = %q, want %q", i, k, j, v, ev)
+ }
+ }
+ }
+ }
+}
diff --git a/libgo/go/utf8/utf8.go b/libgo/go/utf8/utf8.go
index 8910e17d770..3cd919d1d98 100644
--- a/libgo/go/utf8/utf8.go
+++ b/libgo/go/utf8/utf8.go
@@ -354,3 +354,40 @@ func RuneCountInString(s string) (n int) {
// an encoded rune. Second and subsequent bytes always have the top
// two bits set to 10.
func RuneStart(b byte) bool { return b&0xC0 != 0x80 }
+
+// Valid reports whether p consists entirely of valid UTF-8-encoded runes.
+func Valid(p []byte) bool {
+ i := 0
+ for i < len(p) {
+ if p[i] < RuneSelf {
+ i++
+ } else {
+ _, size := DecodeRune(p[i:])
+ if size == 1 {
+ // All valid runes of size of 1 (those
+ // below RuneSelf) were handled above.
+ // This must be a RuneError.
+ return false
+ }
+ i += size
+ }
+ }
+ return true
+}
+
+// ValidString reports whether s consists entirely of valid UTF-8-encoded runes.
+func ValidString(s string) bool {
+ for i, r := range s {
+ if r == RuneError {
+ // The RuneError value can be an error
+ // sentinel value (if it's size 1) or the same
+ // value encoded properly. Decode it to see if
+ // it's the 1 byte sentinel value.
+ _, size := DecodeRuneInString(s[i:])
+ if size == 1 {
+ return false
+ }
+ }
+ }
+ return true
+}
diff --git a/libgo/go/utf8/utf8_test.go b/libgo/go/utf8/utf8_test.go
index 7a1db93e550..6cbbebc1a37 100644
--- a/libgo/go/utf8/utf8_test.go
+++ b/libgo/go/utf8/utf8_test.go
@@ -274,6 +274,35 @@ func TestRuneCount(t *testing.T) {
}
}
+type ValidTest struct {
+ in string
+ out bool
+}
+
+var validTests = []ValidTest{
+ {"", true},
+ {"a", true},
+ {"abc", true},
+ {"Ж", true},
+ {"ЖЖ", true},
+ {"брÑд-ЛГТМ", true},
+ {"☺☻☹", true},
+ {string([]byte{66, 250}), false},
+ {string([]byte{66, 250, 67}), false},
+ {"a\uFFFDb", true},
+}
+
+func TestValid(t *testing.T) {
+ for i, tt := range validTests {
+ if Valid([]byte(tt.in)) != tt.out {
+ t.Errorf("%d. Valid(%q) = %v; want %v", i, tt.in, !tt.out, tt.out)
+ }
+ if ValidString(tt.in) != tt.out {
+ t.Errorf("%d. ValidString(%q) = %v; want %v", i, tt.in, !tt.out, tt.out)
+ }
+ }
+}
+
func BenchmarkRuneCountTenASCIIChars(b *testing.B) {
for i := 0; i < b.N; i++ {
RuneCountInString("0123456789")
diff --git a/libgo/go/websocket/client.go b/libgo/go/websocket/client.go
index 74bede4249f..b7eaafda163 100644
--- a/libgo/go/websocket/client.go
+++ b/libgo/go/websocket/client.go
@@ -6,114 +6,119 @@ package websocket
import (
"bufio"
- "bytes"
"crypto/tls"
- "fmt"
- "http"
"io"
"net"
"os"
- "rand"
- "strings"
"url"
)
-type ProtocolError struct {
- ErrorString string
-}
-
-func (err *ProtocolError) String() string { return string(err.ErrorString) }
-
-var (
- ErrBadScheme = &ProtocolError{"bad scheme"}
- ErrBadStatus = &ProtocolError{"bad status"}
- ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
- ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
- ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
- ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
- ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
- secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte
-)
-
+// DialError is an error that occurs while dialling a websocket server.
type DialError struct {
- URL string
- Protocol string
- Origin string
- Error os.Error
+ *Config
+ Error os.Error
}
func (e *DialError) String() string {
- return "websocket.Dial " + e.URL + ": " + e.Error.String()
+ return "websocket.Dial " + e.Config.Location.String() + ": " + e.Error.String()
}
-func init() {
- i := 0
- for ch := byte(0x21); ch < 0x30; ch++ {
- secKeyRandomChars[i] = ch
- i++
+// NewConfig creates a new WebSocket config for client connection.
+func NewConfig(server, origin string) (config *Config, err os.Error) {
+ config = new(Config)
+ config.Version = ProtocolVersionHybi13
+ config.Location, err = url.ParseRequest(server)
+ if err != nil {
+ return
}
- for ch := byte(0x3a); ch < 0x7F; ch++ {
- secKeyRandomChars[i] = ch
- i++
+ config.Origin, err = url.ParseRequest(origin)
+ if err != nil {
+ return
}
+ return
}
-type handshaker func(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) os.Error
-
-// newClient creates a new Web Socket client connection.
-func newClient(resourceName, host, origin, location, protocol string, rwc io.ReadWriteCloser, handshake handshaker) (ws *Conn, err os.Error) {
+// NewClient creates a new WebSocket client connection over rwc.
+func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err os.Error) {
br := bufio.NewReader(rwc)
bw := bufio.NewWriter(rwc)
- err = handshake(resourceName, host, origin, location, protocol, br, bw)
+ switch config.Version {
+ case ProtocolVersionHixie75:
+ err = hixie75ClientHandshake(config, br, bw)
+ case ProtocolVersionHixie76, ProtocolVersionHybi00:
+ err = hixie76ClientHandshake(config, br, bw)
+ case ProtocolVersionHybi08, ProtocolVersionHybi13:
+ err = hybiClientHandshake(config, br, bw)
+ default:
+ err = ErrBadProtocolVersion
+ }
if err != nil {
return
}
buf := bufio.NewReadWriter(br, bw)
- ws = newConn(origin, location, protocol, buf, rwc)
+ switch config.Version {
+ case ProtocolVersionHixie75, ProtocolVersionHixie76, ProtocolVersionHybi00:
+ ws = newHixieClientConn(config, buf, rwc)
+ case ProtocolVersionHybi08, ProtocolVersionHybi13:
+ ws = newHybiClientConn(config, buf, rwc)
+ }
return
}
/*
-Dial opens a new client connection to a Web Socket.
+Dial opens a new client connection to a WebSocket.
A trivial example client:
package main
import (
- "websocket"
+ "http"
+ "log"
"strings"
+ "websocket"
)
func main() {
- ws, err := websocket.Dial("ws://localhost/ws", "", "http://localhost/");
- if err != nil {
- panic("Dial: " + err.String())
+ origin := "http://localhost/"
+ url := "ws://localhost/ws"
+ ws, err := websocket.Dial(url, "", origin)
+ if err != nil {
+ log.Fatal(err)
}
if _, err := ws.Write([]byte("hello, world!\n")); err != nil {
- panic("Write: " + err.String())
+ log.Fatal(err)
}
var msg = make([]byte, 512);
if n, err := ws.Read(msg); err != nil {
- panic("Read: " + err.String())
+ log.Fatal(err)
}
// use msg[0:n]
}
*/
func Dial(url_, protocol, origin string) (ws *Conn, err os.Error) {
- var client net.Conn
-
- parsedUrl, err := url.Parse(url_)
+ config, err := NewConfig(url_, origin)
if err != nil {
- goto Error
+ return nil, err
}
+ return DialConfig(config)
+}
- switch parsedUrl.Scheme {
+// DialConfig opens a new client connection to a WebSocket with a config.
+func DialConfig(config *Config) (ws *Conn, err os.Error) {
+ var client net.Conn
+ if config.Location == nil {
+ return nil, &DialError{config, ErrBadWebSocketLocation}
+ }
+ if config.Origin == nil {
+ return nil, &DialError{config, ErrBadWebSocketOrigin}
+ }
+ switch config.Location.Scheme {
case "ws":
- client, err = net.Dial("tcp", parsedUrl.Host)
+ client, err = net.Dial("tcp", config.Location.Host)
case "wss":
- client, err = tls.Dial("tcp", parsedUrl.Host, nil)
+ client, err = tls.Dial("tcp", config.Location.Host, config.TlsConfig)
default:
err = ErrBadScheme
@@ -122,202 +127,12 @@ func Dial(url_, protocol, origin string) (ws *Conn, err os.Error) {
goto Error
}
- ws, err = newClient(parsedUrl.RawPath, parsedUrl.Host, origin, url_, protocol, client, handshake)
+ ws, err = NewClient(config, client)
if err != nil {
goto Error
}
return
Error:
- return nil, &DialError{url_, protocol, origin, err}
-}
-
-/*
-Generates handshake key as described in 4.1 Opening handshake step 16 to 22.
-cf. http://www.whatwg.org/specs/web-socket-protocol/
-*/
-func generateKeyNumber() (key string, number uint32) {
- // 16. Let /spaces_n/ be a random integer from 1 to 12 inclusive.
- spaces := rand.Intn(12) + 1
-
- // 17. Let /max_n/ be the largest integer not greater than
- // 4,294,967,295 divided by /spaces_n/
- max := int(4294967295 / uint32(spaces))
-
- // 18. Let /number_n/ be a random integer from 0 to /max_n/ inclusive.
- number = uint32(rand.Intn(max + 1))
-
- // 19. Let /product_n/ be the result of multiplying /number_n/ and
- // /spaces_n/ together.
- product := number * uint32(spaces)
-
- // 20. Let /key_n/ be a string consisting of /product_n/, expressed
- // in base ten using the numerals in the range U+0030 DIGIT ZERO (0)
- // to U+0039 DIGIT NINE (9).
- key = fmt.Sprintf("%d", product)
-
- // 21. Insert between one and twelve random characters from the ranges
- // U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
- // positions.
- n := rand.Intn(12) + 1
- for i := 0; i < n; i++ {
- pos := rand.Intn(len(key)) + 1
- ch := secKeyRandomChars[rand.Intn(len(secKeyRandomChars))]
- key = key[0:pos] + string(ch) + key[pos:]
- }
-
- // 22. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random
- // positions other than the start or end of the string.
- for i := 0; i < spaces; i++ {
- pos := rand.Intn(len(key)-1) + 1
- key = key[0:pos] + " " + key[pos:]
- }
-
- return
-}
-
-/*
-Generates handshake key_3 as described in 4.1 Opening handshake step 26.
-cf. http://www.whatwg.org/specs/web-socket-protocol/
-*/
-func generateKey3() (key []byte) {
- // 26. Let /key3/ be a string consisting of eight random bytes (or
- // equivalently, a random 64 bit integer encoded in big-endian order).
- key = make([]byte, 8)
- for i := 0; i < 8; i++ {
- key[i] = byte(rand.Intn(256))
- }
- return
-}
-
-/*
-Web Socket protocol handshake based on
-http://www.whatwg.org/specs/web-socket-protocol/
-(draft of http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol)
-*/
-func handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
- // 4.1. Opening handshake.
- // Step 5. send a request line.
- bw.WriteString("GET " + resourceName + " HTTP/1.1\r\n")
-
- // Step 6-14. push request headers in fields.
- var fields []string
- fields = append(fields, "Upgrade: WebSocket\r\n")
- fields = append(fields, "Connection: Upgrade\r\n")
- fields = append(fields, "Host: "+host+"\r\n")
- fields = append(fields, "Origin: "+origin+"\r\n")
- if protocol != "" {
- fields = append(fields, "Sec-WebSocket-Protocol: "+protocol+"\r\n")
- }
- // TODO(ukai): Step 15. send cookie if any.
-
- // Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
- key1, number1 := generateKeyNumber()
- key2, number2 := generateKeyNumber()
- fields = append(fields, "Sec-WebSocket-Key1: "+key1+"\r\n")
- fields = append(fields, "Sec-WebSocket-Key2: "+key2+"\r\n")
-
- // Step 24. shuffle fields and send them out.
- for i := 1; i < len(fields); i++ {
- j := rand.Intn(i)
- fields[i], fields[j] = fields[j], fields[i]
- }
- for i := 0; i < len(fields); i++ {
- bw.WriteString(fields[i])
- }
- // Step 25. send CRLF.
- bw.WriteString("\r\n")
-
- // Step 26. generate 8 bytes random key.
- key3 := generateKey3()
- // Step 27. send it out.
- bw.Write(key3)
- if err = bw.Flush(); err != nil {
- return
- }
-
- // Step 28-29, 32-40. read response from server.
- resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
- if err != nil {
- return err
- }
- // Step 30. check response code is 101.
- if resp.StatusCode != 101 {
- return ErrBadStatus
- }
-
- // Step 41. check websocket headers.
- if resp.Header.Get("Upgrade") != "WebSocket" ||
- strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
- return ErrBadUpgrade
- }
-
- if resp.Header.Get("Sec-Websocket-Origin") != origin {
- return ErrBadWebSocketOrigin
- }
-
- if resp.Header.Get("Sec-Websocket-Location") != location {
- return ErrBadWebSocketLocation
- }
-
- if protocol != "" && resp.Header.Get("Sec-Websocket-Protocol") != protocol {
- return ErrBadWebSocketProtocol
- }
-
- // Step 42-43. get expected data from challenge data.
- expected, err := getChallengeResponse(number1, number2, key3)
- if err != nil {
- return err
- }
-
- // Step 44. read 16 bytes from server.
- reply := make([]byte, 16)
- if _, err = io.ReadFull(br, reply); err != nil {
- return err
- }
-
- // Step 45. check the reply equals to expected data.
- if !bytes.Equal(expected, reply) {
- return ErrChallengeResponse
- }
- // WebSocket connection is established.
- return
-}
-
-/*
-Handshake described in (soon obsolete)
-draft-hixie-thewebsocket-protocol-75.
-*/
-func draft75handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
- bw.WriteString("GET " + resourceName + " HTTP/1.1\r\n")
- bw.WriteString("Upgrade: WebSocket\r\n")
- bw.WriteString("Connection: Upgrade\r\n")
- bw.WriteString("Host: " + host + "\r\n")
- bw.WriteString("Origin: " + origin + "\r\n")
- if protocol != "" {
- bw.WriteString("WebSocket-Protocol: " + protocol + "\r\n")
- }
- bw.WriteString("\r\n")
- bw.Flush()
- resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
- if err != nil {
- return
- }
- if resp.Status != "101 Web Socket Protocol Handshake" {
- return ErrBadStatus
- }
- if resp.Header.Get("Upgrade") != "WebSocket" ||
- resp.Header.Get("Connection") != "Upgrade" {
- return ErrBadUpgrade
- }
- if resp.Header.Get("Websocket-Origin") != origin {
- return ErrBadWebSocketOrigin
- }
- if resp.Header.Get("Websocket-Location") != location {
- return ErrBadWebSocketLocation
- }
- if protocol != "" && resp.Header.Get("Websocket-Protocol") != protocol {
- return ErrBadWebSocketProtocol
- }
- return
+ return nil, &DialError{config, err}
}
diff --git a/libgo/go/websocket/hixie.go b/libgo/go/websocket/hixie.go
new file mode 100644
index 00000000000..841ff3c3ef5
--- /dev/null
+++ b/libgo/go/websocket/hixie.go
@@ -0,0 +1,696 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+// This file implements a protocol of Hixie draft version 75 and 76
+// (draft 76 equals to hybi 00)
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/md5"
+ "encoding/binary"
+ "fmt"
+ "http"
+ "io"
+ "io/ioutil"
+ "os"
+ "rand"
+ "strconv"
+ "strings"
+ "url"
+)
+
+// An aray of characters to be randomly inserted to construct Sec-WebSocket-Key
+// value. It holds characters from ranges U+0021 to U+002F and U+003A to U+007E.
+// See Step 21 in Section 4.1 Opening handshake.
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#page-22
+var secKeyRandomChars [0x30 - 0x21 + 0x7F - 0x3A]byte
+
+func init() {
+ i := 0
+ for ch := byte(0x21); ch < 0x30; ch++ {
+ secKeyRandomChars[i] = ch
+ i++
+ }
+ for ch := byte(0x3a); ch < 0x7F; ch++ {
+ secKeyRandomChars[i] = ch
+ i++
+ }
+}
+
+type byteReader interface {
+ ReadByte() (byte, os.Error)
+}
+
+// readHixieLength reads frame length for frame type 0x80-0xFF
+// as defined in Hixie draft.
+// See section 4.2 Data framing.
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00#section-4.2
+func readHixieLength(r byteReader) (length int64, lengthFields []byte, err os.Error) {
+ for {
+ c, err := r.ReadByte()
+ if err != nil {
+ return 0, nil, err
+ }
+ lengthFields = append(lengthFields, c)
+ length = length*128 + int64(c&0x7f)
+ if c&0x80 == 0 {
+ break
+ }
+ }
+ return
+}
+
+// A hixieLengthFrameReader is a reader for frame type 0x80-0xFF
+// as defined in hixie draft.
+type hixieLengthFrameReader struct {
+ reader io.Reader
+ FrameType byte
+ Length int64
+ header *bytes.Buffer
+ length int
+}
+
+func (frame *hixieLengthFrameReader) Read(msg []byte) (n int, err os.Error) {
+ return frame.reader.Read(msg)
+}
+
+func (frame *hixieLengthFrameReader) PayloadType() byte {
+ if frame.FrameType == '\xff' && frame.Length == 0 {
+ return CloseFrame
+ }
+ return UnknownFrame
+}
+
+func (frame *hixieLengthFrameReader) HeaderReader() io.Reader {
+ if frame.header == nil {
+ return nil
+ }
+ if frame.header.Len() == 0 {
+ frame.header = nil
+ return nil
+ }
+ return frame.header
+}
+
+func (frame *hixieLengthFrameReader) TrailerReader() io.Reader { return nil }
+
+func (frame *hixieLengthFrameReader) Len() (n int) { return frame.length }
+
+// A HixieSentinelFrameReader is a reader for frame type 0x00-0x7F
+// as defined in hixie draft.
+type hixieSentinelFrameReader struct {
+ reader *bufio.Reader
+ FrameType byte
+ header *bytes.Buffer
+ data []byte
+ seenTrailer bool
+ trailer *bytes.Buffer
+}
+
+func (frame *hixieSentinelFrameReader) Read(msg []byte) (n int, err os.Error) {
+ if len(frame.data) == 0 {
+ if frame.seenTrailer {
+ return 0, os.EOF
+ }
+ frame.data, err = frame.reader.ReadSlice('\xff')
+ if err == nil {
+ frame.seenTrailer = true
+ frame.data = frame.data[:len(frame.data)-1] // trim \xff
+ frame.trailer = bytes.NewBuffer([]byte{0xff})
+ }
+ }
+ n = copy(msg, frame.data)
+ frame.data = frame.data[n:]
+ return n, err
+}
+
+func (frame *hixieSentinelFrameReader) PayloadType() byte {
+ if frame.FrameType == 0 {
+ return TextFrame
+ }
+ return UnknownFrame
+}
+
+func (frame *hixieSentinelFrameReader) HeaderReader() io.Reader {
+ if frame.header == nil {
+ return nil
+ }
+ if frame.header.Len() == 0 {
+ frame.header = nil
+ return nil
+ }
+ return frame.header
+}
+
+func (frame *hixieSentinelFrameReader) TrailerReader() io.Reader {
+ if frame.trailer == nil {
+ return nil
+ }
+ if frame.trailer.Len() == 0 {
+ frame.trailer = nil
+ return nil
+ }
+ return frame.trailer
+}
+
+func (frame *hixieSentinelFrameReader) Len() int { return -1 }
+
+// A HixieFrameReaderFactory creates new frame reader based on its frame type.
+type hixieFrameReaderFactory struct {
+ *bufio.Reader
+}
+
+func (buf hixieFrameReaderFactory) NewFrameReader() (r frameReader, err os.Error) {
+ var header []byte
+ var b byte
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ if b&0x80 == 0x80 {
+ length, lengthFields, err := readHixieLength(buf.Reader)
+ if err != nil {
+ return nil, err
+ }
+ if length == 0 {
+ return nil, os.EOF
+ }
+ header = append(header, lengthFields...)
+ return &hixieLengthFrameReader{
+ reader: io.LimitReader(buf.Reader, length),
+ FrameType: b,
+ Length: length,
+ header: bytes.NewBuffer(header)}, err
+ }
+ return &hixieSentinelFrameReader{
+ reader: buf.Reader,
+ FrameType: b,
+ header: bytes.NewBuffer(header)}, err
+}
+
+type hixiFrameWriter struct {
+ writer *bufio.Writer
+}
+
+func (frame *hixiFrameWriter) Write(msg []byte) (n int, err os.Error) {
+ frame.writer.WriteByte(0)
+ frame.writer.Write(msg)
+ frame.writer.WriteByte(0xff)
+ err = frame.writer.Flush()
+ return len(msg), err
+}
+
+func (frame *hixiFrameWriter) Close() os.Error { return nil }
+
+type hixiFrameWriterFactory struct {
+ *bufio.Writer
+}
+
+func (buf hixiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err os.Error) {
+ if payloadType != TextFrame {
+ return nil, ErrNotSupported
+ }
+ return &hixiFrameWriter{writer: buf.Writer}, nil
+}
+
+type hixiFrameHandler struct {
+ conn *Conn
+}
+
+func (handler *hixiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err os.Error) {
+ if header := frame.HeaderReader(); header != nil {
+ io.Copy(ioutil.Discard, header)
+ }
+ if frame.PayloadType() != TextFrame {
+ io.Copy(ioutil.Discard, frame)
+ return nil, nil
+ }
+ return frame, nil
+}
+
+func (handler *hixiFrameHandler) WriteClose(_ int) (err os.Error) {
+ handler.conn.wio.Lock()
+ defer handler.conn.wio.Unlock()
+ closingFrame := []byte{'\xff', '\x00'}
+ handler.conn.buf.Write(closingFrame)
+ return handler.conn.buf.Flush()
+}
+
+// newHixiConn creates a new WebSocket connection speaking hixie draft protocol.
+func newHixieConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ if buf == nil {
+ br := bufio.NewReader(rwc)
+ bw := bufio.NewWriter(rwc)
+ buf = bufio.NewReadWriter(br, bw)
+ }
+ ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
+ frameReaderFactory: hixieFrameReaderFactory{buf.Reader},
+ frameWriterFactory: hixiFrameWriterFactory{buf.Writer},
+ PayloadType: TextFrame}
+ ws.frameHandler = &hixiFrameHandler{ws}
+ return ws
+}
+
+// getChallengeResponse computes the expected response from the
+// challenge as described in section 5.1 Opening Handshake steps 42 to
+// 43 of http://www.whatwg.org/specs/web-socket-protocol/
+func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err os.Error) {
+ // 41. Let /challenge/ be the concatenation of /number_1/, expressed
+ // a big-endian 32 bit integer, /number_2/, expressed in a big-
+ // endian 32 bit integer, and the eight bytes of /key_3/ in the
+ // order they were sent to the wire.
+ challenge := make([]byte, 16)
+ binary.BigEndian.PutUint32(challenge[0:], number1)
+ binary.BigEndian.PutUint32(challenge[4:], number2)
+ copy(challenge[8:], key3)
+
+ // 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big-
+ // endian 128 bit string.
+ h := md5.New()
+ if _, err = h.Write(challenge); err != nil {
+ return
+ }
+ expected = h.Sum()
+ return
+}
+
+// Generates handshake key as described in 4.1 Opening handshake step 16 to 22.
+// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
+func generateKeyNumber() (key string, number uint32) {
+ // 16. Let /spaces_n/ be a random integer from 1 to 12 inclusive.
+ spaces := rand.Intn(12) + 1
+
+ // 17. Let /max_n/ be the largest integer not greater than
+ // 4,294,967,295 divided by /spaces_n/
+ max := int(4294967295 / uint32(spaces))
+
+ // 18. Let /number_n/ be a random integer from 0 to /max_n/ inclusive.
+ number = uint32(rand.Intn(max + 1))
+
+ // 19. Let /product_n/ be the result of multiplying /number_n/ and
+ // /spaces_n/ together.
+ product := number * uint32(spaces)
+
+ // 20. Let /key_n/ be a string consisting of /product_n/, expressed
+ // in base ten using the numerals in the range U+0030 DIGIT ZERO (0)
+ // to U+0039 DIGIT NINE (9).
+ key = fmt.Sprintf("%d", product)
+
+ // 21. Insert between one and twelve random characters from the ranges
+ // U+0021 to U+002F and U+003A to U+007E into /key_n/ at random
+ // positions.
+ n := rand.Intn(12) + 1
+ for i := 0; i < n; i++ {
+ pos := rand.Intn(len(key)) + 1
+ ch := secKeyRandomChars[rand.Intn(len(secKeyRandomChars))]
+ key = key[0:pos] + string(ch) + key[pos:]
+ }
+
+ // 22. Insert /spaces_n/ U+0020 SPACE characters into /key_n/ at random
+ // positions other than the start or end of the string.
+ for i := 0; i < spaces; i++ {
+ pos := rand.Intn(len(key)-1) + 1
+ key = key[0:pos] + " " + key[pos:]
+ }
+
+ return
+}
+
+// Generates handshake key_3 as described in 4.1 Opening handshake step 26.
+// cf. http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
+func generateKey3() (key []byte) {
+ // 26. Let /key3/ be a string consisting of eight random bytes (or
+ // equivalently, a random 64 bit integer encoded in big-endian order).
+ key = make([]byte, 8)
+ for i := 0; i < 8; i++ {
+ key[i] = byte(rand.Intn(256))
+ }
+ return
+}
+
+// Cilent handhake described in (soon obsolete)
+// draft-ietf-hybi-thewebsocket-protocol-00
+// (draft-hixie-thewebsocket-protocol-76)
+func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
+ switch config.Version {
+ case ProtocolVersionHixie76, ProtocolVersionHybi00:
+ default:
+ panic("wrong protocol version.")
+ }
+ // 4.1. Opening handshake.
+ // Step 5. send a request line.
+ bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")
+
+ // Step 6-14. push request headers in fields.
+ fields := []string{
+ "Upgrade: WebSocket\r\n",
+ "Connection: Upgrade\r\n",
+ "Host: " + config.Location.Host + "\r\n",
+ "Origin: " + config.Origin.String() + "\r\n",
+ }
+ if len(config.Protocol) > 0 {
+ if len(config.Protocol) != 1 {
+ return ErrBadWebSocketProtocol
+ }
+ fields = append(fields, "Sec-WebSocket-Protocol: "+config.Protocol[0]+"\r\n")
+ }
+ // TODO(ukai): Step 15. send cookie if any.
+
+ // Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
+ key1, number1 := generateKeyNumber()
+ key2, number2 := generateKeyNumber()
+ if config.handshakeData != nil {
+ key1 = config.handshakeData["key1"]
+ n, err := strconv.Atoui(config.handshakeData["number1"])
+ if err != nil {
+ panic(err)
+ }
+ number1 = uint32(n)
+ key2 = config.handshakeData["key2"]
+ n, err = strconv.Atoui(config.handshakeData["number2"])
+ if err != nil {
+ panic(err)
+ }
+ number2 = uint32(n)
+ }
+ fields = append(fields, "Sec-WebSocket-Key1: "+key1+"\r\n")
+ fields = append(fields, "Sec-WebSocket-Key2: "+key2+"\r\n")
+
+ // Step 24. shuffle fields and send them out.
+ for i := 1; i < len(fields); i++ {
+ j := rand.Intn(i)
+ fields[i], fields[j] = fields[j], fields[i]
+ }
+ for i := 0; i < len(fields); i++ {
+ bw.WriteString(fields[i])
+ }
+ // Step 25. send CRLF.
+ bw.WriteString("\r\n")
+
+ // Step 26. generate 8 bytes random key.
+ key3 := generateKey3()
+ if config.handshakeData != nil {
+ key3 = []byte(config.handshakeData["key3"])
+ }
+ // Step 27. send it out.
+ bw.Write(key3)
+ if err = bw.Flush(); err != nil {
+ return
+ }
+
+ // Step 28-29, 32-40. read response from server.
+ resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
+ if err != nil {
+ return err
+ }
+ // Step 30. check response code is 101.
+ if resp.StatusCode != 101 {
+ return ErrBadStatus
+ }
+
+ // Step 41. check websocket headers.
+ if resp.Header.Get("Upgrade") != "WebSocket" ||
+ strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
+ return ErrBadUpgrade
+ }
+
+ if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() {
+ return ErrBadWebSocketOrigin
+ }
+
+ if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() {
+ return ErrBadWebSocketLocation
+ }
+
+ if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] {
+ return ErrBadWebSocketProtocol
+ }
+
+ // Step 42-43. get expected data from challenge data.
+ expected, err := getChallengeResponse(number1, number2, key3)
+ if err != nil {
+ return err
+ }
+
+ // Step 44. read 16 bytes from server.
+ reply := make([]byte, 16)
+ if _, err = io.ReadFull(br, reply); err != nil {
+ return err
+ }
+
+ // Step 45. check the reply equals to expected data.
+ if !bytes.Equal(expected, reply) {
+ return ErrChallengeResponse
+ }
+ // WebSocket connection is established.
+ return
+}
+
+// Client Handshake described in (soon obsolete)
+// draft-hixie-thewebsocket-protocol-75.
+func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
+ if config.Version != ProtocolVersionHixie75 {
+ panic("wrong protocol version.")
+ }
+ bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")
+ bw.WriteString("Upgrade: WebSocket\r\n")
+ bw.WriteString("Connection: Upgrade\r\n")
+ bw.WriteString("Host: " + config.Location.Host + "\r\n")
+ bw.WriteString("Origin: " + config.Origin.String() + "\r\n")
+ if len(config.Protocol) > 0 {
+ if len(config.Protocol) != 1 {
+ return ErrBadWebSocketProtocol
+ }
+ bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
+ }
+ bw.WriteString("\r\n")
+ bw.Flush()
+ resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
+ if err != nil {
+ return
+ }
+ if resp.Status != "101 Web Socket Protocol Handshake" {
+ return ErrBadStatus
+ }
+ if resp.Header.Get("Upgrade") != "WebSocket" ||
+ resp.Header.Get("Connection") != "Upgrade" {
+ return ErrBadUpgrade
+ }
+ if resp.Header.Get("Websocket-Origin") != config.Origin.String() {
+ return ErrBadWebSocketOrigin
+ }
+ if resp.Header.Get("Websocket-Location") != config.Location.String() {
+ return ErrBadWebSocketLocation
+ }
+ if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] {
+ return ErrBadWebSocketProtocol
+ }
+ return
+}
+
+// newHixieClientConn returns new WebSocket connection speaking hixie draft protocol.
+func newHixieClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
+ return newHixieConn(config, buf, rwc, nil)
+}
+
+// Gets key number from Sec-WebSocket-Key<n>: field as described
+// in 5.2 Sending the server's opening handshake, 4.
+func getKeyNumber(s string) (r uint32) {
+ // 4. Let /key-number_n/ be the digits (characters in the range
+ // U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_1/,
+ // interpreted as a base ten integer, ignoring all other characters
+ // in /key_n/.
+ r = 0
+ for i := 0; i < len(s); i++ {
+ if s[i] >= '0' && s[i] <= '9' {
+ r = r*10 + uint32(s[i]) - '0'
+ }
+ }
+ return
+}
+
+// A Hixie76ServerHandshaker performs a server handshake using
+// hixie draft 76 protocol.
+type hixie76ServerHandshaker struct {
+ *Config
+ challengeResponse []byte
+}
+
+func (c *hixie76ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err os.Error) {
+ c.Version = ProtocolVersionHybi00
+ if req.Method != "GET" {
+ return http.StatusMethodNotAllowed, ErrBadRequestMethod
+ }
+ // HTTP version can be safely ignored.
+
+ if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
+ strings.ToLower(req.Header.Get("Connection")) != "upgrade" {
+ return http.StatusBadRequest, ErrNotWebSocket
+ }
+
+ // TODO(ukai): check Host
+ c.Origin, err = url.ParseRequest(req.Header.Get("Origin"))
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+
+ key1 := req.Header.Get("Sec-Websocket-Key1")
+ if key1 == "" {
+ return http.StatusBadRequest, ErrChallengeResponse
+ }
+ key2 := req.Header.Get("Sec-Websocket-Key2")
+ if key2 == "" {
+ return http.StatusBadRequest, ErrChallengeResponse
+ }
+ key3 := make([]byte, 8)
+ if _, err := io.ReadFull(buf, key3); err != nil {
+ return http.StatusBadRequest, ErrChallengeResponse
+ }
+
+ var scheme string
+ if req.TLS != nil {
+ scheme = "wss"
+ } else {
+ scheme = "ws"
+ }
+ c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RawPath)
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+
+ // Step 4. get key number in Sec-WebSocket-Key<n> fields.
+ keyNumber1 := getKeyNumber(key1)
+ keyNumber2 := getKeyNumber(key2)
+
+ // Step 5. get number of spaces in Sec-WebSocket-Key<n> fields.
+ space1 := uint32(strings.Count(key1, " "))
+ space2 := uint32(strings.Count(key2, " "))
+ if space1 == 0 || space2 == 0 {
+ return http.StatusBadRequest, ErrChallengeResponse
+ }
+
+ // Step 6. key number must be an integral multiple of spaces.
+ if keyNumber1%space1 != 0 || keyNumber2%space2 != 0 {
+ return http.StatusBadRequest, ErrChallengeResponse
+ }
+
+ // Step 7. let part be key number divided by spaces.
+ part1 := keyNumber1 / space1
+ part2 := keyNumber2 / space2
+
+ // Step 8. let challenge be concatenation of part1, part2 and key3.
+ // Step 9. get MD5 fingerprint of challenge.
+ c.challengeResponse, err = getChallengeResponse(part1, part2, key3)
+ if err != nil {
+ return http.StatusInternalServerError, err
+ }
+ protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
+ protocols := strings.Split(protocol, ",")
+ for i := 0; i < len(protocols); i++ {
+ c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
+ }
+
+ return http.StatusSwitchingProtocols, nil
+}
+
+func (c *hixie76ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err os.Error) {
+ if len(c.Protocol) > 0 {
+ if len(c.Protocol) != 1 {
+ return ErrBadWebSocketProtocol
+ }
+ }
+
+ // Step 10. send response status line.
+ buf.WriteString("HTTP/1.1 101 WebSocket Protocol Handshake\r\n")
+ // Step 11. send response headers.
+ buf.WriteString("Upgrade: WebSocket\r\n")
+ buf.WriteString("Connection: Upgrade\r\n")
+ buf.WriteString("Sec-WebSocket-Origin: " + c.Origin.String() + "\r\n")
+ buf.WriteString("Sec-WebSocket-Location: " + c.Location.String() + "\r\n")
+ if len(c.Protocol) > 0 {
+ buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
+ }
+ // Step 12. send CRLF.
+ buf.WriteString("\r\n")
+ // Step 13. send response data.
+ buf.Write(c.challengeResponse)
+ return buf.Flush()
+}
+
+func (c *hixie76ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
+ return newHixieServerConn(c.Config, buf, rwc, request)
+}
+
+// A hixie75ServerHandshaker performs a server handshake using
+// hixie draft 75 protocol.
+type hixie75ServerHandshaker struct {
+ *Config
+}
+
+func (c *hixie75ServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err os.Error) {
+ c.Version = ProtocolVersionHixie75
+ if req.Method != "GET" || req.Proto != "HTTP/1.1" {
+ return http.StatusMethodNotAllowed, ErrBadRequestMethod
+ }
+ if req.Header.Get("Upgrade") != "WebSocket" {
+ return http.StatusBadRequest, ErrNotWebSocket
+ }
+ if req.Header.Get("Connection") != "Upgrade" {
+ return http.StatusBadRequest, ErrNotWebSocket
+ }
+ c.Origin, err = url.ParseRequest(strings.TrimSpace(req.Header.Get("Origin")))
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+
+ var scheme string
+ if req.TLS != nil {
+ scheme = "wss"
+ } else {
+ scheme = "ws"
+ }
+ c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RawPath)
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+ protocol := strings.TrimSpace(req.Header.Get("Websocket-Protocol"))
+ protocols := strings.Split(protocol, ",")
+ for i := 0; i < len(protocols); i++ {
+ c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
+ }
+
+ return http.StatusSwitchingProtocols, nil
+}
+
+func (c *hixie75ServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err os.Error) {
+ if len(c.Protocol) > 0 {
+ if len(c.Protocol) != 1 {
+ return ErrBadWebSocketProtocol
+ }
+ }
+
+ buf.WriteString("HTTP/1.1 101 Web Socket Protocol Handshake\r\n")
+ buf.WriteString("Upgrade: WebSocket\r\n")
+ buf.WriteString("Connection: Upgrade\r\n")
+ buf.WriteString("WebSocket-Origin: " + c.Origin.String() + "\r\n")
+ buf.WriteString("WebSocket-Location: " + c.Location.String() + "\r\n")
+ if len(c.Protocol) > 0 {
+ buf.WriteString("WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
+ }
+ buf.WriteString("\r\n")
+ return buf.Flush()
+}
+
+func (c *hixie75ServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) {
+ return newHixieServerConn(c.Config, buf, rwc, request)
+}
+
+// newHixieServerConn returns a new WebSocket connection speaking hixie draft protocol.
+func newHixieServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ return newHixieConn(config, buf, rwc, request)
+}
diff --git a/libgo/go/websocket/hixie_test.go b/libgo/go/websocket/hixie_test.go
new file mode 100644
index 00000000000..98a0de4d6f4
--- /dev/null
+++ b/libgo/go/websocket/hixie_test.go
@@ -0,0 +1,201 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "http"
+ "os"
+ "strings"
+ "testing"
+ "url"
+)
+
+// Test the getChallengeResponse function with values from section
+// 5.1 of the specification steps 18, 26, and 43 from
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00
+func TestHixie76Challenge(t *testing.T) {
+ var part1 uint32 = 777007543
+ var part2 uint32 = 114997259
+ key3 := []byte{0x47, 0x30, 0x22, 0x2D, 0x5A, 0x3F, 0x47, 0x58}
+ expected := []byte("0st3Rl&q-2ZU^weu")
+
+ response, err := getChallengeResponse(part1, part2, key3)
+ if err != nil {
+ t.Errorf("getChallengeResponse: returned error %v", err)
+ return
+ }
+ if !bytes.Equal(expected, response) {
+ t.Errorf("getChallengeResponse: expected %q got %q", expected, response)
+ }
+}
+
+func TestHixie76ClientHandshake(t *testing.T) {
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+ br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 WebSocket Protocol Handshake
+Upgrade: WebSocket
+Connection: Upgrade
+Sec-WebSocket-Origin: http://example.com
+Sec-WebSocket-Location: ws://example.com/demo
+Sec-WebSocket-Protocol: sample
+
+8jKS'y:G*Co,Wxa-`))
+
+ var err os.Error
+ config := new(Config)
+ config.Location, err = url.ParseRequest("ws://example.com/demo")
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+ config.Origin, err = url.ParseRequest("http://example.com")
+ if err != nil {
+ t.Fatal("origin url", err)
+ }
+ config.Protocol = append(config.Protocol, "sample")
+ config.Version = ProtocolVersionHixie76
+
+ config.handshakeData = map[string]string{
+ "key1": "4 @1 46546xW%0l 1 5",
+ "number1": "829309203",
+ "key2": "12998 5 Y3 1 .P00",
+ "number2": "259970620",
+ "key3": "^n:ds[4U",
+ }
+ err = hixie76ClientHandshake(config, br, bw)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ req, err := http.ReadRequest(bufio.NewReader(b))
+ if err != nil {
+ t.Fatalf("read request: %v", err)
+ }
+ if req.Method != "GET" {
+ t.Errorf("request method expected GET, but got %q", req.Method)
+ }
+ if req.URL.Path != "/demo" {
+ t.Errorf("request path expected /demo, but got %q", req.URL.Path)
+ }
+ if req.Proto != "HTTP/1.1" {
+ t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
+ }
+ if req.Host != "example.com" {
+ t.Errorf("request Host expected example.com, but got %v", req.Host)
+ }
+ var expectedHeader = map[string]string{
+ "Connection": "Upgrade",
+ "Upgrade": "WebSocket",
+ "Origin": "http://example.com",
+ "Sec-Websocket-Key1": config.handshakeData["key1"],
+ "Sec-Websocket-Key2": config.handshakeData["key2"],
+ "Sec-WebSocket-Protocol": config.Protocol[0],
+ }
+ for k, v := range expectedHeader {
+ if req.Header.Get(k) != v {
+ t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
+ }
+ }
+}
+
+func TestHixie76ServerHandshake(t *testing.T) {
+ config := new(Config)
+ handshaker := &hixie76ServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /demo HTTP/1.1
+Host: example.com
+Connection: Upgrade
+Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
+Sec-WebSocket-Protocol: sample
+Upgrade: WebSocket
+Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5
+Origin: http://example.com
+
+^n:ds[4U`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 WebSocket Protocol Handshake",
+ "Upgrade: WebSocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Origin: http://example.com",
+ "Sec-WebSocket-Location: ws://example.com/demo",
+ "Sec-WebSocket-Protocol: sample",
+ "", ""}, "\r\n") + "8jKS'y:G*Co,Wxa-"
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
+
+func TestHixie76SkipLengthFrame(t *testing.T) {
+ b := []byte{'\x80', '\x01', 'x', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
+ buf := bytes.NewBuffer(b)
+ br := bufio.NewReader(buf)
+ bw := bufio.NewWriter(buf)
+ config := newConfig(t, "/")
+ ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
+ msg := make([]byte, 5)
+ n, err := ws.Read(msg)
+ if err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if !bytes.Equal(b[4:9], msg[0:n]) {
+ t.Errorf("Read: expected %q got %q", b[4:9], msg[0:n])
+ }
+}
+
+func TestHixie76SkipNoUTF8Frame(t *testing.T) {
+ b := []byte{'\x01', 'n', '\xff', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
+ buf := bytes.NewBuffer(b)
+ br := bufio.NewReader(buf)
+ bw := bufio.NewWriter(buf)
+ config := newConfig(t, "/")
+ ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
+ msg := make([]byte, 5)
+ n, err := ws.Read(msg)
+ if err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if !bytes.Equal(b[4:9], msg[0:n]) {
+ t.Errorf("Read: expected %q got %q", b[4:9], msg[0:n])
+ }
+}
+
+func TestHixie76ClosingFrame(t *testing.T) {
+ b := []byte{0, 'h', 'e', 'l', 'l', 'o', '\xff'}
+ buf := bytes.NewBuffer(b)
+ br := bufio.NewReader(buf)
+ bw := bufio.NewWriter(buf)
+ config := newConfig(t, "/")
+ ws := newHixieConn(config, bufio.NewReadWriter(br, bw), nil, nil)
+ msg := make([]byte, 5)
+ n, err := ws.Read(msg)
+ if err != nil {
+ t.Errorf("read: %v", err)
+ }
+ if !bytes.Equal(b[1:6], msg[0:n]) {
+ t.Errorf("Read: expected %q got %q", b[1:6], msg[0:n])
+ }
+ n, err = ws.Read(msg)
+ if err != os.EOF {
+ t.Errorf("read: %v", err)
+ }
+}
diff --git a/libgo/go/websocket/hybi.go b/libgo/go/websocket/hybi.go
new file mode 100644
index 00000000000..fe08b3d738b
--- /dev/null
+++ b/libgo/go/websocket/hybi.go
@@ -0,0 +1,550 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+// This file implements a protocol of hybi draft.
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
+
+import (
+ "bufio"
+ "bytes"
+ "crypto/rand"
+ "crypto/sha1"
+ "encoding/base64"
+ "encoding/binary"
+ "fmt"
+ "http"
+ "io"
+ "io/ioutil"
+ "os"
+ "strings"
+ "url"
+)
+
+const (
+ websocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+
+ closeStatusNormal = 1000
+ closeStatusGoingAway = 1001
+ closeStatusProtocolError = 1002
+ closeStatusUnsupportedData = 1003
+ closeStatusFrameTooLarge = 1004
+ closeStatusNoStatusRcvd = 1005
+ closeStatusAbnormalClosure = 1006
+ closeStatusBadMessageData = 1007
+ closeStatusPolicyViolation = 1008
+ closeStatusTooBigData = 1009
+ closeStatusExtensionMismatch = 1010
+
+ maxControlFramePayloadLength = 125
+)
+
+var (
+ ErrBadMaskingKey = &ProtocolError{"bad masking key"}
+ ErrBadPongMessage = &ProtocolError{"bad pong message"}
+ ErrBadClosingStatus = &ProtocolError{"bad closing status"}
+ ErrUnsupportedExtensions = &ProtocolError{"unsupported extensions"}
+ ErrNotImplemented = &ProtocolError{"not implemented"}
+)
+
+// A hybiFrameHeader is a frame header as defined in hybi draft.
+type hybiFrameHeader struct {
+ Fin bool
+ Rsv [3]bool
+ OpCode byte
+ Length int64
+ MaskingKey []byte
+
+ data *bytes.Buffer
+}
+
+// A hybiFrameReader is a reader for hybi frame.
+type hybiFrameReader struct {
+ reader io.Reader
+
+ header hybiFrameHeader
+ pos int64
+ length int
+}
+
+func (frame *hybiFrameReader) Read(msg []byte) (n int, err os.Error) {
+ n, err = frame.reader.Read(msg)
+ if err != nil {
+ return 0, err
+ }
+ if frame.header.MaskingKey != nil {
+ for i := 0; i < n; i++ {
+ msg[i] = msg[i] ^ frame.header.MaskingKey[frame.pos%4]
+ frame.pos++
+ }
+ }
+ return n, err
+}
+
+func (frame *hybiFrameReader) PayloadType() byte { return frame.header.OpCode }
+
+func (frame *hybiFrameReader) HeaderReader() io.Reader {
+ if frame.header.data == nil {
+ return nil
+ }
+ if frame.header.data.Len() == 0 {
+ return nil
+ }
+ return frame.header.data
+}
+
+func (frame *hybiFrameReader) TrailerReader() io.Reader { return nil }
+
+func (frame *hybiFrameReader) Len() (n int) { return frame.length }
+
+// A hybiFrameReaderFactory creates new frame reader based on its frame type.
+type hybiFrameReaderFactory struct {
+ *bufio.Reader
+}
+
+// NewFrameReader reads a frame header from the connection, and creates new reader for the frame.
+// See Section 5.2 Base Frameing protocol for detail.
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5.2
+func (buf hybiFrameReaderFactory) NewFrameReader() (frame frameReader, err os.Error) {
+ hybiFrame := new(hybiFrameReader)
+ frame = hybiFrame
+ var header []byte
+ var b byte
+ // First byte. FIN/RSV1/RSV2/RSV3/OpCode(4bits)
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ hybiFrame.header.Fin = ((header[0] >> 7) & 1) != 0
+ for i := 0; i < 3; i++ {
+ j := uint(6 - i)
+ hybiFrame.header.Rsv[i] = ((header[0] >> j) & 1) != 0
+ }
+ hybiFrame.header.OpCode = header[0] & 0x0f
+
+ // Second byte. Mask/Payload len(7bits)
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ mask := (b & 0x80) != 0
+ b &= 0x7f
+ lengthFields := 0
+ switch {
+ case b <= 125: // Payload length 7bits.
+ hybiFrame.header.Length = int64(b)
+ case b == 126: // Payload length 7+16bits
+ lengthFields = 2
+ case b == 127: // Payload length 7+64bits
+ lengthFields = 8
+ }
+ for i := 0; i < lengthFields; i++ {
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ hybiFrame.header.Length = hybiFrame.header.Length*256 + int64(b)
+ }
+ if mask {
+ // Masking key. 4 bytes.
+ for i := 0; i < 4; i++ {
+ b, err = buf.ReadByte()
+ if err != nil {
+ return
+ }
+ header = append(header, b)
+ hybiFrame.header.MaskingKey = append(hybiFrame.header.MaskingKey, b)
+ }
+ }
+ hybiFrame.reader = io.LimitReader(buf.Reader, hybiFrame.header.Length)
+ hybiFrame.header.data = bytes.NewBuffer(header)
+ hybiFrame.length = len(header) + int(hybiFrame.header.Length)
+ return
+}
+
+// A HybiFrameWriter is a writer for hybi frame.
+type hybiFrameWriter struct {
+ writer *bufio.Writer
+
+ header *hybiFrameHeader
+}
+
+func (frame *hybiFrameWriter) Write(msg []byte) (n int, err os.Error) {
+ var header []byte
+ var b byte
+ if frame.header.Fin {
+ b |= 0x80
+ }
+ for i := 0; i < 3; i++ {
+ if frame.header.Rsv[i] {
+ j := uint(6 - i)
+ b |= 1 << j
+ }
+ }
+ b |= frame.header.OpCode
+ header = append(header, b)
+ if frame.header.MaskingKey != nil {
+ b = 0x80
+ } else {
+ b = 0
+ }
+ lengthFields := 0
+ length := len(msg)
+ switch {
+ case length <= 125:
+ b |= byte(length)
+ case length < 65536:
+ b |= 126
+ lengthFields = 2
+ default:
+ b |= 127
+ lengthFields = 8
+ }
+ header = append(header, b)
+ for i := 0; i < lengthFields; i++ {
+ j := uint((lengthFields - i - 1) * 8)
+ b = byte((length >> j) & 0xff)
+ header = append(header, b)
+ }
+ if frame.header.MaskingKey != nil {
+ if len(frame.header.MaskingKey) != 4 {
+ return 0, ErrBadMaskingKey
+ }
+ header = append(header, frame.header.MaskingKey...)
+ frame.writer.Write(header)
+ var data []byte
+
+ for i := 0; i < length; i++ {
+ data = append(data, msg[i]^frame.header.MaskingKey[i%4])
+ }
+ frame.writer.Write(data)
+ err = frame.writer.Flush()
+ return length, err
+ }
+ frame.writer.Write(header)
+ frame.writer.Write(msg)
+ err = frame.writer.Flush()
+ return length, err
+}
+
+func (frame *hybiFrameWriter) Close() os.Error { return nil }
+
+type hybiFrameWriterFactory struct {
+ *bufio.Writer
+ needMaskingKey bool
+}
+
+func (buf hybiFrameWriterFactory) NewFrameWriter(payloadType byte) (frame frameWriter, err os.Error) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: payloadType}
+ if buf.needMaskingKey {
+ frameHeader.MaskingKey, err = generateMaskingKey()
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &hybiFrameWriter{writer: buf.Writer, header: frameHeader}, nil
+}
+
+type hybiFrameHandler struct {
+ conn *Conn
+ payloadType byte
+}
+
+func (handler *hybiFrameHandler) HandleFrame(frame frameReader) (r frameReader, err os.Error) {
+ if handler.conn.IsServerConn() {
+ // The client MUST mask all frames sent to the server.
+ if frame.(*hybiFrameReader).header.MaskingKey == nil {
+ handler.WriteClose(closeStatusProtocolError)
+ return nil, os.EOF
+ }
+ } else {
+ // The server MUST NOT mask all frames.
+ if frame.(*hybiFrameReader).header.MaskingKey != nil {
+ handler.WriteClose(closeStatusProtocolError)
+ return nil, os.EOF
+ }
+ }
+ if header := frame.HeaderReader(); header != nil {
+ io.Copy(ioutil.Discard, header)
+ }
+ switch frame.PayloadType() {
+ case ContinuationFrame:
+ frame.(*hybiFrameReader).header.OpCode = handler.payloadType
+ case TextFrame, BinaryFrame:
+ handler.payloadType = frame.PayloadType()
+ case CloseFrame:
+ return nil, os.EOF
+ case PingFrame:
+ pingMsg := make([]byte, maxControlFramePayloadLength)
+ n, err := io.ReadFull(frame, pingMsg)
+ if err != nil && err != io.ErrUnexpectedEOF {
+ return nil, err
+ }
+ io.Copy(ioutil.Discard, frame)
+ n, err = handler.WritePong(pingMsg[:n])
+ if err != nil {
+ return nil, err
+ }
+ return nil, nil
+ case PongFrame:
+ return nil, ErrNotImplemented
+ }
+ return frame, nil
+}
+
+func (handler *hybiFrameHandler) WriteClose(status int) (err os.Error) {
+ handler.conn.wio.Lock()
+ defer handler.conn.wio.Unlock()
+ w, err := handler.conn.frameWriterFactory.NewFrameWriter(CloseFrame)
+ if err != nil {
+ return err
+ }
+ msg := make([]byte, 2)
+ binary.BigEndian.PutUint16(msg, uint16(status))
+ _, err = w.Write(msg)
+ w.Close()
+ return err
+}
+
+func (handler *hybiFrameHandler) WritePong(msg []byte) (n int, err os.Error) {
+ handler.conn.wio.Lock()
+ defer handler.conn.wio.Unlock()
+ w, err := handler.conn.frameWriterFactory.NewFrameWriter(PongFrame)
+ if err != nil {
+ return 0, err
+ }
+ n, err = w.Write(msg)
+ w.Close()
+ return n, err
+}
+
+// newHybiConn creates a new WebSocket connection speaking hybi draft protocol.
+func newHybiConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ if buf == nil {
+ br := bufio.NewReader(rwc)
+ bw := bufio.NewWriter(rwc)
+ buf = bufio.NewReadWriter(br, bw)
+ }
+ ws := &Conn{config: config, request: request, buf: buf, rwc: rwc,
+ frameReaderFactory: hybiFrameReaderFactory{buf.Reader},
+ frameWriterFactory: hybiFrameWriterFactory{
+ buf.Writer, request == nil},
+ PayloadType: TextFrame,
+ defaultCloseStatus: closeStatusNormal}
+ ws.frameHandler = &hybiFrameHandler{conn: ws}
+ return ws
+}
+
+// generateMaskingKey generates a masking key for a frame.
+func generateMaskingKey() (maskingKey []byte, err os.Error) {
+ maskingKey = make([]byte, 4)
+ if _, err = io.ReadFull(rand.Reader, maskingKey); err != nil {
+ return
+ }
+ return
+}
+
+// genetateNonce geneates a nonce consisting of a randomly selected 16-byte
+// value that has been base64-encoded.
+func generateNonce() (nonce []byte) {
+ key := make([]byte, 16)
+ if _, err := io.ReadFull(rand.Reader, key); err != nil {
+ panic(err)
+ }
+ nonce = make([]byte, 24)
+ base64.StdEncoding.Encode(nonce, key)
+ return
+}
+
+// getNonceAccept computes the base64-encoded SHA-1 of the concatenation of
+// the nonce ("Sec-WebSocket-Key" value) with the websocket GUID string.
+func getNonceAccept(nonce []byte) (expected []byte, err os.Error) {
+ h := sha1.New()
+ if _, err = h.Write(nonce); err != nil {
+ return
+ }
+ if _, err = h.Write([]byte(websocketGUID)); err != nil {
+ return
+ }
+ expected = make([]byte, 28)
+ base64.StdEncoding.Encode(expected, h.Sum())
+ return
+}
+
+func isHybiVersion(version int) bool {
+ switch version {
+ case ProtocolVersionHybi08, ProtocolVersionHybi13:
+ return true
+ default:
+ }
+ return false
+}
+
+// Client handhake described in draft-ietf-hybi-thewebsocket-protocol-17
+func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
+ if !isHybiVersion(config.Version) {
+ panic("wrong protocol version.")
+ }
+
+ bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")
+
+ bw.WriteString("Host: " + config.Location.Host + "\r\n")
+ bw.WriteString("Upgrade: websocket\r\n")
+ bw.WriteString("Connection: Upgrade\r\n")
+ nonce := generateNonce()
+ if config.handshakeData != nil {
+ nonce = []byte(config.handshakeData["key"])
+ }
+ bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
+ if config.Version == ProtocolVersionHybi13 {
+ bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
+ } else if config.Version == ProtocolVersionHybi08 {
+ bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
+ }
+ bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
+ if len(config.Protocol) > 0 {
+ bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
+ }
+ // TODO(ukai): send extensions.
+ // TODO(ukai): send cookie if any.
+
+ bw.WriteString("\r\n")
+ if err = bw.Flush(); err != nil {
+ return err
+ }
+
+ resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
+ if err != nil {
+ return err
+ }
+ if resp.StatusCode != 101 {
+ return ErrBadStatus
+ }
+ if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
+ strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
+ return ErrBadUpgrade
+ }
+ expectedAccept, err := getNonceAccept(nonce)
+ if err != nil {
+ return err
+ }
+ if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
+ return ErrChallengeResponse
+ }
+ if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
+ return ErrUnsupportedExtensions
+ }
+ offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
+ if offeredProtocol != "" {
+ protocolMatched := false
+ for i := 0; i < len(config.Protocol); i++ {
+ if config.Protocol[i] == offeredProtocol {
+ protocolMatched = true
+ break
+ }
+ }
+ if !protocolMatched {
+ return ErrBadWebSocketProtocol
+ }
+ config.Protocol = []string{offeredProtocol}
+ }
+
+ return nil
+}
+
+// newHybiClientConn creates a client WebSocket connection after handshake.
+func newHybiClientConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
+ return newHybiConn(config, buf, rwc, nil)
+}
+
+// A HybiServerHandshaker performs a server handshake using hybi draft protocol.
+type hybiServerHandshaker struct {
+ *Config
+ accept []byte
+}
+
+func (c *hybiServerHandshaker) ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err os.Error) {
+ c.Version = ProtocolVersionHybi13
+ if req.Method != "GET" {
+ return http.StatusMethodNotAllowed, ErrBadRequestMethod
+ }
+ // HTTP version can be safely ignored.
+
+ if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
+ !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
+ return http.StatusBadRequest, ErrNotWebSocket
+ }
+
+ key := req.Header.Get("Sec-Websocket-Key")
+ if key == "" {
+ return http.StatusBadRequest, ErrChallengeResponse
+ }
+ version := req.Header.Get("Sec-Websocket-Version")
+ var origin string
+ switch version {
+ case "13":
+ c.Version = ProtocolVersionHybi13
+ origin = req.Header.Get("Origin")
+ case "8":
+ c.Version = ProtocolVersionHybi08
+ origin = req.Header.Get("Sec-Websocket-Origin")
+ default:
+ return http.StatusBadRequest, ErrBadWebSocketVersion
+ }
+ c.Origin, err = url.ParseRequest(origin)
+ if err != nil {
+ return http.StatusForbidden, err
+ }
+ var scheme string
+ if req.TLS != nil {
+ scheme = "wss"
+ } else {
+ scheme = "ws"
+ }
+ c.Location, err = url.ParseRequest(scheme + "://" + req.Host + req.URL.RawPath)
+ if err != nil {
+ return http.StatusBadRequest, err
+ }
+ protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
+ protocols := strings.Split(protocol, ",")
+ for i := 0; i < len(protocols); i++ {
+ c.Protocol = append(c.Protocol, strings.TrimSpace(protocols[i]))
+ }
+ c.accept, err = getNonceAccept([]byte(key))
+ if err != nil {
+ return http.StatusInternalServerError, err
+ }
+ return http.StatusSwitchingProtocols, nil
+}
+
+func (c *hybiServerHandshaker) AcceptHandshake(buf *bufio.Writer) (err os.Error) {
+ if len(c.Protocol) > 0 {
+ if len(c.Protocol) != 1 {
+ return ErrBadWebSocketProtocol
+ }
+ }
+ buf.WriteString("HTTP/1.1 101 Switching Protocols\r\n")
+ buf.WriteString("Upgrade: websocket\r\n")
+ buf.WriteString("Connection: Upgrade\r\n")
+ buf.WriteString("Sec-WebSocket-Accept: " + string(c.accept) + "\r\n")
+ if len(c.Protocol) > 0 {
+ buf.WriteString("Sec-WebSocket-Protocol: " + c.Protocol[0] + "\r\n")
+ }
+ // TODO(ukai): support extensions
+ buf.WriteString("\r\n")
+ return buf.Flush()
+}
+
+func (c *hybiServerHandshaker) NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ return newHybiServerConn(c.Config, buf, rwc, request)
+}
+
+// newHybiServerConn returns a new WebSocket connection speaking hybi draft protocol.
+func newHybiServerConn(config *Config, buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) *Conn {
+ return newHybiConn(config, buf, rwc, request)
+}
diff --git a/libgo/go/websocket/hybi_test.go b/libgo/go/websocket/hybi_test.go
new file mode 100644
index 00000000000..9db57e3f1b7
--- /dev/null
+++ b/libgo/go/websocket/hybi_test.go
@@ -0,0 +1,584 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package websocket
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "http"
+ "os"
+ "strings"
+ "testing"
+ "url"
+)
+
+// Test the getNonceAccept function with values in
+// http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
+func TestSecWebSocketAccept(t *testing.T) {
+ nonce := []byte("dGhlIHNhbXBsZSBub25jZQ==")
+ expected := []byte("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=")
+ accept, err := getNonceAccept(nonce)
+ if err != nil {
+ t.Errorf("getNonceAccept: returned error %v", err)
+ return
+ }
+ if !bytes.Equal(expected, accept) {
+ t.Errorf("getNonceAccept: expected %q got %q", expected, accept)
+ }
+}
+
+func TestHybiClientHandshake(t *testing.T) {
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+ br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+Sec-WebSocket-Protocol: chat
+
+`))
+ var err os.Error
+ config := new(Config)
+ config.Location, err = url.ParseRequest("ws://server.example.com/chat")
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+ config.Origin, err = url.ParseRequest("http://example.com")
+ if err != nil {
+ t.Fatal("origin url", err)
+ }
+ config.Protocol = append(config.Protocol, "chat")
+ config.Protocol = append(config.Protocol, "superchat")
+ config.Version = ProtocolVersionHybi13
+
+ config.handshakeData = map[string]string{
+ "key": "dGhlIHNhbXBsZSBub25jZQ==",
+ }
+ err = hybiClientHandshake(config, br, bw)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ req, err := http.ReadRequest(bufio.NewReader(b))
+ if err != nil {
+ t.Fatalf("read request: %v", err)
+ }
+ if req.Method != "GET" {
+ t.Errorf("request method expected GET, but got %q", req.Method)
+ }
+ if req.URL.Path != "/chat" {
+ t.Errorf("request path expected /chat, but got %q", req.URL.Path)
+ }
+ if req.Proto != "HTTP/1.1" {
+ t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
+ }
+ if req.Host != "server.example.com" {
+ t.Errorf("request Host expected server.example.com, but got %v", req.Host)
+ }
+ var expectedHeader = map[string]string{
+ "Connection": "Upgrade",
+ "Upgrade": "websocket",
+ "Sec-Websocket-Key": config.handshakeData["key"],
+ "Origin": config.Origin.String(),
+ "Sec-Websocket-Protocol": "chat, superchat",
+ "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi13),
+ }
+ for k, v := range expectedHeader {
+ if req.Header.Get(k) != v {
+ t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
+ }
+ }
+}
+
+func TestHybiClientHandshakeHybi08(t *testing.T) {
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+ br := bufio.NewReader(strings.NewReader(`HTTP/1.1 101 Switching Protocols
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+Sec-WebSocket-Protocol: chat
+
+`))
+ var err os.Error
+ config := new(Config)
+ config.Location, err = url.ParseRequest("ws://server.example.com/chat")
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+ config.Origin, err = url.ParseRequest("http://example.com")
+ if err != nil {
+ t.Fatal("origin url", err)
+ }
+ config.Protocol = append(config.Protocol, "chat")
+ config.Protocol = append(config.Protocol, "superchat")
+ config.Version = ProtocolVersionHybi08
+
+ config.handshakeData = map[string]string{
+ "key": "dGhlIHNhbXBsZSBub25jZQ==",
+ }
+ err = hybiClientHandshake(config, br, bw)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ req, err := http.ReadRequest(bufio.NewReader(b))
+ if err != nil {
+ t.Fatalf("read request: %v", err)
+ }
+ if req.Method != "GET" {
+ t.Errorf("request method expected GET, but got %q", req.Method)
+ }
+ if req.URL.Path != "/chat" {
+ t.Errorf("request path expected /demo, but got %q", req.URL.Path)
+ }
+ if req.Proto != "HTTP/1.1" {
+ t.Errorf("request proto expected HTTP/1.1, but got %q", req.Proto)
+ }
+ if req.Host != "server.example.com" {
+ t.Errorf("request Host expected example.com, but got %v", req.Host)
+ }
+ var expectedHeader = map[string]string{
+ "Connection": "Upgrade",
+ "Upgrade": "websocket",
+ "Sec-Websocket-Key": config.handshakeData["key"],
+ "Sec-Websocket-Origin": config.Origin.String(),
+ "Sec-Websocket-Protocol": "chat, superchat",
+ "Sec-Websocket-Version": fmt.Sprintf("%d", ProtocolVersionHybi08),
+ }
+ for k, v := range expectedHeader {
+ if req.Header.Get(k) != v {
+ t.Errorf(fmt.Sprintf("%s expected %q but got %q", k, v, req.Header.Get(k)))
+ }
+ }
+}
+
+func TestHybiServerHandshake(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 13
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ config.Protocol = []string{"chat"}
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "Sec-WebSocket-Protocol: chat",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
+
+func TestHybiServerHandshakeHybi08(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Sec-WebSocket-Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 8
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ config.Protocol = []string{"chat"}
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "Sec-WebSocket-Protocol: chat",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
+
+func TestHybiServerHandshakeHybiBadVersion(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: Upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Sec-WebSocket-Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 9
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != ErrBadWebSocketVersion {
+ t.Errorf("handshake expected err %q but got %q", ErrBadWebSocketVersion, err)
+ }
+ if code != http.StatusBadRequest {
+ t.Errorf("status expected %q but got %q", http.StatusBadRequest, code)
+ }
+}
+
+func testHybiFrame(t *testing.T, testHeader, testPayload, testMaskedPayload []byte, frameHeader *hybiFrameHeader) {
+ b := bytes.NewBuffer([]byte{})
+ frameWriterFactory := &hybiFrameWriterFactory{bufio.NewWriter(b), false}
+ w, _ := frameWriterFactory.NewFrameWriter(TextFrame)
+ w.(*hybiFrameWriter).header = frameHeader
+ _, err := w.Write(testPayload)
+ w.Close()
+ if err != nil {
+ t.Errorf("Write error %q", err)
+ }
+ var expectedFrame []byte
+ expectedFrame = append(expectedFrame, testHeader...)
+ expectedFrame = append(expectedFrame, testMaskedPayload...)
+ if !bytes.Equal(expectedFrame, b.Bytes()) {
+ t.Errorf("frame expected %q got %q", expectedFrame, b.Bytes())
+ }
+ frameReaderFactory := &hybiFrameReaderFactory{bufio.NewReader(b)}
+ r, err := frameReaderFactory.NewFrameReader()
+ if err != nil {
+ t.Errorf("Read error %q", err)
+ }
+ if header := r.HeaderReader(); header == nil {
+ t.Errorf("no header")
+ } else {
+ actualHeader := make([]byte, r.Len())
+ n, err := header.Read(actualHeader)
+ if err != nil {
+ t.Errorf("Read header error %q", err)
+ } else {
+ if n < len(testHeader) {
+ t.Errorf("header too short %q got %q", testHeader, actualHeader[:n])
+ }
+ if !bytes.Equal(testHeader, actualHeader[:n]) {
+ t.Errorf("header expected %q got %q", testHeader, actualHeader[:n])
+ }
+ }
+ }
+ if trailer := r.TrailerReader(); trailer != nil {
+ t.Errorf("unexpected trailer %q", trailer)
+ }
+ frame := r.(*hybiFrameReader)
+ if frameHeader.Fin != frame.header.Fin ||
+ frameHeader.OpCode != frame.header.OpCode ||
+ len(testPayload) != int(frame.header.Length) {
+ t.Errorf("mismatch %v (%d) vs %v", frameHeader, len(testPayload), frame)
+ }
+ payload := make([]byte, len(testPayload))
+ _, err = r.Read(payload)
+ if err != nil {
+ t.Errorf("read %v", err)
+ }
+ if !bytes.Equal(testPayload, payload) {
+ t.Errorf("payload %q vs %q", testPayload, payload)
+ }
+}
+
+func TestHybiShortTextFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
+ payload := []byte("hello")
+ testHybiFrame(t, []byte{0x81, 0x05}, payload, payload, frameHeader)
+
+ payload = make([]byte, 125)
+ testHybiFrame(t, []byte{0x81, 125}, payload, payload, frameHeader)
+}
+
+func TestHybiShortMaskedTextFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame,
+ MaskingKey: []byte{0xcc, 0x55, 0x80, 0x20}}
+ payload := []byte("hello")
+ maskedPayload := []byte{0xa4, 0x30, 0xec, 0x4c, 0xa3}
+ header := []byte{0x81, 0x85}
+ header = append(header, frameHeader.MaskingKey...)
+ testHybiFrame(t, header, payload, maskedPayload, frameHeader)
+}
+
+func TestHybiShortBinaryFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: BinaryFrame}
+ payload := []byte("hello")
+ testHybiFrame(t, []byte{0x82, 0x05}, payload, payload, frameHeader)
+
+ payload = make([]byte, 125)
+ testHybiFrame(t, []byte{0x82, 125}, payload, payload, frameHeader)
+}
+
+func TestHybiControlFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: PingFrame}
+ payload := []byte("hello")
+ testHybiFrame(t, []byte{0x89, 0x05}, payload, payload, frameHeader)
+
+ frameHeader = &hybiFrameHeader{Fin: true, OpCode: PongFrame}
+ testHybiFrame(t, []byte{0x8A, 0x05}, payload, payload, frameHeader)
+
+ frameHeader = &hybiFrameHeader{Fin: true, OpCode: CloseFrame}
+ payload = []byte{0x03, 0xe8} // 1000
+ testHybiFrame(t, []byte{0x88, 0x02}, payload, payload, frameHeader)
+}
+
+func TestHybiLongFrame(t *testing.T) {
+ frameHeader := &hybiFrameHeader{Fin: true, OpCode: TextFrame}
+ payload := make([]byte, 126)
+ testHybiFrame(t, []byte{0x81, 126, 0x00, 126}, payload, payload, frameHeader)
+
+ payload = make([]byte, 65535)
+ testHybiFrame(t, []byte{0x81, 126, 0xff, 0xff}, payload, payload, frameHeader)
+
+ payload = make([]byte, 65536)
+ testHybiFrame(t, []byte{0x81, 127, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, payload, payload, frameHeader)
+}
+
+func TestHybiClientRead(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
+ 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
+ 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ msg := make([]byte, 512)
+ n, err := conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 1st frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 1st frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(wireData[2:7], msg[:n]) {
+ t.Errorf("read 1st frame %v, got %v", wireData[2:7], msg[:n])
+ }
+ n, err = conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 2nd frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 2nd frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(wireData[16:21], msg[:n]) {
+ t.Errorf("read 2nd frame %v, got %v", wireData[16:21], msg[:n])
+ }
+ n, err = conn.Read(msg)
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+}
+
+func TestHybiShortRead(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o',
+ 0x89, 0x05, 'h', 'e', 'l', 'l', 'o', // ping
+ 0x81, 0x05, 'w', 'o', 'r', 'l', 'd'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ step := 0
+ pos := 0
+ expectedPos := []int{2, 5, 16, 19}
+ expectedLen := []int{3, 2, 3, 2}
+ for {
+ msg := make([]byte, 3)
+ n, err := conn.Read(msg)
+ if step >= len(expectedPos) {
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+ return
+ }
+ pos = expectedPos[step]
+ endPos := pos + expectedLen[step]
+ if err != nil {
+ t.Errorf("read from %d, got error %q", pos, err)
+ return
+ }
+ if n != endPos-pos {
+ t.Errorf("read from %d, expect %d, got %d", pos, endPos-pos, n)
+ }
+ if !bytes.Equal(wireData[pos:endPos], msg[:n]) {
+ t.Errorf("read from %d, frame %v, got %v", pos, wireData[pos:endPos], msg[:n])
+ }
+ step++
+ }
+}
+
+func TestHybiServerRead(t *testing.T) {
+ wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
+ 0x89, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // ping: hello
+ 0x81, 0x85, 0xed, 0x83, 0xb4, 0x24,
+ 0x9a, 0xec, 0xc6, 0x48, 0x89, // world
+ }
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
+
+ expected := [][]byte{[]byte("hello"), []byte("world")}
+
+ msg := make([]byte, 512)
+ n, err := conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 1st frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 1st frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(expected[0], msg[:n]) {
+ t.Errorf("read 1st frame %q, got %q", expected[0], msg[:n])
+ }
+
+ n, err = conn.Read(msg)
+ if err != nil {
+ t.Errorf("read 2nd frame, error %q", err)
+ }
+ if n != 5 {
+ t.Errorf("read 2nd frame, expect 5, got %d", n)
+ }
+ if !bytes.Equal(expected[1], msg[:n]) {
+ t.Errorf("read 2nd frame %q, got %q", expected[1], msg[:n])
+ }
+
+ n, err = conn.Read(msg)
+ if err == nil {
+ t.Errorf("read not EOF")
+ }
+ if n != 0 {
+ t.Errorf("expect read 0, got %d", n)
+ }
+}
+
+func TestHybiServerReadWithoutMasking(t *testing.T) {
+ wireData := []byte{0x81, 0x05, 'h', 'e', 'l', 'l', 'o'}
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, new(http.Request))
+ // server MUST close the connection upon receiving a non-masked frame.
+ msg := make([]byte, 512)
+ _, err := conn.Read(msg)
+ if err != os.EOF {
+ t.Errorf("read 1st frame, expect %q, but got %q", os.EOF, err)
+ }
+}
+
+func TestHybiClientReadWithMasking(t *testing.T) {
+ wireData := []byte{0x81, 0x85, 0xcc, 0x55, 0x80, 0x20,
+ 0xa4, 0x30, 0xec, 0x4c, 0xa3, // hello
+ }
+ br := bufio.NewReader(bytes.NewBuffer(wireData))
+ bw := bufio.NewWriter(bytes.NewBuffer([]byte{}))
+ conn := newHybiConn(newConfig(t, "/"), bufio.NewReadWriter(br, bw), nil, nil)
+
+ // client MUST close the connection upon receiving a masked frame.
+ msg := make([]byte, 512)
+ _, err := conn.Read(msg)
+ if err != os.EOF {
+ t.Errorf("read 1st frame, expect %q, but got %q", os.EOF, err)
+ }
+}
+
+// Test the hybiServerHandshaker supports firefox implementation and
+// checks Connection request header include (but it's not necessary
+// equal to) "upgrade"
+func TestHybiServerFirefoxHandshake(t *testing.T) {
+ config := new(Config)
+ handshaker := &hybiServerHandshaker{Config: config}
+ br := bufio.NewReader(strings.NewReader(`GET /chat HTTP/1.1
+Host: server.example.com
+Upgrade: websocket
+Connection: keep-alive, upgrade
+Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+Origin: http://example.com
+Sec-WebSocket-Protocol: chat, superchat
+Sec-WebSocket-Version: 13
+
+`))
+ req, err := http.ReadRequest(br)
+ if err != nil {
+ t.Fatal("request", err)
+ }
+ code, err := handshaker.ReadHandshake(br, req)
+ if err != nil {
+ t.Errorf("handshake failed: %v", err)
+ }
+ if code != http.StatusSwitchingProtocols {
+ t.Errorf("status expected %q but got %q", http.StatusSwitchingProtocols, code)
+ }
+ b := bytes.NewBuffer([]byte{})
+ bw := bufio.NewWriter(b)
+
+ config.Protocol = []string{"chat"}
+
+ err = handshaker.AcceptHandshake(bw)
+ if err != nil {
+ t.Errorf("handshake response failed: %v", err)
+ }
+ expectedResponse := strings.Join([]string{
+ "HTTP/1.1 101 Switching Protocols",
+ "Upgrade: websocket",
+ "Connection: Upgrade",
+ "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
+ "Sec-WebSocket-Protocol: chat",
+ "", ""}, "\r\n")
+
+ if b.String() != expectedResponse {
+ t.Errorf("handshake expected %q but got %q", expectedResponse, b.String())
+ }
+}
diff --git a/libgo/go/websocket/server.go b/libgo/go/websocket/server.go
index e0e7c872db4..a1d1d48600f 100644
--- a/libgo/go/websocket/server.go
+++ b/libgo/go/websocket/server.go
@@ -5,11 +5,48 @@
package websocket
import (
+ "bufio"
+ "fmt"
"http"
"io"
- "strings"
+ "os"
)
+func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request) (conn *Conn, err os.Error) {
+ config := new(Config)
+ var hs serverHandshaker = &hybiServerHandshaker{Config: config}
+ code, err := hs.ReadHandshake(buf.Reader, req)
+ if err == ErrBadWebSocketVersion {
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion)
+ buf.WriteString("\r\n")
+ buf.WriteString(err.String())
+ return
+ }
+ if err != nil {
+ hs = &hixie76ServerHandshaker{Config: config}
+ code, err = hs.ReadHandshake(buf.Reader, req)
+ }
+ if err != nil {
+ hs = &hixie75ServerHandshaker{Config: config}
+ code, err = hs.ReadHandshake(buf.Reader, req)
+ }
+ if err != nil {
+ fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code))
+ buf.WriteString("\r\n")
+ buf.WriteString(err.String())
+ return
+ }
+ config.Protocol = nil
+
+ err = hs.AcceptHandshake(buf.Writer)
+ if err != nil {
+ return
+ }
+ conn = hs.NewServerConn(buf, rwc, req)
+ return
+}
+
/*
Handler is an interface to a WebSocket.
@@ -23,7 +60,7 @@ A trivial example server:
"websocket"
)
- // Echo the data received on the Web Socket.
+ // Echo the data received on the WebSocket.
func EchoServer(ws *websocket.Conn) {
io.Copy(ws, ws);
}
@@ -38,26 +75,8 @@ A trivial example server:
*/
type Handler func(*Conn)
-/*
-Gets key number from Sec-WebSocket-Key<n>: field as described
-in 5.2 Sending the server's opening handshake, 4.
-*/
-func getKeyNumber(s string) (r uint32) {
- // 4. Let /key-number_n/ be the digits (characters in the range
- // U+0030 DIGIT ZERO (0) to U+0039 DIGIT NINE (9)) in /key_1/,
- // interpreted as a base ten integer, ignoring all other characters
- // in /key_n/.
- r = 0
- for i := 0; i < len(s); i++ {
- if s[i] >= '0' && s[i] <= '9' {
- r = r*10 + uint32(s[i]) - '0'
- }
- }
- return
-}
-
// ServeHTTP implements the http.Handler interface for a Web Socket
-func (f Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
+func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
rwc, buf, err := w.(http.Hijacker).Hijack()
if err != nil {
panic("Hijack failed: " + err.String())
@@ -67,153 +86,12 @@ func (f Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// the client did not send a handshake that matches with protocol
// specification.
defer rwc.Close()
-
- if req.Method != "GET" {
- return
- }
- // HTTP version can be safely ignored.
-
- if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" ||
- strings.ToLower(req.Header.Get("Connection")) != "upgrade" {
- return
- }
-
- // TODO(ukai): check Host
- origin := req.Header.Get("Origin")
- if origin == "" {
- return
- }
-
- key1 := req.Header.Get("Sec-Websocket-Key1")
- if key1 == "" {
- return
- }
- key2 := req.Header.Get("Sec-Websocket-Key2")
- if key2 == "" {
- return
- }
- key3 := make([]byte, 8)
- if _, err := io.ReadFull(buf, key3); err != nil {
- return
- }
-
- var location string
- if req.TLS != nil {
- location = "wss://" + req.Host + req.URL.RawPath
- } else {
- location = "ws://" + req.Host + req.URL.RawPath
- }
-
- // Step 4. get key number in Sec-WebSocket-Key<n> fields.
- keyNumber1 := getKeyNumber(key1)
- keyNumber2 := getKeyNumber(key2)
-
- // Step 5. get number of spaces in Sec-WebSocket-Key<n> fields.
- space1 := uint32(strings.Count(key1, " "))
- space2 := uint32(strings.Count(key2, " "))
- if space1 == 0 || space2 == 0 {
- return
- }
-
- // Step 6. key number must be an integral multiple of spaces.
- if keyNumber1%space1 != 0 || keyNumber2%space2 != 0 {
- return
- }
-
- // Step 7. let part be key number divided by spaces.
- part1 := keyNumber1 / space1
- part2 := keyNumber2 / space2
-
- // Step 8. let challenge be concatenation of part1, part2 and key3.
- // Step 9. get MD5 fingerprint of challenge.
- response, err := getChallengeResponse(part1, part2, key3)
- if err != nil {
- return
- }
-
- // Step 10. send response status line.
- buf.WriteString("HTTP/1.1 101 WebSocket Protocol Handshake\r\n")
- // Step 11. send response headers.
- buf.WriteString("Upgrade: WebSocket\r\n")
- buf.WriteString("Connection: Upgrade\r\n")
- buf.WriteString("Sec-WebSocket-Location: " + location + "\r\n")
- buf.WriteString("Sec-WebSocket-Origin: " + origin + "\r\n")
- protocol := strings.TrimSpace(req.Header.Get("Sec-Websocket-Protocol"))
- if protocol != "" {
- buf.WriteString("Sec-WebSocket-Protocol: " + protocol + "\r\n")
- }
- // Step 12. send CRLF.
- buf.WriteString("\r\n")
- // Step 13. send response data.
- buf.Write(response)
- if err := buf.Flush(); err != nil {
- return
- }
- ws := newConn(origin, location, protocol, buf, rwc)
- ws.Request = req
- f(ws)
-}
-
-/*
-Draft75Handler is an interface to a WebSocket based on the
-(soon obsolete) draft-hixie-thewebsocketprotocol-75.
-*/
-type Draft75Handler func(*Conn)
-
-// ServeHTTP implements the http.Handler interface for a Web Socket.
-func (f Draft75Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- if req.Method != "GET" || req.Proto != "HTTP/1.1" {
- w.WriteHeader(http.StatusBadRequest)
- io.WriteString(w, "Unexpected request")
- return
- }
- if req.Header.Get("Upgrade") != "WebSocket" {
- w.WriteHeader(http.StatusBadRequest)
- io.WriteString(w, "missing Upgrade: WebSocket header")
- return
- }
- if req.Header.Get("Connection") != "Upgrade" {
- w.WriteHeader(http.StatusBadRequest)
- io.WriteString(w, "missing Connection: Upgrade header")
- return
- }
- origin := strings.TrimSpace(req.Header.Get("Origin"))
- if origin == "" {
- w.WriteHeader(http.StatusBadRequest)
- io.WriteString(w, "missing Origin header")
- return
- }
-
- rwc, buf, err := w.(http.Hijacker).Hijack()
+ conn, err := newServerConn(rwc, buf, req)
if err != nil {
- panic("Hijack failed: " + err.String())
return
}
- defer rwc.Close()
-
- var location string
- if req.TLS != nil {
- location = "wss://" + req.Host + req.URL.RawPath
- } else {
- location = "ws://" + req.Host + req.URL.RawPath
- }
-
- // TODO(ukai): verify origin,location,protocol.
-
- buf.WriteString("HTTP/1.1 101 Web Socket Protocol Handshake\r\n")
- buf.WriteString("Upgrade: WebSocket\r\n")
- buf.WriteString("Connection: Upgrade\r\n")
- buf.WriteString("WebSocket-Origin: " + origin + "\r\n")
- buf.WriteString("WebSocket-Location: " + location + "\r\n")
- protocol := strings.TrimSpace(req.Header.Get("Websocket-Protocol"))
- // canonical header key of WebSocket-Protocol.
- if protocol != "" {
- buf.WriteString("WebSocket-Protocol: " + protocol + "\r\n")
- }
- buf.WriteString("\r\n")
- if err := buf.Flush(); err != nil {
- return
+ if conn == nil {
+ panic("unepxected nil conn")
}
- ws := newConn(origin, location, protocol, buf, rwc)
- f(ws)
+ h(conn)
}
diff --git a/libgo/go/websocket/websocket.go b/libgo/go/websocket/websocket.go
index 7447cf85215..a3750dde115 100644
--- a/libgo/go/websocket/websocket.go
+++ b/libgo/go/websocket/websocket.go
@@ -2,145 +2,246 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package websocket implements a client and server for the Web Socket protocol.
-// The protocol is defined at http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol
+// Package websocket implements a client and server for the WebSocket protocol.
+// The protocol is defined at http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol
package websocket
-// TODO(ukai):
-// better logging.
-
import (
"bufio"
- "crypto/md5"
- "encoding/binary"
+ "crypto/tls"
"http"
"io"
+ "io/ioutil"
+ "json"
"net"
"os"
+ "sync"
+ "url"
)
-// WebSocketAddr is an implementation of net.Addr for Web Sockets.
-type WebSocketAddr string
+const (
+ ProtocolVersionHixie75 = -75
+ ProtocolVersionHixie76 = -76
+ ProtocolVersionHybi00 = 0
+ ProtocolVersionHybi08 = 8
+ ProtocolVersionHybi13 = 13
+ ProtocolVersionHybi = ProtocolVersionHybi13
+ SupportedProtocolVersion = "13, 8"
+
+ ContinuationFrame = 0
+ TextFrame = 1
+ BinaryFrame = 2
+ CloseFrame = 8
+ PingFrame = 9
+ PongFrame = 10
+ UnknownFrame = 255
+)
-// Network returns the network type for a Web Socket, "websocket".
-func (addr WebSocketAddr) Network() string { return "websocket" }
+// WebSocket protocol errors.
+type ProtocolError struct {
+ ErrorString string
+}
-// String returns the network address for a Web Socket.
-func (addr WebSocketAddr) String() string { return string(addr) }
+func (err *ProtocolError) String() string { return err.ErrorString }
-const (
- stateFrameByte = iota
- stateFrameLength
- stateFrameData
- stateFrameTextData
+var (
+ ErrBadProtocolVersion = &ProtocolError{"bad protocol version"}
+ ErrBadScheme = &ProtocolError{"bad scheme"}
+ ErrBadStatus = &ProtocolError{"bad status"}
+ ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"}
+ ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"}
+ ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"}
+ ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"}
+ ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"}
+ ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"}
+ ErrBadFrame = &ProtocolError{"bad frame"}
+ ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"}
+ ErrNotWebSocket = &ProtocolError{"not websocket protocol"}
+ ErrBadRequestMethod = &ProtocolError{"bad method"}
+ ErrNotSupported = &ProtocolError{"not supported"}
)
-// Conn is a channel to communicate to a Web Socket.
-// It implements the net.Conn interface.
+// Addr is an implementation of net.Addr for WebSocket.
+type Addr struct {
+ *url.URL
+}
+
+// Network returns the network type for a WebSocket, "websocket".
+func (addr *Addr) Network() string { return "websocket" }
+
+// Config is a WebSocket configuration
+type Config struct {
+ // A WebSocket server address.
+ Location *url.URL
+
+ // A Websocket client origin.
+ Origin *url.URL
+
+ // WebSocket subprotocols.
+ Protocol []string
+
+ // WebSocket protocol version.
+ Version int
+
+ // TLS config for secure WebSocket (wss).
+ TlsConfig *tls.Config
+
+ handshakeData map[string]string
+}
+
+// serverHandshaker is an interface to handle WebSocket server side handshake.
+type serverHandshaker interface {
+ // ReadHandshake reads handshake request message from client.
+ // Returns http response code and error if any.
+ ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err os.Error)
+
+ // AcceptHandshake accepts the client handshake request and sends
+ // handshake response back to client.
+ AcceptHandshake(buf *bufio.Writer) (err os.Error)
+
+ // NewServerConn creates a new WebSocket connection.
+ NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn)
+}
+
+// frameReader is an interface to read a WebSocket frame.
+type frameReader interface {
+ // Reader is to read payload of the frame.
+ io.Reader
+
+ // PayloadType returns payload type.
+ PayloadType() byte
+
+ // HeaderReader returns a reader to read header of the frame.
+ HeaderReader() io.Reader
+
+ // TrailerReader returns a reader to read trailer of the frame.
+ // If it returns nil, there is no trailer in the frame.
+ TrailerReader() io.Reader
+
+ // Len returns total length of the frame, including header and trailer.
+ Len() int
+}
+
+// frameReaderFactory is an interface to creates new frame reader.
+type frameReaderFactory interface {
+ NewFrameReader() (r frameReader, err os.Error)
+}
+
+// frameWriter is an interface to write a WebSocket frame.
+type frameWriter interface {
+ // Writer is to write playload of the frame.
+ io.WriteCloser
+}
+
+// frameWriterFactory is an interface to create new frame writer.
+type frameWriterFactory interface {
+ NewFrameWriter(payloadType byte) (w frameWriter, err os.Error)
+}
+
+type frameHandler interface {
+ HandleFrame(frame frameReader) (r frameReader, err os.Error)
+ WriteClose(status int) (err os.Error)
+}
+
+// Conn represents a WebSocket connection.
type Conn struct {
- // The origin URI for the Web Socket.
- Origin string
- // The location URI for the Web Socket.
- Location string
- // The subprotocol for the Web Socket.
- Protocol string
- // The initial http Request (for the Server side only).
- Request *http.Request
+ config *Config
+ request *http.Request
buf *bufio.ReadWriter
rwc io.ReadWriteCloser
- // It holds text data in previous Read() that failed with small buffer.
- data []byte
- reading bool
-}
+ rio sync.Mutex
+ frameReaderFactory
+ frameReader
-// newConn creates a new Web Socket.
-func newConn(origin, location, protocol string, buf *bufio.ReadWriter, rwc io.ReadWriteCloser) *Conn {
- if buf == nil {
- br := bufio.NewReader(rwc)
- bw := bufio.NewWriter(rwc)
- buf = bufio.NewReadWriter(br, bw)
- }
- ws := &Conn{Origin: origin, Location: location, Protocol: protocol, buf: buf, rwc: rwc}
- return ws
+ wio sync.Mutex
+ frameWriterFactory
+
+ frameHandler
+ PayloadType byte
+ defaultCloseStatus int
}
-// Read implements the io.Reader interface for a Conn.
+// Read implements the io.Reader interface:
+// it reads data of a frame from the WebSocket connection.
+// if msg is not large enough for the frame data, it fills the msg and next Read
+// will read the rest of the frame data.
+// it reads Text frame or Binary frame.
func (ws *Conn) Read(msg []byte) (n int, err os.Error) {
-Frame:
- for !ws.reading && len(ws.data) == 0 {
- // Beginning of frame, possibly.
- b, err := ws.buf.ReadByte()
+ ws.rio.Lock()
+ defer ws.rio.Unlock()
+again:
+ if ws.frameReader == nil {
+ frame, err := ws.frameReaderFactory.NewFrameReader()
if err != nil {
return 0, err
}
- if b&0x80 == 0x80 {
- // Skip length frame.
- length := 0
- for {
- c, err := ws.buf.ReadByte()
- if err != nil {
- return 0, err
- }
- length = length*128 + int(c&0x7f)
- if c&0x80 == 0 {
- break
- }
- }
- for length > 0 {
- _, err := ws.buf.ReadByte()
- if err != nil {
- return 0, err
- }
- }
- continue Frame
+ ws.frameReader, err = ws.frameHandler.HandleFrame(frame)
+ if err != nil {
+ return 0, err
}
- // In text mode
- if b != 0 {
- // Skip this frame
- for {
- c, err := ws.buf.ReadByte()
- if err != nil {
- return 0, err
- }
- if c == '\xff' {
- break
- }
- }
- continue Frame
+ if ws.frameReader == nil {
+ goto again
}
- ws.reading = true
}
- if len(ws.data) == 0 {
- ws.data, err = ws.buf.ReadSlice('\xff')
- if err == nil {
- ws.reading = false
- ws.data = ws.data[:len(ws.data)-1] // trim \xff
+ n, err = ws.frameReader.Read(msg)
+ if err == os.EOF {
+ if trailer := ws.frameReader.TrailerReader(); trailer != nil {
+ io.Copy(ioutil.Discard, trailer)
}
+ ws.frameReader = nil
+ goto again
}
- n = copy(msg, ws.data)
- ws.data = ws.data[n:]
return n, err
}
-// Write implements the io.Writer interface for a Conn.
+// Write implements the io.Writer interface:
+// it writes data as a frame to the WebSocket connection.
func (ws *Conn) Write(msg []byte) (n int, err os.Error) {
- ws.buf.WriteByte(0)
- ws.buf.Write(msg)
- ws.buf.WriteByte(0xff)
- err = ws.buf.Flush()
- return len(msg), err
+ ws.wio.Lock()
+ defer ws.wio.Unlock()
+ w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType)
+ if err != nil {
+ return 0, err
+ }
+ n, err = w.Write(msg)
+ w.Close()
+ if err != nil {
+ return n, err
+ }
+ return n, err
+}
+
+// Close implements the io.Closer interface.
+func (ws *Conn) Close() os.Error {
+ err := ws.frameHandler.WriteClose(ws.defaultCloseStatus)
+ if err != nil {
+ return err
+ }
+ return ws.rwc.Close()
}
-// Close implements the io.Closer interface for a Conn.
-func (ws *Conn) Close() os.Error { return ws.rwc.Close() }
+func (ws *Conn) IsClientConn() bool { return ws.request == nil }
+func (ws *Conn) IsServerConn() bool { return ws.request != nil }
-// LocalAddr returns the WebSocket Origin for the connection.
-func (ws *Conn) LocalAddr() net.Addr { return WebSocketAddr(ws.Origin) }
+// LocalAddr returns the WebSocket Origin for the connection for client, or
+// the WebSocket location for server.
+func (ws *Conn) LocalAddr() net.Addr {
+ if ws.IsClientConn() {
+ return &Addr{ws.config.Origin}
+ }
+ return &Addr{ws.config.Location}
+}
-// RemoteAddr returns the WebSocket locations for the connection.
-func (ws *Conn) RemoteAddr() net.Addr { return WebSocketAddr(ws.Location) }
+// RemoteAddr returns the WebSocket location for the connection for client, or
+// the Websocket Origin for server.
+func (ws *Conn) RemoteAddr() net.Addr {
+ if ws.IsClientConn() {
+ return &Addr{ws.config.Location}
+ }
+ return &Addr{ws.config.Origin}
+}
// SetTimeout sets the connection's network timeout in nanoseconds.
func (ws *Conn) SetTimeout(nsec int64) os.Error {
@@ -166,27 +267,143 @@ func (ws *Conn) SetWriteTimeout(nsec int64) os.Error {
return os.EINVAL
}
-// getChallengeResponse computes the expected response from the
-// challenge as described in section 5.1 Opening Handshake steps 42 to
-// 43 of http://www.whatwg.org/specs/web-socket-protocol/
-func getChallengeResponse(number1, number2 uint32, key3 []byte) (expected []byte, err os.Error) {
- // 41. Let /challenge/ be the concatenation of /number_1/, expressed
- // a big-endian 32 bit integer, /number_2/, expressed in a big-
- // endian 32 bit integer, and the eight bytes of /key_3/ in the
- // order they were sent to the wire.
- challenge := make([]byte, 16)
- binary.BigEndian.PutUint32(challenge[0:], number1)
- binary.BigEndian.PutUint32(challenge[4:], number2)
- copy(challenge[8:], key3)
+// Config returns the WebSocket config.
+func (ws *Conn) Config() *Config { return ws.config }
+
+// Request returns the http request upgraded to the WebSocket.
+// It is nil for client side.
+func (ws *Conn) Request() *http.Request { return ws.request }
+
+// Codec represents a symmetric pair of functions that implement a codec.
+type Codec struct {
+ Marshal func(v interface{}) (data []byte, payloadType byte, err os.Error)
+ Unmarshal func(data []byte, payloadType byte, v interface{}) (err os.Error)
+}
+
+// Send sends v marshaled by cd.Marshal as single frame to ws.
+func (cd Codec) Send(ws *Conn, v interface{}) (err os.Error) {
+ if err != nil {
+ return err
+ }
+ data, payloadType, err := cd.Marshal(v)
+ if err != nil {
+ return err
+ }
+ ws.wio.Lock()
+ defer ws.wio.Unlock()
+ w, err := ws.frameWriterFactory.NewFrameWriter(payloadType)
+ _, err = w.Write(data)
+ w.Close()
+ return err
+}
+
+// Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v.
+func (cd Codec) Receive(ws *Conn, v interface{}) (err os.Error) {
+ ws.rio.Lock()
+ defer ws.rio.Unlock()
+ if ws.frameReader != nil {
+ _, err = io.Copy(ioutil.Discard, ws.frameReader)
+ if err != nil {
+ return err
+ }
+ ws.frameReader = nil
+ }
+again:
+ frame, err := ws.frameReaderFactory.NewFrameReader()
+ if err != nil {
+ return err
+ }
+ frame, err = ws.frameHandler.HandleFrame(frame)
+ if err != nil {
+ return err
+ }
+ if frame == nil {
+ goto again
+ }
+ payloadType := frame.PayloadType()
+ data, err := ioutil.ReadAll(frame)
+ if err != nil {
+ return err
+ }
+ return cd.Unmarshal(data, payloadType, v)
+}
- // 42. Let /expected/ be the MD5 fingerprint of /challenge/ as a big-
- // endian 128 bit string.
- h := md5.New()
- if _, err = h.Write(challenge); err != nil {
- return
+func marshal(v interface{}) (msg []byte, payloadType byte, err os.Error) {
+ switch data := v.(type) {
+ case string:
+ return []byte(data), TextFrame, nil
+ case []byte:
+ return data, BinaryFrame, nil
}
- expected = h.Sum()
- return
+ return nil, UnknownFrame, ErrNotSupported
}
-var _ net.Conn = (*Conn)(nil) // compile-time check that *Conn implements net.Conn.
+func unmarshal(msg []byte, payloadType byte, v interface{}) (err os.Error) {
+ switch data := v.(type) {
+ case *string:
+ *data = string(msg)
+ return nil
+ case *[]byte:
+ *data = msg
+ return nil
+ }
+ return ErrNotSupported
+}
+
+/*
+Message is a codec to send/receive text/binary data in a frame on WebSocket connection.
+To send/receive text frame, use string type.
+To send/receive binary frame, use []byte type.
+
+Trivial usage:
+
+ import "websocket"
+
+ // receive text frame
+ var message string
+ websocket.Message.Receive(ws, &message)
+
+ // send text frame
+ message = "hello"
+ websocket.Message.Send(ws, message)
+
+ // receive binary frame
+ var data []byte
+ websocket.Message.Receive(ws, &data)
+
+ // send binary frame
+ data = []byte{0, 1, 2}
+ websocket.Message.Send(ws, data)
+
+*/
+var Message = Codec{marshal, unmarshal}
+
+func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err os.Error) {
+ msg, err = json.Marshal(v)
+ return msg, TextFrame, err
+}
+
+func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err os.Error) {
+ return json.Unmarshal(msg, v)
+}
+
+/*
+JSON is a codec to send/receive JSON data in a frame from a WebSocket connection.
+
+Trival usage:
+
+ import "websocket"
+
+ type T struct {
+ Msg string
+ Count int
+ }
+
+ // receive JSON type T
+ var data T
+ websocket.JSON.Receive(ws, &data)
+
+ // send JSON type T
+ websocket.JSON.Send(ws, data)
+*/
+var JSON = Codec{jsonMarshal, jsonUnmarshal}
diff --git a/libgo/go/websocket/websocket_test.go b/libgo/go/websocket/websocket_test.go
index 71c3c8514b7..240af4e49bb 100644
--- a/libgo/go/websocket/websocket_test.go
+++ b/libgo/go/websocket/websocket_test.go
@@ -5,7 +5,6 @@
package websocket
import (
- "bufio"
"bytes"
"fmt"
"http"
@@ -13,6 +12,7 @@ import (
"io"
"log"
"net"
+ "strings"
"sync"
"testing"
"url"
@@ -23,31 +23,38 @@ var once sync.Once
func echoServer(ws *Conn) { io.Copy(ws, ws) }
+type Count struct {
+ S string
+ N int
+}
+
+func countServer(ws *Conn) {
+ for {
+ var count Count
+ err := JSON.Receive(ws, &count)
+ if err != nil {
+ return
+ }
+ count.N++
+ count.S = strings.Repeat(count.S, count.N)
+ err = JSON.Send(ws, count)
+ if err != nil {
+ return
+ }
+ }
+}
+
func startServer() {
http.Handle("/echo", Handler(echoServer))
- http.Handle("/echoDraft75", Draft75Handler(echoServer))
+ http.Handle("/count", Handler(countServer))
server := httptest.NewServer(nil)
serverAddr = server.Listener.Addr().String()
log.Print("Test WebSocket server listening on ", serverAddr)
}
-// Test the getChallengeResponse function with values from section
-// 5.1 of the specification steps 18, 26, and 43 from
-// http://www.whatwg.org/specs/web-socket-protocol/
-func TestChallenge(t *testing.T) {
- var part1 uint32 = 777007543
- var part2 uint32 = 114997259
- key3 := []byte{0x47, 0x30, 0x22, 0x2D, 0x5A, 0x3F, 0x47, 0x58}
- expected := []byte("0st3Rl&q-2ZU^weu")
-
- response, err := getChallengeResponse(part1, part2, key3)
- if err != nil {
- t.Errorf("getChallengeResponse: returned error %v", err)
- return
- }
- if !bytes.Equal(expected, response) {
- t.Errorf("getChallengeResponse: expected %q got %q", expected, response)
- }
+func newConfig(t *testing.T, path string) *Config {
+ config, _ := NewConfig(fmt.Sprintf("ws://%s%s", serverAddr, path), "http://localhost")
+ return config
}
func TestEcho(t *testing.T) {
@@ -58,19 +65,18 @@ func TestEcho(t *testing.T) {
if err != nil {
t.Fatal("dialing", err)
}
- ws, err := newClient("/echo", "localhost", "http://localhost",
- "ws://localhost/echo", "", client, handshake)
+ conn, err := NewClient(newConfig(t, "/echo"), client)
if err != nil {
t.Errorf("WebSocket handshake error: %v", err)
return
}
msg := []byte("hello, world\n")
- if _, err := ws.Write(msg); err != nil {
+ if _, err := conn.Write(msg); err != nil {
t.Errorf("Write: %v", err)
}
var actual_msg = make([]byte, 512)
- n, err := ws.Read(actual_msg)
+ n, err := conn.Read(actual_msg)
if err != nil {
t.Errorf("Read: %v", err)
}
@@ -78,10 +84,10 @@ func TestEcho(t *testing.T) {
if !bytes.Equal(msg, actual_msg) {
t.Errorf("Echo: expected %q got %q", msg, actual_msg)
}
- ws.Close()
+ conn.Close()
}
-func TestEchoDraft75(t *testing.T) {
+func TestAddr(t *testing.T) {
once.Do(startServer)
// websocket.Dial()
@@ -89,27 +95,64 @@ func TestEchoDraft75(t *testing.T) {
if err != nil {
t.Fatal("dialing", err)
}
- ws, err := newClient("/echoDraft75", "localhost", "http://localhost",
- "ws://localhost/echoDraft75", "", client, draft75handshake)
+ conn, err := NewClient(newConfig(t, "/echo"), client)
if err != nil {
- t.Errorf("WebSocket handshake: %v", err)
+ t.Errorf("WebSocket handshake error: %v", err)
return
}
- msg := []byte("hello, world\n")
- if _, err := ws.Write(msg); err != nil {
- t.Errorf("Write: error %v", err)
+ ra := conn.RemoteAddr().String()
+ if !strings.HasPrefix(ra, "ws://") || !strings.HasSuffix(ra, "/echo") {
+ t.Errorf("Bad remote addr: %v", ra)
}
- var actual_msg = make([]byte, 512)
- n, err := ws.Read(actual_msg)
+ la := conn.LocalAddr().String()
+ if !strings.HasPrefix(la, "http://") {
+ t.Errorf("Bad local addr: %v", la)
+ }
+ conn.Close()
+}
+
+func TestCount(t *testing.T) {
+ once.Do(startServer)
+
+ // websocket.Dial()
+ client, err := net.Dial("tcp", serverAddr)
if err != nil {
- t.Errorf("Read: error %v", err)
+ t.Fatal("dialing", err)
}
- actual_msg = actual_msg[0:n]
- if !bytes.Equal(msg, actual_msg) {
- t.Errorf("Echo: expected %q got %q", msg, actual_msg)
+ conn, err := NewClient(newConfig(t, "/count"), client)
+ if err != nil {
+ t.Errorf("WebSocket handshake error: %v", err)
+ return
}
- ws.Close()
+
+ var count Count
+ count.S = "hello"
+ if err := JSON.Send(conn, count); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ if err := JSON.Receive(conn, &count); err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if count.N != 1 {
+ t.Errorf("count: expected %d got %d", 1, count.N)
+ }
+ if count.S != "hello" {
+ t.Errorf("count: expected %q got %q", "hello", count.S)
+ }
+ if err := JSON.Send(conn, count); err != nil {
+ t.Errorf("Write: %v", err)
+ }
+ if err := JSON.Receive(conn, &count); err != nil {
+ t.Errorf("Read: %v", err)
+ }
+ if count.N != 2 {
+ t.Errorf("count: expected %d got %d", 2, count.N)
+ }
+ if count.S != "hellohello" {
+ t.Errorf("count: expected %q got %q", "hellohello", count.S)
+ }
+ conn.Close()
}
func TestWithQuery(t *testing.T) {
@@ -120,8 +163,13 @@ func TestWithQuery(t *testing.T) {
t.Fatal("dialing", err)
}
- ws, err := newClient("/echo?q=v", "localhost", "http://localhost",
- "ws://localhost/echo?q=v", "", client, handshake)
+ config := newConfig(t, "/echo")
+ config.Location, err = url.ParseRequest(fmt.Sprintf("ws://%s/echo?q=v", serverAddr))
+ if err != nil {
+ t.Fatal("location url", err)
+ }
+
+ ws, err := NewClient(config, client)
if err != nil {
t.Errorf("WebSocket handshake: %v", err)
return
@@ -137,8 +185,10 @@ func TestWithProtocol(t *testing.T) {
t.Fatal("dialing", err)
}
- ws, err := newClient("/echo", "localhost", "http://localhost",
- "ws://localhost/echo", "test", client, handshake)
+ config := newConfig(t, "/echo")
+ config.Protocol = append(config.Protocol, "test")
+
+ ws, err := NewClient(config, client)
if err != nil {
t.Errorf("WebSocket handshake: %v", err)
return
@@ -167,29 +217,17 @@ func TestHTTP(t *testing.T) {
}
}
-func TestHTTPDraft75(t *testing.T) {
- once.Do(startServer)
-
- r, err := http.Get(fmt.Sprintf("http://%s/echoDraft75", serverAddr))
- if err != nil {
- t.Errorf("Get: error %#v", err)
- return
- }
- if r.StatusCode != http.StatusBadRequest {
- t.Errorf("Get: got status %d", r.StatusCode)
- }
-}
-
func TestTrailingSpaces(t *testing.T) {
// http://code.google.com/p/go/issues/detail?id=955
// The last runs of this create keys with trailing spaces that should not be
// generated by the client.
once.Do(startServer)
+ config := newConfig(t, "/echo")
for i := 0; i < 30; i++ {
// body
- ws, err := Dial(fmt.Sprintf("ws://%s/echo", serverAddr), "", "http://localhost/")
+ ws, err := DialConfig(config)
if err != nil {
- t.Error("Dial failed:", err.String())
+ t.Errorf("Dial #%d failed: %v", i, err)
break
}
ws.Close()
@@ -206,19 +244,18 @@ func TestSmallBuffer(t *testing.T) {
if err != nil {
t.Fatal("dialing", err)
}
- ws, err := newClient("/echo", "localhost", "http://localhost",
- "ws://localhost/echo", "", client, handshake)
+ conn, err := NewClient(newConfig(t, "/echo"), client)
if err != nil {
t.Errorf("WebSocket handshake error: %v", err)
return
}
msg := []byte("hello, world\n")
- if _, err := ws.Write(msg); err != nil {
+ if _, err := conn.Write(msg); err != nil {
t.Errorf("Write: %v", err)
}
var small_msg = make([]byte, 8)
- n, err := ws.Read(small_msg)
+ n, err := conn.Read(small_msg)
if err != nil {
t.Errorf("Read: %v", err)
}
@@ -226,7 +263,7 @@ func TestSmallBuffer(t *testing.T) {
t.Errorf("Echo: expected %q got %q", msg[:len(small_msg)], small_msg)
}
var second_msg = make([]byte, len(msg))
- n, err = ws.Read(second_msg)
+ n, err = conn.Read(second_msg)
if err != nil {
t.Errorf("Read: %v", err)
}
@@ -234,38 +271,5 @@ func TestSmallBuffer(t *testing.T) {
if !bytes.Equal(msg[len(small_msg):], second_msg) {
t.Errorf("Echo: expected %q got %q", msg[len(small_msg):], second_msg)
}
- ws.Close()
-
-}
-
-func testSkipLengthFrame(t *testing.T) {
- b := []byte{'\x80', '\x01', 'x', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
- buf := bytes.NewBuffer(b)
- br := bufio.NewReader(buf)
- bw := bufio.NewWriter(buf)
- ws := newConn("http://127.0.0.1/", "ws://127.0.0.1/", "", bufio.NewReadWriter(br, bw), nil)
- msg := make([]byte, 5)
- n, err := ws.Read(msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- if !bytes.Equal(b[4:8], msg[0:n]) {
- t.Errorf("Read: expected %q got %q", msg[4:8], msg[0:n])
- }
-}
-
-func testSkipNoUTF8Frame(t *testing.T) {
- b := []byte{'\x01', 'n', '\xff', 0, 'h', 'e', 'l', 'l', 'o', '\xff'}
- buf := bytes.NewBuffer(b)
- br := bufio.NewReader(buf)
- bw := bufio.NewWriter(buf)
- ws := newConn("http://127.0.0.1/", "ws://127.0.0.1/", "", bufio.NewReadWriter(br, bw), nil)
- msg := make([]byte, 5)
- n, err := ws.Read(msg)
- if err != nil {
- t.Errorf("Read: %v", err)
- }
- if !bytes.Equal(b[4:8], msg[0:n]) {
- t.Errorf("Read: expected %q got %q", msg[4:8], msg[0:n])
- }
+ conn.Close()
}
diff --git a/libgo/go/xml/marshal.go b/libgo/go/xml/marshal.go
index ea421c1b17d..8396dba27e9 100644
--- a/libgo/go/xml/marshal.go
+++ b/libgo/go/xml/marshal.go
@@ -39,10 +39,10 @@ type printer struct {
// Marshal handles a pointer by marshalling the value it points at or, if the
// pointer is nil, by writing nothing. Marshal handles an interface value by
// marshalling the value it contains or, if the interface value is nil, by
-// writing nothing. Marshal handles all other data by writing a single XML
-// element containing the data.
+// writing nothing. Marshal handles all other data by writing one or more XML
+// elements containing the data.
//
-// The name of that XML element is taken from, in order of preference:
+// The name for the XML elements is taken from, in order of preference:
// - the tag on an XMLName field, if the data is a struct
// - the value of an XMLName field of type xml.Name
// - the tag of the struct field used to obtain the data
@@ -58,6 +58,31 @@ type printer struct {
// - a field with tag "innerxml" is written verbatim,
// not subject to the usual marshalling procedure.
//
+// If a field uses a tag "a>b>c", then the element c will be nested inside
+// parent elements a and b. Fields that appear next to each other that name
+// the same parent will be enclosed in one XML element. For example:
+//
+// type Result struct {
+// XMLName xml.Name `xml:"result"`
+// FirstName string `xml:"person>name>first"`
+// LastName string `xml:"person>name>last"`
+// Age int `xml:"person>age"`
+// }
+//
+// xml.Marshal(w, &Result{FirstName: "John", LastName: "Doe", Age: 42})
+//
+// would be marshalled as:
+//
+// <result>
+// <person>
+// <name>
+// <first>John</first>
+// <last>Doe</last>
+// </name>
+// <age>42</age>
+// </person>
+// </result>
+//
// Marshal will return an error if asked to marshal a channel, function, or map.
func Marshal(w io.Writer, v interface{}) (err os.Error) {
p := &printer{bufio.NewWriter(w)}
@@ -170,22 +195,25 @@ func (p *printer) marshalValue(val reflect.Value, name string) os.Error {
bytes := val.Interface().([]byte)
Escape(p, bytes)
case reflect.Struct:
+ s := parentStack{printer: p}
for i, n := 0, val.NumField(); i < n; i++ {
if f := typ.Field(i); f.Name != "XMLName" && f.PkgPath == "" {
name := f.Name
+ vf := val.Field(i)
switch tag := f.Tag.Get("xml"); tag {
case "":
+ s.trim(nil)
case "chardata":
if tk := f.Type.Kind(); tk == reflect.String {
- Escape(p, []byte(val.Field(i).String()))
+ Escape(p, []byte(vf.String()))
} else if tk == reflect.Slice {
- if elem, ok := val.Field(i).Interface().([]byte); ok {
+ if elem, ok := vf.Interface().([]byte); ok {
Escape(p, elem)
}
}
continue
case "innerxml":
- iface := val.Field(i).Interface()
+ iface := vf.Interface()
switch raw := iface.(type) {
case []byte:
p.Write(raw)
@@ -197,14 +225,28 @@ func (p *printer) marshalValue(val reflect.Value, name string) os.Error {
case "attr":
continue
default:
- name = tag
+ parents := strings.Split(tag, ">")
+ if len(parents) == 1 {
+ parents, name = nil, tag
+ } else {
+ parents, name = parents[:len(parents)-1], parents[len(parents)-1]
+ if parents[0] == "" {
+ parents[0] = f.Name
+ }
+ }
+
+ s.trim(parents)
+ if !(vf.Kind() == reflect.Ptr || vf.Kind() == reflect.Interface) || !vf.IsNil() {
+ s.push(parents[len(s.stack):])
+ }
}
- if err := p.marshalValue(val.Field(i), name); err != nil {
+ if err := p.marshalValue(vf, name); err != nil {
return err
}
}
}
+ s.trim(nil)
default:
return &UnsupportedTypeError{typ}
}
@@ -217,6 +259,41 @@ func (p *printer) marshalValue(val reflect.Value, name string) os.Error {
return nil
}
+type parentStack struct {
+ *printer
+ stack []string
+}
+
+// trim updates the XML context to match the longest common prefix of the stack
+// and the given parents. A closing tag will be written for every parent
+// popped. Passing a zero slice or nil will close all the elements.
+func (s *parentStack) trim(parents []string) {
+ split := 0
+ for ; split < len(parents) && split < len(s.stack); split++ {
+ if parents[split] != s.stack[split] {
+ break
+ }
+ }
+
+ for i := len(s.stack) - 1; i >= split; i-- {
+ s.WriteString("</")
+ s.WriteString(s.stack[i])
+ s.WriteByte('>')
+ }
+
+ s.stack = parents[:split]
+}
+
+// push adds parent elements to the stack and writes open tags.
+func (s *parentStack) push(parents []string) {
+ for i := 0; i < len(parents); i++ {
+ s.WriteString("<")
+ s.WriteString(parents[i])
+ s.WriteByte('>')
+ }
+ s.stack = append(s.stack, parents...)
+}
+
// A MarshalXMLError is returned when Marshal or MarshalIndent encounter a type
// that cannot be converted into XML.
type UnsupportedTypeError struct {
diff --git a/libgo/go/xml/marshal_test.go b/libgo/go/xml/marshal_test.go
index 5b972fafe67..ad3aa97e25f 100644
--- a/libgo/go/xml/marshal_test.go
+++ b/libgo/go/xml/marshal_test.go
@@ -69,6 +69,41 @@ type SecretAgent struct {
Obfuscate string `xml:"innerxml"`
}
+type NestedItems struct {
+ XMLName Name `xml:"result"`
+ Items []string `xml:">item"`
+ Item1 []string `xml:"Items>item1"`
+}
+
+type NestedOrder struct {
+ XMLName Name `xml:"result"`
+ Field1 string `xml:"parent>c"`
+ Field2 string `xml:"parent>b"`
+ Field3 string `xml:"parent>a"`
+}
+
+type MixedNested struct {
+ XMLName Name `xml:"result"`
+ A string `xml:"parent1>a"`
+ B string `xml:"b"`
+ C string `xml:"parent1>parent2>c"`
+ D string `xml:"parent1>d"`
+}
+
+type NilTest struct {
+ A interface{} `xml:"parent1>parent2>a"`
+ B interface{} `xml:"parent1>b"`
+ C interface{} `xml:"parent1>parent2>c"`
+}
+
+type Service struct {
+ XMLName Name `xml:"service"`
+ Domain *Domain `xml:"host>domain"`
+ Port *Port `xml:"host>port"`
+ Extra1 interface{}
+ Extra2 interface{} `xml:"host>extra2"`
+}
+
var nilStruct *Ship
var marshalTests = []struct {
@@ -170,6 +205,94 @@ var marshalTests = []struct {
`</passenger>` +
`</spaceship>`,
},
+ // Test a>b
+ {
+ Value: NestedItems{Items: []string{}, Item1: []string{}},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `</Items>` +
+ `</result>`,
+ },
+ {
+ Value: NestedItems{Items: []string{}, Item1: []string{"A"}},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `<item1>A</item1>` +
+ `</Items>` +
+ `</result>`,
+ },
+ {
+ Value: NestedItems{Items: []string{"A", "B"}, Item1: []string{}},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `<item>A</item>` +
+ `<item>B</item>` +
+ `</Items>` +
+ `</result>`,
+ },
+ {
+ Value: NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},
+ ExpectXML: `<result>` +
+ `<Items>` +
+ `<item>A</item>` +
+ `<item>B</item>` +
+ `<item1>C</item1>` +
+ `</Items>` +
+ `</result>`,
+ },
+ {
+ Value: NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
+ ExpectXML: `<result>` +
+ `<parent>` +
+ `<c>C</c>` +
+ `<b>B</b>` +
+ `<a>A</a>` +
+ `</parent>` +
+ `</result>`,
+ },
+ {
+ Value: NilTest{A: "A", B: nil, C: "C"},
+ ExpectXML: `<???>` +
+ `<parent1>` +
+ `<parent2><a>A</a></parent2>` +
+ `<parent2><c>C</c></parent2>` +
+ `</parent1>` +
+ `</???>`,
+ },
+ {
+ Value: MixedNested{A: "A", B: "B", C: "C", D: "D"},
+ ExpectXML: `<result>` +
+ `<parent1><a>A</a></parent1>` +
+ `<b>B</b>` +
+ `<parent1>` +
+ `<parent2><c>C</c></parent2>` +
+ `<d>D</d>` +
+ `</parent1>` +
+ `</result>`,
+ },
+ {
+ Value: Service{Port: &Port{Number: "80"}},
+ ExpectXML: `<service><host><port>80</port></host></service>`,
+ },
+ {
+ Value: Service{},
+ ExpectXML: `<service></service>`,
+ },
+ {
+ Value: Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},
+ ExpectXML: `<service>` +
+ `<host><port>80</port></host>` +
+ `<Extra1>A</Extra1>` +
+ `<host><extra2>B</extra2></host>` +
+ `</service>`,
+ },
+ {
+ Value: Service{Port: &Port{Number: "80"}, Extra2: "example"},
+ ExpectXML: `<service>` +
+ `<host><port>80</port></host>` +
+ `<host><extra2>example</extra2></host>` +
+ `</service>`,
+ },
}
func TestMarshal(t *testing.T) {
diff --git a/libgo/go/xml/read.go b/libgo/go/xml/read.go
index 786b69f5a32..f64e1300189 100644
--- a/libgo/go/xml/read.go
+++ b/libgo/go/xml/read.go
@@ -321,10 +321,9 @@ func (p *Parser) unmarshal(val reflect.Value, start *StartElement) os.Error {
// Save
v := sv.FieldByIndex(f.Index)
- if _, ok := v.Interface().(Name); !ok {
- return UnmarshalError(sv.Type().String() + " field XMLName does not have type xml.Name")
+ if _, ok := v.Interface().(Name); ok {
+ v.Set(reflect.ValueOf(start.Name))
}
- v.Set(reflect.ValueOf(start.Name))
}
// Assign attributes.
diff --git a/libgo/go/xml/read_test.go b/libgo/go/xml/read_test.go
index 2126da3c751..d39c2d52a83 100644
--- a/libgo/go/xml/read_test.go
+++ b/libgo/go/xml/read_test.go
@@ -369,3 +369,25 @@ var attrStruct = AttrTest{
Bool: true,
},
}
+
+// test data for TestUnmarshalWithoutNameType
+
+const OK = "OK"
+const withoutNameTypeData = `
+<?xml version="1.0" charset="utf-8"?>
+<Test3 attr="OK" />`
+
+type TestThree struct {
+ XMLName bool `xml:"Test3"` // XMLName field without an xml.Name type
+ Attr string `xml:"attr"`
+}
+
+func TestUnmarshalWithoutNameType(t *testing.T) {
+ var x TestThree
+ if err := Unmarshal(StringReader(withoutNameTypeData), &x); err != nil {
+ t.Fatalf("Unmarshal: %s", err)
+ }
+ if x.Attr != OK {
+ t.Fatalf("have %v\nwant %v", x.Attr, OK)
+ }
+}
diff --git a/libgo/go/xml/xml.go b/libgo/go/xml/xml.go
index e7ba44e4a26..85c24bc4503 100644
--- a/libgo/go/xml/xml.go
+++ b/libgo/go/xml/xml.go
@@ -390,7 +390,11 @@ func (p *Parser) popElement(t *EndElement) bool {
// translations that were associated with the element we just closed.
for p.stk != nil && p.stk.kind != stkStart {
s := p.pop()
- p.ns[s.name.Local] = s.name.Space, s.ok
+ if s.ok {
+ p.ns[s.name.Local] = s.name.Space
+ } else {
+ delete(p.ns, s.name.Local)
+ }
}
return true
diff --git a/libgo/merge.sh b/libgo/merge.sh
index 59e1df2018f..660a5f90063 100755
--- a/libgo/merge.sh
+++ b/libgo/merge.sh
@@ -38,9 +38,9 @@ rm -rf ${OLDDIR}
hg clone -r ${old_rev} ${repository} ${OLDDIR}
rm -rf ${NEWDIR}
-hg clone -u release ${repository} ${NEWDIR}
+hg clone -u weekly ${repository} ${NEWDIR}
-new_rev=`cd ${NEWDIR} && hg log -r release | sed 1q | sed -e 's/.*://'`
+new_rev=`cd ${NEWDIR} && hg log -r weekly | sed 1q | sed -e 's/.*://'`
merge() {
name=$1
diff --git a/libgo/mksysinfo.sh b/libgo/mksysinfo.sh
index f959d640fdc..e493ef072c1 100755
--- a/libgo/mksysinfo.sh
+++ b/libgo/mksysinfo.sh
@@ -197,16 +197,13 @@ if ! grep '^const EPOLLRDHUP' ${OUT} >/dev/null 2>&1; then
echo "const EPOLLRDHUP = 0x2000" >> ${OUT}
fi
-# Ptrace constants. We don't expose all the PTRACE flags, just the
-# PTRACE_O_xxx and PTRACE_EVENT_xxx ones.
-grep '^const _PTRACE_O' gen-sysinfo.go |
- sed -e 's/^\(const \)_\(PTRACE_O[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
-grep '^const _PTRACE_EVENT' gen-sysinfo.go |
- sed -e 's/^\(const \)_\(PTRACE_EVENT[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
-# We need PTRACE_SETOPTIONS and PTRACE_GETEVENTMSG, but they are not
-# defined in older versions of glibc.
-if ! grep '^const _PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
- echo "const _PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
+# Ptrace constants.
+grep '^const _PTRACE' gen-sysinfo.go |
+ sed -e 's/^\(const \)_\(PTRACE[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+# We need some ptrace options that are not defined in older versions
+# of glibc.
+if ! grep '^const PTRACE_SETOPTIONS' ${OUT} > /dev/null 2>&1; then
+ echo "const PTRACE_SETOPTIONS = 0x4200" >> ${OUT}
fi
if ! grep '^const PTRACE_O_TRACESYSGOOD' ${OUT} > /dev/null 2>&1; then
echo "const PTRACE_O_TRACESYSGOOD = 0x1" >> ${OUT}
@@ -466,7 +463,7 @@ echo $msghdr | \
-e 's/msg_flags/Flags/' \
>> ${OUT}
-# The ip_mreq struct
+# The ip_mreq struct.
grep '^type _ip_mreq ' gen-sysinfo.go | \
sed -e 's/_ip_mreq/IPMreq/' \
-e 's/imr_multiaddr/Multiaddr/' \
@@ -474,6 +471,19 @@ grep '^type _ip_mreq ' gen-sysinfo.go | \
-e 's/_in_addr/[4]byte/g' \
>> ${OUT}
+# The size of the ip_mreq struct.
+if grep 'type IPMreq ' ${OUT} > /dev/null 2>&1; then
+ echo 'var SizeofIPMreq = int(unsafe.Sizeof(IPMreq{}))' >> ${OUT}
+fi
+
+# The ipv6_mreq struct.
+grep '^type _ipv6_mreq ' gen-sysinfo.go | \
+ sed -e 's/_ipv6_mreq/IPv6Mreq/' \
+ -e 's/ipv6mr_multiaddr/Multiaddr/' \
+ -e 's/ipv6mr_interface/Interface/' \
+ -e 's/_in6_addr/[16]byte/' \
+ >> ${OUT}
+
# Try to guess the type to use for fd_set.
fd_set=`grep '^type _fd_set ' gen-sysinfo.go || true`
fds_bits_type="_C_long"
@@ -502,6 +512,10 @@ grep '^type _passwd ' gen-sysinfo.go | \
grep '^const _TIOC' gen-sysinfo.go | \
sed -e 's/^\(const \)_\(TIOC[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+# The ioctl flags for terminal control
+grep '^const _TC[GS]ET' gen-sysinfo.go | \
+ sed -e 's/^\(const \)_\(TC[GS]ET[^= ]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+
# ioctl constants. Might fall back to 0 if TIOCNXCL is missing, too, but
# needs handling in syscalls.exec.go.
if ! grep '^const _TIOCSCTTY ' gen-sysinfo.go >/dev/null 2>&1; then
@@ -531,6 +545,25 @@ if ! grep '^const NLMSG_HDRLEN' ${OUT} > /dev/null 2>&1; then
fi
fi
+# The rtmsg struct.
+grep '^type _rtmsg ' gen-sysinfo.go | \
+ sed -e 's/_rtmsg/RtMsg/' \
+ -e 's/rtm_family/Family/' \
+ -e 's/rtm_dst_len/Dst_len/' \
+ -e 's/rtm_src_len/Src_len/' \
+ -e 's/rtm_tos/Tos/' \
+ -e 's/rtm_table/Table/' \
+ -e 's/rtm_protocol/Procotol/' \
+ -e 's/rtm_scope/Scope/' \
+ -e 's/rtm_type/Type/' \
+ -e 's/rtm_flags/Flags/' \
+ >> ${OUT}
+
+# The size of the rtmsg struct.
+if grep 'type RtMsg ' ${OUT} > /dev/null 2>&1; then
+ echo 'var SizeofRtMsg = int(unsafe.Sizeof(RtMsg{}))' >> ${OUT}
+fi
+
# The rtgenmsg struct.
grep '^type _rtgenmsg ' gen-sysinfo.go | \
sed -e 's/_rtgenmsg/RtGenmsg/' \
@@ -598,4 +631,33 @@ if grep 'type RtAttr ' ${OUT} > /dev/null 2>&1; then
echo 'var SizeofRtAttr = int(unsafe.Sizeof(RtAttr{}))' >> ${OUT}
fi
+# The termios struct.
+grep '^type _termios ' gen-sysinfo.go | \
+ sed -e 's/_termios/Termios/' \
+ -e 's/c_iflag/Iflag/' \
+ -e 's/c_oflag/Oflag/' \
+ -e 's/c_cflag/Cflag/' \
+ -e 's/c_lflag/Lflag/' \
+ -e 's/c_line/Line/' \
+ -e 's/c_cc/Cc/' \
+ -e 's/c_ispeed/Ispeed/' \
+ -e 's/c_ospeed/Ospeed/' \
+ >> ${OUT}
+
+# The termios constants. The ones starting with 'E' were picked up above.
+for n in IGNBRK BRKINT IGNPAR PARMRK INPCK ISTRIP INLCR IGNCR ICRNL IUCLC \
+ IXON IXANY IXOFF IMAXBEL IUTF8 OPOST OLCUC ONLCR OCRNL ONOCR ONLRET \
+ OFILL OFDEL NLDLY NL0 NL1 CRDLY CR0 CR1 CR2 CR3 TABDLY BSDLY VTDLY \
+ FFDLY CBAUD CBAUDEX CSIZE CSTOPB CREAD PARENB PARODD HUPCL CLOCAL \
+ LOBLK CIBAUD CMSPAR CRTSCTS ISIG ICANON XCASE DEFECHK FLUSHO NOFLSH \
+ TOSTOP PENDIN IEXTEN VINTR VQUIT VERASE VKILL VEOF VMIN VEOL VTIME VEOL2 \
+ VSWTCH VSTART VSTOP VSUSP VDSUSP VLNEXT VWERASE VREPRINT VDISCARD VSTATUS \
+ TCSANOW TCSADRAIN, TCSAFLUSH TCIFLUSH TCOFLUSH TCIOFLUSH TCOOFF TCOON \
+ TCIOFF TCION B0 B50 B75 B110 B134 B150 B200 B300 B600 B1200 B1800 B2400 \
+ B4800 B9600 B19200 B38400 B57600 B115200 B230400; do
+
+ grep "^const _$n " gen-sysinfo.go | \
+ sed -e 's/^\(const \)_\([^=]*\)\(.*\)$/\1\2 = _\2/' >> ${OUT}
+done
+
exit $?
diff --git a/libgo/runtime/arch.h b/libgo/runtime/arch.h
new file mode 100644
index 00000000000..0546a5da160
--- /dev/null
+++ b/libgo/runtime/arch.h
@@ -0,0 +1,8 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// FIXME: Ideally CacheLineSize would be dependent on the host architecture.
+enum {
+ CacheLineSize = 64
+};
diff --git a/libgo/runtime/cpuprof.c b/libgo/runtime/cpuprof.c
index 3797e1ce1e0..bec15ae8ce6 100644
--- a/libgo/runtime/cpuprof.c
+++ b/libgo/runtime/cpuprof.c
@@ -49,6 +49,7 @@
// in the situation when normally the goroutine "owns" handoff.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
#include "array.h"
diff --git a/libgo/runtime/go-append.c b/libgo/runtime/go-append.c
index 261d85b5ba9..b1e882cc575 100644
--- a/libgo/runtime/go-append.c
+++ b/libgo/runtime/go-append.c
@@ -8,6 +8,7 @@
#include "go-panic.h"
#include "array.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
/* We should be OK if we don't split the stack here, since the only
diff --git a/libgo/runtime/go-byte-array-to-string.c b/libgo/runtime/go-byte-array-to-string.c
index ab9e28388bc..cfe19061212 100644
--- a/libgo/runtime/go-byte-array-to-string.c
+++ b/libgo/runtime/go-byte-array-to-string.c
@@ -6,6 +6,7 @@
#include "go-string.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
struct __go_string
diff --git a/libgo/runtime/go-close.c b/libgo/runtime/go-close.c
index 44533ebe4c7..778eab3d7d8 100644
--- a/libgo/runtime/go-close.c
+++ b/libgo/runtime/go-close.c
@@ -16,6 +16,9 @@ __go_builtin_close (struct __go_channel *channel)
{
int i;
+ if (channel == NULL)
+ __go_panic_msg ("close of nil channel");
+
i = pthread_mutex_lock (&channel->lock);
__go_assert (i == 0);
diff --git a/libgo/runtime/go-go.c b/libgo/runtime/go-go.c
index 139162056b8..d56b8b16397 100644
--- a/libgo/runtime/go-go.c
+++ b/libgo/runtime/go-go.c
@@ -17,6 +17,7 @@
#include "go-panic.h"
#include "go-alloc.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
#ifdef USING_SPLIT_STACK
@@ -561,7 +562,7 @@ __go_cachestats (void)
/* Start the other threads after garbage collection. */
void
-runtime_starttheworld (void)
+runtime_starttheworld (bool extra __attribute__ ((unused)))
{
int i;
pthread_t me;
diff --git a/libgo/runtime/go-int-array-to-string.c b/libgo/runtime/go-int-array-to-string.c
index ec07b873907..1a37879f312 100644
--- a/libgo/runtime/go-int-array-to-string.c
+++ b/libgo/runtime/go-int-array-to-string.c
@@ -7,6 +7,7 @@
#include "go-assert.h"
#include "go-string.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
struct __go_string
diff --git a/libgo/runtime/go-int-to-string.c b/libgo/runtime/go-int-to-string.c
index af58015ed8f..e9645bf98fe 100644
--- a/libgo/runtime/go-int-to-string.c
+++ b/libgo/runtime/go-int-to-string.c
@@ -6,6 +6,7 @@
#include "go-string.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
struct __go_string
diff --git a/libgo/runtime/go-main.c b/libgo/runtime/go-main.c
index 37956d5de7d..927a36ce028 100644
--- a/libgo/runtime/go-main.c
+++ b/libgo/runtime/go-main.c
@@ -19,6 +19,7 @@
#include "go-string.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
#undef int
diff --git a/libgo/runtime/go-make-slice.c b/libgo/runtime/go-make-slice.c
index d0e8369c1f6..a818a7f76d9 100644
--- a/libgo/runtime/go-make-slice.c
+++ b/libgo/runtime/go-make-slice.c
@@ -12,6 +12,7 @@
#include "go-type.h"
#include "array.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
struct __go_open_array
diff --git a/libgo/runtime/go-map-delete.c b/libgo/runtime/go-map-delete.c
index 9b19ff19df4..a8f928f0c9a 100644
--- a/libgo/runtime/go-map-delete.c
+++ b/libgo/runtime/go-map-delete.c
@@ -27,7 +27,7 @@ __go_map_delete (struct __go_map *map, const void *key)
void **pentry;
if (map == NULL)
- __go_panic_msg ("assignment to entry in nil map");
+ __go_panic_msg ("deletion of entry in nil map");
descriptor = map->__descriptor;
diff --git a/libgo/runtime/go-new.c b/libgo/runtime/go-new.c
index 657978c30a8..b1af5f22473 100644
--- a/libgo/runtime/go-new.c
+++ b/libgo/runtime/go-new.c
@@ -6,6 +6,7 @@
#include "go-alloc.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
void *
diff --git a/libgo/runtime/go-note.c b/libgo/runtime/go-note.c
index 2b80b9b1221..62c229fa0d9 100644
--- a/libgo/runtime/go-note.c
+++ b/libgo/runtime/go-note.c
@@ -12,7 +12,7 @@
#include "runtime.h"
/* We use a single global lock and condition variable. It would be
- better to use a futex on Linux. */
+ better to use a futex on GNU/Linux. */
static pthread_mutex_t note_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t note_cond = PTHREAD_COND_INITIALIZER;
diff --git a/libgo/runtime/go-panic.c b/libgo/runtime/go-panic.c
index c39ea9f9303..f3e182d9bcc 100644
--- a/libgo/runtime/go-panic.c
+++ b/libgo/runtime/go-panic.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
#include "go-alloc.h"
#include "go-defer.h"
diff --git a/libgo/runtime/go-semacquire.c b/libgo/runtime/go-semacquire.c
index 40fe2af7864..05b637776da 100644
--- a/libgo/runtime/go-semacquire.c
+++ b/libgo/runtime/go-semacquire.c
@@ -13,9 +13,9 @@
/* We use a single global lock and condition variable. This is
painful, since it will cause unnecessary contention, but is hard to
- avoid in a portable manner. On Linux we can use futexes, but they
- are unfortunately not exposed by libc and are thus also hard to use
- portably. */
+ avoid in a portable manner. On GNU/Linux we can use futexes, but
+ they are unfortunately not exposed by libc and are thus also hard
+ to use portably. */
static pthread_mutex_t sem_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t sem_cond = PTHREAD_COND_INITIALIZER;
diff --git a/libgo/runtime/go-string-to-byte-array.c b/libgo/runtime/go-string-to-byte-array.c
index 10c565e39a5..8bae54b0c14 100644
--- a/libgo/runtime/go-string-to-byte-array.c
+++ b/libgo/runtime/go-string-to-byte-array.c
@@ -7,6 +7,7 @@
#include "go-string.h"
#include "array.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
struct __go_open_array
diff --git a/libgo/runtime/go-string-to-int-array.c b/libgo/runtime/go-string-to-int-array.c
index f59df6739f1..aff146872a9 100644
--- a/libgo/runtime/go-string-to-int-array.c
+++ b/libgo/runtime/go-string-to-int-array.c
@@ -8,6 +8,7 @@
#include "go-string.h"
#include "array.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
struct __go_open_array
diff --git a/libgo/runtime/go-strplus.c b/libgo/runtime/go-strplus.c
index e4dea9c4690..bfbe3412a75 100644
--- a/libgo/runtime/go-strplus.c
+++ b/libgo/runtime/go-strplus.c
@@ -6,6 +6,7 @@
#include "go-string.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
struct __go_string
diff --git a/libgo/runtime/go-strslice.c b/libgo/runtime/go-strslice.c
index 94ecee92e4d..40ccac617a1 100644
--- a/libgo/runtime/go-strslice.c
+++ b/libgo/runtime/go-strslice.c
@@ -7,6 +7,7 @@
#include "go-string.h"
#include "go-panic.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
struct __go_string
diff --git a/libgo/runtime/goc2c.c b/libgo/runtime/goc2c.c
index 32fbceba1f5..fe413fe42af 100644
--- a/libgo/runtime/goc2c.c
+++ b/libgo/runtime/goc2c.c
@@ -219,13 +219,14 @@ getchar_skipping_comments(void)
}
/*
- * Read and return a token. Tokens are delimited by whitespace or by
- * [(),{}]. The latter are all returned as single characters.
+ * Read and return a token. Tokens are string or character literals
+ * or else delimited by whitespace or by [(),{}].
+ * The latter are all returned as single characters.
*/
static char *
read_token(void)
{
- int c;
+ int c, q;
char *buf;
unsigned int alc, off;
const char* delims = "(),{}";
@@ -240,7 +241,26 @@ read_token(void)
alc = 16;
buf = xmalloc(alc + 1);
off = 0;
- if (strchr(delims, c) != NULL) {
+ if(c == '"' || c == '\'') {
+ q = c;
+ buf[off] = c;
+ ++off;
+ while (1) {
+ if (off+2 >= alc) { // room for c and maybe next char
+ alc *= 2;
+ buf = xrealloc(buf, alc + 1);
+ }
+ c = getchar_no_eof();
+ buf[off] = c;
+ ++off;
+ if(c == q)
+ break;
+ if(c == '\\') {
+ buf[off] = getchar_no_eof();
+ ++off;
+ }
+ }
+ } else if (strchr(delims, c) != NULL) {
buf[off] = c;
++off;
} else {
diff --git a/libgo/runtime/malloc.goc b/libgo/runtime/malloc.goc
index 2ea69ee795b..66f5bda66c0 100644
--- a/libgo/runtime/malloc.goc
+++ b/libgo/runtime/malloc.goc
@@ -12,6 +12,7 @@ package runtime
#include <stdlib.h>
#include "go-alloc.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
#include "go-string.h"
#include "interface.h"
@@ -96,11 +97,12 @@ runtime_mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed)
m->mcache->next_sample -= size;
else {
// pick next profile time
+ // If you change this, also change allocmcache.
if(rate > 0x3fffffff) // make 2*rate not overflow
rate = 0x3fffffff;
m->mcache->next_sample = runtime_fastrand1() % (2*rate);
profile:
- runtime_setblockspecial(v);
+ runtime_setblockspecial(v, true);
runtime_MProf_Malloc(v, size);
}
}
@@ -224,6 +226,7 @@ runtime_mlookup(void *v, byte **base, uintptr *size, MSpan **sp)
MCache*
runtime_allocmcache(void)
{
+ int32 rate;
MCache *c;
if(!__sync_bool_compare_and_swap(&m->mallocing, 0, 1))
@@ -239,6 +242,13 @@ runtime_allocmcache(void)
mstats.mcache_sys = runtime_mheap.cachealloc.sys;
runtime_unlock(&runtime_mheap);
+ // Set first allocation sample size.
+ rate = runtime_MemProfileRate;
+ if(rate > 0x3fffffff) // make 2*rate not overflow
+ rate = 0x3fffffff;
+ if(rate != 0)
+ c->next_sample = runtime_fastrand1() % (2*rate);
+
__sync_bool_compare_and_swap(&m->mallocing, 1, 0);
if(__sync_bool_compare_and_swap(&m->gcing, 1, 0))
__go_run_goroutine_gc(2);
@@ -280,6 +290,7 @@ runtime_mallocinit(void)
byte *p;
uintptr arena_size, bitmap_size;
extern byte end[];
+ byte *want;
runtime_sizeof_C_MStats = sizeof(MStats);
@@ -341,9 +352,15 @@ runtime_mallocinit(void)
// not as an absolute requirement. If we ask for the end
// of the data segment but the operating system requires
// a little more space before we can start allocating, it will
- // give out a slightly higher pointer. That's fine.
- // Run with what we get back.
- p = runtime_SysReserve(end, bitmap_size + arena_size);
+ // give out a slightly higher pointer. Except QEMU, which
+ // is buggy, as usual: it won't adjust the pointer upward.
+ // So adjust it upward a little bit ourselves: 1/4 MB to get
+ // away from the running binary image and then round up
+ // to a MB boundary.
+ want = (byte*)(((uintptr)end + (1<<18) + (1<<20) - 1)&~((1<<20)-1));
+ if(0xffffffff - (uintptr)want <= bitmap_size + arena_size)
+ want = 0;
+ p = runtime_SysReserve(want, bitmap_size + arena_size);
if(p == nil)
runtime_throw("runtime: cannot reserve arena virtual address space");
}
@@ -418,8 +435,9 @@ runtime_mal(uintptr n)
return runtime_mallocgc(n, 0, 1, 1);
}
-func new(n uint32) (ret *uint8) {
- ret = runtime_mal(n);
+func new(typ *Type) (ret *uint8) {
+ uint32 flag = typ->__code&GO_NO_POINTERS ? FlagNoPointers : 0;
+ ret = runtime_mallocgc(typ->__size, flag, 1, 1);
}
func Alloc(n uintptr) (p *byte) {
@@ -444,9 +462,8 @@ func SetFinalizer(obj Eface, finalizer Eface) {
const FuncType *ft;
if(obj.__type_descriptor == nil) {
- // runtime_printf("runtime.SetFinalizer: first argument is nil interface\n");
- throw:
- runtime_throw("runtime.SetFinalizer");
+ // runtime·printf("runtime.SetFinalizer: first argument is nil interface\n");
+ goto throw;
}
if(obj.__type_descriptor->__code != GO_PTR) {
// runtime_printf("runtime.SetFinalizer: first argument is %S, not pointer\n", *obj.type->string);
@@ -458,19 +475,21 @@ func SetFinalizer(obj Eface, finalizer Eface) {
}
ft = nil;
if(finalizer.__type_descriptor != nil) {
- if(finalizer.__type_descriptor->__code != GO_FUNC) {
- badfunc:
- // runtime_printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.type->string, *obj.type->string);
- goto throw;
- }
+ if(finalizer.__type_descriptor->__code != GO_FUNC)
+ goto badfunc;
ft = (const FuncType*)finalizer.__type_descriptor;
if(ft->__dotdotdot || ft->__in.__count != 1 || !__go_type_descriptors_equal(*(Type**)ft->__in.__values, obj.__type_descriptor))
goto badfunc;
+ }
- if(runtime_getfinalizer(obj.__object, 0)) {
- // runtime_printf("runtime.SetFinalizer: finalizer already set");
- goto throw;
- }
+ if(!runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft)) {
+ runtime_printf("runtime.SetFinalizer: finalizer already set\n");
+ goto throw;
}
- runtime_addfinalizer(obj.__object, finalizer.__type_descriptor != nil ? *(void**)finalizer.__object : nil, ft);
+ return;
+
+badfunc:
+ // runtime_printf("runtime.SetFinalizer: second argument is %S, not func(%S)\n", *finalizer.type->string, *obj.type->string);
+throw:
+ runtime_throw("runtime.SetFinalizer");
}
diff --git a/libgo/runtime/malloc.h b/libgo/runtime/malloc.h
index 3e813bbde8c..1ccc2f0b260 100644
--- a/libgo/runtime/malloc.h
+++ b/libgo/runtime/malloc.h
@@ -120,6 +120,13 @@ enum
#else
MHeapMap_Bits = 20,
#endif
+
+ // Max number of threads to run garbage collection.
+ // 2, 3, and 4 are all plausible maximums depending
+ // on the hardware details of the machine. The second
+ // proc is the one that helps the most (after the first),
+ // so start with just 2 for now.
+ MaxGcproc = 2,
};
// A generic linked list of blocks. (Typically the block is bigger than sizeof(MLink).)
@@ -192,7 +199,7 @@ struct MStats
uint64 nlookup; // number of pointer lookups
uint64 nmalloc; // number of mallocs
uint64 nfree; // number of frees
-
+
// Statistics about malloc heap.
// protected by mheap.Lock
uint64 heap_alloc; // bytes allocated and still in use
@@ -210,7 +217,7 @@ struct MStats
uint64 mcache_inuse; // MCache structures
uint64 mcache_sys;
uint64 buckhash_sys; // profiling bucket hash table
-
+
// Statistics about garbage collector.
// Protected by stopping the world during GC.
uint64 next_gc; // next GC (in heap_alloc time)
@@ -219,7 +226,7 @@ struct MStats
uint32 numgc;
bool enablegc;
bool debuggc;
-
+
// Statistics about allocation size classes.
struct {
uint32 size;
@@ -240,7 +247,7 @@ extern MStats mstats
//
// class_to_size[i] = largest size in class i
// class_to_allocnpages[i] = number of pages to allocate when
-// making new objects in class i
+// making new objects in class i
// class_to_transfercount[i] = number of objects to move when
// taking a bunch of objects out of the central lists
// and putting them in the thread free list.
@@ -279,7 +286,7 @@ struct MCache
int64 nmalloc;
int64 nfree;
} local_by_size[NumSizeClasses];
-
+
};
void* runtime_MCache_Alloc(MCache *c, int32 sizeclass, uintptr size, int32 zeroed);
@@ -352,14 +359,14 @@ struct MHeap
byte *arena_start;
byte *arena_used;
byte *arena_end;
-
+
// central free lists for small size classes.
// the union makes sure that the MCentrals are
- // spaced 64 bytes apart, so that each MCentral.Lock
+ // spaced CacheLineSize bytes apart, so that each MCentral.Lock
// gets its own cache line.
union {
MCentral;
- byte pad[64];
+ byte pad[CacheLineSize];
} central[NumSizeClasses];
FixAlloc spanalloc; // allocator for Span*
@@ -387,7 +394,7 @@ int32 runtime_checking;
void runtime_markspan(void *v, uintptr size, uintptr n, bool leftover);
void runtime_unmarkspan(void *v, uintptr size);
bool runtime_blockspecial(void*);
-void runtime_setblockspecial(void*);
+void runtime_setblockspecial(void*, bool);
void runtime_purgecachedstats(M*);
enum
@@ -402,6 +409,8 @@ void runtime_Mprof_Init(void);
void runtime_MProf_Malloc(void*, uintptr);
void runtime_MProf_Free(void*, uintptr);
void runtime_MProf_Mark(void (*scan)(byte *, int64));
+int32 runtime_helpgc(bool*);
+void runtime_gchelper(void);
// Malloc profiling settings.
// Must match definition in extern.go.
@@ -412,13 +421,6 @@ enum {
};
extern int32 runtime_malloc_profile;
-typedef struct Finalizer Finalizer;
-struct Finalizer
-{
- Finalizer *next; // for use by caller of getfinalizer
- void (*fn)(void*);
- void *arg;
- const struct __go_func_type *ft;
-};
-
-Finalizer* runtime_getfinalizer(void*, bool);
+struct __go_func_type;
+bool runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft);
+void runtime_walkfintab(void (*fn)(void*), void (*scan)(byte*, int64));
diff --git a/libgo/runtime/map.goc b/libgo/runtime/map.goc
index e19bc96de64..da67d49287d 100644
--- a/libgo/runtime/map.goc
+++ b/libgo/runtime/map.goc
@@ -45,6 +45,12 @@ func mapassign2(h *Hmap, key *byte, val *byte, p bool) {
}
}
+/* Delete a key from a map. */
+
+func mapdelete(h *Hmap, key *byte) {
+ __go_map_delete(h, key);
+}
+
/* Initialize a range over a map. */
func mapiterinit(h *Hmap, it *hiter) {
diff --git a/libgo/runtime/mcache.c b/libgo/runtime/mcache.c
index 191b0d1c3f2..6c60aebbe67 100644
--- a/libgo/runtime/mcache.c
+++ b/libgo/runtime/mcache.c
@@ -7,6 +7,7 @@
// See malloc.h for an overview.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
void*
diff --git a/libgo/runtime/mcentral.c b/libgo/runtime/mcentral.c
index cd3d6ca5ede..b98a8d32204 100644
--- a/libgo/runtime/mcentral.c
+++ b/libgo/runtime/mcentral.c
@@ -15,6 +15,7 @@
// so that it is faster to move those lists between MCaches and MCentrals.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
static bool MCentral_Grow(MCentral *c);
diff --git a/libgo/runtime/mem.c b/libgo/runtime/mem.c
index 90c2c61aff9..4e1103e130a 100644
--- a/libgo/runtime/mem.c
+++ b/libgo/runtime/mem.c
@@ -2,6 +2,7 @@
#include <unistd.h>
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
#ifndef MAP_ANON
@@ -84,6 +85,7 @@ void*
runtime_SysReserve(void *v, uintptr n)
{
int fd = -1;
+ void *p;
// On 64-bit, people with ulimit -v set complain if we reserve too
// much address space. Instead, assume that the reservation is okay
@@ -102,7 +104,11 @@ runtime_SysReserve(void *v, uintptr n)
fd = dev_zero;
#endif
- return runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
+ p = runtime_mmap(v, n, PROT_NONE, MAP_ANON|MAP_PRIVATE, fd, 0);
+ if((uintptr)p < 4096 || -(uintptr)p < 4096) {
+ return nil;
+ }
+ return p;
}
void
diff --git a/libgo/runtime/mem_posix_memalign.c b/libgo/runtime/mem_posix_memalign.c
index 2318be8da11..7d04f999f9f 100644
--- a/libgo/runtime/mem_posix_memalign.c
+++ b/libgo/runtime/mem_posix_memalign.c
@@ -1,6 +1,7 @@
#include <errno.h>
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
void*
diff --git a/libgo/runtime/mfinal.c b/libgo/runtime/mfinal.c
index 04d58dddda9..db9a4fdf5ed 100644
--- a/libgo/runtime/mfinal.c
+++ b/libgo/runtime/mfinal.c
@@ -3,18 +3,17 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
-// Lock to protect finalizer data structures.
-// Cannot reuse mheap.Lock because the finalizer
-// maintenance requires allocation.
-static Lock finlock;
+enum { debug = 0 };
-void
-runtime_initfintab()
+typedef struct Fin Fin;
+struct Fin
{
- runtime_initlock(&finlock);
-}
+ void (*fn)(void*);
+ const struct __go_func_type *ft;
+};
// Finalizer hash table. Direct hash, linear scan, at most 3/4 full.
// Table size is power of 3 so that hash can be key % max.
@@ -26,25 +25,43 @@ runtime_initfintab()
typedef struct Fintab Fintab;
struct Fintab
{
- void **key;
- Finalizer **val;
+ Lock;
+ void **fkey;
+ Fin *val;
int32 nkey; // number of non-nil entries in key
int32 ndead; // number of dead (-1) entries in key
int32 max; // size of key, val allocations
};
+#define TABSZ 17
+#define TAB(p) (&fintab[((uintptr)(p)>>3)%TABSZ])
+
+static struct {
+ Fintab;
+ uint8 pad[0 /* CacheLineSize - sizeof(Fintab) */];
+} fintab[TABSZ];
+
+void
+runtime_initfintab()
+{
+ int32 i;
+
+ for(i=0; i<TABSZ; i++)
+ runtime_initlock(&fintab[i]);
+}
+
static void
-addfintab(Fintab *t, void *k, Finalizer *v)
+addfintab(Fintab *t, void *k, void (*fn)(void*), const struct __go_func_type *ft)
{
int32 i, j;
i = (uintptr)k % (uintptr)t->max;
for(j=0; j<t->max; j++) {
- if(t->key[i] == nil) {
+ if(t->fkey[i] == nil) {
t->nkey++;
goto ret;
}
- if(t->key[i] == (void*)-1) {
+ if(t->fkey[i] == (void*)-1) {
t->ndead--;
goto ret;
}
@@ -56,30 +73,32 @@ addfintab(Fintab *t, void *k, Finalizer *v)
runtime_throw("finalizer table inconsistent");
ret:
- t->key[i] = k;
- t->val[i] = v;
+ t->fkey[i] = k;
+ t->val[i].fn = fn;
+ t->val[i].ft = ft;
}
-static Finalizer*
-lookfintab(Fintab *t, void *k, bool del)
+static bool
+lookfintab(Fintab *t, void *k, bool del, Fin *f)
{
int32 i, j;
- Finalizer *v;
if(t->max == 0)
- return nil;
+ return false;
i = (uintptr)k % (uintptr)t->max;
for(j=0; j<t->max; j++) {
- if(t->key[i] == nil)
- return nil;
- if(t->key[i] == k) {
- v = t->val[i];
+ if(t->fkey[i] == nil)
+ return false;
+ if(t->fkey[i] == k) {
+ if(f)
+ *f = t->val[i];
if(del) {
- t->key[i] = (void*)-1;
- t->val[i] = nil;
+ t->fkey[i] = (void*)-1;
+ t->val[i].fn = nil;
+ t->val[i].ft = nil;
t->ndead++;
}
- return v;
+ return true;
}
if(++i == t->max)
i = 0;
@@ -87,108 +106,123 @@ lookfintab(Fintab *t, void *k, bool del)
// cannot happen - table is known to be non-full
runtime_throw("finalizer table inconsistent");
- return nil;
+ return false;
}
-static Fintab fintab;
-
-// add finalizer; caller is responsible for making sure not already in table
-void
-runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft)
+static void
+resizefintab(Fintab *tab)
{
Fintab newtab;
+ void *k;
int32 i;
- byte *base;
- Finalizer *e;
+
+ runtime_memclr((byte*)&newtab, sizeof newtab);
+ newtab.max = tab->max;
+ if(newtab.max == 0)
+ newtab.max = 3*3*3;
+ else if(tab->ndead < tab->nkey/2) {
+ // grow table if not many dead values.
+ // otherwise just rehash into table of same size.
+ newtab.max *= 3;
+ }
+
+ newtab.fkey = runtime_mallocgc(newtab.max*sizeof newtab.fkey[0], FlagNoPointers, 0, 1);
+ newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
- e = nil;
- if(f != nil) {
- e = runtime_mal(sizeof *e);
- e->fn = f;
- e->ft = ft;
+ for(i=0; i<tab->max; i++) {
+ k = tab->fkey[i];
+ if(k != nil && k != (void*)-1)
+ addfintab(&newtab, k, tab->val[i].fn, tab->val[i].ft);
}
+
+ runtime_free(tab->fkey);
+ runtime_free(tab->val);
+
+ tab->fkey = newtab.fkey;
+ tab->val = newtab.val;
+ tab->nkey = newtab.nkey;
+ tab->ndead = newtab.ndead;
+ tab->max = newtab.max;
+}
+bool
+runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft)
+{
+ Fintab *tab;
+ byte *base;
+ bool ret = false;
+
+ if(debug) {
+ if(!runtime_mlookup(p, &base, nil, nil) || p != base)
+ runtime_throw("addfinalizer on invalid pointer");
+ }
+
if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
runtime_throw("finalizer deadlock");
- runtime_lock(&finlock);
- if(!runtime_mlookup(p, &base, nil, nil) || p != base) {
- runtime_unlock(&finlock);
- __sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
- runtime_throw("addfinalizer on invalid pointer");
- }
+ tab = TAB(p);
+ runtime_lock(tab);
if(f == nil) {
- lookfintab(&fintab, p, 1);
+ if(lookfintab(tab, p, true, nil))
+ runtime_setblockspecial(p, false);
+ ret = true;
goto unlock;
}
- if(lookfintab(&fintab, p, 0)) {
- runtime_unlock(&finlock);
- __sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
- runtime_throw("double finalizer");
+ if(lookfintab(tab, p, false, nil)) {
+ ret = false;
+ goto unlock;
}
- runtime_setblockspecial(p);
- if(fintab.nkey >= fintab.max/2+fintab.max/4) {
+ if(tab->nkey >= tab->max/2+tab->max/4) {
// keep table at most 3/4 full:
// allocate new table and rehash.
-
- runtime_memclr((byte*)&newtab, sizeof newtab);
- newtab.max = fintab.max;
- if(newtab.max == 0)
- newtab.max = 3*3*3;
- else if(fintab.ndead < fintab.nkey/2) {
- // grow table if not many dead values.
- // otherwise just rehash into table of same size.
- newtab.max *= 3;
- }
-
- newtab.key = runtime_mallocgc(newtab.max*sizeof newtab.key[0], FlagNoPointers, 0, 1);
- newtab.val = runtime_mallocgc(newtab.max*sizeof newtab.val[0], 0, 0, 1);
-
- for(i=0; i<fintab.max; i++) {
- void *k;
-
- k = fintab.key[i];
- if(k != nil && k != (void*)-1)
- addfintab(&newtab, k, fintab.val[i]);
- }
- runtime_free(fintab.key);
- runtime_free(fintab.val);
- fintab = newtab;
+ resizefintab(tab);
}
- addfintab(&fintab, p, e);
+ addfintab(tab, p, f, ft);
+ runtime_setblockspecial(p, true);
+ ret = true;
+
unlock:
- runtime_unlock(&finlock);
+ runtime_unlock(tab);
__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
__go_run_goroutine_gc(200);
}
+
+ return ret;
}
// get finalizer; if del, delete finalizer.
-// caller is responsible for updating RefHasFinalizer bit.
-Finalizer*
-runtime_getfinalizer(void *p, bool del)
+// caller is responsible for updating RefHasFinalizer (special) bit.
+bool
+runtime_getfinalizer(void *p, bool del, void (**fn)(void*), const struct __go_func_type **ft)
{
- Finalizer *f;
+ Fintab *tab;
+ bool res;
+ Fin f;
if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
runtime_throw("finalizer deadlock");
- runtime_lock(&finlock);
- f = lookfintab(&fintab, p, del);
- runtime_unlock(&finlock);
+ tab = TAB(p);
+ runtime_lock(tab);
+ res = lookfintab(tab, p, del, &f);
+ runtime_unlock(tab);
__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
__go_run_goroutine_gc(201);
}
- return f;
+ if(res==false)
+ return false;
+ *fn = f.fn;
+ *ft = f.ft;
+ return true;
}
void
@@ -196,18 +230,22 @@ runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64))
{
void **key;
void **ekey;
+ int32 i;
if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1))
runtime_throw("finalizer deadlock");
- scan((byte*)&fintab, sizeof fintab);
- runtime_lock(&finlock);
- key = fintab.key;
- ekey = key + fintab.max;
- for(; key < ekey; key++)
- if(*key != nil && *key != ((void*)-1))
- fn(*key);
- runtime_unlock(&finlock);
+ for(i=0; i<TABSZ; i++) {
+ runtime_lock(&fintab[i]);
+ key = fintab[i].fkey;
+ ekey = key + fintab[i].max;
+ for(; key < ekey; key++)
+ if(*key != nil && *key != ((void*)-1))
+ fn(*key);
+ scan((byte*)&fintab[i].fkey, sizeof(void*));
+ scan((byte*)&fintab[i].val, sizeof(void*));
+ runtime_unlock(&fintab[i]);
+ }
__sync_bool_compare_and_swap(&m->holds_finlock, 1, 0);
if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) {
diff --git a/libgo/runtime/mfixalloc.c b/libgo/runtime/mfixalloc.c
index c05583dc27b..109cfe8eeaa 100644
--- a/libgo/runtime/mfixalloc.c
+++ b/libgo/runtime/mfixalloc.c
@@ -7,6 +7,7 @@
// See malloc.h for overview.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
// Initialize f to allocate objects of the given size,
diff --git a/libgo/runtime/mgc0.c b/libgo/runtime/mgc0.c
index 900ebde687c..cb585251b53 100644
--- a/libgo/runtime/mgc0.c
+++ b/libgo/runtime/mgc0.c
@@ -5,13 +5,14 @@
// Garbage collector.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
enum {
Debug = 0,
- UseCas = 1,
PtrSize = sizeof(void*),
-
+ DebugMark = 0, // run second pass to check mark
+
// Four bits per word (see #defines below).
wordsPerBitmapWord = sizeof(void*)*8/4,
bitShift = sizeof(void*)*8/4,
@@ -50,28 +51,72 @@ enum {
#define bitMask (bitBlockBoundary | bitAllocated | bitMarked | bitSpecial)
+// TODO: Make these per-M.
static uint64 nlookup;
static uint64 nsizelookup;
static uint64 naddrlookup;
+static uint64 nhandoff;
+
static int32 gctrace;
typedef struct Workbuf Workbuf;
struct Workbuf
{
Workbuf *next;
- uintptr nw;
- byte *w[2048-2];
+ uintptr nobj;
+ byte *obj[512-2];
+};
+
+typedef struct Finalizer Finalizer;
+struct Finalizer
+{
+ void (*fn)(void*);
+ void *arg;
+ const struct __go_func_type *ft;
+};
+
+typedef struct FinBlock FinBlock;
+struct FinBlock
+{
+ FinBlock *alllink;
+ FinBlock *next;
+ int32 cnt;
+ int32 cap;
+ Finalizer fin[1];
};
static bool finstarted;
static pthread_mutex_t finqlock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t finqcond = PTHREAD_COND_INITIALIZER;
-static Finalizer *finq;
+static FinBlock *finq; // list of finalizers that are to be executed
+static FinBlock *finc; // cache of free blocks
+static FinBlock *allfin; // list of all blocks
+static Lock finlock;
static int32 fingwait;
static void runfinq(void*);
static Workbuf* getempty(Workbuf*);
static Workbuf* getfull(Workbuf*);
+static void putempty(Workbuf*);
+static Workbuf* handoff(Workbuf*);
+
+static struct {
+ Lock fmu;
+ Workbuf *full;
+ Lock emu;
+ Workbuf *empty;
+ uint32 nproc;
+ volatile uint32 nwait;
+ volatile uint32 ndone;
+ Note alldone;
+ Lock markgate;
+ Lock sweepgate;
+ MSpan *spans;
+
+ Lock;
+ byte *chunk;
+ uintptr nchunk;
+} work;
// scanblock scans a block of n bytes starting at pointer b for references
// to other objects, scanning any it finds recursively until there are no
@@ -82,13 +127,14 @@ static Workbuf* getfull(Workbuf*);
static void
scanblock(byte *b, int64 n)
{
- byte *obj, *arena_start, *p;
+ byte *obj, *arena_start, *arena_used, *p;
void **vp;
- uintptr size, *bitp, bits, shift, i, j, x, xbits, off;
+ uintptr size, *bitp, bits, shift, i, j, x, xbits, off, nobj, nproc;
MSpan *s;
PageID k;
- void **bw, **w, **ew;
+ void **wp;
Workbuf *wbuf;
+ bool keepworking;
if((int64)(uintptr)n != n || n < 0) {
// runtime_printf("scanblock %p %lld\n", b, (long long)n);
@@ -97,11 +143,19 @@ scanblock(byte *b, int64 n)
// Memory arena parameters.
arena_start = runtime_mheap.arena_start;
-
+ arena_used = runtime_mheap.arena_used;
+ nproc = work.nproc;
+
wbuf = nil; // current work buffer
- ew = nil; // end of work buffer
- bw = nil; // beginning of work buffer
- w = nil; // current pointer into work buffer
+ wp = nil; // storage for next queued pointer (write pointer)
+ nobj = 0; // number of queued objects
+
+ // Scanblock helpers pass b==nil.
+ // The main proc needs to return to make more
+ // calls to scanblock. But if work.nproc==1 then
+ // might as well process blocks as soon as we
+ // have them.
+ keepworking = b == nil || work.nproc == 1;
// Align b to a word boundary.
off = (uintptr)b & (PtrSize-1);
@@ -117,17 +171,17 @@ scanblock(byte *b, int64 n)
runtime_printf("scanblock %p %lld\n", b, (long long) n);
vp = (void**)b;
- n /= PtrSize;
+ n >>= (2+PtrSize/8); /* n /= PtrSize (4 or 8) */
for(i=0; i<(uintptr)n; i++) {
obj = (byte*)vp[i];
-
+
// Words outside the arena cannot be pointers.
- if((byte*)obj < arena_start || (byte*)obj >= runtime_mheap.arena_used)
+ if((byte*)obj < arena_start || (byte*)obj >= arena_used)
continue;
-
+
// obj may be a pointer to a live object.
// Try to find the beginning of the object.
-
+
// Round down to word boundary.
obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
@@ -185,47 +239,72 @@ scanblock(byte *b, int64 n)
found:
// Now we have bits, bitp, and shift correct for
// obj pointing at the base of the object.
- // If not allocated or already marked, done.
- if((bits & bitAllocated) == 0 || (bits & bitMarked) != 0)
+ // Only care about allocated and not marked.
+ if((bits & (bitAllocated|bitMarked)) != bitAllocated)
continue;
- *bitp |= bitMarked<<shift;
+ if(nproc == 1)
+ *bitp |= bitMarked<<shift;
+ else {
+ for(;;) {
+ x = *bitp;
+ if(x & (bitMarked<<shift))
+ goto continue_obj;
+ if(runtime_casp((void**)bitp, (void*)x, (void*)(x|(bitMarked<<shift))))
+ break;
+ }
+ }
// If object has no pointers, don't need to scan further.
if((bits & bitNoPointers) != 0)
continue;
+ // If another proc wants a pointer, give it some.
+ if(nobj > 4 && work.nwait > 0 && work.full == nil) {
+ wbuf->nobj = nobj;
+ wbuf = handoff(wbuf);
+ nobj = wbuf->nobj;
+ wp = (void**)(wbuf->obj + nobj);
+ }
+
// If buffer is full, get a new one.
- if(w >= ew) {
+ if(wbuf == nil || nobj >= nelem(wbuf->obj)) {
+ if(wbuf != nil)
+ wbuf->nobj = nobj;
wbuf = getempty(wbuf);
- bw = (void**)wbuf->w;
- w = bw;
- ew = bw + nelem(wbuf->w);
+ wp = (void**)(wbuf->obj);
+ nobj = 0;
}
- *w++ = obj;
+ *wp++ = obj;
+ nobj++;
+ continue_obj:;
}
-
+
// Done scanning [b, b+n). Prepare for the next iteration of
// the loop by setting b and n to the parameters for the next block.
- // Fetch b from the work buffers.
- if(w <= bw) {
+ // Fetch b from the work buffer.
+ if(nobj == 0) {
+ if(!keepworking) {
+ putempty(wbuf);
+ return;
+ }
// Emptied our buffer: refill.
wbuf = getfull(wbuf);
if(wbuf == nil)
- break;
- bw = (void**)wbuf->w;
- ew = (void**)(wbuf->w + nelem(wbuf->w));
- w = bw+wbuf->nw;
+ return;
+ nobj = wbuf->nobj;
+ wp = (void**)(wbuf->obj + wbuf->nobj);
}
- b = *--w;
-
+ b = *--wp;
+ nobj--;
+
// Figure out n = size of b. Start by loading bits for b.
off = (uintptr*)b - (uintptr*)arena_start;
bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
xbits = *bitp;
bits = xbits >> shift;
-
+
// Might be small; look for nearby block boundary.
// A block boundary is marked by either bitBlockBoundary
// or bitAllocated being set (see notes near their definition).
@@ -244,12 +323,12 @@ scanblock(byte *b, int64 n)
// apply a mask to keep only the bits corresponding
// to shift+j < bitShift aka j < bitShift-shift.
bits &= (boundary<<(bitShift-shift)) - boundary;
-
+
// A block boundary j words before b is indicated by
// xbits>>(shift-j) & boundary
// (assuming shift >= j). There is no cleverness here
// avoid the test, because when j gets too large the shift
- // turns negative, which is undefined in C.
+ // turns negative, which is undefined in C.
for(j=1; j<bitShift; j++) {
if(((bits>>j)&boundary) != 0 || (shift>=j && ((xbits>>(shift-j))&boundary) != 0)) {
@@ -257,7 +336,7 @@ scanblock(byte *b, int64 n)
goto scan;
}
}
-
+
// Fall back to asking span about size class.
// (Manually inlined copy of MHeap_Lookup.)
nlookup++;
@@ -274,29 +353,123 @@ scanblock(byte *b, int64 n)
}
}
-static struct {
- Workbuf *full;
- Workbuf *empty;
- byte *chunk;
- uintptr nchunk;
-} work;
+// debug_scanblock is the debug copy of scanblock.
+// it is simpler, slower, single-threaded, recursive,
+// and uses bitSpecial as the mark bit.
+static void
+debug_scanblock(byte *b, int64 n)
+{
+ byte *obj, *p;
+ void **vp;
+ uintptr size, *bitp, bits, shift, i, xbits, off;
+ MSpan *s;
+
+ if(!DebugMark)
+ runtime_throw("debug_scanblock without DebugMark");
+
+ if((int64)(uintptr)n != n || n < 0) {
+ //runtime_printf("debug_scanblock %p %D\n", b, n);
+ runtime_throw("debug_scanblock");
+ }
+
+ // Align b to a word boundary.
+ off = (uintptr)b & (PtrSize-1);
+ if(off != 0) {
+ b += PtrSize - off;
+ n -= PtrSize - off;
+ }
+
+ vp = (void**)b;
+ n /= PtrSize;
+ for(i=0; i<(uintptr)n; i++) {
+ obj = (byte*)vp[i];
+
+ // Words outside the arena cannot be pointers.
+ if((byte*)obj < runtime_mheap.arena_start || (byte*)obj >= runtime_mheap.arena_used)
+ continue;
+
+ // Round down to word boundary.
+ obj = (void*)((uintptr)obj & ~((uintptr)PtrSize-1));
+
+ // Consult span table to find beginning.
+ s = runtime_MHeap_LookupMaybe(&runtime_mheap, obj);
+ if(s == nil)
+ continue;
+
+
+ p = (byte*)((uintptr)s->start<<PageShift);
+ if(s->sizeclass == 0) {
+ obj = p;
+ size = (uintptr)s->npages<<PageShift;
+ } else {
+ if((byte*)obj >= (byte*)s->limit)
+ continue;
+ size = runtime_class_to_size[s->sizeclass];
+ int32 i = ((byte*)obj - p)/size;
+ obj = p+i*size;
+ }
+
+ // Now that we know the object header, reload bits.
+ off = (uintptr*)obj - (uintptr*)runtime_mheap.arena_start;
+ bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+ shift = off % wordsPerBitmapWord;
+ xbits = *bitp;
+ bits = xbits >> shift;
+
+ // Now we have bits, bitp, and shift correct for
+ // obj pointing at the base of the object.
+ // If not allocated or already marked, done.
+ if((bits & bitAllocated) == 0 || (bits & bitSpecial) != 0) // NOTE: bitSpecial not bitMarked
+ continue;
+ *bitp |= bitSpecial<<shift;
+ if(!(bits & bitMarked))
+ runtime_printf("found unmarked block %p in %p\n", obj, vp+i);
+
+ // If object has no pointers, don't need to scan further.
+ if((bits & bitNoPointers) != 0)
+ continue;
+
+ debug_scanblock(obj, size);
+ }
+}
// Get an empty work buffer off the work.empty list,
// allocating new buffers as needed.
static Workbuf*
getempty(Workbuf *b)
{
- if(b != nil) {
- b->nw = nelem(b->w);
- b->next = work.full;
- work.full = b;
- }
- b = work.empty;
- if(b != nil) {
- work.empty = b->next;
- return b;
+ if(work.nproc == 1) {
+ // Put b on full list.
+ if(b != nil) {
+ b->next = work.full;
+ work.full = b;
+ }
+ // Grab from empty list if possible.
+ b = work.empty;
+ if(b != nil) {
+ work.empty = b->next;
+ goto haveb;
+ }
+ } else {
+ // Put b on full list.
+ if(b != nil) {
+ runtime_lock(&work.fmu);
+ b->next = work.full;
+ work.full = b;
+ runtime_unlock(&work.fmu);
+ }
+ // Grab from empty list if possible.
+ runtime_lock(&work.emu);
+ b = work.empty;
+ if(b != nil)
+ work.empty = b->next;
+ runtime_unlock(&work.emu);
+ if(b != nil)
+ goto haveb;
}
-
+
+ // Need to allocate.
+ runtime_lock(&work);
if(work.nchunk < sizeof *b) {
work.nchunk = 1<<20;
work.chunk = runtime_SysAlloc(work.nchunk);
@@ -304,25 +477,121 @@ getempty(Workbuf *b)
b = (Workbuf*)work.chunk;
work.chunk += sizeof *b;
work.nchunk -= sizeof *b;
+ runtime_unlock(&work);
+
+haveb:
+ b->nobj = 0;
return b;
}
+static void
+putempty(Workbuf *b)
+{
+ if(b == nil)
+ return;
+
+ if(work.nproc == 1) {
+ b->next = work.empty;
+ work.empty = b;
+ return;
+ }
+
+ runtime_lock(&work.emu);
+ b->next = work.empty;
+ work.empty = b;
+ runtime_unlock(&work.emu);
+}
+
// Get a full work buffer off the work.full list, or return nil.
static Workbuf*
getfull(Workbuf *b)
{
- if(b != nil) {
- b->nw = 0;
- b->next = work.empty;
- work.empty = b;
+ int32 i;
+ Workbuf *b1;
+
+ if(work.nproc == 1) {
+ // Put b on empty list.
+ if(b != nil) {
+ b->next = work.empty;
+ work.empty = b;
+ }
+ // Grab from full list if possible.
+ // Since work.nproc==1, no one else is
+ // going to give us work.
+ b = work.full;
+ if(b != nil)
+ work.full = b->next;
+ return b;
+ }
+
+ putempty(b);
+
+ // Grab buffer from full list if possible.
+ for(;;) {
+ b1 = work.full;
+ if(b1 == nil)
+ break;
+ runtime_lock(&work.fmu);
+ if(work.full != nil) {
+ b1 = work.full;
+ work.full = b1->next;
+ runtime_unlock(&work.fmu);
+ return b1;
+ }
+ runtime_unlock(&work.fmu);
+ }
+
+ runtime_xadd(&work.nwait, +1);
+ for(i=0;; i++) {
+ b1 = work.full;
+ if(b1 != nil) {
+ runtime_lock(&work.fmu);
+ if(work.full != nil) {
+ runtime_xadd(&work.nwait, -1);
+ b1 = work.full;
+ work.full = b1->next;
+ runtime_unlock(&work.fmu);
+ return b1;
+ }
+ runtime_unlock(&work.fmu);
+ continue;
+ }
+ if(work.nwait == work.nproc)
+ return nil;
+ if(i < 10)
+ runtime_procyield(20);
+ else if(i < 20)
+ runtime_osyield();
+ else
+ runtime_usleep(100);
}
- b = work.full;
- if(b != nil)
- work.full = b->next;
- return b;
}
-// Scanstack calls scanblock on each of gp's stack segments.
+static Workbuf*
+handoff(Workbuf *b)
+{
+ int32 n;
+ Workbuf *b1;
+
+ // Make new buffer with half of b's pointers.
+ b1 = getempty(nil);
+ n = b->nobj/2;
+ b->nobj -= n;
+ b1->nobj = n;
+ runtime_memmove(b1->obj, b->obj+b->nobj, n*sizeof b1->obj[0]);
+ nhandoff += n;
+
+ // Put b on full list - let first half of b get stolen.
+ runtime_lock(&work.fmu);
+ b->next = work.full;
+ work.full = b;
+ runtime_unlock(&work.fmu);
+
+ return b1;
+}
+
+// Markfin calls scanblock on the blocks that have finalizers:
+// the things pointed at cannot be freed until the finalizers have run.
static void
markfin(void *v)
{
@@ -355,11 +624,22 @@ __go_register_gc_roots (struct root_list* r)
roots = r;
}
-// Mark
static void
-mark(void)
+debug_markfin(void *v)
+{
+ uintptr size;
+
+ if(!runtime_mlookup(v, (byte**)&v, &size, nil))
+ runtime_throw("debug_mark - finalizer inconsistency");
+ debug_scanblock(v, size);
+}
+
+// Mark
+static void
+mark(void (*scan)(byte*, int64))
{
struct root_list *pl;
+ FinBlock *fb;
for(pl = roots; pl != nil; pl = pl->next) {
struct root* pr = &pl->roots[0];
@@ -372,18 +652,63 @@ mark(void)
}
}
- scanblock((byte*)&m0, sizeof m0);
- scanblock((byte*)&finq, sizeof finq);
- runtime_MProf_Mark(scanblock);
+ scan((byte*)&m0, sizeof m0);
+ scan((byte*)&finq, sizeof finq);
+ runtime_MProf_Mark(scan);
// mark stacks
- __go_scanstacks(scanblock);
+ __go_scanstacks(scan);
// mark things pointed at by objects with finalizers
- runtime_walkfintab(markfin, scanblock);
+ if(scan == debug_scanblock)
+ runtime_walkfintab(debug_markfin, scan);
+ else
+ runtime_walkfintab(markfin, scan);
+
+ for(fb=allfin; fb; fb=fb->alllink)
+ scanblock((byte*)fb->fin, fb->cnt*sizeof(fb->fin[0]));
+
+ // in multiproc mode, join in the queued work.
+ scan(nil, 0);
}
-// Sweep frees or calls finalizers for blocks not marked in the mark phase.
+static bool
+handlespecial(byte *p, uintptr size)
+{
+ void (*fn)(void*);
+ const struct __go_func_type *ft;
+ FinBlock *block;
+ Finalizer *f;
+
+ if(!runtime_getfinalizer(p, true, &fn, &ft)) {
+ runtime_setblockspecial(p, false);
+ runtime_MProf_Free(p, size);
+ return false;
+ }
+
+ runtime_lock(&finlock);
+ if(finq == nil || finq->cnt == finq->cap) {
+ if(finc == nil) {
+ finc = runtime_SysAlloc(PageSize);
+ finc->cap = (PageSize - sizeof(FinBlock)) / sizeof(Finalizer) + 1;
+ finc->alllink = allfin;
+ allfin = finc;
+ }
+ block = finc;
+ finc = block->next;
+ block->next = finq;
+ finq = block;
+ }
+ f = &finq->fin[finq->cnt];
+ finq->cnt++;
+ f->fn = fn;
+ f->ft = ft;
+ f->arg = p;
+ runtime_unlock(&finlock);
+ return true;
+}
+
+// Sweep frees or collects finalizers for blocks not marked in the mark phase.
// It clears the mark bits in preparation for the next GC round.
static void
sweep(void)
@@ -393,9 +718,17 @@ sweep(void)
uintptr size;
byte *p;
MCache *c;
- Finalizer *f;
+ byte *arena_start;
+
+ arena_start = runtime_mheap.arena_start;
+
+ for(;;) {
+ s = work.spans;
+ if(s == nil)
+ break;
+ if(!runtime_casp(&work.spans, s, s->allnext))
+ continue;
- for(s = runtime_mheap.allspans; s != nil; s = s->allnext) {
if(s->state != MSpanInUse)
continue;
@@ -410,13 +743,15 @@ sweep(void)
npages = runtime_class_to_allocnpages[cl];
n = (npages << PageShift) / size;
}
-
- // sweep through n objects of given size starting at p.
+
+ // Sweep through n objects of given size starting at p.
+ // This thread owns the span now, so it can manipulate
+ // the block bitmap without atomic operations.
for(; n > 0; n--, p += size) {
uintptr off, *bitp, shift, bits;
- off = (uintptr*)p - (uintptr*)runtime_mheap.arena_start;
- bitp = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
+ off = (uintptr*)p - (uintptr*)arena_start;
+ bitp = (uintptr*)arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
bits = *bitp>>shift;
@@ -424,20 +759,21 @@ sweep(void)
continue;
if((bits & bitMarked) != 0) {
+ if(DebugMark) {
+ if(!(bits & bitSpecial))
+ runtime_printf("found spurious mark on %p\n", p);
+ *bitp &= ~(bitSpecial<<shift);
+ }
*bitp &= ~(bitMarked<<shift);
continue;
}
- if((bits & bitSpecial) != 0) {
- // Special means it has a finalizer or is being profiled.
- f = runtime_getfinalizer(p, 1);
- if(f != nil) {
- f->arg = p;
- f->next = finq;
- finq = f;
+ // Special means it has a finalizer or is being profiled.
+ // In DebugMark mode, the bit has been coopted so
+ // we have to assume all blocks are special.
+ if(DebugMark || (bits & bitSpecial) != 0) {
+ if(handlespecial(p, size))
continue;
- }
- runtime_MProf_Free(p, size);
}
// Mark freed; restore block boundary bit.
@@ -464,6 +800,23 @@ sweep(void)
static pthread_mutex_t gcsema = PTHREAD_MUTEX_INITIALIZER;
+void
+runtime_gchelper(void)
+{
+ // Wait until main proc is ready for mark help.
+ runtime_lock(&work.markgate);
+ runtime_unlock(&work.markgate);
+ scanblock(nil, 0);
+
+ // Wait until main proc is ready for sweep help.
+ runtime_lock(&work.sweepgate);
+ runtime_unlock(&work.sweepgate);
+ sweep();
+
+ if(runtime_xadd(&work.ndone, +1) == work.nproc-1)
+ runtime_notewakeup(&work.alldone);
+}
+
// Initialized from $GOGC. GOGC=off means no gc.
//
// Next gc is after we've allocated an extra amount of
@@ -481,7 +834,7 @@ runtime_gc(int32 force __attribute__ ((unused)))
int64 t0, t1, t2, t3;
uint64 heap0, heap1, obj0, obj1;
char *p;
- Finalizer *fp;
+ bool extra;
// The gc is turned off (via enablegc) until
// the bootstrap has completed.
@@ -502,10 +855,16 @@ runtime_gc(int32 force __attribute__ ((unused)))
gcpercent = -1;
else
gcpercent = runtime_atoi(p);
-
+
p = runtime_getenv("GOGCTRACE");
if(p != nil)
gctrace = runtime_atoi(p);
+
+ runtime_initlock(&work.fmu);
+ runtime_initlock(&work.emu);
+ runtime_initlock(&work.markgate);
+ runtime_initlock(&work.sweepgate);
+ runtime_initlock(&work.Lock);
}
if(gcpercent < 0)
return;
@@ -522,20 +881,42 @@ runtime_gc(int32 force __attribute__ ((unused)))
nlookup = 0;
nsizelookup = 0;
naddrlookup = 0;
+ nhandoff = 0;
m->gcing = 1;
runtime_stoptheworld();
- if(runtime_mheap.Lock.key != 0)
- runtime_throw("runtime_mheap locked during gc");
__go_cachestats();
heap0 = mstats.heap_alloc;
obj0 = mstats.nmalloc - mstats.nfree;
- mark();
+ runtime_lock(&work.markgate);
+ runtime_lock(&work.sweepgate);
+
+ extra = false;
+ work.nproc = 1;
+#if 0
+ if(runtime_gomaxprocs > 1 && runtime_ncpu > 1) {
+ runtime_noteclear(&work.alldone);
+ work.nproc += runtime_helpgc(&extra);
+ }
+#endif
+ work.nwait = 0;
+ work.ndone = 0;
+
+ runtime_unlock(&work.markgate); // let the helpers in
+ mark(scanblock);
+ if(DebugMark)
+ mark(debug_scanblock);
t1 = runtime_nanotime();
+
+ work.spans = runtime_mheap.allspans;
+ runtime_unlock(&work.sweepgate); // let the helpers in
sweep();
+ if(work.nproc > 1)
+ runtime_notesleep(&work.alldone);
t2 = runtime_nanotime();
+
__go_stealcache();
__go_cachestats();
@@ -553,21 +934,28 @@ runtime_gc(int32 force __attribute__ ((unused)))
mstats.numgc++;
if(mstats.debuggc)
runtime_printf("pause %llu\n", (unsigned long long)t3-t0);
-
+
if(gctrace) {
- runtime_printf("gc%d: %llu+%llu+%llu ms %llu -> %llu MB %llu -> %llu (%llu-%llu) objects %llu pointer lookups (%llu size, %llu addr)\n",
+ runtime_printf("gc%d: %llu+%llu+%llu ms %llu -> %llu MB %llu -> %llu (%llu-%llu) objects %llu pointer lookups (%llu size, %llu addr) %llu handoff\n",
mstats.numgc, (unsigned long long)(t1-t0)/1000000, (unsigned long long)(t2-t1)/1000000, (unsigned long long)(t3-t2)/1000000,
(unsigned long long)heap0>>20, (unsigned long long)heap1>>20, (unsigned long long)obj0, (unsigned long long)obj1,
(unsigned long long)mstats.nmalloc, (unsigned long long)mstats.nfree,
- (unsigned long long)nlookup, (unsigned long long)nsizelookup, (unsigned long long)naddrlookup);
+ (unsigned long long)nlookup, (unsigned long long)nsizelookup, (unsigned long long)naddrlookup, (unsigned long long) nhandoff);
}
pthread_mutex_unlock(&gcsema);
- runtime_starttheworld();
+
+ // If we could have used another helper proc, start one now,
+ // in the hope that it will be available next time.
+ // It would have been even better to start it before the collection,
+ // but doing so requires allocating memory, so it's tricky to
+ // coordinate. This lazy approach works out in practice:
+ // we don't mind if the first couple gc rounds don't have quite
+ // the maximum number of procs.
+ runtime_starttheworld(extra);
// finqlock is still held.
- fp = finq;
- if(fp != nil) {
+ if(finq != nil) {
// kick off or wake up goroutine to run queued finalizers
if(!finstarted) {
__go_go(runfinq, nil);
@@ -601,37 +989,44 @@ runtime_UpdateMemStats(void)
__go_cachestats();
m->gcing = 0;
pthread_mutex_unlock(&gcsema);
- runtime_starttheworld();
+ runtime_starttheworld(false);
}
static void
runfinq(void* dummy)
{
- Finalizer *f, *next;
+ Finalizer *f;
+ FinBlock *fb, *next;
+ uint32 i;
USED(dummy);
for(;;) {
pthread_mutex_lock(&finqlock);
- f = finq;
+ fb = finq;
finq = nil;
- if(f == nil) {
+ if(fb == nil) {
fingwait = 1;
pthread_cond_wait(&finqcond, &finqlock);
pthread_mutex_unlock(&finqlock);
continue;
}
pthread_mutex_unlock(&finqlock);
- for(; f; f=next) {
- void *params[1];
-
- next = f->next;
- params[0] = &f->arg;
- reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
- f->fn = nil;
- f->arg = nil;
- f->next = nil;
- runtime_free(f);
+ for(; fb; fb=next) {
+ next = fb->next;
+ for(i=0; i<(uint32)fb->cnt; i++) {
+ void *params[1];
+
+ f = &fb->fin[i];
+ params[0] = &f->arg;
+ runtime_setblockspecial(f->arg, false);
+ reflect_call(f->ft, (void*)f->fn, 0, 0, params, nil);
+ f->fn = nil;
+ f->arg = nil;
+ }
+ fb->cnt = 0;
+ fb->next = finc;
+ finc = fb;
}
runtime_gc(1); // trigger another gc to clean up the finalized objects, if possible
}
@@ -783,6 +1178,9 @@ runtime_blockspecial(void *v)
{
uintptr *b, off, shift;
+ if(DebugMark)
+ return true;
+
off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;
b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
@@ -791,17 +1189,23 @@ runtime_blockspecial(void *v)
}
void
-runtime_setblockspecial(void *v)
+runtime_setblockspecial(void *v, bool s)
{
uintptr *b, off, shift, bits, obits;
+ if(DebugMark)
+ return;
+
off = (uintptr*)v - (uintptr*)runtime_mheap.arena_start;
b = (uintptr*)runtime_mheap.arena_start - off/wordsPerBitmapWord - 1;
shift = off % wordsPerBitmapWord;
for(;;) {
obits = *b;
- bits = obits | (bitSpecial<<shift);
+ if(s)
+ bits = obits | (bitSpecial<<shift);
+ else
+ bits = obits & ~(bitSpecial<<shift);
if(runtime_singleproc) {
*b = bits;
break;
@@ -812,7 +1216,7 @@ runtime_setblockspecial(void *v)
}
}
}
-
+
void
runtime_MHeap_MapBits(MHeap *h)
{
@@ -823,7 +1227,7 @@ runtime_MHeap_MapBits(MHeap *h)
bitmapChunk = 8192
};
uintptr n;
-
+
n = (h->arena_used - h->arena_start) / wordsPerBitmapWord;
n = (n+bitmapChunk-1) & ~(bitmapChunk-1);
if(h->bitmap_mapped >= n)
diff --git a/libgo/runtime/mheap.c b/libgo/runtime/mheap.c
index cacac7d6037..a49b405a3e2 100644
--- a/libgo/runtime/mheap.c
+++ b/libgo/runtime/mheap.c
@@ -13,6 +13,7 @@
// and heapmap(i) == span for all s->start <= i < s->start+s->npages.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
static MSpan *MHeap_AllocLocked(MHeap*, uintptr, int32);
@@ -102,6 +103,7 @@ HaveSpan:
runtime_throw("MHeap_AllocLocked - bad npages");
runtime_MSpanList_Remove(s);
s->state = MSpanInUse;
+ mstats.heap_idle -= s->npages<<PageShift;
if(s->npages > npage) {
// Trim extra and put it back in the heap.
@@ -277,6 +279,7 @@ MHeap_FreeLocked(MHeap *h, MSpan *s)
// runtime_printf("MHeap_FreeLocked - span %p ptr %p state %d ref %d\n", s, s->start<<PageShift, s->state, s->ref);
runtime_throw("MHeap_FreeLocked - invalid free");
}
+ mstats.heap_idle += s->npages<<PageShift;
s->state = MSpanFree;
runtime_MSpanList_Remove(s);
sp = (uintptr*)(s->start<<PageShift);
diff --git a/libgo/runtime/mprof.goc b/libgo/runtime/mprof.goc
index d87be429d85..23c4f906f80 100644
--- a/libgo/runtime/mprof.goc
+++ b/libgo/runtime/mprof.goc
@@ -7,6 +7,7 @@
package runtime
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
#include "defs.h"
#include "go-type.h"
diff --git a/libgo/runtime/msize.c b/libgo/runtime/msize.c
index 6e82885bab4..e2672b07f9a 100644
--- a/libgo/runtime/msize.c
+++ b/libgo/runtime/msize.c
@@ -26,6 +26,7 @@
// TODO(rsc): Compute max waste for any given size.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
int32 runtime_class_to_size[NumSizeClasses];
diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c
index bbdf894f49d..8af6935b37b 100644
--- a/libgo/runtime/proc.c
+++ b/libgo/runtime/proc.c
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
+#include "arch.h"
#include "malloc.h" /* so that acid generated from proc.c includes malloc data structures */
typedef struct Sched Sched;
@@ -71,3 +72,21 @@ runtime_setcpuprofilerate(void (*fn)(uintptr*, int32), int32 hz)
if(hz != 0)
runtime_resetcpuprofiler(hz);
}
+
+/* The entersyscall and exitsyscall functions aren't used for anything
+ yet. Eventually they will be used to switch to a new OS thread
+ when making a potentially-blocking library call. */
+
+void runtime_entersyscall() __asm__("libgo_syscall.syscall.entersyscall");
+
+void
+runtime_entersyscall()
+{
+}
+
+void runtime_exitsyscall() __asm__("libgo_syscall.syscall.exitsyscall");
+
+void
+runtime_exitsyscall()
+{
+}
diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h
index ddc99eb6fb7..2767dd8b60b 100644
--- a/libgo/runtime/runtime.h
+++ b/libgo/runtime/runtime.h
@@ -136,7 +136,7 @@ bool __go_sigsend(int32 sig);
int64 runtime_nanotime(void);
void runtime_stoptheworld(void);
-void runtime_starttheworld(void);
+void runtime_starttheworld(bool);
void __go_go(void (*pfn)(void*), void*);
void __go_gc_goroutine_init(void*);
void __go_enable_gc(void);
@@ -184,18 +184,21 @@ void runtime_notewakeup(Note*);
MCache* runtime_allocmcache(void);
void free(void *v);
struct __go_func_type;
-void runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *);
-void runtime_walkfintab(void (*fn)(void*), void (*scan)(byte *, int64));
+bool runtime_addfinalizer(void*, void(*fn)(void*), const struct __go_func_type *);
#define runtime_mmap mmap
#define runtime_munmap(p, s) munmap((p), (s))
#define runtime_cas(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
#define runtime_casp(pval, old, new) __sync_bool_compare_and_swap (pval, old, new)
+#define runtime_xadd(p, v) __sync_add_and_fetch (p, v)
void runtime_sigprof(uint8 *pc, uint8 *sp, uint8 *lr);
void runtime_cpuprofinit(void);
void runtime_resetcpuprofiler(int32);
void runtime_setcpuprofilerate(void(*)(uintptr*, int32), int32);
uint32 runtime_fastrand1(void);
+void runtime_procyield(uint32);
+void runtime_osyield(void);
+void runtime_usleep(uint32);
struct __go_func_type;
void reflect_call(const struct __go_func_type *, const void *, _Bool, _Bool,
diff --git a/libgo/runtime/sigqueue.goc b/libgo/runtime/sigqueue.goc
index 2e4722238a4..3a908680ece 100644
--- a/libgo/runtime/sigqueue.goc
+++ b/libgo/runtime/sigqueue.goc
@@ -39,6 +39,7 @@
package runtime
#include "config.h"
#include "runtime.h"
+#include "arch.h"
#include "malloc.h"
#include "defs.h"
diff --git a/libgo/runtime/thread.c b/libgo/runtime/thread.c
index bac3f7dfdc1..822d5da0cac 100644
--- a/libgo/runtime/thread.c
+++ b/libgo/runtime/thread.c
@@ -14,19 +14,6 @@ runtime_initlock(Lock *l)
runtime_throw("sem_init failed");
}
-static uint32
-runtime_xadd(uint32 volatile *val, int32 delta)
-{
- uint32 oval, nval;
-
- for(;;){
- oval = *val;
- nval = oval + delta;
- if(runtime_cas(val, oval, nval))
- return nval;
- }
-}
-
// noinline so that runtime_lock doesn't have to split the stack.
static void runtime_lock_full(Lock *l) __attribute__ ((noinline));
diff --git a/libgo/runtime/yield.c b/libgo/runtime/yield.c
new file mode 100644
index 00000000000..4c2204d3538
--- /dev/null
+++ b/libgo/runtime/yield.c
@@ -0,0 +1,54 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#define _GNU_SOURCE
+
+#include "config.h"
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sched.h>
+#include <unistd.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#include "runtime.h"
+
+/* Spin wait. */
+
+void
+runtime_procyield (uint32 cnt)
+{
+ volatile uint32 i;
+
+ for (i = 0; i < cnt; ++i)
+ {
+#if defined (__i386__) || defined (__x86_64__)
+ __builtin_ia32_pause ();
+#endif
+ }
+}
+
+/* Ask the OS to reschedule this thread. */
+
+void
+runtime_osyield (void)
+{
+ sched_yield ();
+}
+
+/* Sleep for some number of microseconds. */
+
+void
+runtime_usleep (uint32 us)
+{
+ struct timeval tv;
+
+ tv.tv_sec = us / 1000000;
+ tv.tv_usec = us % 1000000;
+ select (0, NULL, NULL, NULL, &tv);
+}
diff --git a/libgo/syscalls/errno.c b/libgo/syscalls/errno.c
deleted file mode 100644
index 34771a0d831..00000000000
--- a/libgo/syscalls/errno.c
+++ /dev/null
@@ -1,25 +0,0 @@
-/* errno.c -- functions for getting and setting errno
-
- Copyright 2010 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include <errno.h>
-
-/* errno is typically a macro. These functions set
- and get errno specific to the libc being used. */
-
-int GetErrno() asm ("libgo_syscalls.syscall.GetErrno");
-void SetErrno(int) asm ("libgo_syscalls.syscall.SetErrno");
-
-int
-GetErrno()
-{
- return errno;
-}
-
-void
-SetErrno(int value)
-{
- errno = value;
-}
diff --git a/libgo/syscalls/errstr.go b/libgo/syscalls/errstr.go
deleted file mode 100644
index a95abc686f3..00000000000
--- a/libgo/syscalls/errstr.go
+++ /dev/null
@@ -1,24 +0,0 @@
-// errstr.go -- Error strings.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func Errstr(errno int) string {
- for len := Size_t(128); ; len *= 2 {
- b := make([]byte, len)
- r := libc_strerror_r(errno, &b[0], len)
- if r >= 0 {
- i := 0
- for b[i] != 0 {
- i++
- }
- return string(b[:i])
- }
- if GetErrno() != ERANGE {
- return "Errstr failure"
- }
- }
-}
diff --git a/libgo/syscalls/errstr_decl.go b/libgo/syscalls/errstr_decl.go
deleted file mode 100644
index b6bff0fb00b..00000000000
--- a/libgo/syscalls/errstr_decl.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// errstr.go -- Declare strerror_r.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_strerror_r(int, *byte, Size_t) int __asm__ ("strerror_r")
diff --git a/libgo/syscalls/errstr_decl_linux.go b/libgo/syscalls/errstr_decl_linux.go
deleted file mode 100644
index 4c1cb82a073..00000000000
--- a/libgo/syscalls/errstr_decl_linux.go
+++ /dev/null
@@ -1,9 +0,0 @@
-// errstr_decl_linux.go -- Declare strerror_r for GNU/Linux.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_strerror_r(int, *byte, Size_t) int __asm__ ("__xpg_strerror_r")
diff --git a/libgo/syscalls/errstr_decl_rtems.go b/libgo/syscalls/errstr_decl_rtems.go
deleted file mode 100644
index b83eedc8e1c..00000000000
--- a/libgo/syscalls/errstr_decl_rtems.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// errstr.go -- Declare strerror_r for RTEMS.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-// RTEMS uses strerror_r in newlib, which is a GNU extension returning a char *.
-func libc_strerror_r(int, *byte, Size_t) *byte __asm__ ("strerror_r")
diff --git a/libgo/syscalls/errstr_nor.go b/libgo/syscalls/errstr_nor.go
deleted file mode 100644
index 358b3ee9cf6..00000000000
--- a/libgo/syscalls/errstr_nor.go
+++ /dev/null
@@ -1,32 +0,0 @@
-// errstr.go -- Error strings when there is no strerror_r.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import (
- "sync"
- "unsafe"
-)
-
-func libc_strerror(int) *byte __asm__ ("strerror")
-
-var errstr_lock sync.Mutex
-
-func Errstr(errno int) string {
- errstr_lock.Lock()
-
- bp := libc_strerror(errno)
- b := (*[1000]byte)(unsafe.Pointer(bp))
- i := 0
- for b[i] != 0 {
- i++
- }
- s := string(b[:i])
-
- errstr_lock.Unlock()
-
- return s
-}
diff --git a/libgo/syscalls/errstr_rtems.go b/libgo/syscalls/errstr_rtems.go
deleted file mode 100644
index f6b453bdc73..00000000000
--- a/libgo/syscalls/errstr_rtems.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// errstr_rtems.go -- RTEMS specific error strings.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func Errstr(errno int) string {
- for len := Size_t(128); ; len *= 2 {
- b := make([]byte, len+1)
-
- // The newlib strerror_r always returns the string in buffer.
- libc_strerror_r(errno, &b[0], len)
- b[len] = 0
-
- i := 0
- for b[i] != 0 {
- i++
- }
-
- if Size_t(i) < len {
- return string(b[0:i])
- }
- }
-}
diff --git a/libgo/syscalls/exec.go b/libgo/syscalls/exec.go
deleted file mode 100644
index 8ad45f9aea5..00000000000
--- a/libgo/syscalls/exec.go
+++ /dev/null
@@ -1,346 +0,0 @@
-// exec.go -- fork/exec syscall support.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Fork, exec, wait, etc.
-
-package syscall
-
-import "unsafe"
-
-func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl")
-func libc_fork() Pid_t __asm__ ("fork")
-func libc_setsid() Pid_t __asm__ ("setsid")
-func libc_setpgid(Pid_t, Pid_t) int __asm__ ("setpgid")
-func libc_chroot(path *byte) int __asm__ ("chroot")
-func libc_setuid(Uid_t) int __asm__ ("setuid")
-func libc_setgid(Gid_t) int __asm__ ("setgid")
-func libc_setgroups(Size_t, *Gid_t) int __asm__ ("setgroups")
-func libc_chdir(name *byte) int __asm__ ("chdir")
-func libc_dup2(int, int) int __asm__ ("dup2")
-func libc_ioctl(int, int) int __asm__ ("ioctl")
-func libc_execve(*byte, **byte, **byte) int __asm__ ("execve")
-func libc_sysexit(int) __asm__ ("_exit")
-
-// Fork, dup fd onto 0..len(fd), and exec(argv0, argvv, envv) in child.
-// If a dup or exec fails, write the errno int to pipe.
-// (Pipe is close-on-exec so if exec succeeds, it will be closed.)
-// In the child, this function must not acquire any locks, because
-// they might have been locked at the time of the fork. This means
-// no rescheduling, no malloc calls, and no new stack segments.
-func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr *ProcAttr, sys *SysProcAttr, pipe int) (pid int, err int) {
- // Declare all variables at top in case any
- // declarations require heap allocation (e.g., err1).
- var r1, r2, err1 uintptr
- var nextfd int
- var i int
-
- // guard against side effects of shuffling fds below.
- fd := append([]int(nil), attr.Files...)
-
- darwin := OS == "darwin"
-
- // About to call fork.
- // No more allocation or calls of non-assembly functions.
- child := libc_fork()
- if child == -1 {
- return 0, GetErrno()
- }
-
- if child != 0 {
- // parent; return PID
- return int(child), 0
- }
-
- // Fork succeeded, now in child.
-
- // Enable tracing if requested.
- if sys.Ptrace {
- if libc_ptrace(_PTRACE_TRACEME, 0, 0, nil) < 0 {
- goto childerror
- }
- }
-
- // Session ID
- if sys.Setsid {
- if libc_setsid() == Pid_t(-1) {
- goto childerror
- }
- }
-
- // Set process group
- if sys.Setpgid {
- if libc_setpgid(0, 0) < 0 {
- goto childerror
- }
- }
-
- // Chroot
- if chroot != nil {
- if libc_chroot(chroot) < 0 {
- goto childerror
- }
- }
-
- // User and groups
- if cred := sys.Credential; cred != nil {
- ngroups := uintptr(len(cred.Groups))
- var groups *Gid_t
- if ngroups > 0 {
- groups = (*Gid_t)(unsafe.Pointer(&cred.Groups[0]))
- }
- if libc_setgroups(Size_t(ngroups), groups) < 0 {
- goto childerror
- }
- if libc_setgid(Gid_t(cred.Gid)) < 0 {
- goto childerror
- }
- if libc_setuid(Uid_t(cred.Uid)) < 0 {
- goto childerror
- }
- }
-
- // Chdir
- if dir != nil {
- if libc_chdir(dir) < 0 {
- goto childerror
- }
- }
-
- // Pass 1: look for fd[i] < i and move those up above len(fd)
- // so that pass 2 won't stomp on an fd it needs later.
- nextfd = int(len(fd))
- if pipe < nextfd {
- r := libc_dup2(pipe, nextfd)
- if r == -1 {
- goto childerror
- }
- libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
- pipe = nextfd
- nextfd++
- }
- for i = 0; i < len(fd); i++ {
- if fd[i] >= 0 && fd[i] < int(i) {
- r := libc_dup2(fd[i], nextfd)
- if r == -1 {
- goto childerror
- }
- libc_fcntl(nextfd, F_SETFD, FD_CLOEXEC)
- fd[i] = nextfd
- nextfd++
- if nextfd == pipe { // don't stomp on pipe
- nextfd++
- }
- }
- }
-
- // Pass 2: dup fd[i] down onto i.
- for i = 0; i < len(fd); i++ {
- if fd[i] == -1 {
- libc_close(i)
- continue
- }
- if fd[i] == int(i) {
- // dup2(i, i) won't clear close-on-exec flag on Linux,
- // probably not elsewhere either.
- r := libc_fcntl(fd[i], F_SETFD, 0)
- if r != 0 {
- goto childerror
- }
- continue
- }
- // The new fd is created NOT close-on-exec,
- // which is exactly what we want.
- r := libc_dup2(fd[i], i)
- if r == -1 {
- goto childerror
- }
- }
-
- // By convention, we don't close-on-exec the fds we are
- // started with, so if len(fd) < 3, close 0, 1, 2 as needed.
- // Programs that know they inherit fds >= 3 will need
- // to set them close-on-exec.
- for i = len(fd); i < 3; i++ {
- libc_close(i)
- }
-
- // Detach fd 0 from tty
- if sys.Noctty {
- if libc_ioctl(0, TIOCNOTTY) < 0 {
- goto childerror
- }
- }
-
- // Make fd 0 the tty
- if sys.Setctty {
- if libc_ioctl(0, TIOCSCTTY) < 0 {
- goto childerror
- }
- }
-
- // Time to exec.
- libc_execve(argv0, &argv[0], &envv[0])
-
-childerror:
- // send error code on pipe
- var e uintptr = uintptr(GetErrno())
- libc_write(pipe, (*byte)(unsafe.Pointer(&e)),
- Size_t(unsafe.Sizeof(err1)))
- for {
- libc_sysexit(253)
- }
-
- // Calling panic is not actually safe,
- // but the for loop above won't break
- // and this shuts up the compiler.
- panic("unreached")
-}
-
-// Credential holds user and group identities to be assumed
-// by a child process started by StartProcess.
-type Credential struct {
- Uid uint32 // User ID.
- Gid uint32 // Group ID.
- Groups []uint32 // Supplementary group IDs.
-}
-
-// ProcAttr holds attributes that will be applied to a new process started
-// by StartProcess.
-type ProcAttr struct {
- Dir string // Current working directory.
- Env []string // Environment.
- Files []int // File descriptors.
- Sys *SysProcAttr
-}
-
-type SysProcAttr struct {
- Chroot string // Chroot.
- Credential *Credential // Credential.
- Ptrace bool // Enable tracing.
- Setsid bool // Create session.
- Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
- Setctty bool // Set controlling terminal to fd 0
- Noctty bool // Detach fd 0 from controlling terminal
-}
-
-var zeroProcAttr ProcAttr
-var zeroSysProcAttr SysProcAttr
-
-func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
- var p [2]int
- var n Ssize_t
- var r1 int
- var err1 uintptr
- var wstatus WaitStatus
-
- if attr == nil {
- attr = &zeroProcAttr
- }
- sys := attr.Sys
- if sys == nil {
- sys = &zeroSysProcAttr
- }
-
- p[0] = -1
- p[1] = -1
-
- // Convert args to C form.
- argv0p := StringBytePtr(argv0)
- argvp := StringArrayPtr(argv)
- envvp := StringArrayPtr(attr.Env)
-
- if OS == "freebsd" && len(argv[0]) > len(argv0) {
- argvp[0] = argv0p
- }
-
- var chroot *byte
- if sys.Chroot != "" {
- chroot = StringBytePtr(sys.Chroot)
- }
- var dir *byte
- if attr.Dir != "" {
- dir = StringBytePtr(attr.Dir)
- }
-
- // Acquire the fork lock so that no other threads
- // create new fds that are not yet close-on-exec
- // before we fork.
- ForkLock.Lock()
-
- // Allocate child status pipe close on exec.
- if err = Pipe(p[0:]); err != 0 {
- goto error
- }
- if _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC); err != 0 {
- goto error
- }
- if _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC); err != 0 {
- goto error
- }
-
- // Kick off child.
- pid, err = forkAndExecInChild(argv0p, argvp, envvp, chroot, dir, attr, sys, p[1])
- if err != 0 {
- goto error
- }
- ForkLock.Unlock()
-
- // Read child error status from pipe.
- Close(p[1])
- n = libc_read(p[0], (*byte)(unsafe.Pointer(&err1)),
- Size_t(unsafe.Sizeof(err1)))
- err = 0
- if n < 0 {
- err = GetErrno()
- }
- Close(p[0])
- if err != 0 || n != 0 {
- if int(n) == unsafe.Sizeof(err1) {
- err = int(err1)
- }
- if err == 0 {
- err = EPIPE
- }
-
- // Child failed; wait for it to exit, to make sure
- // the zombies don't accumulate.
- _, err1 := Wait4(pid, &wstatus, 0, nil)
- for err1 == EINTR {
- _, err1 = Wait4(pid, &wstatus, 0, nil)
- }
- return 0, err
- }
-
- // Read got EOF, so pipe closed on exec, so exec succeeded.
- return pid, 0
-
-error:
- if p[0] >= 0 {
- Close(p[0])
- Close(p[1])
- }
- ForkLock.Unlock()
- return 0, err
-}
-
-// Combination of fork and exec, careful to be thread safe.
-func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err int) {
- return forkExec(argv0, argv, attr)
-}
-
-// StartProcess wraps ForkExec for package os.
-func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid, handle int, err int) {
- pid, err = forkExec(argv0, argv, attr)
- return pid, 0, err
-}
-
-// Ordinary exec.
-func Exec(argv0 string, argv []string, envv []string) (err int) {
- argv_arg := StringArrayPtr(argv)
- envv_arg := StringArrayPtr(envv)
- libc_execve(StringBytePtr(argv0), &argv_arg[0], &envv_arg[0])
- return GetErrno()
-}
diff --git a/libgo/syscalls/exec_helpers.go b/libgo/syscalls/exec_helpers.go
deleted file mode 100644
index c8a68a058b3..00000000000
--- a/libgo/syscalls/exec_helpers.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// exec_helpers.go -- helper functions used with fork, exec, wait.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "sync"
-
-// Lock synchronizing creation of new file descriptors with fork.
-//
-// We want the child in a fork/exec sequence to inherit only the
-// file descriptors we intend. To do that, we mark all file
-// descriptors close-on-exec and then, in the child, explicitly
-// unmark the ones we want the exec'ed program to keep.
-// Unix doesn't make this easy: there is, in general, no way to
-// allocate a new file descriptor close-on-exec. Instead you
-// have to allocate the descriptor and then mark it close-on-exec.
-// If a fork happens between those two events, the child's exec
-// will inherit an unwanted file descriptor.
-//
-// This lock solves that race: the create new fd/mark close-on-exec
-// operation is done holding ForkLock for reading, and the fork itself
-// is done holding ForkLock for writing. At least, that's the idea.
-// There are some complications.
-//
-// Some system calls that create new file descriptors can block
-// for arbitrarily long times: open on a hung NFS server or named
-// pipe, accept on a socket, and so on. We can't reasonably grab
-// the lock across those operations.
-//
-// It is worse to inherit some file descriptors than others.
-// If a non-malicious child accidentally inherits an open ordinary file,
-// that's not a big deal. On the other hand, if a long-lived child
-// accidentally inherits the write end of a pipe, then the reader
-// of that pipe will not see EOF until that child exits, potentially
-// causing the parent program to hang. This is a common problem
-// in threaded C programs that use popen.
-//
-// Luckily, the file descriptors that are most important not to
-// inherit are not the ones that can take an arbitrarily long time
-// to create: pipe returns instantly, and the net package uses
-// non-blocking I/O to accept on a listening socket.
-// The rules for which file descriptor-creating operations use the
-// ForkLock are as follows:
-//
-// 1) Pipe. Does not block. Use the ForkLock.
-// 2) Socket. Does not block. Use the ForkLock.
-// 3) Accept. If using non-blocking mode, use the ForkLock.
-// Otherwise, live with the race.
-// 4) Open. Can block. Use O_CLOEXEC if available (Linux).
-// Otherwise, live with the race.
-// 5) Dup. Does not block. Use the ForkLock.
-// On Linux, could use fcntl F_DUPFD_CLOEXEC
-// instead of the ForkLock, but only for dup(fd, -1).
-
-type WaitStatus int
-
-var ForkLock sync.RWMutex
-
-// Convert array of string to array
-// of NUL-terminated byte pointer.
-func StringArrayPtr(ss []string) []*byte {
- bb := make([]*byte, len(ss)+1);
- for i := 0; i < len(ss); i++ {
- bb[i] = StringBytePtr(ss[i]);
- }
- bb[len(ss)] = nil;
- return bb;
-}
-
-func CloseOnExec(fd int) {
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-}
-
-func SetNonblock(fd int, nonblocking bool) (errno int) {
- flag, err := fcntl(fd, F_GETFL, 0);
- if err != 0 {
- return err;
- }
- if nonblocking {
- flag |= O_NONBLOCK;
- } else {
- flag &= ^O_NONBLOCK;
- }
- flag, err = fcntl(fd, F_SETFL, flag);
- return err;
-}
-
-// Wait status is 7 bits at bottom, either 0 (exited),
-// 0x7F (stopped), or a signal number that caused an exit.
-// The 0x80 bit is whether there was a core dump.
-// An extra number (exit code, signal causing a stop)
-// is in the high bits. At least that's the idea.
-// There are various irregularities. For example, the
-// "continued" status is 0xFFFF, distinguishing itself
-// from stopped via the core dump bit.
-
-const (
- mask = 0x7F;
- core = 0x80;
- exited = 0x00;
- stopped = 0x7F;
- shift = 8;
-)
-
-func (w WaitStatus) Exited() bool {
- return w&mask == exited;
-}
-
-func (w WaitStatus) Signaled() bool {
- return w&mask != stopped && w&mask != exited;
-}
-
-func (w WaitStatus) Stopped() bool {
- return w&0xFF == stopped;
-}
-
-func (w WaitStatus) Continued() bool {
- return w == 0xFFFF;
-}
-
-func (w WaitStatus) CoreDump() bool {
- return w.Signaled() && w&core != 0;
-}
-
-func (w WaitStatus) ExitStatus() int {
- if !w.Exited() {
- return -1;
- }
- return int(w >> shift) & 0xFF;
-}
-
-func (w WaitStatus) Signal() int {
- if !w.Signaled() {
- return -1;
- }
- return int(w & mask);
-}
-
-func (w WaitStatus) StopSignal() int {
- if !w.Stopped() {
- return -1;
- }
- return int(w >> shift) & 0xFF;
-}
-
-func (w WaitStatus) TrapCause() int {
- if w.StopSignal() != SIGTRAP {
- return -1;
- }
- return int(w >> shift) >> 8;
-}
diff --git a/libgo/syscalls/exec_stubs.go b/libgo/syscalls/exec_stubs.go
deleted file mode 100644
index 7b4346cc4c5..00000000000
--- a/libgo/syscalls/exec_stubs.go
+++ /dev/null
@@ -1,25 +0,0 @@
-// exec_stubs.go -- fork/exec stubs.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Stubs for fork, exec and wait.
-
-package syscall
-
-func ForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
- return -1, ENOSYS;
-}
-
-func PtraceForkExec(argv0 string, argv []string, envv []string, dir string, fd []int) (pid int, err int) {
- return -1, ENOSYS;
-}
-
-func Exec(argv0 string, argv []string, envv []string) (err int) {
- return ENOSYS;
-}
-
-func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
- return -1, ENOSYS;
-}
diff --git a/libgo/syscalls/netlink_linux.go b/libgo/syscalls/netlink_linux.go
deleted file mode 100644
index 6f621cee69c..00000000000
--- a/libgo/syscalls/netlink_linux.go
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Netlink sockets and messages
-
-package syscall
-
-import (
- "unsafe"
-)
-
-// Round the length of a netlink message up to align it properly.
-func nlmAlignOf(msglen int) int {
- return (msglen + NLMSG_ALIGNTO - 1) & ^(NLMSG_ALIGNTO - 1)
-}
-
-// Round the length of a netlink route attribute up to align it
-// properly.
-func rtaAlignOf(attrlen int) int {
- return (attrlen + RTA_ALIGNTO - 1) & ^(RTA_ALIGNTO - 1)
-}
-
-// NetlinkRouteRequest represents the request message to receive
-// routing and link states from the kernel.
-type NetlinkRouteRequest struct {
- Header NlMsghdr
- Data RtGenmsg
-}
-
-func (rr *NetlinkRouteRequest) toWireFormat() []byte {
- b := make([]byte, rr.Header.Len)
- b[0] = byte(rr.Header.Len)
- b[1] = byte(rr.Header.Len >> 8)
- b[2] = byte(rr.Header.Len >> 16)
- b[3] = byte(rr.Header.Len >> 24)
- b[4] = byte(rr.Header.Type)
- b[5] = byte(rr.Header.Type >> 8)
- b[6] = byte(rr.Header.Flags)
- b[7] = byte(rr.Header.Flags >> 8)
- b[8] = byte(rr.Header.Seq)
- b[9] = byte(rr.Header.Seq >> 8)
- b[10] = byte(rr.Header.Seq >> 16)
- b[11] = byte(rr.Header.Seq >> 24)
- b[12] = byte(rr.Header.Pid)
- b[13] = byte(rr.Header.Pid >> 8)
- b[14] = byte(rr.Header.Pid >> 16)
- b[15] = byte(rr.Header.Pid >> 24)
- b[16] = byte(rr.Data.Family)
- return b
-}
-
-func newNetlinkRouteRequest(proto, seq, family int) []byte {
- rr := &NetlinkRouteRequest{}
- rr.Header.Len = uint32(NLMSG_HDRLEN + SizeofRtGenmsg)
- rr.Header.Type = uint16(proto)
- rr.Header.Flags = NLM_F_DUMP | NLM_F_REQUEST
- rr.Header.Seq = uint32(seq)
- rr.Data.Family = uint8(family)
- return rr.toWireFormat()
-}
-
-// NetlinkRIB returns routing information base, as known as RIB,
-// which consists of network facility information, states and
-// parameters.
-func NetlinkRIB(proto, family int) ([]byte, int) {
- var (
- s int
- e int
- lsanl SockaddrNetlink
- seq int
- tab []byte
- )
-
- s, e = Socket(AF_NETLINK, SOCK_RAW, 0)
- if e != 0 {
- return nil, e
- }
- defer Close(s)
-
- lsanl.Family = AF_NETLINK
- e = Bind(s, &lsanl)
- if e != 0 {
- return nil, e
- }
-
- seq++
- wb := newNetlinkRouteRequest(proto, seq, family)
- e = Sendto(s, wb, 0, &lsanl)
- if e != 0 {
- return nil, e
- }
-
- for {
- var (
- rb []byte
- nr int
- lsa Sockaddr
- )
-
- rb = make([]byte, Getpagesize())
- nr, _, e = Recvfrom(s, rb, 0)
- if e != 0 {
- return nil, e
- }
- if nr < NLMSG_HDRLEN {
- return nil, EINVAL
- }
- rb = rb[:nr]
- tab = append(tab, rb...)
-
- msgs, _ := ParseNetlinkMessage(rb)
- for _, m := range msgs {
- if lsa, e = Getsockname(s); e != 0 {
- return nil, e
- }
- switch v := lsa.(type) {
- case *SockaddrNetlink:
- if m.Header.Seq != uint32(seq) || m.Header.Pid != v.Pid {
- return nil, EINVAL
- }
- default:
- return nil, EINVAL
- }
- if m.Header.Type == NLMSG_DONE {
- goto done
- }
- if m.Header.Type == NLMSG_ERROR {
- return nil, EINVAL
- }
- }
- }
-
-done:
- return tab, 0
-}
-
-// NetlinkMessage represents the netlink message.
-type NetlinkMessage struct {
- Header NlMsghdr
- Data []byte
-}
-
-// ParseNetlinkMessage parses buf as netlink messages and returns
-// the slice containing the NetlinkMessage structs.
-func ParseNetlinkMessage(buf []byte) ([]NetlinkMessage, int) {
- var (
- h *NlMsghdr
- dbuf []byte
- dlen int
- e int
- msgs []NetlinkMessage
- )
-
- for len(buf) >= NLMSG_HDRLEN {
- h, dbuf, dlen, e = netlinkMessageHeaderAndData(buf)
- if e != 0 {
- break
- }
- m := NetlinkMessage{}
- m.Header = *h
- m.Data = dbuf[:int(h.Len)-NLMSG_HDRLEN]
- msgs = append(msgs, m)
- buf = buf[dlen:]
- }
-
- return msgs, e
-}
-
-func netlinkMessageHeaderAndData(buf []byte) (*NlMsghdr, []byte, int, int) {
- h := (*NlMsghdr)(unsafe.Pointer(&buf[0]))
- if int(h.Len) < NLMSG_HDRLEN || int(h.Len) > len(buf) {
- return nil, nil, 0, EINVAL
- }
- return h, buf[NLMSG_HDRLEN:], nlmAlignOf(int(h.Len)), 0
-}
-
-// NetlinkRouteAttr represents the netlink route attribute.
-type NetlinkRouteAttr struct {
- Attr RtAttr
- Value []byte
-}
-
-// ParseNetlinkRouteAttr parses msg's payload as netlink route
-// attributes and returns the slice containing the NetlinkRouteAttr
-// structs.
-func ParseNetlinkRouteAttr(msg *NetlinkMessage) ([]NetlinkRouteAttr, int) {
- var (
- buf []byte
- a *RtAttr
- alen int
- vbuf []byte
- e int
- attrs []NetlinkRouteAttr
- )
-
- switch msg.Header.Type {
- case RTM_NEWLINK:
- buf = msg.Data[SizeofIfInfomsg:]
- case RTM_NEWADDR:
- buf = msg.Data[SizeofIfAddrmsg:]
- default:
- return nil, EINVAL
- }
-
- for len(buf) >= SizeofRtAttr {
- a, vbuf, alen, e = netlinkRouteAttrAndValue(buf)
- if e != 0 {
- break
- }
- ra := NetlinkRouteAttr{}
- ra.Attr = *a
- ra.Value = vbuf[:int(a.Len)-SizeofRtAttr]
- attrs = append(attrs, ra)
- buf = buf[alen:]
- }
-
- return attrs, 0
-}
-
-func netlinkRouteAttrAndValue(buf []byte) (*RtAttr, []byte, int, int) {
- h := (*RtAttr)(unsafe.Pointer(&buf[0]))
- if int(h.Len) < SizeofRtAttr || int(h.Len) > len(buf) {
- return nil, nil, 0, EINVAL
- }
- return h, buf[SizeofRtAttr:], rtaAlignOf(int(h.Len)), 0
-}
diff --git a/libgo/syscalls/sleep_rtems.go b/libgo/syscalls/sleep_rtems.go
deleted file mode 100644
index 8a9ae8a30fe..00000000000
--- a/libgo/syscalls/sleep_rtems.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// sleep_rtems.go -- Sleep on RTEMS.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_nanosleep(req *Timespec, rem *Timespec) int __asm__ ("nanosleep")
-
-func Sleep(nsec int64) (errno int) {
- errno = 0
- ts := NsecToTimespec(nsec)
- r := libc_nanosleep(&ts, nil)
- if r < 0 {
- errno = GetErrno()
- }
- return
-}
diff --git a/libgo/syscalls/sleep_select.go b/libgo/syscalls/sleep_select.go
deleted file mode 100644
index 6fc13a0ea5e..00000000000
--- a/libgo/syscalls/sleep_select.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// sleep_select.go -- Sleep using select.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func Sleep(nsec int64) (errno int) {
- tv := NsecToTimeval(nsec);
- n, err := Select(0, nil, nil, nil, &tv);
- return err;
-}
diff --git a/libgo/syscalls/socket.go b/libgo/syscalls/socket.go
deleted file mode 100644
index be7a89b7ff2..00000000000
--- a/libgo/syscalls/socket.go
+++ /dev/null
@@ -1,392 +0,0 @@
-// socket.go -- Socket handling.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Low-level socket interface.
-// Only for implementing net package.
-// DO NOT USE DIRECTLY.
-
-package syscall
-
-import "unsafe"
-
-type RawSockaddrAny struct {
- Addr RawSockaddr;
- Pad [12]int8;
-}
-
-const SizeofSockaddrAny = 0x1c;
-
-// For testing: clients can set this flag to force
-// creation of IPv6 sockets to return EAFNOSUPPORT.
-var SocketDisableIPv6 bool
-
-type Sockaddr interface {
- sockaddr() (ptr *RawSockaddrAny, len Socklen_t, errno int); // lowercase; only we can define Sockaddrs
-}
-
-type SockaddrInet4 struct {
- Port int;
- Addr [4]byte;
- raw RawSockaddrInet4;
-}
-
-type SockaddrInet6 struct {
- Port int;
- Addr [16]byte;
- raw RawSockaddrInet6;
-}
-
-type SockaddrUnix struct {
- Name string;
- raw RawSockaddrUnix;
-}
-
-type Linger struct {
- Onoff int32;
- Linger int32;
-}
-
-func (sa *SockaddrInet4) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
- if sa.Port < 0 || sa.Port > 0xFFFF {
- return nil, 0, EINVAL;
- }
- sa.raw.Family = AF_INET;
- n := sa.raw.setLen()
- p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
- p[0] = byte(sa.Port>>8);
- p[1] = byte(sa.Port);
- for i := 0; i < len(sa.Addr); i++ {
- sa.raw.Addr[i] = sa.Addr[i];
- }
- return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0;
-}
-
-func (sa *SockaddrInet6) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
- if sa.Port < 0 || sa.Port > 0xFFFF {
- return nil, 0, EINVAL;
- }
- sa.raw.Family = AF_INET6;
- n := sa.raw.setLen()
- p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port));
- p[0] = byte(sa.Port>>8);
- p[1] = byte(sa.Port);
- for i := 0; i < len(sa.Addr); i++ {
- sa.raw.Addr[i] = sa.Addr[i];
- }
- return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), n, 0;
-}
-
-func (sa *SockaddrUnix) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
- name := sa.Name;
- n := len(name);
- if n >= len(sa.raw.Path) || n == 0 {
- return nil, 0, EINVAL;
- }
- sa.raw.Family = AF_UNIX;
- sa.raw.setLen(n)
- for i := 0; i < n; i++ {
- sa.raw.Path[i] = int8(name[i]);
- }
- if sa.raw.Path[0] == '@' {
- sa.raw.Path[0] = 0;
- }
-
- // length is family (uint16), name, NUL.
- return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), 2 + Socklen_t(n) + 1, 0;
-}
-
-func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, int) {
- switch rsa.Addr.Family {
- case AF_UNIX:
- pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
- sa := new(SockaddrUnix)
- n, err := pp.getLen()
- if err != 0 {
- return nil, err
- }
- bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]));
- sa.Name = string(bytes[0:n]);
- return sa, 0;
-
- case AF_INET:
- pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa));
- sa := new(SockaddrInet4);
- p := (*[2]byte)(unsafe.Pointer(&pp.Port));
- sa.Port = int(p[0])<<8 + int(p[1]);
- for i := 0; i < len(sa.Addr); i++ {
- sa.Addr[i] = pp.Addr[i];
- }
- return sa, 0;
-
- case AF_INET6:
- pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa));
- sa := new(SockaddrInet6);
- p := (*[2]byte)(unsafe.Pointer(&pp.Port));
- sa.Port = int(p[0])<<8 + int(p[1]);
- for i := 0; i < len(sa.Addr); i++ {
- sa.Addr[i] = pp.Addr[i];
- }
- return sa, 0;
- }
- return anyToSockaddrOS(rsa)
-}
-
-func libc_accept(fd int, sa *RawSockaddrAny, len *Socklen_t) int __asm__ ("accept");
-func libc_bind(fd int, sa *RawSockaddrAny, len Socklen_t) int __asm__ ("bind");
-func libc_connect(fd int, sa *RawSockaddrAny, len Socklen_t) int __asm__ ("connect");
-func libc_socket(domain, typ, protocol int) int __asm__ ("socket");
-func libc_setsockopt(fd, level, optname int, optval *byte, optlen Socklen_t) int __asm__ ("setsockopt");
-func libc_listen(fd, backlog int) int __asm__ ("listen");
-func libc_getsockopt(fd, level, optname int, optval *byte, optlen *Socklen_t) int __asm__ ("getsockopt");
-func libc_getsockname(fd int, sa *RawSockaddrAny, len *Socklen_t) int __asm__ ("getsockname");
-func libc_getpeername(fd int, sa *RawSockaddrAny, len *Socklen_t) int __asm__ ("getpeername");
-func libc_recv(fd int, buf *byte, len Size_t, flags int) Ssize_t __asm__ ("recv");
-func libc_recvfrom(fd int, buf *byte, len Size_t, flags int,
- from *RawSockaddrAny, fromlen *Socklen_t) Ssize_t __asm__("recvfrom");
-func libc_recvmsg(fd int, msg *Msghdr, flags int) Ssize_t __asm__("recvmsg")
-func libc_send(fd int, buf *byte, len Size_t, flags int) Ssize_t __asm__("send");
-func libc_sendto(fd int, buf *byte, len Size_t, flags int,
- to *RawSockaddrAny, tolen Socklen_t) Ssize_t __asm__("sendto");
-func libc_sendmsg(fd int, msg *Msghdr, flags int) Ssize_t __asm__("sendmsg")
-func libc_shutdown(fd int, how int) int __asm__ ("shutdown");
-
-func Accept(fd int) (nfd int, sa Sockaddr, errno int) {
- var rsa RawSockaddrAny;
- var len Socklen_t = SizeofSockaddrAny;
- nfd = libc_accept(fd, &rsa, &len);
- if nfd < 0 {
- errno = GetErrno();
- return;
- }
- sa, errno = anyToSockaddr(&rsa);
- if errno != 0 {
- Close(nfd);
- nfd = 0;
- }
- return;
-}
-
-func Bind(fd int, sa Sockaddr) (errno int) {
- ptr, n, err := sa.sockaddr();
- if err != 0 {
- return err;
- }
- if libc_bind(fd, ptr, n) < 0 {
- errno = GetErrno();
- }
- return;
-}
-
-func Connect(fd int, sa Sockaddr) (errno int) {
- ptr, n, err := sa.sockaddr();
- if err != 0 {
- return err;
- }
- if libc_connect(fd, ptr, n) < 0 {
- errno = GetErrno();
- }
- return;
-}
-
-func Socket(domain, typ, proto int) (fd, errno int) {
- if domain == AF_INET6 && SocketDisableIPv6 {
- return -1, EAFNOSUPPORT
- }
- fd = libc_socket(int(domain), int(typ), int(proto));
- if fd < 0 {
- errno = GetErrno();
- }
- return;
-}
-
-func Listen(fd int, n int) (errno int) {
- r := libc_listen(int(fd), int(n));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func GetsockoptInt(fd, level, opt int) (value, errno int) {
- var n int32
- vallen := Socklen_t(4)
- errno = libc_getsockopt(fd, level, opt, (*byte)(unsafe.Pointer(&n)), &vallen)
- return int(n), errno
-}
-
-func setsockopt(fd, level, opt int, valueptr uintptr, length Socklen_t) (errno int) {
- r := libc_setsockopt(fd, level, opt, (*byte)(unsafe.Pointer(valueptr)),
- length);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func SetsockoptInt(fd, level, opt int, value int) (errno int) {
- var n = int32(value);
- return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&n)), 4);
-}
-
-func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (errno int) {
- return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(tv)), Socklen_t(unsafe.Sizeof(*tv)));
-}
-
-func SetsockoptLinger(fd, level, opt int, l *Linger) (errno int) {
- return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(l)), Socklen_t(unsafe.Sizeof(*l)));
-}
-
-func SetsockoptString(fd, level, opt int, s string) (errno int) {
- return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(&[]byte(s)[0])), Socklen_t(len(s)))
-}
-
-func SetsockoptIPMreq(fd, level, opt int, mreq *IPMreq) (errno int) {
- return setsockopt(fd, level, opt, uintptr(unsafe.Pointer(mreq)), unsafe.Sizeof(*mreq))
-}
-
-func Getsockname(fd int) (sa Sockaddr, errno int) {
- var rsa RawSockaddrAny;
- var len Socklen_t = SizeofSockaddrAny;
- if libc_getsockname(fd, &rsa, &len) != 0 {
- errno = GetErrno();
- return;
- }
- return anyToSockaddr(&rsa);
-}
-
-func Getpeername(fd int) (sa Sockaddr, errno int) {
- var rsa RawSockaddrAny;
- var len Socklen_t = SizeofSockaddrAny;
- if libc_getpeername(fd, &rsa, &len) != 0 {
- errno = GetErrno();
- return;
- }
- return anyToSockaddr(&rsa);
-}
-
-func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, errno int) {
- var rsa RawSockaddrAny;
- var slen Socklen_t = SizeofSockaddrAny;
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_recvfrom(fd, _p0, Size_t(len(p)), flags, &rsa, &slen);
- n = int(r);
- if r == -1 {
- errno = GetErrno();
- } else {
- from, errno = anyToSockaddr(&rsa);
- }
- return;
-}
-
-func (iov *Iovec) SetLen(length int) {
- iov.Len = Iovec_len_t(length)
-}
-
-func (msghdr *Msghdr) SetControllen(length int) {
- msghdr.Controllen = Msghdr_controllen_t(length)
-}
-
-func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn int, recvflags int, from Sockaddr, errno int) {
- var msg Msghdr
- var rsa RawSockaddrAny
- msg.Name = (*byte)(unsafe.Pointer(&rsa))
- msg.Namelen = uint32(SizeofSockaddrAny)
- var iov Iovec
- if len(p) > 0 {
- iov.Base = (*byte)(unsafe.Pointer(&p[0]))
- iov.SetLen(len(p))
- }
- var dummy byte
- if len(oob) > 0 {
- // receive at least one normal byte
- if len(p) == 0 {
- iov.Base = &dummy
- iov.SetLen(1)
- }
- msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
- msg.SetControllen(len(oob))
- }
- msg.Iov = &iov
- msg.Iovlen = 1
- if n, errno = recvmsg(fd, &msg, flags); errno != 0 {
- return
- }
- oobn = int(msg.Controllen)
- recvflags = int(msg.Flags)
- // source address is only specified if the socket is unconnected
- if rsa.Addr.Family != 0 {
- from, errno = anyToSockaddr(&rsa)
- }
- return
-}
-
-func recvmsg(s int, msg *Msghdr, flags int) (n int, errno int) {
- r := libc_recvmsg(s, msg, flags)
- if r < 0 {
- errno = GetErrno()
- } else {
- n = int(r)
- }
- return
-}
-
-func Sendto(fd int, p []byte, flags int, to Sockaddr) (errno int) {
- ptr, n, err := to.sockaddr();
- if err != 0 {
- return err;
- }
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_sendto(fd, _p0, Size_t(len(p)), flags, ptr, n);
- if r == -1 { errno = GetErrno(); }
- return;
-}
-
-func Sendmsg(fd int, p, oob []byte, to Sockaddr, flags int) (errno int) {
- var ptr *RawSockaddrAny
- var nsock Socklen_t
- if to != nil {
- var err int
- ptr, nsock, err = to.sockaddr()
- if err != 0 {
- return err
- }
- }
- var msg Msghdr
- msg.Name = (*byte)(unsafe.Pointer(ptr))
- msg.Namelen = uint32(nsock)
- var iov Iovec
- if len(p) > 0 {
- iov.Base = (*byte)(unsafe.Pointer(&p[0]))
- iov.SetLen(len(p))
- }
- var dummy byte
- if len(oob) > 0 {
- // send at least one normal byte
- if len(p) == 0 {
- iov.Base = &dummy
- iov.SetLen(1)
- }
- msg.Control = (*byte)(unsafe.Pointer(&oob[0]))
- msg.SetControllen(len(oob))
- }
- msg.Iov = &iov
- msg.Iovlen = 1
- if errno = sendmsg(fd, &msg, flags); errno != 0 {
- return
- }
- return
-}
-
-func sendmsg(s int, msg *Msghdr, flags int) (errno int) {
- if libc_sendmsg(s, msg, flags) < 0 {
- errno = GetErrno()
- }
- return
-}
-
-func Shutdown(fd int, how int) (errno int) {
- r := libc_shutdown(fd, how);
- if r < 0 { errno = GetErrno() }
- return;
-}
diff --git a/libgo/syscalls/socket_epoll.go b/libgo/syscalls/socket_epoll.go
deleted file mode 100644
index 0013f33498f..00000000000
--- a/libgo/syscalls/socket_epoll.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// socket_epoll.go -- GNU/Linux epoll handling.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Support for GNU/Linux epoll.
-// Only for implementing net package.
-// DO NOT USE DIRECTLY.
-
-package syscall
-
-// We don't take this type directly from the header file because it
-// uses a union. FIXME.
-
-type EpollEvent struct {
- Events uint32;
- Fd int32;
- Pad int32;
-};
-
-func libc_epoll_create(size int) int __asm__ ("epoll_create");
-func libc_epoll_ctl(epfd, op, fd int, event *EpollEvent) int __asm__ ("epoll_ctl");
-func libc_epoll_wait(epfd int, events *EpollEvent, maxevents int,
- timeout int) int __asm__ ("epoll_wait");
-
-
-func EpollCreate(size int) (fd int, errno int) {
- fd = libc_epoll_create(int(size));
- if fd < 0 { errno = GetErrno() }
- return;
-}
-
-func EpollCtl(epfd, op, fd int, ev *EpollEvent) (errno int) {
- r := libc_epoll_ctl(epfd, op, fd, ev);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func EpollWait(epfd int, ev []EpollEvent, msec int) (n int, errno int) {
- var events *EpollEvent;
- var maxevents int;
- if len(ev) > 0 {
- maxevents = len(ev);
- events = &ev[0]
- }
- n = libc_epoll_wait(epfd, events, maxevents, msec);
- if n < 0 { errno = GetErrno() }
- return;
-}
diff --git a/libgo/syscalls/socket_irix.go b/libgo/syscalls/socket_irix.go
deleted file mode 100644
index 6f2aaaff4d0..00000000000
--- a/libgo/syscalls/socket_irix.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// socket_irix.go -- Socket handling specific to IRIX 6.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-const SizeofSockaddrInet4 = 16
-const SizeofSockaddrInet6 = 28
-const SizeofSockaddrUnix = 110
-
-type RawSockaddrInet4 struct {
- Family uint16
- Port uint16
- Addr [4]byte /* in_addr */
- Zero [8]uint8
-}
-
-func (sa *RawSockaddrInet4) setLen() Socklen_t {
- return SizeofSockaddrInet4
-}
-
-type RawSockaddrInet6 struct {
- Family uint16
- Port uint16
- Flowinfo uint32
- Addr [16]byte /* in6_addr */
- Scope_id uint32
-}
-
-func (sa *RawSockaddrInet6) setLen() Socklen_t {
- return SizeofSockaddrInet6
-}
-
-type RawSockaddrUnix struct {
- Family uint16
- Path [108]int8
-}
-
-func (sa *RawSockaddrUnix) setLen(int) {
-}
-
-func (sa *RawSockaddrUnix) getLen() (int, int) {
- if sa.Path[0] == 0 {
- // "Abstract" Unix domain socket.
- // Rewrite leading NUL as @ for textual display.
- // (This is the standard convention.)
- // Not friendly to overwrite in place,
- // but the callers below don't care.
- sa.Path[0] = '@'
- }
-
- // Assume path ends at NUL.
- // This is not technically the Linux semantics for
- // abstract Unix domain sockets--they are supposed
- // to be uninterpreted fixed-size binary blobs--but
- // everyone uses this convention.
- n := 0
- for n < len(sa.Path)-3 && sa.Path[n] != 0 {
- n++
- }
-
- return n, 0
-}
-
-type RawSockaddr struct {
- Family uint16
- Data [14]int8
-}
-
-// BindToDevice binds the socket associated with fd to device.
-func BindToDevice(fd int, device string) (errno int) {
- return ENOSYS
-}
-
-// struct ip_mreg is provived in <netinet/in.h>, but protected with _SGIAPI.
-// This could be enabled with -D_SGI_SOURCE, but conflicts with
-// -D_XOPEN_SOURCE=500 required for msg_control etc. in struct msghgr, so
-// simply provide it here.
-type IPMreq struct {
- Multiaddr [4]byte
- Interface [4]byte
-}
-
-// Similarly, <netdb.h> only provides struct addrinfo, AI_* and EAI_* if
-// _NO_XOPEN4 && _NO_XOPEN5.
-type Addrinfo struct {
- Ai_flags int32
- Ai_family int32
- Ai_socktype int32
- Ai_protocol int32
- Ai_addrlen int32
- Ai_canonname *uint8
- Ai_addr *_sockaddr
- Ai_next *Addrinfo
-}
-
-const (
- AI_PASSIVE = 0x00000001
- AI_CANONNAME = 0x00000002
- AI_NUMERICHOST = 0x00000004
- AI_NUMERICSERV = 0x00000008
- AI_ALL = 0x00000100
- AI_ADDRCONFIG = 0x00000400
- AI_V4MAPPED = 0x00000800
- AI_DEFAULT = (AI_V4MAPPED | AI_ADDRCONFIG)
-)
-
-const (
- EAI_ADDRFAMILY = 1
- EAI_AGAIN = 2
- EAI_BADFLAGS = 3
- EAI_FAIL = 4
- EAI_FAMILY = 5
- EAI_MEMORY = 6
- EAI_NODATA = 7
- EAI_NONAME = 8
- EAI_SERVICE = 9
- EAI_SOCKTYPE = 10
- EAI_SYSTEM = 11
- EAI_BADHINTS = 12
- EAI_OVERFLOW = 13
- EAI_MAX = 14
-)
-
-func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
- return nil, EAFNOSUPPORT;
-}
diff --git a/libgo/syscalls/socket_linux.go b/libgo/syscalls/socket_linux.go
deleted file mode 100644
index 57ea7c3ff1b..00000000000
--- a/libgo/syscalls/socket_linux.go
+++ /dev/null
@@ -1,165 +0,0 @@
-// socket_linux.go -- Socket handling specific to Linux.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-const SizeofSockaddrInet4 = 16
-const SizeofSockaddrInet6 = 28
-const SizeofSockaddrUnix = 110
-const SizeofSockaddrLinklayer = 20
-const SizeofSockaddrNetlink = 12
-
-type SockaddrLinklayer struct {
- Protocol uint16
- Ifindex int
- Hatype uint16
- Pkttype uint8
- Halen uint8
- Addr [8]byte
- raw RawSockaddrLinklayer
-}
-
-func (sa *SockaddrLinklayer) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
- if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
- return nil, 0, EINVAL
- }
- sa.raw.Family = AF_PACKET
- sa.raw.Protocol = sa.Protocol
- sa.raw.Ifindex = int32(sa.Ifindex)
- sa.raw.Hatype = sa.Hatype
- sa.raw.Pkttype = sa.Pkttype
- sa.raw.Halen = sa.Halen
- for i := 0; i < len(sa.Addr); i++ {
- sa.raw.Addr[i] = sa.Addr[i]
- }
- return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrLinklayer, 0
-}
-
-type SockaddrNetlink struct {
- Family uint16
- Pad uint16
- Pid uint32
- Groups uint32
- raw RawSockaddrNetlink
-}
-
-func (sa *SockaddrNetlink) sockaddr() (*RawSockaddrAny, Socklen_t, int) {
- sa.raw.Family = AF_NETLINK
- sa.raw.Pad = sa.Pad
- sa.raw.Pid = sa.Pid
- sa.raw.Groups = sa.Groups
- return (*RawSockaddrAny)(unsafe.Pointer(&sa.raw)), SizeofSockaddrNetlink, 0
-}
-
-type RawSockaddrInet4 struct {
- Family uint16;
- Port uint16;
- Addr [4]byte /* in_addr */;
- Zero [8]uint8;
-}
-
-func (sa *RawSockaddrInet4) setLen() Socklen_t {
- return SizeofSockaddrInet4
-}
-
-type RawSockaddrInet6 struct {
- Family uint16;
- Port uint16;
- Flowinfo uint32;
- Addr [16]byte /* in6_addr */;
- Scope_id uint32;
-}
-
-func (sa *RawSockaddrInet6) setLen() Socklen_t {
- return SizeofSockaddrInet6
-}
-
-type RawSockaddrUnix struct {
- Family uint16;
- Path [108]int8;
-}
-
-func (sa *RawSockaddrUnix) setLen(int) {
-}
-
-func (sa *RawSockaddrUnix) getLen() (int, int) {
- if sa.Path[0] == 0 {
- // "Abstract" Unix domain socket.
- // Rewrite leading NUL as @ for textual display.
- // (This is the standard convention.)
- // Not friendly to overwrite in place,
- // but the callers below don't care.
- sa.Path[0] = '@';
- }
-
- // Assume path ends at NUL.
- // This is not technically the Linux semantics for
- // abstract Unix domain sockets--they are supposed
- // to be uninterpreted fixed-size binary blobs--but
- // everyone uses this convention.
- n := 0;
- for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
- n++;
- }
-
- return n, 0
-}
-
-type RawSockaddrLinklayer struct {
- Family uint16
- Protocol uint16
- Ifindex int32
- Hatype uint16
- Pkttype uint8
- Halen uint8
- Addr [8]uint8
-}
-
-type RawSockaddrNetlink struct {
- Family uint16
- Pad uint16
- Pid uint32
- Groups uint32
-}
-
-type RawSockaddr struct {
- Family uint16;
- Data [14]int8;
-}
-
-// BindToDevice binds the socket associated with fd to device.
-func BindToDevice(fd int, device string) (errno int) {
- return SetsockoptString(fd, SOL_SOCKET, SO_BINDTODEVICE, device)
-}
-
-func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
- switch rsa.Addr.Family {
- case AF_NETLINK:
- pp := (*RawSockaddrNetlink)(unsafe.Pointer(rsa))
- sa := new(SockaddrNetlink)
- sa.Family = pp.Family
- sa.Pad = pp.Pad
- sa.Pid = pp.Pid
- sa.Groups = pp.Groups
- return sa, 0
-
- case AF_PACKET:
- pp := (*RawSockaddrLinklayer)(unsafe.Pointer(rsa))
- sa := new(SockaddrLinklayer)
- sa.Protocol = pp.Protocol
- sa.Ifindex = int(pp.Ifindex)
- sa.Hatype = pp.Hatype
- sa.Pkttype = pp.Pkttype
- sa.Halen = pp.Halen
- for i := 0; i < len(sa.Addr); i++ {
- sa.Addr[i] = pp.Addr[i]
- }
- return sa, 0
- }
- return nil, EAFNOSUPPORT;
-}
diff --git a/libgo/syscalls/socket_solaris.go b/libgo/syscalls/socket_solaris.go
deleted file mode 100644
index 376707858a6..00000000000
--- a/libgo/syscalls/socket_solaris.go
+++ /dev/null
@@ -1,80 +0,0 @@
-// socket_solaris.go -- Socket handling specific to Solaris.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-const SizeofSockaddrInet4 = 16
-const SizeofSockaddrInet6 = 32
-const SizeofSockaddrUnix = 110
-
-type RawSockaddrInet4 struct {
- Family uint16
- Port uint16
- Addr [4]byte /* in_addr */
- Zero [8]uint8
-}
-
-func (sa *RawSockaddrInet4) setLen() Socklen_t {
- return SizeofSockaddrInet4
-}
-
-type RawSockaddrInet6 struct {
- Family uint16
- Port uint16
- Flowinfo uint32
- Addr [16]byte /* in6_addr */
- Scope_id uint32
- Src_id uint32
-}
-
-func (sa *RawSockaddrInet6) setLen() Socklen_t {
- return SizeofSockaddrInet6
-}
-
-type RawSockaddrUnix struct {
- Family uint16
- Path [108]int8
-}
-
-func (sa *RawSockaddrUnix) setLen(int) {
-}
-
-func (sa *RawSockaddrUnix) getLen() (int, int) {
- if sa.Path[0] == 0 {
- // "Abstract" Unix domain socket.
- // Rewrite leading NUL as @ for textual display.
- // (This is the standard convention.)
- // Not friendly to overwrite in place,
- // but the callers below don't care.
- sa.Path[0] = '@'
- }
-
- // Assume path ends at NUL.
- // This is not technically the Linux semantics for
- // abstract Unix domain sockets--they are supposed
- // to be uninterpreted fixed-size binary blobs--but
- // everyone uses this convention.
- n := 0
- for n < len(sa.Path) - 3 && sa.Path[n] != 0 {
- n++
- }
-
- return n, 0
-}
-
-type RawSockaddr struct {
- Family uint16
- Data [14]int8
-}
-
-// BindToDevice binds the socket associated with fd to device.
-func BindToDevice(fd int, device string) (errno int) {
- return ENOSYS
-}
-
-func anyToSockaddrOS(rsa *RawSockaddrAny) (Sockaddr, int) {
- return nil, EAFNOSUPPORT;
-}
diff --git a/libgo/syscalls/stringbyte.go b/libgo/syscalls/stringbyte.go
deleted file mode 100644
index 17619536f2e..00000000000
--- a/libgo/syscalls/stringbyte.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// stringbyte.go -- string to bytes functions.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-// StringByteSlice returns a NUL-terminated slice of bytes
-// containing the text of s.
-func StringByteSlice(s string) []byte {
- a := make([]byte, len(s)+1);
- for i := 0; i < len(s); i++ {
- a[i] = s[i];
- }
- return a;
-}
-
-// StringBytePtr returns a pointer to a NUL-terminated array of bytes
-// containing the text of s.
-func StringBytePtr(s string) *byte {
- p := StringByteSlice(s);
- return &p[0];
-}
-
-// BytePtrToString takes a NUL-terminated array of bytes and convert
-// it to a Go string.
-func BytePtrToString(p *byte) string {
- a := (*[10000]byte)(unsafe.Pointer(p))
- i := 0
- for a[i] != 0 {
- i++
- }
- return string(a[:i])
-}
diff --git a/libgo/syscalls/syscall.go b/libgo/syscalls/syscall.go
deleted file mode 100644
index 8c7a7ba5fee..00000000000
--- a/libgo/syscalls/syscall.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// syscall.go -- Basic syscall interface.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This package contains an interface to the low-level operating system
-// primitives. The details vary depending on the underlying system.
-// Its primary use is inside other packages that provide a more portable
-// interface to the system, such as "os", "time" and "net". Use those
-// packages rather than this one if you can.
-// For details of the functions and data types in this package consult
-// the manuals for the appropriate operating system.
-package syscall
-
-import (
- "sync"
- "unsafe"
-)
-
-func libc_syscall32(trap int32, a1, a2, a3, a4, a5, a6 int32) int32 __asm__ ("syscall");
-func libc_syscall64(trap int64, a1, a2, a3, a4, a5, a6 int64) int64 __asm__ ("syscall");
-
-// Do a system call. We look at the size of uintptr to see how to pass
-// the arguments, so that we don't pass a 64-bit value when the function
-// expects a 32-bit one.
-func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
- var r uintptr;
- if unsafe.Sizeof(r) == 4 {
- r1 := libc_syscall32(int32(trap), int32(a1), int32(a2), int32(a3), 0, 0, 0);
- r = uintptr(r1);
- } else {
- r1 := libc_syscall64(int64(trap), int64(a1), int64(a2), int64(a3), 0, 0, 0);
- r = uintptr(r1);
- }
- return r, 0, uintptr(GetErrno());
-}
-
-func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
- var r uintptr;
- if unsafe.Sizeof(r) == 4 {
- r1 := libc_syscall32(int32(trap), int32(a1), int32(a2), int32(a3),
- int32(a4), int32(a5), int32(a6));
- r = uintptr(r1);
- } else {
- r1 := libc_syscall64(int64(trap), int64(a1), int64(a2), int64(a3),
- int64(a4), int64(a5), int64(a6));
- r = uintptr(r1);
- }
- return r, 0, uintptr(GetErrno());
-}
-
-// Mmap manager, for use by operating system-specific implementations.
-
-type mmapper struct {
- sync.Mutex
- active map[*byte][]byte // active mappings; key is last byte in mapping
- mmap func(addr, length uintptr, prot, flags, fd int, offset int64) (uintptr, int)
- munmap func(addr uintptr, length uintptr) int
-}
-
-func (m *mmapper) Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
- if length <= 0 {
- return nil, EINVAL
- }
-
- // Map the requested memory.
- addr, errno := m.mmap(0, uintptr(length), prot, flags, fd, offset)
- if errno != 0 {
- return nil, errno
- }
-
- // Slice memory layout
- var sl = struct {
- addr uintptr
- len int
- cap int
- }{addr, length, length}
-
- // Use unsafe to turn sl into a []byte.
- b := *(*[]byte)(unsafe.Pointer(&sl))
-
- // Register mapping in m and return it.
- p := &b[cap(b)-1]
- m.Lock()
- defer m.Unlock()
- m.active[p] = b
- return b, 0
-}
-
-func (m *mmapper) Munmap(data []byte) (errno int) {
- if len(data) == 0 || len(data) != cap(data) {
- return EINVAL
- }
-
- // Find the base of the mapping.
- p := &data[cap(data)-1]
- m.Lock()
- defer m.Unlock()
- b := m.active[p]
- if b == nil || &b[0] != &data[0] {
- return EINVAL
- }
-
- // Unmap the memory and update m.
- if errno := m.munmap(uintptr(unsafe.Pointer(&b[0])), uintptr(len(b))); errno != 0 {
- return errno
- }
- m.active[p] = nil, false
- return 0
-}
diff --git a/libgo/syscalls/syscall_irix.go b/libgo/syscalls/syscall_irix.go
deleted file mode 100644
index e66cef045db..00000000000
--- a/libgo/syscalls/syscall_irix.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// syscall_irix.go -- IRIX 6 specific syscall interface.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-// FIXME: ptrace(3C) has this, but exec.go expects the next.
-//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
-
-func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int __asm__ ("ptrace")
-
-var dummy *byte
-const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
diff --git a/libgo/syscalls/syscall_linux.go b/libgo/syscalls/syscall_linux.go
deleted file mode 100644
index 29c8b62403e..00000000000
--- a/libgo/syscalls/syscall_linux.go
+++ /dev/null
@@ -1,206 +0,0 @@
-// syscall_linux.go -- GNU/Linux specific syscall interface.
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) _C_long __asm__ ("ptrace")
-func libc_sendfile(int, int, *Offset_t, Size_t) Ssize_t __asm__ ("sendfile")
-
-var dummy *byte
-const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
-
-func ptracePeek(req int, pid int, addr uintptr, out []byte) (count int, errno int) {
- // The peek requests are machine-size oriented, so we wrap it
- // to retrieve arbitrary-length data.
-
- var buf [sizeofPtr]byte;
-
- // Leading edge. PEEKTEXT/PEEKDATA don't require aligned
- // access (PEEKUSER warns that it might), but if we don't
- // align our reads, we might straddle an unmapped page
- // boundary and not get the bytes leading up to the page
- // boundary.
- n := 0;
- if addr % sizeofPtr != 0 {
- SetErrno(0);
- val := libc_ptrace(req, Pid_t(pid), addr - addr%sizeofPtr, nil);
- if errno := GetErrno(); errno != 0 {
- return 0, errno;
- }
- *(*_C_long)(unsafe.Pointer(&buf[0])) = val;
- n += copy(out, buf[addr%sizeofPtr:]);
- out = out[n:];
- }
-
- // Remainder.
- for len(out) > 0 {
- // We use an internal buffer to gaurantee alignment.
- // It's not documented if this is necessary, but we're paranoid.
- SetErrno(0);
- val := libc_ptrace(req, Pid_t(pid), addr+uintptr(n), nil);
- if errno = GetErrno(); errno != 0 {
- return n, errno;
- }
- *(*_C_long)(unsafe.Pointer(&buf[0])) = val;
- copied := copy(out, buf[0:]);
- n += copied;
- out = out[copied:];
- }
-
- return n, 0;
-}
-
-func PtracePeekText(pid int, addr uintptr, out []byte) (count int, errno int) {
- return ptracePeek(_PTRACE_PEEKTEXT, pid, addr, out);
-}
-
-func PtracePeekData(pid int, addr uintptr, out []byte) (count int, errno int) {
- return ptracePeek(_PTRACE_PEEKDATA, pid, addr, out);
-}
-
-func ptracePoke(pokeReq int, peekReq int, pid int, addr uintptr, data []byte) (count int, errno int) {
- // As for ptracePeek, we need to align our accesses to deal
- // with the possibility of straddling an invalid page.
-
- // Leading edge.
- n := 0;
- if addr % sizeofPtr != 0 {
- var buf [sizeofPtr]byte;
- if libc_ptrace(peekReq, Pid_t(pid), addr - addr%sizeofPtr, &buf[0]) < 0 {
- return 0, GetErrno();
- }
- n += copy(buf[addr%sizeofPtr:], data);
- word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&buf[0])))));
- if libc_ptrace(pokeReq, Pid_t(pid), addr - addr%sizeofPtr, word) < 0 {
- return 0, GetErrno();
- }
- data = data[n:len(data)];
- }
-
- // Interior.
- for uintptr(len(data)) > sizeofPtr {
- word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&data[0])))));
- if libc_ptrace(pokeReq, Pid_t(pid), addr+uintptr(n), word) < 0 {
- return n, GetErrno();
- }
- n += int(sizeofPtr);
- data = data[sizeofPtr:len(data)];
- }
-
- // Trailing edge.
- if len(data) > 0 {
- var buf [sizeofPtr]byte;
- if libc_ptrace(peekReq, Pid_t(pid), addr+uintptr(n), &buf[0]) < 0 {
- return n, GetErrno();
- }
- copy(buf[0:], data);
- word := (*byte)(unsafe.Pointer(*((*uintptr)(unsafe.Pointer(&buf[0])))));
- if libc_ptrace(pokeReq, Pid_t(pid), addr+uintptr(n), word) < 0 {
- return n, GetErrno();
- }
- n += len(data);
- }
-
- return n, 0;
-}
-
-func PtracePokeText(pid int, addr uintptr, data []byte) (count int, errno int) {
- return ptracePoke(_PTRACE_POKETEXT, _PTRACE_PEEKTEXT, pid, addr, data);
-}
-
-func PtracePokeData(pid int, addr uintptr, data []byte) (count int, errno int) {
- return ptracePoke(_PTRACE_POKEDATA, _PTRACE_PEEKDATA, pid, addr, data);
-}
-
-func PtraceGetRegs(pid int, regsout *PtraceRegs) (errno int) {
- if libc_ptrace(_PTRACE_GETREGS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(regsout))) < 0 {
- return GetErrno();
- } else {
- return 0;
- }
-}
-
-func PtraceSetRegs(pid int, regs *PtraceRegs) (errno int) {
- if libc_ptrace(_PTRACE_SETREGS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(regs))) < 0 {
- return GetErrno();
- } else {
- return 0;
- }
-}
-
-func PtraceSetOptions(pid int, options int) (errno int) {
- if libc_ptrace(_PTRACE_SETOPTIONS, Pid_t(pid), 0, (*byte)(unsafe.Pointer(uintptr(options)))) < 0 {
- return GetErrno();
- } else {
- return 0;
- }
-}
-
-func PtraceGetEventMsg(pid int) (msg uint, errno int) {
- var data _C_long;
- if libc_ptrace(_PTRACE_GETEVENTMSG, Pid_t(pid), 0, (*byte)(unsafe.Pointer(&data))) < 0 {
- errno = GetErrno();
- }
- msg = uint(data);
- return;
-}
-
-func PtraceCont(pid int, signal int) (errno int) {
- if libc_ptrace(_PTRACE_CONT, Pid_t(pid), 0, (*byte)(unsafe.Pointer(uintptr(signal)))) < 0 {
- return GetErrno();
- } else {
- return 0;
- }
-}
-
-func PtraceSingleStep(pid int) (errno int) {
- if libc_ptrace(_PTRACE_SINGLESTEP, Pid_t(pid), 0, nil) < 0 {
- return GetErrno();
- } else {
- return 0;
- }
-}
-
-func PtraceAttach(pid int) (errno int) {
- if libc_ptrace(_PTRACE_ATTACH, Pid_t(pid), 0, nil) < 0 {
- return GetErrno();
- } else {
- return 0;
- }
-}
-
-func PtraceDetach(pid int) (errno int) {
- if libc_ptrace(_PTRACE_DETACH, Pid_t(pid), 0, nil) < 0 {
- return GetErrno();
- } else {
- return 0;
- }
-}
-
-func Tgkill(tgid int, tid int, sig int) (errno int) {
- r1, r2, err := Syscall(SYS_TGKILL, uintptr(tgid), uintptr(tid),
- uintptr(sig));
- return int(err);
-}
-
-func Sendfile(outfd int, infd int, offset *int64, count int) (written int, errno int) {
- var o Offset_t
- var po *Offset_t
- if offset != nil {
- o = Offset_t(*offset)
- po = &o
- }
- w := libc_sendfile(outfd, infd, po, Size_t(count))
- if offset != nil {
- *offset = int64(o)
- }
- if w < 0 {
- return 0, GetErrno()
- }
- return int(w), 0
-}
diff --git a/libgo/syscalls/syscall_rtems.go b/libgo/syscalls/syscall_rtems.go
deleted file mode 100644
index 7f0c1195443..00000000000
--- a/libgo/syscalls/syscall_rtems.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// syscall_rtems.go -- RTEMS specific syscall interface.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
diff --git a/libgo/syscalls/syscall_solaris.go b/libgo/syscalls/syscall_solaris.go
deleted file mode 100644
index ec229339d94..00000000000
--- a/libgo/syscalls/syscall_solaris.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// syscall_solaris.go -- Solaris 2 specific syscall interface.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
diff --git a/libgo/syscalls/syscall_solaris_386.go b/libgo/syscalls/syscall_solaris_386.go
deleted file mode 100644
index 7ff8f5b0740..00000000000
--- a/libgo/syscalls/syscall_solaris_386.go
+++ /dev/null
@@ -1,20 +0,0 @@
-// syscall_solaris_386.go -- Solaris/x86 specific support
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-// FIXME: ptrace(3C) has this, but exec.go expects the next.
-//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
-
-func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int __asm__ ("ptrace")
-
-var dummy *byte
-const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
-
-// 32-bit Solaris 2/x86 needs to use _nuname internally, cf. <sys/utsname.h>.
-func libc_uname(buf *Utsname) (errno int) __asm__("_nuname")
diff --git a/libgo/syscalls/syscall_solaris_amd64.go b/libgo/syscalls/syscall_solaris_amd64.go
deleted file mode 100644
index 15d22561507..00000000000
--- a/libgo/syscalls/syscall_solaris_amd64.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// syscall_solaris_amd64.go -- Solaris/x64 specific support
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-// FIXME: ptrace(3C) has this, but exec.go expects the next.
-//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
-
-// 64-bit ptrace(3C) doesn't exist
-func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int {
- SetErrno(ENOSYS)
- return -1
-}
-
-var dummy *byte
-const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
diff --git a/libgo/syscalls/syscall_solaris_sparc.go b/libgo/syscalls/syscall_solaris_sparc.go
deleted file mode 100644
index 0be60b92967..00000000000
--- a/libgo/syscalls/syscall_solaris_sparc.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// syscall_solaris_sparc.go -- Solaris/SPARC specific support
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-// FIXME: ptrace(3C) has this, but exec.go expects the next.
-//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
-
-func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int __asm__ ("ptrace")
-
-var dummy *byte
-const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
diff --git a/libgo/syscalls/syscall_solaris_sparc64.go b/libgo/syscalls/syscall_solaris_sparc64.go
deleted file mode 100644
index 81e2010cd13..00000000000
--- a/libgo/syscalls/syscall_solaris_sparc64.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// syscall_solaris_sparc64.go -- Solaris/SPARCV9 specific support
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-// FIXME: ptrace(3C) has this, but exec.go expects the next.
-//func libc_ptrace(request int, pid Pid_t, addr int, data int) int __asm__ ("ptrace")
-
-// 64-bit ptrace(3C) doesn't exist
-func libc_ptrace(request int, pid Pid_t, addr uintptr, data *byte) int {
- SetErrno(ENOSYS)
- return -1
-}
-
-var dummy *byte
-const sizeofPtr uintptr = uintptr(unsafe.Sizeof(dummy))
diff --git a/libgo/syscalls/syscall_stubs.go b/libgo/syscalls/syscall_stubs.go
deleted file mode 100644
index d864902eaf7..00000000000
--- a/libgo/syscalls/syscall_stubs.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// syscall_stubs.go -- Stubs of the basic syscall interface.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This package contains an interface to the low-level operating system
-// primitives. The details vary depending on the underlying system.
-// Its primary use is inside other packages that provide a more portable
-// interface to the system, such as "os", "time" and "net". Use those
-// packages rather than this one if you can.
-// For details of the functions and data types in this package consult
-// the manuals for the appropriate operating system.
-
-// These are stubs.
-
-package syscall
-
-func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) {
- var r uintptr;
- var i int;
- i = -1;
- r = uintptr(i);
- return r, 0, uintptr(ENOSYS);
-}
-
-func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) {
- var r uintptr;
- var i int;
- i = -1;
- r = uintptr(i);
- return r, 0, uintptr(ENOSYS);
-}
diff --git a/libgo/syscalls/syscall_uname.go b/libgo/syscalls/syscall_uname.go
deleted file mode 100644
index 955866c89f1..00000000000
--- a/libgo/syscalls/syscall_uname.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_uname(buf *Utsname) (errno int) __asm__("uname")
diff --git a/libgo/syscalls/syscall_unix.go b/libgo/syscalls/syscall_unix.go
deleted file mode 100644
index e633ea19146..00000000000
--- a/libgo/syscalls/syscall_unix.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-import "unsafe"
-
-var (
- Stdin = 0
- Stdout = 1
- Stderr = 2
-)
-
-const ENONE = 0
-
-func GetErrno() int
-func SetErrno(int)
-
-func Uname(buf *Utsname) (errno int) {
- r := libc_uname(buf)
- if r < 0 {
- errno = GetErrno()
- }
- return
-}
-
-var mapper = &mmapper{
- active: make(map[*byte][]byte),
- mmap: mmap,
- munmap: munmap,
-}
-
-func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, errno int) {
- return mapper.Mmap(fd, offset, length, prot, flags)
-}
-
-func Munmap(b []byte) (errno int) {
- return mapper.Munmap(b)
-}
-
-func libc_munmap(*byte, Size_t) int __asm__ ("munmap")
-
-func mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, errno int) {
- r0 := libc_mmap((*byte)(unsafe.Pointer(addr)), Size_t(length), prot, flag, fd, Offset_t(pos))
- ret = uintptr(unsafe.Pointer(r0))
- if ret + 1 == 0 {
- errno = GetErrno()
- }
- return
-}
-
-func munmap(addr uintptr, length uintptr) (errno int) {
- if libc_munmap((*byte)(unsafe.Pointer(addr)), Size_t(length)) < 0 {
- errno = GetErrno()
- }
- return
-}
-
-func libc_getrusage(who int, rusage *Rusage) int __asm__ ("getrusage")
-
-func Getrusage(who int, rusage *Rusage) (errno int) {
- if libc_getrusage(who, rusage) < 0 {
- errno = GetErrno()
- }
- return
-}
diff --git a/libgo/syscalls/sysfile_largefile.go b/libgo/syscalls/sysfile_largefile.go
deleted file mode 100644
index c0c4e555e63..00000000000
--- a/libgo/syscalls/sysfile_largefile.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// sysfile_largefile.go -- For systems which use the large file interface.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread64")
-func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite64")
-func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek64")
-func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate64")
-func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate64")
-func libc_mmap(*byte, Size_t, int, int, int, Offset_t) *byte __asm__ ("mmap64")
diff --git a/libgo/syscalls/sysfile_posix.go b/libgo/syscalls/sysfile_posix.go
deleted file mode 100644
index a16ba4aba60..00000000000
--- a/libgo/syscalls/sysfile_posix.go
+++ /dev/null
@@ -1,429 +0,0 @@
-// sysfile_posix.go -- POSIX File handling.
-
-// Copyright 2010 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Support for basic Unix file operations. This file simply
-// translates from Go data types to Unix data types, and handles
-// errno. FIXME: This could probably be done mechanically.
-
-package syscall
-
-import "unsafe"
-
-func libc_open(name *byte, mode int, perm Mode_t) int __asm__ ("open");
-func libc_close(fd int) int __asm__ ("close");
-func libc_read(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("read");
-func libc_write(fd int, buf *byte, count Size_t) Ssize_t __asm__ ("write");
-func libc_fsync(fd int) int __asm__ ("fsync")
-func libc_pipe(filedes *int) int __asm__("pipe");
-func libc_unlink(name *byte) int __asm__ ("unlink");
-func libc_rmdir(name *byte) int __asm__ ("rmdir");
-func libc_fcntl(fd int, cmd int, arg int) int __asm__ ("fcntl");
-func libc_mkdir(name *byte, perm Mode_t) int __asm__ ("mkdir");
-func libc_dup(int) int __asm__ ("dup")
-func libc_gettimeofday(tv *Timeval, tz *byte) int __asm__ ("gettimeofday");
-func libc_select(int, *byte, *byte, *byte, *Timeval) int __asm__ ("select");
-func libc_chdir(name *byte) int __asm__ ("chdir");
-func libc_fchdir(int) int __asm__ ("fchdir");
-func libc_getcwd(*byte, Size_t) *byte __asm__ ("getcwd");
-func libc_link(oldpath *byte, newpath *byte) int __asm__ ("link");
-func libc_symlink(oldpath *byte, newpath *byte) int __asm__ ("symlink");
-func libc_readlink(*byte, *byte, Size_t) Ssize_t __asm__ ("readlink");
-func libc_rename(oldpath *byte, newpath *byte) int __asm__ ("rename");
-func libc_chmod(path *byte, mode Mode_t) int __asm__ ("chmod");
-func libc_fchmod(fd int, mode Mode_t) int __asm__ ("fchmod");
-func libc_chown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("chown");
-func libc_fchown(fd int, owner Uid_t, group Gid_t) int __asm__ ("fchown");
-func libc_lchown(path *byte, owner Uid_t, group Gid_t) int __asm__ ("lchown");
-func libc_utimes(filename *byte, times *[2]Timeval) int __asm__ ("utimes");
-func libc_getuid() Uid_t __asm__ ("getuid");
-func libc_geteuid() Uid_t __asm__ ("geteuid");
-func libc_getgid() Gid_t __asm__ ("getgid");
-func libc_getegid() Gid_t __asm__ ("getegid");
-func libc_getgroups(size int, list *Gid_t) int __asm__ ("getgroups");
-func libc_getpagesize() int __asm__ ("getpagesize");
-func libc_exit(status int) __asm__ ("exit")
-func libc_getpid() Pid_t __asm__ ("getpid")
-func libc_getppid() Pid_t __asm__ ("getppid")
-func libc_kill(Pid_t, int) int __asm__ ("kill")
-
-func Open(name string, mode int, perm uint32) (fd int, errno int) {
- fd = libc_open(StringBytePtr(name), mode, Mode_t(perm));
- if fd < 0 { errno = GetErrno() }
- return;
-}
-
-func Creat(name string, perm uint32) (fd int, errno int) {
- fd = libc_open(StringBytePtr(name), O_CREAT | O_WRONLY | O_TRUNC, Mode_t(perm));
- if fd < 0 { errno = GetErrno() }
- return;
-}
-
-func Close(fd int) (errno int) {
- r := libc_close(fd);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Read(fd int, p []byte) (n int, errno int) {
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_read(fd, _p0, Size_t(len(p)));
- if r == -1 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Write(fd int, p []byte) (n int, errno int) {
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_write(fd, _p0, Size_t(len(p)));
- if r == -1 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Fsync(fd int) (errno int) {
- if libc_fsync(fd) < 0 {
- errno = GetErrno()
- }
- return
-}
-
-func Pread(fd int, p []byte, offset int64) (n int, errno int) {
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_pread(fd, _p0, Size_t(len(p)), Offset_t(offset));
- if r == -1 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Pwrite(fd int, p []byte, offset int64) (n int, errno int) {
- var _p0 *byte;
- if len(p) > 0 { _p0 = &p[0]; }
- r := libc_pwrite(fd, _p0, Size_t(len(p)), Offset_t(offset));
- if r == -1 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Seek(fd int, offset int64, whence int) (off int64, errno int) {
- r := libc_lseek(fd, Offset_t(offset), whence);
- if r == -1 { errno = GetErrno() }
- off = int64(r);
- return;
-}
-
-func Pipe(p []int) (errno int) {
- if len(p) != 2 {
- return EINVAL;
- }
- var pp [2]int;
- r := libc_pipe(&pp[0]);
- if r < 0 {
- errno = GetErrno();
- }
- p[0] = pp[0];
- p[1] = pp[1];
- return;
-}
-
-func Stat(name string, buf *Stat_t) (errno int) {
- r := libc_stat(StringBytePtr(name), buf);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Lstat(name string, buf *Stat_t) (errno int) {
- r := libc_lstat(StringBytePtr(name), buf);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Fstat(fd int, buf *Stat_t) (errno int) {
- r := libc_fstat(fd, buf);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Unlink(name string) (errno int) {
- r := libc_unlink(StringBytePtr(name));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Rmdir(name string) (errno int) {
- r := libc_rmdir(StringBytePtr(name));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Mkdir(path string, mode uint32) (errno int) {
- r := libc_mkdir(StringBytePtr(path), Mode_t(mode));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Dup(oldfd int) (fd int, errno int) {
- fd = libc_dup(oldfd)
- if fd < 0 {
- errno = GetErrno()
- }
- return
-}
-
-func Gettimeofday(tv *Timeval) (errno int) {
- r := libc_gettimeofday(tv, nil);
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-const nfdbits = unsafe.Sizeof(fds_bits_type) * 8
-
-type FdSet_t struct {
- Fds_bits [(FD_SETSIZE + nfdbits - 1) / nfdbits]fds_bits_type
-}
-
-func FDSet(fd int, set *FdSet_t) {
- set.Fds_bits[fd / nfdbits] |= (1 << (uint)(fd % nfdbits))
-}
-
-func FDClr(fd int, set *FdSet_t) {
- set.Fds_bits[fd / nfdbits] &^= (1 << (uint)(fd % nfdbits))
-}
-
-func FDIsSet(fd int, set *FdSet_t) bool {
- if set.Fds_bits[fd / nfdbits] & (1 << (uint)(fd % nfdbits)) != 0 {
- return true
- } else {
- return false
- }
-}
-
-func FDZero(set *FdSet_t) {
- for i := range set.Fds_bits {
- set.Fds_bits[i] = 0
- }
-}
-
-func Select(nfds int, r *FdSet_t, w *FdSet_t, e *FdSet_t, timeout *Timeval) (n int, errno int) {
- n = libc_select(nfds, (*byte)(unsafe.Pointer(r)),
- (*byte)(unsafe.Pointer(w)),
- (*byte)(unsafe.Pointer(e)), timeout);
- if n < 0 { errno = GetErrno() }
- return;
-}
-
-func Chdir(path string) (errno int) {
- r := libc_chdir(StringBytePtr(path));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Fchdir(fd int) (errno int) {
- r := libc_fchdir(int(fd));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-const ImplementsGetwd = true
-
-func Getwd() (ret string, errno int) {
- for len := Size_t(4096); ; len *= 2 {
- b := make([]byte, len);
- p := libc_getcwd(&b[0], len);
- if p != nil {
- i := 0;
- for b[i] != 0 {
- i++;
- }
- return string(b[0:i]), 0;
- }
- e := GetErrno();
- if e != ERANGE {
- return "", e;
- }
- }
-}
-
-func Link(oldpath, newpath string) (errno int) {
- r := libc_link(StringBytePtr(oldpath), StringBytePtr(newpath));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Symlink(oldpath, newpath string) (errno int) {
- r := libc_symlink(StringBytePtr(oldpath), StringBytePtr(newpath));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Readlink(path string, buf []byte) (n int, errno int) {
- var _p0 *byte;
- if len(buf) > 0 { _p0 = &buf[0]; }
- r := libc_readlink(StringBytePtr(path), _p0, Size_t(len(buf)));
- if r < 0 { errno = GetErrno() }
- n = int(r);
- return;
-}
-
-func Rename(oldpath, newpath string) (errno int) {
- r := libc_rename(StringBytePtr(oldpath), StringBytePtr(newpath));
- if r < 0 { errno = GetErrno() }
- return
-}
-
-func Chmod(path string, mode uint32) (errno int) {
- r := libc_chmod(StringBytePtr(path), Mode_t(mode));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Fchmod(fd int, mode uint32) (errno int) {
- r := libc_fchmod(fd, Mode_t(mode));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Chown(path string, uid int, gid int) (errno int) {
- r := libc_chown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Lchown(path string, uid int, gid int) (errno int) {
- r := libc_lchown(StringBytePtr(path), Uid_t(uid), Gid_t(gid));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Fchown(fd int, uid int, gid int) (errno int) {
- r := libc_fchown(fd, Uid_t(uid), Gid_t(gid));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Truncate(path string, length int64) (errno int) {
- r := libc_truncate(StringBytePtr(path), Offset_t(length));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Ftruncate(fd int, length int64) (errno int) {
- r := libc_ftruncate(fd, Offset_t(length));
- if r < 0 { errno = GetErrno() }
- return;
-}
-
-func Utimes(path string, tv []Timeval) (errno int) {
- if len(tv) != 2 {
- return EINVAL;
- }
- r := libc_utimes(StringBytePtr(path),
- (*[2]Timeval)(unsafe.Pointer(&tv[0])));
- if r < 0 {
- errno = GetErrno();
- }
- return;
-}
-
-// Getuid returns the numeric user id of the caller.
-func Getuid() int {
- return int(libc_getuid());
-}
-
-// Geteuid returns the numeric effective user id of the caller.
-func Geteuid() int {
- return int(libc_geteuid());
-}
-
-// Getgid returns the numeric group id of the caller.
-func Getgid() int {
- return int(libc_getgid());
-}
-
-// Getegid returns the numeric effective group id of the caller.
-func Getegid() int {
- return int(libc_getegid());
-}
-
-// Getgroups returns a list of the numeric ids of groups that the caller belongs to.
-func Getgroups() (gids []int, errno int) {
- n := libc_getgroups(0, nil);
- if n < 0 {
- return nil, GetErrno();
- }
- if n == 0 {
- return nil, 0;
- }
-
- // Sanity check group count. Max is 1<<16 on Linux.
- if n < 0 || n > 1<<20 {
- return nil, EINVAL;
- }
-
- a := make([]Gid_t, n);
- n = libc_getgroups(n, &a[0]);
- if n < 0 {
- return nil, GetErrno();
- }
- gids = make([]int, n);
- for i, v := range a[0:n] {
- gids[i] = int(v);
- }
- return;
-}
-
-func Getpagesize() int {
- return libc_getpagesize();
-}
-
-func TimespecToNsec(ts Timespec) int64 {
- return int64(ts.Sec)*1e9 + int64(ts.Nsec);
-}
-
-func NsecToTimespec(nsec int64) (ts Timespec) {
- ts.Sec = Timespec_sec_t(nsec / 1e9);
- ts.Nsec = Timespec_nsec_t(nsec % 1e9);
- return;
-}
-
-func TimevalToNsec(tv Timeval) int64 {
- return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3;
-}
-
-func NsecToTimeval(nsec int64) (tv Timeval) {
- nsec += 999; // round up to microsecond
- tv.Sec = Timeval_sec_t(nsec/1e9);
- tv.Usec = Timeval_usec_t(nsec%1e9 / 1e3);
- return;
-}
-
-func Exit(code int) {
- libc_exit(code);
-}
-
-func fcntl(fd, cmd, arg int) (val int, errno int) {
- val = libc_fcntl(int(fd), int(cmd), int(arg));
- if val == -1 { errno = GetErrno() }
- return;
-}
-
-func Getpid() (pid int) {
- return int(libc_getpid());
-}
-
-func Getppid() (ppid int) {
- return int(libc_getppid());
-}
-
-func Kill(pid int, sig int) (errno int) {
- r := libc_kill(Pid_t(pid), sig)
- if r < 0 {
- errno = GetErrno()
- }
- return
-}
diff --git a/libgo/syscalls/sysfile_regfile.go b/libgo/syscalls/sysfile_regfile.go
deleted file mode 100644
index fcbf254dc0e..00000000000
--- a/libgo/syscalls/sysfile_regfile.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// sysfile_regfile.go -- For systems which do not use the large file interface.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_pread(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pread")
-func libc_pwrite(fd int, buf *byte, count Size_t, offset Offset_t) Ssize_t __asm__ ("pwrite")
-func libc_lseek(int, Offset_t, int) Offset_t __asm__ ("lseek")
-func libc_truncate(path *byte, length Offset_t) int __asm__ ("truncate")
-func libc_ftruncate(fd int, length Offset_t) int __asm__ ("ftruncate")
-func libc_mmap(*byte, Size_t, int, int, int, Offset_t) *byte __asm__ ("mmap")
diff --git a/libgo/syscalls/sysfile_stat_largefile.go b/libgo/syscalls/sysfile_stat_largefile.go
deleted file mode 100644
index 1b785f70a64..00000000000
--- a/libgo/syscalls/sysfile_stat_largefile.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// sysfile_stat_largefile.go -- For systems which use the large file interface
-// for *stat.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat64");
-func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat64");
-func libc_lstat(name *byte, buf *Stat_t) int __asm__ ("lstat64");
diff --git a/libgo/syscalls/sysfile_stat_regfile.go b/libgo/syscalls/sysfile_stat_regfile.go
deleted file mode 100644
index b3d48641375..00000000000
--- a/libgo/syscalls/sysfile_stat_regfile.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// sysfile_stat_regfile.go -- For systems which do not use the large file
-// interface for *stat.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_stat(name *byte, buf *Stat_t) int __asm__ ("stat");
-func libc_fstat(fd int, buf *Stat_t) int __asm__ ("fstat");
-func libc_lstat(name *byte, buf *Stat_t) int __asm__ ("lstat");
diff --git a/libgo/syscalls/wait4.go b/libgo/syscalls/wait4.go
deleted file mode 100644
index bb00c792bc0..00000000000
--- a/libgo/syscalls/wait4.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// wait4.go -- Wait4 for systems with wait4.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_wait4(Pid_t, *int, int, *Rusage) Pid_t __asm__ ("wait4")
-
-func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
- var status int
- r := libc_wait4(Pid_t(pid), &status, options, rusage)
- wpid = int(r)
- if r < 0 {
- errno = GetErrno()
- }
- if wstatus != nil {
- *wstatus = WaitStatus(status)
- }
- return
-}
diff --git a/libgo/syscalls/waitpid.go b/libgo/syscalls/waitpid.go
deleted file mode 100644
index 1cb4d5dda95..00000000000
--- a/libgo/syscalls/waitpid.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// waitpid.go -- Wait4 for systems without wait4, but with waitpid.
-
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package syscall
-
-func libc_waitpid(Pid_t, *int, int) Pid_t __asm__ ("waitpid")
-
-func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, errno int) {
- var status int
- r := libc_waitpid(Pid_t(pid), &status, options)
- wpid = int(r)
- if r < 0 {
- errno = GetErrno()
- }
- if wstatus != nil {
- *wstatus = WaitStatus(status)
- }
- return
-}
diff --git a/libgo/testsuite/Makefile.in b/libgo/testsuite/Makefile.in
index 0acbbb3da4f..21a749276d7 100644
--- a/libgo/testsuite/Makefile.in
+++ b/libgo/testsuite/Makefile.in
@@ -86,7 +86,10 @@ GOARCH = @GOARCH@
GOC = @GOC@
GOCFLAGS = @GOCFLAGS@
GOOS = @GOOS@
-GO_SYSCALLS_SYSCALL_OS_ARCH_FILE = @GO_SYSCALLS_SYSCALL_OS_ARCH_FILE@
+GO_LIBCALL_OS_ARCH_FILE = @GO_LIBCALL_OS_ARCH_FILE@
+GO_LIBCALL_OS_FILE = @GO_LIBCALL_OS_FILE@
+GO_SYSCALL_OS_ARCH_FILE = @GO_SYSCALL_OS_ARCH_FILE@
+GO_SYSCALL_OS_FILE = @GO_SYSCALL_OS_FILE@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
@@ -130,9 +133,11 @@ RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
+SIZEOF_STRUCT_EPOLL_EVENT = @SIZEOF_STRUCT_EPOLL_EVENT@
SPLIT_STACK = @SPLIT_STACK@
STRINGOPS_FLAG = @STRINGOPS_FLAG@
STRIP = @STRIP@
+STRUCT_EPOLL_EVENT_FD_OFFSET = @STRUCT_EPOLL_EVENT_FD_OFFSET@
VERSION = @VERSION@
WARN_FLAGS = @WARN_FLAGS@
WERROR = @WERROR@
diff --git a/libgo/testsuite/gotest b/libgo/testsuite/gotest
index 69cf8eed06a..1dedaa8e361 100755
--- a/libgo/testsuite/gotest
+++ b/libgo/testsuite/gotest
@@ -331,6 +331,10 @@ localname() {
pattern='Benchmark([^a-z].*)?'
benchmarks=$($NM -p -v _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/')
+ # examples are named ExampleFoo
+ pattern='Example([^a-z].*)?'
+ examples=$($NM -p -v _gotest_.o $xofile | egrep ' T .*\.'$pattern'$' | grep -v '\..*\..*\.' | sed 's/.* //' | sed 's/.*\.\(.*\.\)/\1/')
+
# package spec
echo 'package main'
echo
@@ -353,6 +357,7 @@ localname() {
echo ' {"'$i'", '$j'},'
done
echo '}'
+
# benchmark array
# The comment makes the multiline declaration
# gofmt-safe even when there are no benchmarks.
@@ -363,6 +368,17 @@ localname() {
echo ' {"'$i'", '$j'},'
done
echo '}'
+
+ # examples array
+ echo 'var examples = []testing.InternalExample{ //'
+ # This doesn't work because we don't pick up the output.
+ #for i in $examples
+ #do
+ # j=$(localname $i)
+ # echo ' {"'$i'", '$j', ""},'
+ #done
+ echo '}'
+
# body
echo \
'
@@ -381,7 +397,7 @@ func matchString(pat, str string) (result bool, err __os__.Error) {
}
func main() {
- testing.Main(matchString, tests, benchmarks)
+ testing.Main(matchString, tests, benchmarks, examples)
}'
}>_testmain.go
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 6859afa04c3..6a93998e244 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,20 @@
+2011-10-28 Ian Lance Taylor <iant@google.com>
+
+ * setproctitle.c (setproctitle): Use "GNU/Linux" in comment.
+
+2011-10-26 Iain Sandoe <iains@gcc.gnu.org>
+
+ PR target/48108
+ * simple-object-mach-o.c (GNU_WRAPPER_SECTS, GNU_WRAPPER_INDEX,
+ GNU_WRAPPER_NAMES): New macros.
+ (simple_object_mach_o_segment): Handle wrapper scheme.
+ (simple_object_mach_o_write_section_header): Allow the segment name
+ to be supplied.
+ (simple_object_mach_o_write_segment): Handle wrapper scheme. Ensure
+ that the top-level segment name in the load command is empty.
+ (simple_object_mach_o_write_to_file): Determine the number of
+ sections during segment output, use that in writing the header.
+
2011-10-10 Ian Lance Taylor <iant@google.com>
PR c++/48665
diff --git a/libiberty/setproctitle.c b/libiberty/setproctitle.c
index 3b3f377b67b..6a2fe8ce3a5 100644
--- a/libiberty/setproctitle.c
+++ b/libiberty/setproctitle.c
@@ -41,8 +41,8 @@ void
setproctitle (const char *name ATTRIBUTE_UNUSED, ...)
{
#ifdef PR_SET_NAME
- /* On Linux this sets the top visible "comm", but not necessarily
- the name visible in ps. */
+ /* On GNU/Linux this sets the top visible "comm", but not
+ necessarily the name visible in ps. */
prctl (PR_SET_NAME, name);
#endif
}
diff --git a/libiberty/simple-object-mach-o.c b/libiberty/simple-object-mach-o.c
index bbbbd09de58..af5e4f9ca88 100644
--- a/libiberty/simple-object-mach-o.c
+++ b/libiberty/simple-object-mach-o.c
@@ -1,5 +1,5 @@
/* simple-object-mach-o.c -- routines to manipulate Mach-O object files.
- Copyright 2010 Free Software Foundation, Inc.
+ Copyright 2010, 2011 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
This program is free software; you can redistribute it and/or modify it
@@ -174,6 +174,15 @@ struct mach_o_section_64
#define GNU_SECTION_NAMES "__section_names"
+/* A GNU-specific extension to wrap multiple sections using three
+ mach-o sections within a given segment. The section '__wrapper_sects'
+ is subdivided according to the index '__wrapper_index' and each sub
+ sect is named according to the names supplied in '__wrapper_names'. */
+
+#define GNU_WRAPPER_SECTS "__wrapper_sects"
+#define GNU_WRAPPER_INDEX "__wrapper_index"
+#define GNU_WRAPPER_NAMES "__wrapper_names"
+
/* Private data for an simple_object_read. */
struct simple_object_mach_o_read
@@ -214,7 +223,18 @@ struct simple_object_mach_o_attributes
unsigned int reserved;
};
-/* See if we have a Mach-O file. */
+/* See if we have a Mach-O MH_OBJECT file:
+
+ A standard MH_OBJECT (from as) will have three load commands:
+ 0 - LC_SEGMENT/LC_SEGMENT64
+ 1 - LC_SYMTAB
+ 2 - LC_DYSYMTAB
+
+ The LC_SEGMENT/LC_SEGMENT64 will introduce a single anonymous segment
+ containing all the sections.
+
+ Files written by simple-object will have only the segment command
+ (no symbol tables). */
static void *
simple_object_mach_o_match (
@@ -356,8 +376,29 @@ simple_object_mach_o_section_info (int is_big_endian, int is_32,
}
}
-/* Handle a segment in a Mach-O file. Return 1 if we should continue,
- 0 if the caller should return. */
+/* Handle a segment in a Mach-O Object file.
+
+ This will callback to the function pfn for each "section found" the meaning
+ of which depends on gnu extensions to mach-o:
+
+ If we find mach-o sections (with the segment name as specified) which also
+ contain: a 'sects' wrapper, an index, and a name table, we expand this into
+ as many sections as are specified in the index. In this case, there will
+ be a callback for each of these.
+
+ We will also allow an extension that permits long names (more than 16
+ characters) to be used with mach-o. In this case, the section name has
+ a specific format embedding an index into a name table, and the file must
+ contain such name table.
+
+ Return 1 if we should continue, 0 if the caller should return. */
+
+#define SOMO_SECTS_PRESENT 0x01
+#define SOMO_INDEX_PRESENT 0x02
+#define SOMO_NAMES_PRESENT 0x04
+#define SOMO_LONGN_PRESENT 0x08
+#define SOMO_WRAPPING (SOMO_SECTS_PRESENT | SOMO_INDEX_PRESENT \
+ | SOMO_NAMES_PRESENT)
static int
simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
@@ -378,9 +419,20 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
unsigned int nsects;
unsigned char *secdata;
unsigned int i;
+ unsigned int gnu_sections_found;
unsigned int strtab_index;
+ unsigned int index_index;
+ unsigned int nametab_index;
+ unsigned int sections_index;
char *strtab;
+ char *nametab;
+ unsigned char *index;
size_t strtab_size;
+ size_t nametab_size;
+ size_t index_size;
+ unsigned int n_wrapped_sects;
+ size_t wrapper_sect_size;
+ off_t wrapper_sect_offset;
fetch_32 = (omr->is_big_endian
? simple_object_fetch_big_32
@@ -409,6 +461,8 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
nsects));
}
+ /* Fetch the section headers from the segment command. */
+
secdata = XNEWVEC (unsigned char, nsects * sechdrsize);
if (!simple_object_internal_read (sobj->descriptor, offset + seghdrsize,
secdata, nsects * sechdrsize, errmsg, err))
@@ -417,9 +471,13 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
return 0;
}
- /* Scan for a __section_names section. This is in effect a GNU
- extension that permits section names longer than 16 chars. */
+ /* Scan for special sections that signal GNU extensions to the format. */
+ gnu_sections_found = 0;
+ index_index = nsects;
+ sections_index = nsects;
+ strtab_index = nsects;
+ nametab_index = nsects;
for (i = 0; i < nsects; ++i)
{
size_t nameoff;
@@ -427,19 +485,104 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
nameoff = i * sechdrsize + segname_offset;
if (strcmp ((char *) secdata + nameoff, omr->segment_name) != 0)
continue;
+
nameoff = i * sechdrsize + sectname_offset;
- if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
- break;
+ if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_NAMES) == 0)
+ {
+ nametab_index = i;
+ gnu_sections_found |= SOMO_NAMES_PRESENT;
+ }
+ else if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_INDEX) == 0)
+ {
+ index_index = i;
+ gnu_sections_found |= SOMO_INDEX_PRESENT;
+ }
+ else if (strcmp ((char *) secdata + nameoff, GNU_WRAPPER_SECTS) == 0)
+ {
+ sections_index = i;
+ gnu_sections_found |= SOMO_SECTS_PRESENT;
+ }
+ else if (strcmp ((char *) secdata + nameoff, GNU_SECTION_NAMES) == 0)
+ {
+ strtab_index = i;
+ gnu_sections_found |= SOMO_LONGN_PRESENT;
+ }
}
- strtab_index = i;
- if (strtab_index >= nsects)
+ /* If any of the special wrapper section components is present, then
+ they all should be. */
+
+ if ((gnu_sections_found & SOMO_WRAPPING) != 0)
{
- strtab = NULL;
- strtab_size = 0;
+ off_t nametab_offset;
+ off_t index_offset;
+
+ if ((gnu_sections_found & SOMO_WRAPPING) != SOMO_WRAPPING)
+ {
+ *errmsg = "GNU Mach-o section wrapper: required section missing";
+ *err = 0; /* No useful errno. */
+ XDELETEVEC (secdata);
+ return 0;
+ }
+
+ /* Fetch the name table. */
+
+ simple_object_mach_o_section_info (omr->is_big_endian, is_32,
+ secdata + nametab_index * sechdrsize,
+ &nametab_offset, &nametab_size);
+ nametab = XNEWVEC (char, nametab_size);
+ if (!simple_object_internal_read (sobj->descriptor,
+ sobj->offset + nametab_offset,
+ (unsigned char *) nametab, nametab_size,
+ errmsg, err))
+ {
+ XDELETEVEC (nametab);
+ XDELETEVEC (secdata);
+ return 0;
+ }
+
+ /* Fetch the index. */
+
+ simple_object_mach_o_section_info (omr->is_big_endian, is_32,
+ secdata + index_index * sechdrsize,
+ &index_offset, &index_size);
+ index = XNEWVEC (unsigned char, index_size);
+ if (!simple_object_internal_read (sobj->descriptor,
+ sobj->offset + index_offset,
+ index, index_size,
+ errmsg, err))
+ {
+ XDELETEVEC (index);
+ XDELETEVEC (nametab);
+ XDELETEVEC (secdata);
+ return 0;
+ }
+
+ /* The index contains 4 unsigned ints per sub-section:
+ sub-section offset/length, sub-section name/length.
+ We fix this for both 32 and 64 bit mach-o for now, since
+ other fields limit the maximum size of an object to 4G. */
+ n_wrapped_sects = index_size / 16;
+
+ /* Get the parameters for the wrapper too. */
+ simple_object_mach_o_section_info (omr->is_big_endian, is_32,
+ secdata + sections_index * sechdrsize,
+ &wrapper_sect_offset,
+ &wrapper_sect_size);
}
else
{
+ index = NULL;
+ index_size = 0;
+ nametab = NULL;
+ nametab_size = 0;
+ n_wrapped_sects = 0;
+ }
+
+ /* If we have a long names section, fetch it. */
+
+ if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
+ {
off_t strtab_offset;
simple_object_mach_o_section_info (omr->is_big_endian, is_32,
@@ -452,52 +595,120 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
errmsg, err))
{
XDELETEVEC (strtab);
+ XDELETEVEC (index);
+ XDELETEVEC (nametab);
XDELETEVEC (secdata);
return 0;
}
}
+ else
+ {
+ strtab = NULL;
+ strtab_size = 0;
+ strtab_index = nsects;
+ }
/* Process the sections. */
for (i = 0; i < nsects; ++i)
{
const unsigned char *sechdr;
- char namebuf[MACH_O_NAME_LEN + 1];
+ char namebuf[MACH_O_NAME_LEN * 2 + 2];
char *name;
off_t secoffset;
size_t secsize;
+ int l;
- if (i == strtab_index)
+ sechdr = secdata + i * sechdrsize;
+
+ /* We've already processed the long section names. */
+
+ if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0
+ && i == strtab_index)
continue;
- sechdr = secdata + i * sechdrsize;
+ /* We only act on the segment named. */
if (strcmp ((char *) sechdr + segname_offset, omr->segment_name) != 0)
continue;
- memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
- namebuf[MACH_O_NAME_LEN] = '\0';
+ /* Process sections associated with the wrapper. */
- name = &namebuf[0];
- if (strtab != NULL && name[0] == '_' && name[1] == '_')
+ if ((gnu_sections_found & SOMO_WRAPPING) != 0)
{
- unsigned long stringoffset;
+ if (i == nametab_index || i == index_index)
+ continue;
- if (sscanf (name + 2, "%08lX", &stringoffset) == 1)
+ if (i == sections_index)
{
- if (stringoffset >= strtab_size)
+ unsigned int j;
+ for (j = 0; j < n_wrapped_sects; ++j)
{
- *errmsg = "section name offset out of range";
- *err = 0;
- XDELETEVEC (strtab);
- XDELETEVEC (secdata);
- return 0;
+ unsigned int subsect_offset, subsect_length, name_offset;
+ subsect_offset = (*fetch_32) (index + 16 * j);
+ subsect_length = (*fetch_32) (index + 16 * j + 4);
+ name_offset = (*fetch_32) (index + 16 * j + 8);
+ /* We don't need the name_length yet. */
+
+ secoffset = wrapper_sect_offset + subsect_offset;
+ secsize = subsect_length;
+ name = nametab + name_offset;
+
+ if (!(*pfn) (data, name, secoffset, secsize))
+ {
+ *errmsg = NULL;
+ *err = 0;
+ XDELETEVEC (index);
+ XDELETEVEC (nametab);
+ XDELETEVEC (strtab);
+ XDELETEVEC (secdata);
+ return 0;
+ }
}
-
- name = strtab + stringoffset;
+ continue;
}
}
+ if ((gnu_sections_found & SOMO_LONGN_PRESENT) != 0)
+ {
+ memcpy (namebuf, sechdr + sectname_offset, MACH_O_NAME_LEN);
+ namebuf[MACH_O_NAME_LEN] = '\0';
+
+ name = &namebuf[0];
+ if (strtab != NULL && name[0] == '_' && name[1] == '_')
+ {
+ unsigned long stringoffset;
+
+ if (sscanf (name + 2, "%08lX", &stringoffset) == 1)
+ {
+ if (stringoffset >= strtab_size)
+ {
+ *errmsg = "section name offset out of range";
+ *err = 0;
+ XDELETEVEC (index);
+ XDELETEVEC (nametab);
+ XDELETEVEC (strtab);
+ XDELETEVEC (secdata);
+ return 0;
+ }
+
+ name = strtab + stringoffset;
+ }
+ }
+ }
+ else
+ {
+ /* Otherwise, make a name like __segment,__section as per the
+ convention in mach-o asm. */
+ name = &namebuf[0];
+ memset (namebuf, 0, MACH_O_NAME_LEN * 2 + 2);
+ memcpy (namebuf, (char *) sechdr + segname_offset, MACH_O_NAME_LEN);
+ l = strlen (namebuf);
+ namebuf[l] = ',';
+ memcpy (namebuf + l + 1, (char *) sechdr + sectname_offset,
+ MACH_O_NAME_LEN);
+ }
+
simple_object_mach_o_section_info (omr->is_big_endian, is_32, sechdr,
&secoffset, &secsize);
@@ -505,12 +716,16 @@ simple_object_mach_o_segment (simple_object_read *sobj, off_t offset,
{
*errmsg = NULL;
*err = 0;
+ XDELETEVEC (index);
+ XDELETEVEC (nametab);
XDELETEVEC (strtab);
XDELETEVEC (secdata);
return 0;
}
}
+ XDELETEVEC (index);
+ XDELETEVEC (nametab);
XDELETEVEC (strtab);
XDELETEVEC (secdata);
@@ -724,9 +939,9 @@ static int
simple_object_mach_o_write_section_header (simple_object_write *sobj,
int descriptor,
size_t sechdr_offset,
- const char *name, size_t secaddr,
- size_t secsize, size_t offset,
- unsigned int align,
+ const char *name, const char *segn,
+ size_t secaddr, size_t secsize,
+ size_t offset, unsigned int align,
const char **errmsg, int *err)
{
struct simple_object_mach_o_attributes *attrs =
@@ -748,7 +963,7 @@ simple_object_mach_o_write_section_header (simple_object_write *sobj,
strncpy ((char *) hdr + offsetof (struct mach_o_section_32, sectname),
name, MACH_O_NAME_LEN);
strncpy ((char *) hdr + offsetof (struct mach_o_section_32, segname),
- sobj->segment_name, MACH_O_NAME_LEN);
+ segn, MACH_O_NAME_LEN);
set_32 (hdr + offsetof (struct mach_o_section_32, addr), secaddr);
set_32 (hdr + offsetof (struct mach_o_section_32, size), secsize);
set_32 (hdr + offsetof (struct mach_o_section_32, offset), offset);
@@ -773,7 +988,7 @@ simple_object_mach_o_write_section_header (simple_object_write *sobj,
strncpy ((char *) hdr + offsetof (struct mach_o_section_64, sectname),
name, MACH_O_NAME_LEN);
strncpy ((char *) hdr + offsetof (struct mach_o_section_64, segname),
- sobj->segment_name, MACH_O_NAME_LEN);
+ segn, MACH_O_NAME_LEN);
set_64 (hdr + offsetof (struct mach_o_section_64, addr), secaddr);
set_64 (hdr + offsetof (struct mach_o_section_64, size), secsize);
set_32 (hdr + offsetof (struct mach_o_section_64, offset), offset);
@@ -793,11 +1008,25 @@ simple_object_mach_o_write_section_header (simple_object_write *sobj,
sechdrsize, errmsg, err);
}
-/* Write out the single segment and the sections of a Mach-O file. */
+/* Write out the single (anonymous) segment containing the sections of a Mach-O
+ Object file.
+
+ As a GNU extension to mach-o, when the caller specifies a segment name in
+ sobj->segment_name, all the sections passed will be output under a single
+ mach-o section header. The caller's sections are indexed within this
+ 'wrapper' section by a table stored in a second mach-o section. Finally,
+ arbitrary length section names are permitted by the extension and these are
+ stored in a table in a third mach-o section.
+
+ Note that this is only likely to make any sense for the __GNU_LTO segment
+ at present.
+
+ If the wrapper extension is not in force, we assume that the section name
+ is in the form __SEGMENT_NAME,__section_name as per Mach-O asm. */
static int
simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
- size_t nsects, const char **errmsg,
+ size_t *nsects, const char **errmsg,
int *err)
{
struct simple_object_mach_o_attributes *attrs =
@@ -814,6 +1043,10 @@ simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
simple_object_write_section *section;
unsigned char hdrbuf[sizeof (struct mach_o_segment_command_64)];
unsigned char *hdr;
+ size_t nsects_in;
+ unsigned int *index;
+ char *snames;
+ unsigned int sect;
set_32 = (attrs->is_big_endian
? simple_object_set_big_32
@@ -834,19 +1067,62 @@ simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
sechdrsize = sizeof (struct mach_o_section_64);
}
+ name_offset = 0;
+ *nsects = nsects_in = 0;
+
+ /* Count the number of sections we start with. */
+
+ for (section = sobj->sections; section != NULL; section = section->next)
+ nsects_in++;
+
+ if (sobj->segment_name != NULL)
+ {
+ /* We will only write 3 sections: wrapped data, index and names. */
+
+ *nsects = 3;
+
+ /* The index has four entries per wrapped section:
+ Section Offset, length, Name offset, length.
+ Where the offsets are based at the start of the wrapper and name
+ sections respectively.
+ The values are stored as 32 bit int for both 32 and 64 bit mach-o
+ since the size of a mach-o MH_OBJECT cannot exceed 4G owing to
+ other constraints. */
+
+ index = XNEWVEC (unsigned int, nsects_in * 4);
+
+ /* We now need to figure out the size of the names section. This just
+ stores the names as null-terminated c strings, packed without any
+ alignment padding. */
+
+ for (section = sobj->sections, sect = 0; section != NULL;
+ section = section->next, sect++)
+ {
+ index[sect*4+2] = name_offset;
+ index[sect*4+3] = strlen (section->name) + 1;
+ name_offset += strlen (section->name) + 1;
+ }
+ snames = XNEWVEC (char, name_offset);
+ }
+ else
+ {
+ *nsects = nsects_in;
+ index = NULL;
+ snames = NULL;
+ }
+
sechdr_offset = hdrsize + seghdrsize;
- cmdsize = seghdrsize + nsects * sechdrsize;
+ cmdsize = seghdrsize + *nsects * sechdrsize;
offset = hdrsize + cmdsize;
- name_offset = 0;
secaddr = 0;
- for (section = sobj->sections; section != NULL; section = section->next)
+ for (section = sobj->sections, sect = 0;
+ section != NULL; section = section->next, sect++)
{
size_t mask;
size_t new_offset;
size_t secsize;
struct simple_object_write_section_buffer *buffer;
- char namebuf[MACH_O_NAME_LEN + 1];
mask = (1U << section->align) - 1;
new_offset = offset + mask;
@@ -877,39 +1153,126 @@ simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
secsize += buffer->size;
}
- snprintf (namebuf, sizeof namebuf, "__%08X", name_offset);
+ if (sobj->segment_name != NULL)
+ {
+ index[sect*4+0] = (unsigned int) offset;
+ index[sect*4+1] = secsize;
+ /* Stash the section name in our table. */
+ memcpy (snames + index[sect * 4 + 2], section->name,
+ index[sect * 4 + 3]);
+ }
+ else
+ {
+ char namebuf[MACH_O_NAME_LEN + 1];
+ char segnbuf[MACH_O_NAME_LEN + 1];
+ char *comma;
+
+ /* Try to extract segment,section from the input name. */
+
+ memset (namebuf, 0, sizeof namebuf);
+ memset (segnbuf, 0, sizeof segnbuf);
+ comma = strchr (section->name, ',');
+ if (comma != NULL)
+ {
+ int len = comma - section->name;
+ len = len > MACH_O_NAME_LEN ? MACH_O_NAME_LEN : len;
+ strncpy (namebuf, section->name, len);
+ strncpy (segnbuf, comma + 1, MACH_O_NAME_LEN);
+ }
+ else /* just try to copy the name, leave segment blank. */
+ strncpy (namebuf, section->name, MACH_O_NAME_LEN);
+
+ if (!simple_object_mach_o_write_section_header (sobj, descriptor,
+ sechdr_offset,
+ namebuf, segnbuf,
+ secaddr, secsize,
+ offset,
+ section->align,
+ errmsg, err))
+ return 0;
+ sechdr_offset += sechdrsize;
+ }
+
+ offset += secsize;
+ secaddr += secsize;
+ }
+
+ if (sobj->segment_name != NULL)
+ {
+ size_t secsize;
+ unsigned int i;
+
+ /* Write the section header for the wrapper. */
+ /* Account for any initial aligment - which becomes the alignment for this
+ created section. */
+
+ secsize = (offset - index[0]);
if (!simple_object_mach_o_write_section_header (sobj, descriptor,
- sechdr_offset, namebuf,
- secaddr, secsize, offset,
- section->align,
+ sechdr_offset,
+ GNU_WRAPPER_SECTS,
+ sobj->segment_name,
+ 0 /*secaddr*/,
+ secsize, index[0],
+ sobj->sections->align,
errmsg, err))
return 0;
+ /* Subtract the wrapper section start from the begining of each sub
+ section. */
+
+ for (i = 1; i < nsects_in; ++i)
+ index[4 * i] -= index[0];
+ index[0] = 0;
+
sechdr_offset += sechdrsize;
- offset += secsize;
- name_offset += strlen (section->name) + 1;
- secaddr += secsize;
- }
- /* Write out the section names. */
+ /* Write out the section names.
+ ... the header ...
+ name_offset contains the length of the section. It is not aligned. */
- if (!simple_object_mach_o_write_section_header (sobj, descriptor,
- sechdr_offset,
- GNU_SECTION_NAMES, secaddr,
- name_offset, offset, 0,
- errmsg, err))
- return 0;
+ if (!simple_object_mach_o_write_section_header (sobj, descriptor,
+ sechdr_offset,
+ GNU_WRAPPER_NAMES,
+ sobj->segment_name,
+ 0 /*secaddr*/,
+ name_offset,
+ offset,
+ 0, errmsg, err))
+ return 0;
- for (section = sobj->sections; section != NULL; section = section->next)
- {
- size_t namelen;
+ /* ... and the content.. */
+ if (!simple_object_internal_write (descriptor, offset,
+ (const unsigned char *) snames,
+ name_offset, errmsg, err))
+ return 0;
+
+ sechdr_offset += sechdrsize;
+ secaddr += name_offset;
+ offset += name_offset;
+
+ /* Now do the index, we'll align this to 4 bytes although the read code
+ will handle unaligned. */
+
+ offset += 3;
+ offset &= ~0x03;
+ if (!simple_object_mach_o_write_section_header (sobj, descriptor,
+ sechdr_offset,
+ GNU_WRAPPER_INDEX,
+ sobj->segment_name,
+ 0 /*secaddr*/,
+ nsects_in * 16,
+ offset,
+ 2, errmsg, err))
+ return 0;
- namelen = strlen (section->name) + 1;
+ /* ... and the content.. */
if (!simple_object_internal_write (descriptor, offset,
- (const unsigned char *) section->name,
- namelen, errmsg, err))
+ (const unsigned char *) index,
+ nsects_in*16, errmsg, err))
return 0;
- offset += namelen;
+
+ XDELETEVEC (index);
+ XDELETEVEC (snames);
}
/* Write out the segment header. */
@@ -923,9 +1286,8 @@ simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
MACH_O_LC_SEGMENT);
set_32 (hdr + offsetof (struct mach_o_segment_command_32, cmdsize),
cmdsize);
- strncpy (((char *) hdr
- + offsetof (struct mach_o_segment_command_32, segname)),
- sobj->segment_name, MACH_O_NAME_LEN);
+ /* MH_OBJECTS have a single, anonymous, segment - so the segment name
+ is left empty. */
/* vmaddr left as zero. */
/* vmsize left as zero. */
set_32 (hdr + offsetof (struct mach_o_segment_command_32, fileoff),
@@ -935,7 +1297,7 @@ simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
/* maxprot left as zero. */
/* initprot left as zero. */
set_32 (hdr + offsetof (struct mach_o_segment_command_32, nsects),
- nsects);
+ *nsects);
/* flags left as zero. */
}
else
@@ -951,9 +1313,8 @@ simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
MACH_O_LC_SEGMENT);
set_32 (hdr + offsetof (struct mach_o_segment_command_64, cmdsize),
cmdsize);
- strncpy (((char *) hdr
- + offsetof (struct mach_o_segment_command_64, segname)),
- sobj->segment_name, MACH_O_NAME_LEN);
+ /* MH_OBJECTS have a single, anonymous, segment - so the segment name
+ is left empty. */
/* vmaddr left as zero. */
/* vmsize left as zero. */
set_64 (hdr + offsetof (struct mach_o_segment_command_64, fileoff),
@@ -963,7 +1324,7 @@ simple_object_mach_o_write_segment (simple_object_write *sobj, int descriptor,
/* maxprot left as zero. */
/* initprot left as zero. */
set_32 (hdr + offsetof (struct mach_o_segment_command_64, nsects),
- nsects);
+ *nsects);
/* flags left as zero. */
#endif
}
@@ -978,23 +1339,17 @@ static const char *
simple_object_mach_o_write_to_file (simple_object_write *sobj, int descriptor,
int *err)
{
- size_t nsects;
- simple_object_write_section *section;
+ size_t nsects = 0;
const char *errmsg;
- /* Start at 1 for symbol_names section. */
- nsects = 1;
- for (section = sobj->sections; section != NULL; section = section->next)
- ++nsects;
+ if (!simple_object_mach_o_write_segment (sobj, descriptor, &nsects,
+ &errmsg, err))
+ return errmsg;
if (!simple_object_mach_o_write_header (sobj, descriptor, nsects,
&errmsg, err))
return errmsg;
- if (!simple_object_mach_o_write_segment (sobj, descriptor, nsects,
- &errmsg, err))
- return errmsg;
-
return NULL;
}
diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 53adfd45285..7ff941e459f 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,16 @@
+2011-10-17 Paul Brook <paul@codesourcery.com>
+
+ * exception.cc (parse_lsda_header): hardcode ttype_encoding for older
+ ARM EABI toolchains.
+ (get_ttype_entry) Remove __ARM_EABI_UNWINDER__ variant.
+
+2011-10-16 Uros Bizjak <ubizjak@gmail.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ PR target/50737
+ * include/dwarf2-signal.h [__alpha__]: Remove MAKE_THROW_FRAME
+ definition.
+
2011-08-10 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* exception.cc (std::abort): Remove static.
diff --git a/libjava/exception.cc b/libjava/exception.cc
index 5a8a9e21cfa..56f25ad44be 100644
--- a/libjava/exception.cc
+++ b/libjava/exception.cc
@@ -161,6 +161,11 @@ parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
info->ttype_encoding = *p++;
if (info->ttype_encoding != DW_EH_PE_omit)
{
+#if _GLIBCXX_OVERRIDE_TTYPE_ENCODING
+ /* Older ARM EABI toolchains set this value incorrectly, so use a
+ hardcoded OS-specific format. */
+ info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING;
+#endif
p = read_uleb128 (p, &tmp);
info->TType = p + tmp;
}
@@ -176,21 +181,6 @@ parse_lsda_header (_Unwind_Context *context, const unsigned char *p,
return p;
}
-#ifdef __ARM_EABI_UNWINDER__
-
-static void **
-get_ttype_entry(_Unwind_Context *, lsda_header_info* info, _uleb128_t i)
-{
- _Unwind_Ptr ptr;
-
- ptr = (_Unwind_Ptr) (info->TType - (i * 4));
- ptr = _Unwind_decode_target2(ptr);
-
- return reinterpret_cast<void **>(ptr);
-}
-
-#else
-
static void **
get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
{
@@ -202,8 +192,6 @@ get_ttype_entry (_Unwind_Context *context, lsda_header_info *info, long i)
return reinterpret_cast<void **>(ptr);
}
-#endif
-
// Using a different personality function name causes link failures
// when trying to mix code using different exception handling models.
#ifdef SJLJ_EXCEPTIONS
diff --git a/libjava/include/dwarf2-signal.h b/libjava/include/dwarf2-signal.h
index 949bcc0ae39..812968217ee 100644
--- a/libjava/include/dwarf2-signal.h
+++ b/libjava/include/dwarf2-signal.h
@@ -29,20 +29,7 @@ class java::lang::Throwable;
// then throw an exception. With the dwarf2 unwinder we don't usually
// need to do anything, with some minor exceptions.
-#ifdef __alpha__
-#define MAKE_THROW_FRAME(_exception) \
-do \
-{ \
- /* Alpha either leaves PC pointing at a faulting instruction or the \
- following instruction, depending on the signal. SEGV always does \
- the former, so we adjust the saved PC to point to the following \
- instruction; this is what the handler in libgcc expects. */ \
- struct sigcontext *_sc = (struct sigcontext *)_p; \
- _sc->sc_pc += 4; \
-} \
-while (0)
-
-#elif defined(__ia64__)
+#ifdef __ia64__
#define MAKE_THROW_FRAME(_exception) \
do \
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index dbc70f190bb..474849480e0 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,17 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * Makefile.in (INCLUDES): Add -I$(MULTIBUILDTOP)../libgcc.
+ * configure.ac (target_thread_file, HAVE_GTHR_DEFAULT): Remove.
+ * configure: Regenerate.
+ * config.h.in: Regenerate.
+
+2011-10-17 Paul Brook <paul@codesourcery.com>
+ Matthias Klose <doko@ubuntu.com>
+
+ * exception.c (parse_lsda_header): hardcode ttype_encoding for older
+ ARM EABI toolchains.
+ (get_ttype_entry) Remove __ARM_EABI_UNWINDER__ variant.
+
2011-10-09 Nicola Pero <nicola.pero@meta-innovation.com>
PR libobjc/49883
diff --git a/libobjc/Makefile.in b/libobjc/Makefile.in
index 0935ccd98d6..1427bac43b2 100644
--- a/libobjc/Makefile.in
+++ b/libobjc/Makefile.in
@@ -102,6 +102,7 @@ INCLUDES = -I$(srcdir)/$(MULTISRCTOP)../gcc \
-I$(srcdir)/$(MULTISRCTOP)../gcc/config \
-I$(MULTIBUILDTOP)../../$(host_subdir)/gcc \
-I$(srcdir)/$(MULTISRCTOP)../libgcc \
+ -I$(MULTIBUILDTOP)../libgcc \
-I$(srcdir)/$(MULTISRCTOP)../include \
$(OBJC_BOEHM_GC_INCLUDES)
diff --git a/libobjc/config.h.in b/libobjc/config.h.in
index d9c8172d258..c055e7c1909 100644
--- a/libobjc/config.h.in
+++ b/libobjc/config.h.in
@@ -6,9 +6,6 @@
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
-/* Define if the compiler has a thread header that is non single. */
-#undef HAVE_GTHR_DEFAULT
-
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
diff --git a/libobjc/configure b/libobjc/configure
index c68cde0f806..59e3d98a7a5 100755
--- a/libobjc/configure
+++ b/libobjc/configure
@@ -11248,18 +11248,6 @@ done
# Miscellanea
# -----------
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread model used by GCC" >&5
-$as_echo_n "checking for thread model used by GCC... " >&6; }
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $target_thread_file" >&5
-$as_echo "$target_thread_file" >&6; }
-
-if test $target_thread_file != single; then
-
-$as_echo "#define HAVE_GTHR_DEFAULT 1" >>confdefs.h
-
-fi
-
# Check if we have thread-local storage
@@ -11483,7 +11471,7 @@ if test "${enable_sjlj_exceptions+set}" = set; then :
enableval=$enable_sjlj_exceptions; :
else
cat > conftest.$ac_ext << EOF
-#line 11486 "configure"
+#line 11474 "configure"
@interface Frob
@end
@implementation Frob
diff --git a/libobjc/configure.ac b/libobjc/configure.ac
index dd303fff065..52599e6019e 100644
--- a/libobjc/configure.ac
+++ b/libobjc/configure.ac
@@ -217,15 +217,6 @@ AC_CHECK_HEADERS(sched.h)
# Miscellanea
# -----------
-AC_MSG_CHECKING([for thread model used by GCC])
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-AC_MSG_RESULT([$target_thread_file])
-
-if test $target_thread_file != single; then
- AC_DEFINE(HAVE_GTHR_DEFAULT, 1,
- [Define if the compiler has a thread header that is non single.])
-fi
-
# Check if we have thread-local storage
GCC_CHECK_TLS
diff --git a/libobjc/exception.c b/libobjc/exception.c
index 37daed8f30c..04308ce13e7 100644
--- a/libobjc/exception.c
+++ b/libobjc/exception.c
@@ -159,6 +159,11 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
info->ttype_encoding = *p++;
if (info->ttype_encoding != DW_EH_PE_omit)
{
+#if _GLIBCXX_OVERRIDE_TTYPE_ENCODING
+ /* Older ARM EABI toolchains set this value incorrectly, so use a
+ hardcoded OS-specific format. */
+ info->ttype_encoding = _GLIBCXX_OVERRIDE_TTYPE_ENCODING;
+#endif
p = read_uleb128 (p, &tmp);
info->TType = p + tmp;
}
@@ -174,26 +179,6 @@ parse_lsda_header (struct _Unwind_Context *context, const unsigned char *p,
return p;
}
-#ifdef __ARM_EABI_UNWINDER__
-
-static Class
-get_ttype_entry (struct lsda_header_info *info, _uleb128_t i)
-{
- _Unwind_Ptr ptr;
-
- ptr = (_Unwind_Ptr) (info->TType - (i * 4));
- ptr = _Unwind_decode_target2 (ptr);
-
- /* NULL ptr means catch-all. Note that if the class is not found,
- this will abort the program. */
- if (ptr)
- return objc_getRequiredClass ((const char *) ptr);
- else
- return 0;
-}
-
-#else
-
static Class
get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
{
@@ -211,8 +196,6 @@ get_ttype_entry (struct lsda_header_info *info, _Unwind_Word i)
return 0;
}
-#endif
-
/* Using a different personality function name causes link failures
when trying to mix code using different exception handling
models. */
diff --git a/libquadmath/ChangeLog b/libquadmath/ChangeLog
index fd24f5f400d..97c15b573bf 100644
--- a/libquadmath/ChangeLog
+++ b/libquadmath/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * printf/gmp-impl.h: Adapt path to longlong.h.
+
2011-09-21 Joseph Myers <joseph@codesourcery.com>
* Makefile.am (FLAGS_TO_PASS): Define.
diff --git a/libquadmath/printf/gmp-impl.h b/libquadmath/printf/gmp-impl.h
index ca49e196613..0f1419277de 100644
--- a/libquadmath/printf/gmp-impl.h
+++ b/libquadmath/printf/gmp-impl.h
@@ -1,6 +1,6 @@
/* Include file for internal GNU MP types and definitions.
-Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+Copyright (C) 1991, 1993, 1994, 1995, 1996, 2011 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
@@ -60,7 +60,7 @@ typedef unsigned int UHWtype;
#define attribute_hidden
#endif
-#include "../../gcc/longlong.h"
+#include "../../libgcc/longlong.h"
/* Copy NLIMBS *limbs* from SRC to DST. */
#define MPN_COPY_INCR(DST, SRC, NLIMBS) \
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 628e213f1fc..f57b699471a 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,346 @@
+2011-11-02 Richard B. Kreckel <kreckel@ginac.de>
+ Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/50880
+ * include/std/complex (__complex_acosh): Fix in a better way,
+ use Kahan's formula.
+ * include/tr1/complex (__complex_acosh): Likewise.
+
+2011-11-02 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/50951
+ * include/bits/random.tcc (operator<<(basic_ostream<>&,
+ const mersenne_twister_engine<>&): Output _M_p too.
+ (operator<<(basic_ostream<>&, const
+ subtract_with_carry_engine<>&): Likewise.
+ (operator>>(basic_istream<>&, mersenne_twister_engine<>&):
+ Reload it.
+ (operator>>(basic_istream<>&, subtract_with_carry_engine<>&):
+ Likewise.
+ * include/bits/random.h (mersenne_twister_engine<>::operator==):
+ Compare _M_p too.
+ (subtract_with_carry_engine<>::operator==): Compare _M_carry
+ and _M_p too.
+ (shuffle_order_engine<>::operator==): Compare _M_v(s) and _M_y too.
+ * testsuite/26_numerics/random/independent_bits_engine/
+ operators/serialize.cc: Extend.
+ * testsuite/26_numerics/random/subtract_with_carry_engine/
+ operators/serialize.cc: Likewise.
+ * testsuite/26_numerics/random/discard_block_engine/
+ operators/serialize.cc: Likewise.
+ * testsuite/26_numerics/random/mersenne_twister_engine/
+ operators/serialize.cc: Likewise.
+ * testsuite/26_numerics/random/linear_congruential_engine/
+ operators/serialize.cc: Likewise.
+ * testsuite/26_numerics/random/shuffle_order_engine/
+ operators/serialize.cc: Likewise.
+
+2011-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * acinclude.m4 (GLIBCXX_CONFIGURE): Determine and substitute
+ toplevel_builddir.
+ (GLIBCXX_ENABLE_THREADS): Remove glibcxx_thread_h,
+ HAVE_GTHR_DEFAULT, enable_thread.
+ (GLIBCXX_CHECK_GTHREADS): Reflect gthr move to libgcc.
+ * include/Makefile.am (thread_host_headers): Remove
+ ${host_builddir}/gthr-tpf.h.
+ (${host_builddir}/gthr.h): Reflect gthr move to libgcc.
+ Use $<.
+ (${host_builddir}/gthr-single.h): Likewise.
+ (${host_builddir}/gthr-posix.h): Likewise.
+ (${host_builddir}/gthr-tpf.h): Remove.
+ (${host_builddir}/gthr-default.h): Likewise.
+ * configure, config.h.in: Regenerate.
+ * Makefile.in, doc/Makefile.in, include/Makefile.in,
+ libsupc++/Makefile.in, po/Makefile.in, python/Makefile.in,
+ src/Makefile.intestsuite/Makefile.in: Regenerate.
+
+2011-11-02 Benjamin Kosnik <bkoz@redhat.com>
+
+ * include/bits/c++config: Add tr2 to versioned namespaces.
+ * scripts/run_doxygen: Adjust generated man files as well.
+ * testsuite/ext/profile/mutex_extensions_neg.cc: Adjust line numbers.
+
+2011-11-02 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/std/future (promise): Add constructors for uses-allocator
+ construction from rvalue promise.
+ (packaged_task): Implement LWG 2067. Add additional constructors for
+ uses-allocator construction.
+ * testsuite/30_threads/packaged_task/cons/3.cc: New.
+ * testsuite/30_threads/packaged_task/cons/alloc2.cc: New.
+ * testsuite/30_threads/promise/cons/alloc2.cc: New.
+
+2011-10-31 Jason Merrill <jason@redhat.com>
+
+ * include/Makefile.am (install-freestanding-headers): Install
+ c++0x_warning.h.
+ * libsupc++/initializer_list: Include it.
+
+2011-10-31 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * acinclude.m4 (GLIBCXX_CONFIGURE): Refer to GNU/Linux.
+ * configure: Regenerate.
+
+2011-10-31 Jason Merrill <jason@redhat.com>
+
+ PR c++/50920
+ * include/bits/c++0x_warning.h: Change -std=c++0x to -std=c++11.
+
+2011-10-30 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * prerequisites.xml: Refer to GCC (instead of gcc) and GNU/Linux.
+ Remove an obsolete reference to a Red Hat release we do not
+ support any longer.
+ Refer to Debian GNU/Linux.
+
+2011-10-30 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * faq.xml (Who's in charge of it?): Refer to the Linux kernel
+ instead of just Linux.
+ (How do I install libstdc++?): Refer to GNU/Linux instead of
+ just Linux.
+
+2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * testsuite/30_threads/condition_variable_any/50862.cc: Trivial
+ formatting fixes.
+
+2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * testsuite/23_containers/unordered_map/operations/count.cc: New.
+ * testsuite/23_containers/multimap/operations/count.cc: Likewise.
+ * testsuite/23_containers/set/operations/count.cc: Likewise.
+ * testsuite/23_containers/unordered_multimap/operations/count.cc:
+ Likewise.
+ * testsuite/23_containers/unordered_set/operations/count.cc: Likewise.
+ * testsuite/23_containers/multiset/operations/count.cc: Likewise.
+ * testsuite/23_containers/unordered_multiset/operations/count.cc:
+ Likewise.
+ * testsuite/23_containers/map/operations/count.cc: Likewise.
+
+2011-10-28 Richard B. Kreckel <kreckel@ginac.de>
+
+ * include/std/complex (__complex_acosh): Just use '< _Tp()'.
+ * include/tr1/complex (__complex_acosh): Likewise.
+
+2011-10-27 Richard B. Kreckel <kreckel@ginac.de>
+ Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/50880
+ * include/std/complex (__complex_acosh): Fix for __z.real() < 0.
+ * include/tr1/complex (__complex_acosh): Likewise.
+ * testsuite/26_numerics/complex/50880.cc: New.
+ * testsuite/tr1/8_c_compatibility/complex/50880.cc: Likewise.
+
+2011-10-27 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/50862
+ * include/std/condition_variable (condition_variable_any::wait): Avoid
+ terminating if relocking user mutex throws during stack-unwinding.
+ * testsuite/30_threads/condition_variable_any/50862.cc: Add dg-require.
+
+2011-10-25 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * include/std/condition_variable (condition_variable_any): Remove
+ unused native_handle_type typedef.
+ * src/condition_variable.cc (condition_variable): Add missing noexcept
+ specifications.
+ * testsuite/30_threads/condition_variable_any/requirements/
+ typedefs.cc: Remove.
+
+2011-10-25 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/50862
+ * include/std/condition_variable (condition_variable_any::wait): Fix
+ deadlock and ensure _Lock::lock() is called on exit.
+ (condition_variable_any::native_handle): Remove, as per LWG 1500.
+ * testsuite/30_threads/condition_variable_any/50862.cc: New.
+
+2011-10-25 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/49894
+ * include/std/mutex (__mutex_base,__recursive_mutex_base): Define new
+ base classes to manage construction/destruction of native mutexes,
+ using NSDMI when INIT macros are defined.
+ (mutex,recursive_mutex,timed_mutex,recursive_timed_mutex): Derive from
+ new base classes.
+ * include/std/condition_variable (condition_variable): Use NSDMI when
+ INIT macro is defined. Use noexcept.
+ * src/condition_variable.cc (condition_variable): Explicitly-default
+ constructor/destructor when using NSDMI. Use noexcept.
+ (condition_variable_any): Likewise.
+
+2011-10-24 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/30_threads/async/49668.cc: Add missing dg-require.
+ * testsuite/30_threads/packaged_task/49668.cc: Likewise.
+
+2011-10-22 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/50834
+ * doc/xml/manual/using.xml: Update thread safety docs w.r.t. C++11.
+
+2011-10-22 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ PR libstdc++/50196
+ * acinclude.m4 (GLIBCXX_HAS_GTHREADS): Don't depend on _POSIX_TIMEOUTS.
+ * configure: Regenerate.
+ * include/std/mutex (timed_mutex, recursive_timed_mutex): Define
+ conditionally on GTHREADS_HAS_MUTEX_TIMEDLOCK.
+ * testsuite/lib/libstdc++.exp (check_v3_target_gthreads_timed): Define.
+ * testsuite/lib/dg-options.exp (dg-require-gthreads-timed): Define.
+ * testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc:
+ Use dg-require-gthreads-timed instead of dg-require-gthreads.
+ * testsuite/30_threads/recursive_timed_mutex/native_handle/
+ typesizes.cc: Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc:
+ Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc:
+ Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc:
+ Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc:
+ Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/cons/1.cc: Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc:
+ Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/requirements/typedefs.cc:
+ Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc: Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc: Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/lock/1.cc: Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/lock/2.cc: Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/unlock/1.cc: Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc:
+ Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc:
+ Likewise.
+ * testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc:
+ Likewise.
+ * testsuite/30_threads/timed_mutex/dest/destructor_locked.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/native_handle/typesizes.cc:
+ Likewise.
+ * testsuite/30_threads/timed_mutex/native_handle/1.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/try_lock_until/1.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/try_lock_until/2.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/cons/assign_neg.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/cons/1.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/cons/copy_neg.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/requirements/standard_layout.cc:
+ Likewise.
+ * testsuite/30_threads/timed_mutex/requirements/typedefs.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/try_lock/1.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/try_lock/2.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/lock/1.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/unlock/1.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/try_lock_for/1.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/try_lock_for/2.cc: Likewise.
+ * testsuite/30_threads/timed_mutex/try_lock_for/3.cc: Likewise.
+ * testsuite/30_threads/unique_lock/cons/5.cc: Likewise.
+ * testsuite/30_threads/unique_lock/cons/6.cc: Likewise.
+ * testsuite/30_threads/unique_lock/locking/3.cc: Likewise.
+ * testsuite/30_threads/unique_lock/locking/4.cc: Likewise.
+
+2011-10-19 Ed Smith-Rowland <3dw4rd@verizon.net>
+
+ * include/tr2/bool_set (bool_set): New.
+ * include/tr2/bool_set.tcc: New.
+ * include/tr2/dynamic_bitset (dynamic_bitset): New.
+ * include/tr2/ratio (kibi, mebi, gibi, tebi, pebi, exbi): New.
+ * include/Makefile.am: Add files.
+ * include/Makefile.in: Regenerate.
+
+2011-10-19 Benjamin Kosnik <bkoz@redhat.com>
+
+ * doc/doxygen/user.cfg.in: Add tr2 files.
+ * testsuite/tr2/headers/all.cc: New.
+ * testsuite/tr2/headers/using_namespace_std_tr2.cc: New.
+
+ * include/tr2/type_traits: Tweak.
+
+2011-10-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/50500
+ * include/bits/shared_ptr.h: Default copy ctor and assignment.
+ * testsuite/util/testsuite_allocator.h: Define copy assignment.
+ * testsuite/util/testsuite_rvalref.h: Default copy assignment.
+ * testsuite/20_util/weak_ptr/comparison/cmp_neg.cc: Remove note tags.
+
+2011-10-17 Michael Spertus <mike_spertus@symantec.com>
+
+ * include/tr2/type_traits (bases, direct_bases, typelist): New.
+
+2011-10-17 Benjamin Kosnik <bkoz@redhat.com>
+
+ * libstdc++-v3/include/Makefile.am: Add tr2 directory and includes.
+ * libstdc++-v3/include/Makefile.in: Regenerate.
+
+ * scripts/create_testsuite_files: Search tr2 directory.
+ * testsuite/libstdc++-dg/conformance.exp: Same.
+
+ * testsuite/tr2/bases/requirements/explicit_instantiation.cc: New.
+ * testsuite/tr2/bases/requirements/typedefs.cc: New.
+ * testsuite/tr2/bases/value.cc: New.
+ * testsuite/tr2/direct_bases/requirements/
+ explicit_instantiation.cc: New.
+ * testsuite/tr2/direct_bases/requirements/typedefs.cc: New.
+ * testsuite/tr2/direct_bases/value.cc: New.
+
+2011-10-17 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ PR bootstrap/50715
+ * config/abi/pre/gnu.ver (CXXABI_1.3.6): Remove duplicate
+ __cxa_get_exception_ptr.
+
+2011-10-14 François Dumont <francois.cppdevs@free.fr>
+
+ * testsuite/performance/23_containers/insert_erase/41975.cc: New.
+
+2011-10-14 Jonathan Wakely <jwakely.gcc@gmail.com>
+
+ * testsuite/22_locale/codecvt_byname/50714.cc: Fix mychar.
+
+2011-10-14 Jonathan Yong <jon_y@users.sourceforge.net>
+
+ * configure.host: Use config/os/mingw32-w64 instead of
+ config/os/mingw32 if vendor key is "w64".
+ * config/os/mingw32-w64: Duplicate from config/os/mingw32.
+ * config/os/mingw32-w64/os_defines.h: Enable
+ _GLIBCXX_FULLY_DYNAMIC_STRING if undefined.
+ * acinclude.m4: Set fully-dynamic-string to 1 when enabled,
+ 0 when disabled or undefined if unset by user.
+ * include/bits/basic_string.h: Check if
+ _GLIBCXX_FULLY_DYNAMIC_STRING is set to 0 instead of undefined.
+ include/bits/basic_string.tcc: Likewise.
+ * configure: Regenerated.
+ * config.h.in: Likewise.
+
+2011-10-13 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR libstdc++/50714
+ * include/bits/codecvt.h (codecvt<>::codecvt(size_t)): Initialize
+ _M_c_locale_codecvt member.
+ * testsuite/22_locale/codecvt_byname/50714.cc: New.
+
+2011-10-12 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/50594
+ * libsupc++/new (operator new, operator delete): Decorate with
+ __attribute__((__externally_visible__)).
+ * include/bits/c++config: Add _GLIBCXX_THROW.
+ * libsupc++/del_op.cc: Adjust.
+ * libsupc++/del_opv.cc: Likewise.
+ * libsupc++/del_opnt.cc: Likewise.
+ * libsupc++/del_opvnt.cc: Likewise.
+ * libsupc++/new_op.cc: Likewise.
+ * libsupc++/new_opv.cc: Likewise.
+ * libsupc++/new_opnt.cc: Likewise.
+ * libsupc++/new_opvnt.cc: Likewise.
+ * testsuite/18_support/50594.cc: New.
+ * testsuite/ext/profile/mutex_extensions_neg.cc: Adjust dg-error
+ line number.
+
2011-10-11 Emil Wojak <emil@wojak.eu>
PR c++/50661
@@ -140,7 +483,7 @@
* testsuite/23_containers/deque/modifiers/erase/3.cc: Adjust.
2011-09-25 Benjamin Kosnik <bkoz@redhat.com>
- Jonathan Wakely <jwakely.gcc@gmail.com>
+ Jonathan Wakely <jwakely.gcc@gmail.com>
PR libstdc++/48698
* acinclude.m4 (GLIBCXX_ENABLE_SYMVERS): Set libtool_VERSION here.
diff --git a/libstdc++-v3/Makefile.in b/libstdc++-v3/Makefile.in
index 272c4eeea40..2284126ab06 100644
--- a/libstdc++-v3/Makefile.in
+++ b/libstdc++-v3/Makefile.in
@@ -239,7 +239,6 @@ glibcxx_builddir = @glibcxx_builddir@
glibcxx_localedir = @glibcxx_localedir@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
-glibcxx_thread_h = @glibcxx_thread_h@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@
gxx_include_dir = @gxx_include_dir@
@@ -279,6 +278,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
# May be used by various substitution variables.
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 1b9d025efc3..684a2958ce8 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -35,6 +35,7 @@ dnl SUBDIRS
dnl Substs:
dnl glibcxx_builddir (absolute path)
dnl glibcxx_srcdir (absolute path)
+dnl toplevel_builddir (absolute path)
dnl toplevel_srcdir (absolute path)
dnl with_cross_host
dnl with_newlib
@@ -59,9 +60,11 @@ AC_DEFUN([GLIBCXX_CONFIGURE], [
[\\/$]* | ?:[\\/]*) glibcxx_srcdir=${srcdir} ;;
*) glibcxx_srcdir=`cd "$srcdir" && ${PWDCMD-pwd} || echo "$srcdir"` ;;
esac
+ toplevel_builddir=${glibcxx_builddir}/..
toplevel_srcdir=${glibcxx_srcdir}/..
AC_SUBST(glibcxx_builddir)
AC_SUBST(glibcxx_srcdir)
+ AC_SUBST(toplevel_builddir)
AC_SUBST(toplevel_srcdir)
# We use these options to decide which functions to include. They are
@@ -94,8 +97,8 @@ AC_DEFUN([GLIBCXX_CONFIGURE], [
## (Right now, this only matters for enable_wchar_t, but nothing prevents
## other macros from doing the same. This should be automated.) -pme
- # Check for C library flavor since Linux platforms use different configuration
- # directories depending on the C library in use.
+ # Check for C library flavor since GNU/Linux platforms use different
+ # configuration directories depending on the C library in use.
AC_EGREP_CPP([_using_uclibc], [
#include <stdio.h>
#if __UCLIBC__
@@ -564,17 +567,21 @@ dnl be turned on, that does not put empty objects in per-process static
dnl memory (mostly useful together with shared memory allocators, see PR
dnl libstdc++/16612 for details).
dnl
-dnl --enable-fully-dynamic-string defines _GLIBCXX_FULLY_DYNAMIC_STRING
-dnl --disable-fully-dynamic-string leaves _GLIBCXX_FULLY_DYNAMIC_STRING undefined
+dnl --enable-fully-dynamic-string defines _GLIBCXX_FULLY_DYNAMIC_STRING to 1
+dnl --disable-fully-dynamic-string defines _GLIBCXX_FULLY_DYNAMIC_STRING to 0
+dnl otherwise undefined
dnl + Usage: GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING[(DEFAULT)]
dnl Where DEFAULT is either `yes' or `no'.
dnl
AC_DEFUN([GLIBCXX_ENABLE_FULLY_DYNAMIC_STRING], [
GLIBCXX_ENABLE(fully-dynamic-string,$1,,[do not put empty strings in per-process static memory])
if test $enable_fully_dynamic_string = yes; then
- AC_DEFINE(_GLIBCXX_FULLY_DYNAMIC_STRING, 1,
- [Define if a fully dynamic basic_string is wanted.])
+ enable_fully_dynamic_string_def=1
+ else
+ enable_fully_dynamic_string_def=0
fi
+ AC_DEFINE_UNQUOTED([_GLIBCXX_FULLY_DYNAMIC_STRING], [${enable_fully_dynamic_string_def}],
+ [Define to 1 if a fully dynamic basic_string is wanted, 0 to disable, undefined for platform defaults])
])
@@ -3311,34 +3318,10 @@ dnl having to write complex code (the sed commands to clean the macro
dnl namespace are complex and fragile enough as it is). We must also
dnl add a relative path so that -I- is supported properly.
dnl
-dnl Substs:
-dnl glibcxx_thread_h
-dnl
-dnl Defines:
-dnl HAVE_GTHR_DEFAULT
-dnl
AC_DEFUN([GLIBCXX_ENABLE_THREADS], [
AC_MSG_CHECKING([for thread model used by GCC])
target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
AC_MSG_RESULT([$target_thread_file])
-
- if test $target_thread_file != single; then
- AC_DEFINE(HAVE_GTHR_DEFAULT, 1,
- [Define if gthr-default.h exists
- (meaning that threading support is enabled).])
- fi
-
- glibcxx_thread_h=gthr-$target_thread_file.h
-
- dnl Check for __GTHREADS define.
- gthread_file=${toplevel_srcdir}/gcc/${glibcxx_thread_h}
- if grep __GTHREADS $gthread_file >/dev/null 2>&1 ; then
- enable_thread=yes
- else
- enable_thread=no
- fi
-
- AC_SUBST(glibcxx_thread_h)
])
@@ -3352,13 +3335,22 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
AC_LANG_CPLUSPLUS
ac_save_CXXFLAGS="$CXXFLAGS"
- CXXFLAGS="$CXXFLAGS -fno-exceptions -I${toplevel_srcdir}/gcc"
+ CXXFLAGS="$CXXFLAGS -fno-exceptions \
+ -I${toplevel_srcdir}/libgcc -I${toplevel_builddir}/libgcc"
- AC_MSG_CHECKING([check whether it can be safely assumed that mutex_timedlock is available])
+ target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
+ case $target_thread_file in
+ posix)
+ CXXFLAGS="$CXXFLAGS -DSUPPORTS_WEAK -DGTHREAD_USE_WEAK -D_PTHREADS"
+ esac
+
+ AC_MSG_CHECKING([whether it can be safely assumed that mutex_timedlock is available])
AC_TRY_COMPILE([#include <unistd.h>],
[
- #if !defined(_POSIX_TIMEOUTS) || _POSIX_TIMEOUTS < 0
+ // In case of POSIX threads check _POSIX_TIMEOUTS.
+ #if (defined(_PTHREADS) \
+ && (!defined(_POSIX_TIMEOUTS) || _POSIX_TIMEOUTS <= 0))
#error
#endif
], [ac_gthread_use_mutex_timedlock=1], [ac_gthread_use_mutex_timedlock=0])
@@ -3370,28 +3362,13 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
else res_mutex_timedlock=no ; fi
AC_MSG_RESULT([$res_mutex_timedlock])
- target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
- case $target_thread_file in
- posix)
- CXXFLAGS="$CXXFLAGS -DSUPPORTS_WEAK -DGTHREAD_USE_WEAK -D_PTHREADS"
- esac
-
AC_MSG_CHECKING([for gthreads library])
- AC_TRY_COMPILE([
- #include "gthr.h"
- #include <unistd.h>
- ],
+ AC_TRY_COMPILE([#include "gthr.h"],
[
#ifndef __GTHREADS_CXX0X
#error
#endif
-
- // In case of POSIX threads check _POSIX_TIMEOUTS too.
- #if (defined(_PTHREADS) \
- && (!defined(_POSIX_TIMEOUTS) || _POSIX_TIMEOUTS <= 0))
- #error
- #endif
], [ac_has_gthreads=yes], [ac_has_gthreads=no])
AC_MSG_RESULT([$ac_has_gthreads])
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 82470c8cec9..f82d91ad417 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -171,10 +171,6 @@
/* Define if _Unwind_GetIPInfo is available. */
#undef HAVE_GETIPINFO
-/* Define if gthr-default.h exists (meaning that threading support is
- enabled). */
-#undef HAVE_GTHR_DEFAULT
-
/* Define to 1 if you have the `hypot' function. */
#undef HAVE_HYPOT
@@ -707,7 +703,8 @@
/* Define to use concept checking code from the boost libraries. */
#undef _GLIBCXX_CONCEPT_CHECKS
-/* Define if a fully dynamic basic_string is wanted. */
+/* Define to 1 if a fully dynamic basic_string is wanted, 0 to disable,
+ undefined for platform defaults */
#undef _GLIBCXX_FULLY_DYNAMIC_STRING
/* Define if gthreads library is available. */
diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index c45b7db47f7..bb5ff9a3a20 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -1496,7 +1496,6 @@ CXXABI_1.3.6 {
__cxa_allocate_dependent_exception;
__cxa_free_dependent_exception;
- __cxa_get_exception_ptr;
__cxa_deleted_virtual;
-} CXXABI_1.3.5; \ No newline at end of file
+} CXXABI_1.3.5;
diff --git a/libstdc++-v3/config/os/mingw32-w64/ctype_base.h b/libstdc++-v3/config/os/mingw32-w64/ctype_base.h
new file mode 100644
index 00000000000..5fbdff8e7f0
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/ctype_base.h
@@ -0,0 +1,64 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 1997, 1998, 1999, 2007, 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+// We don't use the C-locale masks defined in mingw/include/ctype.h
+// because those masks do not conform to the requirements of 22.2.1.
+// In particular, a separate 'print' bitmask does not exist (isprint(c)
+// relies on a combination of flags) and the '_ALPHA' mask is also a
+// combination of simple bitmasks. Thus, we define libstdc++-specific
+// masks here, based on the generic masks, and the corresponding
+// classic_table in ctype_noninline.h.
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /// @brief Base class for ctype.
+ struct ctype_base
+ {
+ // Non-standard typedefs.
+ typedef const int* __to_type;
+
+ // NB: Offsets into ctype<char>::_M_table force a particular size
+ // on the mask type. Because of this, we don't use an enum.
+ typedef unsigned short mask;
+ static const mask upper = 1 << 0;
+ static const mask lower = 1 << 1;
+ static const mask alpha = 1 << 2;
+ static const mask digit = 1 << 3;
+ static const mask xdigit = 1 << 4;
+ static const mask space = 1 << 5;
+ static const mask print = 1 << 6;
+ static const mask graph = (1 << 2) | (1 << 3) | (1 << 9); // alnum|punct
+ static const mask cntrl = 1 << 8;
+ static const mask punct = 1 << 9;
+ static const mask alnum = (1 << 2) | (1 << 3); // alpha|digit
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc b/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc
new file mode 100644
index 00000000000..12184075d77
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/ctype_configure_char.cc
@@ -0,0 +1,243 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file ctype_configure_char.cc */
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+#include <locale>
+#include <cstdlib>
+#include <cstring>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ // The classic table used in libstdc++ is *not* the C _ctype table
+ // used by mscvrt, but is based on the ctype masks defined for libstdc++
+ // in ctype_base.h.
+
+ const ctype_base::mask*
+ ctype<char>::classic_table() throw()
+ {
+ static const ctype_base::mask _S_classic_table[256] =
+ {
+ cntrl /* null */,
+ cntrl /* ^A */,
+ cntrl /* ^B */,
+ cntrl /* ^C */,
+ cntrl /* ^D */,
+ cntrl /* ^E */,
+ cntrl /* ^F */,
+ cntrl /* ^G */,
+ cntrl /* ^H */,
+ ctype_base::mask(space | cntrl) /* tab */,
+ ctype_base::mask(space | cntrl) /* LF */,
+ ctype_base::mask(space | cntrl) /* ^K */,
+ ctype_base::mask(space | cntrl) /* FF */,
+ ctype_base::mask(space | cntrl) /* ^M */,
+ cntrl /* ^N */,
+ cntrl /* ^O */,
+ cntrl /* ^P */,
+ cntrl /* ^Q */,
+ cntrl /* ^R */,
+ cntrl /* ^S */,
+ cntrl /* ^T */,
+ cntrl /* ^U */,
+ cntrl /* ^V */,
+ cntrl /* ^W */,
+ cntrl /* ^X */,
+ cntrl /* ^Y */,
+ cntrl /* ^Z */,
+ cntrl /* esc */,
+ cntrl /* ^\ */,
+ cntrl /* ^] */,
+ cntrl /* ^^ */,
+ cntrl /* ^_ */,
+ ctype_base::mask(space | print) /* */,
+ ctype_base::mask(punct | print) /* ! */,
+ ctype_base::mask(punct | print) /* " */,
+ ctype_base::mask(punct | print) /* # */,
+ ctype_base::mask(punct | print) /* $ */,
+ ctype_base::mask(punct | print) /* % */,
+ ctype_base::mask(punct | print) /* & */,
+ ctype_base::mask(punct | print) /* ' */,
+ ctype_base::mask(punct | print) /* ( */,
+ ctype_base::mask(punct | print) /* ) */,
+ ctype_base::mask(punct | print) /* * */,
+ ctype_base::mask(punct | print) /* + */,
+ ctype_base::mask(punct | print) /* , */,
+ ctype_base::mask(punct | print) /* - */,
+ ctype_base::mask(punct | print) /* . */,
+ ctype_base::mask(punct | print) /* / */,
+ ctype_base::mask(digit | xdigit | print) /* 0 */,
+ ctype_base::mask(digit | xdigit | print) /* 1 */,
+ ctype_base::mask(digit | xdigit | print) /* 2 */,
+ ctype_base::mask(digit | xdigit | print) /* 3 */,
+ ctype_base::mask(digit | xdigit | print) /* 4 */,
+ ctype_base::mask(digit | xdigit | print) /* 5 */,
+ ctype_base::mask(digit | xdigit | print) /* 6 */,
+ ctype_base::mask(digit | xdigit | print) /* 7 */,
+ ctype_base::mask(digit | xdigit | print) /* 8 */,
+ ctype_base::mask(digit | xdigit | print) /* 9 */,
+ ctype_base::mask(punct | print) /* : */,
+ ctype_base::mask(punct | print) /* ; */,
+ ctype_base::mask(punct | print) /* < */,
+ ctype_base::mask(punct | print) /* = */,
+ ctype_base::mask(punct | print) /* > */,
+ ctype_base::mask(punct | print) /* ? */,
+ ctype_base::mask(punct | print) /* ! */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* A */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* B */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* C */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* D */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* E */,
+ ctype_base::mask(alpha | upper | xdigit | print) /* F */,
+ ctype_base::mask(alpha | upper | print) /* G */,
+ ctype_base::mask(alpha | upper | print) /* H */,
+ ctype_base::mask(alpha | upper | print) /* I */,
+ ctype_base::mask(alpha | upper | print) /* J */,
+ ctype_base::mask(alpha | upper | print) /* K */,
+ ctype_base::mask(alpha | upper | print) /* L */,
+ ctype_base::mask(alpha | upper | print) /* M */,
+ ctype_base::mask(alpha | upper | print) /* N */,
+ ctype_base::mask(alpha | upper | print) /* O */,
+ ctype_base::mask(alpha | upper | print) /* P */,
+ ctype_base::mask(alpha | upper | print) /* Q */,
+ ctype_base::mask(alpha | upper | print) /* R */,
+ ctype_base::mask(alpha | upper | print) /* S */,
+ ctype_base::mask(alpha | upper | print) /* T */,
+ ctype_base::mask(alpha | upper | print) /* U */,
+ ctype_base::mask(alpha | upper | print) /* V */,
+ ctype_base::mask(alpha | upper | print) /* W */,
+ ctype_base::mask(alpha | upper | print) /* X */,
+ ctype_base::mask(alpha | upper | print) /* Y */,
+ ctype_base::mask(alpha | upper | print) /* Z */,
+ ctype_base::mask(punct | print) /* [ */,
+ ctype_base::mask(punct | print) /* \ */,
+ ctype_base::mask(punct | print) /* ] */,
+ ctype_base::mask(punct | print) /* ^ */,
+ ctype_base::mask(punct | print) /* _ */,
+ ctype_base::mask(punct | print) /* ` */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* a */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* b */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* c */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* d */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* e */,
+ ctype_base::mask(alpha | lower | xdigit | print) /* f */,
+ ctype_base::mask(alpha | lower | print) /* g */,
+ ctype_base::mask(alpha | lower | print) /* h */,
+ ctype_base::mask(alpha | lower | print) /* i */,
+ ctype_base::mask(alpha | lower | print) /* j */,
+ ctype_base::mask(alpha | lower | print) /* k */,
+ ctype_base::mask(alpha | lower | print) /* l */,
+ ctype_base::mask(alpha | lower | print) /* m */,
+ ctype_base::mask(alpha | lower | print) /* n */,
+ ctype_base::mask(alpha | lower | print) /* o */,
+ ctype_base::mask(alpha | lower | print) /* p */,
+ ctype_base::mask(alpha | lower | print) /* q */,
+ ctype_base::mask(alpha | lower | print) /* r */,
+ ctype_base::mask(alpha | lower | print) /* s */,
+ ctype_base::mask(alpha | lower | print) /* t */,
+ ctype_base::mask(alpha | lower | print) /* u */,
+ ctype_base::mask(alpha | lower | print) /* v */,
+ ctype_base::mask(alpha | lower | print) /* w */,
+ ctype_base::mask(alpha | lower | print) /* x */,
+ ctype_base::mask(alpha | lower | print) /* y */,
+ ctype_base::mask(alpha | lower | print) /* x */,
+ ctype_base::mask(punct | print) /* { */,
+ ctype_base::mask(punct | print) /* | */,
+ ctype_base::mask(punct | print) /* } */,
+ ctype_base::mask(punct | print) /* ~ */,
+ cntrl /* del (0x7f)*/,
+ /* The next 128 entries are all 0. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ return _S_classic_table;
+ }
+
+ ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
+ size_t __refs)
+ : facet(__refs), _M_del(__table != 0 && __del),
+ _M_toupper(NULL), _M_tolower(NULL),
+ _M_table(__table ? __table : classic_table())
+ {
+ memset(_M_widen, 0, sizeof(_M_widen));
+ _M_widen_ok = 0;
+ memset(_M_narrow, 0, sizeof(_M_narrow));
+ _M_narrow_ok = 0;
+ }
+
+ ctype<char>::ctype(const mask* __table, bool __del, size_t __refs)
+ : facet(__refs), _M_del(__table != 0 && __del),
+ _M_toupper(NULL), _M_tolower(NULL),
+ _M_table(__table ? __table : classic_table())
+ {
+ memset(_M_widen, 0, sizeof(_M_widen));
+ _M_widen_ok = 0;
+ memset(_M_narrow, 0, sizeof(_M_narrow));
+ _M_narrow_ok = 0;
+ }
+
+ char
+ ctype<char>::do_toupper(char __c) const
+ { return (this->is(ctype_base::lower, __c) ? (__c - 'a' + 'A') : __c); }
+
+ const char*
+ ctype<char>::do_toupper(char* __low, const char* __high) const
+ {
+ while (__low < __high)
+ {
+ *__low = this->do_toupper(*__low);
+ ++__low;
+ }
+ return __high;
+ }
+
+ char
+ ctype<char>::do_tolower(char __c) const
+ { return (this->is(ctype_base::upper, __c) ? (__c - 'A' + 'a') : __c); }
+
+ const char*
+ ctype<char>::do_tolower(char* __low, const char* __high) const
+ {
+ while (__low < __high)
+ {
+ *__low = this->do_tolower(*__low);
+ ++__low;
+ }
+ return __high;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/mingw32-w64/ctype_inline.h b/libstdc++-v3/config/os/mingw32-w64/ctype_inline.h
new file mode 100644
index 00000000000..f1b9f6c6617
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/ctype_inline.h
@@ -0,0 +1,75 @@
+// Locale support -*- C++ -*-
+
+// Copyright (C) 2000, 2009, 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/ctype_inline.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{locale}
+ */
+
+//
+// ISO C++ 14882: 22.1 Locales
+//
+
+// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
+// functions go in ctype.cc
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ bool
+ ctype<char>::
+ is(mask __m, char __c) const
+ { return (_M_table[static_cast<unsigned char>(__c) ] & __m); }
+
+
+ const char*
+ ctype<char>::
+ is(const char* __low, const char* __high, mask* __vec) const
+ {
+ while (__low < __high)
+ *__vec++ = _M_table[static_cast<unsigned char>(*__low++)];
+ return __high;
+ }
+
+ const char*
+ ctype<char>::
+ scan_is(mask __m, const char* __low, const char* __high) const
+ {
+ while (__low < __high && !this->is(__m, *__low))
+ ++__low;
+ return __low;
+ }
+
+ const char*
+ ctype<char>::
+ scan_not(mask __m, const char* __low, const char* __high) const
+ {
+ while (__low < __high && this->is(__m, *__low) != 0)
+ ++__low;
+ return __low;
+ }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
diff --git a/libstdc++-v3/config/os/mingw32-w64/error_constants.h b/libstdc++-v3/config/os/mingw32-w64/error_constants.h
new file mode 100644
index 00000000000..da2d311762c
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/error_constants.h
@@ -0,0 +1,142 @@
+// Specific definitions for mingw32 platform -*- C++ -*-
+
+// Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/error_constants.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{system_error}
+ */
+
+#ifndef _GLIBCXX_ERROR_CONSTANTS
+# define _GLIBCXX_ERROR_CONSTANTS
+
+#include <bits/c++config.h>
+#include <cerrno>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+// Most of the commented-out error codes are socket-related and could be
+// replaced by Winsock WSA-prefixed equivalents.
+ enum class errc
+ {
+// address_family_not_supported = EAFNOSUPPORT,
+// address_in_use = EADDRINUSE,
+// address_not_available = EADDRNOTAVAIL,
+// already_connected = EISCONN,
+ argument_list_too_long = E2BIG,
+ argument_out_of_domain = EDOM,
+ bad_address = EFAULT,
+ bad_file_descriptor = EBADF,
+// bad_message = EBADMSG,
+ broken_pipe = EPIPE,
+// connection_aborted = ECONNABORTED,
+// connection_already_in_progress = EALREADY,
+// connection_refused = ECONNREFUSED,
+// connection_reset = ECONNRESET,
+// cross_device_link = EXDEV,
+// destination_address_required = EDESTADDRREQ,
+ device_or_resource_busy = EBUSY,
+ directory_not_empty = ENOTEMPTY,
+ executable_format_error = ENOEXEC,
+ file_exists = EEXIST,
+ file_too_large = EFBIG,
+ filename_too_long = ENAMETOOLONG,
+ function_not_supported = ENOSYS,
+// host_unreachable = EHOSTUNREACH,
+// identifier_removed = EIDRM,
+ illegal_byte_sequence = EILSEQ,
+ inappropriate_io_control_operation = ENOTTY,
+ interrupted = EINTR,
+ invalid_argument = EINVAL,
+ invalid_seek = ESPIPE,
+ io_error = EIO,
+ is_a_directory = EISDIR,
+// message_size = EMSGSIZE,
+// network_down = ENETDOWN,
+// network_reset = ENETRESET,
+// network_unreachable = ENETUNREACH,
+// no_buffer_space = ENOBUFS,
+#ifdef _GLIBCXX_HAVE_ECHILD
+ no_child_process = ECHILD,
+#endif
+// no_link = ENOLINK,
+ no_lock_available = ENOLCK,
+// no_message_available = ENODATA,
+// no_message = ENOMSG,
+// no_protocol_option = ENOPROTOOPT,
+#ifdef _GLIBCXX_HAVE_ENOSPC
+ no_space_on_device = ENOSPC,
+#endif
+// no_stream_resources = ENOSR,
+ no_such_device_or_address = ENXIO,
+ no_such_device = ENODEV,
+ no_such_file_or_directory = ENOENT,
+ no_such_process = ESRCH,
+ not_a_directory = ENOTDIR,
+// not_a_socket = ENOTSOCK,
+// not_a_stream = ENOSTR,
+// not_connected = ENOTCONN,
+ not_enough_memory = ENOMEM,
+#ifdef _GLIBCXX_HAVE_ENOTSUP
+ not_supported = ENOTSUP,
+#endif
+// operation_canceled = ECANCELED,
+// operation_in_progress = EINPROGRESS,
+#ifdef _GLIBCXX_HAVE_EPERM
+ operation_not_permitted = EPERM,
+#endif
+// operation_not_supported = EOPNOTSUPP,
+#ifdef _GLIBCXX_HAVE_EWOULDBLOCK
+ operation_would_block = EWOULDBLOCK,
+#endif
+// owner_dead = EOWNERDEAD,
+ permission_denied = EACCES,
+// protocol_error = EPROTO,
+// protocol_not_supported = EPROTONOSUPPORT,
+ read_only_file_system = EROFS,
+ resource_deadlock_would_occur = EDEADLK,
+ resource_unavailable_try_again = EAGAIN,
+ result_out_of_range = ERANGE,
+// state_not_recoverable = ENOTRECOVERABLE,
+// stream_timeout = ETIME,
+// text_file_busy = ETXTBSY,
+#ifdef _GLIBCXX_HAVE_ETIMEDOUT
+ timed_out = ETIMEDOUT,
+#endif
+ too_many_files_open_in_system = ENFILE,
+ too_many_files_open = EMFILE,
+ too_many_links = EMLINK
+// too_many_symbolic_link_levels = ELOOP,
+#ifdef _GLIBCXX_HAVE_EOVERFLOW
+ ,
+ value_too_large = EOVERFLOW
+#endif
+// wrong_protocol_type = EPROTOTYPE
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif
diff --git a/libstdc++-v3/config/os/mingw32-w64/os_defines.h b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
new file mode 100644
index 00000000000..c483a92e6da
--- /dev/null
+++ b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
@@ -0,0 +1,68 @@
+// Specific definitions for generic platforms -*- C++ -*-
+
+// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+// 2009, 2010 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/os_defines.h
+ * This is an internal header file, included by other library headers.
+ * Do not attempt to use it directly. @headername{iosfwd}
+ */
+
+#ifndef _GLIBCXX_OS_DEFINES
+# define _GLIBCXX_OS_DEFINES
+
+// System-specific #define, typedefs, corrections, etc, go here. This
+// file will come before all others.
+
+// Define as 0, if you want, to enable inlining of gthread functions.
+// By default, don't pollute libstdc++ with win32api names.
+#if !defined (__GTHREAD_HIDE_WIN32API)
+# define __GTHREAD_HIDE_WIN32API 1
+#endif
+
+// Don't let win32api windef.h define min and max as macros
+// if included after c++config.h.
+#undef NOMINMAX
+#define NOMINMAX 1
+
+#if defined (_GLIBCXX_DLL)
+#define _GLIBCXX_PSEUDO_VISIBILITY_default __attribute__ ((__dllimport__))
+#else
+#define _GLIBCXX_PSEUDO_VISIBILITY_default
+#endif
+#define _GLIBCXX_PSEUDO_VISIBILITY_hidden
+
+#define _GLIBCXX_PSEUDO_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY_ ## V
+
+// See libstdc++/20806.
+#define _GLIBCXX_HAVE_DOS_BASED_FILESYSTEM 1
+
+// See libstdc++/37522.
+#define _GLIBCXX_HAVE_BROKEN_VSWPRINTF 1
+
+// See libstdc++/43738
+// On native windows targets there is no ioctl function. And the existing
+// ioctlsocket function doesn't work for normal file-descriptors.
+#define _GLIBCXX_NO_IOCTL 1
+
+#endif
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index ef663beee0c..428cdc5bd80 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -707,7 +707,6 @@ BASIC_FILE_H
CSTDIO_H
SECTION_FLAGS
WERROR
-glibcxx_thread_h
glibcxx_PCHFLAGS
GLIBCXX_BUILD_PCH_FALSE
GLIBCXX_BUILD_PCH_TRUE
@@ -741,6 +740,7 @@ AR
AS
LN_S
toplevel_srcdir
+toplevel_builddir
glibcxx_srcdir
glibcxx_builddir
ac_ct_CXX
@@ -4870,11 +4870,13 @@ $as_echo "$ac_cv_path_EGREP" >&6; }
\\/$* | ?:\\/*) glibcxx_srcdir=${srcdir} ;;
*) glibcxx_srcdir=`cd "$srcdir" && ${PWDCMD-pwd} || echo "$srcdir"` ;;
esac
+ toplevel_builddir=${glibcxx_builddir}/..
toplevel_srcdir=${glibcxx_srcdir}/..
+
# We use these options to decide which functions to include. They are
# set from the top level.
@@ -5219,8 +5221,8 @@ fi
## (Right now, this only matters for enable_wchar_t, but nothing prevents
## other macros from doing the same. This should be automated.) -pme
- # Check for C library flavor since Linux platforms use different configuration
- # directories depending on the C library in use.
+ # Check for C library flavor since GNU/Linux platforms use different
+ # configuration directories depending on the C library in use.
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -11485,7 +11487,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11488 "configure"
+#line 11490 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11591,7 +11593,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11594 "configure"
+#line 11596 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -14949,7 +14951,7 @@ fi
#
# Fake what AC_TRY_COMPILE does. XXX Look at redoing this new-style.
cat > conftest.$ac_ext << EOF
-#line 14952 "configure"
+#line 14954 "configure"
struct S { ~S(); };
void bar();
void foo()
@@ -15077,23 +15079,6 @@ $as_echo_n "checking for thread model used by GCC... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $target_thread_file" >&5
$as_echo "$target_thread_file" >&6; }
- if test $target_thread_file != single; then
-
-$as_echo "#define HAVE_GTHR_DEFAULT 1" >>confdefs.h
-
- fi
-
- glibcxx_thread_h=gthr-$target_thread_file.h
-
- gthread_file=${toplevel_srcdir}/gcc/${glibcxx_thread_h}
- if grep __GTHREADS $gthread_file >/dev/null 2>&1 ; then
- enable_thread=yes
- else
- enable_thread=no
- fi
-
-
-
ac_ext=cpp
@@ -15317,7 +15302,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
# Fake what AC_TRY_COMPILE does.
cat > conftest.$ac_ext << EOF
-#line 15320 "configure"
+#line 15305 "configure"
int main()
{
typedef bool atomic_type;
@@ -15354,7 +15339,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15357 "configure"
+#line 15342 "configure"
int main()
{
typedef short atomic_type;
@@ -15391,7 +15376,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15394 "configure"
+#line 15379 "configure"
int main()
{
// NB: _Atomic_word not necessarily int.
@@ -15429,7 +15414,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15432 "configure"
+#line 15417 "configure"
int main()
{
typedef long long atomic_type;
@@ -15505,7 +15490,7 @@ $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15508 "configure"
+#line 15493 "configure"
int main()
{
_Decimal32 d1;
@@ -15547,7 +15532,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 15550 "configure"
+#line 15535 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -15581,7 +15566,7 @@ $as_echo "$enable_int128" >&6; }
rm -f conftest*
cat > conftest.$ac_ext << EOF
-#line 15584 "configure"
+#line 15569 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -17240,10 +17225,15 @@ fi
if test $enable_fully_dynamic_string = yes; then
+ enable_fully_dynamic_string_def=1
+ else
+ enable_fully_dynamic_string_def=0
+ fi
-$as_echo "#define _GLIBCXX_FULLY_DYNAMIC_STRING 1" >>confdefs.h
+cat >>confdefs.h <<_ACEOF
+#define _GLIBCXX_FULLY_DYNAMIC_STRING ${enable_fully_dynamic_string_def}
+_ACEOF
- fi
@@ -19816,10 +19806,17 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
ac_save_CXXFLAGS="$CXXFLAGS"
- CXXFLAGS="$CXXFLAGS -fno-exceptions -I${toplevel_srcdir}/gcc"
+ CXXFLAGS="$CXXFLAGS -fno-exceptions \
+ -I${toplevel_srcdir}/libgcc -I${toplevel_builddir}/libgcc"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking check whether it can be safely assumed that mutex_timedlock is available" >&5
-$as_echo_n "checking check whether it can be safely assumed that mutex_timedlock is available... " >&6; }
+ target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
+ case $target_thread_file in
+ posix)
+ CXXFLAGS="$CXXFLAGS -DSUPPORTS_WEAK -DGTHREAD_USE_WEAK -D_PTHREADS"
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it can be safely assumed that mutex_timedlock is available" >&5
+$as_echo_n "checking whether it can be safely assumed that mutex_timedlock is available... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -19828,7 +19825,9 @@ int
main ()
{
- #if !defined(_POSIX_TIMEOUTS) || _POSIX_TIMEOUTS < 0
+ // In case of POSIX threads check _POSIX_TIMEOUTS.
+ #if (defined(_PTHREADS) \
+ && (!defined(_POSIX_TIMEOUTS) || _POSIX_TIMEOUTS <= 0))
#error
#endif
@@ -19854,21 +19853,12 @@ _ACEOF
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $res_mutex_timedlock" >&5
$as_echo "$res_mutex_timedlock" >&6; }
- target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
- case $target_thread_file in
- posix)
- CXXFLAGS="$CXXFLAGS -DSUPPORTS_WEAK -DGTHREAD_USE_WEAK -D_PTHREADS"
- esac
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gthreads library" >&5
$as_echo_n "checking for gthreads library... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-
- #include "gthr.h"
- #include <unistd.h>
-
+#include "gthr.h"
int
main ()
{
@@ -19877,12 +19867,6 @@ main ()
#error
#endif
- // In case of POSIX threads check _POSIX_TIMEOUTS too.
- #if (defined(_PTHREADS) \
- && (!defined(_POSIX_TIMEOUTS) || _POSIX_TIMEOUTS <= 0))
- #error
- #endif
-
;
return 0;
}
diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
index 799cec2f412..4da4508fa4f 100644
--- a/libstdc++-v3/configure.host
+++ b/libstdc++-v3/configure.host
@@ -260,8 +260,16 @@ case "${host_os}" in
atomic_word_dir=os/irix
;;
mingw32*)
- os_include_dir="os/mingw32"
- error_constants_dir="os/mingw32"
+ case "$host" in
+ *-w64-*)
+ os_include_dir="os/mingw32-w64"
+ error_constants_dir="os/mingw32-w64"
+ ;;
+ *)
+ os_include_dir="os/mingw32"
+ error_constants_dir="os/mingw32"
+ ;;
+ esac
OPT_LDFLAGS="${OPT_LDFLAGS} \$(lt_host_flags)"
;;
netbsd*)
diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in
index 43045671ccd..8c38839bff7 100644
--- a/libstdc++-v3/doc/Makefile.in
+++ b/libstdc++-v3/doc/Makefile.in
@@ -215,7 +215,6 @@ glibcxx_builddir = @glibcxx_builddir@
glibcxx_localedir = @glibcxx_localedir@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
-glibcxx_thread_h = @glibcxx_thread_h@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@
gxx_include_dir = @gxx_include_dir@
@@ -263,6 +262,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
# May be used by various substitution variables.
diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index def04065751..0b01ceb61e6 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -746,6 +746,10 @@ INPUT = @srcdir@/doc/doxygen/doxygroups.cc \
include/tr1/ctime \
include/tr1/cwchar \
include/tr1/cwctype \
+ include/tr2/bool_set \
+ include/tr2/dynamic_bitset \
+ include/tr2/ratio \
+ include/tr2/type_traits \
include/decimal/decimal \
include/ext \
include/ext/pb_ds \
diff --git a/libstdc++-v3/doc/xml/faq.xml b/libstdc++-v3/doc/xml/faq.xml
index 05e805e90a5..4be79df6762 100644
--- a/libstdc++-v3/doc/xml/faq.xml
+++ b/libstdc++-v3/doc/xml/faq.xml
@@ -87,7 +87,7 @@
<answer xml:id="a-who">
<para>
The libstdc++ project is contributed to by several developers
- all over the world, in the same way as GCC or Linux.
+ all over the world, in the same way as GCC or the Linux kernel.
Benjamin Kosnik, Gabriel Dos Reis, Phil Edwards, Ulrich Drepper,
Loren James Rittle, and Paolo Carlini are the lead maintainers of
the SVN archive.
@@ -261,7 +261,7 @@
<answer xml:id="a-how_to_install">
<para>
Often libstdc++ comes pre-installed as an integral part of many
- existing Linux and Unix systems, as well as many embedded
+ existing GNU/Linux and Unix systems, as well as many embedded
development tools. It may be necessary to install extra
development packages to get the headers, or the documentation, or
the source: please consult your vendor for details.
diff --git a/libstdc++-v3/doc/xml/manual/prerequisites.xml b/libstdc++-v3/doc/xml/manual/prerequisites.xml
index 0a41c44ea75..078813bf949 100644
--- a/libstdc++-v3/doc/xml/manual/prerequisites.xml
+++ b/libstdc++-v3/doc/xml/manual/prerequisites.xml
@@ -57,9 +57,9 @@
<listitem>
<para>
- If gcc 3.1.0 or later on is being used on linux, an attempt
+ If GCC 3.1.0 or later on is being used on GNU/Linux, an attempt
will be made to use "C" library functionality necessary for
- C++ named locale support. For gcc 4.6.0 and later, this
+ C++ named locale support. For GCC 4.6.0 and later, this
means that glibc 2.3 or later is required.
</para>
@@ -110,32 +110,12 @@ zh_TW BIG5
<itemizedlist>
<listitem>
<para>install all locales</para>
- <itemizedlist>
- <listitem>
- <para>with RedHat Linux:
- </para>
- <para> <code> export LC_ALL=C </code>
- </para>
- <para> <code> rpm -e glibc-common --nodeps </code>
- </para>
- <para>
- <code> rpm -i --define "_install_langs all"
- glibc-common-2.2.5-34.i386.rpm
- </code>
- </para>
- </listitem>
- <listitem>
- <para>
- Instructions for other operating systems solicited.
- </para>
- </listitem>
- </itemizedlist>
</listitem>
<listitem>
<para>install just the necessary locales</para>
<itemizedlist>
<listitem>
- <para>with Debian Linux:</para>
+ <para>with Debian GNU/Linux:</para>
<para> Add the above list, as shown, to the file
<code>/etc/locale.gen</code> </para>
<para> run <code>/usr/sbin/locale-gen</code> </para>
diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml
index 02498e21cd8..49541165868 100644
--- a/libstdc++-v3/doc/xml/manual/using.xml
+++ b/libstdc++-v3/doc/xml/manual/using.xml
@@ -1281,9 +1281,16 @@ A quick read of the relevant part of the GCC
<section xml:id="manual.intro.using.concurrency.thread_safety" xreflabel="Thread Safety"><info><title>Thread Safety</title></info>
-
<para>
-We currently use the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/thread_safety.html">SGI STL</link> definition of thread safety.
+In the terms of the 2011 C++ standard a thread-safe program is one which
+does not perform any conflicting non-atomic operations on memory locations
+and so does not contain any data races.
+The standard places requirements on the library to ensure that no data
+races are caused by the library itself or by programs which use the
+library correctly (as described below).
+The C++11 memory model and library requirements are a more formal version
+of the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.sgi.com/tech/stl/thread_safety.html">SGI STL</link> definition of thread safety, which the library used
+prior to the 2011 standard.
</para>
@@ -1329,17 +1336,25 @@ gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)
</listitem>
</itemizedlist>
- <para>The user-code must guard against concurrent method calls which may
- access any particular library object's state. Typically, the
- application programmer may infer what object locks must be held
- based on the objects referenced in a method call. Without getting
+
+ <para>The user code must guard against concurrent function calls which
+ access any particular library object's state when one or more of
+ those accesses modifies the state. An object will be modified by
+ invoking a non-const member function on it or passing it as a
+ non-const argument to a library function. An object will not be
+ modified by invoking a const member function on it or passing it to
+ a function as a pointer- or reference-to-const.
+ Typically, the application
+ programmer may infer what object locks must be held based on the
+ objects referenced in a function call and whether the objects are
+ accessed as const or non-const. Without getting
into great detail, here is an example which requires user-level
locks:
</para>
<programlisting>
library_class_a shared_object_a;
- thread_main () {
+ void thread_main () {
library_class_b *object_b = new library_class_b;
shared_object_a.add_b (object_b); // must hold lock for shared_object_a
shared_object_a.mutate (); // must hold lock for shared_object_a
@@ -1347,25 +1362,84 @@ gcc version 4.1.2 20070925 (Red Hat 4.1.2-33)
// Multiple copies of thread_main() are started in independent threads.</programlisting>
<para>Under the assumption that object_a and object_b are never exposed to
- another thread, here is an example that should not require any
+ another thread, here is an example that does not require any
user-level locks:
</para>
<programlisting>
- thread_main () {
+ void thread_main () {
library_class_a object_a;
library_class_b *object_b = new library_class_b;
object_a.add_b (object_b);
object_a.mutate ();
} </programlisting>
- <para>All library objects are safe to use in a multithreaded program as
- long as each thread carefully locks out access by any other
- thread while it uses any object visible to another thread, i.e.,
- treat library objects like any other shared resource. In general,
- this requirement includes both read and write access to objects;
- unless otherwise documented as safe, do not assume that two threads
- may access a shared standard library object at the same time.
+
+ <para>All library types are safe to use in a multithreaded program
+ if objects are not shared between threads or as
+ long each thread carefully locks out access by any other
+ thread while it modifies any object visible to another thread.
+ Unless otherwise documented, the only exceptions to these rules
+ are atomic operations on the types in
+ <filename class="headerfile">&lt;atomic&gt;</filename>
+ and lock/unlock operations on the standard mutex types in
+ <filename class="headerfile">&lt;mutex&gt;</filename>. These
+ atomic operations allow concurrent accesses to the same object
+ without introducing data races.
+ </para>
+
+ <para>The following member functions of standard containers can be
+ considered to be const for the purposes of avoiding data races:
+ <code>begin</code>, <code>end</code>, <code>rbegin</code>, <code>rend</code>,
+ <code>front</code>, <code>back</code>, <code>data</code>,
+ <code>find</code>, <code>lower_bound</code>, <code>upper_bound</code>,
+ <code>equal_range</code>, <code>at</code>
+ and, except in associative or unordered associative containers,
+ <code>operator[]</code>. In other words, although they are non-const
+ so that they can return mutable iterators, those member functions
+ will not modify the container.
+ Accessing an iterator might cause a non-modifying access to
+ the container the iterator refers to (for example incrementing a
+ list iterator must access the pointers between nodes, which are part
+ of the container and so conflict with other accesses to the container).
</para>
+ <para>Programs which follow the rules above will not encounter data
+ races in library code, even when using library types which share
+ state between distinct objects. In the example below the
+ <code>shared_ptr</code> objects share a reference count, but
+ because the code does not perform any non-const operations on the
+ globally-visible object, the library ensures that the reference
+ count updates are atomic and do not introduce data races:
+ </para>
+ <programlisting>
+ std::shared_ptr&lt;int&gt; global_sp;
+
+ void thread_main() {
+ auto local_sp = global_sp; // OK, copy constructor's parameter is reference-to-const
+
+ int i = *global_sp; // OK, operator* is const
+ int j = *local_sp; // OK, does not operate on global_sp
+
+ // *global_sp = 2; // NOT OK, modifies int visible to other threads
+ // *local_sp = 2; // NOT OK, modifies int visible to other threads
+
+ // global_sp.reset(); // NOT OK, reset is non-const
+ local_sp.reset(); // OK, does not operate on global_sp
+ }
+
+ int main() {
+ global_sp.reset(new int(1));
+ std::thread t1(thread_main);
+ std::thread t2(thread_main);
+ t1.join();
+ t2.join();
+ }
+ </programlisting>
+
+ <para>For further details of the C++11 memory model see Hans-J. Boehm's
+ <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/user-faq.html">Threads
+ and memory model for C++</link> pages, particularly the <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/threadsintro.html">introduction</link>
+ and <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://www.hpl.hp.com/personal/Hans_Boehm/c++mm/user-faq.html">FAQ</link>.
+ </para>
</section>
<section xml:id="manual.intro.using.concurrency.atomics" xreflabel="Atomics"><info><title>Atomics</title></info>
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 1abd6dded30..bc4594db4a3 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -79,7 +79,7 @@ std_headers = \
bits_srcdir = ${glibcxx_srcdir}/include/bits
bits_builddir = ./bits
bits_headers = \
- ${bits_srcdir}/algorithmfwd.h \
+ ${bits_srcdir}/algorithmfwd.h \
${bits_srcdir}/alloc_traits.h \
${bits_srcdir}/allocator.h \
${bits_srcdir}/atomic_base.h \
@@ -177,11 +177,11 @@ bits_headers = \
bits_sup_srcdir = ${glibcxx_srcdir}/libsupc++
bits_sup_headers = \
- ${bits_sup_srcdir}/cxxabi_forced.h \
- ${bits_sup_srcdir}/exception_defines.h \
- ${bits_sup_srcdir}/exception_ptr.h \
- ${bits_sup_srcdir}/hash_bytes.h \
- ${bits_sup_srcdir}/nested_exception.h
+ ${bits_sup_srcdir}/cxxabi_forced.h \
+ ${bits_sup_srcdir}/exception_defines.h \
+ ${bits_sup_srcdir}/exception_ptr.h \
+ ${bits_sup_srcdir}/hash_bytes.h \
+ ${bits_sup_srcdir}/nested_exception.h
backward_srcdir = ${glibcxx_srcdir}/include/backward
backward_builddir = ./backward
@@ -267,7 +267,7 @@ pb_headers1 = \
${pb_srcdir}/detail/binomial_heap_/binomial_heap_.hpp \
${pb_srcdir}/detail/binomial_heap_/constructors_destructor_fn_imps.hpp \
${pb_srcdir}/detail/binomial_heap_/debug_fn_imps.hpp \
- ${pb_srcdir}/detail/bin_search_tree_/bin_search_tree_.hpp
+ ${pb_srcdir}/detail/bin_search_tree_/bin_search_tree_.hpp
pb_headers2 = \
${pb_srcdir}/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp \
@@ -602,6 +602,15 @@ tr1_headers = \
${tr1_srcdir}/wchar.h \
${tr1_srcdir}/wctype.h
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+ ${tr2_srcdir}/bool_set \
+ ${tr2_srcdir}/bool_set.tcc \
+ ${tr2_srcdir}/dynamic_bitset \
+ ${tr2_srcdir}/ratio \
+ ${tr2_srcdir}/type_traits
+
decimal_srcdir = ${glibcxx_srcdir}/include/decimal
decimal_builddir = ./decimal
decimal_headers = \
@@ -718,49 +727,49 @@ parallel_srcdir = ${glibcxx_srcdir}/include/parallel
parallel_builddir = ./parallel
if ENABLE_PARALLEL
parallel_headers = \
- ${parallel_srcdir}/algo.h \
- ${parallel_srcdir}/algobase.h \
- ${parallel_srcdir}/algorithm \
- ${parallel_srcdir}/algorithmfwd.h \
- ${parallel_srcdir}/balanced_quicksort.h \
- ${parallel_srcdir}/base.h \
- ${parallel_srcdir}/basic_iterator.h \
- ${parallel_srcdir}/checkers.h \
- ${parallel_srcdir}/compatibility.h \
- ${parallel_srcdir}/compiletime_settings.h \
- ${parallel_srcdir}/equally_split.h \
- ${parallel_srcdir}/features.h \
- ${parallel_srcdir}/find.h \
- ${parallel_srcdir}/find_selectors.h \
- ${parallel_srcdir}/for_each.h \
- ${parallel_srcdir}/for_each_selectors.h \
- ${parallel_srcdir}/iterator.h \
- ${parallel_srcdir}/list_partition.h \
- ${parallel_srcdir}/losertree.h \
- ${parallel_srcdir}/merge.h \
- ${parallel_srcdir}/multiseq_selection.h \
- ${parallel_srcdir}/multiway_merge.h \
- ${parallel_srcdir}/multiway_mergesort.h \
- ${parallel_srcdir}/numeric \
- ${parallel_srcdir}/numericfwd.h \
- ${parallel_srcdir}/omp_loop.h \
- ${parallel_srcdir}/omp_loop_static.h \
- ${parallel_srcdir}/par_loop.h \
- ${parallel_srcdir}/parallel.h \
- ${parallel_srcdir}/partial_sum.h \
- ${parallel_srcdir}/partition.h \
- ${parallel_srcdir}/queue.h \
- ${parallel_srcdir}/quicksort.h \
- ${parallel_srcdir}/random_number.h \
- ${parallel_srcdir}/random_shuffle.h \
- ${parallel_srcdir}/search.h \
- ${parallel_srcdir}/set_operations.h \
- ${parallel_srcdir}/settings.h \
- ${parallel_srcdir}/sort.h \
- ${parallel_srcdir}/tags.h \
- ${parallel_srcdir}/types.h \
- ${parallel_srcdir}/unique_copy.h \
- ${parallel_srcdir}/workstealing.h
+ ${parallel_srcdir}/algo.h \
+ ${parallel_srcdir}/algobase.h \
+ ${parallel_srcdir}/algorithm \
+ ${parallel_srcdir}/algorithmfwd.h \
+ ${parallel_srcdir}/balanced_quicksort.h \
+ ${parallel_srcdir}/base.h \
+ ${parallel_srcdir}/basic_iterator.h \
+ ${parallel_srcdir}/checkers.h \
+ ${parallel_srcdir}/compatibility.h \
+ ${parallel_srcdir}/compiletime_settings.h \
+ ${parallel_srcdir}/equally_split.h \
+ ${parallel_srcdir}/features.h \
+ ${parallel_srcdir}/find.h \
+ ${parallel_srcdir}/find_selectors.h \
+ ${parallel_srcdir}/for_each.h \
+ ${parallel_srcdir}/for_each_selectors.h \
+ ${parallel_srcdir}/iterator.h \
+ ${parallel_srcdir}/list_partition.h \
+ ${parallel_srcdir}/losertree.h \
+ ${parallel_srcdir}/merge.h \
+ ${parallel_srcdir}/multiseq_selection.h \
+ ${parallel_srcdir}/multiway_merge.h \
+ ${parallel_srcdir}/multiway_mergesort.h \
+ ${parallel_srcdir}/numeric \
+ ${parallel_srcdir}/numericfwd.h \
+ ${parallel_srcdir}/omp_loop.h \
+ ${parallel_srcdir}/omp_loop_static.h \
+ ${parallel_srcdir}/par_loop.h \
+ ${parallel_srcdir}/parallel.h \
+ ${parallel_srcdir}/partial_sum.h \
+ ${parallel_srcdir}/partition.h \
+ ${parallel_srcdir}/queue.h \
+ ${parallel_srcdir}/quicksort.h \
+ ${parallel_srcdir}/random_number.h \
+ ${parallel_srcdir}/random_shuffle.h \
+ ${parallel_srcdir}/search.h \
+ ${parallel_srcdir}/set_operations.h \
+ ${parallel_srcdir}/settings.h \
+ ${parallel_srcdir}/sort.h \
+ ${parallel_srcdir}/tags.h \
+ ${parallel_srcdir}/types.h \
+ ${parallel_srcdir}/unique_copy.h \
+ ${parallel_srcdir}/workstealing.h
else
parallel_headers =
endif
@@ -844,7 +853,6 @@ thread_host_headers = \
${host_builddir}/gthr.h \
${host_builddir}/gthr-single.h \
${host_builddir}/gthr-posix.h \
- ${host_builddir}/gthr-tpf.h \
${host_builddir}/gthr-default.h
@@ -885,9 +893,9 @@ endif
# CLEANFILES and all-local are kept up-to-date.
allstamped = \
stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
- stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+ stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
- stamp-host
+ stamp-host
# List of all files that are created by explicit building, editing, or
# catenation.
@@ -1000,6 +1008,11 @@ stamp-tr1: ${tr1_headers}
@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
@$(STAMP) stamp-tr1
+stamp-tr2: ${tr2_headers}
+ @-mkdir -p ${tr2_builddir}
+ @-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+ @$(STAMP) stamp-tr2
+
stamp-decimal: ${decimal_headers}
@-mkdir -p ${decimal_builddir}
@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1092,7 +1105,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e "s,define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY, define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY $$visibility," \
-e "s,define _GLIBCXX_EXTERN_TEMPLATE, define _GLIBCXX_EXTERN_TEMPLATE $$externtemplate," \
-e "$$ldbl_compat" \
- < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
+ < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
-e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
-e 's/VERSION/_GLIBCXX_VERSION/g' \
@@ -1106,43 +1119,35 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
# Host includes for threads
uppercase = [ABCDEFGHIJKLMNOPQRSTUVWXYZ_]
-${host_builddir}/gthr.h: ${toplevel_srcdir}/gcc/gthr.h stamp-${host_alias}
+${host_builddir}/gthr.h: ${toplevel_srcdir}/libgcc/gthr.h stamp-${host_alias}
sed -e '/^#pragma/b' \
-e '/^#/s/\(${uppercase}${uppercase}*\)/_GLIBCXX_\1/g' \
-e 's/_GLIBCXX_SUPPORTS_WEAK/__GXX_WEAK__/g' \
-e 's,^#include "\(.*\)",#include <bits/\1>,g' \
- < ${toplevel_srcdir}/gcc/gthr.h > $@
+ < $< > $@
-${host_builddir}/gthr-single.h: ${toplevel_srcdir}/gcc/gthr-single.h \
+${host_builddir}/gthr-single.h: ${toplevel_srcdir}/libgcc/gthr-single.h \
stamp-${host_alias}
sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \
-e 's/\(GCC${uppercase}*_H\)/_GLIBCXX_\1/g' \
- < ${toplevel_srcdir}/gcc/gthr-single.h > $@
+ < $< > $@
-${host_builddir}/gthr-posix.h: ${toplevel_srcdir}/gcc/gthr-posix.h \
+${host_builddir}/gthr-posix.h: ${toplevel_srcdir}/libgcc/config/gthr-posix.h \
stamp-${host_alias}
sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \
-e 's/\(GCC${uppercase}*_H\)/_GLIBCXX_\1/g' \
-e 's/SUPPORTS_WEAK/__GXX_WEAK__/g' \
-e 's/\(${uppercase}*USE_WEAK\)/_GLIBCXX_\1/g' \
- < ${toplevel_srcdir}/gcc/gthr-posix.h > $@
+ < $< > $@
-${host_builddir}/gthr-tpf.h: ${toplevel_srcdir}/gcc/gthr-tpf.h \
- stamp-${host_alias}
- sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \
- -e 's/\(GCC${uppercase}*_H\)/_GLIBCXX_\1/g' \
- -e 's/SUPPORTS_WEAK/__GXX_WEAK__/g' \
- -e 's/\(${uppercase}*USE_WEAK\)/_GLIBCXX_\1/g' \
- < ${toplevel_srcdir}/gcc/gthr-tpf.h > $@
-
-${host_builddir}/gthr-default.h: ${toplevel_srcdir}/gcc/${glibcxx_thread_h} \
+${host_builddir}/gthr-default.h: ${toplevel_builddir}/libgcc/gthr-default.h \
stamp-${host_alias}
sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \
-e 's/\(GCC${uppercase}*_H\)/_GLIBCXX_\1/g' \
-e 's/SUPPORTS_WEAK/__GXX_WEAK__/g' \
-e 's/\(${uppercase}*USE_WEAK\)/_GLIBCXX_\1/g' \
-e 's,^#include "\(.*\)",#include <bits/\1>,g' \
- < ${toplevel_srcdir}/gcc/${glibcxx_thread_h} > $@
+ < $< > $@
# Build two precompiled C++ includes, stdc++.h.gch/*.gch
${pch1a_output}: ${allstamped} ${host_builddir}/c++config.h ${pch1_source}
@@ -1185,8 +1190,10 @@ endif
# are installed by libsupc++, so only the first four and the sub-includes
# are copied here.
install-freestanding-headers:
- $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}
+ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/bits
$(mkinstalldirs) $(DESTDIR)${host_installdir}
+ $(INSTALL_DATA) ${glibcxx_srcdir}/include/bits/c++0x_warning.h \
+ $(DESTDIR)${gxx_include_dir}/bits
for file in ${host_srcdir}/os_defines.h ${host_builddir}/c++config.h \
${glibcxx_srcdir}/$(ABI_TWEAKS_SRCDIR)/cxxabi_tweaks.h \
${glibcxx_srcdir}/$(CPU_DEFINES_SRCDIR)/cpu_defines.h; do \
@@ -1243,6 +1250,9 @@ install-headers:
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
for file in ${tr1_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+ for file in ${tr2_headers}; do \
+ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
for file in ${decimal_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1289,7 +1299,7 @@ clean-local:
# developer tries to create them via make in the include build
# directory. (This is more of an example of how this kind of rule can
# be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
$(decimal_headers) $(ext_headers)
$(std_headers): ; @:
$(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index b05c85157ce..3b31e8a2c5d 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -213,7 +213,6 @@ glibcxx_builddir = @glibcxx_builddir@
glibcxx_localedir = @glibcxx_localedir@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
-glibcxx_thread_h = @glibcxx_thread_h@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@
gxx_include_dir = @gxx_include_dir@
@@ -253,6 +252,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
# May be used by various substitution variables.
@@ -331,7 +331,7 @@ std_headers = \
bits_srcdir = ${glibcxx_srcdir}/include/bits
bits_builddir = ./bits
bits_headers = \
- ${bits_srcdir}/algorithmfwd.h \
+ ${bits_srcdir}/algorithmfwd.h \
${bits_srcdir}/alloc_traits.h \
${bits_srcdir}/allocator.h \
${bits_srcdir}/atomic_base.h \
@@ -429,11 +429,11 @@ bits_headers = \
bits_sup_srcdir = ${glibcxx_srcdir}/libsupc++
bits_sup_headers = \
- ${bits_sup_srcdir}/cxxabi_forced.h \
- ${bits_sup_srcdir}/exception_defines.h \
- ${bits_sup_srcdir}/exception_ptr.h \
- ${bits_sup_srcdir}/hash_bytes.h \
- ${bits_sup_srcdir}/nested_exception.h
+ ${bits_sup_srcdir}/cxxabi_forced.h \
+ ${bits_sup_srcdir}/exception_defines.h \
+ ${bits_sup_srcdir}/exception_ptr.h \
+ ${bits_sup_srcdir}/hash_bytes.h \
+ ${bits_sup_srcdir}/nested_exception.h
backward_srcdir = ${glibcxx_srcdir}/include/backward
backward_builddir = ./backward
@@ -518,7 +518,7 @@ pb_headers1 = \
${pb_srcdir}/detail/binomial_heap_/binomial_heap_.hpp \
${pb_srcdir}/detail/binomial_heap_/constructors_destructor_fn_imps.hpp \
${pb_srcdir}/detail/binomial_heap_/debug_fn_imps.hpp \
- ${pb_srcdir}/detail/bin_search_tree_/bin_search_tree_.hpp
+ ${pb_srcdir}/detail/bin_search_tree_/bin_search_tree_.hpp
pb_headers2 = \
${pb_srcdir}/detail/bin_search_tree_/constructors_destructor_fn_imps.hpp \
@@ -852,6 +852,15 @@ tr1_headers = \
${tr1_srcdir}/wchar.h \
${tr1_srcdir}/wctype.h
+tr2_srcdir = ${glibcxx_srcdir}/include/tr2
+tr2_builddir = ./tr2
+tr2_headers = \
+ ${tr2_srcdir}/bool_set \
+ ${tr2_srcdir}/bool_set.tcc \
+ ${tr2_srcdir}/dynamic_bitset \
+ ${tr2_srcdir}/ratio \
+ ${tr2_srcdir}/type_traits
+
decimal_srcdir = ${glibcxx_srcdir}/include/decimal
decimal_builddir = ./decimal
decimal_headers = \
@@ -964,49 +973,49 @@ parallel_srcdir = ${glibcxx_srcdir}/include/parallel
parallel_builddir = ./parallel
@ENABLE_PARALLEL_FALSE@parallel_headers =
@ENABLE_PARALLEL_TRUE@parallel_headers = \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algo.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algobase.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algorithm \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algorithmfwd.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/balanced_quicksort.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/base.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/basic_iterator.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/checkers.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/compatibility.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/compiletime_settings.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/equally_split.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/features.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/find.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/find_selectors.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/for_each.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/for_each_selectors.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/iterator.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/list_partition.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/losertree.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/merge.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiseq_selection.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiway_merge.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiway_mergesort.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/numeric \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/numericfwd.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/omp_loop.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/omp_loop_static.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/par_loop.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/parallel.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/partial_sum.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/partition.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/queue.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/quicksort.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/random_number.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/random_shuffle.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/search.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/set_operations.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/settings.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/sort.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/tags.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/types.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/unique_copy.h \
-@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/workstealing.h
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algo.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algobase.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algorithm \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/algorithmfwd.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/balanced_quicksort.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/base.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/basic_iterator.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/checkers.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/compatibility.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/compiletime_settings.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/equally_split.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/features.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/find.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/find_selectors.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/for_each.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/for_each_selectors.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/iterator.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/list_partition.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/losertree.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/merge.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiseq_selection.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiway_merge.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/multiway_mergesort.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/numeric \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/numericfwd.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/omp_loop.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/omp_loop_static.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/par_loop.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/parallel.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/partial_sum.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/partition.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/queue.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/quicksort.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/random_number.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/random_shuffle.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/search.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/set_operations.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/settings.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/sort.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/tags.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/types.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/unique_copy.h \
+@ENABLE_PARALLEL_TRUE@ ${parallel_srcdir}/workstealing.h
# Profile mode headers
@@ -1088,7 +1097,6 @@ thread_host_headers = \
${host_builddir}/gthr.h \
${host_builddir}/gthr-single.h \
${host_builddir}/gthr-posix.h \
- ${host_builddir}/gthr-tpf.h \
${host_builddir}/gthr-default.h
pch1_source = ${glibcxx_srcdir}/include/precompiled/stdc++.h
@@ -1123,9 +1131,9 @@ PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS)
# CLEANFILES and all-local are kept up-to-date.
allstamped = \
stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
- stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-decimal \
+ stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
- stamp-host
+ stamp-host
# List of all files that are created by explicit building, editing, or
@@ -1400,6 +1408,11 @@ stamp-tr1: ${tr1_headers}
@-cd ${tr1_builddir} && $(LN_S) $? . 2>/dev/null
@$(STAMP) stamp-tr1
+stamp-tr2: ${tr2_headers}
+ @-mkdir -p ${tr2_builddir}
+ @-cd ${tr2_builddir} && $(LN_S) $? . 2>/dev/null
+ @$(STAMP) stamp-tr2
+
stamp-decimal: ${decimal_headers}
@-mkdir -p ${decimal_builddir}
@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1483,7 +1496,7 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
-e "s,define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY, define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY $$visibility," \
-e "s,define _GLIBCXX_EXTERN_TEMPLATE, define _GLIBCXX_EXTERN_TEMPLATE $$externtemplate," \
-e "$$ldbl_compat" \
- < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
+ < ${glibcxx_srcdir}/include/bits/c++config > $@ ;\
sed -e 's/HAVE_/_GLIBCXX_HAVE_/g' \
-e 's/PACKAGE/_GLIBCXX_PACKAGE/g' \
-e 's/VERSION/_GLIBCXX_VERSION/g' \
@@ -1494,43 +1507,35 @@ ${host_builddir}/c++config.h: ${CONFIG_HEADER} \
echo "" >> $@ ;\
echo "#endif // _GLIBCXX_CXX_CONFIG_H" >> $@
-${host_builddir}/gthr.h: ${toplevel_srcdir}/gcc/gthr.h stamp-${host_alias}
+${host_builddir}/gthr.h: ${toplevel_srcdir}/libgcc/gthr.h stamp-${host_alias}
sed -e '/^#pragma/b' \
-e '/^#/s/\(${uppercase}${uppercase}*\)/_GLIBCXX_\1/g' \
-e 's/_GLIBCXX_SUPPORTS_WEAK/__GXX_WEAK__/g' \
-e 's,^#include "\(.*\)",#include <bits/\1>,g' \
- < ${toplevel_srcdir}/gcc/gthr.h > $@
+ < $< > $@
-${host_builddir}/gthr-single.h: ${toplevel_srcdir}/gcc/gthr-single.h \
+${host_builddir}/gthr-single.h: ${toplevel_srcdir}/libgcc/gthr-single.h \
stamp-${host_alias}
sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \
-e 's/\(GCC${uppercase}*_H\)/_GLIBCXX_\1/g' \
- < ${toplevel_srcdir}/gcc/gthr-single.h > $@
+ < $< > $@
-${host_builddir}/gthr-posix.h: ${toplevel_srcdir}/gcc/gthr-posix.h \
+${host_builddir}/gthr-posix.h: ${toplevel_srcdir}/libgcc/config/gthr-posix.h \
stamp-${host_alias}
sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \
-e 's/\(GCC${uppercase}*_H\)/_GLIBCXX_\1/g' \
-e 's/SUPPORTS_WEAK/__GXX_WEAK__/g' \
-e 's/\(${uppercase}*USE_WEAK\)/_GLIBCXX_\1/g' \
- < ${toplevel_srcdir}/gcc/gthr-posix.h > $@
+ < $< > $@
-${host_builddir}/gthr-tpf.h: ${toplevel_srcdir}/gcc/gthr-tpf.h \
- stamp-${host_alias}
- sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \
- -e 's/\(GCC${uppercase}*_H\)/_GLIBCXX_\1/g' \
- -e 's/SUPPORTS_WEAK/__GXX_WEAK__/g' \
- -e 's/\(${uppercase}*USE_WEAK\)/_GLIBCXX_\1/g' \
- < ${toplevel_srcdir}/gcc/gthr-tpf.h > $@
-
-${host_builddir}/gthr-default.h: ${toplevel_srcdir}/gcc/${glibcxx_thread_h} \
+${host_builddir}/gthr-default.h: ${toplevel_builddir}/libgcc/gthr-default.h \
stamp-${host_alias}
sed -e 's/\(UNUSED\)/_GLIBCXX_\1/g' \
-e 's/\(GCC${uppercase}*_H\)/_GLIBCXX_\1/g' \
-e 's/SUPPORTS_WEAK/__GXX_WEAK__/g' \
-e 's/\(${uppercase}*USE_WEAK\)/_GLIBCXX_\1/g' \
-e 's,^#include "\(.*\)",#include <bits/\1>,g' \
- < ${toplevel_srcdir}/gcc/${glibcxx_thread_h} > $@
+ < $< > $@
# Build two precompiled C++ includes, stdc++.h.gch/*.gch
${pch1a_output}: ${allstamped} ${host_builddir}/c++config.h ${pch1_source}
@@ -1570,8 +1575,10 @@ ${pch3_output}: ${pch3_source} ${pch2_output}
# are installed by libsupc++, so only the first four and the sub-includes
# are copied here.
install-freestanding-headers:
- $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}
+ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/bits
$(mkinstalldirs) $(DESTDIR)${host_installdir}
+ $(INSTALL_DATA) ${glibcxx_srcdir}/include/bits/c++0x_warning.h \
+ $(DESTDIR)${gxx_include_dir}/bits
for file in ${host_srcdir}/os_defines.h ${host_builddir}/c++config.h \
${glibcxx_srcdir}/$(ABI_TWEAKS_SRCDIR)/cxxabi_tweaks.h \
${glibcxx_srcdir}/$(CPU_DEFINES_SRCDIR)/cpu_defines.h; do \
@@ -1628,6 +1635,9 @@ install-headers:
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr1_builddir}
for file in ${tr1_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr1_builddir}; done
+ $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${tr2_builddir}
+ for file in ${tr2_headers}; do \
+ $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${tr2_builddir}; done
$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
for file in ${decimal_headers}; do \
$(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
@@ -1671,7 +1681,7 @@ clean-local:
# developer tries to create them via make in the include build
# directory. (This is more of an example of how this kind of rule can
# be made.)
-.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers)
+.PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
$(decimal_headers) $(ext_headers)
$(std_headers): ; @:
$(c_base_headers): ; @:
diff --git a/libstdc++-v3/include/bits/algorithmfwd.h b/libstdc++-v3/include/bits/algorithmfwd.h
index cc0b98ed7d2..fbec55d0c36 100644
--- a/libstdc++-v3/include/bits/algorithmfwd.h
+++ b/libstdc++-v3/include/bits/algorithmfwd.h
@@ -35,7 +35,9 @@
#include <bits/c++config.h>
#include <bits/stl_pair.h>
#include <bits/stl_iterator_base_types.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 55513ea910f..0edb8b2f8df 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -40,7 +40,9 @@
#include <ext/atomicity.h>
#include <debug/debug.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -201,7 +203,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_set_length_and_sharable(size_type __n)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
{
@@ -231,7 +233,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_dispose(const _Alloc& __a)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
{
@@ -252,7 +254,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_CharT*
_M_refcopy() throw()
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__builtin_expect(this != &_S_empty_rep(), false))
#endif
__gnu_cxx::__atomic_add_dispatch(&this->_M_refcount, 1);
@@ -430,7 +432,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @brief Default constructor creates an empty string.
*/
basic_string()
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
: _M_dataplus(_S_empty_rep()._M_refdata(), _Alloc()) { }
#else
: _M_dataplus(_S_construct(size_type(), _CharT(), _Alloc()), _Alloc()){ }
@@ -502,7 +504,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string(basic_string&& __str) noexcept
: _M_dataplus(__str._M_dataplus)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
__str._M_data(_S_empty_rep()._M_refdata());
#else
__str._M_data(_S_construct(size_type(), _CharT(), get_allocator()));
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc
index 056e2657390..7eff81819f6 100644
--- a/libstdc++-v3/include/bits/basic_string.tcc
+++ b/libstdc++-v3/include/bits/basic_string.tcc
@@ -80,7 +80,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
input_iterator_tag)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
@@ -126,7 +126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
forward_iterator_tag)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__beg == __end && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
@@ -154,7 +154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string<_CharT, _Traits, _Alloc>::
_S_construct(size_type __n, _CharT __c, const _Alloc& __a)
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (__n == 0 && __a == _Alloc())
return _S_empty_rep()._M_refdata();
#endif
@@ -456,7 +456,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
basic_string<_CharT, _Traits, _Alloc>::
_M_leak_hard()
{
-#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
if (_M_rep() == &_S_empty_rep())
return;
#endif
diff --git a/libstdc++-v3/include/bits/c++0x_warning.h b/libstdc++-v3/include/bits/c++0x_warning.h
index 0685a50e6e3..eb072d00a45 100644
--- a/libstdc++-v3/include/bits/c++0x_warning.h
+++ b/libstdc++-v3/include/bits/c++0x_warning.h
@@ -29,9 +29,9 @@
#define _CXX0X_WARNING_H 1
#ifndef __GXX_EXPERIMENTAL_CXX0X__
-#error This file requires compiler and library support for the upcoming \
-ISO C++ standard, C++0x. This support is currently experimental, and must be \
-enabled with the -std=c++0x or -std=gnu++0x compiler options.
+#error This file requires compiler and library support for the \
+ISO C++ 2011 standard. This support is currently experimental, and must be \
+enabled with the -std=c++11 or -std=gnu++11 compiler options.
#endif
#endif
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 8c61de311d4..e76e7423021 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -103,9 +103,11 @@
# ifdef __GXX_EXPERIMENTAL_CXX0X__
# define _GLIBCXX_NOEXCEPT noexcept
# define _GLIBCXX_USE_NOEXCEPT noexcept
+# define _GLIBCXX_THROW(_EXC)
# else
# define _GLIBCXX_NOEXCEPT
# define _GLIBCXX_USE_NOEXCEPT throw()
+# define _GLIBCXX_THROW(_EXC) throw(_EXC)
# endif
#endif
@@ -146,6 +148,8 @@
namespace __detail { }
}
+ namespace tr2 { }
+
namespace decimal { }
namespace chrono { }
@@ -195,6 +199,9 @@ namespace std
namespace __detail { inline namespace __7 { } }
}
+ namespace tr2
+ { inline namespace __7 { } }
+
namespace decimal { inline namespace __7 { } }
namespace chrono { inline namespace __7 { } }
diff --git a/libstdc++-v3/include/bits/codecvt.h b/libstdc++-v3/include/bits/codecvt.h
index 2570f4c6104..f485c170dea 100644
--- a/libstdc++-v3/include/bits/codecvt.h
+++ b/libstdc++-v3/include/bits/codecvt.h
@@ -292,7 +292,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit
codecvt(size_t __refs = 0)
- : __codecvt_abstract_base<_InternT, _ExternT, _StateT> (__refs) { }
+ : __codecvt_abstract_base<_InternT, _ExternT, _StateT> (__refs),
+ _M_c_locale_codecvt(0)
+ { }
explicit
codecvt(__c_locale __cloc, size_t __refs = 0);
diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index c80ee508757..0fc8323767b 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -33,7 +33,9 @@
#pragma GCC system_header
#include <memory>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index 7c66d633863..d109224d1bf 100644
--- a/libstdc++-v3/include/bits/random.h
+++ b/libstdc++-v3/include/bits/random.h
@@ -491,7 +491,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const mersenne_twister_engine& __lhs,
const mersenne_twister_engine& __rhs)
- { return std::equal(__lhs._M_x, __lhs._M_x + state_size, __rhs._M_x); }
+ { return (std::equal(__lhs._M_x, __lhs._M_x + state_size, __rhs._M_x)
+ && __lhs._M_p == __rhs._M_p); }
/**
* @brief Inserts the current state of a % mersenne_twister_engine
@@ -705,7 +706,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const subtract_with_carry_engine& __lhs,
const subtract_with_carry_engine& __rhs)
- { return std::equal(__lhs._M_x, __lhs._M_x + long_lag, __rhs._M_x); }
+ { return (std::equal(__lhs._M_x, __lhs._M_x + long_lag, __rhs._M_x)
+ && __lhs._M_carry == __rhs._M_carry
+ && __lhs._M_p == __rhs._M_p); }
/**
* @brief Inserts the current state of a % subtract_with_carry_engine
@@ -1370,7 +1373,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend bool
operator==(const shuffle_order_engine& __lhs,
const shuffle_order_engine& __rhs)
- { return __lhs._M_b == __rhs._M_b; }
+ { return (__lhs._M_b == __rhs._M_b
+ && std::equal(__lhs._M_v, __lhs._M_v + __k, __rhs._M_v)
+ && __lhs._M_y == __rhs._M_y); }
/**
* @brief Inserts the current state of a %shuffle_order_engine random
diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc
index 0e74848ff3c..8936a62316a 100644
--- a/libstdc++-v3/include/bits/random.tcc
+++ b/libstdc++-v3/include/bits/random.tcc
@@ -471,9 +471,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__os.flags(__ios_base::dec | __ios_base::fixed | __ios_base::left);
__os.fill(__space);
- for (size_t __i = 0; __i < __n - 1; ++__i)
+ for (size_t __i = 0; __i < __n; ++__i)
__os << __x._M_x[__i] << __space;
- __os << __x._M_x[__n - 1];
+ __os << __x._M_p;
__os.flags(__flags);
__os.fill(__fill);
@@ -498,6 +498,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
for (size_t __i = 0; __i < __n; ++__i)
__is >> __x._M_x[__i];
+ __is >> __x._M_p;
__is.flags(__flags);
return __is;
@@ -627,7 +628,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
for (size_t __i = 0; __i < __r; ++__i)
__os << __x._M_x[__i] << __space;
- __os << __x._M_carry;
+ __os << __x._M_carry << __space << __x._M_p;
__os.flags(__flags);
__os.fill(__fill);
@@ -649,6 +650,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
for (size_t __i = 0; __i < __r; ++__i)
__is >> __x._M_x[__i];
__is >> __x._M_carry;
+ __is >> __x._M_p;
__is.flags(__flags);
return __is;
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index 42acace5b66..32addf95105 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -211,6 +211,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* @param __r A %shared_ptr.
* @post get() == __r.get() && use_count() == __r.use_count()
*/
+ shared_ptr(const shared_ptr&) noexcept = default;
template<typename _Tp1, typename = typename
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
@@ -264,6 +265,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr shared_ptr(nullptr_t __p) noexcept
: __shared_ptr<_Tp>(__p) { }
+ shared_ptr& operator=(const shared_ptr&) noexcept = default;
template<typename _Tp1>
shared_ptr&
operator=(const shared_ptr<_Tp1>& __r) noexcept
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index bddecb0d4c5..8f286400aec 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -57,7 +57,9 @@
#ifndef _STL_BVECTOR_H
#define _STL_BVECTOR_H 1
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index 17ea01a96e9..b9249179356 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -60,7 +60,9 @@
#include <bits/concept_check.h>
#include <bits/stl_iterator_base_types.h>
#include <bits/stl_iterator_base_funcs.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index 56ee2fbfd2e..fc1d8f8c6ea 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -58,7 +58,9 @@
#define _STL_LIST_H 1
#include <bits/concept_check.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h
index 889e52b388a..45824f04079 100644
--- a/libstdc++-v3/include/bits/stl_map.h
+++ b/libstdc++-v3/include/bits/stl_map.h
@@ -59,7 +59,9 @@
#include <bits/functexcept.h>
#include <bits/concept_check.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h
index 6b74558948c..fd5a5a8cffb 100644
--- a/libstdc++-v3/include/bits/stl_multimap.h
+++ b/libstdc++-v3/include/bits/stl_multimap.h
@@ -58,7 +58,9 @@
#define _STL_MULTIMAP_H 1
#include <bits/concept_check.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h
index 8b25a975480..ab467c80dc3 100644
--- a/libstdc++-v3/include/bits/stl_multiset.h
+++ b/libstdc++-v3/include/bits/stl_multiset.h
@@ -58,7 +58,9 @@
#define _STL_MULTISET_H 1
#include <bits/concept_check.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h
index b30966a2292..18fd1176a13 100644
--- a/libstdc++-v3/include/bits/stl_set.h
+++ b/libstdc++-v3/include/bits/stl_set.h
@@ -58,7 +58,9 @@
#define _STL_SET_H 1
#include <bits/concept_check.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 869bcf74489..9b7b698925f 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -60,7 +60,9 @@
#include <bits/stl_iterator_base_funcs.h>
#include <bits/functexcept.h>
#include <bits/concept_check.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/ext/vstring.h b/libstdc++-v3/include/ext/vstring.h
index 8e825e055d0..5720daf3919 100644
--- a/libstdc++-v3/include/ext/vstring.h
+++ b/libstdc++-v3/include/ext/vstring.h
@@ -32,7 +32,10 @@
#pragma GCC system_header
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
+
#include <ext/vstring_util.h>
#include <ext/rc_string_base.h>
#include <ext/sso_string_base.h>
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index 82ac62de61b..d7423433803 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -1686,12 +1686,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::complex<_Tp>
__complex_acosh(const std::complex<_Tp>& __z)
{
- std::complex<_Tp> __t((__z.real() - __z.imag())
- * (__z.real() + __z.imag()) - _Tp(1.0),
- _Tp(2.0) * __z.real() * __z.imag());
- __t = std::sqrt(__t);
-
- return std::log(__t + __z);
+ // Kahan's formula.
+ return _Tp(2.0) * std::log(std::sqrt(_Tp(0.5) * (__z + _Tp(1.0)))
+ + std::sqrt(_Tp(0.5) * (__z - _Tp(1.0))));
}
#if _GLIBCXX_USE_C99_COMPLEX_TR1
diff --git a/libstdc++-v3/include/std/condition_variable b/libstdc++-v3/include/std/condition_variable
index a0a3c08794a..c4e2080165d 100644
--- a/libstdc++-v3/include/std/condition_variable
+++ b/libstdc++-v3/include/std/condition_variable
@@ -60,22 +60,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
typedef chrono::system_clock __clock_t;
typedef __gthread_cond_t __native_type;
+
+#ifdef __GTHREAD_COND_INIT
+ __native_type _M_cond = __GTHREAD_COND_INIT;
+#else
__native_type _M_cond;
+#endif
public:
typedef __native_type* native_handle_type;
- condition_variable() throw ();
- ~condition_variable() throw ();
+ condition_variable() noexcept;
+ ~condition_variable() noexcept;
condition_variable(const condition_variable&) = delete;
condition_variable& operator=(const condition_variable&) = delete;
void
- notify_one();
+ notify_one() noexcept;
void
- notify_all();
+ notify_all() noexcept;
void
wait(unique_lock<mutex>& __lock);
@@ -172,23 +177,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
mutex _M_mutex;
public:
- typedef condition_variable::native_handle_type native_handle_type;
- condition_variable_any() throw ();
- ~condition_variable_any() throw ();
+ condition_variable_any() noexcept;
+ ~condition_variable_any() noexcept;
condition_variable_any(const condition_variable_any&) = delete;
condition_variable_any& operator=(const condition_variable_any&) = delete;
void
- notify_one()
+ notify_one() noexcept
{
lock_guard<mutex> __lock(_M_mutex);
_M_cond.notify_one();
}
void
- notify_all()
+ notify_all() noexcept
{
lock_guard<mutex> __lock(_M_mutex);
_M_cond.notify_all();
@@ -198,10 +202,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
wait(_Lock& __lock)
{
- unique_lock<mutex> __my_lock(_M_mutex);
- __lock.unlock();
- _M_cond.wait(__my_lock);
- __lock.lock();
+ // scoped unlock - unlocks in ctor, re-locks in dtor
+ struct _Unlock {
+ explicit _Unlock(_Lock& __lk) : _M_lock(__lk) { __lk.unlock(); }
+ ~_Unlock() noexcept(false)
+ {
+ if (uncaught_exception())
+ __try { _M_lock.lock(); } __catch(...) { }
+ else
+ _M_lock.lock();
+ }
+ _Lock& _M_lock;
+ };
+
+ unique_lock<mutex> __my_lock(_M_mutex);
+ _Unlock __unlock(__lock);
+ // _M_mutex must be unlocked before re-locking __lock so move
+ // ownership of _M_mutex lock to an object with shorter lifetime.
+ unique_lock<mutex> __my_lock2(std::move(__my_lock));
+ _M_cond.wait(__my_lock2);
}
@@ -249,10 +268,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
wait_for(_Lock& __lock,
const chrono::duration<_Rep, _Period>& __rtime, _Predicate __p)
{ return wait_until(__lock, __clock_t::now() + __rtime, std::move(__p)); }
-
- native_handle_type
- native_handle()
- { return _M_cond.native_handle(); }
};
// @} group condition_variables
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index 497b964833f..cc8779b40b3 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -955,6 +955,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_storage(__future_base::_S_allocate_result<_Res>(__a))
{ }
+ template<typename _Allocator>
+ promise(allocator_arg_t, const _Allocator&, promise&& __rhs)
+ : _M_future(std::move(__rhs._M_future)),
+ _M_storage(std::move(__rhs._M_storage))
+ { }
+
promise(const promise&) = delete;
~promise()
@@ -1047,6 +1053,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_storage(__future_base::_S_allocate_result<_Res&>(__a))
{ }
+ template<typename _Allocator>
+ promise(allocator_arg_t, const _Allocator&, promise&& __rhs)
+ : _M_future(std::move(__rhs._M_future)),
+ _M_storage(std::move(__rhs._M_storage))
+ { }
+
promise(const promise&) = delete;
~promise()
@@ -1122,6 +1134,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_storage(__future_base::_S_allocate_result<void>(__a))
{ }
+ template<typename _Allocator>
+ promise(allocator_arg_t, const _Allocator&, promise&& __rhs)
+ : _M_future(std::move(__rhs._M_future)),
+ _M_storage(std::move(__rhs._M_storage))
+ { }
+
promise(const promise&) = delete;
~promise()
@@ -1270,6 +1288,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return std::forward<_Tp>(__t); }
};
+ template<typename _Task, typename _Fn, bool
+ = is_same<_Task, typename remove_reference<_Fn>::type>::value>
+ struct __is_same_pkgdtask
+ { typedef void __type; };
+
+ template<typename _Task, typename _Fn>
+ struct __is_same_pkgdtask<_Task, _Fn, true>
+ { };
+
/// packaged_task
template<typename _Res, typename... _ArgTypes>
class packaged_task<_Res(_ArgTypes...)>
@@ -1281,13 +1308,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Construction and destruction
packaged_task() noexcept { }
- template<typename _Fn>
+ template<typename _Allocator>
+ explicit
+ packaged_task(allocator_arg_t, const _Allocator& __a) noexcept
+ { }
+
+ template<typename _Fn, typename = typename
+ __is_same_pkgdtask<packaged_task, _Fn>::__type>
explicit
packaged_task(_Fn&& __fn)
: _M_state(std::make_shared<_State_type>(std::forward<_Fn>(__fn)))
{ }
- template<typename _Fn, typename _Allocator>
+ template<typename _Fn, typename _Allocator, typename = typename
+ __is_same_pkgdtask<packaged_task, _Fn>::__type>
explicit
packaged_task(allocator_arg_t, const _Allocator& __a, _Fn&& __fn)
: _M_state(std::allocate_shared<_State_type>(__a,
@@ -1301,13 +1335,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
// No copy
- packaged_task(packaged_task&) = delete;
- packaged_task& operator=(packaged_task&) = delete;
+ packaged_task(const packaged_task&) = delete;
+ packaged_task& operator=(const packaged_task&) = delete;
+
+ template<typename _Allocator>
+ explicit
+ packaged_task(allocator_arg_t, const _Allocator&,
+ const packaged_task&) = delete;
// Move support
packaged_task(packaged_task&& __other) noexcept
{ this->swap(__other); }
+ template<typename _Allocator>
+ explicit
+ packaged_task(allocator_arg_t, const _Allocator&,
+ packaged_task&& __other) noexcept
+ { this->swap(__other); }
+
packaged_task& operator=(packaged_task&& __other) noexcept
{
packaged_task(std::move(__other)).swap(*this);
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index 184011715c7..4d154ff6f0c 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -52,6 +52,94 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ // Common base class for std::mutex and std::timed_mutex
+ class __mutex_base
+ {
+ protected:
+ typedef __gthread_mutex_t __native_type;
+
+#ifdef __GTHREAD_MUTEX_INIT
+ __native_type _M_mutex = __GTHREAD_MUTEX_INIT;
+
+ constexpr __mutex_base() noexcept = default;
+#else
+ __native_type _M_mutex;
+
+ __mutex_base() noexcept
+ {
+ // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
+ __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
+ }
+
+ ~__mutex_base() { __gthread_mutex_destroy(&_M_mutex); }
+#endif
+
+ __mutex_base(const __mutex_base&) = delete;
+ __mutex_base& operator=(const __mutex_base&) = delete;
+ };
+
+ // Common base class for std::recursive_mutex and std::timed_recursive_mutex
+ class __recursive_mutex_base
+ {
+ protected:
+ typedef __gthread_recursive_mutex_t __native_type;
+
+ __recursive_mutex_base(const __recursive_mutex_base&) = delete;
+ __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete;
+
+#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
+ __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT;
+
+ __recursive_mutex_base() = default;
+#else
+ __native_type _M_mutex;
+
+ __recursive_mutex_base()
+ {
+ // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
+ __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
+ }
+
+ ~__recursive_mutex_base()
+ { _S_destroy(&_M_mutex); }
+
+ private:
+ // FIXME: gthreads doesn't define __gthread_recursive_mutex_destroy
+ // so we need to obtain a __gthread_mutex_t to destroy
+
+ // matches when there's only one mutex type
+ template<typename _Rm>
+ static
+ typename enable_if<is_same<_Rm, __gthread_mutex_t>::value, void>::type
+ _S_destroy(_Rm* __mx)
+ { __gthread_mutex_destroy(__mx); }
+
+ // matches a recursive mutex with a member 'actual'
+ template<typename _Rm>
+ static typename enable_if<sizeof(&_Rm::actual), void>::type
+ _S_destroy(_Rm* __mx)
+ { __gthread_mutex_destroy(&__mx->actual); }
+
+ // matches a gthr-win32.h recursive mutex
+ template<typename _Rm>
+ static typename enable_if<sizeof(&_Rm::sema), void>::type
+ _S_destroy(_Rm* __mx)
+ {
+ __gthread_mutex_t __tmp;
+ _S_destroy_win32(&__tmp, __mx);
+ }
+
+ template<typename _Mx, typename _Rm>
+ static void
+ _S_destroy_win32(_Mx* __mx, _Rm const* __rmx)
+ {
+ __mx->counter = __rmx->counter;
+ __mx->sema = __rmx->sema;
+ __gthread_mutex_destroy(__mx);
+ }
+#endif
+ };
+
/**
* @defgroup mutexes Mutexes
* @ingroup concurrency
@@ -61,25 +149,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*/
/// mutex
- class mutex
+ class mutex : private __mutex_base
{
- typedef __gthread_mutex_t __native_type;
- __native_type _M_mutex;
-
public:
typedef __native_type* native_handle_type;
#ifdef __GTHREAD_MUTEX_INIT
- constexpr mutex() noexcept : _M_mutex(__GTHREAD_MUTEX_INIT) { }
-#else
- mutex() noexcept
- {
- // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
- __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
- }
-
- ~mutex() { __gthread_mutex_destroy(&_M_mutex); }
+ constexpr
#endif
+ mutex() noexcept = default;
+ ~mutex() = default;
mutex(const mutex&) = delete;
mutex& operator=(const mutex&) = delete;
@@ -113,66 +192,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return &_M_mutex; }
};
-#ifndef __GTHREAD_RECURSIVE_MUTEX_INIT
- // FIXME: gthreads doesn't define __gthread_recursive_mutex_destroy
- // so we need to obtain a __gthread_mutex_t to destroy
- class __destroy_recursive_mutex
- {
- template<typename _Mx, typename _Rm>
- static void
- _S_destroy_win32(_Mx* __mx, _Rm const* __rmx)
- {
- __mx->counter = __rmx->counter;
- __mx->sema = __rmx->sema;
- __gthread_mutex_destroy(__mx);
- }
-
- public:
- // matches a gthr-win32.h recursive mutex
- template<typename _Rm>
- static typename enable_if<sizeof(&_Rm::sema), void>::type
- _S_destroy(_Rm* __mx)
- {
- __gthread_mutex_t __tmp;
- _S_destroy_win32(&__tmp, __mx);
- }
-
- // matches a recursive mutex with a member 'actual'
- template<typename _Rm>
- static typename enable_if<sizeof(&_Rm::actual), void>::type
- _S_destroy(_Rm* __mx)
- { __gthread_mutex_destroy(&__mx->actual); }
-
- // matches when there's only one mutex type
- template<typename _Rm>
- static
- typename enable_if<is_same<_Rm, __gthread_mutex_t>::value, void>::type
- _S_destroy(_Rm* __mx)
- { __gthread_mutex_destroy(__mx); }
- };
-#endif
-
/// recursive_mutex
- class recursive_mutex
+ class recursive_mutex : private __recursive_mutex_base
{
- typedef __gthread_recursive_mutex_t __native_type;
- __native_type _M_mutex;
-
public:
typedef __native_type* native_handle_type;
-#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
- recursive_mutex() : _M_mutex(__GTHREAD_RECURSIVE_MUTEX_INIT) { }
-#else
- recursive_mutex()
- {
- // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
- __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
- }
-
- ~recursive_mutex()
- { __destroy_recursive_mutex::_S_destroy(&_M_mutex); }
-#endif
+ recursive_mutex() = default;
+ ~recursive_mutex() = default;
recursive_mutex(const recursive_mutex&) = delete;
recursive_mutex& operator=(const recursive_mutex&) = delete;
@@ -206,32 +233,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return &_M_mutex; }
};
+#if _GTHREAD_USE_MUTEX_TIMEDLOCK
/// timed_mutex
- class timed_mutex
+ class timed_mutex : private __mutex_base
{
- typedef __gthread_mutex_t __native_type;
-
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
typedef chrono::steady_clock __clock_t;
#else
typedef chrono::high_resolution_clock __clock_t;
#endif
- __native_type _M_mutex;
-
public:
typedef __native_type* native_handle_type;
-#ifdef __GTHREAD_MUTEX_INIT
- timed_mutex() : _M_mutex(__GTHREAD_MUTEX_INIT) { }
-#else
- timed_mutex()
- {
- __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex);
- }
-
- ~timed_mutex() { __gthread_mutex_destroy(&_M_mutex); }
-#endif
+ timed_mutex() = default;
+ ~timed_mutex() = default;
timed_mutex(const timed_mutex&) = delete;
timed_mutex& operator=(const timed_mutex&) = delete;
@@ -312,33 +328,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
/// recursive_timed_mutex
- class recursive_timed_mutex
+ class recursive_timed_mutex : private __recursive_mutex_base
{
- typedef __gthread_recursive_mutex_t __native_type;
-
#ifdef _GLIBCXX_USE_CLOCK_MONOTONIC
typedef chrono::steady_clock __clock_t;
#else
typedef chrono::high_resolution_clock __clock_t;
#endif
- __native_type _M_mutex;
-
public:
typedef __native_type* native_handle_type;
-#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT
- recursive_timed_mutex() : _M_mutex(__GTHREAD_RECURSIVE_MUTEX_INIT) { }
-#else
- recursive_timed_mutex()
- {
- // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may)
- __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex);
- }
-
- ~recursive_timed_mutex()
- { __destroy_recursive_mutex::_S_destroy(&_M_mutex); }
-#endif
+ recursive_timed_mutex() = default;
+ ~recursive_timed_mutex() = default;
recursive_timed_mutex(const recursive_timed_mutex&) = delete;
recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete;
@@ -417,6 +419,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return try_lock_until(__atime);
}
};
+#endif
/// Do not acquire ownership of the mutex.
struct defer_lock_t { };
diff --git a/libstdc++-v3/include/std/valarray b/libstdc++-v3/include/std/valarray
index 3b155c525d8..a159aab51ae 100644
--- a/libstdc++-v3/include/std/valarray
+++ b/libstdc++-v3/include/std/valarray
@@ -39,7 +39,9 @@
#include <cmath>
#include <algorithm>
#include <debug/debug.h>
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <initializer_list>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
diff --git a/libstdc++-v3/include/tr1/complex b/libstdc++-v3/include/tr1/complex
index fc213b8f1d5..689ea167ba2 100644
--- a/libstdc++-v3/include/tr1/complex
+++ b/libstdc++-v3/include/tr1/complex
@@ -185,12 +185,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::complex<_Tp>
__complex_acosh(const std::complex<_Tp>& __z)
{
- std::complex<_Tp> __t((__z.real() - __z.imag())
- * (__z.real() + __z.imag()) - _Tp(1.0),
- _Tp(2.0) * __z.real() * __z.imag());
- __t = std::sqrt(__t);
-
- return std::log(__t + __z);
+ // Kahan's formula.
+ return _Tp(2.0) * std::log(std::sqrt(_Tp(0.5) * (__z + _Tp(1.0)))
+ + std::sqrt(_Tp(0.5) * (__z - _Tp(1.0))));
}
#if _GLIBCXX_USE_C99_COMPLEX_TR1
diff --git a/libstdc++-v3/include/tr2/bool_set b/libstdc++-v3/include/tr2/bool_set
new file mode 100644
index 00000000000..fe322675991
--- /dev/null
+++ b/libstdc++-v3/include/tr2/bool_set
@@ -0,0 +1,320 @@
+// TR2 <bool_set> -*- C++ -*-
+
+// Copyright (C) 2009, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/bool_set
+ * This is a TR2 C++ Library header.
+ */
+
+//
+// Sort of an implementation of bool_set in n2136 Hervé Brönnimann,
+// Guillaume Melquiond, Sylvain Pion.
+//
+// The implicit conversion to bool is slippery! I may use the new
+// explicit conversion. This has been specialized in the language so
+// that in contexts requiring a bool the conversion happens
+// implicitly. Thus most objections should be eliminated.
+//
+
+#ifndef _GLIBCXX_TR2_BOOL_SET
+#define _GLIBCXX_TR2_BOOL_SET 1
+
+#pragma GCC system_header
+
+#include <typeinfo>
+#include <iostream>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ class bool_set
+ {
+ public:
+
+ /// Default constructor.
+ bool_set() : _M_b(_S_false) { }
+
+ /// Constructor from bool.
+ bool_set(bool __t) : _M_b(_Bool_set_val(__t)) { }
+
+ ///
+ // I'm not sure about this.
+ bool contains(bool_set __b) const
+ { return this->is_singleton() && this->equals(__b); }
+
+ /// Return true if states are equal.
+ bool equals(bool_set __b) const
+ { return __b._M_b == _M_b; }
+
+ /// Return true if this is empty.
+ bool is_emptyset() const
+ { return _M_b == _S_empty; }
+
+ /// Return true if this is indeterminate.
+ bool is_indeterminate() const
+ { return _M_b == _S_indet; }
+
+ /// Return true if this is false or true (normal boolean).
+ bool is_singleton() const
+ { return _M_b == _S_false || _M_b == _S_true_; }
+
+ /// Conversion to bool.
+ //explicit
+ operator bool() const
+ {
+ if (! is_singleton())
+ throw std::bad_cast();
+ return _M_b;
+ }
+
+ ///
+ static bool_set indeterminate()
+ {
+ bool_set __b;
+ __b._M_b = _S_indet;
+ return __b;
+ }
+
+ ///
+ static bool_set emptyset()
+ {
+ bool_set __b;
+ __b._M_b = _S_empty;
+ return __b;
+ }
+
+ friend bool_set
+ operator!(bool_set __b)
+ { return __b._M_not(); }
+
+ friend bool_set
+ operator^(bool_set __s, bool_set __t)
+ { return __s._M_xor(__t); }
+
+ friend bool_set
+ operator|(bool_set __s, bool_set __t)
+ { return __s._M_or(__t); }
+
+ friend bool_set
+ operator&(bool_set __s, bool_set __t)
+ { return __s._M_and(__t); }
+
+ friend bool_set
+ operator==(bool_set __s, bool_set __t)
+ { return __s._M_eq(__t); }
+
+
+ // These overloads replace the facet additions in the paper!
+
+ template<typename CharT, typename Traits>
+ friend std::basic_ostream<CharT, Traits>&
+ operator<<(std::basic_ostream<CharT, Traits>& __out, bool_set __b)
+ {
+ int __a = __b._M_b;
+ __out << __a;
+ }
+
+ template<typename CharT, typename Traits>
+ friend std::basic_istream<CharT, Traits>&
+ operator>>(std::basic_istream<CharT, Traits>& __in, bool_set& __b)
+ {
+ long __c;
+ __in >> __c;
+ if (__c >= _S_false && __c < _S_empty)
+ __b._M_b = static_cast<_Bool_set_val>(__c);
+ }
+
+ private:
+
+ ///
+ enum _Bool_set_val: unsigned char
+ {
+ _S_false = 0,
+ _S_true_ = 1,
+ _S_indet = 2,
+ _S_empty = 3
+ };
+
+ /// Bool set state.
+ _Bool_set_val _M_b;
+
+ ///
+ bool_set(_Bool_set_val __c) : _M_b(__c) { }
+
+ ///
+ bool_set _M_not() const
+ { return _S_not[this->_M_b]; }
+
+ ///
+ bool_set _M_xor(bool_set __b) const
+ { return _S_xor[this->_M_b][__b._M_b]; }
+
+ ///
+ bool_set _M_or(bool_set __b) const
+ { return _S_or[this->_M_b][__b._M_b]; }
+
+ ///
+ bool_set _M_and(bool_set __b) const
+ { return _S_and[this->_M_b][__b._M_b]; }
+
+ ///
+ bool_set _M_eq(bool_set __b) const
+ { return _S_eq[this->_M_b][__b._M_b]; }
+
+ ///
+ static _Bool_set_val _S_not[4];
+
+ ///
+ static _Bool_set_val _S_xor[4][4];
+
+ ///
+ static _Bool_set_val _S_or[4][4];
+
+ ///
+ static _Bool_set_val _S_and[4][4];
+
+ ///
+ static _Bool_set_val _S_eq[4][4];
+ };
+
+ // 20.2.3.2 bool_set values
+
+ inline bool
+ contains(bool_set __s, bool_set __t)
+ { return __s.contains(__t); }
+
+ inline bool
+ equals(bool_set __s, bool_set __t)
+ { return __s.equals(__t); }
+
+ inline bool
+ is_emptyset(bool_set __b)
+ { return __b.is_emptyset(); }
+
+ inline bool
+ is_indeterminate(bool_set __b)
+ { return __b.is_indeterminate(); }
+
+ inline bool
+ is_singleton(bool_set __b)
+ { return __b.is_singleton(); }
+
+ inline bool
+ certainly(bool_set __b)
+ { return ! __b.contains(false); }
+
+ inline bool
+ possibly(bool_set __b)
+ { return __b.contains(true); }
+
+
+ // 20.2.3.3 bool_set set operations
+
+ inline bool_set
+ set_union(bool __s, bool_set __t)
+ { return bool_set(__s) | __t; }
+
+ inline bool_set
+ set_union(bool_set __s, bool __t)
+ { return __s | bool_set(__t); }
+
+ inline bool_set
+ set_union(bool_set __s, bool_set __t)
+ { return __s | __t; }
+
+ inline bool_set
+ set_intersection(bool __s, bool_set __t)
+ { return bool_set(__s) & __t; }
+
+ inline bool_set
+ set_intersection(bool_set __s, bool __t)
+ { return __s & bool_set(__t); }
+
+ inline bool_set
+ set_intersection(bool_set __s, bool_set __t)
+ { return __s & __t; }
+
+ inline bool_set
+ set_complement(bool_set __b)
+ { return ! __b; }
+
+
+ // 20.2.3.4 bool_set logical operators
+
+ inline bool_set
+ operator^(bool __s, bool_set __t)
+ { return bool_set(__s) ^ __t; }
+
+ inline bool_set
+ operator^(bool_set __s, bool __t)
+ { return __s ^ bool_set(__t); }
+
+ inline bool_set
+ operator|(bool __s, bool_set __t)
+ { return bool_set(__s) | __t; }
+
+ inline bool_set
+ operator|(bool_set __s, bool __t)
+ { return __s | bool_set(__t); }
+
+ inline bool_set
+ operator&(bool __s, bool_set __t)
+ { return bool_set(__s) & __t; }
+
+ inline bool_set
+ operator&(bool_set __s, bool __t)
+ { return __s & bool_set(__t); }
+
+
+ // 20.2.3.5 bool_set relational operators
+
+ inline bool_set
+ operator==(bool __s, bool_set __t)
+ { return bool_set(__s) == __t; }
+
+ inline bool_set
+ operator==(bool_set __s, bool __t)
+ { return __s == bool_set(__t); }
+
+ inline bool_set
+ operator!=(bool __s, bool_set __t)
+ { return ! (__s == __t); }
+
+ inline bool_set
+ operator!=(bool_set __s, bool __t)
+ { return ! (__s == __t); }
+
+ inline bool_set
+ operator!=(bool_set __s, bool_set __t)
+ { return ! (__s == __t); }
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#include <tr2/bool_set.tcc>
+
+#endif // _GLIBCXX_TR2_BOOL_SET
diff --git a/libstdc++-v3/include/tr2/bool_set.tcc b/libstdc++-v3/include/tr2/bool_set.tcc
new file mode 100644
index 00000000000..f24d4482398
--- /dev/null
+++ b/libstdc++-v3/include/tr2/bool_set.tcc
@@ -0,0 +1,277 @@
+// TR2 <bool_set> support files -*- C++ -*-
+
+// Copyright (C) 2009, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/bool_set.tcc
+ * This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_BOOL_SET_TCC
+#define _GLIBCXX_TR2_BOOL_SET_TCC 1
+
+#pragma GCC system_header
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ bool_set::_Bool_set_val
+ bool_set::_S_not[4] =
+ { _S_true_, _S_false, _S_indet, _S_empty };
+
+ bool_set::_Bool_set_val
+ bool_set::_S_xor[4][4] =
+ { { _S_false, _S_true_, _S_indet, _S_empty },
+ { _S_true_, _S_false, _S_indet, _S_empty },
+ { _S_indet, _S_indet, _S_indet, _S_empty },
+ { _S_empty, _S_empty, _S_empty, _S_empty } };
+
+ bool_set::_Bool_set_val
+ bool_set::_S_or[4][4] =
+ { { _S_false, _S_true_, _S_indet, _S_empty },
+ { _S_true_, _S_true_, _S_true_, _S_empty },
+ { _S_indet, _S_true_, _S_indet, _S_empty },
+ { _S_empty, _S_empty, _S_empty, _S_empty } };
+
+ bool_set::_Bool_set_val
+ bool_set::_S_and[4][4] =
+ { { _S_false, _S_false, _S_false, _S_empty },
+ { _S_false, _S_true_, _S_indet, _S_empty },
+ { _S_false, _S_indet, _S_indet, _S_empty },
+ { _S_empty, _S_empty, _S_empty, _S_empty } };
+
+ bool_set::_Bool_set_val
+ bool_set::_S_eq[4][4] =
+ { { _S_true_, _S_false, _S_indet, _S_empty },
+ { _S_false, _S_true_, _S_indet, _S_empty },
+ { _S_indet, _S_indet, _S_indet, _S_empty },
+ { _S_empty, _S_empty, _S_empty, _S_empty } };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+// I object to these things.
+// The stuff in locale facets are for basic types.
+// I think we could hack operator<< and operator>>.
+
+ /**
+ * @brief Numeric parsing.
+ *
+ * Parses the input stream into the bool @a v. It does so by calling
+ * num_get::do_get().
+ *
+ * If ios_base::boolalpha is set, attempts to read
+ * ctype<CharT>::truename() or ctype<CharT>::falsename(). Sets
+ * @a v to true or false if successful. Sets err to
+ * ios_base::failbit if reading the string fails. Sets err to
+ * ios_base::eofbit if the stream is emptied.
+ *
+ * If ios_base::boolalpha is not set, proceeds as with reading a long,
+ * except if the value is 1, sets @a v to true, if the value is 0, sets
+ * @a v to false, and otherwise set err to ios_base::failbit.
+ *
+ * @param in Start of input stream.
+ * @param end End of input stream.
+ * @param io Source of locale and flags.
+ * @param err Error flags to set.
+ * @param v Value to format and insert.
+ * @return Iterator after reading.
+ iter_type
+ get(iter_type __in, iter_type __end, ios_base& __io,
+ ios_base::iostate& __err, bool& __v) const
+ { return this->do_get(__in, __end, __io, __err, __v); }
+ */
+/*
+ template<typename _CharT, typename _InIter>
+ _InIter
+ num_get<_CharT, _InIter>::
+ do_get(iter_type __beg, iter_type __end, ios_base& __io,
+ ios_base::iostate& __err, bool_set& __v) const
+ {
+ if (!(__io.flags() & ios_base::boolalpha))
+ {
+ // Parse bool values as long.
+ // NB: We can't just call do_get(long) here, as it might
+ // refer to a derived class.
+ long __l = -1;
+ __beg = _M_extract_int(__beg, __end, __io, __err, __l);
+ if (__c >= _S_false && __c < _S_empty)
+ __b._M_b = static_cast<_Bool_set_val>(__c);
+ else
+ {
+ // What should we do here?
+ __v = true;
+ __err = ios_base::failbit;
+ if (__beg == __end)
+ __err |= ios_base::eofbit;
+ }
+ }
+ else
+ {
+ // Parse bool values as alphanumeric.
+ typedef __numpunct_cache<_CharT> __cache_type;
+ __use_cache<__cache_type> __uc;
+ const locale& __loc = __io._M_getloc();
+ const __cache_type* __lc = __uc(__loc);
+
+ bool __testf = true;
+ bool __testt = true;
+ bool __donef = __lc->_M_falsename_size == 0;
+ bool __donet = __lc->_M_truename_size == 0;
+ bool __testeof = false;
+ size_t __n = 0;
+ while (!__donef || !__donet)
+ {
+ if (__beg == __end)
+ {
+ __testeof = true;
+ break;
+ }
+
+ const char_type __c = *__beg;
+
+ if (!__donef)
+ __testf = __c == __lc->_M_falsename[__n];
+
+ if (!__testf && __donet)
+ break;
+
+ if (!__donet)
+ __testt = __c == __lc->_M_truename[__n];
+
+ if (!__testt && __donef)
+ break;
+
+ if (!__testt && !__testf)
+ break;
+
+ ++__n;
+ ++__beg;
+
+ __donef = !__testf || __n >= __lc->_M_falsename_size;
+ __donet = !__testt || __n >= __lc->_M_truename_size;
+ }
+ if (__testf && __n == __lc->_M_falsename_size && __n)
+ {
+ __v = false;
+ if (__testt && __n == __lc->_M_truename_size)
+ __err = ios_base::failbit;
+ else
+ __err = __testeof ? ios_base::eofbit : ios_base::goodbit;
+ }
+ else if (__testt && __n == __lc->_M_truename_size && __n)
+ {
+ __v = true;
+ __err = __testeof ? ios_base::eofbit : ios_base::goodbit;
+ }
+ else
+ {
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 23. Num_get overflow result.
+ __v = false;
+ __err = ios_base::failbit;
+ if (__testeof)
+ __err |= ios_base::eofbit;
+ }
+ }
+ return __beg;
+ }
+*/
+
+ /**
+ * @brief Numeric formatting.
+ *
+ * Formats the boolean @a v and inserts it into a stream. It does so
+ * by calling num_put::do_put().
+ *
+ * If ios_base::boolalpha is set, writes ctype<CharT>::truename() or
+ * ctype<CharT>::falsename(). Otherwise formats @a v as an int.
+ *
+ * @param s Stream to write to.
+ * @param io Source of locale and flags.
+ * @param fill Char_type to use for filling.
+ * @param v Value to format and insert.
+ * @return Iterator after writing.
+ iter_type
+ put(iter_type __s, ios_base& __f, char_type __fill, bool __v) const
+ { return this->do_put(__s, __f, __fill, __v); }
+ */
+
+/*
+ template<typename _CharT, typename _OutIter>
+ _OutIter
+ num_put<_CharT, _OutIter>::
+ do_put(iter_type __s, ios_base& __io, char_type __fill, bool_set __v) const
+ {
+ const ios_base::fmtflags __flags = __io.flags();
+ if ((__flags & ios_base::boolalpha) == 0)
+ {
+ const long __l = __v;
+ __s = _M_insert_int(__s, __io, __fill, __l);
+ }
+ else
+ {
+ typedef __numpunct_cache<_CharT> __cache_type;
+ __use_cache<__cache_type> __uc;
+ const locale& __loc = __io._M_getloc();
+ const __cache_type* __lc = __uc(__loc);
+
+ const _CharT* __name = __v ? __lc->_M_truename
+ : __lc->_M_falsename;
+ int __len = __v ? __lc->_M_truename_size
+ : __lc->_M_falsename_size;
+
+ const streamsize __w = __io.width();
+ if (__w > static_cast<streamsize>(__len))
+ {
+ const streamsize __plen = __w - __len;
+ _CharT* __ps
+ = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
+ * __plen));
+
+ char_traits<_CharT>::assign(__ps, __plen, __fill);
+ __io.width(0);
+
+ if ((__flags & ios_base::adjustfield) == ios_base::left)
+ {
+ __s = std::__write(__s, __name, __len);
+ __s = std::__write(__s, __ps, __plen);
+ }
+ else
+ {
+ __s = std::__write(__s, __ps, __plen);
+ __s = std::__write(__s, __name, __len);
+ }
+ return __s;
+ }
+ __io.width(0);
+ __s = std::__write(__s, __name, __len);
+ }
+ return __s;
+ }
+*/
+
+#endif // _GLIBCXX_TR2_BOOL_SET_TCC
diff --git a/libstdc++-v3/include/tr2/dynamic_bitset b/libstdc++-v3/include/tr2/dynamic_bitset
new file mode 100644
index 00000000000..5a4b7943bbe
--- /dev/null
+++ b/libstdc++-v3/include/tr2/dynamic_bitset
@@ -0,0 +1,1472 @@
+// TR2 <dynamic_bitset> -*- C++ -*-
+
+// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/dynamic_bitset
+ * This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_DYNAMIC_BITSET
+#define _GLIBCXX_TR2_DYNAMIC_BITSET 1
+
+#pragma GCC system_header
+
+#include <limits>
+#include <vector>
+#include <cstddef> // For size_t
+#include <string>
+#include <memory> // For std::allocator
+#include <bits/functexcept.h> // For invalid_argument, out_of_range,
+ // overflow_error
+#include <iosfwd>
+#include <cxxabi_forced.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * Dynamic Bitset.
+ *
+ * See N2050,
+ * Proposal to Add a Dynamically Sizeable Bitset to the Standard Library.
+ */
+namespace __detail
+{
+
+template<typename T>
+class _Bool2UChar
+{
+ typedef T type;
+};
+
+template<>
+class _Bool2UChar<bool>
+{
+public:
+ typedef unsigned char type;
+};
+
+}
+
+ /**
+ * Base class, general case.
+ *
+ * See documentation for dynamic_bitset.
+ */
+ template<typename _WordT = unsigned long long,
+ typename _Alloc = std::allocator<_WordT>>
+ struct __dynamic_bitset_base
+ {
+ static_assert(std::is_unsigned<_WordT>::value, "template argument "
+ "_WordT not an unsigned integral type");
+
+ typedef _WordT block_type;
+ typedef _Alloc allocator_type;
+ typedef size_t size_type;
+
+ static const size_type _S_bits_per_block = __CHAR_BIT__ * sizeof(block_type);
+ static const size_type npos = static_cast<size_type>(-1);
+
+ /// 0 is the least significant word.
+ std::vector<block_type, allocator_type> _M_w;
+
+ explicit
+ __dynamic_bitset_base(const allocator_type& __alloc = allocator_type())
+ : _M_w(__alloc)
+ { }
+
+ explicit
+ __dynamic_bitset_base(__dynamic_bitset_base&& __b)
+ { this->_M_w.swap(__b._M_w); }
+
+ explicit
+ __dynamic_bitset_base(size_type __nbits, unsigned long long __val = 0ULL,
+ const allocator_type& __alloc = allocator_type())
+ : _M_w(__nbits / _S_bits_per_block
+ + (__nbits % _S_bits_per_block > 0),
+ __val, __alloc)
+ {
+ unsigned long long __mask = ~static_cast<block_type>(0);
+ size_t __n = std::min(this->_M_w.size(),
+ sizeof(unsigned long long) / sizeof(block_type));
+ for (size_t __i = 0; __i < __n; ++__i)
+ {
+ this->_M_w[__i] = (__val & __mask) >> (__i * _S_bits_per_block);
+ __mask <<= _S_bits_per_block;
+ }
+ }
+
+ void
+ _M_assign(const __dynamic_bitset_base<block_type, allocator_type>& __b)
+ { this->_M_w = __b._M_w; }
+
+ void
+ _M_swap(__dynamic_bitset_base<block_type, allocator_type>& __b)
+ { this->_M_w.swap(__b._M_w); }
+
+ void
+ _M_clear()
+ { this->_M_w.clear(); }
+
+ void
+ _M_resize(size_t __nbits, bool __value)
+ {
+ size_t __sz = __nbits / _S_bits_per_block;
+ if (__nbits % _S_bits_per_block > 0)
+ ++__sz;
+ if (__sz != this->_M_w.size())
+ this->_M_w.resize(__sz);
+ }
+
+ allocator_type
+ _M_get_allocator() const
+ { return this->_M_w.get_allocator(); }
+
+ static size_type
+ _S_whichword(size_type __pos)
+ { return __pos / _S_bits_per_block; }
+
+ static size_type
+ _S_whichbyte(size_type __pos)
+ { return (__pos % _S_bits_per_block) / __CHAR_BIT__; }
+
+ static size_type
+ _S_whichbit(size_type __pos)
+ { return __pos % _S_bits_per_block; }
+
+ static block_type
+ _S_maskbit(size_type __pos)
+ { return (static_cast<block_type>(1)) << _S_whichbit(__pos); }
+
+ block_type&
+ _M_getword(size_type __pos)
+ { return this->_M_w[_S_whichword(__pos)]; }
+
+ block_type
+ _M_getword(size_type __pos) const
+ { return this->_M_w[_S_whichword(__pos)]; }
+
+ block_type&
+ _M_hiword()
+ { return this->_M_w[_M_w.size() - 1]; }
+
+ block_type
+ _M_hiword() const
+ { return this->_M_w[_M_w.size() - 1]; }
+
+ void
+ _M_do_and(const __dynamic_bitset_base<block_type, allocator_type>& __x)
+ {
+ if (__x._M_w.size() == this->_M_w.size())
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] &= __x._M_w[__i];
+ else
+ return;
+ }
+
+ void
+ _M_do_or(const __dynamic_bitset_base<block_type, allocator_type>& __x)
+ {
+ if (__x._M_w.size() == this->_M_w.size())
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] |= __x._M_w[__i];
+ else
+ return;
+ }
+
+ void
+ _M_do_xor(const __dynamic_bitset_base<block_type, allocator_type>& __x)
+ {
+ if (__x._M_w.size() == this->_M_w.size())
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] ^= __x._M_w[__i];
+ else
+ return;
+ }
+
+ void
+ _M_do_dif(const __dynamic_bitset_base<block_type, allocator_type>& __x)
+ {
+ if (__x._M_w.size() == this->_M_w.size())
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] &= ~__x._M_w[__i];
+ else
+ return;
+ }
+
+ void
+ _M_do_left_shift(size_t __shift);
+
+ void
+ _M_do_right_shift(size_t __shift);
+
+ void
+ _M_do_flip()
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] = ~this->_M_w[__i];
+ }
+
+ void
+ _M_do_set()
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] = ~static_cast<block_type>(0);
+ }
+
+ void
+ _M_do_reset()
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ this->_M_w[__i] = static_cast<block_type>(0);
+ }
+
+ bool
+ _M_is_equal(const __dynamic_bitset_base<block_type, allocator_type>& __x) const
+ {
+ if (__x.size() == this->size())
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i] != __x._M_w[__i])
+ return false;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ bool
+ _M_is_less(const __dynamic_bitset_base<block_type, allocator_type>& __x) const
+ {
+ if (__x.size() == this->size())
+ {
+ for (size_t __i = this->_M_w.size(); __i > 0; --__i)
+ {
+ if (this->_M_w[__i-1] < __x._M_w[__i-1])
+ return true;
+ else if (this->_M_w[__i-1] > __x._M_w[__i-1])
+ return false;
+ }
+ return false;
+ }
+ else
+ return false;
+ }
+
+ size_t
+ _M_are_all_aux() const
+ {
+ for (size_t __i = 0; __i < this->_M_w.size() - 1; ++__i)
+ if (_M_w[__i] != ~static_cast<block_type>(0))
+ return 0;
+ return ((this->_M_w.size() - 1) * _S_bits_per_block
+ + __builtin_popcountl(this->_M_hiword()));
+ }
+
+ bool
+ _M_is_any() const
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i] != static_cast<block_type>(0))
+ return true;
+ return false;
+ }
+
+ bool
+ _M_is_subset_of(const __dynamic_bitset_base<block_type, allocator_type>& __b)
+ {
+ if (__b.size() == this->size())
+ {
+ for (size_t __i = 0; __i < _M_w.size(); ++__i)
+ if (this->_M_w[__i] != (this->_M_w[__i] | __b._M_w[__i]))
+ return false;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ bool
+ _M_is_proper_subset_of(const __dynamic_bitset_base<block_type, allocator_type>& __b) const
+ {
+ if (this->is_subset_of(__b))
+ {
+ if (*this == __b)
+ return false;
+ else
+ return true;
+ }
+ else
+ return false;
+ }
+
+ size_t
+ _M_do_count() const
+ {
+ size_t __result = 0;
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ __result += __builtin_popcountl(this->_M_w[__i]);
+ return __result;
+ }
+
+ size_type
+ _M_size() const
+ { return this->_M_w.size(); }
+
+ unsigned long
+ _M_do_to_ulong() const;
+
+ unsigned long long
+ _M_do_to_ullong() const;
+
+ // find first "on" bit
+ size_type
+ _M_do_find_first(size_t __not_found) const;
+
+ // find the next "on" bit that follows "prev"
+ size_type
+ _M_do_find_next(size_t __prev, size_t __not_found) const;
+
+ // do append of block
+ void
+ _M_do_append_block(block_type __block, size_type __pos)
+ {
+ size_t __offset = __pos % _S_bits_per_block;
+ if (__offset == 0)
+ this->_M_w.push_back(__block);
+ else
+ {
+ this->_M_hiword() |= (__block << __offset);
+ this->_M_w.push_back(__block >> (_S_bits_per_block - __offset));
+ }
+ }
+ };
+
+ // Definitions of non-inline functions from __dynamic_bitset_base.
+ template<typename _WordT, typename _Alloc>
+ void
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_left_shift(size_t __shift)
+ {
+ if (__builtin_expect(__shift != 0, 1))
+ {
+ const size_t __wshift = __shift / _S_bits_per_block;
+ const size_t __offset = __shift % _S_bits_per_block;
+
+ if (__offset == 0)
+ for (size_t __n = this->_M_w.size() - 1; __n >= __wshift; --__n)
+ this->_M_w[__n] = this->_M_w[__n - __wshift];
+ else
+ {
+ const size_t __sub_offset = _S_bits_per_block - __offset;
+ for (size_t __n = _M_w.size() - 1; __n > __wshift; --__n)
+ this->_M_w[__n] = ((this->_M_w[__n - __wshift] << __offset)
+ | (this->_M_w[__n - __wshift - 1] >> __sub_offset));
+ this->_M_w[__wshift] = this->_M_w[0] << __offset;
+ }
+
+ ////std::fill(this->_M_w.begin(), this->_M_w.begin() + __wshift,
+ //// static_cast<_WordT>(0));
+ }
+ }
+
+ template<typename _WordT, typename _Alloc>
+ void
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_right_shift(size_t __shift)
+ {
+ if (__builtin_expect(__shift != 0, 1))
+ {
+ const size_t __wshift = __shift / _S_bits_per_block;
+ const size_t __offset = __shift % _S_bits_per_block;
+ const size_t __limit = this->_M_w.size() - __wshift - 1;
+
+ if (__offset == 0)
+ for (size_t __n = 0; __n <= __limit; ++__n)
+ this->_M_w[__n] = this->_M_w[__n + __wshift];
+ else
+ {
+ const size_t __sub_offset = (_S_bits_per_block
+ - __offset);
+ for (size_t __n = 0; __n < __limit; ++__n)
+ this->_M_w[__n] = ((this->_M_w[__n + __wshift] >> __offset)
+ | (this->_M_w[__n + __wshift + 1] << __sub_offset));
+ this->_M_w[__limit] = this->_M_w[_M_w.size()-1] >> __offset;
+ }
+
+ ////std::fill(this->_M_w.begin() + __limit + 1, this->_M_w.end(),
+ //// static_cast<_WordT>(0));
+ }
+ }
+
+ template<typename _WordT, typename _Alloc>
+ unsigned long
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ulong() const
+ {
+ size_t __n = sizeof(unsigned long) / sizeof(block_type);
+ for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i])
+ __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ulong"));
+ unsigned long __res = 0UL;
+ for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
+ __res += this->_M_w[__i] << (__i * _S_bits_per_block);
+ return __res;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ unsigned long long
+ __dynamic_bitset_base<_WordT, _Alloc>::_M_do_to_ullong() const
+ {
+ size_t __n = sizeof(unsigned long long) / sizeof(block_type);
+ for (size_t __i = __n; __i < this->_M_w.size(); ++__i)
+ if (this->_M_w[__i])
+ __throw_overflow_error(__N("__dynamic_bitset_base::_M_do_to_ullong"));
+ unsigned long long __res = 0ULL;
+ for (size_t __i = 0; __i < __n && __i < this->_M_w.size(); ++__i)
+ __res += this->_M_w[__i] << (__i * _S_bits_per_block);
+ return __res;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ size_t
+ __dynamic_bitset_base<_WordT, _Alloc>
+ ::_M_do_find_first(size_t __not_found) const
+ {
+ for (size_t __i = 0; __i < this->_M_w.size(); ++__i)
+ {
+ _WordT __thisword = this->_M_w[__i];
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzl(__thisword));
+ }
+ // not found, so return an indication of failure.
+ return __not_found;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ size_t
+ __dynamic_bitset_base<_WordT, _Alloc>
+ ::_M_do_find_next(size_t __prev, size_t __not_found) const
+ {
+ // make bound inclusive
+ ++__prev;
+
+ // check out of bounds
+ if (__prev >= this->_M_w.size() * _S_bits_per_block)
+ return __not_found;
+
+ // search first word
+ size_t __i = _S_whichword(__prev);
+ _WordT __thisword = this->_M_w[__i];
+
+ // mask off bits below bound
+ __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev);
+
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzl(__thisword));
+
+ // check subsequent words
+ for (++__i; __i < this->_M_w.size(); ++__i)
+ {
+ __thisword = this->_M_w[__i];
+ if (__thisword != static_cast<_WordT>(0))
+ return (__i * _S_bits_per_block
+ + __builtin_ctzl(__thisword));
+ }
+ // not found, so return an indication of failure.
+ return __not_found;
+ } // end _M_do_find_next
+
+ /**
+ * @brief The %dynamic_bitset class represents a sequence of bits.
+ *
+ * @ingroup containers
+ *
+ * (Note that %dynamic_bitset does @e not meet the formal
+ * requirements of a <a href="tables.html#65">container</a>.
+ * Mainly, it lacks iterators.)
+ *
+ * The template argument, @a Nb, may be any non-negative number,
+ * specifying the number of bits (e.g., "0", "12", "1024*1024").
+ *
+ * In the general unoptimized case, storage is allocated in
+ * word-sized blocks. Let B be the number of bits in a word, then
+ * (Nb+(B-1))/B words will be used for storage. B - Nb%B bits are
+ * unused. (They are the high-order bits in the highest word.) It
+ * is a class invariant that those unused bits are always zero.
+ *
+ * If you think of %dynamic_bitset as "a simple array of bits," be
+ * aware that your mental picture is reversed: a %dynamic_bitset
+ * behaves the same way as bits in integers do, with the bit at
+ * index 0 in the "least significant / right-hand" position, and
+ * the bit at index Nb-1 in the "most significant / left-hand"
+ * position. Thus, unlike other containers, a %dynamic_bitset's
+ * index "counts from right to left," to put it very loosely.
+ *
+ * This behavior is preserved when translating to and from strings.
+ * For example, the first line of the following program probably
+ * prints "b('a') is 0001100001" on a modern ASCII system.
+ *
+ * @code
+ * #include <dynamic_bitset>
+ * #include <iostream>
+ * #include <sstream>
+ *
+ * using namespace std;
+ *
+ * int main()
+ * {
+ * long a = 'a';
+ * dynamic_bitset b(a);
+ *
+ * cout << "b('a') is " << b << endl;
+ *
+ * ostringstream s;
+ * s << b;
+ * string str = s.str();
+ * cout << "index 3 in the string is " << str[3] << " but\n"
+ * << "index 3 in the bitset is " << b[3] << endl;
+ * }
+ * @endcode
+ *
+ * Also see:
+ * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch33s02.html
+ * for a description of extensions.
+ *
+ * Most of the actual code isn't contained in %dynamic_bitset<>
+ * itself, but in the base class __dynamic_bitset_base. The base
+ * class works with whole words, not with individual bits. This
+ * allows us to specialize __dynamic_bitset_base for the important
+ * special case where the %dynamic_bitset is only a single word.
+ *
+ * Extra confusion can result due to the fact that the storage for
+ * __dynamic_bitset_base @e is a vector, and is indexed as such. This is
+ * carefully encapsulated.
+ */
+ template<typename _WordT = unsigned long long,
+ typename _Alloc = std::allocator<_WordT>>
+ class dynamic_bitset
+ : private __dynamic_bitset_base<_WordT, _Alloc>
+ {
+ static_assert(std::is_unsigned<_WordT>::value, "template argument "
+ "_WordT not an unsigned integral type");
+
+ public:
+
+ typedef __dynamic_bitset_base<_WordT, _Alloc> _Base;
+ typedef _WordT block_type;
+ typedef _Alloc allocator_type;
+ typedef size_t size_type;
+
+ static const size_type bits_per_block = __CHAR_BIT__ * sizeof(block_type);
+ // Use this: constexpr size_type std::numeric_limits<size_type>::max().
+ static const size_type npos = static_cast<size_type>(-1);
+
+ private:
+
+ // Clear the unused bits in the uppermost word.
+ void
+ _M_do_sanitize()
+ {
+ size_type __shift = this->_M_Nb % bits_per_block;
+ if (__shift > 0)
+ this->_M_hiword() &= ~((~static_cast<block_type>(0)) << __shift);
+ }
+
+ /**
+ * These versions of single-bit set, reset, flip, and test
+ * do no range checking.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ _M_unchecked_set(size_type __pos)
+ {
+ this->_M_getword(__pos) |= _Base::_S_maskbit(__pos);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ _M_unchecked_set(size_type __pos, int __val)
+ {
+ if (__val)
+ this->_M_getword(__pos) |= _Base::_S_maskbit(__pos);
+ else
+ this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ _M_unchecked_reset(size_type __pos)
+ {
+ this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ _M_unchecked_flip(size_type __pos)
+ {
+ this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos);
+ return *this;
+ }
+
+ bool
+ _M_unchecked_test(size_type __pos) const
+ { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos))
+ != static_cast<_WordT>(0)); }
+
+ size_type _M_Nb;
+
+ public:
+ /**
+ * This encapsulates the concept of a single bit. An instance
+ * of this class is a proxy for an actual bit; this way the
+ * individual bit operations are done as faster word-size
+ * bitwise instructions.
+ *
+ * Most users will never need to use this class directly;
+ * conversions to and from bool are automatic and should be
+ * transparent. Overloaded operators help to preserve the
+ * illusion.
+ *
+ * (On a typical system, this "bit %reference" is 64 times the
+ * size of an actual bit. Ha.)
+ */
+ class reference
+ {
+ friend class dynamic_bitset;
+
+ block_type *_M_wp;
+ size_type _M_bpos;
+
+ // left undefined
+ reference();
+
+ public:
+ reference(dynamic_bitset& __b, size_type __pos)
+ {
+ this->_M_wp = &__b._M_getword(__pos);
+ this->_M_bpos = _Base::_S_whichbit(__pos);
+ }
+
+ ~reference()
+ { }
+
+ // For b[i] = __x;
+ reference&
+ operator=(bool __x)
+ {
+ if (__x)
+ *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos);
+ else
+ *this->_M_wp &= ~_Base::_S_maskbit(this->_M_bpos);
+ return *this;
+ }
+
+ // For b[i] = b[__j];
+ reference&
+ operator=(const reference& __j)
+ {
+ if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos)))
+ *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos);
+ else
+ *this->_M_wp &= ~_Base::_S_maskbit(this->_M_bpos);
+ return *this;
+ }
+
+ // Flips the bit
+ bool
+ operator~() const
+ { return (*(_M_wp) & _Base::_S_maskbit(this->_M_bpos)) == 0; }
+
+ // For __x = b[i];
+ operator bool() const
+ { return (*(this->_M_wp) & _Base::_S_maskbit(this->_M_bpos)) != 0; }
+
+ // For b[i].flip();
+ reference&
+ flip()
+ {
+ *this->_M_wp ^= _Base::_S_maskbit(this->_M_bpos);
+ return *this;
+ }
+ };
+
+ friend class reference;
+
+ typedef bool const_reference;
+
+ // 23.3.5.1 constructors:
+ /// All bits set to zero.
+ explicit
+ dynamic_bitset(const allocator_type& __alloc = allocator_type())
+ : _Base(__alloc), _M_Nb(0)
+ { }
+
+ /// Initial bits bitwise-copied from a single word (others set to zero).
+ explicit
+ dynamic_bitset(size_type __nbits, unsigned long long __val = 0ULL,
+ const allocator_type& __alloc = allocator_type())
+ : _Base(__nbits, __val, __alloc),
+ _M_Nb(__nbits)
+ { }
+
+ dynamic_bitset(initializer_list<block_type> __il,
+ const allocator_type& __alloc = allocator_type())
+ : _Base(__alloc), _M_Nb(0)
+ { this->append(__il); }
+
+ /**
+ * @brief Use a subset of a string.
+ * @param str A string of '0' and '1' characters.
+ * @param pos Index of the first character in @a s to use.
+ * @param n The number of characters to copy.
+ * @throw std::out_of_range If @a pos is bigger the size of @a s.
+ * @throw std::invalid_argument If a character appears in the string
+ * which is neither '0' nor '1'.
+ */
+ template<typename _CharT, typename _Traits, typename _Alloc1>
+ explicit
+ dynamic_bitset(const std::basic_string<_CharT, _Traits, _Alloc1>& __str,
+ typename basic_string<_CharT,_Traits,_Alloc1>::size_type
+ __pos = 0,
+ typename basic_string<_CharT,_Traits,_Alloc1>::size_type
+ __n = std::basic_string<_CharT, _Traits, _Alloc1>::npos,
+ _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'),
+ const allocator_type& __alloc = allocator_type())
+ : _Base(__alloc),
+ _M_Nb(0) // Watch for npos.
+ {
+ if (__pos > __str.size())
+ __throw_out_of_range(__N("dynamic_bitset::bitset initial position "
+ "not valid"));
+
+ // Watch for npos.
+ this->_M_Nb = (__n > __str.size() ? __str.size() - __pos : __n);
+ this->resize(this->_M_Nb);
+ this->_M_copy_from_string(__str, __pos, __n,
+ _CharT('0'), _CharT('1'));
+ }
+
+ /**
+ * @brief Construct from a string.
+ * @param str A string of '0' and '1' characters.
+ * @throw std::invalid_argument If a character appears in the string
+ * which is neither '0' nor '1'.
+ */
+ explicit
+ dynamic_bitset(const char* __str,
+ const allocator_type& __alloc = allocator_type())
+ : _Base(__alloc)
+ {
+ size_t __len = 0;
+ if (__str)
+ while (__str[__len] != '\0')
+ ++__len;
+ this->resize(__len);
+ this->_M_copy_from_ptr<char,std::char_traits<char>>
+ (__str, __len, 0, __len, '0', '1');
+ }
+
+ /**
+ * @brief Copy constructor.
+ */
+ dynamic_bitset(const dynamic_bitset& __b)
+ : _Base(__b), _M_Nb(__b.size())
+ { }
+
+ /**
+ * @brief Move constructor.
+ */
+ dynamic_bitset(dynamic_bitset&& __b)
+ : _Base(std::forward<_Base>(__b)), _M_Nb(__b.size())
+ { }
+
+ /**
+ * @brief Swap with another bitset.
+ */
+ void
+ swap(dynamic_bitset& __b)
+ {
+ this->_M_swap(__b);
+ std::swap(this->_M_Nb, __b._M_Nb);
+ }
+
+ /**
+ * @brief Assignment.
+ */
+ dynamic_bitset&
+ operator=(const dynamic_bitset& __b)
+ {
+ if (&__b != this)
+ {
+ this->_M_assign(__b);
+ this->_M_Nb = __b._M_Nb;
+ }
+ }
+
+ /**
+ * @brief Move assignment.
+ */
+ dynamic_bitset&
+ operator=(dynamic_bitset&& __b)
+ {
+ this->swap(__b);
+ return *this;
+ }
+
+ /**
+ * @brief Return the allocator for the bitset.
+ */
+ allocator_type
+ get_allocator() const
+ { return this->_M_get_allocator(); }
+
+ /**
+ * @brief Resize the bitset.
+ */
+ void
+ resize(size_type __nbits, bool __value = false)
+ {
+ this->_M_resize(__nbits, __value);
+ this->_M_Nb = __nbits;
+ this->_M_do_sanitize();
+ }
+
+ /**
+ * @brief Clear the bitset.
+ */
+ void
+ clear()
+ {
+ this->_M_clear();
+ this->_M_Nb = 0;
+ }
+
+ /**
+ * @brief Push a bit onto the high end of the bitset.
+ */
+ void
+ push_back(bool __bit)
+ {
+ if (size_t __offset = this->size() % bits_per_block == 0)
+ this->_M_do_append_block(block_type(0), this->_M_Nb);
+ ++this->_M_Nb;
+ this->_M_unchecked_set(this->_M_Nb, __bit);
+ }
+
+ /**
+ * @brief Append a block.
+ */
+ void
+ append(block_type __block)
+ {
+ this->_M_do_append_block(__block, this->_M_Nb);
+ this->_M_Nb += bits_per_block;
+ }
+
+ /**
+ * @brief
+ */
+ void
+ append(initializer_list<block_type> __il)
+ { this->append(__il.begin(), __il.end()); }
+
+ /**
+ * @brief Append an iterator range of blocks.
+ */
+ template <typename _BlockInputIterator>
+ void
+ append(_BlockInputIterator __first, _BlockInputIterator __last)
+ {
+ for (; __first != __last; ++__first)
+ this->append(*__first);
+ }
+
+ // 23.3.5.2 dynamic_bitset operations:
+ //@{
+ /**
+ * @brief Operations on dynamic_bitsets.
+ * @param rhs A same-sized dynamic_bitset.
+ *
+ * These should be self-explanatory.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ operator&=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ {
+ this->_M_do_and(__rhs);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator&=(dynamic_bitset<_WordT, _Alloc>&& __rhs)
+ {
+ this->_M_do_and(std::move(__rhs));
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator|=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ {
+ this->_M_do_or(__rhs);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator^=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ {
+ this->_M_do_xor(__rhs);
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator-=(const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ {
+ this->_M_do_dif(__rhs);
+ return *this;
+ }
+ //@}
+
+ //@{
+ /**
+ * @brief Operations on dynamic_bitsets.
+ * @param position The number of places to shift.
+ *
+ * These should be self-explanatory.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ operator<<=(size_type __pos)
+ {
+ if (__builtin_expect(__pos < this->_M_Nb, 1))
+ {
+ this->_M_do_left_shift(__pos);
+ this->_M_do_sanitize();
+ }
+ else
+ this->_M_do_reset();
+ return *this;
+ }
+
+ dynamic_bitset<_WordT, _Alloc>&
+ operator>>=(size_type __pos)
+ {
+ if (__builtin_expect(__pos < this->_M_Nb, 1))
+ {
+ this->_M_do_right_shift(__pos);
+ this->_M_do_sanitize();
+ }
+ else
+ this->_M_do_reset();
+ return *this;
+ }
+ //@}
+
+ // Set, reset, and flip.
+ /**
+ * @brief Sets every bit to true.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ set()
+ {
+ this->_M_do_set();
+ this->_M_do_sanitize();
+ return *this;
+ }
+
+ /**
+ * @brief Sets a given bit to a particular value.
+ * @param position The index of the bit.
+ * @param val Either true or false, defaults to true.
+ * @throw std::out_of_range If @a pos is bigger the size of the %set.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ set(size_type __pos, bool __val = true)
+ {
+ if (__pos >= _M_Nb)
+ __throw_out_of_range(__N("dynamic_bitset::set"));
+ return this->_M_unchecked_set(__pos, __val);
+ }
+
+ /**
+ * @brief Sets every bit to false.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ reset()
+ {
+ this->_M_do_reset();
+ return *this;
+ }
+
+ /**
+ * @brief Sets a given bit to false.
+ * @param position The index of the bit.
+ * @throw std::out_of_range If @a pos is bigger the size of the %set.
+ *
+ * Same as writing @c set(pos,false).
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ reset(size_type __pos)
+ {
+ if (__pos >= _M_Nb)
+ __throw_out_of_range(__N("dynamic_bitset::reset"));
+ return this->_M_unchecked_reset(__pos);
+ }
+
+ /**
+ * @brief Toggles every bit to its opposite value.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ flip()
+ {
+ this->_M_do_flip();
+ this->_M_do_sanitize();
+ return *this;
+ }
+
+ /**
+ * @brief Toggles a given bit to its opposite value.
+ * @param position The index of the bit.
+ * @throw std::out_of_range If @a pos is bigger the size of the %set.
+ */
+ dynamic_bitset<_WordT, _Alloc>&
+ flip(size_type __pos)
+ {
+ if (__pos >= _M_Nb)
+ __throw_out_of_range(__N("dynamic_bitset::flip"));
+ return this->_M_unchecked_flip(__pos);
+ }
+
+ /// See the no-argument flip().
+ dynamic_bitset<_WordT, _Alloc>
+ operator~() const
+ { return dynamic_bitset<_WordT, _Alloc>(*this).flip(); }
+
+ //@{
+ /**
+ * @brief Array-indexing support.
+ * @param position Index into the %dynamic_bitset.
+ * @return A bool for a 'const %dynamic_bitset'. For non-const
+ * bitsets, an instance of the reference proxy class.
+ * @note These operators do no range checking and throw no
+ * exceptions, as required by DR 11 to the standard.
+ */
+ reference
+ operator[](size_type __pos)
+ { return reference(*this,__pos); }
+
+ const_reference
+ operator[](size_type __pos) const
+ { return _M_unchecked_test(__pos); }
+ //@}
+
+ /**
+ * @brief Returns a numerical interpretation of the %dynamic_bitset.
+ * @return The integral equivalent of the bits.
+ * @throw std::overflow_error If there are too many bits to be
+ * represented in an @c unsigned @c long.
+ */
+ unsigned long
+ to_ulong() const
+ { return this->_M_do_to_ulong(); }
+
+ /**
+ * @brief Returns a numerical interpretation of the %dynamic_bitset.
+ * @return The integral equivalent of the bits.
+ * @throw std::overflow_error If there are too many bits to be
+ * represented in an @c unsigned @c long.
+ */
+ unsigned long long
+ to_ullong() const
+ { return this->_M_do_to_ullong(); }
+
+ /**
+ * @brief Returns a character interpretation of the %dynamic_bitset.
+ * @return The string equivalent of the bits.
+ *
+ * Note the ordering of the bits: decreasing character positions
+ * correspond to increasing bit positions (see the main class notes for
+ * an example).
+ */
+ template<typename _CharT = char,
+ typename _Traits = std::char_traits<_CharT>,
+ typename _Alloc1 = std::allocator<_CharT>>
+ std::basic_string<_CharT, _Traits, _Alloc1>
+ to_string(_CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) const
+ {
+ std::basic_string<_CharT, _Traits, _Alloc1> __result;
+ _M_copy_to_string(__result, __zero, __one);
+ return __result;
+ }
+
+ // Helper functions for string operations.
+ template<typename _CharT, typename _Traits>
+ void
+ _M_copy_from_ptr(const _CharT*, size_t, size_t, size_t,
+ _CharT, _CharT);
+
+ template<typename _CharT, typename _Traits, typename _Alloc1>
+ void
+ _M_copy_from_string(const std::basic_string<_CharT,
+ _Traits, _Alloc1>& __str, size_t __pos, size_t __n,
+ _CharT __zero = _CharT('0'),
+ _CharT __one = _CharT('1'))
+ { _M_copy_from_ptr<_CharT, _Traits>(__str.data(), __str.size(),
+ __pos, __n, __zero, __one); }
+
+ template<typename _CharT, typename _Traits, typename _Alloc1>
+ void
+ _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc1>& __str,
+ _CharT __zero = _CharT('0'),
+ _CharT __one = _CharT('1')) const;
+
+ /// Returns the number of bits which are set.
+ size_type
+ count() const
+ { return this->_M_do_count(); }
+
+ /// Returns the total number of bits.
+ size_type
+ size() const
+ { return this->_M_Nb; }
+
+ /// Returns the total number of blocks.
+ size_type num_blocks() const
+ { return this->_M_size(); }
+
+ /// Returns true if the dynamic_bitset is empty.
+ bool
+ empty() const
+ { return (this->_M_Nb == 0); }
+
+ /// Returns the maximum size of a dynamic_bitset object having the same
+ /// type as *this.
+ /// The real answer is max() * bits_per_block but is likely to overflow.
+ /*constexpr*/ size_type
+ max_size() const
+ { return std::numeric_limits<block_type>::max(); }
+
+ /**
+ * @brief Tests the value of a bit.
+ * @param position The index of a bit.
+ * @return The value at @a pos.
+ * @throw std::out_of_range If @a pos is bigger the size of the %set.
+ */
+ bool
+ test(size_type __pos) const
+ {
+ if (__pos >= _M_Nb)
+ __throw_out_of_range(__N("dynamic_bitset::test"));
+ return _M_unchecked_test(__pos);
+ }
+
+ /**
+ * @brief Tests whether all the bits are on.
+ * @return True if all the bits are set.
+ */
+ bool
+ all() const
+ { return this->_M_are_all_aux() == _M_Nb; }
+
+ /**
+ * @brief Tests whether any of the bits are on.
+ * @return True if at least one bit is set.
+ */
+ bool
+ any() const
+ { return this->_M_is_any(); }
+
+ /**
+ * @brief Tests whether any of the bits are on.
+ * @return True if none of the bits are set.
+ */
+ bool
+ none() const
+ { return !this->_M_is_any(); }
+
+ //@{
+ /// Self-explanatory.
+ dynamic_bitset<_WordT, _Alloc>
+ operator<<(size_type __pos) const
+ { return dynamic_bitset<_WordT, _Alloc>(*this) <<= __pos; }
+
+ dynamic_bitset<_WordT, _Alloc>
+ operator>>(size_type __pos) const
+ { return dynamic_bitset<_WordT, _Alloc>(*this) >>= __pos; }
+ //@}
+
+ /**
+ * @brief Finds the index of the first "on" bit.
+ * @return The index of the first bit set, or size() if not found.
+ * @sa find_next
+ */
+ size_type
+ find_first() const
+ { return this->_M_do_find_first(this->_M_Nb); }
+
+ /**
+ * @brief Finds the index of the next "on" bit after prev.
+ * @return The index of the next bit set, or size() if not found.
+ * @param prev Where to start searching.
+ * @sa find_first
+ */
+ size_type
+ find_next(size_t __prev) const
+ { return this->_M_do_find_next(__prev, this->_M_Nb); }
+
+ bool
+ is_subset_of(const dynamic_bitset& __b) const
+ { return this->_M_is_subset_of(__b); }
+
+ bool
+ is_proper_subset_of(const dynamic_bitset& __b) const
+ { return this->_M_is_proper_subset_of(__b); }
+ };
+
+ // Definitions of non-inline member functions.
+ template<typename _WordT, typename _Alloc>
+ template<typename _CharT, typename _Traits>
+ void
+ dynamic_bitset<_WordT, _Alloc>::
+ _M_copy_from_ptr(const _CharT* __str, size_t __len,
+ size_t __pos, size_t __n, _CharT __zero, _CharT __one)
+ {
+ reset();
+ const size_t __nbits = std::min(_M_Nb, std::min(__n, __len - __pos));
+ for (size_t __i = __nbits; __i > 0; --__i)
+ {
+ const _CharT __c = __str[__pos + __nbits - __i];
+ if (_Traits::eq(__c, __zero))
+ ;
+ else if (_Traits::eq(__c, __one))
+ _M_unchecked_set(__i - 1);
+ else
+ __throw_invalid_argument(__N("dynamic_bitset::_M_copy_from_ptr"));
+ }
+ }
+
+ template<typename _WordT, typename _Alloc>
+ template<typename _CharT, typename _Traits, typename _Alloc1>
+ void
+ dynamic_bitset<_WordT, _Alloc>::
+ _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc1>& __str,
+ _CharT __zero, _CharT __one) const
+ {
+ __str.assign(_M_Nb, __zero);
+ for (size_t __i = _M_Nb; __i > 0; --__i)
+ if (_M_unchecked_test(__i - 1))
+ _Traits::assign(__str[_M_Nb - __i], __one);
+ }
+
+
+ //@{
+ /// These comparisons for equality/inequality are, well, @e bitwise.
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator==(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return __lhs._M_is_equal(__rhs); }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator!=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return !__lhs._M_is_equal(__rhs); }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator<(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return __lhs._M_is_less(__rhs); }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator<=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return !(__lhs > __rhs); }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator>(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return __rhs < __lhs; }
+
+ template<typename _WordT, typename _Alloc>
+ bool
+ operator>=(const dynamic_bitset<_WordT, _Alloc>& __lhs,
+ const dynamic_bitset<_WordT, _Alloc>& __rhs)
+ { return !(__lhs < __rhs); }
+ //@}
+
+ // 23.3.5.3 bitset operations:
+ //@{
+ /**
+ * @brief Global bitwise operations on bitsets.
+ * @param x A bitset.
+ * @param y A bitset of the same size as @a x.
+ * @return A new bitset.
+ *
+ * These should be self-explanatory.
+ */
+ template<typename _WordT, typename _Alloc>
+ inline dynamic_bitset<_WordT, _Alloc>
+ operator&(const dynamic_bitset<_WordT, _Alloc>& __x,
+ const dynamic_bitset<_WordT, _Alloc>& __y)
+ {
+ dynamic_bitset<_WordT, _Alloc> __result(__x);
+ __result &= __y;
+ return __result;
+ }
+
+ template<typename _WordT, typename _Alloc>
+ inline dynamic_bitset<_WordT, _Alloc>
+ operator|(const dynamic_bitset<_WordT, _Alloc>& __x,
+ const dynamic_bitset<_WordT, _Alloc>& __y)
+ {
+ dynamic_bitset<_WordT, _Alloc> __result(__x);
+ __result |= __y;
+ return __result;
+ }
+
+ template <typename _WordT, typename _Alloc>
+ inline dynamic_bitset<_WordT, _Alloc>
+ operator^(const dynamic_bitset<_WordT, _Alloc>& __x,
+ const dynamic_bitset<_WordT, _Alloc>& __y)
+ {
+ dynamic_bitset<_WordT, _Alloc> __result(__x);
+ __result ^= __y;
+ return __result;
+ }
+
+ template <typename _WordT, typename _Alloc>
+ inline dynamic_bitset<_WordT, _Alloc>
+ operator-(const dynamic_bitset<_WordT, _Alloc>& __x,
+ const dynamic_bitset<_WordT, _Alloc>& __y)
+ {
+ dynamic_bitset<_WordT, _Alloc> __result(__x);
+ __result -= __y;
+ return __result;
+ }
+ //@}
+
+ //@{
+ /**
+ * @brief Global I/O operators for bitsets.
+ *
+ * Direct I/O between streams and bitsets is supported. Output is
+ * straightforward. Input will skip whitespace and only accept '0'
+ * and '1' characters. The %dynamic_bitset will grow as necessary
+ * to hold the string of bits.
+ */
+ template<typename _CharT, typename _Traits,
+ typename _WordT, typename _Alloc>
+ std::basic_istream<_CharT, _Traits>&
+ operator>>(std::basic_istream<_CharT, _Traits>& __is,
+ dynamic_bitset<_WordT, _Alloc>& __x)
+ {
+ typedef typename _Traits::char_type char_type;
+ typedef std::basic_istream<_CharT, _Traits> __istream_type;
+ typedef typename __istream_type::ios_base __ios_base;
+
+ std::basic_string<_CharT, _Traits> __tmp;
+ __tmp.reserve(__x.size());
+
+ const char_type __zero = __is.widen('0');
+ const char_type __one = __is.widen('1');
+
+ typename __ios_base::iostate __state = __ios_base::goodbit;
+ typename __istream_type::sentry __sentry(__is);
+ if (__sentry)
+ {
+ __try
+ {
+ while (1)
+ {
+ static typename _Traits::int_type __eof = _Traits::eof();
+
+ typename _Traits::int_type __c1 = __is.rdbuf()->sbumpc();
+ if (_Traits::eq_int_type(__c1, __eof))
+ {
+ __state |= __ios_base::eofbit;
+ break;
+ }
+ else
+ {
+ const char_type __c2 = _Traits::to_char_type(__c1);
+ if (_Traits::eq(__c2, __zero))
+ __tmp.push_back(__zero);
+ else if (_Traits::eq(__c2, __one))
+ __tmp.push_back(__one);
+ else if (_Traits::
+ eq_int_type(__is.rdbuf()->sputbackc(__c2),
+ __eof))
+ {
+ __state |= __ios_base::failbit;
+ break;
+ }
+ else
+ break;
+ }
+ }
+ }
+ __catch(__cxxabiv1::__forced_unwind&)
+ {
+ __is._M_setstate(__ios_base::badbit);
+ __throw_exception_again;
+ }
+ __catch(...)
+ { __is._M_setstate(__ios_base::badbit); }
+ }
+
+ __x.resize(__tmp.size());
+
+ if (__tmp.empty() && __x.size())
+ __state |= __ios_base::failbit;
+ else
+ __x._M_copy_from_string(__tmp, static_cast<size_t>(0), __x.size(),
+ __zero, __one);
+ if (__state)
+ __is.setstate(__state);
+ return __is;
+ }
+
+ template <typename _CharT, typename _Traits,
+ typename _WordT, typename _Alloc>
+ std::basic_ostream<_CharT, _Traits>&
+ operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+ const dynamic_bitset<_WordT, _Alloc>& __x)
+ {
+ std::basic_string<_CharT, _Traits> __tmp;
+
+ const ctype<_CharT>& __ct = use_facet<ctype<_CharT>>(__os.getloc());
+ __x._M_copy_to_string(__tmp, __ct.widen('0'), __ct.widen('1'));
+ return __os << __tmp;
+ }
+ //@}
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // tr2
+} // std
+
+#undef _GLIBCXX_BITSET_BITS_PER_WORD
+
+#endif /* _GLIBCXX_TR2_DYNAMIC_BITSET */
diff --git a/libstdc++-v3/include/tr2/ratio b/libstdc++-v3/include/tr2/ratio
new file mode 100644
index 00000000000..34a9553c444
--- /dev/null
+++ b/libstdc++-v3/include/tr2/ratio
@@ -0,0 +1,59 @@
+// TR2 <ratio> -*- C++ -*-
+
+// Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/ratio
+ * This is a TR2 C++ Library header.
+ */
+
+#include <ratio>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ template<intmax_t _Pn, size_t _Bit,
+ bool = _Bit < static_cast<size_t>
+ (std::numeric_limits<intmax_t>::digits)>
+ struct __safe_lshift
+ { static const intmax_t __value = 0; };
+
+ template<intmax_t _Pn, size_t _Bit>
+ struct __safe_lshift<_Pn, _Bit, true>
+ { static const intmax_t __value = _Pn << _Bit; };
+
+ /// Add binary prefixes (IEC 60027-2 A.2 and ISO/IEC 80000).
+ typedef ratio<__safe_lshift<1, 10>::__value, 1> kibi;
+ typedef ratio<__safe_lshift<1, 20>::__value, 1> mebi;
+ typedef ratio<__safe_lshift<1, 30>::__value, 1> gibi;
+ typedef ratio<__safe_lshift<1, 40>::__value, 1> tebi;
+ typedef ratio<__safe_lshift<1, 50>::__value, 1> pebi;
+ typedef ratio<__safe_lshift<1, 60>::__value, 1> exbi;
+ //typedef ratio<__safe_lshift<1, 70>::__value, 1> zebi;
+ //typedef ratio<__safe_lshift<1, 80>::__value, 1> yobi;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
diff --git a/libstdc++-v3/include/tr2/type_traits b/libstdc++-v3/include/tr2/type_traits
new file mode 100644
index 00000000000..73edf1137e4
--- /dev/null
+++ b/libstdc++-v3/include/tr2/type_traits
@@ -0,0 +1,102 @@
+// TR2 <type_traits> -*- C++ -*-
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file tr2/type_traits
+ * This is a TR2 C++ Library header.
+ */
+
+#ifndef _GLIBCXX_TR2_TYPE_TRAITS
+#define _GLIBCXX_TR2_TYPE_TRAITS 1
+
+#pragma GCC system_header
+#include <type_traits>
+#include <bits/c++config.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace tr2
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+ /**
+ * @defgroup metaprogramming Type Traits
+ * @ingroup utilities
+ *
+ * Compile time type transformation and information.
+ * @{
+ */
+
+ template<typename... _Elements>
+ struct typelist;
+
+ template<>
+ struct typelist<>
+ {
+ typedef std::true_type empty;
+ };
+
+ template<typename _First, typename... _Rest>
+ struct typelist<_First, _Rest...>
+ {
+ typedef std::false_type empty;
+
+ struct first
+ {
+ typedef _First type;
+ };
+
+ struct rest
+ {
+ typedef typelist<_Rest...> type;
+ };
+ };
+
+ // Sequence abstraction metafunctions default to looking in the type
+ template<typename _Tp>
+ struct first : public _Tp::first { };
+
+ template<typename _Tp>
+ struct rest : public _Tp::rest { };
+
+ template<typename _Tp>
+ struct empty : public _Tp::empty { };
+
+
+ template<typename _Tp>
+ struct bases
+ {
+ typedef typelist<__bases(_Tp)...> type;
+ };
+
+ template<typename _Tp>
+ struct direct_bases
+ {
+ typedef typelist<__direct_bases(_Tp)...> type;
+ };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+}
+
+#endif // _GLIBCXX_TR2_TYPE_TRAITS
diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
index 4c36c35e0bc..9ef5e683af8 100644
--- a/libstdc++-v3/libsupc++/Makefile.in
+++ b/libstdc++-v3/libsupc++/Makefile.in
@@ -272,7 +272,6 @@ glibcxx_builddir = @glibcxx_builddir@
glibcxx_localedir = @glibcxx_localedir@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
-glibcxx_thread_h = @glibcxx_thread_h@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@
gxx_include_dir = @gxx_include_dir@
@@ -312,6 +311,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
# May be used by various substitution variables.
diff --git a/libstdc++-v3/libsupc++/del_op.cc b/libstdc++-v3/libsupc++/del_op.cc
index 86d4c1e2985..0d69aa3aa35 100644
--- a/libstdc++-v3/libsupc++/del_op.cc
+++ b/libstdc++-v3/libsupc++/del_op.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2007, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2007, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -41,7 +42,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete(void* ptr) throw ()
+operator delete(void* ptr) _GLIBCXX_USE_NOEXCEPT
{
if (ptr)
std::free(ptr);
diff --git a/libstdc++-v3/libsupc++/del_opnt.cc b/libstdc++-v3/libsupc++/del_opnt.cc
index 29eab1022ee..1a43ca4e789 100644
--- a/libstdc++-v3/libsupc++/del_opnt.cc
+++ b/libstdc++-v3/libsupc++/del_opnt.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -29,7 +30,7 @@
extern "C" void free (void *);
_GLIBCXX_WEAK_DEFINITION void
-operator delete (void *ptr, const std::nothrow_t&) throw ()
+operator delete (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
free (ptr);
}
diff --git a/libstdc++-v3/libsupc++/del_opv.cc b/libstdc++-v3/libsupc++/del_opv.cc
index c56df07d9d7..594f86262d7 100644
--- a/libstdc++-v3/libsupc++/del_opv.cc
+++ b/libstdc++-v3/libsupc++/del_opv.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -27,7 +28,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr) throw ()
+operator delete[] (void *ptr) _GLIBCXX_USE_NOEXCEPT
{
::operator delete (ptr);
}
diff --git a/libstdc++-v3/libsupc++/del_opvnt.cc b/libstdc++-v3/libsupc++/del_opvnt.cc
index fec64953e63..e27eb5826e3 100644
--- a/libstdc++-v3/libsupc++/del_opvnt.cc
+++ b/libstdc++-v3/libsupc++/del_opvnt.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -27,7 +28,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void
-operator delete[] (void *ptr, const std::nothrow_t&) throw ()
+operator delete[] (void *ptr, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
::operator delete (ptr);
}
diff --git a/libstdc++-v3/libsupc++/initializer_list b/libstdc++-v3/libsupc++/initializer_list
index 0dc8ae90f06..0e2c58a43ae 100644
--- a/libstdc++-v3/libsupc++/initializer_list
+++ b/libstdc++-v3/libsupc++/initializer_list
@@ -32,7 +32,9 @@
#pragma GCC system_header
-#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+# include <bits/c++0x_warning.h>
+#endif // C++0x
#pragma GCC visibility push(default)
@@ -99,5 +101,4 @@ namespace std
}
#pragma GCC visibility pop
-#endif // C++0x
#endif // _INITIALIZER_LIST
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 80ee3ba0fd8..1c258002e65 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -1,7 +1,7 @@
// The -*- C++ -*- dynamic memory management header.
// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-// 2003, 2004, 2005, 2006, 2007, 2009, 2010
+// 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011
// Free Software Foundation
// This file is part of GCC.
@@ -90,22 +90,32 @@ namespace std
* Placement new and delete signatures (take a memory address argument,
* does nothing) may not be replaced by a user's program.
*/
-void* operator new(std::size_t) throw (std::bad_alloc);
-void* operator new[](std::size_t) throw (std::bad_alloc);
-void operator delete(void*) throw();
-void operator delete[](void*) throw();
-void* operator new(std::size_t, const std::nothrow_t&) throw();
-void* operator new[](std::size_t, const std::nothrow_t&) throw();
-void operator delete(void*, const std::nothrow_t&) throw();
-void operator delete[](void*, const std::nothrow_t&) throw();
+void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
+ __attribute__((__externally_visible__));
+void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
+ __attribute__((__externally_visible__));
+void operator delete(void*) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
+void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
+ __attribute__((__externally_visible__));
// Default placement versions of operator new.
-inline void* operator new(std::size_t, void* __p) throw() { return __p; }
-inline void* operator new[](std::size_t, void* __p) throw() { return __p; }
+inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
+{ return __p; }
+inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
+{ return __p; }
// Default placement versions of operator delete.
-inline void operator delete (void*, void*) throw() { }
-inline void operator delete[](void*, void*) throw() { }
+inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { }
+inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
//@}
} // extern "C++"
diff --git a/libstdc++-v3/libsupc++/new_op.cc b/libstdc++-v3/libsupc++/new_op.cc
index c61e941bcff..bb0199e969e 100644
--- a/libstdc++-v3/libsupc++/new_op.cc
+++ b/libstdc++-v3/libsupc++/new_op.cc
@@ -42,7 +42,7 @@ extern "C" void *malloc (std::size_t);
extern new_handler __new_handler;
_GLIBCXX_WEAK_DEFINITION void *
-operator new (std::size_t sz) throw (std::bad_alloc)
+operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
void *p;
diff --git a/libstdc++-v3/libsupc++/new_opnt.cc b/libstdc++-v3/libsupc++/new_opnt.cc
index 1bcdead5846..71600a63c3d 100644
--- a/libstdc++-v3/libsupc++/new_opnt.cc
+++ b/libstdc++-v3/libsupc++/new_opnt.cc
@@ -34,7 +34,7 @@ extern "C" void *malloc (std::size_t);
extern new_handler __new_handler;
_GLIBCXX_WEAK_DEFINITION void *
-operator new (std::size_t sz, const std::nothrow_t&) throw()
+operator new (std::size_t sz, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
{
void *p;
diff --git a/libstdc++-v3/libsupc++/new_opv.cc b/libstdc++-v3/libsupc++/new_opv.cc
index b200e23c3ec..4080bd25b4f 100644
--- a/libstdc++-v3/libsupc++/new_opv.cc
+++ b/libstdc++-v3/libsupc++/new_opv.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -27,7 +28,7 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void*
-operator new[] (std::size_t sz) throw (std::bad_alloc)
+operator new[] (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
return ::operator new(sz);
}
diff --git a/libstdc++-v3/libsupc++/new_opvnt.cc b/libstdc++-v3/libsupc++/new_opvnt.cc
index da4ae80b697..0609e687ab7 100644
--- a/libstdc++-v3/libsupc++/new_opvnt.cc
+++ b/libstdc++-v3/libsupc++/new_opvnt.cc
@@ -1,6 +1,7 @@
// Boilerplate support routines for -*- C++ -*- dynamic memory management.
-// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009 Free Software Foundation
+// Copyright (C) 1997, 1998, 1999, 2000, 2004, 2009, 2010, 2011
+// Free Software Foundation
//
// This file is part of GCC.
//
@@ -27,7 +28,8 @@
#include "new"
_GLIBCXX_WEAK_DEFINITION void*
-operator new[] (std::size_t sz, const std::nothrow_t& nothrow) throw()
+operator new[] (std::size_t sz, const std::nothrow_t& nothrow)
+ _GLIBCXX_USE_NOEXCEPT
{
return ::operator new(sz, nothrow);
}
diff --git a/libstdc++-v3/po/Makefile.in b/libstdc++-v3/po/Makefile.in
index 09092677b04..0226b894a6e 100644
--- a/libstdc++-v3/po/Makefile.in
+++ b/libstdc++-v3/po/Makefile.in
@@ -213,7 +213,6 @@ glibcxx_builddir = @glibcxx_builddir@
glibcxx_localedir = @glibcxx_localedir@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
-glibcxx_thread_h = @glibcxx_thread_h@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@
gxx_include_dir = @gxx_include_dir@
@@ -253,6 +252,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
# May be used by various substitution variables.
diff --git a/libstdc++-v3/python/Makefile.in b/libstdc++-v3/python/Makefile.in
index 01bcddbe1c6..ca046cf0a33 100644
--- a/libstdc++-v3/python/Makefile.in
+++ b/libstdc++-v3/python/Makefile.in
@@ -237,7 +237,6 @@ glibcxx_builddir = @glibcxx_builddir@
glibcxx_localedir = @glibcxx_localedir@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
-glibcxx_thread_h = @glibcxx_thread_h@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@
gxx_include_dir = @gxx_include_dir@
@@ -277,6 +276,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
# May be used by various substitution variables.
diff --git a/libstdc++-v3/scripts/create_testsuite_files b/libstdc++-v3/scripts/create_testsuite_files
index f4a0bcd80e0..a427eef2db0 100755
--- a/libstdc++-v3/scripts/create_testsuite_files
+++ b/libstdc++-v3/scripts/create_testsuite_files
@@ -32,7 +32,7 @@ cd $srcdir
# This is the ugly version of "everything but the current directory". It's
# what has to happen when find(1) doesn't support -mindepth, or -xtype.
dlist=`echo [0-9][0-9]*`
-dlist="$dlist abi backward ext performance tr1 decimal"
+dlist="$dlist abi backward ext performance tr1 tr2 decimal"
find $dlist "(" -type f -o -type l ")" -name "*.cc" -print > $tmp.01
find $dlist "(" -type f -o -type l ")" -name "*.c" -print > $tmp.02
cat $tmp.01 $tmp.02 | sort > $tmp.1
diff --git a/libstdc++-v3/scripts/run_doxygen b/libstdc++-v3/scripts/run_doxygen
index 48b17249737..3fef95f83fb 100644
--- a/libstdc++-v3/scripts/run_doxygen
+++ b/libstdc++-v3/scripts/run_doxygen
@@ -339,6 +339,10 @@ for f in std_tr1_*; do
newname=`echo $f | sed 's/^std_tr1_/std::tr1::/'`
mv $f $newname
done
+for f in std_tr2_*; do
+ newname=`echo $f | sed 's/^std_tr2_/std::tr2::/'`
+ mv $f $newname
+done
for f in std_*; do
newname=`echo $f | sed 's/^std_/std::/'`
mv $f $newname
diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in
index 279f162d9dc..4b2646e4a05 100644
--- a/libstdc++-v3/src/Makefile.in
+++ b/libstdc++-v3/src/Makefile.in
@@ -277,7 +277,6 @@ glibcxx_builddir = @glibcxx_builddir@
glibcxx_localedir = @glibcxx_localedir@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
-glibcxx_thread_h = @glibcxx_thread_h@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@
gxx_include_dir = @gxx_include_dir@
@@ -317,6 +316,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
# May be used by various substitution variables.
diff --git a/libstdc++-v3/src/condition_variable.cc b/libstdc++-v3/src/condition_variable.cc
index 7f1e1946a55..400fcf3546a 100644
--- a/libstdc++-v3/src/condition_variable.cc
+++ b/libstdc++-v3/src/condition_variable.cc
@@ -30,25 +30,25 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
- condition_variable::condition_variable() throw ()
- {
#ifdef __GTHREAD_COND_INIT
- __native_type __tmp = __GTHREAD_COND_INIT;
- _M_cond = __tmp;
+ condition_variable::condition_variable() noexcept = default;
+ condition_variable::~condition_variable() noexcept = default;
#else
+ condition_variable::condition_variable() noexcept
+ {
int __e = __gthread_cond_init(&_M_cond, 0);
if (__e)
__throw_system_error(__e);
-#endif
}
- condition_variable::~condition_variable() throw ()
+ condition_variable::~condition_variable() noexcept
{
// XXX no thread blocked
/* int __e = */ __gthread_cond_destroy(&_M_cond);
// if __e == EBUSY then blocked
}
+#endif
void
condition_variable::wait(unique_lock<mutex>& __lock)
@@ -60,7 +60,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
void
- condition_variable::notify_one()
+ condition_variable::notify_one() noexcept
{
int __e = __gthread_cond_signal(&_M_cond);
@@ -71,7 +71,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
void
- condition_variable::notify_all()
+ condition_variable::notify_all() noexcept
{
int __e = __gthread_cond_broadcast(&_M_cond);
@@ -81,11 +81,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_system_error(__e);
}
- condition_variable_any::condition_variable_any() throw ()
- { }
+ condition_variable_any::condition_variable_any() noexcept = default;
- condition_variable_any::~condition_variable_any() throw ()
- { }
+ condition_variable_any::~condition_variable_any() noexcept = default;
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/testsuite/18_support/50594.cc b/libstdc++-v3/testsuite/18_support/50594.cc
new file mode 100644
index 00000000000..047f4a732bf
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/50594.cc
@@ -0,0 +1,72 @@
+// { dg-options "-fwhole-program" }
+
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <new>
+#include <string>
+#include <cstdlib>
+#include <testsuite_hooks.h>
+
+bool user_new_called;
+bool user_delete_called;
+
+void* operator new(std::size_t n)
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+ throw(std::bad_alloc)
+#endif
+{
+ user_new_called = true;
+
+ void* p = std::malloc(n);
+
+ if (!p)
+ throw std::bad_alloc();
+
+ return p;
+}
+
+void operator delete(void* p)
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ noexcept
+#else
+ throw()
+#endif
+{
+ user_delete_called = true;
+
+ std::free(p);
+}
+
+// libstdc++/50594
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+
+ {
+ std::string s = "Hello World.";
+ }
+
+ VERIFY( user_new_called );
+ VERIFY( user_delete_called );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc b/libstdc++-v3/testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc
index 146b9656f3d..f8361c40cf2 100644
--- a/libstdc++-v3/testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <cstdbool>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/18_support/headers/cstdint/std_c++0x_neg.cc b/libstdc++-v3/testsuite/18_support/headers/cstdint/std_c++0x_neg.cc
index afd65a36ade..7dbc10ef20c 100644
--- a/libstdc++-v3/testsuite/18_support/headers/cstdint/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/18_support/headers/cstdint/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <cstdint>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/std_c++0x_neg.cc b/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/std_c++0x_neg.cc
index 9698cf03191..38e27dc8246 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/std_c++0x_neg.cc
@@ -19,7 +19,7 @@
#include <system_error>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc b/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc
index 4fd554e350f..e698114091b 100644
--- a/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/headers/type_traits/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <type_traits>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
index a3abadf4622..b72553ba0f4 100644
--- a/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/weak_ptr/comparison/cmp_neg.cc
@@ -41,19 +41,3 @@ main()
test01();
return 0;
}
-
-// { dg-warning "note" "" { target *-*-* } 370 }
-// { dg-warning "note" "" { target *-*-* } 365 }
-// { dg-warning "note" "" { target *-*-* } 356 }
-// { dg-warning "note" "" { target *-*-* } 1103 }
-// { dg-warning "note" "" { target *-*-* } 1098 }
-// { dg-warning "note" "" { target *-*-* } 1089 }
-// { dg-warning "note" "" { target *-*-* } 485 }
-// { dg-warning "note" "" { target *-*-* } 479 }
-// { dg-warning "note" "" { target *-*-* } 468 }
-// { dg-warning "note" "" { target *-*-* } 841 }
-// { dg-warning "note" "" { target *-*-* } 1056 }
-// { dg-warning "note" "" { target *-*-* } 1050 }
-// { dg-warning "note" "" { target *-*-* } 342 }
-// { dg-warning "note" "" { target *-*-* } 292 }
-// { dg-warning "note" "" { target *-*-* } 224 }
diff --git a/libstdc++-v3/testsuite/22_locale/codecvt_byname/50714.cc b/libstdc++-v3/testsuite/22_locale/codecvt_byname/50714.cc
new file mode 100644
index 00000000000..9bdc310aaaf
--- /dev/null
+++ b/libstdc++-v3/testsuite/22_locale/codecvt_byname/50714.cc
@@ -0,0 +1,95 @@
+// { dg-require-namedlocale "de_DE" }
+
+// Copyright (C) 2011 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <locale>
+#include <ext/pod_char_traits.h>
+
+#define mychar __gnu_cxx::character<unsigned short, int>
+
+namespace std
+{
+ template<> codecvt<mychar, char, mbstate_t>::~codecvt()
+ { }
+
+ template<>
+ codecvt<mychar, char, mbstate_t>::result
+ codecvt<mychar, char, mbstate_t>::
+ do_out(state_type&, const intern_type*, const intern_type*,
+ const intern_type*&, extern_type*, extern_type*,
+ extern_type*&) const
+ { return codecvt_base::ok; }
+
+ template<>
+ codecvt<mychar, char, mbstate_t>::result
+ codecvt<mychar, char, mbstate_t>::
+ do_in(state_type&, const extern_type*, const extern_type*,
+ const extern_type*&, intern_type*, intern_type*,
+ intern_type*&) const
+ { return codecvt_base::ok; }
+
+ template<>
+ codecvt<mychar, char, mbstate_t>::result
+ codecvt<mychar, char, mbstate_t>::
+ do_unshift(state_type&, extern_type*, extern_type*,
+ extern_type*&) const
+ { return noconv; }
+
+ template<>
+ int
+ codecvt<mychar, char, mbstate_t>::do_encoding() const
+ { return 0; }
+
+ template<>
+ bool
+ codecvt<mychar, char, mbstate_t>::do_always_noconv() const
+ { return false; }
+
+ template<>
+ int
+ codecvt<mychar, char, mbstate_t>::
+ do_length(state_type&, const extern_type*, const extern_type*,
+ size_t) const
+ { return 0; }
+
+ template<>
+ int
+ codecvt<mychar, char, mbstate_t>::do_max_length() const
+ { return 4; }
+}
+
+// libstdc++/50714
+void test01()
+{
+ using namespace std;
+
+ {
+ locale loc(locale::classic(),
+ new codecvt<mychar, char, mbstate_t>());
+ }
+ {
+ locale loc2(locale::classic(),
+ new codecvt_byname<mychar, char, mbstate_t>("de_DE"));
+ }
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc
index 60f5008d690..006041dc5f7 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1668 }
+// { dg-error "no matching" "" { target *-*-* } 1670 }
#include <deque>
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc
index 2d84537e30a..c7ed29a2104 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1601 }
+// { dg-error "no matching" "" { target *-*-* } 1603 }
#include <deque>
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc
index 2329a32a4d2..e390f44b565 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1601 }
+// { dg-error "no matching" "" { target *-*-* } 1603 }
#include <deque>
#include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc
index 631d76c4aa6..ed81d582fdf 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1752 }
+// { dg-error "no matching" "" { target *-*-* } 1754 }
#include <deque>
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/assign_neg.cc
index 7dd46e1fb48..774c728ddab 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/assign_neg.cc
@@ -1,6 +1,6 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
-// { dg-error "no matching" "" { target *-*-* } 1211 }
+// { dg-error "no matching" "" { target *-*-* } 1213 }
// Copyright (C) 2009, 2010, 2011 Free Software Foundation
//
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_1_neg.cc
index e8e4d570019..e19698d6140 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_1_neg.cc
@@ -1,6 +1,6 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
-// { dg-error "no matching" "" { target *-*-* } 1211 }
+// { dg-error "no matching" "" { target *-*-* } 1213 }
// Copyright (C) 2009, 2010, 2011 Free Software Foundation
//
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_2_neg.cc
index 0ea7d2b7335..1d7fdb8a2a3 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/constructor_2_neg.cc
@@ -1,6 +1,6 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
-// { dg-error "no matching" "" { target *-*-* } 1211 }
+// { dg-error "no matching" "" { target *-*-* } 1213 }
// Copyright (C) 2009, 2010, 2011 Free Software Foundation
//
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/insert_neg.cc
index 8d7844cabe4..12dd38e76e4 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/requirements/dr438/insert_neg.cc
@@ -1,6 +1,6 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
-// { dg-error "no matching" "" { target *-*-* } 1211 }
+// { dg-error "no matching" "" { target *-*-* } 1213 }
// Copyright (C) 2009, 2010, 2011 Free Software Foundation
//
diff --git a/libstdc++-v3/testsuite/23_containers/headers/array/std_c++0x_neg.cc b/libstdc++-v3/testsuite/23_containers/headers/array/std_c++0x_neg.cc
index e9317d7ed7f..bded29ee68c 100644
--- a/libstdc++-v3/testsuite/23_containers/headers/array/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/headers/array/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <array>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/23_containers/headers/tuple/std_c++0x_neg.cc b/libstdc++-v3/testsuite/23_containers/headers/tuple/std_c++0x_neg.cc
index 0a2e073a50b..b5a10d2d611 100644
--- a/libstdc++-v3/testsuite/23_containers/headers/tuple/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/headers/tuple/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <tuple>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/23_containers/headers/unordered_map/std_c++0x_neg.cc b/libstdc++-v3/testsuite/23_containers/headers/unordered_map/std_c++0x_neg.cc
index 0b32304ca61..612124006c1 100644
--- a/libstdc++-v3/testsuite/23_containers/headers/unordered_map/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/headers/unordered_map/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <unordered_map>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/23_containers/headers/unordered_set/std_c++0x_neg.cc b/libstdc++-v3/testsuite/23_containers/headers/unordered_set/std_c++0x_neg.cc
index bc6963c80d0..85aca13c344 100644
--- a/libstdc++-v3/testsuite/23_containers/headers/unordered_set/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/headers/unordered_set/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <unordered_set>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
index 974821f0e52..6349ea2ca4e 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1549 }
+// { dg-error "no matching" "" { target *-*-* } 1551 }
#include <list>
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
index 6683e78062d..12f28fffd0f 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1505 }
+// { dg-error "no matching" "" { target *-*-* } 1507 }
#include <list>
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
index f3e70098ea0..05993340af9 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1505 }
+// { dg-error "no matching" "" { target *-*-* } 1507 }
#include <list>
#include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
index 7e19c4205dc..22acf3ad82d 100644
--- a/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1505 }
+// { dg-error "no matching" "" { target *-*-* } 1507 }
#include <list>
diff --git a/libstdc++-v3/testsuite/23_containers/map/operations/count.cc b/libstdc++-v3/testsuite/23_containers/map/operations/count.cc
new file mode 100644
index 00000000000..dfbaee6eda4
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/map/operations/count.cc
@@ -0,0 +1,106 @@
+// 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include <map>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ typedef map<int, int>::value_type value_type;
+
+ map<int, int> m0;
+ VERIFY( m0.count(0) == 0 );
+ VERIFY( m0.count(1) == 0 );
+
+ m0.insert(value_type(1, 1));
+ VERIFY( m0.count(0) == 0 );
+ VERIFY( m0.count(1) == 1 );
+
+ m0.insert(value_type(1, 2));
+ VERIFY( m0.count(0) == 0 );
+ VERIFY( m0.count(1) == 1 );
+
+ m0.insert(value_type(2, 1));
+ VERIFY( m0.count(2) == 1 );
+
+ m0.insert(value_type(3, 1));
+ m0.insert(value_type(3, 2));
+ m0.insert(value_type(3, 3));
+ VERIFY( m0.count(3) == 1 );
+
+ m0.erase(2);
+ VERIFY( m0.count(2) == 0 );
+
+ m0.erase(0);
+ VERIFY( m0.count(0) == 0 );
+
+ map<int, int> m1(m0);
+ VERIFY( m1.count(0) == 0 );
+ VERIFY( m1.count(1) == 1 );
+ VERIFY( m1.count(2) == 0 );
+ VERIFY( m1.count(3) == 1 );
+
+ m0.clear();
+ VERIFY( m0.count(0) == 0 );
+ VERIFY( m0.count(1) == 0 );
+ VERIFY( m0.count(2) == 0 );
+ VERIFY( m0.count(3) == 0 );
+
+ m1.insert(value_type(4, 1));
+ m1.insert(value_type(5, 1));
+ m1.insert(value_type(5, 2));
+ m1.insert(value_type(5, 3));
+ m1.insert(value_type(5, 4));
+ VERIFY( m1.count(4) == 1 );
+ VERIFY( m1.count(5) == 1 );
+
+ m1.erase(1);
+ VERIFY( m1.count(1) == 0 );
+
+ m1.erase(m1.find(5));
+ VERIFY( m1.count(5) == 0 );
+
+ m1.insert(value_type(1, 1));
+ m1.insert(value_type(1, 2));
+ VERIFY( m1.count(1) == 1 );
+
+ m1.erase(5);
+ VERIFY( m1.count(5) == 0 );
+
+ m1.erase(m1.find(4));
+ VERIFY( m1.count(4) == 0 );
+
+ m1.clear();
+ VERIFY( m1.count(0) == 0 );
+ VERIFY( m1.count(1) == 0 );
+ VERIFY( m1.count(2) == 0 );
+ VERIFY( m1.count(3) == 0 );
+ VERIFY( m1.count(4) == 0 );
+ VERIFY( m1.count(5) == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multimap/operations/count.cc b/libstdc++-v3/testsuite/23_containers/multimap/operations/count.cc
new file mode 100644
index 00000000000..2658615776e
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/multimap/operations/count.cc
@@ -0,0 +1,106 @@
+// 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include <map>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ typedef multimap<int, int>::value_type value_type;
+
+ multimap<int, int> mm0;
+ VERIFY( mm0.count(0) == 0 );
+ VERIFY( mm0.count(1) == 0 );
+
+ mm0.insert(value_type(1, 1));
+ VERIFY( mm0.count(0) == 0 );
+ VERIFY( mm0.count(1) == 1 );
+
+ mm0.insert(value_type(1, 2));
+ VERIFY( mm0.count(0) == 0 );
+ VERIFY( mm0.count(1) == 2 );
+
+ mm0.insert(value_type(2, 1));
+ VERIFY( mm0.count(2) == 1 );
+
+ mm0.insert(value_type(3, 1));
+ mm0.insert(value_type(3, 2));
+ mm0.insert(value_type(3, 3));
+ VERIFY( mm0.count(3) == 3 );
+
+ mm0.erase(2);
+ VERIFY( mm0.count(2) == 0 );
+
+ mm0.erase(0);
+ VERIFY( mm0.count(0) == 0 );
+
+ multimap<int, int> mm1(mm0);
+ VERIFY( mm1.count(0) == 0 );
+ VERIFY( mm1.count(1) == 2 );
+ VERIFY( mm1.count(2) == 0 );
+ VERIFY( mm1.count(3) == 3 );
+
+ mm0.clear();
+ VERIFY( mm0.count(0) == 0 );
+ VERIFY( mm0.count(1) == 0 );
+ VERIFY( mm0.count(2) == 0 );
+ VERIFY( mm0.count(3) == 0 );
+
+ mm1.insert(value_type(4, 1));
+ mm1.insert(value_type(5, 1));
+ mm1.insert(value_type(5, 2));
+ mm1.insert(value_type(5, 3));
+ mm1.insert(value_type(5, 4));
+ VERIFY( mm1.count(4) == 1 );
+ VERIFY( mm1.count(5) == 4 );
+
+ mm1.erase(1);
+ VERIFY( mm1.count(1) == 0 );
+
+ mm1.erase(mm1.find(5));
+ VERIFY( mm1.count(5) == 3 );
+
+ mm1.insert(value_type(1, 1));
+ mm1.insert(value_type(1, 2));
+ VERIFY( mm1.count(1) == 2 );
+
+ mm1.erase(5);
+ VERIFY( mm1.count(5) == 0 );
+
+ mm1.erase(mm1.find(4));
+ VERIFY( mm1.count(4) == 0 );
+
+ mm1.clear();
+ VERIFY( mm1.count(0) == 0 );
+ VERIFY( mm1.count(1) == 0 );
+ VERIFY( mm1.count(2) == 0 );
+ VERIFY( mm1.count(3) == 0 );
+ VERIFY( mm1.count(4) == 0 );
+ VERIFY( mm1.count(5) == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/operations/count.cc b/libstdc++-v3/testsuite/23_containers/multiset/operations/count.cc
new file mode 100644
index 00000000000..96323877c49
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/multiset/operations/count.cc
@@ -0,0 +1,104 @@
+// 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include <set>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ multiset<int> ms0;
+ VERIFY( ms0.count(0) == 0 );
+ VERIFY( ms0.count(1) == 0 );
+
+ ms0.insert(1);
+ VERIFY( ms0.count(0) == 0 );
+ VERIFY( ms0.count(1) == 1 );
+
+ ms0.insert(1);
+ VERIFY( ms0.count(0) == 0 );
+ VERIFY( ms0.count(1) == 2 );
+
+ ms0.insert(2);
+ VERIFY( ms0.count(2) == 1 );
+
+ ms0.insert(3);
+ ms0.insert(3);
+ ms0.insert(3);
+ VERIFY( ms0.count(3) == 3 );
+
+ ms0.erase(2);
+ VERIFY( ms0.count(2) == 0 );
+
+ ms0.erase(0);
+ VERIFY( ms0.count(0) == 0 );
+
+ multiset<int> ms1(ms0);
+ VERIFY( ms1.count(0) == 0 );
+ VERIFY( ms1.count(1) == 2 );
+ VERIFY( ms1.count(2) == 0 );
+ VERIFY( ms1.count(3) == 3 );
+
+ ms0.clear();
+ VERIFY( ms0.count(0) == 0 );
+ VERIFY( ms0.count(1) == 0 );
+ VERIFY( ms0.count(2) == 0 );
+ VERIFY( ms0.count(3) == 0 );
+
+ ms1.insert(4);
+ ms1.insert(5);
+ ms1.insert(5);
+ ms1.insert(5);
+ ms1.insert(5);
+ VERIFY( ms1.count(4) == 1 );
+ VERIFY( ms1.count(5) == 4 );
+
+ ms1.erase(1);
+ VERIFY( ms1.count(1) == 0 );
+
+ ms1.erase(ms1.find(5));
+ VERIFY( ms1.count(5) == 3 );
+
+ ms1.insert(1);
+ ms1.insert(1);
+ VERIFY( ms1.count(1) == 2 );
+
+ ms1.erase(5);
+ VERIFY( ms1.count(5) == 0 );
+
+ ms1.erase(ms1.find(4));
+ VERIFY( ms1.count(4) == 0 );
+
+ ms1.clear();
+ VERIFY( ms1.count(0) == 0 );
+ VERIFY( ms1.count(1) == 0 );
+ VERIFY( ms1.count(2) == 0 );
+ VERIFY( ms1.count(3) == 0 );
+ VERIFY( ms1.count(4) == 0 );
+ VERIFY( ms1.count(5) == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/set/operations/count.cc b/libstdc++-v3/testsuite/23_containers/set/operations/count.cc
new file mode 100644
index 00000000000..4a6b0f2683f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/set/operations/count.cc
@@ -0,0 +1,104 @@
+// 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include <set>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ set<int> s0;
+ VERIFY( s0.count(0) == 0 );
+ VERIFY( s0.count(1) == 0 );
+
+ s0.insert(1);
+ VERIFY( s0.count(0) == 0 );
+ VERIFY( s0.count(1) == 1 );
+
+ s0.insert(1);
+ VERIFY( s0.count(0) == 0 );
+ VERIFY( s0.count(1) == 1 );
+
+ s0.insert(2);
+ VERIFY( s0.count(2) == 1 );
+
+ s0.insert(3);
+ s0.insert(3);
+ s0.insert(3);
+ VERIFY( s0.count(3) == 1 );
+
+ s0.erase(2);
+ VERIFY( s0.count(2) == 0 );
+
+ s0.erase(0);
+ VERIFY( s0.count(0) == 0 );
+
+ set<int> s1(s0);
+ VERIFY( s1.count(0) == 0 );
+ VERIFY( s1.count(1) == 1 );
+ VERIFY( s1.count(2) == 0 );
+ VERIFY( s1.count(3) == 1 );
+
+ s0.clear();
+ VERIFY( s0.count(0) == 0 );
+ VERIFY( s0.count(1) == 0 );
+ VERIFY( s0.count(2) == 0 );
+ VERIFY( s0.count(3) == 0 );
+
+ s1.insert(4);
+ s1.insert(5);
+ s1.insert(5);
+ s1.insert(5);
+ s1.insert(5);
+ VERIFY( s1.count(4) == 1 );
+ VERIFY( s1.count(5) == 1 );
+
+ s1.erase(1);
+ VERIFY( s1.count(1) == 0 );
+
+ s1.erase(s1.find(5));
+ VERIFY( s1.count(5) == 0 );
+
+ s1.insert(1);
+ s1.insert(1);
+ VERIFY( s1.count(1) == 1 );
+
+ s1.erase(5);
+ VERIFY( s1.count(5) == 0 );
+
+ s1.erase(s1.find(4));
+ VERIFY( s1.count(4) == 0 );
+
+ s1.clear();
+ VERIFY( s1.count(0) == 0 );
+ VERIFY( s1.count(1) == 0 );
+ VERIFY( s1.count(2) == 0 );
+ VERIFY( s1.count(3) == 0 );
+ VERIFY( s1.count(4) == 0 );
+ VERIFY( s1.count(5) == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/operations/count.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/operations/count.cc
new file mode 100644
index 00000000000..4aedc5e1e11
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/operations/count.cc
@@ -0,0 +1,108 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include <unordered_map>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ typedef unordered_map<int, int>::value_type value_type;
+
+ unordered_map<int, int> um0;
+ VERIFY( um0.count(0) == 0 );
+ VERIFY( um0.count(1) == 0 );
+
+ um0.insert(value_type(1, 1));
+ VERIFY( um0.count(0) == 0 );
+ VERIFY( um0.count(1) == 1 );
+
+ um0.insert(value_type(1, 2));
+ VERIFY( um0.count(0) == 0 );
+ VERIFY( um0.count(1) == 1 );
+
+ um0.insert(value_type(2, 1));
+ VERIFY( um0.count(2) == 1 );
+
+ um0.insert(value_type(3, 1));
+ um0.insert(value_type(3, 2));
+ um0.insert(value_type(3, 3));
+ VERIFY( um0.count(3) == 1 );
+
+ um0.erase(2);
+ VERIFY( um0.count(2) == 0 );
+
+ um0.erase(0);
+ VERIFY( um0.count(0) == 0 );
+
+ unordered_map<int, int> um1(um0);
+ VERIFY( um1.count(0) == 0 );
+ VERIFY( um1.count(1) == 1 );
+ VERIFY( um1.count(2) == 0 );
+ VERIFY( um1.count(3) == 1 );
+
+ um0.clear();
+ VERIFY( um0.count(0) == 0 );
+ VERIFY( um0.count(1) == 0 );
+ VERIFY( um0.count(2) == 0 );
+ VERIFY( um0.count(3) == 0 );
+
+ um1.insert(value_type(4, 1));
+ um1.insert(value_type(5, 1));
+ um1.insert(value_type(5, 2));
+ um1.insert(value_type(5, 3));
+ um1.insert(value_type(5, 4));
+ VERIFY( um1.count(4) == 1 );
+ VERIFY( um1.count(5) == 1 );
+
+ um1.erase(1);
+ VERIFY( um1.count(1) == 0 );
+
+ um1.erase(um1.find(5));
+ VERIFY( um1.count(5) == 0 );
+
+ um1.insert(value_type(1, 1));
+ um1.insert(value_type(1, 2));
+ VERIFY( um1.count(1) == 1 );
+
+ um1.erase(5);
+ VERIFY( um1.count(5) == 0 );
+
+ um1.erase(um1.find(4));
+ VERIFY( um1.count(4) == 0 );
+
+ um1.clear();
+ VERIFY( um1.count(0) == 0 );
+ VERIFY( um1.count(1) == 0 );
+ VERIFY( um1.count(2) == 0 );
+ VERIFY( um1.count(3) == 0 );
+ VERIFY( um1.count(4) == 0 );
+ VERIFY( um1.count(5) == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/operations/count.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/operations/count.cc
new file mode 100644
index 00000000000..12f9e1f5ebc
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/operations/count.cc
@@ -0,0 +1,108 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include <unordered_map>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ typedef unordered_multimap<int, int>::value_type value_type;
+
+ unordered_multimap<int, int> umm0;
+ VERIFY( umm0.count(0) == 0 );
+ VERIFY( umm0.count(1) == 0 );
+
+ umm0.insert(value_type(1, 1));
+ VERIFY( umm0.count(0) == 0 );
+ VERIFY( umm0.count(1) == 1 );
+
+ umm0.insert(value_type(1, 2));
+ VERIFY( umm0.count(0) == 0 );
+ VERIFY( umm0.count(1) == 2 );
+
+ umm0.insert(value_type(2, 1));
+ VERIFY( umm0.count(2) == 1 );
+
+ umm0.insert(value_type(3, 1));
+ umm0.insert(value_type(3, 2));
+ umm0.insert(value_type(3, 3));
+ VERIFY( umm0.count(3) == 3 );
+
+ umm0.erase(2);
+ VERIFY( umm0.count(2) == 0 );
+
+ umm0.erase(0);
+ VERIFY( umm0.count(0) == 0 );
+
+ unordered_multimap<int, int> umm1(umm0);
+ VERIFY( umm1.count(0) == 0 );
+ VERIFY( umm1.count(1) == 2 );
+ VERIFY( umm1.count(2) == 0 );
+ VERIFY( umm1.count(3) == 3 );
+
+ umm0.clear();
+ VERIFY( umm0.count(0) == 0 );
+ VERIFY( umm0.count(1) == 0 );
+ VERIFY( umm0.count(2) == 0 );
+ VERIFY( umm0.count(3) == 0 );
+
+ umm1.insert(value_type(4, 1));
+ umm1.insert(value_type(5, 1));
+ umm1.insert(value_type(5, 2));
+ umm1.insert(value_type(5, 3));
+ umm1.insert(value_type(5, 4));
+ VERIFY( umm1.count(4) == 1 );
+ VERIFY( umm1.count(5) == 4 );
+
+ umm1.erase(1);
+ VERIFY( umm1.count(1) == 0 );
+
+ umm1.erase(umm1.find(5));
+ VERIFY( umm1.count(5) == 3 );
+
+ umm1.insert(value_type(1, 1));
+ umm1.insert(value_type(1, 2));
+ VERIFY( umm1.count(1) == 2 );
+
+ umm1.erase(5);
+ VERIFY( umm1.count(5) == 0 );
+
+ umm1.erase(umm1.find(4));
+ VERIFY( umm1.count(4) == 0 );
+
+ umm1.clear();
+ VERIFY( umm1.count(0) == 0 );
+ VERIFY( umm1.count(1) == 0 );
+ VERIFY( umm1.count(2) == 0 );
+ VERIFY( umm1.count(3) == 0 );
+ VERIFY( umm1.count(4) == 0 );
+ VERIFY( umm1.count(5) == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/operations/count.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/operations/count.cc
new file mode 100644
index 00000000000..17c37f82ed7
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/operations/count.cc
@@ -0,0 +1,106 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include <unordered_set>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ unordered_multiset<int> ums0;
+ VERIFY( ums0.count(0) == 0 );
+ VERIFY( ums0.count(1) == 0 );
+
+ ums0.insert(1);
+ VERIFY( ums0.count(0) == 0 );
+ VERIFY( ums0.count(1) == 1 );
+
+ ums0.insert(1);
+ VERIFY( ums0.count(0) == 0 );
+ VERIFY( ums0.count(1) == 2 );
+
+ ums0.insert(2);
+ VERIFY( ums0.count(2) == 1 );
+
+ ums0.insert(3);
+ ums0.insert(3);
+ ums0.insert(3);
+ VERIFY( ums0.count(3) == 3 );
+
+ ums0.erase(2);
+ VERIFY( ums0.count(2) == 0 );
+
+ ums0.erase(0);
+ VERIFY( ums0.count(0) == 0 );
+
+ unordered_multiset<int> ums1(ums0);
+ VERIFY( ums1.count(0) == 0 );
+ VERIFY( ums1.count(1) == 2 );
+ VERIFY( ums1.count(2) == 0 );
+ VERIFY( ums1.count(3) == 3 );
+
+ ums0.clear();
+ VERIFY( ums0.count(0) == 0 );
+ VERIFY( ums0.count(1) == 0 );
+ VERIFY( ums0.count(2) == 0 );
+ VERIFY( ums0.count(3) == 0 );
+
+ ums1.insert(4);
+ ums1.insert(5);
+ ums1.insert(5);
+ ums1.insert(5);
+ ums1.insert(5);
+ VERIFY( ums1.count(4) == 1 );
+ VERIFY( ums1.count(5) == 4 );
+
+ ums1.erase(1);
+ VERIFY( ums1.count(1) == 0 );
+
+ ums1.erase(ums1.find(5));
+ VERIFY( ums1.count(5) == 3 );
+
+ ums1.insert(1);
+ ums1.insert(1);
+ VERIFY( ums1.count(1) == 2 );
+
+ ums1.erase(5);
+ VERIFY( ums1.count(5) == 0 );
+
+ ums1.erase(ums1.find(4));
+ VERIFY( ums1.count(4) == 0 );
+
+ ums1.clear();
+ VERIFY( ums1.count(0) == 0 );
+ VERIFY( ums1.count(1) == 0 );
+ VERIFY( ums1.count(2) == 0 );
+ VERIFY( ums1.count(3) == 0 );
+ VERIFY( ums1.count(4) == 0 );
+ VERIFY( ums1.count(5) == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/operations/count.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/operations/count.cc
new file mode 100644
index 00000000000..942338f9e5a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/operations/count.cc
@@ -0,0 +1,106 @@
+// { dg-options "-std=gnu++0x" }
+
+// 2011-10-28 Paolo Carlini <paolo.carlini@oracle.com>
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+//
+
+#include <unordered_set>
+#include <testsuite_hooks.h>
+
+void test01()
+{
+ bool test __attribute__((unused)) = true;
+ using namespace std;
+
+ unordered_set<int> us0;
+ VERIFY( us0.count(0) == 0 );
+ VERIFY( us0.count(1) == 0 );
+
+ us0.insert(1);
+ VERIFY( us0.count(0) == 0 );
+ VERIFY( us0.count(1) == 1 );
+
+ us0.insert(1);
+ VERIFY( us0.count(0) == 0 );
+ VERIFY( us0.count(1) == 1 );
+
+ us0.insert(2);
+ VERIFY( us0.count(2) == 1 );
+
+ us0.insert(3);
+ us0.insert(3);
+ us0.insert(3);
+ VERIFY( us0.count(3) == 1 );
+
+ us0.erase(2);
+ VERIFY( us0.count(2) == 0 );
+
+ us0.erase(0);
+ VERIFY( us0.count(0) == 0 );
+
+ unordered_set<int> us1(us0);
+ VERIFY( us1.count(0) == 0 );
+ VERIFY( us1.count(1) == 1 );
+ VERIFY( us1.count(2) == 0 );
+ VERIFY( us1.count(3) == 1 );
+
+ us0.clear();
+ VERIFY( us0.count(0) == 0 );
+ VERIFY( us0.count(1) == 0 );
+ VERIFY( us0.count(2) == 0 );
+ VERIFY( us0.count(3) == 0 );
+
+ us1.insert(4);
+ us1.insert(5);
+ us1.insert(5);
+ us1.insert(5);
+ us1.insert(5);
+ VERIFY( us1.count(4) == 1 );
+ VERIFY( us1.count(5) == 1 );
+
+ us1.erase(1);
+ VERIFY( us1.count(1) == 0 );
+
+ us1.erase(us1.find(5));
+ VERIFY( us1.count(5) == 0 );
+
+ us1.insert(1);
+ us1.insert(1);
+ VERIFY( us1.count(1) == 1 );
+
+ us1.erase(5);
+ VERIFY( us1.count(5) == 0 );
+
+ us1.erase(us1.find(4));
+ VERIFY( us1.count(4) == 0 );
+
+ us1.clear();
+ VERIFY( us1.count(0) == 0 );
+ VERIFY( us1.count(1) == 0 );
+ VERIFY( us1.count(2) == 0 );
+ VERIFY( us1.count(3) == 0 );
+ VERIFY( us1.count(4) == 0 );
+ VERIFY( us1.count(5) == 0 );
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
index 00d18b74fd5..1855fddafbd 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1223 }
+// { dg-error "no matching" "" { target *-*-* } 1225 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
index 34c2ed1c6a8..9c05486e35b 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1153 }
+// { dg-error "no matching" "" { target *-*-* } 1155 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
index 563def0e666..152393c15dc 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1153 }
+// { dg-error "no matching" "" { target *-*-* } 1155 }
#include <vector>
#include <utility>
diff --git a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
index fec41a39fdb..f44ae63eb99 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc
@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1264 }
+// { dg-error "no matching" "" { target *-*-* } 1266 }
#include <vector>
diff --git a/libstdc++-v3/testsuite/26_numerics/complex/50880.cc b/libstdc++-v3/testsuite/26_numerics/complex/50880.cc
new file mode 100644
index 00000000000..2b70a99ddca
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/complex/50880.cc
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <testsuite_hooks.h>
+
+template<typename T>
+ void test01_do()
+ {
+ bool test __attribute__((unused)) = true;
+
+ const std::complex<T> ca(T(-2), T(2));
+ const std::complex<T> cb(T(-2), T(0));
+ const std::complex<T> cc(T(-2), T(-2));
+
+ std::complex<T> cra = std::acosh(ca);
+ std::complex<T> crb = std::acosh(cb);
+ std::complex<T> crc = std::acosh(cc);
+
+ VERIFY( cra.real() > T(0) );
+ VERIFY( crb.real() > T(0) );
+ VERIFY( crc.real() > T(0) );
+ }
+
+// libstdc++/50880
+void test01()
+{
+ test01_do<float>();
+ test01_do<double>();
+ test01_do<long double>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc b/libstdc++-v3/testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc
index 29e8dac5fa4..2f1226f3e17 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <ccomplex>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cfenv/std_c++0x_neg.cc b/libstdc++-v3/testsuite/26_numerics/headers/cfenv/std_c++0x_neg.cc
index 3a191069207..36e19d05af9 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/cfenv/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cfenv/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <cfenv>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc b/libstdc++-v3/testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc
index 23b266e8562..b8238df9591 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <ctgmath>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/random/std_c++0x_neg.cc b/libstdc++-v3/testsuite/26_numerics/headers/random/std_c++0x_neg.cc
index 1f83cdac692..467caa0736c 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/random/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/random/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <random>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/operators/serialize.cc
index 7aec649c03b..4249d975a82 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/operators/serialize.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/operators/serialize.cc
@@ -3,7 +3,7 @@
//
// 2008-11-24 Edward M. Smith-Rowland <3dw4rd@verizon.net>
//
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -46,6 +46,20 @@ test01()
str >> v;
VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
+
+ str.clear();
+ str << v;
+
+ u();
+ u();
+ u();
+
+ str >> u;
+ VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
}
int main()
diff --git a/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/operators/serialize.cc
index 332931addfa..32a5157608c 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/operators/serialize.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/operators/serialize.cc
@@ -3,7 +3,7 @@
//
// 2008-11-24 Edward M. Smith-Rowland <3dw4rd@verizon.net>
//
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -44,6 +44,20 @@ test01()
str >> v;
VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
+
+ str.clear();
+ str << v;
+
+ u();
+ u();
+ u();
+
+ str >> u;
+ VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
}
int main()
diff --git a/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/operators/serialize.cc
index 8b67e5f3a33..a83b22ef651 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/operators/serialize.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/operators/serialize.cc
@@ -3,7 +3,7 @@
//
// 2008-11-24 Edward M. Smith-Rowland <3dw4rd@verizon.net>
//
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -33,15 +33,29 @@ test01()
bool test __attribute__((unused)) = true;
std::stringstream str;
- std::minstd_rand0 a;
- std::minstd_rand0 b;
+ std::minstd_rand0 u;
+ std::minstd_rand0 v;
- a(); // advance
- str << a;
- VERIFY( !(a == b) );
+ u(); // advance
+ str << u;
+ VERIFY( !(u == v) );
- str >> b;
- VERIFY( a == b );
+ str >> v;
+ VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
+
+ str.clear();
+ str << v;
+
+ u();
+ u();
+ u();
+
+ str >> u;
+ VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
}
int main()
diff --git a/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/operators/serialize.cc
index 03fb8b04fa1..7c90e3d390f 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/operators/serialize.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/operators/serialize.cc
@@ -3,7 +3,7 @@
//
// 2008-11-24 Edward M. Smith-Rowland <3dw4rd@verizon.net>
//
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -47,6 +47,20 @@ test01()
str >> v;
VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
+
+ str.clear();
+ str << v;
+
+ u();
+ u();
+ u();
+
+ str >> u;
+ VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
}
int main()
diff --git a/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/operators/serialize.cc
index 578e4959371..c7b15d1ba15 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/operators/serialize.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/shuffle_order_engine/operators/serialize.cc
@@ -3,7 +3,7 @@
//
// 2008-11-24 Edward M. Smith-Rowland <3dw4rd@verizon.net>
//
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -46,6 +46,20 @@ test01()
str >> v;
VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
+
+ str.clear();
+ str << v;
+
+ u();
+ u();
+ u();
+
+ str >> u;
+ VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
}
int main()
diff --git a/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/operators/serialize.cc b/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/operators/serialize.cc
index e4129fc8df5..1e2e53ac593 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/operators/serialize.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/operators/serialize.cc
@@ -3,7 +3,7 @@
//
// 2008-11-24 Edward M. Smith-Rowland <3dw4rd@verizon.net>
//
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -43,6 +43,20 @@ test01()
str >> v;
VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
+
+ str.clear();
+ str << v;
+
+ u();
+ u();
+ u();
+
+ str >> u;
+ VERIFY( u == v );
+ for (unsigned i = 0; i < 1000; ++i)
+ VERIFY( u() == v() );
}
int main()
diff --git a/libstdc++-v3/testsuite/27_io/headers/cinttypes/std_c++0x_neg.cc b/libstdc++-v3/testsuite/27_io/headers/cinttypes/std_c++0x_neg.cc
index 21da0770b9b..0285417ab12 100644
--- a/libstdc++-v3/testsuite/27_io/headers/cinttypes/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/27_io/headers/cinttypes/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <cinttypes>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/28_regex/headers/regex/std_c++0x_neg.cc b/libstdc++-v3/testsuite/28_regex/headers/regex/std_c++0x_neg.cc
index 21a98b8ae69..b5289f802b6 100644
--- a/libstdc++-v3/testsuite/28_regex/headers/regex/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/28_regex/headers/regex/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <regex>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/29_atomics/headers/atomic/std_c++0x_neg.cc b/libstdc++-v3/testsuite/29_atomics/headers/atomic/std_c++0x_neg.cc
index be390b0f71c..38b49b6db11 100644
--- a/libstdc++-v3/testsuite/29_atomics/headers/atomic/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/29_atomics/headers/atomic/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <atomic> // { dg-excess-errors "In file included from" }
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/30_threads/async/49668.cc b/libstdc++-v3/testsuite/30_threads/async/49668.cc
index 4d5bd0515ea..d17687b68db 100644
--- a/libstdc++-v3/testsuite/30_threads/async/49668.cc
+++ b/libstdc++-v3/testsuite/30_threads/async/49668.cc
@@ -4,6 +4,7 @@
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
// Copyright (C) 2011 Free Software Foundation, Inc.
//
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc
new file mode 100644
index 00000000000..b85a5e13626
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/condition_variable_any/50862.cc
@@ -0,0 +1,80 @@
+// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-sched-yield "" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <condition_variable>
+#include <thread>
+#include <mutex>
+#include <array>
+#include <sstream>
+
+struct scoped_thread
+{
+ ~scoped_thread() { if (t.joinable()) t.join(); }
+ std::thread t;
+};
+
+int main()
+{
+ typedef std::unique_lock<std::mutex> Lock;
+
+ std::mutex m;
+ std::condition_variable_any cond;
+ unsigned int product = 0;
+ const unsigned int count = 10;
+
+ // writing to stream causes timing changes which makes deadlock easier
+ // to reproduce - do not remove
+ std::ostringstream out;
+
+ // create consumers
+ std::array<scoped_thread, 2> threads;
+ for (std::size_t i = 0; i < threads.size(); ++i)
+ threads[i].t
+ = std::thread( [&]
+ {
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ std::this_thread::yield();
+ Lock lock(m);
+ while(product == 0)
+ cond.wait(lock);
+ out << "got product "
+ << std::this_thread::get_id()
+ << ' ' << product << std::endl;
+ --product;
+ }
+ } );
+
+ // single producer
+ for (std::size_t i = 0; i < threads.size() * count; ++i)
+ {
+ std::this_thread::yield();
+ Lock lock(m);
+ ++product;
+ out << "setting product " << std::this_thread::get_id()
+ << ' ' << product << std::endl;
+ cond.notify_one();
+ }
+}
diff --git a/libstdc++-v3/testsuite/30_threads/condition_variable_any/requirements/typedefs.cc b/libstdc++-v3/testsuite/30_threads/condition_variable_any/requirements/typedefs.cc
deleted file mode 100644
index 8a6fd82ccf6..00000000000
--- a/libstdc++-v3/testsuite/30_threads/condition_variable_any/requirements/typedefs.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// { dg-do compile }
-// { dg-options "-std=gnu++0x" }
-// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
-
-// Copyright (C) 2010 Free Software Foundation, Inc.
-//
-// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
-// any later version.
-
-// This library 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 library; see the file COPYING3. If not see
-// <http://www.gnu.org/licenses/>.
-
-#include <condition_variable>
-
-void test01()
-{
- // Check for required typedefs
- typedef std::condition_variable_any test_type;
- typedef test_type::native_handle_type type;
-}
diff --git a/libstdc++-v3/testsuite/30_threads/headers/condition_variable/std_c++0x_neg.cc b/libstdc++-v3/testsuite/30_threads/headers/condition_variable/std_c++0x_neg.cc
index 6e345243c26..5df33d943a9 100644
--- a/libstdc++-v3/testsuite/30_threads/headers/condition_variable/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/headers/condition_variable/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <condition_variable>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/30_threads/headers/future/std_c++0x_neg.cc b/libstdc++-v3/testsuite/30_threads/headers/future/std_c++0x_neg.cc
index 5dbaffdefd9..ec018f73639 100644
--- a/libstdc++-v3/testsuite/30_threads/headers/future/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/headers/future/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <future>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/30_threads/headers/mutex/std_c++0x_neg.cc b/libstdc++-v3/testsuite/30_threads/headers/mutex/std_c++0x_neg.cc
index 31bf41c06a5..3d7a09d829a 100644
--- a/libstdc++-v3/testsuite/30_threads/headers/mutex/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/headers/mutex/std_c++0x_neg.cc
@@ -20,7 +20,7 @@
#include <mutex>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/30_threads/headers/thread/std_c++0x_neg.cc b/libstdc++-v3/testsuite/30_threads/headers/thread/std_c++0x_neg.cc
index cc8a3877dec..6089f33171a 100644
--- a/libstdc++-v3/testsuite/30_threads/headers/thread/std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/headers/thread/std_c++0x_neg.cc
@@ -22,4 +22,4 @@
#include <thread>
-// { dg-error "upcoming ISO" "" { target *-*-* } 32 }
+// { dg-error "ISO C.. 2011" "" { target *-*-* } 32 }
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc
index 55a2f07c1e8..596e3d31e4e 100644
--- a/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/49668.cc
@@ -4,6 +4,7 @@
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
// Copyright (C) 2011 Free Software Foundation, Inc.
//
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc
new file mode 100644
index 00000000000..24ca72085fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/3.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-solaris* *-*-cygwin *-*-darwin* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* alpha*-*-osf* mips-sgi-irix6* } }
+// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// LWG 2067. packaged_task should have deleted copy c'tor with const parameter
+
+#include <future>
+#include <thread>
+#include <testsuite_hooks.h>
+
+template<typename F>
+std::future<typename std::result_of<F()>::type> spawn_task(F f)
+{
+ typedef typename std::result_of<F()>::type result_type;
+ std::packaged_task<result_type()> task(std::move(f));
+ std::future<result_type> res(task.get_future());
+ std::thread(std::move(task)).detach();
+ return res;
+}
+
+int get_res()
+{
+ return 42;
+}
+
+void test01()
+{
+ auto f = spawn_task(get_res);
+ VERIFY( f.get() == get_res() );
+}
+
+int main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc2.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc2.cc
new file mode 100644
index 00000000000..40d30705a63
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/cons/alloc2.cc
@@ -0,0 +1,40 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Test that packaged_task can be default-constructed or move-constructed
+// in a context that does uses-allocator construction.
+
+#include <future>
+#include <memory>
+#include <tuple>
+
+using std::packaged_task;
+using std::allocator_arg;
+using std::allocator;
+using std::tuple;
+
+typedef packaged_task<void()> task;
+allocator<task> a;
+
+tuple<task> t1{ allocator_arg, a };
+tuple<task> t2{ allocator_arg, a, task{} };
diff --git a/libstdc++-v3/testsuite/30_threads/promise/cons/alloc2.cc b/libstdc++-v3/testsuite/30_threads/promise/cons/alloc2.cc
new file mode 100644
index 00000000000..a22fd203438
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/promise/cons/alloc2.cc
@@ -0,0 +1,42 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// Test that promise can be default-constructed or move-constructed
+// in a context that does uses-allocator construction.
+
+#include <future>
+#include <memory>
+#include <tuple>
+
+using std::promise;
+using std::allocator_arg;
+using std::allocator;
+using std::tuple;
+
+typedef promise<int> p;
+typedef promise<int&> pr;
+typedef promise<void> pv;
+allocator<p> a;
+
+tuple<p, pr, pv> t1{ allocator_arg, a };
+tuple<p, pr, pv> t2{ allocator_arg, a, p{}, pr{}, pv{} };
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc
index cc257956ce0..ace63b3e209 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc
index 1694423cb1f..291a469d6b8 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/assign_neg.cc
@@ -1,9 +1,9 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc
index c729d5b76a2..6c7d31cae4c 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/cons/copy_neg.cc
@@ -1,9 +1,9 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc
index 8442fbfa528..26f95b3ea4b 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/dest/destructor_locked.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc
index 2fc97e019ff..d57f97cff49 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc
index c725b63b634..29fc4c37edf 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/lock/2.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc
index 96e64f34c71..89554e0bb65 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc
index d2fd9f6e0e5..76fd2a73e37 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/native_handle/typesizes.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2009 Free Software Foundation, Inc.
+// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/requirements/typedefs.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/requirements/typedefs.cc
index 46a27d6da3e..cb70ab3f068 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/requirements/typedefs.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/requirements/typedefs.cc
@@ -1,11 +1,11 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
// 2008-03-18 Benjamin Kosnik <bkoz@redhat.com>
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc
index d61f821c691..c7b8720cab6 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc
index 0e95bab943d..f479d9db241 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock/2.cc
@@ -3,9 +3,9 @@
// { dg-options "-std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options "-std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc
index d4e7d0a2f91..7a87cafd7ae 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc
index 207cad6ace7..950e9f2f3f1 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/2.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc
index d4a93484b26..f05000ad39a 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_for/3.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc
index d61f821c691..c7b8720cab6 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc
index 911686c76ad..ca16b398316 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/try_lock_until/2.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc
index a1e4458f28c..2b1a4e55c7b 100644
--- a/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/recursive_timed_mutex/unlock/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc
index 5f122c21f4c..aa8a684c395 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/assign_neg.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/assign_neg.cc
index 7c9199f321b..220f29af7dd 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/assign_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/assign_neg.cc
@@ -1,9 +1,9 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/copy_neg.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/copy_neg.cc
index 2c388962e45..b2c33dbbef7 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/copy_neg.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/cons/copy_neg.cc
@@ -1,9 +1,9 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc
index 2e4d42bbbf3..4eb457f810b 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/dest/destructor_locked.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc
index b7223ee585a..69c5c24b270 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/lock/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc
index dc5c60964c1..9292bdce58a 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc
index 56f98b1004f..ad010e8f624 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/native_handle/typesizes.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2009 Free Software Foundation, Inc.
+// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/standard_layout.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/standard_layout.cc
index 2da736ed14d..763fec2b9ad 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/standard_layout.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/standard_layout.cc
@@ -1,9 +1,9 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2009 Free Software Foundation, Inc.
+// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/typedefs.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/typedefs.cc
index f8a2851e72d..820d22a32a2 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/typedefs.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/requirements/typedefs.cc
@@ -1,11 +1,11 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
// 2008-07-23 Chris Fairles <chris.fairles@gmail.com>
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc
index 16aed125656..3a699255228 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc
index e12a706afbc..8cf2fc7eac6 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock/2.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc
index a40fd6ab085..5227341d859 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc
index 77fead751df..35fc0043799 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/2.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc
index 7a5e42d4fb1..a39daa82d54 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_for/3.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc
index 16aed125656..3a699255228 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc
index e12a706afbc..8cf2fc7eac6 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/try_lock_until/2.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc b/libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc
index 5706bcc191d..be3386fd55c 100644
--- a/libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/timed_mutex/unlock/1.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc
index 100a2a76a29..f0c0d615c3a 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/5.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc
index 049eaa56e1e..e6c7b8d3bd6 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/cons/6.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc
index bb0bd0d700c..b0d0075b283 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/3.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc
index a5e9581a6fd..1e60a549318 100644
--- a/libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc
+++ b/libstdc++-v3/testsuite/30_threads/unique_lock/locking/4.cc
@@ -3,9 +3,9 @@
// { dg-options " -std=gnu++0x -pthreads" { target *-*-solaris* } }
// { dg-options " -std=gnu++0x " { target *-*-cygwin *-*-darwin* } }
// { dg-require-cstdint "" }
-// { dg-require-gthreads "" }
+// { dg-require-gthreads-timed "" }
-// Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
diff --git a/libstdc++-v3/testsuite/Makefile.in b/libstdc++-v3/testsuite/Makefile.in
index 37e8a3cf675..af161ea5d26 100644
--- a/libstdc++-v3/testsuite/Makefile.in
+++ b/libstdc++-v3/testsuite/Makefile.in
@@ -213,7 +213,6 @@ glibcxx_builddir = @glibcxx_builddir@
glibcxx_localedir = @glibcxx_localedir@
glibcxx_prefixdir = @glibcxx_prefixdir@
glibcxx_srcdir = @glibcxx_srcdir@
-glibcxx_thread_h = @glibcxx_thread_h@
glibcxx_toolexecdir = @glibcxx_toolexecdir@
glibcxx_toolexeclibdir = @glibcxx_toolexeclibdir@
gxx_include_dir = @gxx_include_dir@
@@ -253,6 +252,7 @@ target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
+toplevel_builddir = @toplevel_builddir@
toplevel_srcdir = @toplevel_srcdir@
AUTOMAKE_OPTIONS = nostdinc
RUNTESTDEFAULTFLAGS = --tool $$tool --srcdir $$srcdir
diff --git a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
index ba515b7fb6b..c6e6feac6c0 100644
--- a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
+++ b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc
@@ -25,4 +25,4 @@
#include <vector>
-// { dg-error "multiple inlined namespaces" "" { target *-*-* } 256 }
+// { dg-error "multiple inlined namespaces" "" { target *-*-* } 263 }
diff --git a/libstdc++-v3/testsuite/lib/dg-options.exp b/libstdc++-v3/testsuite/lib/dg-options.exp
index 46d3ce9e71a..d5eb5e827ad 100644
--- a/libstdc++-v3/testsuite/lib/dg-options.exp
+++ b/libstdc++-v3/testsuite/lib/dg-options.exp
@@ -134,6 +134,15 @@ proc dg-require-gthreads { args } {
return
}
+proc dg-require-gthreads-timed { args } {
+ if { ![ check_v3_target_gthreads_timed ] } {
+ upvar dg-do-what dg-do-what
+ set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+ return
+ }
+ return
+}
+
proc dg-require-nanosleep { args } {
if { ![ check_v3_target_nanosleep ] } {
upvar dg-do-what dg-do-what
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index d39e8ea182c..b510c06126f 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -1299,6 +1299,66 @@ proc check_v3_target_gthreads { } {
return $et_gthreads
}
+proc check_v3_target_gthreads_timed { } {
+ global cxxflags
+ global DEFAULT_CXXFLAGS
+ global et_gthreads_timed
+
+ global tool
+
+ if { ![info exists et_gthreads_timed_target_name] } {
+ set et_gthreads_timed_target_name ""
+ }
+
+ # If the target has changed since we set the cached value, clear it.
+ set current_target [current_target_name]
+ if { $current_target != $et_gthreads_timed_target_name } {
+ verbose "check_v3_target_gthreads_timed: `$et_gthreads_timed_target_name'" 2
+ set et_gthreads_timed_target_name $current_target
+ if [info exists et_gthreads_timed] {
+ verbose "check_v3_target_gthreads_timed: removing cached result" 2
+ unset et_gthreads_timed
+ }
+ }
+
+ if [info exists et_gthreads_timed] {
+ verbose "check_v3_target_gthreads_timed: using cached result" 2
+ } else {
+ set et_gthreads_timed 0
+
+ # Set up and preprocess a C++0x test program that depends
+ # on the gthreads timed mutex facilities to be available.
+ set src gthreads_timed[pid].cc
+
+ set f [open $src "w"]
+ puts $f "#include <bits/c++config.h>"
+ puts $f "#ifndef _GLIBCXX_HAS_GTHREADS"
+ puts $f "# error No gthread"
+ puts $f "#endif"
+ puts $f "#if !_GTHREAD_USE_MUTEX_TIMEDLOCK"
+ puts $f "# error No gthread timed mutexes"
+ puts $f "#endif"
+ close $f
+
+ set cxxflags_saved $cxxflags
+ set cxxflags "$cxxflags $DEFAULT_CXXFLAGS -Werror"
+
+ set lines [v3_target_compile $src /dev/null preprocess ""]
+ set cxxflags $cxxflags_saved
+ file delete $src
+
+ if [string match "" $lines] {
+ # No error message, preprocessing succeeded.
+ set et_gthreads_timed 1
+ } else {
+ verbose "check_v3_target_gthreads_timed: compilation failed" 2
+ }
+ }
+ verbose "check_v3_target_gthreads_timed: $et_gthreads_timed" 2
+ return $et_gthreads_timed
+}
+
+
proc check_v3_target_nanosleep { } {
global cxxflags
global DEFAULT_CXXFLAGS
diff --git a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
index 8642eb7eea6..19fa0e2cc79 100644
--- a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
+++ b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
@@ -58,6 +58,7 @@ if {[info exists tests_file] && [file exists $tests_file]} {
lappend subdirs "$srcdir/ext"
lappend subdirs "$srcdir/performance"
lappend subdirs "$srcdir/tr1"
+ lappend subdirs "$srcdir/tr2"
lappend subdirs "$srcdir/decimal"
verbose "subdirs are $subdirs"
diff --git a/libstdc++-v3/testsuite/performance/23_containers/insert_erase/41975.cc b/libstdc++-v3/testsuite/performance/23_containers/insert_erase/41975.cc
new file mode 100644
index 00000000000..30fc105c272
--- /dev/null
+++ b/libstdc++-v3/testsuite/performance/23_containers/insert_erase/41975.cc
@@ -0,0 +1,72 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <cassert>
+#include <unordered_set>
+#include <testsuite_performance.h>
+
+int main()
+{
+ using namespace __gnu_test;
+
+ time_counter time;
+ resource_counter resource;
+
+ start_counters(time, resource);
+
+ std::unordered_set<int> us;
+ for (int i = 0; i != 5000000; ++i)
+ us.insert(i);
+
+ stop_counters(time, resource);
+ report_performance(__FILE__, "Container generation", time, resource);
+
+ start_counters(time, resource);
+
+ for (int j = 100; j != 0; --j)
+ {
+ auto it = us.begin();
+ while (it != us.end())
+ {
+ if ((*it % j) == 0)
+ it = us.erase(it);
+ else
+ ++it;
+ }
+ }
+
+ stop_counters(time, resource);
+ report_performance(__FILE__, "Container erase", time, resource);
+
+ start_counters(time, resource);
+
+ us.insert(0);
+
+ for (int i = 0; i != 500; ++i)
+ {
+ auto it = us.begin();
+ ++it;
+ assert( it == us.end() );
+ }
+
+ stop_counters(time, resource);
+ report_performance(__FILE__, "Container iteration", time, resource);
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr1/8_c_compatibility/complex/50880.cc b/libstdc++-v3/testsuite/tr1/8_c_compatibility/complex/50880.cc
new file mode 100644
index 00000000000..eaa2f3d81f4
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr1/8_c_compatibility/complex/50880.cc
@@ -0,0 +1,51 @@
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr1/complex>
+#include <testsuite_hooks.h>
+
+template<typename T>
+ void test01_do()
+ {
+ bool test __attribute__((unused)) = true;
+
+ const std::complex<T> ca(T(-2), T(2));
+ const std::complex<T> cb(T(-2), T(0));
+ const std::complex<T> cc(T(-2), T(-2));
+
+ std::complex<T> cra = std::tr1::acosh(ca);
+ std::complex<T> crb = std::tr1::acosh(cb);
+ std::complex<T> crc = std::tr1::acosh(cc);
+
+ VERIFY( cra.real() > T(0) );
+ VERIFY( crb.real() > T(0) );
+ VERIFY( crc.real() > T(0) );
+ }
+
+// libstdc++/50880
+void test01()
+{
+ test01_do<float>();
+ test01_do<double>();
+ test01_do<long double>();
+}
+
+int main()
+{
+ test01();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc
new file mode 100644
index 00000000000..ddd6d6fa38e
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/requirements/explicit_instantiation.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+namespace std
+{
+ namespace tr2
+ {
+ typedef short test_type;
+ template struct bases<test_type>;
+ }
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc
new file mode 100644
index 00000000000..a62acffe89c
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/requirements/typedefs.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+//
+// NB: This file is for testing tr1/type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+void test01()
+{
+ // Check for required typedefs
+ typedef std::tr2::bases<int> test_type;
+ typedef test_type::type value_type;
+}
diff --git a/libstdc++-v3/testsuite/tr2/bases/value.cc b/libstdc++-v3/testsuite/tr2/bases/value.cc
new file mode 100644
index 00000000000..415e974a980
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/bases/value.cc
@@ -0,0 +1,97 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <typeinfo>
+#include <stdexcept>
+
+struct A { };
+struct B1 : virtual public A { };
+struct B2 : virtual public A { };
+struct C : public B1, public B2 { };
+
+void test()
+{
+ bool test __attribute__((unused)) = true;
+
+ // 1
+ {
+ typedef std::tr2::bases<A>::type tl;
+ static_assert(tl::empty::value, "error");
+ }
+
+ // 2
+ {
+ typedef std::tr2::bases<B1>::type tl1;
+ typedef std::tr2::bases<B2>::type tl2;
+
+ // Sanity check w/ runtime.
+ bool eq = typeid(tl1) == typeid(tl2);
+ if (!eq)
+ throw std::logic_error("typelist not equal");
+
+ // Sanity check.
+ static_assert(tl1::empty::value != std::true_type::value, "!empty");
+ static_assert(tl2::empty::value != std::true_type::value, "!empty");
+
+ typedef tl1::first::type tl1_first;
+ typedef tl1::rest::type tl1_rest;
+ typedef tl2::first::type tl2_first;
+ typedef tl2::rest::type tl2_rest;
+
+ eq = typeid(tl1_first) == typeid(tl2_first);
+ if (!eq)
+ throw std::logic_error("base not equal");
+
+ static_assert(tl1_rest::empty::value == std::true_type::value, "empty");
+ static_assert(tl2_rest::empty::value == std::true_type::value, "empty");
+ }
+
+ // 3
+ {
+ typedef std::tr2::bases<C>::type tl;
+
+ // Sanity check.
+ static_assert(tl::empty::value != std::true_type::value, "!empty");
+
+ typedef tl::first::type tl1_first;
+ typedef tl::rest::type tl2;
+ typedef tl2::first::type tl2_first;
+ typedef tl2::rest::type tl3;
+ typedef tl3::first::type tl3_first;
+ typedef tl3::rest::type tl4;
+
+ bool eq = typeid(tl1_first) == typeid(tl2_first);
+ if (eq)
+ throw std::logic_error("bases are not equal");
+
+ eq = typeid(tl2_first) == typeid(tl3_first);
+ if (eq)
+ throw std::logic_error("bases are not equal");
+
+ static_assert(tl4::empty::value == std::true_type::value, "empty");
+ }
+
+}
+
+int main()
+{
+ test();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc
new file mode 100644
index 00000000000..d7fb96aff01
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/explicit_instantiation.cc
@@ -0,0 +1,32 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// NB: This file is for testing type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+namespace std
+{
+ namespace tr2
+ {
+ typedef short test_type;
+ template struct direct_bases<test_type>;
+ }
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc
new file mode 100644
index 00000000000..7d219ea3ffc
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/requirements/typedefs.cc
@@ -0,0 +1,31 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+//
+// NB: This file is for testing tr1/type_traits with NO OTHER INCLUDES.
+
+#include <tr2/type_traits>
+
+void test01()
+{
+ // Check for required typedefs
+ typedef std::tr2::direct_bases<int> test_type;
+ typedef test_type::type value_type;
+}
diff --git a/libstdc++-v3/testsuite/tr2/direct_bases/value.cc b/libstdc++-v3/testsuite/tr2/direct_bases/value.cc
new file mode 100644
index 00000000000..81d0269c525
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/direct_bases/value.cc
@@ -0,0 +1,91 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <typeinfo>
+#include <stdexcept>
+
+struct A { };
+struct B1 : virtual public A { };
+struct B2 : virtual public A { };
+struct C : public B1, public B2 { };
+
+void test()
+{
+ bool test __attribute__((unused)) = true;
+
+ // 1
+ {
+ typedef std::tr2::direct_bases<A>::type tl;
+ static_assert(tl::empty::value, "error");
+ }
+
+ // 2
+ {
+ typedef std::tr2::direct_bases<B1>::type tl1;
+ typedef std::tr2::direct_bases<B2>::type tl2;
+
+ // Sanity check w/ runtime.
+ bool eq = typeid(tl1) == typeid(tl2);
+ if (!eq)
+ throw std::logic_error("typelist not equal");
+
+ // Sanity check.
+ static_assert(tl1::empty::value != std::true_type::value, "!empty");
+ static_assert(tl2::empty::value != std::true_type::value, "!empty");
+
+ typedef tl1::first::type tl1_first;
+ typedef tl1::rest::type tl1_rest;
+ typedef tl2::first::type tl2_first;
+ typedef tl2::rest::type tl2_rest;
+
+ eq = typeid(tl1_first) == typeid(tl2_first);
+ if (!eq)
+ throw std::logic_error("base not equal");
+
+ static_assert(tl1_rest::empty::value == std::true_type::value, "empty");
+ static_assert(tl2_rest::empty::value == std::true_type::value, "empty");
+ }
+
+ // 3
+ {
+ typedef std::tr2::direct_bases<C>::type tl;
+
+ // Sanity check.
+ static_assert(tl::empty::value != std::true_type::value, "!empty");
+
+ typedef tl::first::type tl1_first;
+ typedef tl::rest::type tl2;
+ typedef tl2::first::type tl2_first;
+ typedef tl2::rest::type tl3;
+
+ bool eq = typeid(tl1_first) == typeid(tl2_first);
+ if (eq)
+ throw std::logic_error("bases are not equal");
+
+ static_assert(tl3::empty::value == std::true_type::value, "empty");
+ }
+
+}
+
+int main()
+{
+ test();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/tr2/headers/all.cc b/libstdc++-v3/testsuite/tr2/headers/all.cc
new file mode 100644
index 00000000000..096cdc06248
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/headers/all.cc
@@ -0,0 +1,24 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+//
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+#include <tr2/dynamic_bitset>
+#include <tr2/bool_set>
+#include <tr2/ratio>
diff --git a/libstdc++-v3/testsuite/tr2/headers/using_namespace_std_tr2.cc b/libstdc++-v3/testsuite/tr2/headers/using_namespace_std_tr2.cc
new file mode 100644
index 00000000000..b114327bb20
--- /dev/null
+++ b/libstdc++-v3/testsuite/tr2/headers/using_namespace_std_tr2.cc
@@ -0,0 +1,26 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library 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 3, or (at your option)
+// any later version.
+
+// This library 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 library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tr2/type_traits>
+
+namespace gnu
+{
+ using namespace std::tr2;
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h
index 38bfac8adc7..c0b8ee3be9b 100644
--- a/libstdc++-v3/testsuite/util/testsuite_allocator.h
+++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h
@@ -409,6 +409,14 @@ namespace __gnu_test
propagating_allocator(const propagating_allocator&) noexcept = default;
+ propagating_allocator&
+ operator=(const propagating_allocator& a) noexcept
+ {
+ static_assert(Propagate, "assigning propagating_allocator<T, true>");
+ propagating_allocator(a).swap_base(*this);
+ return *this;
+ }
+
template<bool P2>
propagating_allocator&
operator=(const propagating_allocator<Tp, P2>& a) noexcept
diff --git a/libstdc++-v3/testsuite/util/testsuite_rvalref.h b/libstdc++-v3/testsuite/util/testsuite_rvalref.h
index 2234e8112a9..73c70e06990 100644
--- a/libstdc++-v3/testsuite/util/testsuite_rvalref.h
+++ b/libstdc++-v3/testsuite/util/testsuite_rvalref.h
@@ -255,6 +255,9 @@ namespace __gnu_test
{ throw 1; }
throwing_move_constructor(const throwing_move_constructor&) = default;
+
+ throwing_move_constructor&
+ operator=(const throwing_move_constructor&) = default;
};
} // namespace __gnu_test